xref: /csrg-svn/sys/netinet/ip_output.c (revision 4899)
1*4899Swnj /* ip_output.c 1.12 81/11/15 */
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"
13*4899Swnj #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;
35*4899Swnj /*###35 [cc] ip_id undefined %%%*/
364662Swnj 	p->ip_id = ip_id++;
374496Swnj 
384674Swnj 	if (p->ip_len <= MTU)
394674Swnj 		return (ip_send(p));
404674Swnj 	if (p->ip_off & IP_DF)
414674Swnj 		return (0);
424674Swnj 	max = MTU - hlen;
434674Swnj 	len = p->ip_len - hlen;
444674Swnj 	off = 0;
454674Swnj 	m = mp;
464674Swnj 	while (len > 0) {
474674Swnj 		p->ip_off |= off >> 3;
484674Swnj 		i = -hlen;
494674Swnj 		while (m != NULL) {
504674Swnj 			i += m->m_len;
514674Swnj 			if (i > max)
524496Swnj 				break;
534674Swnj 			n = m;
544674Swnj 			m = m->m_next;
554496Swnj 		}
564674Swnj 		if (i < max || m == NULL) {
574674Swnj 			p->ip_off = p->ip_off &~ IP_MF;
584674Swnj 			p->ip_len = i + hlen;
594674Swnj 			return (ip_send(p));
604674Swnj 		}
614674Swnj 		if ((mm = m_get(1)) == NULL)    /* no more bufs */
624674Swnj 			return(0);
634674Swnj 		p->ip_off |= IP_MF;
644674Swnj 		i -= m->m_len;
654674Swnj 		rnd = i & ~7;
664674Swnj 		adj = i - rnd;
674674Swnj 		p->ip_len = rnd + hlen;
684674Swnj 		n->m_next = NULL;
694674Swnj 		mm->m_next = m;
704674Swnj 		m = mm;
714674Swnj 		m->m_off = MMAXOFF - hlen - adj;
724674Swnj 		m->m_len = hlen + adj;
734674Swnj 		bcopy(p, (caddr_t)((int)m + m->m_off), hlen);
744674Swnj 		if (adj) {
754674Swnj 			n->m_len -= adj;
764674Swnj 			bcopy((caddr_t)((int)n + n->m_len + n->m_off),
774674Swnj 			      (caddr_t)((int)m + m->m_off + hlen), adj);
784674Swnj 		}
794674Swnj 		ip_send(p);
804674Swnj 		p = (struct ip *)((int)m + m->m_off);
814674Swnj 		len -= rnd;
824674Swnj 		off += rnd;
834545Swnj 	}
844496Swnj }
854496Swnj 
864693Swnj ip_send(ip)
874693Swnj 	register struct ip *ip;		/* known to be r11 */
884496Swnj {
894496Swnj 	register struct mbuf *m;
904496Swnj 	register struct imp *l;
914693Swnj 	register int hlen = ip->ip_hl << 2;
924545Swnj 	int s;
934496Swnj COUNT(IP_SEND);
944496Swnj 
954693Swnj 	m = dtom(ip);
964496Swnj 	l = (struct imp *)((int)m + m->m_off - L1822);
974693Swnj 	l->i_shost = ip->ip_src.s_host;
984693Swnj 	l->i_dhost = ip->ip_dst.s_host;
994496Swnj 	l->i_type = IPTYPE;
1004693Swnj 	ip->ip_sum = 0;
1014693Swnj 	ip->ip_len = htons(ip->ip_len);
1024693Swnj 	ip->ip_id = htons(ip->ip_id);
1034693Swnj 	ip->ip_off = htons(ip->ip_off);
1044693Swnj 	CKSUM_IPSET(m, ip, r11, hlen);
1054693Swnj 	m->m_off -= L1822;
1064496Swnj 	m->m_len += L1822;
1074545Swnj 	m->m_act = NULL;
1084545Swnj #ifndef IMPLOOP
1094662Swnj 	s = splimp();
1104545Swnj 	if (imp_stat.outq_head != NULL)
1114545Swnj 		imp_stat.outq_tail->m_act = m;
1124545Swnj 	else
1134545Swnj 		imp_stat.outq_head = m;
1144545Swnj 	imp_stat.outq_tail = m;
1154545Swnj 	splx(s);
1164545Swnj 	if (!imp_stat.outactive)
1174688Swnj 		enstart(0);
1184545Swnj #else
1194545Swnj 	if (imp_stat.inq_head != NULL)
1204545Swnj 		imp_stat.inq_tail->m_act = m;
1214545Swnj 	else
1224545Swnj 		imp_stat.inq_head = m;
1234545Swnj 	imp_stat.inq_tail = m;
1244724Swnj 	setsoftnet();
1254545Swnj #endif IMPLOOP
1264545Swnj 	return (1);
1274496Swnj }
128