summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authoritojun <itojun@FreeBSD.org>2000-07-04 16:35:15 +0000
committeritojun <itojun@FreeBSD.org>2000-07-04 16:35:15 +0000
commit5f4e854de19331a53788d6100bbcd42845056bc1 (patch)
tree3ff8c876a5868b103fb8713055d83e29a3fa38d5 /sys/netinet
parentbdc16885232d771a99d7dfc247cd27a44cd061f9 (diff)
downloadFreeBSD-src-5f4e854de19331a53788d6100bbcd42845056bc1.zip
FreeBSD-src-5f4e854de19331a53788d6100bbcd42845056bc1.tar.gz
sync with kame tree as of july00. tons of bug fixes/improvements.
API changes: - additional IPv6 ioctls - IPsec PF_KEY API was changed, it is mandatory to upgrade setkey(8). (also syntax change)
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/icmp6.h634
-rw-r--r--sys/netinet/in.c1
-rw-r--r--sys/netinet/in.h31
-rw-r--r--sys/netinet/in_gif.c242
-rw-r--r--sys/netinet/in_gif.h19
-rw-r--r--sys/netinet/in_pcb.c4
-rw-r--r--sys/netinet/in_proto.c41
-rw-r--r--sys/netinet/ip6.h280
-rw-r--r--sys/netinet/ip_ecn.c5
-rw-r--r--sys/netinet/ip_ecn.h11
-rw-r--r--sys/netinet/ip_encap.c534
-rw-r--r--sys/netinet/ip_encap.h64
-rw-r--r--sys/netinet/ip_input.c5
-rw-r--r--sys/netinet/ip_output.c45
-rw-r--r--sys/netinet/ip_var.h3
-rw-r--r--sys/netinet/raw_ip.c5
-rw-r--r--sys/netinet/tcp_debug.c2
-rw-r--r--sys/netinet/tcp_input.c18
-rw-r--r--sys/netinet/tcp_output.c41
-rw-r--r--sys/netinet/tcp_reass.c18
-rw-r--r--sys/netinet/tcp_subr.c12
-rw-r--r--sys/netinet/tcp_timewait.c12
-rw-r--r--sys/netinet/udp_usrreq.c12
23 files changed, 1791 insertions, 248 deletions
diff --git a/sys/netinet/icmp6.h b/sys/netinet/icmp6.h
index 7a3dbbd..3625ee4 100644
--- a/sys/netinet/icmp6.h
+++ b/sys/netinet/icmp6.h
@@ -1,3 +1,6 @@
+/* $FreeBSD$ */
+/* $KAME: icmp6.h,v 1.18 2000/07/03 02:51:08 itojun Exp $ */
+
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
@@ -25,15 +28,634 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. All rights reserved.
*
- * $FreeBSD$
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93
*/
#ifndef _NETINET_ICMP6_H_
-#define _NETINET_ICMP6_H_
+#define _NETINET_ICMP6_H_
+
+#define ICMPV6_PLD_MAXLEN 1232 /* IPV6_MMTU - sizeof(struct ip6_hdr)
+ - sizeof(struct icmp6_hdr) */
+
+struct icmp6_hdr {
+ u_int8_t icmp6_type; /* type field */
+ u_int8_t icmp6_code; /* code field */
+ u_int16_t icmp6_cksum; /* checksum field */
+ union {
+ u_int32_t icmp6_un_data32[1]; /* type-specific field */
+ u_int16_t icmp6_un_data16[2]; /* type-specific field */
+ u_int8_t icmp6_un_data8[4]; /* type-specific field */
+ } icmp6_dataun;
+};
+
+#define icmp6_data32 icmp6_dataun.icmp6_un_data32
+#define icmp6_data16 icmp6_dataun.icmp6_un_data16
+#define icmp6_data8 icmp6_dataun.icmp6_un_data8
+#define icmp6_pptr icmp6_data32[0] /* parameter prob */
+#define icmp6_mtu icmp6_data32[0] /* packet too big */
+#define icmp6_id icmp6_data16[0] /* echo request/reply */
+#define icmp6_seq icmp6_data16[1] /* echo request/reply */
+#define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */
+
+#define ICMP6_DST_UNREACH 1 /* dest unreachable, codes: */
+#define ICMP6_PACKET_TOO_BIG 2 /* packet too big */
+#define ICMP6_TIME_EXCEEDED 3 /* time exceeded, code: */
+#define ICMP6_PARAM_PROB 4 /* ip6 header bad */
+
+#define ICMP6_ECHO_REQUEST 128 /* echo service */
+#define ICMP6_ECHO_REPLY 129 /* echo reply */
+#define ICMP6_MEMBERSHIP_QUERY 130 /* group membership query */
+#define MLD6_LISTENER_QUERY 130 /* multicast listener query */
+#define ICMP6_MEMBERSHIP_REPORT 131 /* group membership report */
+#define MLD6_LISTENER_REPORT 131 /* multicast listener report */
+#define ICMP6_MEMBERSHIP_REDUCTION 132 /* group membership termination */
+#define MLD6_LISTENER_DONE 132 /* multicast listener done */
+
+#define ND_ROUTER_SOLICIT 133 /* router solicitation */
+#define ND_ROUTER_ADVERT 134 /* router advertisment */
+#define ND_NEIGHBOR_SOLICIT 135 /* neighbor solicitation */
+#define ND_NEIGHBOR_ADVERT 136 /* neighbor advertisment */
+#define ND_REDIRECT 137 /* redirect */
+
+#define ICMP6_ROUTER_RENUMBERING 138 /* router renumbering */
+
+#define ICMP6_WRUREQUEST 139 /* who are you request */
+#define ICMP6_WRUREPLY 140 /* who are you reply */
+#define ICMP6_FQDN_QUERY 139 /* FQDN query */
+#define ICMP6_FQDN_REPLY 140 /* FQDN reply */
+#define ICMP6_NI_QUERY 139 /* node information request */
+#define ICMP6_NI_REPLY 140 /* node information reply */
+
+/* The definitions below are experimental. TBA */
+#define MLD6_MTRACE_RESP 141 /* mtrace response(to sender) */
+#define MLD6_MTRACE 142 /* mtrace messages */
+
+#define ICMP6_MAXTYPE 142
+
+#define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */
+#define ICMP6_DST_UNREACH_ADMIN 1 /* administratively prohibited */
+#define ICMP6_DST_UNREACH_NOTNEIGHBOR 2 /* not a neighbor(obsolete) */
+#define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* beyond scope of source address */
+#define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */
+#define ICMP6_DST_UNREACH_NOPORT 4 /* port unreachable */
+
+#define ICMP6_TIME_EXCEED_TRANSIT 0 /* ttl==0 in transit */
+#define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* ttl==0 in reass */
+
+#define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */
+#define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized next header */
+#define ICMP6_PARAMPROB_OPTION 2 /* unrecognized option */
+
+#define ICMP6_INFOMSG_MASK 0x80 /* all informational messages */
+
+#define ICMP6_NI_SUBJ_IPV6 0 /* Query Subject is an IPv6 address */
+#define ICMP6_NI_SUBJ_FQDN 1 /* Query Subject is a Domain name */
+#define ICMP6_NI_SUBJ_IPV4 2 /* Query Subject is an IPv4 address */
+
+#define ICMP6_NI_SUCESS 0 /* node information successful reply */
+#define ICMP6_NI_REFUSED 1 /* node information request is refused */
+#define ICMP6_NI_UNKNOWN 2 /* unknown Qtype */
+
+#define ICMP6_ROUTER_RENUMBERING_COMMAND 0 /* rr command */
+#define ICMP6_ROUTER_RENUMBERING_RESULT 1 /* rr result */
+#define ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET 255 /* rr seq num reset */
+
+/* Used in kernel only */
+#define ND_REDIRECT_ONLINK 0 /* redirect to an on-link node */
+#define ND_REDIRECT_ROUTER 1 /* redirect to a better router */
+
+/*
+ * Multicast Listener Discovery
+ */
+struct mld6_hdr {
+ struct icmp6_hdr mld6_hdr;
+ struct in6_addr mld6_addr; /* multicast address */
+};
+
+#define mld6_type mld6_hdr.icmp6_type
+#define mld6_code mld6_hdr.icmp6_code
+#define mld6_cksum mld6_hdr.icmp6_cksum
+#define mld6_maxdelay mld6_hdr.icmp6_data16[0]
+#define mld6_reserved mld6_hdr.icmp6_data16[1]
+
+/*
+ * Neighbor Discovery
+ */
+
+struct nd_router_solicit { /* router solicitation */
+ struct icmp6_hdr nd_rs_hdr;
+ /* could be followed by options */
+};
+
+#define nd_rs_type nd_rs_hdr.icmp6_type
+#define nd_rs_code nd_rs_hdr.icmp6_code
+#define nd_rs_cksum nd_rs_hdr.icmp6_cksum
+#define nd_rs_reserved nd_rs_hdr.icmp6_data32[0]
+
+struct nd_router_advert { /* router advertisement */
+ struct icmp6_hdr nd_ra_hdr;
+ u_int32_t nd_ra_reachable; /* reachable time */
+ u_int32_t nd_ra_retransmit; /* retransmit timer */
+ /* could be followed by options */
+};
+
+#define nd_ra_type nd_ra_hdr.icmp6_type
+#define nd_ra_code nd_ra_hdr.icmp6_code
+#define nd_ra_cksum nd_ra_hdr.icmp6_cksum
+#define nd_ra_curhoplimit nd_ra_hdr.icmp6_data8[0]
+#define nd_ra_flags_reserved nd_ra_hdr.icmp6_data8[1]
+#define ND_RA_FLAG_MANAGED 0x80
+#define ND_RA_FLAG_OTHER 0x40
+#define nd_ra_router_lifetime nd_ra_hdr.icmp6_data16[1]
+
+struct nd_neighbor_solicit { /* neighbor solicitation */
+ struct icmp6_hdr nd_ns_hdr;
+ struct in6_addr nd_ns_target; /*target address */
+ /* could be followed by options */
+};
+
+#define nd_ns_type nd_ns_hdr.icmp6_type
+#define nd_ns_code nd_ns_hdr.icmp6_code
+#define nd_ns_cksum nd_ns_hdr.icmp6_cksum
+#define nd_ns_reserved nd_ns_hdr.icmp6_data32[0]
+
+struct nd_neighbor_advert { /* neighbor advertisement */
+ struct icmp6_hdr nd_na_hdr;
+ struct in6_addr nd_na_target; /* target address */
+ /* could be followed by options */
+};
+
+#define nd_na_type nd_na_hdr.icmp6_type
+#define nd_na_code nd_na_hdr.icmp6_code
+#define nd_na_cksum nd_na_hdr.icmp6_cksum
+#define nd_na_flags_reserved nd_na_hdr.icmp6_data32[0]
+#if BYTE_ORDER == BIG_ENDIAN
+#define ND_NA_FLAG_ROUTER 0x80000000
+#define ND_NA_FLAG_SOLICITED 0x40000000
+#define ND_NA_FLAG_OVERRIDE 0x20000000
+#else
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define ND_NA_FLAG_ROUTER 0x80
+#define ND_NA_FLAG_SOLICITED 0x40
+#define ND_NA_FLAG_OVERRIDE 0x20
+#endif
+#endif
+
+struct nd_redirect { /* redirect */
+ struct icmp6_hdr nd_rd_hdr;
+ struct in6_addr nd_rd_target; /* target address */
+ struct in6_addr nd_rd_dst; /* destination address */
+ /* could be followed by options */
+};
+
+#define nd_rd_type nd_rd_hdr.icmp6_type
+#define nd_rd_code nd_rd_hdr.icmp6_code
+#define nd_rd_cksum nd_rd_hdr.icmp6_cksum
+#define nd_rd_reserved nd_rd_hdr.icmp6_data32[0]
+
+struct nd_opt_hdr { /* Neighbor discovery option header */
+ u_int8_t nd_opt_type;
+ u_int8_t nd_opt_len;
+ /* followed by option specific data*/
+};
+
+#define ND_OPT_SOURCE_LINKADDR 1
+#define ND_OPT_TARGET_LINKADDR 2
+#define ND_OPT_PREFIX_INFORMATION 3
+#define ND_OPT_REDIRECTED_HEADER 4
+#define ND_OPT_MTU 5
+
+struct nd_opt_prefix_info { /* prefix information */
+ u_int8_t nd_opt_pi_type;
+ u_int8_t nd_opt_pi_len;
+ u_int8_t nd_opt_pi_prefix_len;
+ u_int8_t nd_opt_pi_flags_reserved;
+ u_int32_t nd_opt_pi_valid_time;
+ u_int32_t nd_opt_pi_preferred_time;
+ u_int32_t nd_opt_pi_reserved2;
+ struct in6_addr nd_opt_pi_prefix;
+};
+
+#define ND_OPT_PI_FLAG_ONLINK 0x80
+#define ND_OPT_PI_FLAG_AUTO 0x40
+
+struct nd_opt_rd_hdr { /* redirected header */
+ u_int8_t nd_opt_rh_type;
+ u_int8_t nd_opt_rh_len;
+ u_int16_t nd_opt_rh_reserved1;
+ u_int32_t nd_opt_rh_reserved2;
+ /* followed by IP header and data */
+};
+
+struct nd_opt_mtu { /* MTU option */
+ u_int8_t nd_opt_mtu_type;
+ u_int8_t nd_opt_mtu_len;
+ u_int16_t nd_opt_mtu_reserved;
+ u_int32_t nd_opt_mtu_mtu;
+};
+
+/*
+ * icmp6 namelookup
+ */
+
+struct icmp6_namelookup {
+ struct icmp6_hdr icmp6_nl_hdr;
+ u_int8_t icmp6_nl_nonce[8];
+ int32_t icmp6_nl_ttl;
+#if 0
+ u_int8_t icmp6_nl_len;
+ u_int8_t icmp6_nl_name[3];
+#endif
+ /* could be followed by options */
+};
+
+/*
+ * icmp6 node information
+ */
+struct icmp6_nodeinfo {
+ struct icmp6_hdr icmp6_ni_hdr;
+ u_int8_t icmp6_ni_nonce[8];
+ /* could be followed by reply data */
+};
+
+#define ni_type icmp6_ni_hdr.icmp6_type
+#define ni_code icmp6_ni_hdr.icmp6_code
+#define ni_cksum icmp6_ni_hdr.icmp6_cksum
+#define ni_qtype icmp6_ni_hdr.icmp6_data16[0]
+#define ni_flags icmp6_ni_hdr.icmp6_data16[1]
+
+#define NI_QTYPE_NOOP 0 /* NOOP */
+#define NI_QTYPE_SUPTYPES 1 /* Supported Qtypes */
+#define NI_QTYPE_FQDN 2 /* FQDN */
+#define NI_QTYPE_NODEADDR 3 /* Node Addresses. XXX: spec says 2, but it may be a typo... */
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define NI_SUPTYPE_FLAG_COMPRESS 0x1
+#define NI_FQDN_FLAG_VALIDTTL 0x1
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#define NI_SUPTYPE_FLAG_COMPRESS 0x0100
+#define NI_FQDN_FLAG_VALIDTTL 0x0100
+#endif
+
+#ifdef NAME_LOOKUPS_04
+#if BYTE_ORDER == BIG_ENDIAN
+#define NI_NODEADDR_FLAG_LINKLOCAL 0x1
+#define NI_NODEADDR_FLAG_SITELOCAL 0x2
+#define NI_NODEADDR_FLAG_GLOBAL 0x4
+#define NI_NODEADDR_FLAG_ALL 0x8
+#define NI_NODEADDR_FLAG_TRUNCATE 0x10
+#define NI_NODEADDR_FLAG_ANYCAST 0x20 /* just experimental. not in spec */
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#define NI_NODEADDR_FLAG_LINKLOCAL 0x0100
+#define NI_NODEADDR_FLAG_SITELOCAL 0x0200
+#define NI_NODEADDR_FLAG_GLOBAL 0x0400
+#define NI_NODEADDR_FLAG_ALL 0x0800
+#define NI_NODEADDR_FLAG_TRUNCATE 0x1000
+#define NI_NODEADDR_FLAG_ANYCAST 0x2000 /* just experimental. not in spec */
+#endif
+#else /* draft-ietf-ipngwg-icmp-name-lookups-05 (and later?) */
+#if BYTE_ORDER == BIG_ENDIAN
+#define NI_NODEADDR_FLAG_TRUNCATE 0x1
+#define NI_NODEADDR_FLAG_ALL 0x2
+#define NI_NODEADDR_FLAG_COMPAT 0x4
+#define NI_NODEADDR_FLAG_LINKLOCAL 0x8
+#define NI_NODEADDR_FLAG_SITELOCAL 0x10
+#define NI_NODEADDR_FLAG_GLOBAL 0x20
+#define NI_NODEADDR_FLAG_ANYCAST 0x40 /* just experimental. not in spec */
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#define NI_NODEADDR_FLAG_TRUNCATE 0x0100
+#define NI_NODEADDR_FLAG_ALL 0x0200
+#define NI_NODEADDR_FLAG_COMPAT 0x0400
+#define NI_NODEADDR_FLAG_LINKLOCAL 0x0800
+#define NI_NODEADDR_FLAG_SITELOCAL 0x1000
+#define NI_NODEADDR_FLAG_GLOBAL 0x2000
+#define NI_NODEADDR_FLAG_ANYCAST 0x4000 /* just experimental. not in spec */
+#endif
+#endif
+
+struct ni_reply_fqdn {
+ u_int32_t ni_fqdn_ttl; /* TTL */
+ u_int8_t ni_fqdn_namelen; /* length in octets of the FQDN */
+ u_int8_t ni_fqdn_name[3]; /* XXX: alignment */
+};
+
+/*
+ * Router Renumbering. as router-renum-08.txt
+ */
+struct icmp6_router_renum { /* router renumbering header */
+ struct icmp6_hdr rr_hdr;
+ u_int8_t rr_segnum;
+ u_int8_t rr_flags;
+ u_int16_t rr_maxdelay;
+ u_int32_t rr_reserved;
+};
+#define ICMP6_RR_FLAGS_SEGNUM 0x80
+#define ICMP6_RR_FLAGS_TEST 0x40
+#define ICMP6_RR_FLAGS_REQRESULT 0x20
+#define ICMP6_RR_FLAGS_FORCEAPPLY 0x10
+#define ICMP6_RR_FLAGS_SPECSITE 0x08
+#define ICMP6_RR_FLAGS_PREVDONE 0x04
+
+#define rr_type rr_hdr.icmp6_type
+#define rr_code rr_hdr.icmp6_code
+#define rr_cksum rr_hdr.icmp6_cksum
+#define rr_seqnum rr_hdr.icmp6_data32[0]
+
+struct rr_pco_match { /* match prefix part */
+ u_int8_t rpm_code;
+ u_int8_t rpm_len;
+ u_int8_t rpm_ordinal;
+ u_int8_t rpm_matchlen;
+ u_int8_t rpm_minlen;
+ u_int8_t rpm_maxlen;
+ u_int16_t rpm_reserved;
+ struct in6_addr rpm_prefix;
+};
+
+#define RPM_PCO_ADD 1
+#define RPM_PCO_CHANGE 2
+#define RPM_PCO_SETGLOBAL 3
+#define RPM_PCO_MAX 4
+
+struct rr_pco_use { /* use prefix part */
+ u_int8_t rpu_uselen;
+ u_int8_t rpu_keeplen;
+ u_int8_t rpu_ramask;
+ u_int8_t rpu_raflags;
+ u_int32_t rpu_vltime;
+ u_int32_t rpu_pltime;
+ u_int32_t rpu_flags;
+ struct in6_addr rpu_prefix;
+};
+#define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK 0x80
+#define ICMP6_RR_PCOUSE_RAFLAGS_AUTO 0x40
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80000000
+#define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40000000
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80
+#define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40
+#endif
+
+struct rr_result { /* router renumbering result message */
+ u_int16_t rrr_flags;
+ u_int8_t rrr_ordinal;
+ u_int8_t rrr_matchedlen;
+ u_int32_t rrr_ifid;
+ struct in6_addr rrr_prefix;
+};
+#if BYTE_ORDER == BIG_ENDIAN
+#define ICMP6_RR_RESULT_FLAGS_OOB 0x0002
+#define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x0001
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#define ICMP6_RR_RESULT_FLAGS_OOB 0x02
+#define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x01
+#endif
+
+/*
+ * icmp6 filter structures.
+ */
+
+struct icmp6_filter {
+ u_int32_t icmp6_filt[8];
+};
+
+#ifdef _KERNEL
+#define ICMP6_FILTER_SETPASSALL(filterp) \
+do { \
+ int i; u_char *p; \
+ p = (u_char *)filterp; \
+ for (i = 0; i < sizeof(struct icmp6_filter); i++) \
+ p[i] = 0xff; \
+} while (0)
+#define ICMP6_FILTER_SETBLOCKALL(filterp) \
+ bzero(filterp, sizeof(struct icmp6_filter))
+#else /* _KERNEL */
+#define ICMP6_FILTER_SETPASSALL(filterp) \
+ memset(filterp, 0xff, sizeof(struct icmp6_filter))
+#define ICMP6_FILTER_SETBLOCKALL(filterp) \
+ memset(filterp, 0x00, sizeof(struct icmp6_filter))
+#endif /* _KERNEL */
+
+#define ICMP6_FILTER_SETPASS(type, filterp) \
+ (((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31)))
+#define ICMP6_FILTER_SETBLOCK(type, filterp) \
+ (((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31)))
+#define ICMP6_FILTER_WILLPASS(type, filterp) \
+ ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0)
+#define ICMP6_FILTER_WILLBLOCK(type, filterp) \
+ ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0)
+
+/*
+ * Variables related to this implementation
+ * of the internet control message protocol version 6.
+ */
+struct icmp6errstat {
+ u_quad_t icp6errs_dst_unreach_noroute;
+ u_quad_t icp6errs_dst_unreach_admin;
+ u_quad_t icp6errs_dst_unreach_beyondscope;
+ u_quad_t icp6errs_dst_unreach_addr;
+ u_quad_t icp6errs_dst_unreach_noport;
+ u_quad_t icp6errs_packet_too_big;
+ u_quad_t icp6errs_time_exceed_transit;
+ u_quad_t icp6errs_time_exceed_reassembly;
+ u_quad_t icp6errs_paramprob_header;
+ u_quad_t icp6errs_paramprob_nextheader;
+ u_quad_t icp6errs_paramprob_option;
+ u_quad_t icp6errs_redirect; /* we regard redirect as an error here */
+ u_quad_t icp6errs_unknown;
+};
+
+struct icmp6stat {
+/* statistics related to icmp6 packets generated */
+ u_quad_t icp6s_error; /* # of calls to icmp6_error */
+ u_quad_t icp6s_canterror; /* no error 'cuz old was icmp */
+ u_quad_t icp6s_toofreq; /* no error 'cuz rate limitation */
+ u_quad_t icp6s_outhist[256];
+/* statistics related to input message processed */
+ u_quad_t icp6s_badcode; /* icmp6_code out of range */
+ u_quad_t icp6s_tooshort; /* packet < sizeof(struct icmp6_hdr) */
+ u_quad_t icp6s_checksum; /* bad checksum */
+ u_quad_t icp6s_badlen; /* calculated bound mismatch */
+ u_quad_t icp6s_reflect; /* number of responses */
+ u_quad_t icp6s_inhist[256];
+ u_quad_t icp6s_nd_toomanyopt; /* too many ND options */
+ struct icmp6errstat icp6s_outerrhist;
+#define icp6s_odst_unreach_noroute \
+ icp6s_outerrhist.icp6errs_dst_unreach_noroute
+#define icp6s_odst_unreach_admin icp6s_outerrhist.icp6errs_dst_unreach_admin
+#define icp6s_odst_unreach_beyondscope \
+ icp6s_outerrhist.icp6errs_dst_unreach_beyondscope
+#define icp6s_odst_unreach_addr icp6s_outerrhist.icp6errs_dst_unreach_addr
+#define icp6s_odst_unreach_noport icp6s_outerrhist.icp6errs_dst_unreach_noport
+#define icp6s_opacket_too_big icp6s_outerrhist.icp6errs_packet_too_big
+#define icp6s_otime_exceed_transit \
+ icp6s_outerrhist.icp6errs_time_exceed_transit
+#define icp6s_otime_exceed_reassembly \
+ icp6s_outerrhist.icp6errs_time_exceed_reassembly
+#define icp6s_oparamprob_header icp6s_outerrhist.icp6errs_paramprob_header
+#define icp6s_oparamprob_nextheader \
+ icp6s_outerrhist.icp6errs_paramprob_nextheader
+#define icp6s_oparamprob_option icp6s_outerrhist.icp6errs_paramprob_option
+#define icp6s_oredirect icp6s_outerrhist.icp6errs_redirect
+#define icp6s_ounknown icp6s_outerrhist.icp6errs_unknown
+};
+
+/*
+ * Names for ICMP sysctl objects
+ */
+#define ICMPV6CTL_STATS 1
+#define ICMPV6CTL_REDIRACCEPT 2 /* accept/process redirects */
+#define ICMPV6CTL_REDIRTIMEOUT 3 /* redirect cache time */
+#define ICMPV6CTL_ERRRATELIMIT 5 /* ICMPv6 error rate limitation */
+#define ICMPV6CTL_ND6_PRUNE 6
+#define ICMPV6CTL_ND6_DELAY 8
+#define ICMPV6CTL_ND6_UMAXTRIES 9
+#define ICMPV6CTL_ND6_MMAXTRIES 10
+#define ICMPV6CTL_ND6_USELOOPBACK 11
+/*#define ICMPV6CTL_ND6_PROXYALL 12 obsoleted, do not reuse here */
+#define ICMPV6CTL_NODEINFO 13
+#define ICMPV6CTL_ERRPPSLIMIT 14 /* ICMPv6 error pps limitation */
+#define ICMPV6CTL_ND6_MAXNUDHINT 15
+#define ICMPV6CTL_MAXID 16
+
+#define ICMPV6CTL_NAMES { \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { "rediraccept", CTLTYPE_INT }, \
+ { "redirtimeout", CTLTYPE_INT }, \
+ { 0, 0 }, \
+ { "errratelimit", CTLTYPE_INT }, \
+ { "nd6_prune", CTLTYPE_INT }, \
+ { 0, 0 }, \
+ { "nd6_delay", CTLTYPE_INT }, \
+ { "nd6_umaxtries", CTLTYPE_INT }, \
+ { "nd6_mmaxtries", CTLTYPE_INT }, \
+ { "nd6_useloopback", CTLTYPE_INT }, \
+ { 0, 0 }, \
+ { "nodeinfo", CTLTYPE_INT }, \
+ { "errppslimit", CTLTYPE_INT }, \
+ { "nd6_maxnudhint", CTLTYPE_INT }, \
+}
+
+#define RTF_PROBEMTU RTF_PROTO1
+
+#ifdef _KERNEL
+# ifdef __STDC__
+struct rtentry;
+struct rttimer;
+struct in6_multi;
+# endif
+void icmp6_init __P((void));
+void icmp6_paramerror __P((struct mbuf *, int));
+void icmp6_error __P((struct mbuf *, int, int, int));
+int icmp6_input __P((struct mbuf **, int *, int));
+void icmp6_fasttimo __P((void));
+void icmp6_reflect __P((struct mbuf *, size_t));
+void icmp6_prepare __P((struct mbuf *));
+void icmp6_redirect_input __P((struct mbuf *, int));
+void icmp6_redirect_output __P((struct mbuf *, struct rtentry *));
+
+/* XXX: is this the right place for these macros? */
+#define icmp6_ifstat_inc(ifp, tag) \
+do { \
+ if ((ifp) && (ifp)->if_index <= if_index \
+ && (ifp)->if_index < icmp6_ifstatmax \
+ && icmp6_ifstat && icmp6_ifstat[(ifp)->if_index]) { \
+ icmp6_ifstat[(ifp)->if_index]->tag++; \
+ } \
+} while (0)
+
+#define icmp6_ifoutstat_inc(ifp, type, code) \
+do { \
+ icmp6_ifstat_inc(ifp, ifs6_out_msg); \
+ if (type < ICMP6_INFOMSG_MASK) \
+ icmp6_ifstat_inc(ifp, ifs6_out_error); \
+ switch(type) { \
+ case ICMP6_DST_UNREACH: \
+ icmp6_ifstat_inc(ifp, ifs6_out_dstunreach); \
+ if (code == ICMP6_DST_UNREACH_ADMIN) \
+ icmp6_ifstat_inc(ifp, ifs6_out_adminprohib); \
+ break; \
+ case ICMP6_PACKET_TOO_BIG: \
+ icmp6_ifstat_inc(ifp, ifs6_out_pkttoobig); \
+ break; \
+ case ICMP6_TIME_EXCEEDED: \
+ icmp6_ifstat_inc(ifp, ifs6_out_timeexceed); \
+ break; \
+ case ICMP6_PARAM_PROB: \
+ icmp6_ifstat_inc(ifp, ifs6_out_paramprob); \
+ break; \
+ case ICMP6_ECHO_REQUEST: \
+ icmp6_ifstat_inc(ifp, ifs6_out_echo); \
+ break; \
+ case ICMP6_ECHO_REPLY: \
+ icmp6_ifstat_inc(ifp, ifs6_out_echoreply); \
+ break; \
+ case MLD6_LISTENER_QUERY: \
+ icmp6_ifstat_inc(ifp, ifs6_out_mldquery); \
+ break; \
+ case MLD6_LISTENER_REPORT: \
+ icmp6_ifstat_inc(ifp, ifs6_out_mldreport); \
+ break; \
+ case MLD6_LISTENER_DONE: \
+ icmp6_ifstat_inc(ifp, ifs6_out_mlddone); \
+ break; \
+ case ND_ROUTER_SOLICIT: \
+ icmp6_ifstat_inc(ifp, ifs6_out_routersolicit); \
+ break; \
+ case ND_ROUTER_ADVERT: \
+ icmp6_ifstat_inc(ifp, ifs6_out_routeradvert); \
+ break; \
+ case ND_NEIGHBOR_SOLICIT: \
+ icmp6_ifstat_inc(ifp, ifs6_out_neighborsolicit); \
+ break; \
+ case ND_NEIGHBOR_ADVERT: \
+ icmp6_ifstat_inc(ifp, ifs6_out_neighboradvert); \
+ break; \
+ case ND_REDIRECT: \
+ icmp6_ifstat_inc(ifp, ifs6_out_redirect); \
+ break; \
+ } \
+} while (0)
-#define __KAME_NETINET_ICMP6_H_INCLUDED_
-#include <netinet6/icmp6.h>
-#undef __KAME_NETINET_ICMP6_H_INCLUDED_
+extern int icmp6_rediraccept; /* accept/process redirects */
+extern int icmp6_redirtimeout; /* cache time for redirect routes */
+#endif /* _KERNEL */
-#endif /* !_NETINET_ICMP6_H_ */
+#endif /* not _NETINET_ICMP6_H_ */
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 1cb0170..f1bc7f7 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -207,6 +207,7 @@ in_control(so, cmd, data, ifp, p)
if (ifp && ifp->if_type == IFT_GIF) {
switch (cmd) {
case SIOCSIFPHYADDR:
+ case SIOCDIFPHYADDR:
if (p &&
(error = suser(p)) != 0)
return(error);
diff --git a/sys/netinet/in.h b/sys/netinet/in.h
index dbff92a..403c534 100644
--- a/sys/netinet/in.h
+++ b/sys/netinet/in.h
@@ -372,7 +372,7 @@ struct ip_mreq {
* Third level is protocol number.
* Fourth level is desired variable within that protocol.
*/
-#define IPPROTO_MAXID (IPPROTO_ESP + 1) /* don't list to IPPROTO_MAX */
+#define IPPROTO_MAXID (IPPROTO_AH + 1) /* don't list to IPPROTO_MAX */
#define CTL_IPPROTO_NAMES { \
{ "ip", CTLTYPE_NODE }, \
@@ -398,6 +398,35 @@ struct ip_mreq {
{ 0, 0 }, \
{ 0, 0 }, \
{ "idp", CTLTYPE_NODE }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { "ipsec", CTLTYPE_NODE }, \
}
/*
diff --git a/sys/netinet/in_gif.c b/sys/netinet/in_gif.c
index 0efa40e0..2335873 100644
--- a/sys/netinet/in_gif.c
+++ b/sys/netinet/in_gif.c
@@ -1,3 +1,6 @@
+/* $FreeBSD$ */
+/* $KAME: in_gif.c,v 1.43 2000/06/20 19:45:00 itojun Exp $ */
+
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
@@ -25,15 +28,10 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-/*
- * in_gif.c
*/
#include "opt_mrouting.h"
+#include "opt_inet.h"
#include "opt_inet6.h"
#include <sys/param.h>
@@ -44,7 +42,8 @@
#include <sys/errno.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
-#include <sys/protosw.h>
+
+#include <sys/malloc.h>
#include <net/if.h>
#include <net/route.h>
@@ -52,21 +51,21 @@
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
-#ifdef INET6
-#include <netinet/ip6.h>
-#endif
#include <netinet/ip_var.h>
#include <netinet/in_gif.h>
+#include <netinet/in_var.h>
+#include <netinet/ip_encap.h>
#include <netinet/ip_ecn.h>
+
#ifdef INET6
-#include <netinet6/ip6_ecn.h>
+#include <netinet/ip6.h>
#endif
#ifdef MROUTING
#include <netinet/ip_mroute.h>
#endif /* MROUTING */
-#include <net/if_gif.h>
+#include <net/if_gif.h>
#include "gif.h"
@@ -79,13 +78,12 @@ int ip_gif_ttl = GIF_TTL;
#else
int ip_gif_ttl = 0;
#endif
-
-SYSCTL_DECL(_net_inet_ip);
SYSCTL_INT(_net_inet_ip, IPCTL_GIF_TTL, gifttl, CTLFLAG_RW,
&ip_gif_ttl, 0, "");
-#define IN6_IS_ADDR_6TO4(x) (ntohs((x)->s6_addr16[0]) == 0x2002)
-#define GET_V4(x) ((struct in_addr *)(&(x)->s6_addr16[1]))
+#ifndef offsetof
+#define offsetof(s, e) ((int)&((s *)0)->e)
+#endif
int
in_gif_output(ifp, family, m, rt)
@@ -101,9 +99,6 @@ in_gif_output(ifp, family, m, rt)
struct ip iphdr; /* capsule IP header, host byte ordered */
int proto, error;
u_int8_t tos;
-#ifdef INET6
- struct ip6_hdr *ip6 = NULL;
-#endif
if (sin_src == NULL || sin_dst == NULL ||
sin_src->sin_family != AF_INET ||
@@ -113,6 +108,7 @@ in_gif_output(ifp, family, m, rt)
}
switch (family) {
+#ifdef INET
case AF_INET:
{
struct ip *ip;
@@ -127,9 +123,11 @@ in_gif_output(ifp, family, m, rt)
tos = ip->ip_tos;
break;
}
+#endif /*INET*/
#ifdef INET6
case AF_INET6:
{
+ struct ip6_hdr *ip6;
proto = IPPROTO_IPV6;
if (m->m_len < sizeof(*ip6)) {
m = m_pullup(m, sizeof(*ip6));
@@ -142,7 +140,7 @@ in_gif_output(ifp, family, m, rt)
}
#endif /*INET6*/
default:
-#ifdef DIAGNOSTIC
+#ifdef DEBUG
printf("in_gif_output: warning: unknown family %d passed\n",
family);
#endif
@@ -152,37 +150,15 @@ in_gif_output(ifp, family, m, rt)
bzero(&iphdr, sizeof(iphdr));
iphdr.ip_src = sin_src->sin_addr;
-#ifdef INET6
- /* XXX: temporal stf support hack */
- if (bcmp(ifp->if_name, "stf", 3) == 0) {
- if (ip6 == NULL) {
- m_freem(m);
- return ENETUNREACH;
- }
- if (IN6_IS_ADDR_6TO4(&ip6->ip6_dst))
- iphdr.ip_dst = *GET_V4(&ip6->ip6_dst);
- else if (rt && rt->rt_gateway->sa_family == AF_INET6) {
- struct in6_addr *dst6;
-
- dst6 = &((struct sockaddr_in6 *)
- (rt->rt_gateway))->sin6_addr;
- if (IN6_IS_ADDR_6TO4(dst6))
- iphdr.ip_dst = *GET_V4(dst6);
- else {
- m_freem(m);
- return ENETUNREACH;
- }
- } else {
- m_freem(m);
- return ENETUNREACH;
- }
- } else
-#endif
if (ifp->if_flags & IFF_LINK0) {
/* multi-destination mode */
if (sin_dst->sin_addr.s_addr != INADDR_ANY)
iphdr.ip_dst = sin_dst->sin_addr;
else if (rt) {
+ if (family != AF_INET) {
+ m_freem(m);
+ return EINVAL; /*XXX*/
+ }
iphdr.ip_dst = ((struct sockaddr_in *)
(rt->rt_gateway))->sin_addr;
} else {
@@ -213,8 +189,7 @@ in_gif_output(ifp, family, m, rt)
printf("ENOBUFS in in_gif_output %d\n", __LINE__);
return ENOBUFS;
}
-
- *(mtod(m, struct ip *)) = iphdr;
+ bcopy(&iphdr, mtod(m, struct ip *), sizeof(struct ip));
if (dst->sin_family != sin_dst->sin_family ||
dst->sin_addr.s_addr != sin_dst->sin_addr.s_addr) {
@@ -226,6 +201,9 @@ in_gif_output(ifp, family, m, rt)
RTFREE(sc->gif_ro.ro_rt);
sc->gif_ro.ro_rt = NULL;
}
+#if 0
+ sc->gif_if.if_mtu = GIF_MTU;
+#endif
}
if (sc->gif_ro.ro_rt == NULL) {
@@ -234,73 +212,48 @@ in_gif_output(ifp, family, m, rt)
m_freem(m);
return ENETUNREACH;
}
+
+ /* if it constitutes infinite encapsulation, punt. */
+ if (sc->gif_ro.ro_rt->rt_ifp == ifp) {
+ m_freem(m);
+ return ENETUNREACH; /*XXX*/
+ }
+#if 0
+ ifp->if_mtu = sc->gif_ro.ro_rt->rt_ifp->if_mtu
+ - sizeof(struct ip);
+#endif
}
- error = ip_output(m, 0, &sc->gif_ro, 0, 0);
+ error = ip_output(m, NULL, &sc->gif_ro, 0, NULL);
return(error);
}
void
-in_gif_input(struct mbuf *m, int off, int proto)
+#if __STDC__
+in_gif_input(struct mbuf *m, ...)
+#else
+in_gif_input(m, va_alist)
+ struct mbuf *m;
+ va_dcl
+#endif
{
- struct gif_softc *sc;
+ int off, proto;
struct ifnet *gifp = NULL;
struct ip *ip;
- int i, af;
+ va_list ap;
+ int af;
u_int8_t otos;
- ip = mtod(m, struct ip *);
-
- /* this code will be soon improved. */
-#define satosin(sa) ((struct sockaddr_in *)(sa))
- for (i = 0, sc = gif; i < ngif; i++, sc++) {
- if (sc->gif_psrc == NULL
- || sc->gif_pdst == NULL
- || sc->gif_psrc->sa_family != AF_INET
- || sc->gif_pdst->sa_family != AF_INET) {
- continue;
- }
-
- if ((sc->gif_if.if_flags & IFF_UP) == 0)
- continue;
-
-#ifdef INET6
- /* XXX: temporal stf support hack */
- if (proto == IPPROTO_IPV6 &&
- bcmp(sc->gif_if.if_name, "stf", 3) == 0 &&
- (satosin(sc->gif_psrc)->sin_addr.s_addr ==
- ip->ip_dst.s_addr ||
- IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) &&
- satosin(sc->gif_pdst)->sin_addr.s_addr ==
- INADDR_BROADCAST) {
- gifp = &sc->gif_if;
- break;
- }
-#endif
+ va_start(ap, m);
+ off = va_arg(ap, int);
+ proto = va_arg(ap, int);
+ va_end(ap);
- if ((sc->gif_if.if_flags & IFF_LINK0)
- && satosin(sc->gif_psrc)->sin_addr.s_addr == ip->ip_dst.s_addr
- && satosin(sc->gif_pdst)->sin_addr.s_addr == INADDR_ANY) {
- gifp = &sc->gif_if;
- continue;
- }
+ ip = mtod(m, struct ip *);
- if (satosin(sc->gif_psrc)->sin_addr.s_addr == ip->ip_dst.s_addr
- && satosin(sc->gif_pdst)->sin_addr.s_addr == ip->ip_src.s_addr)
- {
- gifp = &sc->gif_if;
- break;
- }
- }
+ gifp = (struct ifnet *)encap_getarg(m);
- if (gifp == NULL) {
-#ifdef MROUTING
- /* for backward compatibility */
- if (proto == IPPROTO_IPV4) {
- ipip_input(m, off, proto);
- return;
- }
-#endif /*MROUTING*/
+ if (gifp == NULL || (gifp->if_flags & IFF_UP) == 0) {
m_freem(m);
ipstat.ips_nogif++;
return;
@@ -310,16 +263,10 @@ in_gif_input(struct mbuf *m, int off, int proto)
m_adj(m, off);
switch (proto) {
+#ifdef INET
case IPPROTO_IPV4:
{
struct ip *ip;
-
-#ifdef INET6
- if (bcmp(gifp->if_name, "stf", 3) == 0) {
- m_freem(m);
- return;
- }
-#endif
af = AF_INET;
if (m->m_len < sizeof(*ip)) {
m = m_pullup(m, sizeof(*ip));
@@ -331,6 +278,7 @@ in_gif_input(struct mbuf *m, int off, int proto)
ip_ecn_egress(ECN_ALLOWED, &otos, &ip->ip_tos);
break;
}
+#endif
#ifdef INET6
case IPPROTO_IPV6:
{
@@ -359,3 +307,81 @@ in_gif_input(struct mbuf *m, int off, int proto)
gif_input(m, af, gifp);
return;
}
+
+/*
+ * we know that we are in IFF_UP, outer address available, and outer family
+ * matched the physical addr family. see gif_encapcheck().
+ */
+int
+gif_encapcheck4(m, off, proto, arg)
+ const struct mbuf *m;
+ int off;
+ int proto;
+ void *arg;
+{
+ struct ip ip;
+ struct gif_softc *sc;
+ struct sockaddr_in *src, *dst;
+ int addrmatch;
+ struct in_ifaddr *ia4;
+
+ /* sanity check done in caller */
+ sc = (struct gif_softc *)arg;
+ src = (struct sockaddr_in *)sc->gif_psrc;
+ dst = (struct sockaddr_in *)sc->gif_pdst;
+
+ /* LINTED const cast */
+ m_copydata((struct mbuf *)m, 0, sizeof(ip), (caddr_t)&ip);
+
+ /* check for address match */
+ addrmatch = 0;
+ if (src->sin_addr.s_addr == ip.ip_dst.s_addr)
+ addrmatch |= 1;
+ if (dst->sin_addr.s_addr == ip.ip_src.s_addr)
+ addrmatch |= 2;
+ else if ((sc->gif_if.if_flags & IFF_LINK0) != 0 &&
+ dst->sin_addr.s_addr == INADDR_ANY) {
+ addrmatch |= 2; /* we accept any source */
+ }
+ if (addrmatch != 3)
+ return 0;
+
+ /* martian filters on outer source - NOT done in ip_input! */
+ if (IN_MULTICAST(ip.ip_src.s_addr))
+ return 0;
+ switch ((ntohl(ip.ip_src.s_addr) & 0xff000000) >> 24) {
+ case 0: case 127: case 255:
+ return 0;
+ }
+ /* reject packets with broadcast on source */
+ for (ia4 = TAILQ_FIRST(&in_ifaddrhead); ia4;
+ ia4 = TAILQ_NEXT(ia4, ia_link))
+ {
+ if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0)
+ continue;
+ if (ip.ip_src.s_addr == ia4->ia_broadaddr.sin_addr.s_addr)
+ return 0;
+ }
+
+ /* ingress filters on outer source */
+ if ((m->m_flags & M_PKTHDR) != 0 && m->m_pkthdr.rcvif) {
+ struct sockaddr_in sin;
+ struct rtentry *rt;
+
+ bzero(&sin, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_addr = ip.ip_src;
+ rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL);
+ if (!rt)
+ return 0;
+ if (rt->rt_ifp != m->m_pkthdr.rcvif) {
+ rtfree(rt);
+ return 0;
+ }
+ rtfree(rt);
+ }
+
+ /* prioritize: IFF_LINK0 mode is less preferred */
+ return (sc->gif_if.if_flags & IFF_LINK0) ? 32 : 32 * 2;
+}
diff --git a/sys/netinet/in_gif.h b/sys/netinet/in_gif.h
index 39d1aba..de03c6e 100644
--- a/sys/netinet/in_gif.h
+++ b/sys/netinet/in_gif.h
@@ -1,3 +1,6 @@
+/* $FreeBSD$ */
+/* $KAME: in_gif.h,v 1.5 2000/04/14 08:36:02 itojun Exp $ */
+
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
@@ -25,23 +28,17 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD$
*/
#ifndef _NETINET_IN_GIF_H_
-#define _NETINET_IN_GIF_H_
+#define _NETINET_IN_GIF_H_
-#define GIF_TTL 30
+#define GIF_TTL 30
extern int ip_gif_ttl;
-struct mbuf;
-struct ifnet;
-struct rtentry;
-
-void in_gif_input __P((struct mbuf *, int off, int proto));
-int in_gif_output __P((struct ifnet *, int, struct mbuf *,
- struct rtentry *));
+void in_gif_input __P((struct mbuf *, ...));
+int in_gif_output __P((struct ifnet *, int, struct mbuf *, struct rtentry *));
+int gif_encapcheck4 __P((const struct mbuf *, int, int, void *));
#endif /*_NETINET_IN_GIF_H_*/
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 2ed3aa0..b8b8278 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -72,7 +72,6 @@
#ifdef IPSEC
#include <netinet6/ipsec.h>
#include <netkey/key.h>
-#include <netkey/key_debug.h>
#endif /* IPSEC */
struct in_addr zeroin_addr;
@@ -534,8 +533,7 @@ in_pcbdetach(inp)
struct inpcbinfo *ipi = inp->inp_pcbinfo;
#ifdef IPSEC
- if (inp->inp_sp != NULL)
- ipsec4_delete_pcbpolicy(inp);
+ ipsec4_delete_pcbpolicy(inp);
#endif /*IPSEC*/
inp->inp_gencnt = ++ipi->ipi_gencnt;
in_pcbremlists(inp);
diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c
index 2fdfddf..f863b4f 100644
--- a/sys/netinet/in_proto.c
+++ b/sys/netinet/in_proto.c
@@ -61,6 +61,7 @@
#include <netinet/tcp_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
+#include <netinet/ip_encap.h>
#include <netinet/ipprotosw.h>
@@ -81,6 +82,11 @@
#include <netinet/in_gif.h>
#endif
+#include "stf.h"
+#if NSTF > 0
+#include <net/if_stf.h>
+#endif
+
#ifdef IPXIP
#include <netipx/ipx_ip.h>
#endif
@@ -153,29 +159,20 @@ struct ipprotosw inetsw[] = {
},
#endif
#endif /* IPSEC */
-#if NGIF > 0
{ SOCK_RAW, &inetdomain, IPPROTO_IPV4, PR_ATOMIC|PR_ADDR,
- in_gif_input, 0, 0, 0,
+ encap4_input, 0, 0, rip_ctloutput,
0,
- 0, 0, 0, 0,
+ encap_init, 0, 0, 0,
&nousrreqs
},
# ifdef INET6
{ SOCK_RAW, &inetdomain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR,
- in_gif_input, 0, 0, 0,
+ encap4_input, 0, 0, rip_ctloutput,
0,
0, 0, 0, 0,
&nousrreqs
},
#endif
-#else /*NGIF*/
-{ SOCK_RAW, &inetdomain, IPPROTO_IPIP, PR_ATOMIC|PR_ADDR,
- ipip_input, 0, 0, rip_ctloutput,
- 0,
- 0, 0, 0, 0,
- &rip_usrreqs
-},
-#endif /*NGIF*/
#ifdef IPDIVERT
{ SOCK_RAW, &inetdomain, IPPROTO_DIVERT, PR_ATOMIC|PR_ADDR,
div_input, 0, 0, ip_ctloutput,
@@ -209,6 +206,26 @@ struct ipprotosw inetsw[] = {
},
};
+#if NGIF > 0
+struct ipprotosw in_gif_protosw =
+{ SOCK_RAW, &inetdomain, 0/*IPPROTO_IPV[46]*/, PR_ATOMIC|PR_ADDR,
+ in_gif_input, rip_output, 0, rip_ctloutput,
+ 0,
+ 0, 0, 0, 0,
+ &rip_usrreqs
+};
+#endif /*NGIF*/
+
+#if NSTF > 0
+struct ipprotosw in_stf_protosw =
+{ SOCK_RAW, &inetdomain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR,
+ in_stf_input, rip_output, 0, rip_ctloutput,
+ 0,
+ 0, 0, 0, 0,
+ &rip_usrreqs
+};
+#endif /*NSTF*/
+
extern int in_inithead __P((void **, int));
struct domain inetdomain =
diff --git a/sys/netinet/ip6.h b/sys/netinet/ip6.h
index 2c0297f..c194043 100644
--- a/sys/netinet/ip6.h
+++ b/sys/netinet/ip6.h
@@ -1,5 +1,8 @@
+/* $FreeBSD$ */
+/* $KAME: ip6.h,v 1.9 2000/07/02 21:01:32 itojun Exp $ */
+
/*
- * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,10 +28,277 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ip.h 8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _NETINET_IP6_H_
+#define _NETINET_IP6_H_
+
+/*
+ * Definition for internet protocol version 6.
+ * RFC 2460
+ */
+
+struct ip6_hdr {
+ union {
+ struct ip6_hdrctl {
+ u_int32_t ip6_un1_flow; /* 20 bits of flow-ID */
+ u_int16_t ip6_un1_plen; /* payload length */
+ u_int8_t ip6_un1_nxt; /* next header */
+ u_int8_t ip6_un1_hlim; /* hop limit */
+ } ip6_un1;
+ u_int8_t ip6_un2_vfc; /* 4 bits version, top 4 bits class */
+ } ip6_ctlun;
+ struct in6_addr ip6_src; /* source address */
+ struct in6_addr ip6_dst; /* destination address */
+};
+
+#define ip6_vfc ip6_ctlun.ip6_un2_vfc
+#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
+#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
+#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt
+#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim
+#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim
+
+#define IPV6_VERSION 0x60
+#define IPV6_VERSION_MASK 0xf0
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define IPV6_FLOWINFO_MASK 0x0fffffff /* flow info (28 bits) */
+#define IPV6_FLOWLABEL_MASK 0x000fffff /* flow label (20 bits) */
+#else
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define IPV6_FLOWINFO_MASK 0xffffff0f /* flow info (28 bits) */
+#define IPV6_FLOWLABEL_MASK 0xffff0f00 /* flow label (20 bits) */
+#endif /* LITTLE_ENDIAN */
+#endif
+/* ECN bits proposed by Sally Floyd */
+#define IP6TOS_CE 0x01 /* congestion experienced */
+#define IP6TOS_ECT 0x02 /* ECN-capable transport */
+
+/*
+ * Extension Headers
+ */
+
+struct ip6_ext {
+ u_char ip6e_nxt;
+ u_char ip6e_len;
+};
+
+/* Hop-by-Hop options header */
+/* XXX should we pad it to force alignment on an 8-byte boundary? */
+struct ip6_hbh {
+ u_int8_t ip6h_nxt; /* next header */
+ u_int8_t ip6h_len; /* length in units of 8 octets */
+ /* followed by options */
+};
+
+/* Destination options header */
+/* XXX should we pad it to force alignment on an 8-byte boundary? */
+struct ip6_dest {
+ u_int8_t ip6d_nxt; /* next header */
+ u_int8_t ip6d_len; /* length in units of 8 octets */
+ /* followed by options */
+};
+
+/* Option types and related macros */
+#define IP6OPT_PAD1 0x00 /* 00 0 00000 */
+#define IP6OPT_PADN 0x01 /* 00 0 00001 */
+#define IP6OPT_JUMBO 0xC2 /* 11 0 00010 = 194 */
+#define IP6OPT_JUMBO_LEN 6
+#define IP6OPT_RTALERT 0x05 /* 00 0 00101 */
+#define IP6OPT_RTALERT_LEN 4
+#define IP6OPT_RTALERT_MLD 0 /* Datagram contains an MLD message */
+#define IP6OPT_RTALERT_RSVP 1 /* Datagram contains an RSVP message */
+#define IP6OPT_RTALERT_ACTNET 2 /* contains an Active Networks msg */
+#define IP6OPT_MINLEN 2
+
+#define IP6OPT_TYPE(o) ((o) & 0xC0)
+#define IP6OPT_TYPE_SKIP 0x00
+#define IP6OPT_TYPE_DISCARD 0x40
+#define IP6OPT_TYPE_FORCEICMP 0x80
+#define IP6OPT_TYPE_ICMP 0xC0
+
+#define IP6OPT_MUTABLE 0x20
+
+/* Routing header */
+struct ip6_rthdr {
+ u_int8_t ip6r_nxt; /* next header */
+ u_int8_t ip6r_len; /* length in units of 8 octets */
+ u_int8_t ip6r_type; /* routing type */
+ u_int8_t ip6r_segleft; /* segments left */
+ /* followed by routing type specific data */
+};
+
+/* Type 0 Routing header */
+struct ip6_rthdr0 {
+ u_int8_t ip6r0_nxt; /* next header */
+ u_int8_t ip6r0_len; /* length in units of 8 octets */
+ u_int8_t ip6r0_type; /* always zero */
+ u_int8_t ip6r0_segleft; /* segments left */
+ u_int8_t ip6r0_reserved; /* reserved field */
+ u_int8_t ip6r0_slmap[3]; /* strict/loose bit map */
+ struct in6_addr ip6r0_addr[1]; /* up to 23 addresses */
+};
+
+/* Fragment header */
+struct ip6_frag {
+ u_int8_t ip6f_nxt; /* next header */
+ u_int8_t ip6f_reserved; /* reserved field */
+ u_int16_t ip6f_offlg; /* offset, reserved, and flag */
+ u_int32_t ip6f_ident; /* identification */
+};
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define IP6F_OFF_MASK 0xfff8 /* mask out offset from _offlg */
+#define IP6F_RESERVED_MASK 0x0006 /* reserved bits in ip6f_offlg */
+#define IP6F_MORE_FRAG 0x0001 /* more-fragments flag */
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+#define IP6F_OFF_MASK 0xf8ff /* mask out offset from _offlg */
+#define IP6F_RESERVED_MASK 0x0600 /* reserved bits in ip6f_offlg */
+#define IP6F_MORE_FRAG 0x0100 /* more-fragments flag */
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+/*
+ * Internet implementation parameters.
+ */
+#define IPV6_MAXHLIM 255 /* maximun hoplimit */
+#define IPV6_DEFHLIM 64 /* default hlim */
+#define IPV6_FRAGTTL 120 /* ttl for fragment packets, in slowtimo tick */
+#define IPV6_HLIMDEC 1 /* subtracted when forwaeding */
+
+#define IPV6_MMTU 1280 /* minimal MTU and reassembly. 1024 + 256 */
+#define IPV6_MAXPACKET 65535 /* ip6 max packet size without Jumbo payload*/
+
+#ifdef _KERNEL
+/*
+ * IP6_EXTHDR_CHECK ensures that region between the IP6 header and the
+ * target header (including IPv6 itself, extension headers and
+ * TCP/UDP/ICMP6 headers) are continuous. KAME requires drivers
+ * to store incoming data into one internal mbuf or one or more external
+ * mbufs(never into two or more internal mbufs). Thus, the third case is
+ * supposed to never be matched but is prepared just in case.
+ */
+
+#ifdef INET6
+#define IP6_EXTHDR_STAT(x) x
+#else
+#define IP6_EXTHDR_STAT(x)
+#endif
+
+#define IP6_EXTHDR_CHECK(m, off, hlen, ret) \
+do { \
+ if ((m)->m_next != NULL) { \
+ if (((m)->m_flags & M_LOOP) && \
+ ((m)->m_len < (off) + (hlen)) && \
+ (((m) = m_pullup((m), (off) + (hlen))) == NULL)) { \
+ IP6_EXTHDR_STAT(ip6stat.ip6s_exthdrtoolong++); \
+ return ret; \
+ } else if ((m)->m_flags & M_EXT) { \
+ if ((m)->m_len < (off) + (hlen)) { \
+ IP6_EXTHDR_STAT(ip6stat.ip6s_exthdrtoolong++); \
+ m_freem(m); \
+ return ret; \
+ } \
+ } else { \
+ if ((m)->m_len < (off) + (hlen)) { \
+ IP6_EXTHDR_STAT(ip6stat.ip6s_exthdrtoolong++); \
+ m_freem(m); \
+ return ret; \
+ } \
+ } \
+ } else { \
+ if ((m)->m_len < (off) + (hlen)) { \
+ IP6_EXTHDR_STAT(ip6stat.ip6s_tooshort++); \
+ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); \
+ m_freem(m); \
+ return ret; \
+ } \
+ } \
+} while (0)
+
+/*
+ * IP6_EXTHDR_GET ensures that intermediate protocol header (from "off" to
+ * "len") is located in single mbuf, on contiguous memory region.
+ * The pointer to the region will be returned to pointer variable "val",
+ * with type "typ".
+ * IP6_EXTHDR_GET0 does the same, except that it aligns the structure at the
+ * very top of mbuf. GET0 is likely to make memory copy than GET.
*
- * $FreeBSD$
+ * XXX we're now testing this, needs m_pulldown()
*/
+#define IP6_EXTHDR_GET(val, typ, m, off, len) \
+do { \
+ struct mbuf *t; \
+ int tmp; \
+ IP6_EXTHDR_STAT(ip6stat.ip6s_exthdrget++); \
+ if ((m)->m_len >= (off) + (len)) \
+ (val) = (typ)(mtod((m), caddr_t) + (off)); \
+ else { \
+ t = m_pulldown((m), (off), (len), &tmp); \
+ if (t) { \
+ if (t->m_len < tmp + (len)) \
+ panic("m_pulldown malfunction"); \
+ (val) = (typ)(mtod(t, caddr_t) + tmp); \
+ } else { \
+ (val) = (typ)NULL; \
+ (m) = NULL; \
+ } \
+ } \
+} while (0)
+
+#define IP6_EXTHDR_GET0(val, typ, m, off, len) \
+do { \
+ struct mbuf *t; \
+ IP6_EXTHDR_STAT(ip6stat.ip6s_exthdrget0++); \
+ if ((off) == 0) \
+ (val) = (typ)mtod(m, caddr_t); \
+ else { \
+ t = m_pulldown((m), (off), (len), NULL); \
+ if (t) { \
+ if (t->m_len < (len)) \
+ panic("m_pulldown malfunction"); \
+ (val) = (typ)mtod(t, caddr_t); \
+ } else { \
+ (val) = (typ)NULL; \
+ (m) = NULL; \
+ } \
+ } \
+} while (0)
+#endif /*_KERNEL*/
-#define __KAME_NETINET_IP6_H_INCLUDED_
-#include <netinet6/ip6.h>
-#undef __KAME_NETINET_IP6_H_INCLUDED_
+#endif /* not _NETINET_IP6_H_ */
diff --git a/sys/netinet/ip_ecn.c b/sys/netinet/ip_ecn.c
index aeb588e..047f82e 100644
--- a/sys/netinet/ip_ecn.c
+++ b/sys/netinet/ip_ecn.c
@@ -1,3 +1,6 @@
+/* $FreeBSD$ */
+/* $KAME: ip_ecn.c,v 1.7 2000/05/05 11:00:56 sumikawa Exp $ */
+
/*
* Copyright (C) 1999 WIDE Project.
* All rights reserved.
@@ -26,8 +29,6 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ip_ecn.c,v 1.2 1999/07/30 12:17:15 itojun Exp $
- * $FreeBSD$
*/
/*
* ECN consideration on tunnel ingress/egress operation.
diff --git a/sys/netinet/ip_ecn.h b/sys/netinet/ip_ecn.h
index 921ce37..6445d0f 100644
--- a/sys/netinet/ip_ecn.h
+++ b/sys/netinet/ip_ecn.h
@@ -1,3 +1,6 @@
+/* $FreeBSD$ */
+/* $KAME: ip_ecn.h,v 1.5 2000/03/27 04:58:38 sumikawa Exp $ */
+
/*
* Copyright (C) 1999 WIDE Project.
* All rights reserved.
@@ -26,17 +29,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ip_ecn.h,v 1.2 1999/08/19 12:57:44 itojun Exp $
- * $FreeBSD$
*/
/*
* ECN consideration on tunnel ingress/egress operation.
* http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt
*/
-#define ECN_ALLOWED 1 /* ECN allowed */
-#define ECN_FORBIDDEN 0 /* ECN forbidden */
-#define ECN_NOCARE (-1) /* no consideration to ECN */
+#define ECN_ALLOWED 1 /* ECN allowed */
+#define ECN_FORBIDDEN 0 /* ECN forbidden */
+#define ECN_NOCARE (-1) /* no consideration to ECN */
#ifdef _KERNEL
extern void ip_ecn_ingress __P((int, u_int8_t *, u_int8_t *));
diff --git a/sys/netinet/ip_encap.c b/sys/netinet/ip_encap.c
new file mode 100644
index 0000000..de83334
--- /dev/null
+++ b/sys/netinet/ip_encap.c
@@ -0,0 +1,534 @@
+/* $FreeBSD$ */
+/* $KAME: ip_encap.c,v 1.36 2000/06/17 20:34:24 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * My grandfather said that there's a devil inside tunnelling technology...
+ *
+ * We have surprisingly many protocols that want packets with IP protocol
+ * #4 or #41. Here's a list of protocols that want protocol #41:
+ * RFC1933 configured tunnel
+ * RFC1933 automatic tunnel
+ * RFC2401 IPsec tunnel
+ * RFC2473 IPv6 generic packet tunnelling
+ * RFC2529 6over4 tunnel
+ * mobile-ip6 (uses RFC2473)
+ * 6to4 tunnel
+ * Here's a list of protocol that want protocol #4:
+ * RFC1853 IPv4-in-IPv4 tunnelling
+ * RFC2003 IPv4 encapsulation within IPv4
+ * RFC2344 reverse tunnelling for mobile-ip4
+ * RFC2401 IPsec tunnel
+ * Well, what can I say. They impose different en/decapsulation mechanism
+ * from each other, so they need separate protocol handler. The only one
+ * we can easily determine by protocol # is IPsec, which always has
+ * AH/ESP/IPComp header right after outer IP header.
+ *
+ * So, clearly good old protosw does not work for protocol #4 and #41.
+ * The code will let you match protocol via src/dst address pair.
+ */
+/* XXX is M_NETADDR correct? */
+
+#include "opt_mrouting.h"
+#include "opt_inet.h"
+#include "opt_inet6.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/errno.h>
+#include <sys/protosw.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip_encap.h>
+#ifdef MROUTING
+#include <netinet/ip_mroute.h>
+#endif /* MROUTING */
+#include <netinet/ipprotosw.h>
+
+#ifdef INET6
+#include <netinet/ip6.h>
+#include <netinet6/ip6_var.h>
+#include <netinet6/ip6protosw.h>
+#endif
+
+#include <machine/stdarg.h>
+
+#include <net/net_osdep.h>
+
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+MALLOC_DEFINE(M_NETADDR, "Export Host", "Export host address structure");
+
+static void encap_add __P((struct encaptab *));
+static int mask_match __P((const struct encaptab *, const struct sockaddr *,
+ const struct sockaddr *));
+static void encap_fillarg __P((struct mbuf *, const struct encaptab *));
+
+/* rely upon BSS initialization */
+LIST_HEAD(, encaptab) encaptab;
+
+void
+encap_init()
+{
+#if 0
+ /*
+ * we cannot use LIST_INIT() here, since drivers may want to call
+ * encap_attach(), on driver attach. encap_init() will be called
+ * on AF_INET{,6} initialization, which happens after driver
+ * initialization - using LIST_INIT() here can nuke encap_attach()
+ * from drivers.
+ */
+ LIST_INIT(&encaptab);
+#endif
+}
+
+void
+#if __STDC__
+encap4_input(struct mbuf *m, ...)
+#else
+encap4_input(m, va_alist)
+ struct mbuf *m;
+ va_dcl
+#endif
+{
+ int off, proto;
+ struct ip *ip;
+ struct sockaddr_in s, d;
+ const struct ipprotosw *psw;
+ struct encaptab *ep, *match;
+ va_list ap;
+ int prio, matchprio;
+
+ va_start(ap, m);
+ off = va_arg(ap, int);
+ proto = va_arg(ap, int);
+ va_end(ap);
+
+ ip = mtod(m, struct ip *);
+
+ bzero(&s, sizeof(s));
+ s.sin_family = AF_INET;
+ s.sin_len = sizeof(struct sockaddr_in);
+ s.sin_addr = ip->ip_src;
+ bzero(&d, sizeof(d));
+ d.sin_family = AF_INET;
+ d.sin_len = sizeof(struct sockaddr_in);
+ d.sin_addr = ip->ip_dst;
+
+ match = NULL;
+ matchprio = 0;
+ for (ep = LIST_FIRST(&encaptab); ep; ep = LIST_NEXT(ep, chain)) {
+ if (ep->af != AF_INET)
+ continue;
+ if (ep->proto >= 0 && ep->proto != proto)
+ continue;
+ if (ep->func)
+ prio = (*ep->func)(m, off, proto, ep->arg);
+ else {
+ /*
+ * it's inbound traffic, we need to match in reverse
+ * order
+ */
+ prio = mask_match(ep, (struct sockaddr *)&d,
+ (struct sockaddr *)&s);
+ }
+
+ /*
+ * We prioritize the matches by using bit length of the
+ * matches. mask_match() and user-supplied matching function
+ * should return the bit length of the matches (for example,
+ * if both src/dst are matched for IPv4, 64 should be returned).
+ * 0 or negative return value means "it did not match".
+ *
+ * The question is, since we have two "mask" portion, we
+ * cannot really define total order between entries.
+ * For example, which of these should be preferred?
+ * mask_match() returns 48 (32 + 16) for both of them.
+ * src=3ffe::/16, dst=3ffe:501::/32
+ * src=3ffe:501::/32, dst=3ffe::/16
+ *
+ * We need to loop through all the possible candidates
+ * to get the best match - the search takes O(n) for
+ * n attachments (i.e. interfaces).
+ */
+ if (prio <= 0)
+ continue;
+ if (prio > matchprio) {
+ matchprio = prio;
+ match = ep;
+ }
+ }
+
+ if (match) {
+ /* found a match, "match" has the best one */
+ psw = (const struct ipprotosw *)match->psw;
+ if (psw && psw->pr_input) {
+ encap_fillarg(m, match);
+ (*psw->pr_input)(m, off, proto);
+ } else
+ m_freem(m);
+ return;
+ }
+
+ /* for backward compatibility */
+# ifdef MROUTING
+# define COMPATFUNC ipip_input
+# endif /*MROUTING*/
+
+#ifdef COMPATFUNC
+ if (proto == IPPROTO_IPV4) {
+ COMPATFUNC(m, off, proto);
+ return;
+ }
+#endif
+
+ /* last resort: inject to raw socket */
+ rip_input(m, off, proto);
+}
+
+#ifdef INET6
+int
+encap6_input(mp, offp, proto)
+ struct mbuf **mp;
+ int *offp;
+ int proto;
+{
+ struct mbuf *m = *mp;
+ struct ip6_hdr *ip6;
+ struct sockaddr_in6 s, d;
+ const struct ip6protosw *psw;
+ struct encaptab *ep, *match;
+ int prio, matchprio;
+
+ ip6 = mtod(m, struct ip6_hdr *);
+
+ bzero(&s, sizeof(s));
+ s.sin6_family = AF_INET6;
+ s.sin6_len = sizeof(struct sockaddr_in6);
+ s.sin6_addr = ip6->ip6_src;
+ bzero(&d, sizeof(d));
+ d.sin6_family = AF_INET6;
+ d.sin6_len = sizeof(struct sockaddr_in6);
+ d.sin6_addr = ip6->ip6_dst;
+
+ match = NULL;
+ matchprio = 0;
+ for (ep = LIST_FIRST(&encaptab); ep; ep = LIST_NEXT(ep, chain)) {
+ if (ep->af != AF_INET6)
+ continue;
+ if (ep->proto >= 0 && ep->proto != proto)
+ continue;
+ if (ep->func)
+ prio = (*ep->func)(m, *offp, proto, ep->arg);
+ else {
+ /*
+ * it's inbound traffic, we need to match in reverse
+ * order
+ */
+ prio = mask_match(ep, (struct sockaddr *)&d,
+ (struct sockaddr *)&s);
+ }
+
+ /* see encap4_input() for issues here */
+ if (prio <= 0)
+ continue;
+ if (prio > matchprio) {
+ matchprio = prio;
+ match = ep;
+ }
+ }
+
+ if (match) {
+ /* found a match */
+ psw = (const struct ip6protosw *)match->psw;
+ if (psw && psw->pr_input) {
+ encap_fillarg(m, match);
+ return (*psw->pr_input)(mp, offp, proto);
+ } else {
+ m_freem(m);
+ return IPPROTO_DONE;
+ }
+ }
+
+ /* last resort: inject to raw socket */
+ return rip6_input(mp, offp, proto);
+}
+#endif
+
+static void
+encap_add(ep)
+ struct encaptab *ep;
+{
+
+ LIST_INSERT_HEAD(&encaptab, ep, chain);
+}
+
+/*
+ * sp (src ptr) is always my side, and dp (dst ptr) is always remote side.
+ * length of mask (sm and dm) is assumed to be same as sp/dp.
+ * Return value will be necessary as input (cookie) for encap_detach().
+ */
+const struct encaptab *
+encap_attach(af, proto, sp, sm, dp, dm, psw, arg)
+ int af;
+ int proto;
+ const struct sockaddr *sp, *sm;
+ const struct sockaddr *dp, *dm;
+ const struct protosw *psw;
+ void *arg;
+{
+ struct encaptab *ep;
+ int error;
+ int s;
+
+ s = splnet();
+ /* sanity check on args */
+ if (sp->sa_len > sizeof(ep->src) || dp->sa_len > sizeof(ep->dst)) {
+ error = EINVAL;
+ goto fail;
+ }
+ if (sp->sa_len != dp->sa_len) {
+ error = EINVAL;
+ goto fail;
+ }
+ if (af != sp->sa_family || af != dp->sa_family) {
+ error = EINVAL;
+ goto fail;
+ }
+
+ /* check if anyone have already attached with exactly same config */
+ for (ep = LIST_FIRST(&encaptab); ep; ep = LIST_NEXT(ep, chain)) {
+ if (ep->af != af)
+ continue;
+ if (ep->proto != proto)
+ continue;
+ if (ep->src.ss_len != sp->sa_len ||
+ bcmp(&ep->src, sp, sp->sa_len) != 0 ||
+ bcmp(&ep->srcmask, sm, sp->sa_len) != 0)
+ continue;
+ if (ep->dst.ss_len != dp->sa_len ||
+ bcmp(&ep->dst, dp, dp->sa_len) != 0 ||
+ bcmp(&ep->dstmask, dm, dp->sa_len) != 0)
+ continue;
+
+ error = EEXIST;
+ goto fail;
+ }
+
+ ep = malloc(sizeof(*ep), M_NETADDR, M_NOWAIT); /*XXX*/
+ if (ep == NULL) {
+ error = ENOBUFS;
+ goto fail;
+ }
+ bzero(ep, sizeof(*ep));
+
+ ep->af = af;
+ ep->proto = proto;
+ bcopy(sp, &ep->src, sp->sa_len);
+ bcopy(sm, &ep->srcmask, sp->sa_len);
+ bcopy(dp, &ep->dst, dp->sa_len);
+ bcopy(dm, &ep->dstmask, dp->sa_len);
+ ep->psw = psw;
+ ep->arg = arg;
+
+ encap_add(ep);
+
+ error = 0;
+ splx(s);
+ return ep;
+
+fail:
+ splx(s);
+ return NULL;
+}
+
+const struct encaptab *
+encap_attach_func(af, proto, func, psw, arg)
+ int af;
+ int proto;
+ int (*func) __P((const struct mbuf *, int, int, void *));
+ const struct protosw *psw;
+ void *arg;
+{
+ struct encaptab *ep;
+ int error;
+ int s;
+
+ s = splnet();
+ /* sanity check on args */
+ if (!func) {
+ error = EINVAL;
+ goto fail;
+ }
+
+ ep = malloc(sizeof(*ep), M_NETADDR, M_NOWAIT); /*XXX*/
+ if (ep == NULL) {
+ error = ENOBUFS;
+ goto fail;
+ }
+ bzero(ep, sizeof(*ep));
+
+ ep->af = af;
+ ep->proto = proto;
+ ep->func = func;
+ ep->psw = psw;
+ ep->arg = arg;
+
+ encap_add(ep);
+
+ error = 0;
+ splx(s);
+ return ep;
+
+fail:
+ splx(s);
+ return NULL;
+}
+
+int
+encap_detach(cookie)
+ const struct encaptab *cookie;
+{
+ const struct encaptab *ep = cookie;
+ struct encaptab *p;
+
+ for (p = LIST_FIRST(&encaptab); p; p = LIST_NEXT(p, chain)) {
+ if (p == ep) {
+ LIST_REMOVE(p, chain);
+ free(p, M_NETADDR); /*XXX*/
+ return 0;
+ }
+ }
+
+ return EINVAL;
+}
+
+static int
+mask_match(ep, sp, dp)
+ const struct encaptab *ep;
+ const struct sockaddr *sp;
+ const struct sockaddr *dp;
+{
+ struct sockaddr_storage s;
+ struct sockaddr_storage d;
+ int i;
+ const u_int8_t *p, *q;
+ u_int8_t *r;
+ int matchlen;
+
+ if (sp->sa_len > sizeof(s) || dp->sa_len > sizeof(d))
+ return 0;
+ if (sp->sa_family != ep->af || dp->sa_family != ep->af)
+ return 0;
+ if (sp->sa_len != ep->src.ss_len || dp->sa_len != ep->dst.ss_len)
+ return 0;
+
+ matchlen = 0;
+
+ p = (const u_int8_t *)sp;
+ q = (const u_int8_t *)&ep->srcmask;
+ r = (u_int8_t *)&s;
+ for (i = 0 ; i < sp->sa_len; i++) {
+ r[i] = p[i] & q[i];
+ /* XXX estimate */
+ matchlen += (q[i] ? 8 : 0);
+ }
+
+ p = (const u_int8_t *)dp;
+ q = (const u_int8_t *)&ep->dstmask;
+ r = (u_int8_t *)&d;
+ for (i = 0 ; i < dp->sa_len; i++) {
+ r[i] = p[i] & q[i];
+ /* XXX rough estimate */
+ matchlen += (q[i] ? 8 : 0);
+ }
+
+ /* need to overwrite len/family portion as we don't compare them */
+ s.ss_len = sp->sa_len;
+ s.ss_family = sp->sa_family;
+ d.ss_len = dp->sa_len;
+ d.ss_family = dp->sa_family;
+
+ if (bcmp(&s, &ep->src, ep->src.ss_len) == 0 &&
+ bcmp(&d, &ep->dst, ep->dst.ss_len) == 0) {
+ return matchlen;
+ } else
+ return 0;
+}
+
+static void
+encap_fillarg(m, ep)
+ struct mbuf *m;
+ const struct encaptab *ep;
+{
+#if 0
+ m->m_pkthdr.aux = ep->arg;
+#else
+ struct mbuf *n;
+
+ n = m_aux_add(m, AF_INET, IPPROTO_IPV4);
+ if (n) {
+ *mtod(n, void **) = ep->arg;
+ n->m_len = sizeof(void *);
+ }
+#endif
+}
+
+void *
+encap_getarg(m)
+ struct mbuf *m;
+{
+ void *p;
+#if 0
+ p = m->m_pkthdr.aux;
+ m->m_pkthdr.aux = NULL;
+ return p;
+#else
+ struct mbuf *n;
+
+ p = NULL;
+ n = m_aux_find(m, AF_INET, IPPROTO_IPV4);
+ if (n) {
+ if (n->m_len == sizeof(void *))
+ p = *mtod(n, void **);
+ m_aux_delete(m, n);
+ }
+ return p;
+#endif
+}
diff --git a/sys/netinet/ip_encap.h b/sys/netinet/ip_encap.h
new file mode 100644
index 0000000..38df6f9
--- /dev/null
+++ b/sys/netinet/ip_encap.h
@@ -0,0 +1,64 @@
+/* $FreeBSD$ */
+/* $KAME: ip_encap.h,v 1.7 2000/03/25 07:23:37 sumikawa Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _NETINET_IP_ENCAP_H_
+#define _NETINET_IP_ENCAP_H_
+
+#ifdef _KERNEL
+
+struct encaptab {
+ LIST_ENTRY(encaptab) chain;
+ int af;
+ int proto; /* -1: don't care, I'll check myself */
+ struct sockaddr_storage src; /* my addr */
+ struct sockaddr_storage srcmask;
+ struct sockaddr_storage dst; /* remote addr */
+ struct sockaddr_storage dstmask;
+ int (*func) __P((const struct mbuf *, int, int, void *));
+ const struct protosw *psw; /* only pr_input will be used */
+ void *arg; /* passed via m->m_pkthdr.aux */
+};
+
+void encap_init __P((void));
+void encap4_input __P((struct mbuf *, ...));
+int encap6_input __P((struct mbuf **, int *, int));
+const struct encaptab *encap_attach __P((int, int, const struct sockaddr *,
+ const struct sockaddr *, const struct sockaddr *,
+ const struct sockaddr *, const struct protosw *, void *));
+const struct encaptab *encap_attach_func __P((int, int,
+ int (*) __P((const struct mbuf *, int, int, void *)),
+ const struct protosw *, void *));
+int encap_detach __P((const struct encaptab *));
+void *encap_getarg __P((struct mbuf *));
+#endif
+
+#endif /*_NETINET_IP_ENCAP_H_*/
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index fc355af..6647622 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -83,11 +83,6 @@
#ifdef IPSEC
#include <netinet6/ipsec.h>
#include <netkey/key.h>
-#ifdef IPSEC_DEBUG
-#include <netkey/key_debug.h>
-#else
-#define KEYDEBUG(lev,arg)
-#endif
#endif
#include "faith.h"
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 2536b63..450b0d6 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -152,16 +152,6 @@ ip_output(m0, opt, ro, flags, imo)
divert_cookie = 0;
#endif
- /*
- * NOTE: If IP_SOCKINMRCVIF flag is set, 'socket *' is kept in
- * m->m_pkthdr.rcvif for later IPSEC check. In this case,
- * m->m_pkthdr will be NULL cleared after the contents is saved in
- * 'so'.
- * NULL clearance of rcvif should be natural because the packet should
- * have been sent from my own socket and has no rcvif in this case.
- * It is also necessary because someone might consider it as
- * 'ifnet *', and cause SEGV.
- */
#if defined(IPFIREWALL) && defined(DUMMYNET)
/*
* dummynet packet are prepended a vestigial mbuf with
@@ -184,10 +174,8 @@ ip_output(m0, opt, ro, flags, imo)
m0 = m = m->m_next ;
#ifdef IPSEC
- if ((flags & IP_SOCKINMRCVIF) != 0) {
- so = (struct socket *)m->m_pkthdr.rcvif;
- m->m_pkthdr.rcvif = NULL;
- }
+ so = ipsec_getsocket(m);
+ ipsec_setsocket(m, NULL);
#endif
ip = mtod(m, struct ip *);
hlen = IP_VHL_HL(ip->ip_vhl) << 2 ;
@@ -196,10 +184,8 @@ ip_output(m0, opt, ro, flags, imo)
rule = NULL ;
#endif
#ifdef IPSEC
- if ((flags & IP_SOCKINMRCVIF) != 0) {
- so = (struct socket *)m->m_pkthdr.rcvif;
- m->m_pkthdr.rcvif = NULL;
- }
+ so = ipsec_getsocket(m);
+ ipsec_setsocket(m, NULL);
#endif
#ifdef DIAGNOSTIC
@@ -1051,8 +1037,16 @@ ip_optcopy(ip, jp)
*dp++ = IPOPT_NOP;
optlen = 1;
continue;
- } else
- optlen = cp[IPOPT_OLEN];
+ }
+#ifdef DIAGNOSTIC
+ if (cnt < IPOPT_OLEN + sizeof(*cp))
+ panic("malformed IPv4 option passed to ip_optcopy");
+#endif
+ optlen = cp[IPOPT_OLEN];
+#ifdef DIAGNOSTIC
+ if (optlen < IPOPT_OLEN + sizeof(*cp) || optlen > cnt)
+ panic("malformed IPv4 option passed to ip_optcopy");
+#endif
/* bogus lengths should have been caught by ip_dooptions */
if (optlen > cnt)
optlen = cnt;
@@ -1202,6 +1196,7 @@ ip_ctloutput(so, sopt)
case IP_IPSEC_POLICY:
{
caddr_t req;
+ size_t len = 0;
int priv;
struct mbuf *m;
int optname;
@@ -1213,8 +1208,9 @@ ip_ctloutput(so, sopt)
priv = (sopt->sopt_p != NULL &&
suser(sopt->sopt_p) != 0) ? 0 : 1;
req = mtod(m, caddr_t);
+ len = m->m_len;
optname = sopt->sopt_name;
- error = ipsec4_set_policy(inp, optname, req, priv);
+ error = ipsec4_set_policy(inp, optname, req, len, priv);
m_freem(m);
break;
}
@@ -1309,10 +1305,13 @@ ip_ctloutput(so, sopt)
{
struct mbuf *m = NULL;
caddr_t req = NULL;
+ size_t len = 0;
- if (m != 0)
+ if (m != 0) {
req = mtod(m, caddr_t);
- error = ipsec4_get_policy(sotoinpcb(so), req, &m);
+ len = m->m_len;
+ }
+ error = ipsec4_get_policy(sotoinpcb(so), req, len, &m);
if (error == 0)
error = soopt_mcopyout(sopt, m); /* XXX */
if (error == 0)
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index 1610ae2..4ddec93 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -131,9 +131,6 @@ struct ipstat {
#define IP_RAWOUTPUT 0x2 /* raw ip header exists */
#define IP_ROUTETOIF SO_DONTROUTE /* bypass routing tables */
#define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */
-#define IP_SOCKINMRCVIF 0x100 /* IPSEC hack;
- * socket pointer in sending
- * packet's m_pkthdr.rcvif */
struct ip;
struct inpcb;
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index 0bf0466..5d056ce 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -228,11 +228,10 @@ rip_output(m, so, dst)
}
#ifdef IPSEC
- m->m_pkthdr.rcvif = (struct ifnet *)so; /*XXX*/
+ ipsec_setsocket(m, so);
#endif /*IPSEC*/
- return (ip_output(m, inp->inp_options, &inp->inp_route,
- flags | IP_SOCKINMRCVIF,
+ return (ip_output(m, inp->inp_options, &inp->inp_route, flags,
inp->inp_moptions));
}
diff --git a/sys/netinet/tcp_debug.c b/sys/netinet/tcp_debug.c
index d84c37a..89e9d7c 100644
--- a/sys/netinet/tcp_debug.c
+++ b/sys/netinet/tcp_debug.c
@@ -59,7 +59,7 @@
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#ifdef INET6
-#include <netinet6/ip6.h>
+#include <netinet/ip6.h>
#endif
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 28fb89e..9cdff6a 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -60,22 +60,18 @@
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#ifdef INET6
-#include <netinet/ip6.h>
+#include <netinet/ip_icmp.h> /* for ICMP_BANDLIM */
#include <netinet/in_var.h>
-#include <netinet6/nd6.h>
-#include <netinet/icmp6.h>
-#endif
+#include <netinet/icmp_var.h> /* for ICMP_BANDLIM */
#include <netinet/in_pcb.h>
-#ifdef INET6
-#include <netinet6/in6_pcb.h>
-#endif
#include <netinet/ip_var.h>
#ifdef INET6
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#include <netinet6/nd6.h>
#include <netinet6/ip6_var.h>
+#include <netinet6/in6_pcb.h>
#endif
-#include <netinet/icmp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_seq.h>
@@ -157,7 +153,7 @@ do { \
if ((tp) && (tp)->t_inpcb && \
((tp)->t_inpcb->inp_vflag & INP_IPV6) != 0 && \
(tp)->t_inpcb->in6p_route.ro_rt) \
- nd6_nud_hint((tp)->t_inpcb->in6p_route.ro_rt, NULL); \
+ nd6_nud_hint((tp)->t_inpcb->in6p_route.ro_rt, NULL, 0); \
} while (0)
#else
#define ND6_HINT(tp)
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index eb49848..5a3c1bd 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -45,6 +45,7 @@
#include <sys/kernel.h>
#include <sys/sysctl.h>
#include <sys/mbuf.h>
+#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
@@ -54,15 +55,11 @@
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
-#ifdef INET6
-#include <netinet/ip6.h>
-#endif
#include <netinet/in_pcb.h>
-#ifdef INET6
-#include <netinet6/in6_pcb.h>
-#endif
#include <netinet/ip_var.h>
#ifdef INET6
+#include <netinet6/in6_pcb.h>
+#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#endif
#include <netinet/tcp.h>
@@ -813,31 +810,38 @@ send:
*/
#ifdef INET6
if (isipv6) {
- /*
+ /*
* we separately set hoplimit for every segment, since the
* user might want to change the value via setsockopt.
* Also, desired default hop limit might be changed via
- * Neighbor Discovery.
- */
- ip6->ip6_hlim = in6_selecthlim(tp->t_inpcb,
- tp->t_inpcb->in6p_route.ro_rt ?
- tp->t_inpcb->in6p_route.ro_rt->rt_ifp
- : NULL);
+ * Neighbor Discovery.
+ */
+ ip6->ip6_hlim = in6_selecthlim(tp->t_inpcb,
+ tp->t_inpcb->in6p_route.ro_rt ?
+ tp->t_inpcb->in6p_route.ro_rt->rt_ifp
+ : NULL);
/* TODO: IPv6 IP6TOS_ECT bit on */
#ifdef IPSEC
- m->m_pkthdr.rcvif = (struct ifnet *)so;
+ ipsec_setsocket(m, so);
#endif /*IPSEC*/
error = ip6_output(m,
tp->t_inpcb->in6p_outputopts,
&tp->t_inpcb->in6p_route,
- (so->so_options & SO_DONTROUTE)|IPV6_SOCKINMRCVIF,
- NULL, NULL);
+ (so->so_options & SO_DONTROUTE), NULL, NULL);
} else
#endif /* INET6 */
{
struct rtentry *rt;
ip->ip_len = m->m_pkthdr.len;
+#ifdef INET6
+ if (INP_CHECK_SOCKAF(so, AF_INET6))
+ ip->ip_ttl = in6_selecthlim(tp->t_inpcb,
+ tp->t_inpcb->in6p_route.ro_rt ?
+ tp->t_inpcb->in6p_route.ro_rt->rt_ifp
+ : NULL);
+ else
+#endif /* INET6 */
ip->ip_ttl = tp->t_inpcb->inp_ip_ttl; /* XXX */
ip->ip_tos = tp->t_inpcb->inp_ip_tos; /* XXX */
/*
@@ -853,8 +857,11 @@ send:
&& !(rt->rt_rmx.rmx_locks & RTV_MTU)) {
ip->ip_off |= IP_DF;
}
+#ifdef IPSEC
+ ipsec_setsocket(m, so);
+#endif /*IPSEC*/
error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
- (so->so_options & SO_DONTROUTE)|IP_SOCKINMRCVIF, 0);
+ (so->so_options & SO_DONTROUTE), 0);
}
if (error) {
out:
diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c
index 28fb89e..9cdff6a 100644
--- a/sys/netinet/tcp_reass.c
+++ b/sys/netinet/tcp_reass.c
@@ -60,22 +60,18 @@
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#ifdef INET6
-#include <netinet/ip6.h>
+#include <netinet/ip_icmp.h> /* for ICMP_BANDLIM */
#include <netinet/in_var.h>
-#include <netinet6/nd6.h>
-#include <netinet/icmp6.h>
-#endif
+#include <netinet/icmp_var.h> /* for ICMP_BANDLIM */
#include <netinet/in_pcb.h>
-#ifdef INET6
-#include <netinet6/in6_pcb.h>
-#endif
#include <netinet/ip_var.h>
#ifdef INET6
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#include <netinet6/nd6.h>
#include <netinet6/ip6_var.h>
+#include <netinet6/in6_pcb.h>
#endif
-#include <netinet/icmp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_seq.h>
@@ -157,7 +153,7 @@ do { \
if ((tp) && (tp)->t_inpcb && \
((tp)->t_inpcb->inp_vflag & INP_IPV6) != 0 && \
(tp)->t_inpcb->in6p_route.ro_rt) \
- nd6_nud_hint((tp)->t_inpcb->in6p_route.ro_rt, NULL); \
+ nd6_nud_hint((tp)->t_inpcb->in6p_route.ro_rt, NULL, 0); \
} while (0)
#else
#define ND6_HINT(tp)
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index aee77e7..68f87aa 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -92,6 +92,9 @@
#ifdef IPSEC
#include <netinet6/ipsec.h>
+#ifdef INET6
+#include <netinet6/ipsec6.h>
+#endif
#endif /*IPSEC*/
#include <machine/in_cksum.h>
@@ -441,14 +444,7 @@ tcp_respond(tp, ipgen, th, m, ack, seq, flags)
tcp_trace(TA_OUTPUT, 0, tp, mtod(m, void *), th, 0);
#endif
#ifdef IPSEC
- if (tp != NULL) {
- m->m_pkthdr.rcvif = (struct ifnet *)tp->t_inpcb->inp_socket;
- ipflags |=
-#ifdef INET6
- isipv6 ? IPV6_SOCKINMRCVIF :
-#endif
- IP_SOCKINMRCVIF;
- }
+ ipsec_setsocket(m, tp ? tp->t_inpcb->inp_socket : NULL);
#endif
#ifdef INET6
if (isipv6) {
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index aee77e7..68f87aa 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -92,6 +92,9 @@
#ifdef IPSEC
#include <netinet6/ipsec.h>
+#ifdef INET6
+#include <netinet6/ipsec6.h>
+#endif
#endif /*IPSEC*/
#include <machine/in_cksum.h>
@@ -441,14 +444,7 @@ tcp_respond(tp, ipgen, th, m, ack, seq, flags)
tcp_trace(TA_OUTPUT, 0, tp, mtod(m, void *), th, 0);
#endif
#ifdef IPSEC
- if (tp != NULL) {
- m->m_pkthdr.rcvif = (struct ifnet *)tp->t_inpcb->inp_socket;
- ipflags |=
-#ifdef INET6
- isipv6 ? IPV6_SOCKINMRCVIF :
-#endif
- IP_SOCKINMRCVIF;
- }
+ ipsec_setsocket(m, tp ? tp->t_inpcb->inp_socket : NULL);
#endif
#ifdef INET6
if (isipv6) {
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 1ec33b2..09b5c96 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -188,6 +188,10 @@ udp_input(m, off, proto)
}
uh = (struct udphdr *)((caddr_t)ip + iphlen);
+ /* destination port of 0 is illegal, based on RFC768. */
+ if (uh->uh_dport == 0)
+ goto bad;
+
/*
* Make mbuf data length reflect UDP length.
* If not enough data to reflect UDP length, drop.
@@ -407,7 +411,7 @@ bad:
return;
}
-#if defined(INET6)
+#ifdef INET6
static void
ip_2_ip6_hdr(ip6, ip)
struct ip6_hdr *ip6;
@@ -714,12 +718,10 @@ udp_output(inp, m, addr, control, p)
udpstat.udps_opackets++;
#ifdef IPSEC
- m->m_pkthdr.rcvif = (struct ifnet *)inp->inp_socket;
+ ipsec_setsocket(m, inp->inp_socket);
#endif /*IPSEC*/
-
error = ip_output(m, inp->inp_options, &inp->inp_route,
- (inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST))
- | IP_SOCKINMRCVIF,
+ (inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)),
inp->inp_moptions);
if (addr) {
OpenPOWER on IntegriCloud