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