dest6.c revision 62587
162587Sitojun/* $FreeBSD: head/sys/netinet6/dest6.c 62587 2000-07-04 16:35:15Z itojun $ */ 262587Sitojun/* $KAME: dest6.c,v 1.12 2000/05/05 11:00:57 sumikawa Exp $ */ 362587Sitojun 453541Sshin/* 553541Sshin * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 653541Sshin * All rights reserved. 753541Sshin * 853541Sshin * Redistribution and use in source and binary forms, with or without 953541Sshin * modification, are permitted provided that the following conditions 1053541Sshin * are met: 1153541Sshin * 1. Redistributions of source code must retain the above copyright 1253541Sshin * notice, this list of conditions and the following disclaimer. 1353541Sshin * 2. Redistributions in binary form must reproduce the above copyright 1453541Sshin * notice, this list of conditions and the following disclaimer in the 1553541Sshin * documentation and/or other materials provided with the distribution. 1653541Sshin * 3. Neither the name of the project nor the names of its contributors 1753541Sshin * may be used to endorse or promote products derived from this software 1853541Sshin * without specific prior written permission. 1953541Sshin * 2053541Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 2153541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2253541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2353541Sshin * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2453541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2553541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2653541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2753541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2853541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2953541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3053541Sshin * SUCH DAMAGE. 3153541Sshin */ 3253541Sshin 3362587Sitojun#include "opt_inet.h" 3462587Sitojun#include "opt_inet6.h" 3562587Sitojun 3653541Sshin#include <sys/param.h> 3753541Sshin#include <sys/systm.h> 3853541Sshin#include <sys/mbuf.h> 3953541Sshin#include <sys/domain.h> 4053541Sshin#include <sys/protosw.h> 4153541Sshin#include <sys/socket.h> 4253541Sshin#include <sys/errno.h> 4353541Sshin#include <sys/time.h> 4453541Sshin 4553541Sshin#include <net/if.h> 4653541Sshin#include <net/route.h> 4753541Sshin 4853541Sshin#include <netinet/in.h> 4953541Sshin#include <netinet/in_var.h> 5062587Sitojun#include <netinet/ip6.h> 5153541Sshin#include <netinet6/ip6_var.h> 5262587Sitojun#include <netinet/icmp6.h> 5353541Sshin 5453541Sshin/* 5553541Sshin * Destination options header processing. 5653541Sshin */ 5753541Sshinint 5853541Sshindest6_input(mp, offp, proto) 5953541Sshin struct mbuf **mp; 6053541Sshin int *offp, proto; 6153541Sshin{ 6253541Sshin register struct mbuf *m = *mp; 6353541Sshin int off = *offp, dstoptlen, optlen; 6453541Sshin struct ip6_dest *dstopts; 6553541Sshin u_int8_t *opt; 6653541Sshin 6753541Sshin /* validation of the length of the header */ 6862587Sitojun#ifndef PULLDOWN_TEST 6953541Sshin IP6_EXTHDR_CHECK(m, off, sizeof(*dstopts), IPPROTO_DONE); 7053541Sshin dstopts = (struct ip6_dest *)(mtod(m, caddr_t) + off); 7162587Sitojun#else 7262587Sitojun IP6_EXTHDR_GET(dstopts, struct ip6_dest *, m, off, sizeof(*dstopts)); 7362587Sitojun if (dstopts == NULL) 7462587Sitojun return IPPROTO_DONE; 7562587Sitojun#endif 7653541Sshin dstoptlen = (dstopts->ip6d_len + 1) << 3; 7753541Sshin 7862587Sitojun#ifndef PULLDOWN_TEST 7953541Sshin IP6_EXTHDR_CHECK(m, off, dstoptlen, IPPROTO_DONE); 8053541Sshin dstopts = (struct ip6_dest *)(mtod(m, caddr_t) + off); 8162587Sitojun#else 8262587Sitojun IP6_EXTHDR_GET(dstopts, struct ip6_dest *, m, off, dstoptlen); 8362587Sitojun if (dstopts == NULL) 8462587Sitojun return IPPROTO_DONE; 8562587Sitojun#endif 8653541Sshin off += dstoptlen; 8753541Sshin dstoptlen -= sizeof(struct ip6_dest); 8853541Sshin opt = (u_int8_t *)dstopts + sizeof(struct ip6_dest); 8953541Sshin 9053541Sshin /* search header for all options. */ 9153541Sshin for (optlen = 0; dstoptlen > 0; dstoptlen -= optlen, opt += optlen) { 9253541Sshin switch(*opt) { 9353541Sshin case IP6OPT_PAD1: 9453541Sshin optlen = 1; 9553541Sshin break; 9653541Sshin case IP6OPT_PADN: 9753541Sshin if (dstoptlen < IP6OPT_MINLEN) { 9853541Sshin ip6stat.ip6s_toosmall++; 9953541Sshin goto bad; 10053541Sshin } 10153541Sshin optlen = *(opt + 1) + 2; 10253541Sshin break; 10353541Sshin default: /* unknown option */ 10453541Sshin if (dstoptlen < IP6OPT_MINLEN) { 10553541Sshin ip6stat.ip6s_toosmall++; 10653541Sshin goto bad; 10753541Sshin } 10853541Sshin if ((optlen = ip6_unknown_opt(opt, m, 10953541Sshin opt-mtod(m, u_int8_t *))) == -1) 11053541Sshin return(IPPROTO_DONE); 11153541Sshin optlen += 2; 11253541Sshin break; 11353541Sshin } 11453541Sshin } 11553541Sshin 11653541Sshin *offp = off; 11753541Sshin return(dstopts->ip6d_nxt); 11853541Sshin 11953541Sshin bad: 12053541Sshin m_freem(m); 12153541Sshin return(IPPROTO_DONE); 12253541Sshin} 123