1139826Simp/*- 253541Sshin * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 353541Sshin * All rights reserved. 453541Sshin * 553541Sshin * Redistribution and use in source and binary forms, with or without 653541Sshin * modification, are permitted provided that the following conditions 753541Sshin * are met: 853541Sshin * 1. Redistributions of source code must retain the above copyright 953541Sshin * notice, this list of conditions and the following disclaimer. 1053541Sshin * 2. Redistributions in binary form must reproduce the above copyright 1153541Sshin * notice, this list of conditions and the following disclaimer in the 1253541Sshin * documentation and/or other materials provided with the distribution. 1353541Sshin * 3. Neither the name of the project nor the names of its contributors 1453541Sshin * may be used to endorse or promote products derived from this software 1553541Sshin * without specific prior written permission. 1653541Sshin * 1753541Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 1853541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1953541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2053541Sshin * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2153541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2253541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2353541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2453541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2553541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2653541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2753541Sshin * SUCH DAMAGE. 28174510Sobrien * 29174510Sobrien * $KAME: dest6.c,v 1.59 2003/07/11 13:21:16 t-momose Exp $ 3053541Sshin */ 3153541Sshin 32174510Sobrien#include <sys/cdefs.h> 33174510Sobrien__FBSDID("$FreeBSD$"); 34174510Sobrien 3562587Sitojun#include "opt_inet.h" 3662587Sitojun#include "opt_inet6.h" 3762587Sitojun 3853541Sshin#include <sys/param.h> 3953541Sshin#include <sys/systm.h> 4078064Sume#include <sys/malloc.h> 4153541Sshin#include <sys/mbuf.h> 4253541Sshin#include <sys/domain.h> 4353541Sshin#include <sys/protosw.h> 4453541Sshin#include <sys/socket.h> 4553541Sshin#include <sys/errno.h> 4653541Sshin#include <sys/time.h> 4778064Sume#include <sys/kernel.h> 4853541Sshin 4953541Sshin#include <net/if.h> 5053541Sshin#include <net/route.h> 5153541Sshin 5253541Sshin#include <netinet/in.h> 5353541Sshin#include <netinet/in_var.h> 5462587Sitojun#include <netinet/ip6.h> 5553541Sshin#include <netinet6/ip6_var.h> 5662587Sitojun#include <netinet/icmp6.h> 5753541Sshin 5853541Sshin/* 5953541Sshin * Destination options header processing. 6053541Sshin */ 6153541Sshinint 62171259Sdelphijdest6_input(struct mbuf **mp, int *offp, int proto) 6353541Sshin{ 6478064Sume struct mbuf *m = *mp; 6553541Sshin int off = *offp, dstoptlen, optlen; 6653541Sshin struct ip6_dest *dstopts; 6753541Sshin u_int8_t *opt; 6853541Sshin 6953541Sshin /* validation of the length of the header */ 7062587Sitojun#ifndef PULLDOWN_TEST 7153541Sshin IP6_EXTHDR_CHECK(m, off, sizeof(*dstopts), IPPROTO_DONE); 7253541Sshin dstopts = (struct ip6_dest *)(mtod(m, caddr_t) + off); 7362587Sitojun#else 7462587Sitojun IP6_EXTHDR_GET(dstopts, struct ip6_dest *, m, off, sizeof(*dstopts)); 7562587Sitojun if (dstopts == NULL) 7662587Sitojun return IPPROTO_DONE; 7762587Sitojun#endif 7853541Sshin dstoptlen = (dstopts->ip6d_len + 1) << 3; 7953541Sshin 8062587Sitojun#ifndef PULLDOWN_TEST 8153541Sshin IP6_EXTHDR_CHECK(m, off, dstoptlen, IPPROTO_DONE); 8253541Sshin dstopts = (struct ip6_dest *)(mtod(m, caddr_t) + off); 8362587Sitojun#else 8462587Sitojun IP6_EXTHDR_GET(dstopts, struct ip6_dest *, m, off, dstoptlen); 8562587Sitojun if (dstopts == NULL) 8662587Sitojun return IPPROTO_DONE; 8762587Sitojun#endif 8853541Sshin off += dstoptlen; 8953541Sshin dstoptlen -= sizeof(struct ip6_dest); 9053541Sshin opt = (u_int8_t *)dstopts + sizeof(struct ip6_dest); 9153541Sshin 9253541Sshin /* search header for all options. */ 9353541Sshin for (optlen = 0; dstoptlen > 0; dstoptlen -= optlen, opt += optlen) { 9473059Skris if (*opt != IP6OPT_PAD1 && 9573059Skris (dstoptlen < IP6OPT_MINLEN || *(opt + 1) + 2 > dstoptlen)) { 96250044Sae IP6STAT_INC(ip6s_toosmall); 9773059Skris goto bad; 9873059Skris } 9973059Skris 10073059Skris switch (*opt) { 10173059Skris case IP6OPT_PAD1: 10273059Skris optlen = 1; 10373059Skris break; 10473059Skris case IP6OPT_PADN: 10573059Skris optlen = *(opt + 1) + 2; 10673059Skris break; 10778064Sume default: /* unknown option */ 10878064Sume optlen = ip6_unknown_opt(opt, m, 10978064Sume opt - mtod(m, u_int8_t *)); 11078064Sume if (optlen == -1) 11178064Sume return (IPPROTO_DONE); 11278064Sume optlen += 2; 11378064Sume break; 11453541Sshin } 11553541Sshin } 11653541Sshin 11753541Sshin *offp = off; 11878064Sume return (dstopts->ip6d_nxt); 11953541Sshin 12053541Sshin bad: 12153541Sshin m_freem(m); 12278064Sume return (IPPROTO_DONE); 12353541Sshin} 124