1*4688Swnj /* ip_output.c 1.7 81/10/31 */ 24571Swnj 34496Swnj #include "../h/param.h" 44662Swnj #include "../h/mbuf.h" 54662Swnj #include "../h/socket.h" 64662Swnj #include "../inet/inet.h" 74662Swnj #include "../inet/inet_systm.h" 84662Swnj #include "../inet/imp.h" 94662Swnj #include "../inet/inet_host.h" 104662Swnj #include "../inet/ip.h" 114662Swnj #include "../inet/tcp.h" 124496Swnj 134496Swnj ip_output(mp) 144545Swnj struct mbuf *mp; 154496Swnj { 164496Swnj register i, rnd; 174496Swnj register struct mbuf *m, *n; 184496Swnj register struct ip *p; 194496Swnj struct mbuf *mm; 204496Swnj int hlen, adj, max, len, off; 214496Swnj 224496Swnj COUNT(IP_OUTPUT); 234496Swnj p = (struct ip *)((int)mp + mp->m_off); /* -> ip header */ 244545Swnj hlen = sizeof (struct ip); /* header length */ 254496Swnj 264545Swnj /* 274545Swnj * Fill in and byte swap ip header. 284545Swnj */ 294545Swnj p->ip_v = IPVERSION; 304496Swnj p->ip_hl = hlen >> 2; 314662Swnj p->ip_off = 0 | (p->ip_off & IP_DF); 324496Swnj p->ip_ttl = MAXTTL; 334662Swnj p->ip_id = ip_id++; 344496Swnj 354674Swnj if (p->ip_len <= MTU) 364674Swnj return (ip_send(p)); 374674Swnj if (p->ip_off & IP_DF) 384674Swnj return (0); 394674Swnj max = MTU - hlen; 404674Swnj len = p->ip_len - hlen; 414674Swnj off = 0; 424674Swnj m = mp; 434674Swnj while (len > 0) { 444674Swnj p->ip_off |= off >> 3; 454674Swnj i = -hlen; 464674Swnj while (m != NULL) { 474674Swnj i += m->m_len; 484674Swnj if (i > max) 494496Swnj break; 504674Swnj n = m; 514674Swnj m = m->m_next; 524496Swnj } 534674Swnj if (i < max || m == NULL) { 544674Swnj p->ip_off = p->ip_off &~ IP_MF; 554674Swnj p->ip_len = i + hlen; 564674Swnj return (ip_send(p)); 574674Swnj } 584674Swnj if ((mm = m_get(1)) == NULL) /* no more bufs */ 594674Swnj return(0); 604674Swnj p->ip_off |= IP_MF; 614674Swnj i -= m->m_len; 624674Swnj rnd = i & ~7; 634674Swnj adj = i - rnd; 644674Swnj p->ip_len = rnd + hlen; 654674Swnj n->m_next = NULL; 664674Swnj mm->m_next = m; 674674Swnj m = mm; 684674Swnj m->m_off = MMAXOFF - hlen - adj; 694674Swnj m->m_len = hlen + adj; 704674Swnj bcopy(p, (caddr_t)((int)m + m->m_off), hlen); 714674Swnj if (adj) { 724674Swnj n->m_len -= adj; 734674Swnj bcopy((caddr_t)((int)n + n->m_len + n->m_off), 744674Swnj (caddr_t)((int)m + m->m_off + hlen), adj); 754674Swnj } 764674Swnj ip_send(p); 774674Swnj p = (struct ip *)((int)m + m->m_off); 784674Swnj len -= rnd; 794674Swnj off += rnd; 804545Swnj } 814496Swnj } 824496Swnj 834674Swnj ip_send(p) 844674Swnj struct ip *p; 854496Swnj { 864496Swnj register struct mbuf *m; 874496Swnj register struct imp *l; 884545Swnj int s; 894496Swnj COUNT(IP_SEND); 904496Swnj 914674Swnj m = dtom(p); 924496Swnj l = (struct imp *)((int)m + m->m_off - L1822); 934545Swnj if ((l->i_shost = p->ip_src.s_host) == 0) 944545Swnj l->i_shost = 253; 954545Swnj if ((l->i_dhost = p->ip_dst.s_host) == 0) 964545Swnj l->i_dhost = 253; 974496Swnj l->i_type = IPTYPE; 984496Swnj p->ip_sum = 0; 994662Swnj p->ip_len = htons(p->ip_len); 1004662Swnj p->ip_id = htons(p->ip_id); 1014662Swnj p->ip_off = htons(p->ip_off); 1024545Swnj p->ip_sum = cksum(m, sizeof(struct ip)); 1034496Swnj m->m_off -= L1822; /* -> 1822 leader */ 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) 115*4688Swnj 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