VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/slirp/ip_input.c@ 14227

Last change on this file since 14227 was 14227, checked in by vboxsync, 16 years ago

initial preparation for injecting FreeBSD IP fragmentation code
(Windows compilation wasn't checked)

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette