first listing
[unix-history] / usr / src / sys / netinet / ip_output.c
CommitLineData
d52566dd 1/* ip_output.c 1.11 81/11/08 */
6e8b2eca 2
ac904f92 3#include "../h/param.h"
dad64fdf 4#include "../h/mbuf.h"
69435e93 5#include "../h/mtpr.h"
dad64fdf 6#include "../h/socket.h"
d52566dd
BJ
7#include "../net/inet_cksum.h"
8#include "../net/inet.h"
9#include "../net/inet_systm.h"
10#include "../net/imp.h"
11#include "../net/inet_host.h"
12#include "../net/ip.h"
13#include "../net/tcp.h"
ac904f92 14
ac904f92 15ip_output(mp)
e8d11875 16 struct mbuf *mp;
ac904f92
BJ
17{
18 register i, rnd;
19 register struct mbuf *m, *n;
20 register struct ip *p;
21 struct mbuf *mm;
22 int hlen, adj, max, len, off;
23
24COUNT(IP_OUTPUT);
7816bf89
BJ
25 p = mtod(mp, struct ip *);
26 hlen = sizeof (struct ip);
ac904f92 27
e8d11875
BJ
28 /*
29 * Fill in and byte swap ip header.
30 */
31 p->ip_v = IPVERSION;
ac904f92 32 p->ip_hl = hlen >> 2;
dad64fdf 33 p->ip_off = 0 | (p->ip_off & IP_DF);
ac904f92 34 p->ip_ttl = MAXTTL;
dad64fdf 35 p->ip_id = ip_id++;
ac904f92 36
98444525
BJ
37 if (p->ip_len <= MTU)
38 return (ip_send(p));
39 if (p->ip_off & IP_DF)
40 return (0);
41 max = MTU - hlen;
42 len = p->ip_len - hlen;
43 off = 0;
44 m = mp;
45 while (len > 0) {
46 p->ip_off |= off >> 3;
47 i = -hlen;
48 while (m != NULL) {
49 i += m->m_len;
50 if (i > max)
ac904f92 51 break;
98444525
BJ
52 n = m;
53 m = m->m_next;
54 }
55 if (i < max || m == NULL) {
56 p->ip_off = p->ip_off &~ IP_MF;
57 p->ip_len = i + hlen;
58 return (ip_send(p));
59 }
60 if ((mm = m_get(1)) == NULL) /* no more bufs */
61 return(0);
62 p->ip_off |= IP_MF;
63 i -= m->m_len;
64 rnd = i & ~7;
65 adj = i - rnd;
66 p->ip_len = rnd + hlen;
67 n->m_next = NULL;
68 mm->m_next = m;
69 m = mm;
70 m->m_off = MMAXOFF - hlen - adj;
71 m->m_len = hlen + adj;
72 bcopy(p, (caddr_t)((int)m + m->m_off), hlen);
73 if (adj) {
74 n->m_len -= adj;
75 bcopy((caddr_t)((int)n + n->m_len + n->m_off),
76 (caddr_t)((int)m + m->m_off + hlen), adj);
ac904f92 77 }
98444525
BJ
78 ip_send(p);
79 p = (struct ip *)((int)m + m->m_off);
80 len -= rnd;
81 off += rnd;
e8d11875 82 }
ac904f92
BJ
83}
84
7816bf89
BJ
85ip_send(ip)
86 register struct ip *ip; /* known to be r11 */
ac904f92
BJ
87{
88 register struct mbuf *m;
89 register struct imp *l;
7816bf89 90 register int hlen = ip->ip_hl << 2;
e8d11875 91 int s;
ac904f92
BJ
92COUNT(IP_SEND);
93
7816bf89 94 m = dtom(ip);
ac904f92 95 l = (struct imp *)((int)m + m->m_off - L1822);
7816bf89
BJ
96 l->i_shost = ip->ip_src.s_host;
97 l->i_dhost = ip->ip_dst.s_host;
ac904f92 98 l->i_type = IPTYPE;
7816bf89
BJ
99 ip->ip_sum = 0;
100 ip->ip_len = htons(ip->ip_len);
101 ip->ip_id = htons(ip->ip_id);
102 ip->ip_off = htons(ip->ip_off);
103 CKSUM_IPSET(m, ip, r11, hlen);
104 m->m_off -= L1822;
ac904f92 105 m->m_len += L1822;
e8d11875 106 m->m_act = NULL;
e8d11875 107#ifndef IMPLOOP
dad64fdf 108 s = splimp();
e8d11875
BJ
109 if (imp_stat.outq_head != NULL)
110 imp_stat.outq_tail->m_act = m;
111 else
112 imp_stat.outq_head = m;
113 imp_stat.outq_tail = m;
114 splx(s);
e8d11875 115 if (!imp_stat.outactive)
ae348eea 116 enstart(0);
e8d11875 117#else
e8d11875
BJ
118 if (imp_stat.inq_head != NULL)
119 imp_stat.inq_tail->m_act = m;
120 else
121 imp_stat.inq_head = m;
122 imp_stat.inq_tail = m;
69435e93 123 setsoftnet();
e8d11875
BJ
124#endif IMPLOOP
125 return (1);
ac904f92 126}