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, 7 months 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

# User Rev Content
1 gbeauche 1.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 asvitkine 1.3 * 3. Neither the name of the University nor the names of its contributors
14 gbeauche 1.1 * 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 gbeauche 1.2 if (ip->ip_dst.s_addr == alias_addr.s_addr) {
114 gbeauche 1.1 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 gbeauche 1.2 } /* if ip->ip_dst.s_addr == alias_addr.s_addr */
160 gbeauche 1.1 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 gbeauche 1.2 ip->ip_src = alias_addr;
310 gbeauche 1.1
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     }