xref: /openbsd/sys/netinet6/dest6.c (revision 287546ea)
1*287546eaSitojun /*	$OpenBSD: dest6.c,v 1.1 1999/12/08 06:50:20 itojun Exp $	*/
2*287546eaSitojun 
3*287546eaSitojun /*
4*287546eaSitojun  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5*287546eaSitojun  * All rights reserved.
6*287546eaSitojun  *
7*287546eaSitojun  * Redistribution and use in source and binary forms, with or without
8*287546eaSitojun  * modification, are permitted provided that the following conditions
9*287546eaSitojun  * are met:
10*287546eaSitojun  * 1. Redistributions of source code must retain the above copyright
11*287546eaSitojun  *    notice, this list of conditions and the following disclaimer.
12*287546eaSitojun  * 2. Redistributions in binary form must reproduce the above copyright
13*287546eaSitojun  *    notice, this list of conditions and the following disclaimer in the
14*287546eaSitojun  *    documentation and/or other materials provided with the distribution.
15*287546eaSitojun  * 3. Neither the name of the project nor the names of its contributors
16*287546eaSitojun  *    may be used to endorse or promote products derived from this software
17*287546eaSitojun  *    without specific prior written permission.
18*287546eaSitojun  *
19*287546eaSitojun  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20*287546eaSitojun  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*287546eaSitojun  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*287546eaSitojun  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23*287546eaSitojun  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*287546eaSitojun  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*287546eaSitojun  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*287546eaSitojun  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*287546eaSitojun  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*287546eaSitojun  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*287546eaSitojun  * SUCH DAMAGE.
30*287546eaSitojun  */
31*287546eaSitojun 
32*287546eaSitojun #include <sys/param.h>
33*287546eaSitojun #include <sys/systm.h>
34*287546eaSitojun #include <sys/malloc.h>
35*287546eaSitojun #include <sys/mbuf.h>
36*287546eaSitojun #include <sys/domain.h>
37*287546eaSitojun #include <sys/protosw.h>
38*287546eaSitojun #include <sys/socket.h>
39*287546eaSitojun #include <sys/errno.h>
40*287546eaSitojun #include <sys/time.h>
41*287546eaSitojun #include <sys/kernel.h>
42*287546eaSitojun 
43*287546eaSitojun #include <net/if.h>
44*287546eaSitojun #include <net/route.h>
45*287546eaSitojun 
46*287546eaSitojun #include <netinet/in.h>
47*287546eaSitojun #include <netinet/in_var.h>
48*287546eaSitojun #include <netinet6/ip6.h>
49*287546eaSitojun #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__OpenBSD__)
50*287546eaSitojun #include <netinet6/in6_pcb.h>
51*287546eaSitojun #endif
52*287546eaSitojun #include <netinet6/ip6_var.h>
53*287546eaSitojun #include <netinet6/icmp6.h>
54*287546eaSitojun 
55*287546eaSitojun /*
56*287546eaSitojun  * Destination options header processing.
57*287546eaSitojun  */
58*287546eaSitojun int
59*287546eaSitojun dest6_input(mp, offp, proto)
60*287546eaSitojun 	struct mbuf **mp;
61*287546eaSitojun 	int *offp, proto;
62*287546eaSitojun {
63*287546eaSitojun 	register struct mbuf *m = *mp;
64*287546eaSitojun 	int off = *offp, dstoptlen, optlen;
65*287546eaSitojun 	struct ip6_dest *dstopts;
66*287546eaSitojun 	u_int8_t *opt;
67*287546eaSitojun 
68*287546eaSitojun 	/* validation of the length of the header */
69*287546eaSitojun #ifndef PULLDOWN_TEST
70*287546eaSitojun 	IP6_EXTHDR_CHECK(m, off, sizeof(*dstopts), IPPROTO_DONE);
71*287546eaSitojun 	dstopts = (struct ip6_dest *)(mtod(m, caddr_t) + off);
72*287546eaSitojun #else
73*287546eaSitojun 	IP6_EXTHDR_GET(dstopts, struct ip6_dest *, m, off, sizeof(*dstopts));
74*287546eaSitojun 	if (dstopts == NULL)
75*287546eaSitojun 		return IPPROTO_DONE;
76*287546eaSitojun #endif
77*287546eaSitojun 	dstoptlen = (dstopts->ip6d_len + 1) << 3;
78*287546eaSitojun 
79*287546eaSitojun #ifndef PULLDOWN_TEST
80*287546eaSitojun 	IP6_EXTHDR_CHECK(m, off, dstoptlen, IPPROTO_DONE);
81*287546eaSitojun 	dstopts = (struct ip6_dest *)(mtod(m, caddr_t) + off);
82*287546eaSitojun #else
83*287546eaSitojun 	IP6_EXTHDR_GET(dstopts, struct ip6_dest *, m, off, dstoptlen);
84*287546eaSitojun 	if (dstopts == NULL)
85*287546eaSitojun 		return IPPROTO_DONE;
86*287546eaSitojun #endif
87*287546eaSitojun 	off += dstoptlen;
88*287546eaSitojun 	dstoptlen -= sizeof(struct ip6_dest);
89*287546eaSitojun 	opt = (u_int8_t *)dstopts + sizeof(struct ip6_dest);
90*287546eaSitojun 
91*287546eaSitojun 	/* search header for all options. */
92*287546eaSitojun 	for (optlen = 0; dstoptlen > 0; dstoptlen -= optlen, opt += optlen) {
93*287546eaSitojun 		switch(*opt) {
94*287546eaSitojun 		 case IP6OPT_PAD1:
95*287546eaSitojun 			 optlen = 1;
96*287546eaSitojun 			 break;
97*287546eaSitojun 		 case IP6OPT_PADN:
98*287546eaSitojun 			 if (dstoptlen < IP6OPT_MINLEN) {
99*287546eaSitojun 				 ip6stat.ip6s_toosmall++;
100*287546eaSitojun 				 goto bad;
101*287546eaSitojun 			 }
102*287546eaSitojun 			 optlen = *(opt + 1) + 2;
103*287546eaSitojun 			 break;
104*287546eaSitojun 		 default:		/* unknown option */
105*287546eaSitojun 			 if (dstoptlen < IP6OPT_MINLEN) {
106*287546eaSitojun 				 ip6stat.ip6s_toosmall++;
107*287546eaSitojun 				 goto bad;
108*287546eaSitojun 			 }
109*287546eaSitojun 			 if ((optlen = ip6_unknown_opt(opt, m,
110*287546eaSitojun 						       opt-mtod(m, u_int8_t *))) == -1)
111*287546eaSitojun 				 return(IPPROTO_DONE);
112*287546eaSitojun 			 optlen += 2;
113*287546eaSitojun 			 break;
114*287546eaSitojun 		}
115*287546eaSitojun 	}
116*287546eaSitojun 
117*287546eaSitojun 	*offp = off;
118*287546eaSitojun 	return(dstopts->ip6d_nxt);
119*287546eaSitojun 
120*287546eaSitojun   bad:
121*287546eaSitojun 	m_freem(m);
122*287546eaSitojun 	return(IPPROTO_DONE);
123*287546eaSitojun }
124