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