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