1 /* ip_output.c 1.9 81/11/01 */ 2 3 #include "../h/param.h" 4 #include "../h/mbuf.h" 5 #include "../h/socket.h" 6 #include "../inet/inet_cksum.h" 7 #include "../inet/inet.h" 8 #include "../inet/inet_systm.h" 9 #include "../inet/imp.h" 10 #include "../inet/inet_host.h" 11 #include "../inet/ip.h" 12 #include "../inet/tcp.h" 13 14 ip_output(mp) 15 struct mbuf *mp; 16 { 17 register i, rnd; 18 register struct mbuf *m, *n; 19 register struct ip *p; 20 struct mbuf *mm; 21 int hlen, adj, max, len, off; 22 23 COUNT(IP_OUTPUT); 24 p = mtod(mp, struct ip *); 25 hlen = sizeof (struct ip); 26 27 /* 28 * Fill in and byte swap ip header. 29 */ 30 p->ip_v = IPVERSION; 31 p->ip_hl = hlen >> 2; 32 p->ip_off = 0 | (p->ip_off & IP_DF); 33 p->ip_ttl = MAXTTL; 34 p->ip_id = ip_id++; 35 36 if (p->ip_len <= MTU) 37 return (ip_send(p)); 38 if (p->ip_off & IP_DF) 39 return (0); 40 max = MTU - hlen; 41 len = p->ip_len - hlen; 42 off = 0; 43 m = mp; 44 while (len > 0) { 45 p->ip_off |= off >> 3; 46 i = -hlen; 47 while (m != NULL) { 48 i += m->m_len; 49 if (i > max) 50 break; 51 n = m; 52 m = m->m_next; 53 } 54 if (i < max || m == NULL) { 55 p->ip_off = p->ip_off &~ IP_MF; 56 p->ip_len = i + hlen; 57 return (ip_send(p)); 58 } 59 if ((mm = m_get(1)) == NULL) /* no more bufs */ 60 return(0); 61 p->ip_off |= IP_MF; 62 i -= m->m_len; 63 rnd = i & ~7; 64 adj = i - rnd; 65 p->ip_len = rnd + hlen; 66 n->m_next = NULL; 67 mm->m_next = m; 68 m = mm; 69 m->m_off = MMAXOFF - hlen - adj; 70 m->m_len = hlen + adj; 71 bcopy(p, (caddr_t)((int)m + m->m_off), hlen); 72 if (adj) { 73 n->m_len -= adj; 74 bcopy((caddr_t)((int)n + n->m_len + n->m_off), 75 (caddr_t)((int)m + m->m_off + hlen), adj); 76 } 77 ip_send(p); 78 p = (struct ip *)((int)m + m->m_off); 79 len -= rnd; 80 off += rnd; 81 } 82 } 83 84 ip_send(ip) 85 register struct ip *ip; /* known to be r11 */ 86 { 87 register struct mbuf *m; 88 register struct imp *l; 89 register int hlen = ip->ip_hl << 2; 90 int s; 91 COUNT(IP_SEND); 92 93 m = dtom(ip); 94 l = (struct imp *)((int)m + m->m_off - L1822); 95 l->i_shost = ip->ip_src.s_host; 96 l->i_dhost = ip->ip_dst.s_host; 97 l->i_type = IPTYPE; 98 ip->ip_sum = 0; 99 ip->ip_len = htons(ip->ip_len); 100 ip->ip_id = htons(ip->ip_id); 101 ip->ip_off = htons(ip->ip_off); 102 CKSUM_IPSET(m, ip, r11, hlen); 103 m->m_off -= L1822; 104 m->m_len += L1822; 105 m->m_act = NULL; 106 #ifndef IMPLOOP 107 s = splimp(); 108 if (imp_stat.outq_head != NULL) 109 imp_stat.outq_tail->m_act = m; 110 else 111 imp_stat.outq_head = m; 112 imp_stat.outq_tail = m; 113 splx(s); 114 if (!imp_stat.outactive) 115 enstart(0); 116 #else 117 if (imp_stat.inq_head != NULL) 118 imp_stat.inq_tail->m_act = m; 119 else 120 imp_stat.inq_head = m; 121 imp_stat.inq_tail = m; 122 #endif IMPLOOP 123 return (1); 124 } 125