xref: /csrg-svn/sys/netinet/ip_output.c (revision 4908)
1*4908Swnj /* ip_output.c 1.13 81/11/16 */
24571Swnj 
34496Swnj #include "../h/param.h"
44662Swnj #include "../h/mbuf.h"
54724Swnj #include "../h/mtpr.h"
64662Swnj #include "../h/socket.h"
74802Swnj #include "../net/inet_cksum.h"
84802Swnj #include "../net/inet.h"
94802Swnj #include "../net/inet_systm.h"
104802Swnj #include "../net/imp.h"
114802Swnj #include "../net/inet_host.h"
124802Swnj #include "../net/ip.h"
134899Swnj #include "../net/ip_var.h"
144496Swnj 
154496Swnj ip_output(mp)
164545Swnj 	struct mbuf *mp;
174496Swnj {
184496Swnj 	register i, rnd;
194496Swnj 	register struct mbuf *m, *n;
204496Swnj 	register struct ip *p;
214496Swnj 	struct mbuf *mm;
224496Swnj 	int hlen, adj, max, len, off;
234496Swnj 
244496Swnj COUNT(IP_OUTPUT);
254693Swnj 	p = mtod(mp, struct ip *);
264693Swnj 	hlen = sizeof (struct ip);
274496Swnj 
284545Swnj 	/*
294545Swnj 	 * Fill in and byte swap ip header.
304545Swnj 	 */
314545Swnj 	p->ip_v = IPVERSION;
324496Swnj 	p->ip_hl = hlen >> 2;
334662Swnj 	p->ip_off = 0 | (p->ip_off & IP_DF);
344496Swnj 	p->ip_ttl = MAXTTL;
354662Swnj 	p->ip_id = ip_id++;
364496Swnj 
37*4908Swnj 	if (p->ip_len <= MTU) {
38*4908Swnj 		ip_send(p);
39*4908Swnj 		return;
40*4908Swnj 	}
414674Swnj 	if (p->ip_off & IP_DF)
42*4908Swnj 		return;
434674Swnj 	max = MTU - hlen;
444674Swnj 	len = p->ip_len - hlen;
454674Swnj 	off = 0;
464674Swnj 	m = mp;
474674Swnj 	while (len > 0) {
484674Swnj 		p->ip_off |= off >> 3;
494674Swnj 		i = -hlen;
504674Swnj 		while (m != NULL) {
514674Swnj 			i += m->m_len;
524674Swnj 			if (i > max)
534496Swnj 				break;
544674Swnj 			n = m;
554674Swnj 			m = m->m_next;
564496Swnj 		}
574674Swnj 		if (i < max || m == NULL) {
584674Swnj 			p->ip_off = p->ip_off &~ IP_MF;
594674Swnj 			p->ip_len = i + hlen;
60*4908Swnj 			ip_send(p);
61*4908Swnj 			return;
624674Swnj 		}
634674Swnj 		if ((mm = m_get(1)) == NULL)    /* no more bufs */
64*4908Swnj 			return;
654674Swnj 		p->ip_off |= IP_MF;
664674Swnj 		i -= m->m_len;
674674Swnj 		rnd = i & ~7;
684674Swnj 		adj = i - rnd;
694674Swnj 		p->ip_len = rnd + hlen;
704674Swnj 		n->m_next = NULL;
714674Swnj 		mm->m_next = m;
724674Swnj 		m = mm;
734674Swnj 		m->m_off = MMAXOFF - hlen - adj;
744674Swnj 		m->m_len = hlen + adj;
75*4908Swnj 		bcopy((caddr_t)p, mtod(m, caddr_t), (unsigned)hlen);
764674Swnj 		if (adj) {
774674Swnj 			n->m_len -= adj;
78*4908Swnj 			bcopy(mtod(n, caddr_t) + n->m_len,
79*4908Swnj 			    mtod(m, caddr_t) + hlen, (unsigned) adj);
804674Swnj 		}
814674Swnj 		ip_send(p);
824674Swnj 		p = (struct ip *)((int)m + m->m_off);
834674Swnj 		len -= rnd;
844674Swnj 		off += rnd;
854545Swnj 	}
86*4908Swnj 	return;
874496Swnj }
884496Swnj 
894693Swnj ip_send(ip)
904693Swnj 	register struct ip *ip;		/* known to be r11 */
914496Swnj {
924496Swnj 	register struct mbuf *m;
934496Swnj 	register struct imp *l;
944693Swnj 	register int hlen = ip->ip_hl << 2;
954545Swnj 	int s;
964496Swnj COUNT(IP_SEND);
974496Swnj 
984693Swnj 	m = dtom(ip);
99*4908Swnj 	l = (struct imp *)(mtod(m, caddr_t) - L1822);
1004693Swnj 	l->i_shost = ip->ip_src.s_host;
1014693Swnj 	l->i_dhost = ip->ip_dst.s_host;
1024496Swnj 	l->i_type = IPTYPE;
1034693Swnj 	ip->ip_sum = 0;
104*4908Swnj 	ip->ip_len = htons((u_short)ip->ip_len);
1054693Swnj 	ip->ip_id = htons(ip->ip_id);
106*4908Swnj 	ip->ip_off = htons((u_short)ip->ip_off);
1074693Swnj 	CKSUM_IPSET(m, ip, r11, hlen);
1084693Swnj 	m->m_off -= L1822;
1094496Swnj 	m->m_len += L1822;
1104545Swnj 	m->m_act = NULL;
1114545Swnj #ifndef IMPLOOP
1124662Swnj 	s = splimp();
1134545Swnj 	if (imp_stat.outq_head != NULL)
1144545Swnj 		imp_stat.outq_tail->m_act = m;
1154545Swnj 	else
1164545Swnj 		imp_stat.outq_head = m;
1174545Swnj 	imp_stat.outq_tail = m;
1184545Swnj 	splx(s);
1194545Swnj 	if (!imp_stat.outactive)
1204688Swnj 		enstart(0);
1214545Swnj #else
1224545Swnj 	if (imp_stat.inq_head != NULL)
1234545Swnj 		imp_stat.inq_tail->m_act = m;
1244545Swnj 	else
1254545Swnj 		imp_stat.inq_head = m;
1264545Swnj 	imp_stat.inq_tail = m;
1274724Swnj 	setsoftnet();
1284545Swnj #endif IMPLOOP
1294496Swnj }
130