find -type f | xargs sed -i 's/[\t ]$//g' # on most files
[qemu] / slirp / ip_output.c
1 /*
2  * Copyright (c) 1982, 1986, 1988, 1990, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *      @(#)ip_output.c 8.3 (Berkeley) 1/21/94
34  * ip_output.c,v 1.9 1994/11/16 10:17:10 jkh Exp
35  */
36
37 /*
38  * Changes and additions relating to SLiRP are
39  * Copyright (c) 1995 Danny Gasparovski.
40  *
41  * Please read the file COPYRIGHT for the
42  * terms and conditions of the copyright.
43  */
44
45 #include <slirp.h>
46
47 u_int16_t ip_id;
48
49 /*
50  * IP output.  The packet in mbuf chain m contains a skeletal IP
51  * header (with len, off, ttl, proto, tos, src, dst).
52  * The mbuf chain containing the packet will be freed.
53  * The mbuf opt, if present, will not be freed.
54  */
55 int
56 ip_output(so, m0)
57         struct socket *so;
58         struct mbuf *m0;
59 {
60         register struct ip *ip;
61         register struct mbuf *m = m0;
62         register int hlen = sizeof(struct ip );
63         int len, off, error = 0;
64
65         DEBUG_CALL("ip_output");
66         DEBUG_ARG("so = %lx", (long)so);
67         DEBUG_ARG("m0 = %lx", (long)m0);
68
69         /* We do no options */
70 /*      if (opt) {
71  *              m = ip_insertoptions(m, opt, &len);
72  *              hlen = len;
73  *      }
74  */
75         ip = mtod(m, struct ip *);
76         /*
77          * Fill in IP header.
78          */
79         ip->ip_v = IPVERSION;
80         ip->ip_off &= IP_DF;
81         ip->ip_id = htons(ip_id++);
82         ip->ip_hl = hlen >> 2;
83         ipstat.ips_localout++;
84
85         /*
86          * Verify that we have any chance at all of being able to queue
87          *      the packet or packet fragments
88          */
89         /* XXX Hmmm... */
90 /*      if (if_queued > if_thresh && towrite <= 0) {
91  *              error = ENOBUFS;
92  *              goto bad;
93  *      }
94  */
95
96         /*
97          * If small enough for interface, can just send directly.
98          */
99         if ((u_int16_t)ip->ip_len <= if_mtu) {
100                 ip->ip_len = htons((u_int16_t)ip->ip_len);
101                 ip->ip_off = htons((u_int16_t)ip->ip_off);
102                 ip->ip_sum = 0;
103                 ip->ip_sum = cksum(m, hlen);
104
105                 if_output(so, m);
106                 goto done;
107         }
108
109         /*
110          * Too large for interface; fragment if possible.
111          * Must be able to put at least 8 bytes per fragment.
112          */
113         if (ip->ip_off & IP_DF) {
114                 error = -1;
115                 ipstat.ips_cantfrag++;
116                 goto bad;
117         }
118
119         len = (if_mtu - hlen) &~ 7;       /* ip databytes per packet */
120         if (len < 8) {
121                 error = -1;
122                 goto bad;
123         }
124
125     {
126         int mhlen, firstlen = len;
127         struct mbuf **mnext = &m->m_nextpkt;
128
129         /*
130          * Loop through length of segment after first fragment,
131          * make new header and copy data of each part and link onto chain.
132          */
133         m0 = m;
134         mhlen = sizeof (struct ip);
135         for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) {
136           register struct ip *mhip;
137           m = m_get();
138           if (m == 0) {
139             error = -1;
140             ipstat.ips_odropped++;
141             goto sendorfree;
142           }
143           m->m_data += if_maxlinkhdr;
144           mhip = mtod(m, struct ip *);
145           *mhip = *ip;
146         
147                 /* No options */
148 /*              if (hlen > sizeof (struct ip)) {
149  *                      mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
150  *                      mhip->ip_hl = mhlen >> 2;
151  *              }
152  */
153           m->m_len = mhlen;
154           mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
155           if (ip->ip_off & IP_MF)
156             mhip->ip_off |= IP_MF;
157           if (off + len >= (u_int16_t)ip->ip_len)
158             len = (u_int16_t)ip->ip_len - off;
159           else
160             mhip->ip_off |= IP_MF;
161           mhip->ip_len = htons((u_int16_t)(len + mhlen));
162          
163           if (m_copy(m, m0, off, len) < 0) {
164             error = -1;
165             goto sendorfree;
166           }
167          
168           mhip->ip_off = htons((u_int16_t)mhip->ip_off);
169           mhip->ip_sum = 0;
170           mhip->ip_sum = cksum(m, mhlen);
171           *mnext = m;
172           mnext = &m->m_nextpkt;
173           ipstat.ips_ofragments++;
174         }
175         /*
176          * Update first fragment by trimming what's been copied out
177          * and updating header, then send each fragment (in order).
178          */
179         m = m0;
180         m_adj(m, hlen + firstlen - (u_int16_t)ip->ip_len);
181         ip->ip_len = htons((u_int16_t)m->m_len);
182         ip->ip_off = htons((u_int16_t)(ip->ip_off | IP_MF));
183         ip->ip_sum = 0;
184         ip->ip_sum = cksum(m, hlen);
185 sendorfree:
186         for (m = m0; m; m = m0) {
187                 m0 = m->m_nextpkt;
188                 m->m_nextpkt = 0;
189                 if (error == 0)
190                         if_output(so, m);
191                 else
192                         m_freem(m);
193         }
194
195         if (error == 0)
196                 ipstat.ips_fragmented++;
197     }
198
199 done:
200         return (error);
201
202 bad:
203         m_freem(m0);
204         goto done;
205 }