VirtualBox

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

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

Resolved locks in UDP
Some mutex operations checked with AssertReleaseRC
Still TCP part need to be re-checked
udb_mutex now used only for controlling pData->udb
and udp_last_so controlled by udp_last_so_mutex

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

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