ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/slirp/ip_input.c
Revision: 1.3
Committed: 2012-03-30T01:10:28Z (12 years, 6 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_input.c 8.2 (Berkeley) 1/4/94
30     * ip_input.c,v 1.11 1994/11/16 10:17:08 jkh Exp
31     */
32    
33     /*
34     * Changes and additions relating to SLiRP are
35     * Copyright (c) 1995 Danny Gasparovski.
36     *
37     * Please read the file COPYRIGHT for the
38     * terms and conditions of the copyright.
39     */
40    
41     #include <slirp.h>
42     #include "ip_icmp.h"
43    
44     int ip_defttl;
45     struct ipstat ipstat;
46     struct ipq ipq;
47    
48     /*
49     * IP initialization: fill in IP protocol switch table.
50     * All protocols not implemented in kernel go to raw IP protocol handler.
51     */
52     void
53     ip_init()
54     {
55     ipq.next = ipq.prev = (ipqp_32)&ipq;
56     ip_id = tt.tv_sec & 0xffff;
57     udp_init();
58     tcp_init();
59     ip_defttl = IPDEFTTL;
60     }
61    
62     /*
63     * Ip input routine. Checksum and byte swap header. If fragmented
64     * try to reassemble. Process options. Pass to next level.
65     */
66     void
67     ip_input(m)
68     struct mbuf *m;
69     {
70     register struct ip *ip;
71     int hlen;
72    
73     DEBUG_CALL("ip_input");
74     DEBUG_ARG("m = %lx", (long)m);
75     DEBUG_ARG("m_len = %d", m->m_len);
76    
77     ipstat.ips_total++;
78    
79     if (m->m_len < sizeof (struct ip)) {
80     ipstat.ips_toosmall++;
81     return;
82     }
83    
84     ip = mtod(m, struct ip *);
85    
86     if (ip->ip_v != IPVERSION) {
87     ipstat.ips_badvers++;
88     goto bad;
89     }
90    
91     hlen = ip->ip_hl << 2;
92     if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */
93     ipstat.ips_badhlen++; /* or packet too short */
94     goto bad;
95     }
96    
97     /* keep ip header intact for ICMP reply
98     * ip->ip_sum = cksum(m, hlen);
99     * if (ip->ip_sum) {
100     */
101     if(cksum(m,hlen)) {
102     ipstat.ips_badsum++;
103     goto bad;
104     }
105    
106     /*
107     * Convert fields to host representation.
108     */
109     NTOHS(ip->ip_len);
110     if (ip->ip_len < hlen) {
111     ipstat.ips_badlen++;
112     goto bad;
113     }
114     NTOHS(ip->ip_id);
115     NTOHS(ip->ip_off);
116    
117     /*
118     * Check that the amount of data in the buffers
119     * is as at least much as the IP header would have us expect.
120     * Trim mbufs if longer than we expect.
121     * Drop packet if shorter than we expect.
122     */
123     if (m->m_len < ip->ip_len) {
124     ipstat.ips_tooshort++;
125     goto bad;
126     }
127     /* Should drop packet if mbuf too long? hmmm... */
128     if (m->m_len > ip->ip_len)
129     m_adj(m, ip->ip_len - m->m_len);
130    
131     /* check ip_ttl for a correct ICMP reply */
132     if(ip->ip_ttl==0 || ip->ip_ttl==1) {
133     icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl");
134     goto bad;
135     }
136    
137     /*
138     * Process options and, if not destined for us,
139     * ship it on. ip_dooptions returns 1 when an
140     * error was detected (causing an icmp message
141     * to be sent and the original packet to be freed).
142     */
143     /* We do no IP options */
144     /* if (hlen > sizeof (struct ip) && ip_dooptions(m))
145     * goto next;
146     */
147     /*
148     * If offset or IP_MF are set, must reassemble.
149     * Otherwise, nothing need be done.
150     * (We could look in the reassembly queue to see
151     * if the packet was previously fragmented,
152     * but it's not worth the time; just let them time out.)
153     *
154     * XXX This should fail, don't fragment yet
155     */
156     if (ip->ip_off &~ IP_DF) {
157     register struct ipq *fp;
158     /*
159     * Look for queue of fragments
160     * of this datagram.
161     */
162     for (fp = (struct ipq *) ipq.next; fp != &ipq;
163     fp = (struct ipq *) fp->next)
164     if (ip->ip_id == fp->ipq_id &&
165     ip->ip_src.s_addr == fp->ipq_src.s_addr &&
166     ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
167     ip->ip_p == fp->ipq_p)
168     goto found;
169     fp = 0;
170     found:
171    
172     /*
173     * Adjust ip_len to not reflect header,
174     * set ip_mff if more fragments are expected,
175     * convert offset of this to bytes.
176     */
177     ip->ip_len -= hlen;
178     if (ip->ip_off & IP_MF)
179     ((struct ipasfrag *)ip)->ipf_mff |= 1;
180     else
181     ((struct ipasfrag *)ip)->ipf_mff &= ~1;
182    
183     ip->ip_off <<= 3;
184    
185     /*
186     * If datagram marked as having more fragments
187     * or if this is not the first fragment,
188     * attempt reassembly; if it succeeds, proceed.
189     */
190     if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
191     ipstat.ips_fragments++;
192     ip = ip_reass((struct ipasfrag *)ip, fp);
193     if (ip == 0)
194     return;
195     ipstat.ips_reassembled++;
196     m = dtom(ip);
197     } else
198     if (fp)
199     ip_freef(fp);
200    
201     } else
202     ip->ip_len -= hlen;
203    
204     /*
205     * Switch out to protocol's input routine.
206     */
207     ipstat.ips_delivered++;
208     switch (ip->ip_p) {
209     case IPPROTO_TCP:
210     tcp_input(m, hlen, (struct socket *)NULL);
211     break;
212     case IPPROTO_UDP:
213     udp_input(m, hlen);
214     break;
215     case IPPROTO_ICMP:
216     icmp_input(m, hlen);
217     break;
218     default:
219     ipstat.ips_noproto++;
220     m_free(m);
221     }
222     return;
223     bad:
224     m_freem(m);
225     return;
226     }
227    
228     /*
229     * Take incoming datagram fragment and try to
230     * reassemble it into whole datagram. If a chain for
231     * reassembly of this datagram already exists, then it
232     * is given as fp; otherwise have to make a chain.
233     */
234     struct ip *
235     ip_reass(ip, fp)
236     register struct ipasfrag *ip;
237     register struct ipq *fp;
238     {
239     register struct mbuf *m = dtom(ip);
240     register struct ipasfrag *q;
241     int hlen = ip->ip_hl << 2;
242     int i, next;
243    
244     DEBUG_CALL("ip_reass");
245     DEBUG_ARG("ip = %lx", (long)ip);
246     DEBUG_ARG("fp = %lx", (long)fp);
247     DEBUG_ARG("m = %lx", (long)m);
248    
249     /*
250     * Presence of header sizes in mbufs
251     * would confuse code below.
252     * Fragment m_data is concatenated.
253     */
254     m->m_data += hlen;
255     m->m_len -= hlen;
256    
257     /*
258     * If first fragment to arrive, create a reassembly queue.
259     */
260     if (fp == 0) {
261     struct mbuf *t;
262     if ((t = m_get()) == NULL) goto dropfrag;
263     fp = mtod(t, struct ipq *);
264     insque_32(fp, &ipq);
265     fp->ipq_ttl = IPFRAGTTL;
266     fp->ipq_p = ip->ip_p;
267     fp->ipq_id = ip->ip_id;
268     fp->ipq_next = fp->ipq_prev = (ipasfragp_32)fp;
269     fp->ipq_src = ((struct ip *)ip)->ip_src;
270     fp->ipq_dst = ((struct ip *)ip)->ip_dst;
271     q = (struct ipasfrag *)fp;
272     goto insert;
273     }
274    
275     /*
276     * Find a segment which begins after this one does.
277     */
278     for (q = (struct ipasfrag *)fp->ipq_next; q != (struct ipasfrag *)fp;
279     q = (struct ipasfrag *)q->ipf_next)
280     if (q->ip_off > ip->ip_off)
281     break;
282    
283     /*
284     * If there is a preceding segment, it may provide some of
285     * our data already. If so, drop the data from the incoming
286     * segment. If it provides all of our data, drop us.
287     */
288     if (q->ipf_prev != (ipasfragp_32)fp) {
289     i = ((struct ipasfrag *)(q->ipf_prev))->ip_off +
290     ((struct ipasfrag *)(q->ipf_prev))->ip_len - ip->ip_off;
291     if (i > 0) {
292     if (i >= ip->ip_len)
293     goto dropfrag;
294     m_adj(dtom(ip), i);
295     ip->ip_off += i;
296     ip->ip_len -= i;
297     }
298     }
299    
300     /*
301     * While we overlap succeeding segments trim them or,
302     * if they are completely covered, dequeue them.
303     */
304     while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) {
305     i = (ip->ip_off + ip->ip_len) - q->ip_off;
306     if (i < q->ip_len) {
307     q->ip_len -= i;
308     q->ip_off += i;
309     m_adj(dtom(q), i);
310     break;
311     }
312     q = (struct ipasfrag *) q->ipf_next;
313     m_freem(dtom((struct ipasfrag *) q->ipf_prev));
314     ip_deq((struct ipasfrag *) q->ipf_prev);
315     }
316    
317     insert:
318     /*
319     * Stick new segment in its place;
320     * check for complete reassembly.
321     */
322     ip_enq(ip, (struct ipasfrag *) q->ipf_prev);
323     next = 0;
324     for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
325     q = (struct ipasfrag *) q->ipf_next) {
326     if (q->ip_off != next)
327     return (0);
328     next += q->ip_len;
329     }
330     if (((struct ipasfrag *)(q->ipf_prev))->ipf_mff & 1)
331     return (0);
332    
333     /*
334     * Reassembly is complete; concatenate fragments.
335     */
336     q = (struct ipasfrag *) fp->ipq_next;
337     m = dtom(q);
338    
339     q = (struct ipasfrag *) q->ipf_next;
340     while (q != (struct ipasfrag *)fp) {
341     struct mbuf *t;
342     t = dtom(q);
343 gbeauche 1.2 q = (struct ipasfrag *) q->ipf_next;
344 gbeauche 1.1 m_cat(m, t);
345     }
346    
347     /*
348     * Create header for new ip packet by
349     * modifying header of first packet;
350     * dequeue and discard fragment reassembly header.
351     * Make header visible.
352     */
353     ip = (struct ipasfrag *) fp->ipq_next;
354    
355     /*
356     * If the fragments concatenated to an mbuf that's
357     * bigger than the total size of the fragment, then and
358     * m_ext buffer was alloced. But fp->ipq_next points to
359     * the old buffer (in the mbuf), so we must point ip
360     * into the new buffer.
361     */
362     if (m->m_flags & M_EXT) {
363     int delta;
364     delta = (char *)ip - m->m_dat;
365     ip = (struct ipasfrag *)(m->m_ext + delta);
366     }
367    
368     /* DEBUG_ARG("ip = %lx", (long)ip);
369     * ip=(struct ipasfrag *)m->m_data; */
370    
371     ip->ip_len = next;
372     ip->ipf_mff &= ~1;
373     ((struct ip *)ip)->ip_src = fp->ipq_src;
374     ((struct ip *)ip)->ip_dst = fp->ipq_dst;
375     remque_32(fp);
376     (void) m_free(dtom(fp));
377     m = dtom(ip);
378     m->m_len += (ip->ip_hl << 2);
379     m->m_data -= (ip->ip_hl << 2);
380    
381     return ((struct ip *)ip);
382    
383     dropfrag:
384     ipstat.ips_fragdropped++;
385     m_freem(m);
386     return (0);
387     }
388    
389     /*
390     * Free a fragment reassembly header and all
391     * associated datagrams.
392     */
393     void
394     ip_freef(fp)
395     struct ipq *fp;
396     {
397     register struct ipasfrag *q, *p;
398    
399     for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
400     q = p) {
401     p = (struct ipasfrag *) q->ipf_next;
402     ip_deq(q);
403     m_freem(dtom(q));
404     }
405     remque_32(fp);
406     (void) m_free(dtom(fp));
407     }
408    
409     /*
410     * Put an ip fragment on a reassembly chain.
411     * Like insque, but pointers in middle of structure.
412     */
413     void
414     ip_enq(p, prev)
415     register struct ipasfrag *p, *prev;
416     {
417     DEBUG_CALL("ip_enq");
418     DEBUG_ARG("prev = %lx", (long)prev);
419     p->ipf_prev = (ipasfragp_32) prev;
420     p->ipf_next = prev->ipf_next;
421     ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = (ipasfragp_32) p;
422     prev->ipf_next = (ipasfragp_32) p;
423     }
424    
425     /*
426     * To ip_enq as remque is to insque.
427     */
428     void
429     ip_deq(p)
430     register struct ipasfrag *p;
431     {
432     ((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next;
433     ((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev;
434     }
435    
436     /*
437     * IP timer processing;
438     * if a timer expires on a reassembly
439     * queue, discard it.
440     */
441     void
442     ip_slowtimo()
443     {
444     register struct ipq *fp;
445    
446     DEBUG_CALL("ip_slowtimo");
447    
448     fp = (struct ipq *) ipq.next;
449     if (fp == 0)
450     return;
451    
452     while (fp != &ipq) {
453     --fp->ipq_ttl;
454     fp = (struct ipq *) fp->next;
455     if (((struct ipq *)(fp->prev))->ipq_ttl == 0) {
456     ipstat.ips_fragtimeout++;
457     ip_freef((struct ipq *) fp->prev);
458     }
459     }
460     }
461    
462     /*
463     * Do option processing on a datagram,
464     * possibly discarding it if bad options are encountered,
465     * or forwarding it if source-routed.
466     * Returns 1 if packet has been forwarded/freed,
467     * 0 if the packet should be processed further.
468     */
469    
470     #ifdef notdef
471    
472     int
473     ip_dooptions(m)
474     struct mbuf *m;
475     {
476     register struct ip *ip = mtod(m, struct ip *);
477     register u_char *cp;
478     register struct ip_timestamp *ipt;
479     register struct in_ifaddr *ia;
480     /* int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; */
481     int opt, optlen, cnt, off, code, type, forward = 0;
482     struct in_addr *sin, dst;
483     typedef u_int32_t n_time;
484     n_time ntime;
485    
486     dst = ip->ip_dst;
487     cp = (u_char *)(ip + 1);
488     cnt = (ip->ip_hl << 2) - sizeof (struct ip);
489     for (; cnt > 0; cnt -= optlen, cp += optlen) {
490     opt = cp[IPOPT_OPTVAL];
491     if (opt == IPOPT_EOL)
492     break;
493     if (opt == IPOPT_NOP)
494     optlen = 1;
495     else {
496     optlen = cp[IPOPT_OLEN];
497     if (optlen <= 0 || optlen > cnt) {
498     code = &cp[IPOPT_OLEN] - (u_char *)ip;
499     goto bad;
500     }
501     }
502     switch (opt) {
503    
504     default:
505     break;
506    
507     /*
508     * Source routing with record.
509     * Find interface with current destination address.
510     * If none on this machine then drop if strictly routed,
511     * or do nothing if loosely routed.
512     * Record interface address and bring up next address
513     * component. If strictly routed make sure next
514     * address is on directly accessible net.
515     */
516     case IPOPT_LSRR:
517     case IPOPT_SSRR:
518     if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
519     code = &cp[IPOPT_OFFSET] - (u_char *)ip;
520     goto bad;
521     }
522     ipaddr.sin_addr = ip->ip_dst;
523     ia = (struct in_ifaddr *)
524     ifa_ifwithaddr((struct sockaddr *)&ipaddr);
525     if (ia == 0) {
526     if (opt == IPOPT_SSRR) {
527     type = ICMP_UNREACH;
528     code = ICMP_UNREACH_SRCFAIL;
529     goto bad;
530     }
531     /*
532     * Loose routing, and not at next destination
533     * yet; nothing to do except forward.
534     */
535     break;
536     }
537     off--; / * 0 origin * /
538     if (off > optlen - sizeof(struct in_addr)) {
539     /*
540     * End of source route. Should be for us.
541     */
542     save_rte(cp, ip->ip_src);
543     break;
544     }
545     /*
546     * locate outgoing interface
547     */
548     bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr,
549     sizeof(ipaddr.sin_addr));
550     if (opt == IPOPT_SSRR) {
551     #define INA struct in_ifaddr *
552     #define SA struct sockaddr *
553     if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0)
554     ia = (INA)ifa_ifwithnet((SA)&ipaddr);
555     } else
556     ia = ip_rtaddr(ipaddr.sin_addr);
557     if (ia == 0) {
558     type = ICMP_UNREACH;
559     code = ICMP_UNREACH_SRCFAIL;
560     goto bad;
561     }
562     ip->ip_dst = ipaddr.sin_addr;
563     bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
564     (caddr_t)(cp + off), sizeof(struct in_addr));
565     cp[IPOPT_OFFSET] += sizeof(struct in_addr);
566     /*
567     * Let ip_intr's mcast routing check handle mcast pkts
568     */
569     forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr));
570     break;
571    
572     case IPOPT_RR:
573     if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
574     code = &cp[IPOPT_OFFSET] - (u_char *)ip;
575     goto bad;
576     }
577     /*
578     * If no space remains, ignore.
579     */
580     off--; * 0 origin *
581     if (off > optlen - sizeof(struct in_addr))
582     break;
583     bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr,
584     sizeof(ipaddr.sin_addr));
585     /*
586     * locate outgoing interface; if we're the destination,
587     * use the incoming interface (should be same).
588     */
589     if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 &&
590     (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {
591     type = ICMP_UNREACH;
592     code = ICMP_UNREACH_HOST;
593     goto bad;
594     }
595     bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
596     (caddr_t)(cp + off), sizeof(struct in_addr));
597     cp[IPOPT_OFFSET] += sizeof(struct in_addr);
598     break;
599    
600     case IPOPT_TS:
601     code = cp - (u_char *)ip;
602     ipt = (struct ip_timestamp *)cp;
603     if (ipt->ipt_len < 5)
604     goto bad;
605     if (ipt->ipt_ptr > ipt->ipt_len - sizeof (int32_t)) {
606     if (++ipt->ipt_oflw == 0)
607     goto bad;
608     break;
609     }
610     sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);
611     switch (ipt->ipt_flg) {
612    
613     case IPOPT_TS_TSONLY:
614     break;
615    
616     case IPOPT_TS_TSANDADDR:
617     if (ipt->ipt_ptr + sizeof(n_time) +
618     sizeof(struct in_addr) > ipt->ipt_len)
619     goto bad;
620     ipaddr.sin_addr = dst;
621     ia = (INA)ifaof_ i f p foraddr((SA)&ipaddr,
622     m->m_pkthdr.rcvif);
623     if (ia == 0)
624     continue;
625     bcopy((caddr_t)&IA_SIN(ia)->sin_addr,
626     (caddr_t)sin, sizeof(struct in_addr));
627     ipt->ipt_ptr += sizeof(struct in_addr);
628     break;
629    
630     case IPOPT_TS_PRESPEC:
631     if (ipt->ipt_ptr + sizeof(n_time) +
632     sizeof(struct in_addr) > ipt->ipt_len)
633     goto bad;
634     bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr,
635     sizeof(struct in_addr));
636     if (ifa_ifwithaddr((SA)&ipaddr) == 0)
637     continue;
638     ipt->ipt_ptr += sizeof(struct in_addr);
639     break;
640    
641     default:
642     goto bad;
643     }
644     ntime = iptime();
645     bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1,
646     sizeof(n_time));
647     ipt->ipt_ptr += sizeof(n_time);
648     }
649     }
650     if (forward) {
651     ip_forward(m, 1);
652     return (1);
653     }
654     }
655     }
656     return (0);
657     bad:
658     /* ip->ip_len -= ip->ip_hl << 2; XXX icmp_error adds in hdr length */
659    
660     /* Not yet */
661     icmp_error(m, type, code, 0, 0);
662    
663     ipstat.ips_badoptions++;
664     return (1);
665     }
666    
667     #endif /* notdef */
668    
669     /*
670     * Strip out IP options, at higher
671     * level protocol in the kernel.
672     * Second argument is buffer to which options
673     * will be moved, and return value is their length.
674     * (XXX) should be deleted; last arg currently ignored.
675     */
676     void
677     ip_stripoptions(m, mopt)
678     register struct mbuf *m;
679     struct mbuf *mopt;
680     {
681     register int i;
682     struct ip *ip = mtod(m, struct ip *);
683     register caddr_t opts;
684     int olen;
685    
686     olen = (ip->ip_hl<<2) - sizeof (struct ip);
687     opts = (caddr_t)(ip + 1);
688     i = m->m_len - (sizeof (struct ip) + olen);
689     memcpy(opts, opts + olen, (unsigned)i);
690     m->m_len -= olen;
691    
692     ip->ip_hl = sizeof(struct ip) >> 2;
693     }