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