1*4693Swnj /* ip_output.c 1.8 81/10/31 */ 24571Swnj 34496Swnj #include "../h/param.h" 44662Swnj #include "../h/mbuf.h" 54662Swnj #include "../h/socket.h" 6*4693Swnj #include "../inet/cksum.h" 74662Swnj #include "../inet/inet.h" 84662Swnj #include "../inet/inet_systm.h" 94662Swnj #include "../inet/imp.h" 104662Swnj #include "../inet/inet_host.h" 114662Swnj #include "../inet/ip.h" 124662Swnj #include "../inet/tcp.h" 134496Swnj 144496Swnj ip_output(mp) 154545Swnj struct mbuf *mp; 164496Swnj { 174496Swnj register i, rnd; 184496Swnj register struct mbuf *m, *n; 194496Swnj register struct ip *p; 204496Swnj struct mbuf *mm; 214496Swnj int hlen, adj, max, len, off; 224496Swnj 234496Swnj COUNT(IP_OUTPUT); 24*4693Swnj p = mtod(mp, struct ip *); 25*4693Swnj hlen = sizeof (struct ip); 264496Swnj 274545Swnj /* 284545Swnj * Fill in and byte swap ip header. 294545Swnj */ 304545Swnj p->ip_v = IPVERSION; 314496Swnj p->ip_hl = hlen >> 2; 324662Swnj p->ip_off = 0 | (p->ip_off & IP_DF); 334496Swnj p->ip_ttl = MAXTTL; 344662Swnj p->ip_id = ip_id++; 354496Swnj 364674Swnj if (p->ip_len <= MTU) 374674Swnj return (ip_send(p)); 384674Swnj if (p->ip_off & IP_DF) 394674Swnj return (0); 404674Swnj max = MTU - hlen; 414674Swnj len = p->ip_len - hlen; 424674Swnj off = 0; 434674Swnj m = mp; 444674Swnj while (len > 0) { 454674Swnj p->ip_off |= off >> 3; 464674Swnj i = -hlen; 474674Swnj while (m != NULL) { 484674Swnj i += m->m_len; 494674Swnj if (i > max) 504496Swnj break; 514674Swnj n = m; 524674Swnj m = m->m_next; 534496Swnj } 544674Swnj if (i < max || m == NULL) { 554674Swnj p->ip_off = p->ip_off &~ IP_MF; 564674Swnj p->ip_len = i + hlen; 574674Swnj return (ip_send(p)); 584674Swnj } 594674Swnj if ((mm = m_get(1)) == NULL) /* no more bufs */ 604674Swnj return(0); 614674Swnj p->ip_off |= IP_MF; 624674Swnj i -= m->m_len; 634674Swnj rnd = i & ~7; 644674Swnj adj = i - rnd; 654674Swnj p->ip_len = rnd + hlen; 664674Swnj n->m_next = NULL; 674674Swnj mm->m_next = m; 684674Swnj m = mm; 694674Swnj m->m_off = MMAXOFF - hlen - adj; 704674Swnj m->m_len = hlen + adj; 714674Swnj bcopy(p, (caddr_t)((int)m + m->m_off), hlen); 724674Swnj if (adj) { 734674Swnj n->m_len -= adj; 744674Swnj bcopy((caddr_t)((int)n + n->m_len + n->m_off), 754674Swnj (caddr_t)((int)m + m->m_off + hlen), adj); 764674Swnj } 774674Swnj ip_send(p); 784674Swnj p = (struct ip *)((int)m + m->m_off); 794674Swnj len -= rnd; 804674Swnj off += rnd; 814545Swnj } 824496Swnj } 834496Swnj 84*4693Swnj ip_send(ip) 85*4693Swnj register struct ip *ip; /* known to be r11 */ 864496Swnj { 874496Swnj register struct mbuf *m; 884496Swnj register struct imp *l; 89*4693Swnj register int hlen = ip->ip_hl << 2; 904545Swnj int s; 914496Swnj COUNT(IP_SEND); 924496Swnj 93*4693Swnj m = dtom(ip); 944496Swnj l = (struct imp *)((int)m + m->m_off - L1822); 95*4693Swnj l->i_shost = ip->ip_src.s_host; 96*4693Swnj l->i_dhost = ip->ip_dst.s_host; 974496Swnj l->i_type = IPTYPE; 98*4693Swnj ip->ip_sum = 0; 99*4693Swnj ip->ip_len = htons(ip->ip_len); 100*4693Swnj ip->ip_id = htons(ip->ip_id); 101*4693Swnj ip->ip_off = htons(ip->ip_off); 102*4693Swnj CKSUM_IPSET(m, ip, r11, hlen); 103*4693Swnj m->m_off -= L1822; 1044496Swnj m->m_len += L1822; 1054545Swnj m->m_act = NULL; 1064545Swnj #ifndef IMPLOOP 1074662Swnj s = splimp(); 1084545Swnj if (imp_stat.outq_head != NULL) 1094545Swnj imp_stat.outq_tail->m_act = m; 1104545Swnj else 1114545Swnj imp_stat.outq_head = m; 1124545Swnj imp_stat.outq_tail = m; 1134545Swnj splx(s); 1144545Swnj if (!imp_stat.outactive) 1154688Swnj enstart(0); 1164545Swnj #else 1174545Swnj if (imp_stat.inq_head != NULL) 1184545Swnj imp_stat.inq_tail->m_act = m; 1194545Swnj else 1204545Swnj imp_stat.inq_head = m; 1214545Swnj imp_stat.inq_tail = m; 1224545Swnj #endif IMPLOOP 1234545Swnj return (1); 1244496Swnj } 125