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