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