ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/slirp/ip_icmp.c
Revision: 1.3
Committed: 2012-03-30T01:10:28Z (12 years, 1 month ago) by asvitkine
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.2: +1 -5 lines
Log Message:
Switch slirp to 3-clause BSD license. This change went in upstream to QEMU's
version of slirp (where this code comes from), with the following checkin:

commit 2f5f89963186d42a7ded253bc6cf5b32abb45cec
Author: aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>
Date:   Mon Jan 26 19:37:41 2009 +0000

    Remove the advertising clause from the slirp license

    According to the FSF, the 4-clause BSD license, which slirp is covered under,
    is not compatible with the GPL or LGPL[1].

    [1] http://www.fsf.org/licensing/licenses/index_html#GPLIncompatibleLicenses

    There are three declared copyright holders in slirp that use the 4-clause
    BSD license, the Regents of UC Berkley, Danny Gasparovski, and Kelly Price.
    Below are the appropriate permissions to remove the advertise clause from slirp
    from each party.

    Special thanks go to Richard Fontana from Red Hat for contacting all of the
    necessary authors to resolve this issue!

    Regents of UC Berkley:
    From ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change

    July 22, 1999

    To All Licensees, Distributors of Any Version of BSD:

    As you know, certain of the Berkeley Software Distribution ("BSD") source
    code files require that further distributions of products containing all or
    portions of the software, acknowledge within their advertising materials
    that such products contain software developed by UC Berkeley and its
    contributors.

    Specifically, the provision reads:

    "     * 3. All advertising materials mentioning features or use of this software
          *    must display the following acknowledgement:
          *    This product includes software developed by the University of
          *    California, Berkeley and its contributors."

    Effective immediately, licensees and distributors are no longer required to
    include the acknowledgement within advertising materials.  Accordingly, the
    foregoing paragraph of those BSD Unix files containing it is hereby deleted
    in its entirety.

    William Hoskins
    Director, Office of Technology Licensing
    University of California, Berkeley

    Danny Gasparovski:

    Subject: RE: Slirp license
    Date: Thu, 8 Jan 2009 10:51:00 +1100
    From: "Gasparovski, Daniel" <Daniel.Gasparovski@ato.gov.au>
    To: "Richard Fontana" <rfontana@redhat.com>

    Hi Richard,

    I have no objection to having Slirp code in QEMU be licensed under the
    3-clause BSD license.

    Thanks for taking the effort to consult me about this.


    Dan ...

    Kelly Price:

    Date: Thu, 8 Jan 2009 19:38:56 -0500
    From: "Kelly Price" <strredwolf@gmail.com>
    To: "Richard Fontana" <rfontana@redhat.com>
    Subject: Re: Slirp license

    Thanks for contacting me, Richard.  I'm glad you were able to find
    Dan, as I've been "keeping the light on" for Slirp.  I have no use for
    it now, and I have little time for it (now holding onto Keenspot's
    Comic Genesis and having a regular US state government position). If
    Dan would like to return to the project, I'd love to give it back to
    him.

    As for copyright, I don't own all of it.  Dan does, so I will defer to
    him.  Any of my patches I will gladly license to the 3-part BSD
    license.  My interest in re-licensing was because we didn't have ready
    info to contact Dan.  If Dan would like to port Slirp back out of
    QEMU, a lot of us 64-bit users would be grateful.

    Feel free to share this email address with Dan.  I will be glad to
    effect a transfer of the project to him and Mr. Bellard of the QEMU
    project.

    Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


    git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6451 c046a42c-6fe2-441c-8c8c-71466251a162

File Contents

