1*4802Swnj /* ip_output.c 1.11 81/11/08 */ 24571Swnj 34496Swnj #include "../h/param.h" 44662Swnj #include "../h/mbuf.h" 54724Swnj #include "../h/mtpr.h" 64662Swnj #include "../h/socket.h" 7*4802Swnj #include "../net/inet_cksum.h" 8*4802Swnj #include "../net/inet.h" 9*4802Swnj #include "../net/inet_systm.h" 10*4802Swnj #include "../net/imp.h" 11*4802Swnj #include "../net/inet_host.h" 12*4802Swnj #include "../net/ip.h" 13*4802Swnj #include "../net/tcp.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 374674Swnj if (p->ip_len <= MTU) 384674Swnj return (ip_send(p)); 394674Swnj if (p->ip_off & IP_DF) 404674Swnj return (0); 414674Swnj max = MTU - hlen; 424674Swnj len = p->ip_len - hlen; 434674Swnj off = 0; 444674Swnj m = mp; 454674Swnj while (len > 0) { 464674Swnj p->ip_off |= off >> 3; 474674Swnj i = -hlen; 484674Swnj while (m != NULL) { 494674Swnj i += m->m_len; 504674Swnj if (i > max) 514496Swnj break; 524674Swnj n = m; 534674Swnj m = m->m_next; 544496Swnj } 554674Swnj if (i < max || m == NULL) { 564674Swnj p->ip_off = p->ip_off &~ IP_MF; 574674Swnj p->ip_len = i + hlen; 584674Swnj return (ip_send(p)); 594674Swnj } 604674Swnj if ((mm = m_get(1)) == NULL) /* no more bufs */ 614674Swnj return(0); 624674Swnj p->ip_off |= IP_MF; 634674Swnj i -= m->m_len; 644674Swnj rnd = i & ~7; 654674Swnj adj = i - rnd; 664674Swnj p->ip_len = rnd + hlen; 674674Swnj n->m_next = NULL; 684674Swnj mm->m_next = m; 694674Swnj m = mm; 704674Swnj m->m_off = MMAXOFF - hlen - adj; 714674Swnj m->m_len = hlen + adj; 724674Swnj bcopy(p, (caddr_t)((int)m + m->m_off), hlen); 734674Swnj if (adj) { 744674Swnj n->m_len -= adj; 754674Swnj bcopy((caddr_t)((int)n + n->m_len + n->m_off), 764674Swnj (caddr_t)((int)m + m->m_off + hlen), adj); 774674Swnj } 784674Swnj ip_send(p); 794674Swnj p = (struct ip *)((int)m + m->m_off); 804674Swnj len -= rnd; 814674Swnj off += rnd; 824545Swnj } 834496Swnj } 844496Swnj 854693Swnj ip_send(ip) 864693Swnj register struct ip *ip; /* known to be r11 */ 874496Swnj { 884496Swnj register struct mbuf *m; 894496Swnj register struct imp *l; 904693Swnj register int hlen = ip->ip_hl << 2; 914545Swnj int s; 924496Swnj COUNT(IP_SEND); 934496Swnj 944693Swnj m = dtom(ip); 954496Swnj l = (struct imp *)((int)m + m->m_off - L1822); 964693Swnj l->i_shost = ip->ip_src.s_host; 974693Swnj l->i_dhost = ip->ip_dst.s_host; 984496Swnj l->i_type = IPTYPE; 994693Swnj ip->ip_sum = 0; 1004693Swnj ip->ip_len = htons(ip->ip_len); 1014693Swnj ip->ip_id = htons(ip->ip_id); 1024693Swnj ip->ip_off = htons(ip->ip_off); 1034693Swnj CKSUM_IPSET(m, ip, r11, hlen); 1044693Swnj m->m_off -= L1822; 1054496Swnj m->m_len += L1822; 1064545Swnj m->m_act = NULL; 1074545Swnj #ifndef IMPLOOP 1084662Swnj s = splimp(); 1094545Swnj if (imp_stat.outq_head != NULL) 1104545Swnj imp_stat.outq_tail->m_act = m; 1114545Swnj else 1124545Swnj imp_stat.outq_head = m; 1134545Swnj imp_stat.outq_tail = m; 1144545Swnj splx(s); 1154545Swnj if (!imp_stat.outactive) 1164688Swnj enstart(0); 1174545Swnj #else 1184545Swnj if (imp_stat.inq_head != NULL) 1194545Swnj imp_stat.inq_tail->m_act = m; 1204545Swnj else 1214545Swnj imp_stat.inq_head = m; 1224545Swnj imp_stat.inq_tail = m; 1234724Swnj setsoftnet(); 1244545Swnj #endif IMPLOOP 1254545Swnj return (1); 1264496Swnj } 127