summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2001-06-11 12:39:29 +0000
committerume <ume@FreeBSD.org>2001-06-11 12:39:29 +0000
commit832f8d224926758a9ae0b23a6b45353e44fbc87a (patch)
treea79fc7ad2b97862c4a404f352f0211ad93a7b5f1 /sys/netinet
parent2693854b01a52b0395a91322aa3edf926bddff38 (diff)
downloadFreeBSD-src-832f8d224926758a9ae0b23a6b45353e44fbc87a.zip
FreeBSD-src-832f8d224926758a9ae0b23a6b45353e44fbc87a.tar.gz
Sync with recent KAME.
This work was based on kame-20010528-freebsd43-snap.tgz and some critical problem after the snap was out were fixed. There are many many changes since last KAME merge. TODO: - The definitions of SADB_* in sys/net/pfkeyv2.h are still different from RFC2407/IANA assignment because of binary compatibility issue. It should be fixed under 5-CURRENT. - ip6po_m member of struct ip6_pktopts is no longer used. But, it is still there because of binary compatibility issue. It should be removed under 5-CURRENT. Reviewed by: itojun Obtained from: KAME MFC after: 3 weeks
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/icmp6.h117
-rw-r--r--sys/netinet/in.c23
-rw-r--r--sys/netinet/in_gif.c61
-rw-r--r--sys/netinet/in_pcb.c17
-rw-r--r--sys/netinet/in_pcb.h32
-rw-r--r--sys/netinet/in_proto.c27
-rw-r--r--sys/netinet/ip6.h36
-rw-r--r--sys/netinet/ip_ecn.c21
-rw-r--r--sys/netinet/ip_ecn.h10
-rw-r--r--sys/netinet/ip_encap.c14
-rw-r--r--sys/netinet/ip_icmp.c9
-rw-r--r--sys/netinet/ip_input.c66
-rw-r--r--sys/netinet/ip_output.c313
-rw-r--r--sys/netinet/ip_var.h4
-rw-r--r--sys/netinet/raw_ip.c29
-rw-r--r--sys/netinet/tcp_input.c109
-rw-r--r--sys/netinet/tcp_output.c8
-rw-r--r--sys/netinet/tcp_reass.c109
-rw-r--r--sys/netinet/tcp_subr.c65
-rw-r--r--sys/netinet/tcp_timewait.c65
-rw-r--r--sys/netinet/tcp_usrreq.c13
-rw-r--r--sys/netinet/udp_usrreq.c8
22 files changed, 697 insertions, 459 deletions
diff --git a/sys/netinet/icmp6.h b/sys/netinet/icmp6.h
index 3625ee4..425495d 100644
--- a/sys/netinet/icmp6.h
+++ b/sys/netinet/icmp6.h
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: icmp6.h,v 1.18 2000/07/03 02:51:08 itojun Exp $ */
+/* $KAME: icmp6.h,v 1.46 2001/04/27 15:09:48 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -80,7 +80,7 @@ struct icmp6_hdr {
u_int16_t icmp6_un_data16[2]; /* type-specific field */
u_int8_t icmp6_un_data8[4]; /* type-specific field */
} icmp6_dataun;
-};
+} __attribute__((__packed__));
#define icmp6_data32 icmp6_dataun.icmp6_un_data32
#define icmp6_data16 icmp6_dataun.icmp6_un_data16
@@ -124,7 +124,10 @@ struct icmp6_hdr {
#define MLD6_MTRACE_RESP 141 /* mtrace response(to sender) */
#define MLD6_MTRACE 142 /* mtrace messages */
-#define ICMP6_MAXTYPE 142
+#define ICMP6_HADISCOV_REQUEST 143 /* XXX To be defined */
+#define ICMP6_HADISCOV_REPLY 144 /* XXX To be defined */
+
+#define ICMP6_MAXTYPE 144
#define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */
#define ICMP6_DST_UNREACH_ADMIN 1 /* administratively prohibited */
@@ -146,7 +149,7 @@ struct icmp6_hdr {
#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_SUCCESS 0 /* node information successful reply */
#define ICMP6_NI_REFUSED 1 /* node information request is refused */
#define ICMP6_NI_UNKNOWN 2 /* unknown Qtype */
@@ -164,7 +167,7 @@ struct icmp6_hdr {
struct mld6_hdr {
struct icmp6_hdr mld6_hdr;
struct in6_addr mld6_addr; /* multicast address */
-};
+} __attribute__((__packed__));
#define mld6_type mld6_hdr.icmp6_type
#define mld6_code mld6_hdr.icmp6_code
@@ -179,7 +182,7 @@ struct mld6_hdr {
struct nd_router_solicit { /* router solicitation */
struct icmp6_hdr nd_rs_hdr;
/* could be followed by options */
-};
+} __attribute__((__packed__));
#define nd_rs_type nd_rs_hdr.icmp6_type
#define nd_rs_code nd_rs_hdr.icmp6_code
@@ -191,7 +194,7 @@ struct nd_router_advert { /* router advertisement */
u_int32_t nd_ra_reachable; /* reachable time */
u_int32_t nd_ra_retransmit; /* retransmit timer */
/* could be followed by options */
-};
+} __attribute__((__packed__));
#define nd_ra_type nd_ra_hdr.icmp6_type
#define nd_ra_code nd_ra_hdr.icmp6_code
@@ -200,13 +203,26 @@ struct nd_router_advert { /* router advertisement */
#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_FLAG_HA 0x20
+
+/*
+ * Router preference values based on draft-draves-ipngwg-router-selection-01.
+ * These are non-standard definitions.
+ */
+#define ND_RA_FLAG_RTPREF_MASK 0x18 /* 00011000 */
+
+#define ND_RA_FLAG_RTPREF_HIGH 0x08 /* 00001000 */
+#define ND_RA_FLAG_RTPREF_MEDIUM 0x00 /* 00000000 */
+#define ND_RA_FLAG_RTPREF_LOW 0x18 /* 00011000 */
+#define ND_RA_FLAG_RTPREF_RSV 0x10 /* 00010000 */
+
#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 */
-};
+} __attribute__((__packed__));
#define nd_ns_type nd_ns_hdr.icmp6_type
#define nd_ns_code nd_ns_hdr.icmp6_code
@@ -217,7 +233,7 @@ 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 */
-};
+} __attribute__((__packed__));
#define nd_na_type nd_na_hdr.icmp6_type
#define nd_na_code nd_na_hdr.icmp6_code
@@ -240,7 +256,7 @@ struct nd_redirect { /* redirect */
struct in6_addr nd_rd_target; /* target address */
struct in6_addr nd_rd_dst; /* destination address */
/* could be followed by options */
-};
+} __attribute__((__packed__));
#define nd_rd_type nd_rd_hdr.icmp6_type
#define nd_rd_code nd_rd_hdr.icmp6_code
@@ -251,13 +267,14 @@ 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*/
-};
+} __attribute__((__packed__));
#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
+#define ND_OPT_ROUTE_INFO 9 /* draft-draves-router-preference, not officially assigned yet */
struct nd_opt_prefix_info { /* prefix information */
u_int8_t nd_opt_pi_type;
@@ -268,7 +285,7 @@ struct nd_opt_prefix_info { /* prefix information */
u_int32_t nd_opt_pi_preferred_time;
u_int32_t nd_opt_pi_reserved2;
struct in6_addr nd_opt_pi_prefix;
-};
+} __attribute__((__packed__));
#define ND_OPT_PI_FLAG_ONLINK 0x80
#define ND_OPT_PI_FLAG_AUTO 0x40
@@ -279,15 +296,23 @@ struct nd_opt_rd_hdr { /* redirected header */
u_int16_t nd_opt_rh_reserved1;
u_int32_t nd_opt_rh_reserved2;
/* followed by IP header and data */
-};
+} __attribute__((__packed__));
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;
-};
-
+} __attribute__((__packed__));
+
+struct nd_opt_route_info { /* route info */
+ u_int8_t nd_opt_rti_type;
+ u_int8_t nd_opt_rti_len;
+ u_int8_t nd_opt_rti_prefixlen;
+ u_int8_t nd_opt_rti_flags;
+ u_int32_t nd_opt_rti_lifetime;
+ /* followed by prefix */
+} __attribute__((__packed__));
/*
* icmp6 namelookup
*/
@@ -301,7 +326,7 @@ struct icmp6_namelookup {
u_int8_t icmp6_nl_name[3];
#endif
/* could be followed by options */
-};
+} __attribute__((__packed__));
/*
* icmp6 node information
@@ -310,7 +335,7 @@ struct icmp6_nodeinfo {
struct icmp6_hdr icmp6_ni_hdr;
u_int8_t icmp6_ni_nonce[8];
/* could be followed by reply data */
-};
+} __attribute__((__packed__));
#define ni_type icmp6_ni_hdr.icmp6_type
#define ni_code icmp6_ni_hdr.icmp6_code
@@ -320,8 +345,10 @@ struct icmp6_nodeinfo {
#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... */
+#define NI_QTYPE_FQDN 2 /* FQDN (draft 04) */
+#define NI_QTYPE_DNSNAME 2 /* DNS Name */
+#define NI_QTYPE_NODEADDR 3 /* Node Addresses */
+#define NI_QTYPE_IPV4ADDR 4 /* IPv4 Addresses */
#if BYTE_ORDER == BIG_ENDIAN
#define NI_SUPTYPE_FLAG_COMPRESS 0x1
@@ -371,7 +398,7 @@ 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 */
-};
+} __attribute__((__packed__));
/*
* Router Renumbering. as router-renum-08.txt
@@ -382,13 +409,13 @@ struct icmp6_router_renum { /* router renumbering header */
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
+} __attribute__((__packed__));
+
+#define ICMP6_RR_FLAGS_TEST 0x80
+#define ICMP6_RR_FLAGS_REQRESULT 0x40
+#define ICMP6_RR_FLAGS_FORCEAPPLY 0x20
+#define ICMP6_RR_FLAGS_SPECSITE 0x10
+#define ICMP6_RR_FLAGS_PREVDONE 0x08
#define rr_type rr_hdr.icmp6_type
#define rr_code rr_hdr.icmp6_code
@@ -404,7 +431,7 @@ struct rr_pco_match { /* match prefix part */
u_int8_t rpm_maxlen;
u_int16_t rpm_reserved;
struct in6_addr rpm_prefix;
-};
+} __attribute__((__packed__));
#define RPM_PCO_ADD 1
#define RPM_PCO_CHANGE 2
@@ -420,7 +447,7 @@ struct rr_pco_use { /* use prefix part */
u_int32_t rpu_pltime;
u_int32_t rpu_flags;
struct in6_addr rpu_prefix;
-};
+} __attribute__((__packed__));
#define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK 0x80
#define ICMP6_RR_PCOUSE_RAFLAGS_AUTO 0x40
@@ -438,13 +465,13 @@ struct rr_result { /* router renumbering result message */
u_int8_t rrr_matchedlen;
u_int32_t rrr_ifid;
struct in6_addr rrr_prefix;
-};
+} __attribute__((__packed__));
#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
+#define ICMP6_RR_RESULT_FLAGS_OOB 0x0200
+#define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x0100
#endif
/*
@@ -534,6 +561,13 @@ struct icmp6stat {
#define icp6s_oparamprob_option icp6s_outerrhist.icp6errs_paramprob_option
#define icp6s_oredirect icp6s_outerrhist.icp6errs_redirect
#define icp6s_ounknown icp6s_outerrhist.icp6errs_unknown
+ u_quad_t icp6s_pmtuchg; /* path MTU changes */
+ u_quad_t icp6s_nd_badopt; /* bad ND options */
+ u_quad_t icp6s_badns; /* bad neighbor solicitation */
+ u_quad_t icp6s_badna; /* bad neighbor advertisement */
+ u_quad_t icp6s_badrs; /* bad router advertisement */
+ u_quad_t icp6s_badra; /* bad router advertisement */
+ u_quad_t icp6s_badredirect; /* bad redirect message */
};
/*
@@ -542,7 +576,9 @@ struct icmp6stat {
#define ICMPV6CTL_STATS 1
#define ICMPV6CTL_REDIRACCEPT 2 /* accept/process redirects */
#define ICMPV6CTL_REDIRTIMEOUT 3 /* redirect cache time */
+#if 0 /*obsoleted*/
#define ICMPV6CTL_ERRRATELIMIT 5 /* ICMPv6 error rate limitation */
+#endif
#define ICMPV6CTL_ND6_PRUNE 6
#define ICMPV6CTL_ND6_DELAY 8
#define ICMPV6CTL_ND6_UMAXTRIES 9
@@ -552,7 +588,12 @@ struct icmp6stat {
#define ICMPV6CTL_NODEINFO 13
#define ICMPV6CTL_ERRPPSLIMIT 14 /* ICMPv6 error pps limitation */
#define ICMPV6CTL_ND6_MAXNUDHINT 15
-#define ICMPV6CTL_MAXID 16
+#define ICMPV6CTL_MTUDISC_HIWAT 16
+#define ICMPV6CTL_MTUDISC_LOWAT 17
+#define ICMPV6CTL_ND6_DEBUG 18
+#define ICMPV6CTL_ND6_DRLIST 19
+#define ICMPV6CTL_ND6_PRLIST 20
+#define ICMPV6CTL_MAXID 21
#define ICMPV6CTL_NAMES { \
{ 0, 0 }, \
@@ -560,7 +601,7 @@ struct icmp6stat {
{ "rediraccept", CTLTYPE_INT }, \
{ "redirtimeout", CTLTYPE_INT }, \
{ 0, 0 }, \
- { "errratelimit", CTLTYPE_INT }, \
+ { 0, 0 }, \
{ "nd6_prune", CTLTYPE_INT }, \
{ 0, 0 }, \
{ "nd6_delay", CTLTYPE_INT }, \
@@ -571,6 +612,11 @@ struct icmp6stat {
{ "nodeinfo", CTLTYPE_INT }, \
{ "errppslimit", CTLTYPE_INT }, \
{ "nd6_maxnudhint", CTLTYPE_INT }, \
+ { "mtudisc_hiwat", CTLTYPE_INT }, \
+ { "mtudisc_lowat", CTLTYPE_INT }, \
+ { "nd6_debug", CTLTYPE_INT }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
}
#define RTF_PROBEMTU RTF_PROTO1
@@ -591,6 +637,9 @@ void icmp6_prepare __P((struct mbuf *));
void icmp6_redirect_input __P((struct mbuf *, int));
void icmp6_redirect_output __P((struct mbuf *, struct rtentry *));
+struct ip6ctlparam;
+void icmp6_mtudisc_update __P((struct ip6ctlparam *, int));
+
/* XXX: is this the right place for these macros? */
#define icmp6_ifstat_inc(ifp, tag) \
do { \
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 95abe3f..170a343 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -51,11 +51,6 @@
#include <netinet/igmp_var.h>
-#include "gif.h"
-#if NGIF > 0
-#include <net/if_gif.h>
-#endif
-
static MALLOC_DEFINE(M_IPMADDR, "in_multi", "internet multicast address");
static int in_mask2len __P((struct in_addr *));
@@ -200,21 +195,6 @@ in_control(so, cmd, data, ifp, p)
int error, hostIsNew, maskIsNew, s;
u_long i;
-#if NGIF > 0
- if (ifp && ifp->if_type == IFT_GIF) {
- switch (cmd) {
- case SIOCSIFPHYADDR:
- case SIOCDIFPHYADDR:
- if (p &&
- (error = suser(p)) != 0)
- return(error);
- case SIOCGIFPSRCADDR:
- case SIOCGIFPDSTADDR:
- return gif_ioctl(ifp, cmd, data);
- }
- }
-#endif
-
switch (cmd) {
case SIOCALIFADDR:
case SIOCDLIFADDR:
@@ -713,6 +693,9 @@ in_ifinit(ifp, ia, sin, scrub)
}
if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
ia->ia_flags |= IFA_ROUTE;
+ /* XXX check if the subnet route points to the same interface */
+ if (error == EEXIST)
+ error = 0;
/*
* If the interface supports multicast, join the "all hosts"
diff --git a/sys/netinet/in_gif.c b/sys/netinet/in_gif.c
index 17955ad..5ad92e1 100644
--- a/sys/netinet/in_gif.c
+++ b/sys/netinet/in_gif.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: in_gif.c,v 1.44 2000/08/15 07:24:24 itojun Exp $ */
+/* $KAME: in_gif.c,v 1.54 2001/05/14 14:02:16 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -88,7 +88,7 @@ in_gif_output(ifp, family, m, rt)
struct mbuf *m;
struct rtentry *rt;
{
- register struct gif_softc *sc = (struct gif_softc*)ifp;
+ struct gif_softc *sc = (struct gif_softc*)ifp;
struct sockaddr_in *dst = (struct sockaddr_in *)&sc->gif_ro.ro_dst;
struct sockaddr_in *sin_src = (struct sockaddr_in *)sc->gif_psrc;
struct sockaddr_in *sin_dst = (struct sockaddr_in *)sc->gif_pdst;
@@ -146,29 +146,12 @@ in_gif_output(ifp, family, m, rt)
bzero(&iphdr, sizeof(iphdr));
iphdr.ip_src = sin_src->sin_addr;
- 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 {
- m_freem(m);
- return ENETUNREACH;
- }
- } else {
- /* bidirectional configured tunnel mode */
- if (sin_dst->sin_addr.s_addr != INADDR_ANY)
- iphdr.ip_dst = sin_dst->sin_addr;
- else {
- m_freem(m);
- return ENETUNREACH;
- }
+ /* bidirectional configured tunnel mode */
+ if (sin_dst->sin_addr.s_addr != INADDR_ANY)
+ iphdr.ip_dst = sin_dst->sin_addr;
+ else {
+ m_freem(m);
+ return ENETUNREACH;
}
iphdr.ip_p = proto;
/* version will be set in ip_output() */
@@ -176,6 +159,8 @@ in_gif_output(ifp, family, m, rt)
iphdr.ip_len = m->m_pkthdr.len + sizeof(struct ip);
if (ifp->if_flags & IFF_LINK1)
ip_ecn_ingress(ECN_ALLOWED, &iphdr.ip_tos, &tos);
+ else
+ ip_ecn_ingress(ECN_NOCARE, &iphdr.ip_tos, &tos);
/* prepend new IP header */
M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
@@ -272,6 +257,8 @@ in_gif_input(m, va_alist)
ip = mtod(m, struct ip *);
if (gifp->if_flags & IFF_LINK1)
ip_ecn_egress(ECN_ALLOWED, &otos, &ip->ip_tos);
+ else
+ ip_ecn_egress(ECN_NOCARE, &otos, &ip->ip_tos);
break;
}
#endif
@@ -290,6 +277,8 @@ in_gif_input(m, va_alist)
itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
if (gifp->if_flags & IFF_LINK1)
ip_ecn_egress(ECN_ALLOWED, &otos, &itos);
+ else
+ ip_ecn_egress(ECN_NOCARE, &otos, &itos);
ip6->ip6_flow &= ~htonl(0xff << 20);
ip6->ip6_flow |= htonl((u_int32_t)itos << 20);
break;
@@ -335,10 +324,6 @@ gif_encapcheck4(m, off, proto, arg)
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;
@@ -359,7 +344,8 @@ gif_encapcheck4(m, off, proto, arg)
}
/* ingress filters on outer source */
- if ((m->m_flags & M_PKTHDR) != 0 && m->m_pkthdr.rcvif) {
+ if ((sc->gif_if.if_flags & IFF_LINK2) == 0 &&
+ (m->m_flags & M_PKTHDR) != 0 && m->m_pkthdr.rcvif) {
struct sockaddr_in sin;
struct rtentry *rt;
@@ -368,15 +354,18 @@ gif_encapcheck4(m, off, proto, arg)
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);
+ if (!rt || rt->rt_ifp != m->m_pkthdr.rcvif) {
+#if 0
+ log(LOG_WARNING, "%s: packet from 0x%x dropped "
+ "due to ingress filter\n", if_name(&sc->gif_if),
+ (u_int32_t)ntohl(sin.sin_addr.s_addr));
+#endif
+ if (rt)
+ rtfree(rt);
return 0;
}
rtfree(rt);
}
- /* prioritize: IFF_LINK0 mode is less preferred */
- return (sc->gif_if.if_flags & IFF_LINK0) ? 32 : 32 * 2;
+ return 32 * 2;
}
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index b24b404..ba5f77f 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -151,14 +151,16 @@ in_pcballoc(so, pcbinfo, p)
inp->inp_pcbinfo = pcbinfo;
inp->inp_socket = so;
#if defined(INET6)
- if (ip6_mapped_addr_on)
- inp->inp_flags &= ~IN6P_BINDV6ONLY;
- else
- inp->inp_flags |= IN6P_BINDV6ONLY;
+ if (INP_SOCKAF(so) == AF_INET6 && !ip6_mapped_addr_on)
+ inp->inp_flags |= IN6P_IPV6_V6ONLY;
#endif
LIST_INSERT_HEAD(pcbinfo->listhead, inp, inp_list);
pcbinfo->ipi_count++;
so->so_pcb = (caddr_t)inp;
+#ifdef INET6
+ if (ip6_auto_flowlabel)
+ inp->inp_flags |= IN6P_AUTOFLOWLABEL;
+#endif
return (0);
}
@@ -234,9 +236,7 @@ in_pcbbind(inp, nam, p)
(so->so_cred->cr_uid !=
t->inp_socket->so_cred->cr_uid)) {
#if defined(INET6)
- if ((inp->inp_flags &
- IN6P_BINDV6ONLY) != 0 ||
- ntohl(sin->sin_addr.s_addr) !=
+ if (ntohl(sin->sin_addr.s_addr) !=
INADDR_ANY ||
ntohl(t->inp_laddr.s_addr) !=
INADDR_ANY ||
@@ -254,8 +254,7 @@ in_pcbbind(inp, nam, p)
if (t &&
(reuseport & t->inp_socket->so_options) == 0) {
#if defined(INET6)
- if ((inp->inp_flags & IN6P_BINDV6ONLY) != 0 ||
- ntohl(sin->sin_addr.s_addr) !=
+ if (ntohl(sin->sin_addr.s_addr) !=
INADDR_ANY ||
ntohl(t->inp_laddr.s_addr) !=
INADDR_ANY ||
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index f4abb4d..1ae93d2 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -226,25 +226,27 @@ struct inpcbinfo { /* XXX documentation, prefixes */
#define INP_RECVIF 0x80 /* receive incoming interface */
#define INP_MTUDISC 0x100 /* user can do MTU discovery */
#define INP_FAITH 0x200 /* accept FAITH'ed connections */
-#define IN6P_PKTINFO 0x010000
-#define IN6P_HOPLIMIT 0x020000
-#define IN6P_NEXTHOP 0x040000
-#define IN6P_HOPOPTS 0x080000
-#define IN6P_DSTOPTS 0x100000
-#define IN6P_RTHDR 0x200000
-#define IN6P_BINDV6ONLY 0x400000
+
+#define IN6P_IPV6_V6ONLY 0x008000 /* restrict AF_INET6 socket for v6 */
+
+#define IN6P_PKTINFO 0x010000 /* receive IP6 dst and I/F */
+#define IN6P_HOPLIMIT 0x020000 /* receive hoplimit */
+#define IN6P_HOPOPTS 0x040000 /* receive hop-by-hop options */
+#define IN6P_DSTOPTS 0x080000 /* receive dst options after rthdr */
+#define IN6P_RTHDR 0x100000 /* receive routing header */
+#define IN6P_RTHDRDSTOPTS 0x200000 /* receive dstoptions before rthdr */
+#define IN6P_AUTOFLOWLABEL 0x800000 /* attach flowlabel automatically */
+#define IN6P_BINDV6ONLY 0x10000000 /* do not grab IPv4 traffic */
+
#define INP_CONTROLOPTS (INP_RECVOPTS|INP_RECVRETOPTS|INP_RECVDSTADDR|\
INP_RECVIF|\
- IN6P_PKTINFO|IN6P_HOPLIMIT|IN6P_NEXTHOP|\
- IN6P_HOPOPTS|IN6P_DSTOPTS|IN6P_RTHDR)
-
-#define INP_UNMAPPABLEOPTS (IN6P_HOPOPTS|IN6P_DSTOPTS|IN6P_RTHDR)
+ IN6P_PKTINFO|IN6P_HOPLIMIT|IN6P_HOPOPTS|\
+ IN6P_DSTOPTS|IN6P_RTHDR|IN6P_RTHDRDSTOPTS|\
+ IN6P_AUTOFLOWLABEL)
+#define INP_UNMAPPABLEOPTS (IN6P_HOPOPTS|IN6P_DSTOPTS|IN6P_RTHDR|\
+ IN6P_AUTOFLOWLABEL)
/* for KAME src sync over BSD*'s */
-#define IN6P_RECVOPTS INP_RECVOPTS
-#define IN6P_RECVRETOPTS INP_RECVRETOPTS
-#define IN6P_RECVDSTADDR INP_RECVDSTADDR
-#define IN6P_HDRINCL INP_HDRINCL
#define IN6P_HIGHPORT INP_HIGHPORT
#define IN6P_LOWPORT INP_LOWPORT
#define IN6P_ANONPORT INP_ANONPORT
diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c
index 02e6313..4c07a04 100644
--- a/sys/netinet/in_proto.c
+++ b/sys/netinet/in_proto.c
@@ -75,6 +75,7 @@
#ifdef IPSEC_ESP
#include <netinet6/esp.h>
#endif
+#include <netinet6/ipcomp.h>
#endif /* IPSEC */
#include "gif.h"
@@ -125,19 +126,19 @@ struct ipprotosw inetsw[] = {
0, 0, 0, 0,
&rip_usrreqs
},
-{ SOCK_RAW, &inetdomain, IPPROTO_ICMP, PR_ATOMIC|PR_ADDR,
+{ SOCK_RAW, &inetdomain, IPPROTO_ICMP, PR_ATOMIC|PR_ADDR|PR_LASTHDR,
icmp_input, 0, 0, rip_ctloutput,
0,
0, 0, 0, 0,
&rip_usrreqs
},
-{ SOCK_RAW, &inetdomain, IPPROTO_IGMP, PR_ATOMIC|PR_ADDR,
+{ SOCK_RAW, &inetdomain, IPPROTO_IGMP, PR_ATOMIC|PR_ADDR|PR_LASTHDR,
igmp_input, 0, 0, rip_ctloutput,
0,
igmp_init, igmp_fasttimo, igmp_slowtimo, 0,
&rip_usrreqs
},
-{ SOCK_RAW, &inetdomain, IPPROTO_RSVP, PR_ATOMIC|PR_ADDR,
+{ SOCK_RAW, &inetdomain, IPPROTO_RSVP, PR_ATOMIC|PR_ADDR|PR_LASTHDR,
rsvp_input, 0, 0, rip_ctloutput,
0,
0, 0, 0, 0,
@@ -158,19 +159,25 @@ struct ipprotosw inetsw[] = {
&nousrreqs
},
#endif
+{ SOCK_RAW, &inetdomain, IPPROTO_IPCOMP, PR_ATOMIC|PR_ADDR,
+ ipcomp4_input, 0, 0, 0,
+ 0,
+ 0, 0, 0, 0,
+ &nousrreqs
+},
#endif /* IPSEC */
-{ SOCK_RAW, &inetdomain, IPPROTO_IPV4, PR_ATOMIC|PR_ADDR,
+{ SOCK_RAW, &inetdomain, IPPROTO_IPV4, PR_ATOMIC|PR_ADDR|PR_LASTHDR,
encap4_input, 0, 0, rip_ctloutput,
0,
encap_init, 0, 0, 0,
- &nousrreqs
+ &rip_usrreqs
},
# ifdef INET6
-{ SOCK_RAW, &inetdomain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR,
+{ SOCK_RAW, &inetdomain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR|PR_LASTHDR,
encap4_input, 0, 0, rip_ctloutput,
0,
- 0, 0, 0, 0,
- &nousrreqs
+ encap_init, 0, 0, 0,
+ &rip_usrreqs
},
#endif
#ifdef IPDIVERT
@@ -182,7 +189,7 @@ struct ipprotosw inetsw[] = {
},
#endif
#ifdef IPXIP
-{ SOCK_RAW, &inetdomain, IPPROTO_IDP, PR_ATOMIC|PR_ADDR,
+{ SOCK_RAW, &inetdomain, IPPROTO_IDP, PR_ATOMIC|PR_ADDR|PR_LASTHDR,
ipxip_input, 0, ipxip_ctlinput, 0,
0,
0, 0, 0, 0,
@@ -190,7 +197,7 @@ struct ipprotosw inetsw[] = {
},
#endif
#ifdef NSIP
-{ SOCK_RAW, &inetdomain, IPPROTO_IDP, PR_ATOMIC|PR_ADDR,
+{ SOCK_RAW, &inetdomain, IPPROTO_IDP, PR_ATOMIC|PR_ADDR|PR_LASTHDR,
idpip_input, 0, nsip_ctlinput, 0,
0,
0, 0, 0, 0,
diff --git a/sys/netinet/ip6.h b/sys/netinet/ip6.h
index 77d1ab6..ec2c216 100644
--- a/sys/netinet/ip6.h
+++ b/sys/netinet/ip6.h
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: ip6.h,v 1.9 2000/07/02 21:01:32 itojun Exp $ */
+/* $KAME: ip6.h,v 1.18 2001/03/29 05:34:30 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -85,7 +85,7 @@ struct ip6_hdr {
} ip6_ctlun;
struct in6_addr ip6_src; /* source address */
struct in6_addr ip6_dst; /* destination address */
-};
+} __attribute__((__packed__));
#define ip6_vfc ip6_ctlun.ip6_un2_vfc
#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
@@ -106,18 +106,20 @@ struct ip6_hdr {
#define IPV6_FLOWLABEL_MASK 0xffff0f00 /* flow label (20 bits) */
#endif /* LITTLE_ENDIAN */
#endif
+#if 1
/* ECN bits proposed by Sally Floyd */
#define IP6TOS_CE 0x01 /* congestion experienced */
#define IP6TOS_ECT 0x02 /* ECN-capable transport */
+#endif
/*
* Extension Headers
*/
struct ip6_ext {
- u_char ip6e_nxt;
- u_char ip6e_len;
-};
+ u_int8_t ip6e_nxt;
+ u_int8_t ip6e_len;
+} __attribute__((__packed__));
/* Hop-by-Hop options header */
/* XXX should we pad it to force alignment on an 8-byte boundary? */
@@ -125,7 +127,7 @@ struct ip6_hbh {
u_int8_t ip6h_nxt; /* next header */
u_int8_t ip6h_len; /* length in units of 8 octets */
/* followed by options */
-};
+} __attribute__((__packed__));
/* Destination options header */
/* XXX should we pad it to force alignment on an 8-byte boundary? */
@@ -133,20 +135,28 @@ struct ip6_dest {
u_int8_t ip6d_nxt; /* next header */
u_int8_t ip6d_len; /* length in units of 8 octets */
/* followed by options */
-};
+} __attribute__((__packed__));
/* 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_NSAP_ADDR 0xC3 /* 11 0 00011 */
+#define IP6OPT_TUNNEL_LIMIT 0x04 /* 00 0 00100 */
+#define IP6OPT_RTALERT 0x05 /* 00 0 00101 (KAME definition) */
+
#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_BINDING_UPDATE 0xc6 /* 11 0 00110 */
+#define IP6OPT_BINDING_ACK 0x07 /* 00 0 00111 */
+#define IP6OPT_BINDING_REQ 0x08 /* 00 0 01000 */
+#define IP6OPT_HOME_ADDRESS 0xc9 /* 11 0 01001 */
+#define IP6OPT_EID 0x8a /* 10 0 01010 */
+
#define IP6OPT_TYPE(o) ((o) & 0xC0)
#define IP6OPT_TYPE_SKIP 0x00
#define IP6OPT_TYPE_DISCARD 0x40
@@ -155,6 +165,8 @@ struct ip6_dest {
#define IP6OPT_MUTABLE 0x20
+#define IP6OPT_JUMBO_LEN 6
+
/* Routing header */
struct ip6_rthdr {
u_int8_t ip6r_nxt; /* next header */
@@ -162,7 +174,7 @@ struct ip6_rthdr {
u_int8_t ip6r_type; /* routing type */
u_int8_t ip6r_segleft; /* segments left */
/* followed by routing type specific data */
-};
+} __attribute__((__packed__));
/* Type 0 Routing header */
struct ip6_rthdr0 {
@@ -173,7 +185,7 @@ struct ip6_rthdr0 {
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 */
-};
+} __attribute__((__packed__));
/* Fragment header */
struct ip6_frag {
@@ -181,7 +193,7 @@ struct ip6_frag {
u_int8_t ip6f_reserved; /* reserved field */
u_int16_t ip6f_offlg; /* offset, reserved, and flag */
u_int32_t ip6f_ident; /* identification */
-};
+} __attribute__((__packed__));
#if BYTE_ORDER == BIG_ENDIAN
#define IP6F_OFF_MASK 0xfff8 /* mask out offset from _offlg */
diff --git a/sys/netinet/ip_ecn.c b/sys/netinet/ip_ecn.c
index 047f82e..3abc3b6 100644
--- a/sys/netinet/ip_ecn.c
+++ b/sys/netinet/ip_ecn.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: ip_ecn.c,v 1.7 2000/05/05 11:00:56 sumikawa Exp $ */
+/* $KAME: ip_ecn.c,v 1.11 2001/05/03 16:09:29 itojun Exp $ */
/*
* Copyright (C) 1999 WIDE Project.
@@ -43,16 +43,10 @@
#include <sys/mbuf.h>
#include <sys/errno.h>
-#ifdef INET
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
-#endif
-
#ifdef INET6
-#ifndef INET
-#include <netinet/in.h>
-#endif
#include <netinet/ip6.h>
#endif
@@ -63,17 +57,17 @@
/*
* modify outer ECN (TOS) field on ingress operation (tunnel encapsulation).
- * call it after you've done the default initialization/copy for the outer.
*/
void
ip_ecn_ingress(mode, outer, inner)
int mode;
u_int8_t *outer;
- u_int8_t *inner;
+ const u_int8_t *inner;
{
if (!outer || !inner)
panic("NULL pointer passed to ip_ecn_ingress");
+ *outer = *inner;
switch (mode) {
case ECN_ALLOWED: /* ECN allowed */
*outer &= ~IPTOS_CE;
@@ -88,12 +82,11 @@ ip_ecn_ingress(mode, outer, inner)
/*
* modify inner ECN (TOS) field on egress operation (tunnel decapsulation).
- * call it after you've done the default initialization/copy for the inner.
*/
void
ip_ecn_egress(mode, outer, inner)
int mode;
- u_int8_t *outer;
+ const u_int8_t *outer;
u_int8_t *inner;
{
if (!outer || !inner)
@@ -115,14 +108,13 @@ void
ip6_ecn_ingress(mode, outer, inner)
int mode;
u_int32_t *outer;
- u_int32_t *inner;
+ const u_int32_t *inner;
{
u_int8_t outer8, inner8;
if (!outer || !inner)
panic("NULL pointer passed to ip6_ecn_ingress");
- outer8 = (ntohl(*outer) >> 20) & 0xff;
inner8 = (ntohl(*inner) >> 20) & 0xff;
ip_ecn_ingress(mode, &outer8, &inner8);
*outer &= ~htonl(0xff << 20);
@@ -132,7 +124,7 @@ ip6_ecn_ingress(mode, outer, inner)
void
ip6_ecn_egress(mode, outer, inner)
int mode;
- u_int32_t *outer;
+ const u_int32_t *outer;
u_int32_t *inner;
{
u_int8_t outer8, inner8;
@@ -141,7 +133,6 @@ ip6_ecn_egress(mode, outer, inner)
panic("NULL pointer passed to ip6_ecn_egress");
outer8 = (ntohl(*outer) >> 20) & 0xff;
- inner8 = (ntohl(*inner) >> 20) & 0xff;
ip_ecn_egress(mode, &outer8, &inner8);
*inner &= ~htonl(0xff << 20);
*inner |= htonl((u_int32_t)inner8 << 20);
diff --git a/sys/netinet/ip_ecn.h b/sys/netinet/ip_ecn.h
index 6445d0f..9aca731 100644
--- a/sys/netinet/ip_ecn.h
+++ b/sys/netinet/ip_ecn.h
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: ip_ecn.h,v 1.5 2000/03/27 04:58:38 sumikawa Exp $ */
+/* $KAME: ip_ecn.h,v 1.6 2001/05/03 14:51:48 itojun Exp $ */
/*
* Copyright (C) 1999 WIDE Project.
@@ -35,11 +35,15 @@
* http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt
*/
+#if defined(_KERNEL) && !defined(_LKM)
+#include "opt_inet.h"
+#endif
+
#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 *));
-extern void ip_ecn_egress __P((int, u_int8_t *, u_int8_t *));
+extern void ip_ecn_ingress __P((int, u_int8_t *, const u_int8_t *));
+extern void ip_ecn_egress __P((int, const u_int8_t *, u_int8_t *));
#endif
diff --git a/sys/netinet/ip_encap.c b/sys/netinet/ip_encap.c
index 7d623ea..7463300 100644
--- a/sys/netinet/ip_encap.c
+++ b/sys/netinet/ip_encap.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: ip_encap.c,v 1.36 2000/06/17 20:34:24 itojun Exp $ */
+/* $KAME: ip_encap.c,v 1.41 2001/03/15 08:35:08 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -67,6 +67,7 @@
#include <sys/mbuf.h>
#include <sys/errno.h>
#include <sys/protosw.h>
+#include <sys/queue.h>
#include <net/if.h>
#include <net/route.h>
@@ -100,12 +101,21 @@ static int mask_match __P((const struct encaptab *, const struct sockaddr *,
const struct sockaddr *));
static void encap_fillarg __P((struct mbuf *, const struct encaptab *));
+#ifndef LIST_HEAD_INITIALIZER
/* rely upon BSS initialization */
LIST_HEAD(, encaptab) encaptab;
+#else
+LIST_HEAD(, encaptab) encaptab = LIST_HEAD_INITIALIZER(&encaptab);
+#endif
void
encap_init()
{
+ static int initialized = 0;
+
+ if (initialized)
+ return;
+ initialized++;
#if 0
/*
* we cannot use LIST_INIT() here, since drivers may want to call
@@ -118,6 +128,7 @@ encap_init()
#endif
}
+#ifdef INET
void
#if __STDC__
encap4_input(struct mbuf *m, ...)
@@ -221,6 +232,7 @@ encap4_input(m, va_alist)
/* last resort: inject to raw socket */
rip_input(m, off, proto);
}
+#endif
#ifdef INET6
int
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c
index ddb95f0..7e8c722 100644
--- a/sys/netinet/ip_icmp.c
+++ b/sys/netinet/ip_icmp.c
@@ -296,15 +296,6 @@ icmp_input(m, off, proto)
icp->icmp_code);
#endif
-#ifdef IPSEC
- /* drop it if it does not match the policy */
- /* XXX Is there meaning of check in here ? */
- if (ipsec4_in_reject(m, NULL)) {
- ipsecstat.in_polvio++;
- goto freeit;
- }
-#endif
-
/*
* Message type specific processing.
*/
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 7cd8568..3cf13cf 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -350,6 +350,16 @@ ip_input(struct mbuf *m)
}
ip = mtod(m, struct ip *);
}
+
+ /* 127/8 must not appear on wire - RFC1122 */
+ if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
+ (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
+ if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
+ ipstat.ips_badaddr++;
+ goto bad;
+ }
+ }
+
if (m->m_pkthdr.csum_flags & CSUM_IP_CHECKED) {
sum = !(m->m_pkthdr.csum_flags & CSUM_IP_VALID);
} else {
@@ -393,15 +403,10 @@ tooshort:
m_adj(m, ip->ip_len - m->m_pkthdr.len);
}
- /*
- * Don't accept packets with a loopback destination address
- * unless they arrived via the loopback interface.
- */
- if ((ntohl(ip->ip_dst.s_addr) & IN_CLASSA_NET) ==
- (IN_LOOPBACKNET << IN_CLASSA_NSHIFT) &&
- (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
- goto bad;
- }
+#ifdef IPSEC
+ if (ipsec_gethist(m, NULL))
+ goto pass;
+#endif
/*
* IpHack's section.
@@ -796,6 +801,19 @@ found:
}
#endif
+#ifdef IPSEC
+ /*
+ * enforce IPsec policy checking if we are seeing last header.
+ * note that we do not visit this with protocols with pcb layer
+ * code - like udp/tcp/raw ip.
+ */
+ if ((inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0 &&
+ ipsec4_in_reject(m, NULL)) {
+ ipsecstat.in_polvio++;
+ goto bad;
+ }
+#endif
+
/*
* Switch out to protocol's input routine.
*/
@@ -1189,6 +1207,10 @@ ip_dooptions(m)
*/
case IPOPT_LSRR:
case IPOPT_SSRR:
+ if (optlen < IPOPT_OFFSET + sizeof(*cp)) {
+ code = &cp[IPOPT_OLEN] - (u_char *)ip;
+ goto bad;
+ }
if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
code = &cp[IPOPT_OFFSET] - (u_char *)ip;
goto bad;
@@ -1308,12 +1330,21 @@ nosourcerouting:
case IPOPT_TS:
code = cp - (u_char *)ip;
ipt = (struct ip_timestamp *)cp;
- if (ipt->ipt_len < 5)
+ if (ipt->ipt_len < 4 || ipt->ipt_len > 40) {
+ code = (u_char *)&ipt->ipt_len - (u_char *)ip;
goto bad;
+ }
+ if (ipt->ipt_ptr < 5) {
+ code = (u_char *)&ipt->ipt_ptr - (u_char *)ip;
+ goto bad;
+ }
if (ipt->ipt_ptr >
ipt->ipt_len - (int)sizeof(int32_t)) {
- if (++ipt->ipt_oflw == 0)
+ if (++ipt->ipt_oflw == 0) {
+ code = (u_char *)&ipt->ipt_ptr -
+ (u_char *)ip;
goto bad;
+ }
break;
}
sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);
@@ -1324,8 +1355,11 @@ nosourcerouting:
case IPOPT_TS_TSANDADDR:
if (ipt->ipt_ptr - 1 + sizeof(n_time) +
- sizeof(struct in_addr) > ipt->ipt_len)
+ sizeof(struct in_addr) > ipt->ipt_len) {
+ code = (u_char *)&ipt->ipt_ptr -
+ (u_char *)ip;
goto bad;
+ }
ipaddr.sin_addr = dst;
ia = (INA)ifaof_ifpforaddr((SA)&ipaddr,
m->m_pkthdr.rcvif);
@@ -1338,8 +1372,11 @@ nosourcerouting:
case IPOPT_TS_PRESPEC:
if (ipt->ipt_ptr - 1 + sizeof(n_time) +
- sizeof(struct in_addr) > ipt->ipt_len)
+ sizeof(struct in_addr) > ipt->ipt_len) {
+ code = (u_char *)&ipt->ipt_ptr -
+ (u_char *)ip;
goto bad;
+ }
(void)memcpy(&ipaddr.sin_addr, sin,
sizeof(struct in_addr));
if (ifa_ifwithaddr((SA)&ipaddr) == 0)
@@ -1348,6 +1385,9 @@ nosourcerouting:
break;
default:
+ /* XXX can't take &ipt->ipt_flg */
+ code = (u_char *)&ipt->ipt_ptr -
+ (u_char *)ip + 1;
goto bad;
}
ntime = iptime();
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 1025e37..10de694 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -95,6 +95,7 @@ static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options");
u_short ip_id;
static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *));
+static struct ifnet *ip_multicast_if __P((struct in_addr *, int *));
static void ip_mloopback
__P((struct ifnet *, struct mbuf *, struct sockaddr_in *, int));
static int ip_getmoptions
@@ -177,7 +178,7 @@ ip_output(m0, opt, ro, flags, imo)
m0 = m = m->m_next ;
#ifdef IPSEC
so = ipsec_getsocket(m);
- ipsec_setsocket(m, NULL);
+ (void)ipsec_setsocket(m, NULL);
#endif
ip = mtod(m, struct ip *);
hlen = IP_VHL_HL(ip->ip_vhl) << 2 ;
@@ -188,7 +189,7 @@ ip_output(m0, opt, ro, flags, imo)
#endif
#ifdef IPSEC
so = ipsec_getsocket(m);
- ipsec_setsocket(m, NULL);
+ (void)ipsec_setsocket(m, NULL);
#endif
#ifdef DIAGNOSTIC
@@ -430,6 +431,133 @@ ip_output(m0, opt, ro, flags, imo)
}
sendit:
+#ifdef IPSEC
+ /* get SP for this packet */
+ if (so == NULL)
+ sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, flags, &error);
+ else
+ sp = ipsec4_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error);
+
+ if (sp == NULL) {
+ ipsecstat.out_inval++;
+ goto bad;
+ }
+
+ error = 0;
+
+ /* check policy */
+ switch (sp->policy) {
+ case IPSEC_POLICY_DISCARD:
+ /*
+ * This packet is just discarded.
+ */
+ ipsecstat.out_polvio++;
+ goto bad;
+
+ case IPSEC_POLICY_BYPASS:
+ case IPSEC_POLICY_NONE:
+ /* no need to do IPsec. */
+ goto skip_ipsec;
+
+ case IPSEC_POLICY_IPSEC:
+ if (sp->req == NULL) {
+ /* acquire a policy */
+ error = key_spdacquire(sp);
+ goto bad;
+ }
+ break;
+
+ case IPSEC_POLICY_ENTRUST:
+ default:
+ printf("ip_output: Invalid policy found. %d\n", sp->policy);
+ }
+ {
+ struct ipsec_output_state state;
+ bzero(&state, sizeof(state));
+ state.m = m;
+ if (flags & IP_ROUTETOIF) {
+ state.ro = &iproute;
+ bzero(&iproute, sizeof(iproute));
+ } else
+ state.ro = ro;
+ state.dst = (struct sockaddr *)dst;
+
+ ip->ip_sum = 0;
+
+ /*
+ * XXX
+ * delayed checksums are not currently compatible with IPsec
+ */
+ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+ in_delayed_cksum(m);
+ m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
+ }
+
+ HTONS(ip->ip_len);
+ HTONS(ip->ip_off);
+
+ error = ipsec4_output(&state, sp, flags);
+
+ m = state.m;
+ if (flags & IP_ROUTETOIF) {
+ /*
+ * if we have tunnel mode SA, we may need to ignore
+ * IP_ROUTETOIF.
+ */
+ if (state.ro != &iproute || state.ro->ro_rt != NULL) {
+ flags &= ~IP_ROUTETOIF;
+ ro = state.ro;
+ }
+ } else
+ ro = state.ro;
+ dst = (struct sockaddr_in *)state.dst;
+ if (error) {
+ /* mbuf is already reclaimed in ipsec4_output. */
+ m0 = NULL;
+ switch (error) {
+ case EHOSTUNREACH:
+ case ENETUNREACH:
+ case EMSGSIZE:
+ case ENOBUFS:
+ case ENOMEM:
+ break;
+ default:
+ printf("ip4_output (ipsec): error code %d\n", error);
+ /*fall through*/
+ case ENOENT:
+ /* don't show these error codes to the user */
+ error = 0;
+ break;
+ }
+ goto bad;
+ }
+ }
+
+ /* be sure to update variables that are affected by ipsec4_output() */
+ ip = mtod(m, struct ip *);
+#ifdef _IP_VHL
+ hlen = IP_VHL_HL(ip->ip_vhl) << 2;
+#else
+ hlen = ip->ip_hl << 2;
+#endif
+ if (ro->ro_rt == NULL) {
+ if ((flags & IP_ROUTETOIF) == 0) {
+ printf("ip_output: "
+ "can't update route after IPsec processing\n");
+ error = EHOSTUNREACH; /*XXX*/
+ goto bad;
+ }
+ } else {
+ ia = ifatoia(ro->ro_rt->rt_ifa);
+ ifp = ro->ro_rt->rt_ifp;
+ }
+
+ /* make it flipped, again. */
+ NTOHS(ip->ip_len);
+ NTOHS(ip->ip_off);
+skip_ipsec:
+#endif /*IPSEC*/
+
/*
* IpHack's section.
* - Xlate: translate packet's addr/port (NAT).
@@ -661,134 +789,6 @@ sendit:
}
pass:
-#ifdef IPSEC
- /* get SP for this packet */
- if (so == NULL)
- sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, flags, &error);
- else
- sp = ipsec4_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error);
-
- if (sp == NULL) {
- ipsecstat.out_inval++;
- goto bad;
- }
-
- error = 0;
-
- /* check policy */
- switch (sp->policy) {
- case IPSEC_POLICY_DISCARD:
- /*
- * This packet is just discarded.
- */
- ipsecstat.out_polvio++;
- goto bad;
-
- case IPSEC_POLICY_BYPASS:
- case IPSEC_POLICY_NONE:
- /* no need to do IPsec. */
- goto skip_ipsec;
-
- case IPSEC_POLICY_IPSEC:
- if (sp->req == NULL) {
- /* XXX should be panic ? */
- printf("ip_output: No IPsec request specified.\n");
- error = EINVAL;
- goto bad;
- }
- break;
-
- case IPSEC_POLICY_ENTRUST:
- default:
- printf("ip_output: Invalid policy found. %d\n", sp->policy);
- }
- {
- struct ipsec_output_state state;
- bzero(&state, sizeof(state));
- state.m = m;
- if (flags & IP_ROUTETOIF) {
- state.ro = &iproute;
- bzero(&iproute, sizeof(iproute));
- } else
- state.ro = ro;
- state.dst = (struct sockaddr *)dst;
-
- ip->ip_sum = 0;
-
- /*
- * XXX
- * delayed checksums are not currently compatible with IPsec
- */
- if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
- in_delayed_cksum(m);
- m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
- }
-
- HTONS(ip->ip_len);
- HTONS(ip->ip_off);
-
- error = ipsec4_output(&state, sp, flags);
-
- m = state.m;
- if (flags & IP_ROUTETOIF) {
- /*
- * if we have tunnel mode SA, we may need to ignore
- * IP_ROUTETOIF.
- */
- if (state.ro != &iproute || state.ro->ro_rt != NULL) {
- flags &= ~IP_ROUTETOIF;
- ro = state.ro;
- }
- } else
- ro = state.ro;
- dst = (struct sockaddr_in *)state.dst;
- if (error) {
- /* mbuf is already reclaimed in ipsec4_output. */
- m0 = NULL;
- switch (error) {
- case EHOSTUNREACH:
- case ENETUNREACH:
- case EMSGSIZE:
- case ENOBUFS:
- case ENOMEM:
- break;
- default:
- printf("ip4_output (ipsec): error code %d\n", error);
- /*fall through*/
- case ENOENT:
- /* don't show these error codes to the user */
- error = 0;
- break;
- }
- goto bad;
- }
- }
-
- /* be sure to update variables that are affected by ipsec4_output() */
- ip = mtod(m, struct ip *);
-#ifdef _IP_VHL
- hlen = IP_VHL_HL(ip->ip_vhl) << 2;
-#else
- hlen = ip->ip_hl << 2;
-#endif
- if (ro->ro_rt == NULL) {
- if ((flags & IP_ROUTETOIF) == 0) {
- printf("ip_output: "
- "can't update route after IPsec processing\n");
- error = EHOSTUNREACH; /*XXX*/
- goto bad;
- }
- } else {
- ia = ifatoia(ro->ro_rt->rt_ifa);
- ifp = ro->ro_rt->rt_ifp;
- }
-
- /* make it flipped, again. */
- NTOHS(ip->ip_len);
- NTOHS(ip->ip_off);
-skip_ipsec:
-#endif /*IPSEC*/
-
m->m_pkthdr.csum_flags |= CSUM_IP;
sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_hwassist;
if (sw_csum & CSUM_DELAY_DATA) {
@@ -820,6 +820,11 @@ skip_ipsec:
ia->ia_ifa.if_obytes += m->m_pkthdr.len;
}
+#ifdef IPSEC
+ /* clean ipsec history once it goes out of the node */
+ ipsec_delaux(m);
+#endif
+
error = (*ifp->if_output)(ifp, m,
(struct sockaddr *)dst, ro->ro_rt);
goto done;
@@ -946,6 +951,10 @@ sendorfree:
for (m = m0; m; m = m0) {
m0 = m->m_nextpkt;
m->m_nextpkt = 0;
+#ifdef IPSEC
+ /* clean ipsec history once it goes out of the node */
+ ipsec_delaux(m);
+#endif
if (error == 0) {
/* Record statistics for this interface address. */
ia->ia_ifa.if_opackets++;
@@ -1480,6 +1489,33 @@ bad:
* transmission, and one (IP_MULTICAST_TTL) totally duplicates a
* standard option (IP_TTL).
*/
+
+/*
+ * following RFC1724 section 3.3, 0.0.0.0/8 is interpreted as interface index.
+ */
+static struct ifnet *
+ip_multicast_if(a, ifindexp)
+ struct in_addr *a;
+ int *ifindexp;
+{
+ int ifindex;
+ struct ifnet *ifp;
+
+ if (ifindexp)
+ *ifindexp = 0;
+ if (ntohl(a->s_addr) >> 24 == 0) {
+ ifindex = ntohl(a->s_addr) & 0xffffff;
+ if (ifindex < 0 || if_index < ifindex)
+ return NULL;
+ ifp = ifindex2ifnet[ifindex];
+ if (ifindexp)
+ *ifindexp = ifindex;
+ } else {
+ INADDR_TO_IFP(*a, ifp);
+ }
+ return ifp;
+}
+
/*
* Set the IP multicast options in response to user setsockopt().
*/
@@ -1496,6 +1532,7 @@ ip_setmoptions(sopt, imop)
struct ip_moptions *imo = *imop;
struct route ro;
struct sockaddr_in *dst;
+ int ifindex;
int s;
if (imo == NULL) {
@@ -1510,6 +1547,7 @@ ip_setmoptions(sopt, imop)
return (ENOBUFS);
*imop = imo;
imo->imo_multicast_ifp = NULL;
+ imo->imo_multicast_addr.s_addr = INADDR_ANY;
imo->imo_multicast_vif = -1;
imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
@@ -1555,13 +1593,17 @@ ip_setmoptions(sopt, imop)
* it supports multicasting.
*/
s = splimp();
- INADDR_TO_IFP(addr, ifp);
+ ifp = ip_multicast_if(&addr, &ifindex);
if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
splx(s);
error = EADDRNOTAVAIL;
break;
}
imo->imo_multicast_ifp = ifp;
+ if (ifindex)
+ imo->imo_multicast_addr = addr;
+ else
+ imo->imo_multicast_addr.s_addr = INADDR_ANY;
splx(s);
break;
@@ -1648,7 +1690,7 @@ ip_setmoptions(sopt, imop)
rtfree(ro.ro_rt);
}
else {
- INADDR_TO_IFP(mreq.imr_interface, ifp);
+ ifp = ip_multicast_if(&mreq.imr_interface, NULL);
}
/*
@@ -1716,7 +1758,7 @@ ip_setmoptions(sopt, imop)
if (mreq.imr_interface.s_addr == INADDR_ANY)
ifp = NULL;
else {
- INADDR_TO_IFP(mreq.imr_interface, ifp);
+ ifp = ip_multicast_if(&mreq.imr_interface, NULL);
if (ifp == NULL) {
error = EADDRNOTAVAIL;
splx(s);
@@ -1798,7 +1840,10 @@ ip_getmoptions(sopt, imo)
case IP_MULTICAST_IF:
if (imo == NULL || imo->imo_multicast_ifp == NULL)
addr.s_addr = INADDR_ANY;
- else {
+ else if (imo->imo_multicast_addr.s_addr) {
+ /* return the value user has set */
+ addr = imo->imo_multicast_addr;
+ } else {
IFP_TO_IA(imo->imo_multicast_ifp, ia);
addr.s_addr = (ia == NULL) ? INADDR_ANY
: IA_SIN(ia)->sin_addr.s_addr;
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index 6354d84..b318a1c 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -37,6 +37,8 @@
#ifndef _NETINET_IP_VAR_H_
#define _NETINET_IP_VAR_H_
+#include <sys/queue.h>
+
/*
* Overlay for ip header used by other protocols (tcp, udp).
*/
@@ -86,6 +88,7 @@ struct ipoption {
*/
struct ip_moptions {
struct ifnet *imo_multicast_ifp; /* ifp for outgoing multicasts */
+ struct in_addr imo_multicast_addr; /* ifindex/addr on MULTICAST_IF */
u_char imo_multicast_ttl; /* TTL for outgoing multicasts */
u_char imo_multicast_loop; /* 1 => hear sends if a member */
u_short imo_num_memberships; /* no. memberships this socket */
@@ -122,6 +125,7 @@ struct ipstat {
u_long ips_toolong; /* ip length > max ip packet size */
u_long ips_notmember; /* multicasts for unregistered grps */
u_long ips_nogif; /* no match gif found */
+ u_long ips_badaddr; /* invalid address on header */
};
#ifdef _KERNEL
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index 4fdcf95..32c909a 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -137,6 +137,15 @@ rip_input(m, off, proto)
continue;
if (last) {
struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
+
+#ifdef IPSEC
+ /* check AH/ESP integrity. */
+ if (n && ipsec4_in_reject_so(n, last->inp_socket)) {
+ m_freem(n);
+ ipsecstat.in_polvio++;
+ /* do not inject data to pcb */
+ } else
+#endif /*IPSEC*/
if (n) {
if (last->inp_flags & INP_CONTROLOPTS ||
last->inp_socket->so_options & SO_TIMESTAMP)
@@ -155,6 +164,15 @@ rip_input(m, off, proto)
}
last = inp;
}
+#ifdef IPSEC
+ /* check AH/ESP integrity. */
+ if (last && ipsec4_in_reject_so(m, last->inp_socket)) {
+ m_freem(m);
+ ipsecstat.in_polvio++;
+ ipstat.ips_delivered--;
+ /* do not inject data to pcb */
+ } else
+#endif /*IPSEC*/
if (last) {
if (last->inp_flags & INP_CONTROLOPTS ||
last->inp_socket->so_options & SO_TIMESTAMP)
@@ -168,9 +186,9 @@ rip_input(m, off, proto)
sorwakeup(last->inp_socket);
} else {
m_freem(m);
- ipstat.ips_noproto++;
- ipstat.ips_delivered--;
- }
+ ipstat.ips_noproto++;
+ ipstat.ips_delivered--;
+ }
}
/*
@@ -232,7 +250,10 @@ rip_output(m, so, dst)
}
#ifdef IPSEC
- ipsec_setsocket(m, so);
+ if (ipsec_setsocket(m, so) != 0) {
+ m_freem(m);
+ return ENOBUFS;
+ }
#endif /*IPSEC*/
return (ip_output(m, inp->inp_options, &inp->inp_route, flags,
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 34c2006..3554dae 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -305,6 +305,7 @@ tcp6_input(mp, offp, proto)
int *offp, proto;
{
register struct mbuf *m = *mp;
+ struct in6_ifaddr *ia6;
IP6_EXTHDR_CHECK(m, *offp, sizeof(struct tcphdr), IPPROTO_DONE);
@@ -312,7 +313,8 @@ tcp6_input(mp, offp, proto)
* draft-itojun-ipv6-tcp-to-anycast
* better place to put this in?
*/
- if (m->m_flags & M_ANYCAST6) {
+ ia6 = ip6_getdstifaddr(m);
+ if (ia6 && (ia6->ia6_flags & IN6_IFF_ANYCAST)) {
struct ip6_hdr *ip6;
ip6 = mtod(m, struct ip6_hdr *);
@@ -379,6 +381,19 @@ tcp_input(m, off0, proto)
goto drop;
}
th = (struct tcphdr *)((caddr_t)ip6 + off0);
+
+ /*
+ * Be proactive about unspecified IPv6 address in source.
+ * As we use all-zero to indicate unbounded/unconnected pcb,
+ * unspecified IPv6 address can be used to confuse us.
+ *
+ * Note that packets with unspecified IPv6 destination is
+ * already dropped in ip6_input.
+ */
+ if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
+ /* XXX stat */
+ goto drop;
+ }
} else
#endif /* INET6 */
{
@@ -627,18 +642,6 @@ findpcb:
else
tiwin = th->th_win;
-#ifdef INET6
- /* save packet options if user wanted */
- if (isipv6 && inp->in6p_flags & INP_CONTROLOPTS) {
- if (inp->in6p_options) {
- m_freem(inp->in6p_options);
- inp->in6p_options = 0;
- }
- ip6_savecontrol(inp, &inp->in6p_options, ip6, m);
- }
- /* else, should also do ip_srcroute() here? */
-#endif /* INET6 */
-
so = inp->inp_socket;
if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) {
#ifdef TCPDEBUG
@@ -683,6 +686,50 @@ findpcb:
goto drop;
}
#endif
+
+#ifdef INET6
+ /*
+ * If deprecated address is forbidden,
+ * we do not accept SYN to deprecated interface
+ * address to prevent any new inbound connection from
+ * getting established.
+ * When we do not accept SYN, we send a TCP RST,
+ * with deprecated source address (instead of dropping
+ * it). We compromise it as it is much better for peer
+ * to send a RST, and RST will be the final packet
+ * for the exchange.
+ *
+ * If we do not forbid deprecated addresses, we accept
+ * the SYN packet. RFC2462 does not suggest dropping
+ * SYN in this case.
+ * If we decipher RFC2462 5.5.4, it says like this:
+ * 1. use of deprecated addr with existing
+ * communication is okay - "SHOULD continue to be
+ * used"
+ * 2. use of it with new communication:
+ * (2a) "SHOULD NOT be used if alternate address
+ * with sufficient scope is available"
+ * (2b) nothing mentioned otherwise.
+ * Here we fall into (2b) case as we have no choice in
+ * our source address selection - we must obey the peer.
+ *
+ * The wording in RFC2462 is confusing, and there are
+ * multiple description text for deprecated address
+ * handling - worse, they are not exactly the same.
+ * I believe 5.5.4 is the best one, so we follow 5.5.4.
+ */
+ if (isipv6 && !ip6_use_deprecated) {
+ struct in6_ifaddr *ia6;
+
+ if ((ia6 = ip6_getdstifaddr(m)) &&
+ (ia6->ia6_flags & IN6_IFF_DEPRECATED)) {
+ tp = NULL;
+ rstreason = BANDLIM_RST_OPENPORT;
+ goto dropwithreset;
+ }
+ }
+#endif
+
so2 = sonewconn(so, 0);
if (so2 == 0) {
/*
@@ -731,10 +778,8 @@ findpcb:
if (isipv6)
inp->in6p_laddr = ip6->ip6_dst;
else {
- if ((inp->inp_flags & IN6P_BINDV6ONLY) == 0) {
- inp->inp_vflag &= ~INP_IPV6;
- inp->inp_vflag |= INP_IPV4;
- }
+ inp->inp_vflag &= ~INP_IPV6;
+ inp->inp_vflag |= INP_IPV4;
#endif /* INET6 */
inp->inp_laddr = ip->ip_dst;
#ifdef INET6
@@ -779,21 +824,25 @@ findpcb:
#endif
#ifdef INET6
if (isipv6) {
- /*
- * inherit socket options from the listening
- * socket.
- */
+ /*
+ * Inherit socket options from the listening
+ * socket.
+ * Note that in6p_inputopts are not (even
+ * should not be) copied, since it stores
+ * previously received options and is used to
+ * detect if each new option is different than
+ * the previous one and hence should be passed
+ * to a user.
+ * If we copied in6p_inputopts, a user would
+ * not be able to receive options just after
+ * calling the accept system call.
+ */
inp->inp_flags |=
oinp->inp_flags & INP_CONTROLOPTS;
- if (inp->inp_flags & INP_CONTROLOPTS) {
- if (inp->in6p_options) {
- m_freem(inp->in6p_options);
- inp->in6p_options = 0;
- }
- ip6_savecontrol(inp,
- &inp->in6p_options,
- ip6, m);
- }
+ if (oinp->in6p_outputopts)
+ inp->in6p_outputopts =
+ ip6_copypktopts(oinp->in6p_outputopts,
+ M_NOWAIT);
} else
#endif /* INET6 */
inp->inp_options = ip_srcroute();
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 286b420..a2a2cf3 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -376,7 +376,7 @@ send:
* NOTE: we assume that the IP/TCP header plus TCP options
* always fit in a single mbuf, leaving room for a maximum
* link header, i.e.
- * max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MHLEN
+ * max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MCLBYTES
*/
optlen = 0;
#ifdef INET6
@@ -823,7 +823,11 @@ send:
/* TODO: IPv6 IP6TOS_ECT bit on */
#ifdef IPSEC
- ipsec_setsocket(m, so);
+ if (ipsec_setsocket(m, so) != 0) {
+ m_freem(m);
+ error = ENOBUFS;
+ goto out;
+ }
#endif /*IPSEC*/
error = ip6_output(m,
tp->t_inpcb->in6p_outputopts,
diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c
index 34c2006..3554dae 100644
--- a/sys/netinet/tcp_reass.c
+++ b/sys/netinet/tcp_reass.c
@@ -305,6 +305,7 @@ tcp6_input(mp, offp, proto)
int *offp, proto;
{
register struct mbuf *m = *mp;
+ struct in6_ifaddr *ia6;
IP6_EXTHDR_CHECK(m, *offp, sizeof(struct tcphdr), IPPROTO_DONE);
@@ -312,7 +313,8 @@ tcp6_input(mp, offp, proto)
* draft-itojun-ipv6-tcp-to-anycast
* better place to put this in?
*/
- if (m->m_flags & M_ANYCAST6) {
+ ia6 = ip6_getdstifaddr(m);
+ if (ia6 && (ia6->ia6_flags & IN6_IFF_ANYCAST)) {
struct ip6_hdr *ip6;
ip6 = mtod(m, struct ip6_hdr *);
@@ -379,6 +381,19 @@ tcp_input(m, off0, proto)
goto drop;
}
th = (struct tcphdr *)((caddr_t)ip6 + off0);
+
+ /*
+ * Be proactive about unspecified IPv6 address in source.
+ * As we use all-zero to indicate unbounded/unconnected pcb,
+ * unspecified IPv6 address can be used to confuse us.
+ *
+ * Note that packets with unspecified IPv6 destination is
+ * already dropped in ip6_input.
+ */
+ if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
+ /* XXX stat */
+ goto drop;
+ }
} else
#endif /* INET6 */
{
@@ -627,18 +642,6 @@ findpcb:
else
tiwin = th->th_win;
-#ifdef INET6
- /* save packet options if user wanted */
- if (isipv6 && inp->in6p_flags & INP_CONTROLOPTS) {
- if (inp->in6p_options) {
- m_freem(inp->in6p_options);
- inp->in6p_options = 0;
- }
- ip6_savecontrol(inp, &inp->in6p_options, ip6, m);
- }
- /* else, should also do ip_srcroute() here? */
-#endif /* INET6 */
-
so = inp->inp_socket;
if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) {
#ifdef TCPDEBUG
@@ -683,6 +686,50 @@ findpcb:
goto drop;
}
#endif
+
+#ifdef INET6
+ /*
+ * If deprecated address is forbidden,
+ * we do not accept SYN to deprecated interface
+ * address to prevent any new inbound connection from
+ * getting established.
+ * When we do not accept SYN, we send a TCP RST,
+ * with deprecated source address (instead of dropping
+ * it). We compromise it as it is much better for peer
+ * to send a RST, and RST will be the final packet
+ * for the exchange.
+ *
+ * If we do not forbid deprecated addresses, we accept
+ * the SYN packet. RFC2462 does not suggest dropping
+ * SYN in this case.
+ * If we decipher RFC2462 5.5.4, it says like this:
+ * 1. use of deprecated addr with existing
+ * communication is okay - "SHOULD continue to be
+ * used"
+ * 2. use of it with new communication:
+ * (2a) "SHOULD NOT be used if alternate address
+ * with sufficient scope is available"
+ * (2b) nothing mentioned otherwise.
+ * Here we fall into (2b) case as we have no choice in
+ * our source address selection - we must obey the peer.
+ *
+ * The wording in RFC2462 is confusing, and there are
+ * multiple description text for deprecated address
+ * handling - worse, they are not exactly the same.
+ * I believe 5.5.4 is the best one, so we follow 5.5.4.
+ */
+ if (isipv6 && !ip6_use_deprecated) {
+ struct in6_ifaddr *ia6;
+
+ if ((ia6 = ip6_getdstifaddr(m)) &&
+ (ia6->ia6_flags & IN6_IFF_DEPRECATED)) {
+ tp = NULL;
+ rstreason = BANDLIM_RST_OPENPORT;
+ goto dropwithreset;
+ }
+ }
+#endif
+
so2 = sonewconn(so, 0);
if (so2 == 0) {
/*
@@ -731,10 +778,8 @@ findpcb:
if (isipv6)
inp->in6p_laddr = ip6->ip6_dst;
else {
- if ((inp->inp_flags & IN6P_BINDV6ONLY) == 0) {
- inp->inp_vflag &= ~INP_IPV6;
- inp->inp_vflag |= INP_IPV4;
- }
+ inp->inp_vflag &= ~INP_IPV6;
+ inp->inp_vflag |= INP_IPV4;
#endif /* INET6 */
inp->inp_laddr = ip->ip_dst;
#ifdef INET6
@@ -779,21 +824,25 @@ findpcb:
#endif
#ifdef INET6
if (isipv6) {
- /*
- * inherit socket options from the listening
- * socket.
- */
+ /*
+ * Inherit socket options from the listening
+ * socket.
+ * Note that in6p_inputopts are not (even
+ * should not be) copied, since it stores
+ * previously received options and is used to
+ * detect if each new option is different than
+ * the previous one and hence should be passed
+ * to a user.
+ * If we copied in6p_inputopts, a user would
+ * not be able to receive options just after
+ * calling the accept system call.
+ */
inp->inp_flags |=
oinp->inp_flags & INP_CONTROLOPTS;
- if (inp->inp_flags & INP_CONTROLOPTS) {
- if (inp->in6p_options) {
- m_freem(inp->in6p_options);
- inp->in6p_options = 0;
- }
- ip6_savecontrol(inp,
- &inp->in6p_options,
- ip6, m);
- }
+ if (oinp->in6p_outputopts)
+ inp->in6p_outputopts =
+ ip6_copypktopts(oinp->in6p_outputopts,
+ M_NOWAIT);
} else
#endif /* INET6 */
inp->inp_options = ip_srcroute();
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 3857b75..06849be 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -443,7 +443,10 @@ tcp_respond(tp, ipgen, th, m, ack, seq, flags)
tcp_trace(TA_OUTPUT, 0, tp, mtod(m, void *), th, 0);
#endif
#ifdef IPSEC
- ipsec_setsocket(m, tp ? tp->t_inpcb->inp_socket : NULL);
+ if (ipsec_setsocket(m, tp ? tp->t_inpcb->inp_socket : NULL) != 0) {
+ m_freem(m);
+ return;
+ }
#endif
#ifdef INET6
if (isipv6) {
@@ -1020,13 +1023,17 @@ tcp6_ctlinput(cmd, sa, d)
struct sockaddr *sa;
void *d;
{
- register struct tcphdr *thp;
struct tcphdr th;
void (*notify) __P((struct inpcb *, int)) = tcp_notify;
- struct sockaddr_in6 sa6;
struct ip6_hdr *ip6;
struct mbuf *m;
+ struct ip6ctlparam *ip6cp = NULL;
+ const struct sockaddr_in6 *sa6_src = NULL;
int off;
+ struct tcp_portonly {
+ u_int16_t th_sport;
+ u_int16_t th_dport;
+ } *thp;
if (sa->sa_family != AF_INET6 ||
sa->sa_len != sizeof(struct sockaddr_in6))
@@ -1042,56 +1049,36 @@ tcp6_ctlinput(cmd, sa, d)
/* if the parameter is from icmp6, decode it. */
if (d != NULL) {
- struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d;
+ ip6cp = (struct ip6ctlparam *)d;
m = ip6cp->ip6c_m;
ip6 = ip6cp->ip6c_ip6;
off = ip6cp->ip6c_off;
+ sa6_src = ip6cp->ip6c_src;
} else {
m = NULL;
ip6 = NULL;
off = 0; /* fool gcc */
+ sa6_src = &sa6_any;
}
- /*
- * Translate addresses into internal form.
- * Sa check if it is AF_INET6 is done at the top of this funciton.
- */
- sa6 = *(struct sockaddr_in6 *)sa;
- if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr) != 0 && m != NULL &&
- m->m_pkthdr.rcvif != NULL)
- sa6.sin6_addr.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
-
if (ip6) {
/*
* XXX: We assume that when IPV6 is non NULL,
* M and OFF are valid.
*/
- struct in6_addr s;
-
- /* translate addresses into internal form */
- memcpy(&s, &ip6->ip6_src, sizeof(s));
- if (IN6_IS_ADDR_LINKLOCAL(&s) != 0 && m != NULL &&
- m->m_pkthdr.rcvif != NULL)
- s.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
/* check if we can safely examine src and dst ports */
- if (m->m_pkthdr.len < off + sizeof(th))
+ if (m->m_pkthdr.len < off + sizeof(*thp))
return;
- if (m->m_len < off + sizeof(th)) {
- /*
- * this should be rare case
- * because now MINCLSIZE is "(MHLEN + 1)",
- * so we compromise on this copy...
- */
- m_copydata(m, off, sizeof(th), (caddr_t)&th);
- thp = &th;
- } else
- thp = (struct tcphdr *)(mtod(m, caddr_t) + off);
- in6_pcbnotify(&tcb, (struct sockaddr *)&sa6, thp->th_dport,
- &s, thp->th_sport, cmd, notify);
+ bzero(&th, sizeof(th));
+ m_copydata(m, off, sizeof(*thp), (caddr_t)&th);
+
+ in6_pcbnotify(&tcb, sa, th.th_dport,
+ (struct sockaddr *)ip6cp->ip6c_src,
+ th.th_sport, cmd, notify);
} else
- in6_pcbnotify(&tcb, (struct sockaddr *)&sa6, 0, &zeroin6_addr,
+ in6_pcbnotify(&tcb, sa, 0, (struct sockaddr *)sa6_src,
0, cmd, notify);
}
#endif /* INET6 */
@@ -1323,9 +1310,12 @@ tcp_rtlookup6(inp)
if (rt == NULL || !(rt->rt_flags & RTF_UP)) {
/* No route yet, so try to acquire one */
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
- ro6->ro_dst.sin6_family = AF_INET6;
- ro6->ro_dst.sin6_len = sizeof(ro6->ro_dst);
- ro6->ro_dst.sin6_addr = inp->in6p_faddr;
+ struct sockaddr_in6 *dst6;
+
+ dst6 = (struct sockaddr_in6 *)&ro6->ro_dst;
+ dst6->sin6_family = AF_INET6;
+ dst6->sin6_len = sizeof(ro6->ro_dst);
+ dst6->sin6_addr = inp->in6p_faddr;
rtalloc((struct route *)ro6);
rt = ro6->ro_rt;
}
@@ -1376,6 +1366,7 @@ ipsec_hdrsiz_tcp(tp)
sizeof(struct ip));
bcopy((caddr_t)&tp->t_template->tt_t, (caddr_t)th,
sizeof(struct tcphdr));
+ ip->ip_vhl = IP_VHL_BORING;
hdrsiz = ipsec4_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp);
}
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index 3857b75..06849be 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -443,7 +443,10 @@ tcp_respond(tp, ipgen, th, m, ack, seq, flags)
tcp_trace(TA_OUTPUT, 0, tp, mtod(m, void *), th, 0);
#endif
#ifdef IPSEC
- ipsec_setsocket(m, tp ? tp->t_inpcb->inp_socket : NULL);
+ if (ipsec_setsocket(m, tp ? tp->t_inpcb->inp_socket : NULL) != 0) {
+ m_freem(m);
+ return;
+ }
#endif
#ifdef INET6
if (isipv6) {
@@ -1020,13 +1023,17 @@ tcp6_ctlinput(cmd, sa, d)
struct sockaddr *sa;
void *d;
{
- register struct tcphdr *thp;
struct tcphdr th;
void (*notify) __P((struct inpcb *, int)) = tcp_notify;
- struct sockaddr_in6 sa6;
struct ip6_hdr *ip6;
struct mbuf *m;
+ struct ip6ctlparam *ip6cp = NULL;
+ const struct sockaddr_in6 *sa6_src = NULL;
int off;
+ struct tcp_portonly {
+ u_int16_t th_sport;
+ u_int16_t th_dport;
+ } *thp;
if (sa->sa_family != AF_INET6 ||
sa->sa_len != sizeof(struct sockaddr_in6))
@@ -1042,56 +1049,36 @@ tcp6_ctlinput(cmd, sa, d)
/* if the parameter is from icmp6, decode it. */
if (d != NULL) {
- struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d;
+ ip6cp = (struct ip6ctlparam *)d;
m = ip6cp->ip6c_m;
ip6 = ip6cp->ip6c_ip6;
off = ip6cp->ip6c_off;
+ sa6_src = ip6cp->ip6c_src;
} else {
m = NULL;
ip6 = NULL;
off = 0; /* fool gcc */
+ sa6_src = &sa6_any;
}
- /*
- * Translate addresses into internal form.
- * Sa check if it is AF_INET6 is done at the top of this funciton.
- */
- sa6 = *(struct sockaddr_in6 *)sa;
- if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr) != 0 && m != NULL &&
- m->m_pkthdr.rcvif != NULL)
- sa6.sin6_addr.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
-
if (ip6) {
/*
* XXX: We assume that when IPV6 is non NULL,
* M and OFF are valid.
*/
- struct in6_addr s;
-
- /* translate addresses into internal form */
- memcpy(&s, &ip6->ip6_src, sizeof(s));
- if (IN6_IS_ADDR_LINKLOCAL(&s) != 0 && m != NULL &&
- m->m_pkthdr.rcvif != NULL)
- s.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
/* check if we can safely examine src and dst ports */
- if (m->m_pkthdr.len < off + sizeof(th))
+ if (m->m_pkthdr.len < off + sizeof(*thp))
return;
- if (m->m_len < off + sizeof(th)) {
- /*
- * this should be rare case
- * because now MINCLSIZE is "(MHLEN + 1)",
- * so we compromise on this copy...
- */
- m_copydata(m, off, sizeof(th), (caddr_t)&th);
- thp = &th;
- } else
- thp = (struct tcphdr *)(mtod(m, caddr_t) + off);
- in6_pcbnotify(&tcb, (struct sockaddr *)&sa6, thp->th_dport,
- &s, thp->th_sport, cmd, notify);
+ bzero(&th, sizeof(th));
+ m_copydata(m, off, sizeof(*thp), (caddr_t)&th);
+
+ in6_pcbnotify(&tcb, sa, th.th_dport,
+ (struct sockaddr *)ip6cp->ip6c_src,
+ th.th_sport, cmd, notify);
} else
- in6_pcbnotify(&tcb, (struct sockaddr *)&sa6, 0, &zeroin6_addr,
+ in6_pcbnotify(&tcb, sa, 0, (struct sockaddr *)sa6_src,
0, cmd, notify);
}
#endif /* INET6 */
@@ -1323,9 +1310,12 @@ tcp_rtlookup6(inp)
if (rt == NULL || !(rt->rt_flags & RTF_UP)) {
/* No route yet, so try to acquire one */
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
- ro6->ro_dst.sin6_family = AF_INET6;
- ro6->ro_dst.sin6_len = sizeof(ro6->ro_dst);
- ro6->ro_dst.sin6_addr = inp->in6p_faddr;
+ struct sockaddr_in6 *dst6;
+
+ dst6 = (struct sockaddr_in6 *)&ro6->ro_dst;
+ dst6->sin6_family = AF_INET6;
+ dst6->sin6_len = sizeof(ro6->ro_dst);
+ dst6->sin6_addr = inp->in6p_faddr;
rtalloc((struct route *)ro6);
rt = ro6->ro_rt;
}
@@ -1376,6 +1366,7 @@ ipsec_hdrsiz_tcp(tp)
sizeof(struct ip));
bcopy((caddr_t)&tp->t_template->tt_t, (caddr_t)th,
sizeof(struct tcphdr));
+ ip->ip_vhl = IP_VHL_BORING;
hdrsiz = ipsec4_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp);
}
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 25834d4..aea92c0 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -240,8 +240,7 @@ tcp6_usr_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
}
inp->inp_vflag &= ~INP_IPV4;
inp->inp_vflag |= INP_IPV6;
- if ((inp->inp_flags & IN6P_BINDV6ONLY) == 0) {
-
+ if (ip6_mapped_addr_on && (inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) {
if (IN6_IS_ADDR_UNSPECIFIED(&sin6p->sin6_addr))
inp->inp_vflag |= INP_IPV4;
else if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) {
@@ -292,7 +291,8 @@ tcp6_usr_listen(struct socket *so, struct proc *p)
COMMON_START();
if (inp->inp_lport == 0) {
inp->inp_vflag &= ~INP_IPV4;
- if ((inp->inp_flags & IN6P_BINDV6ONLY) == 0)
+ if (ip6_mapped_addr_on &&
+ (inp->inp_flags & IN6P_IPV6_V6ONLY) == 0)
inp->inp_vflag |= INP_IPV4;
error = in6_pcbbind(inp, (struct sockaddr *)0, p);
}
@@ -361,10 +361,13 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
goto out;
}
- if ((inp->inp_flags & IN6P_BINDV6ONLY) == 0 &&
- IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) {
+ if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) {
struct sockaddr_in sin;
+ if (!ip6_mapped_addr_on ||
+ (inp->inp_flags & IN6P_IPV6_V6ONLY))
+ return(EINVAL);
+
in6_sin6_2_sin(&sin, sin6p);
inp->inp_vflag |= INP_IPV4;
inp->inp_vflag &= ~INP_IPV6;
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 350a384..d546b1f 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -392,8 +392,7 @@ udp_input(m, off, proto)
#endif
ip_savecontrol(inp, &opts, ip, m);
}
- iphlen += sizeof(struct udphdr);
- m_adj(m, iphlen);
+ m_adj(m, iphlen + sizeof(struct udphdr));
#ifdef INET6
if (inp->inp_vflag & INP_IPV6) {
in6_sin_2_v4mapsin6(&udp_in, &udp_in6.uin6_sin);
@@ -744,7 +743,10 @@ udp_output(inp, m, addr, control, p)
udpstat.udps_opackets++;
#ifdef IPSEC
- ipsec_setsocket(m, inp->inp_socket);
+ if (ipsec_setsocket(m, inp->inp_socket) != 0) {
+ error = ENOBUFS;
+ goto release;
+ }
#endif /*IPSEC*/
error = ip_output(m, inp->inp_options, &inp->inp_route,
(inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)),
OpenPOWER on IntegriCloud