1*4674Swnj /* ip_output.c 1.6 81/10/30 */ 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 35*4674Swnj if (p->ip_len <= MTU) 36*4674Swnj return (ip_send(p)); 37*4674Swnj if (p->ip_off & IP_DF) 38*4674Swnj return (0); 39*4674Swnj max = MTU - hlen; 40*4674Swnj len = p->ip_len - hlen; 41*4674Swnj off = 0; 42*4674Swnj m = mp; 43*4674Swnj while (len > 0) { 44*4674Swnj p->ip_off |= off >> 3; 45*4674Swnj i = -hlen; 46*4674Swnj while (m != NULL) { 47*4674Swnj i += m->m_len; 48*4674Swnj if (i > max) 494496Swnj break; 50*4674Swnj n = m; 51*4674Swnj m = m->m_next; 524496Swnj } 53*4674Swnj if (i < max || m == NULL) { 54*4674Swnj p->ip_off = p->ip_off &~ IP_MF; 55*4674Swnj p->ip_len = i + hlen; 56*4674Swnj return (ip_send(p)); 57*4674Swnj } 58*4674Swnj if ((mm = m_get(1)) == NULL) /* no more bufs */ 59*4674Swnj return(0); 60*4674Swnj p->ip_off |= IP_MF; 61*4674Swnj i -= m->m_len; 62*4674Swnj rnd = i & ~7; 63*4674Swnj adj = i - rnd; 64*4674Swnj p->ip_len = rnd + hlen; 65*4674Swnj n->m_next = NULL; 66*4674Swnj mm->m_next = m; 67*4674Swnj m = mm; 68*4674Swnj m->m_off = MMAXOFF - hlen - adj; 69*4674Swnj m->m_len = hlen + adj; 70*4674Swnj bcopy(p, (caddr_t)((int)m + m->m_off), hlen); 71*4674Swnj if (adj) { 72*4674Swnj n->m_len -= adj; 73*4674Swnj bcopy((caddr_t)((int)n + n->m_len + n->m_off), 74*4674Swnj (caddr_t)((int)m + m->m_off + hlen), adj); 75*4674Swnj } 76*4674Swnj ip_send(p); 77*4674Swnj p = (struct ip *)((int)m + m->m_off); 78*4674Swnj len -= rnd; 79*4674Swnj off += rnd; 804545Swnj } 814496Swnj } 824496Swnj 83*4674Swnj ip_send(p) 84*4674Swnj struct ip *p; 854496Swnj { 864496Swnj register struct mbuf *m; 874496Swnj register struct imp *l; 884545Swnj int s; 894496Swnj COUNT(IP_SEND); 904496Swnj 91*4674Swnj 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) 1154545Swnj imp_output(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