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

# 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_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 q = (struct ipasfrag *) q->ipf_next;
344 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 }