# Content
1 /*
2 * Copyright (c) 1982, 1986, 1988, 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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
30 * ip_icmp.c,v 1.7 1995/05/30 08:09:42 rgrimes Exp
31 */
32
33 #include "slirp.h"
34 #include "ip_icmp.h"
35
36 struct icmpstat icmpstat;
37
38 /* The message sent when emulating PING */
39 /* Be nice and tell them it's just a psuedo-ping packet */
40 char icmp_ping_msg[] = "This is a psuedo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n";
41
42 /* list of actions for icmp_error() on RX of an icmp message */
43 static int icmp_flush[19] = {
44 /* ECHO REPLY (0) */ 0,
45 1,
46 1,
47 /* DEST UNREACH (3) */ 1,
48 /* SOURCE QUENCH (4)*/ 1,
49 /* REDIRECT (5) */ 1,
50 1,
51 1,
52 /* ECHO (8) */ 0,
53 /* ROUTERADVERT (9) */ 1,
54 /* ROUTERSOLICIT (10) */ 1,
55 /* TIME EXCEEDED (11) */ 1,
56 /* PARAMETER PROBLEM (12) */ 1,
57 /* TIMESTAMP (13) */ 0,
58 /* TIMESTAMP REPLY (14) */ 0,
59 /* INFO (15) */ 0,
60 /* INFO REPLY (16) */ 0,
61 /* ADDR MASK (17) */ 0,
62 /* ADDR MASK REPLY (18) */ 0
63 };
64
65 /*
66 * Process a received ICMP message.
67 */
68 void
69 icmp_input(m, hlen)
70 struct mbuf *m;
71 int hlen;
72 {
73 register struct icmp *icp;
74 register struct ip *ip=mtod(m, struct ip *);
75 int icmplen=ip->ip_len;
76 /* int code; */
77
78 DEBUG_CALL("icmp_input");
79 DEBUG_ARG("m = %lx", (long )m);
80 DEBUG_ARG("m_len = %d", m->m_len);
81
82 icmpstat.icps_received++;
83
84 /*
85 * Locate icmp structure in mbuf, and check
86 * that its not corrupted and of at least minimum length.
87 */
88 if (icmplen < ICMP_MINLEN) { /* min 8 bytes payload */
89 icmpstat.icps_tooshort++;
90 freeit:
91 m_freem(m);
92 goto end_error;
93 }
94
95 m->m_len -= hlen;
96 m->m_data += hlen;
97 icp = mtod(m, struct icmp *);
98 if (cksum(m, icmplen)) {
99 icmpstat.icps_checksum++;
100 goto freeit;
101 }
102 m->m_len += hlen;
103 m->m_data -= hlen;
104
105 /* icmpstat.icps_inhist[icp->icmp_type]++; */
106 /* code = icp->icmp_code; */
107
108 DEBUG_ARG("icmp_type = %d", icp->icmp_type);
109 switch (icp->icmp_type) {
110 case ICMP_ECHO:
111 icp->icmp_type = ICMP_ECHOREPLY;
112 ip->ip_len += hlen; /* since ip_input subtracts this */
113 if (ip->ip_dst.s_addr == alias_addr.s_addr) {
114 icmp_reflect(m);
115 } else {
116 struct socket *so;
117 struct sockaddr_in addr;
118 if ((so = socreate()) == NULL) goto freeit;
119 if(udp_attach(so) == -1) {
120 DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n",
121 errno,strerror(errno)));
122 sofree(so);
123 m_free(m);
124 goto end_error;
125 }
126 so->so_m = m;
127 so->so_faddr = ip->ip_dst;
128 so->so_fport = htons(7);
129 so->so_laddr = ip->ip_src;
130 so->so_lport = htons(9);
131 so->so_iptos = ip->ip_tos;
132 so->so_type = IPPROTO_ICMP;
133 so->so_state = SS_ISFCONNECTED;
134
135 /* Send the packet */
136 addr.sin_family = AF_INET;
137 if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
138 /* It's an alias */
139 switch(ntohl(so->so_faddr.s_addr) & 0xff) {
140 case CTL_DNS:
141 addr.sin_addr = dns_addr;
142 break;
143 case CTL_ALIAS:
144 default:
145 addr.sin_addr = loopback_addr;
146 break;
147 }
148 } else {
149 addr.sin_addr = so->so_faddr;
150 }
151 addr.sin_port = so->so_fport;
152 if(sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0,
153 (struct sockaddr *)&addr, sizeof(addr)) == -1) {
154 DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n",
155 errno,strerror(errno)));
156 icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
157 udp_detach(so);
158 }
159 } /* if ip->ip_dst.s_addr == alias_addr.s_addr */
160 break;
161 case ICMP_UNREACH:
162 /* XXX? report error? close socket? */
163 case ICMP_TIMXCEED:
164 case ICMP_PARAMPROB:
165 case ICMP_SOURCEQUENCH:
166 case ICMP_TSTAMP:
167 case ICMP_MASKREQ:
168 case ICMP_REDIRECT:
169 icmpstat.icps_notsupp++;
170 m_freem(m);
171 break;
172
173 default:
174 icmpstat.icps_badtype++;
175 m_freem(m);
176 } /* swith */
177
178 end_error:
179 /* m is m_free()'d xor put in a socket xor or given to ip_send */
180 return;
181 }
182
183
184 /*
185 * Send an ICMP message in response to a situation
186 *
187 * RFC 1122: 3.2.2 MUST send at least the IP header and 8 bytes of header. MAY send more (we do).
188 * MUST NOT change this header information.
189 * MUST NOT reply to a multicast/broadcast IP address.
190 * MUST NOT reply to a multicast/broadcast MAC address.
191 * MUST reply to only the first fragment.
192 */
193 /*
194 * Send ICMP_UNREACH back to the source regarding msrc.
195 * mbuf *msrc is used as a template, but is NOT m_free()'d.
196 * It is reported as the bad ip packet. The header should
197 * be fully correct and in host byte order.
198 * ICMP fragmentation is illegal. All machines must accept 576 bytes in one
199 * packet. The maximum payload is 576-20(ip hdr)-8(icmp hdr)=548
200 */
201
202 #define ICMP_MAXDATALEN (IP_MSS-28)
203 void
204 icmp_error(msrc, type, code, minsize, message)
205 struct mbuf *msrc;
206 u_char type;
207 u_char code;
208 int minsize;
209 char *message;
210 {
211 unsigned hlen, shlen, s_ip_len;
212 register struct ip *ip;
213 register struct icmp *icp;
214 register struct mbuf *m;
215
216 DEBUG_CALL("icmp_error");
217 DEBUG_ARG("msrc = %lx", (long )msrc);
218 DEBUG_ARG("msrc_len = %d", msrc->m_len);
219
220 if(type!=ICMP_UNREACH && type!=ICMP_TIMXCEED) goto end_error;
221
222 /* check msrc */
223 if(!msrc) goto end_error;
224 ip = mtod(msrc, struct ip *);
225 #if DEBUG
226 { char bufa[20], bufb[20];
227 strcpy(bufa, inet_ntoa(ip->ip_src));
228 strcpy(bufb, inet_ntoa(ip->ip_dst));
229 DEBUG_MISC((dfd, " %.16s to %.16s\n", bufa, bufb));
230 }
231 #endif
232 if(ip->ip_off & IP_OFFMASK) goto end_error; /* Only reply to fragment 0 */
233
234 shlen=ip->ip_hl << 2;
235 s_ip_len=ip->ip_len;
236 if(ip->ip_p == IPPROTO_ICMP) {
237 icp = (struct icmp *)((char *)ip + shlen);
238 /*
239 * Assume any unknown ICMP type is an error. This isn't
240 * specified by the RFC, but think about it..
241 */
242 if(icp->icmp_type>18 || icmp_flush[icp->icmp_type]) goto end_error;
243 }
244
245 /* make a copy */
246 if(!(m=m_get())) goto end_error; /* get mbuf */
247 { int new_m_size;
248 new_m_size=sizeof(struct ip )+ICMP_MINLEN+msrc->m_len+ICMP_MAXDATALEN;
249 if(new_m_size>m->m_size) m_inc(m, new_m_size);
250 }
251 memcpy(m->m_data, msrc->m_data, msrc->m_len);
252 m->m_len = msrc->m_len; /* copy msrc to m */
253
254 /* make the header of the reply packet */
255 ip = mtod(m, struct ip *);
256 hlen= sizeof(struct ip ); /* no options in reply */
257
258 /* fill in icmp */
259 m->m_data += hlen;
260 m->m_len -= hlen;
261
262 icp = mtod(m, struct icmp *);
263
264 if(minsize) s_ip_len=shlen+ICMP_MINLEN; /* return header+8b only */
265 else if(s_ip_len>ICMP_MAXDATALEN) /* maximum size */
266 s_ip_len=ICMP_MAXDATALEN;
267
268 m->m_len=ICMP_MINLEN+s_ip_len; /* 8 bytes ICMP header */
269
270 /* min. size = 8+sizeof(struct ip)+8 */
271
272 icp->icmp_type = type;
273 icp->icmp_code = code;
274 icp->icmp_id = 0;
275 icp->icmp_seq = 0;
276
277 memcpy(&icp->icmp_ip, msrc->m_data, s_ip_len); /* report the ip packet */
278 HTONS(icp->icmp_ip.ip_len);
279 HTONS(icp->icmp_ip.ip_id);
280 HTONS(icp->icmp_ip.ip_off);
281
282 #if DEBUG
283 if(message) { /* DEBUG : append message to ICMP packet */
284 int message_len;
285 char *cpnt;
286 message_len=strlen(message);
287 if(message_len>ICMP_MAXDATALEN) message_len=ICMP_MAXDATALEN;
288 cpnt=(char *)m->m_data+m->m_len;
289 memcpy(cpnt, message, message_len);
290 m->m_len+=message_len;
291 }
292 #endif
293
294 icp->icmp_cksum = 0;
295 icp->icmp_cksum = cksum(m, m->m_len);
296
297 m->m_data -= hlen;
298 m->m_len += hlen;
299
300 /* fill in ip */
301 ip->ip_hl = hlen >> 2;
302 ip->ip_len = m->m_len;
303
304 ip->ip_tos=((ip->ip_tos & 0x1E) | 0xC0); /* high priority for errors */
305
306 ip->ip_ttl = MAXTTL;
307 ip->ip_p = IPPROTO_ICMP;
308 ip->ip_dst = ip->ip_src; /* ip adresses */
309 ip->ip_src = alias_addr;
310
311 (void ) ip_output((struct socket *)NULL, m);
312
313 icmpstat.icps_reflect++;
314
315 end_error:
316 return;
317 }
318 #undef ICMP_MAXDATALEN
319
320 /*
321 * Reflect the ip packet back to the source
322 */
323 void
324 icmp_reflect(m)
325 struct mbuf *m;
326 {
327 register struct ip *ip = mtod(m, struct ip *);
328 int hlen = ip->ip_hl << 2;
329 int optlen = hlen - sizeof(struct ip );
330 register struct icmp *icp;
331
332 /*
333 * Send an icmp packet back to the ip level,
334 * after supplying a checksum.
335 */
336 m->m_data += hlen;
337 m->m_len -= hlen;
338 icp = mtod(m, struct icmp *);
339
340 icp->icmp_cksum = 0;
341 icp->icmp_cksum = cksum(m, ip->ip_len - hlen);
342
343 m->m_data -= hlen;
344 m->m_len += hlen;
345
346 /* fill in ip */
347 if (optlen > 0) {
348 /*
349 * Strip out original options by copying rest of first
350 * mbuf's data back, and adjust the IP length.
351 */
352 memmove((caddr_t)(ip + 1), (caddr_t)ip + hlen,
353 (unsigned )(m->m_len - hlen));
354 hlen -= optlen;
355 ip->ip_hl = hlen >> 2;
356 ip->ip_len -= optlen;
357 m->m_len -= optlen;
358 }
359
360 ip->ip_ttl = MAXTTL;
361 { /* swap */
362 struct in_addr icmp_dst;
363 icmp_dst = ip->ip_dst;
364 ip->ip_dst = ip->ip_src;
365 ip->ip_src = icmp_dst;
366 }
367
368 (void ) ip_output((struct socket *)NULL, m);
369
370 icmpstat.icps_reflect++;
371 }