From 5fe56c549d6d29e62ec8852d9f64bf04eae9bbea Mon Sep 17 00:00:00 2001 From: rwatson Date: Thu, 19 Jul 2007 22:34:25 +0000 Subject: Attempt to improve feature parity between UDPv4 and UDPv6 by merging UDPv4 features to UDPv6: - Add MAC checks on delivery and MAC labeling on transmit. - Check for (and reject) datagrams with destination port 0. - For multicast delivery, check the source port only if the socket being considered as a destination has been connected. - Implement UDP blackholing based on net.inet.udp.blackhole. - Add a new ICMPv6 unreachable reply rate limiting category for failed delivery attempts and implement rate limiting for UDPv6 (submitted by bz). Approved by: re (kensmith) Reviewed by: bz --- sys/netinet/icmp_var.h | 3 ++- sys/netinet/ip_icmp.c | 3 ++- sys/netinet6/udp6_usrreq.c | 36 ++++++++++++++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/sys/netinet/icmp_var.h b/sys/netinet/icmp_var.h index f7bfa8b..dda84f2 100644 --- a/sys/netinet/icmp_var.h +++ b/sys/netinet/icmp_var.h @@ -82,7 +82,8 @@ extern int badport_bandlim(int); #define BANDLIM_ICMP_TSTAMP 2 #define BANDLIM_RST_CLOSEDPORT 3 /* No connection, and no listeners */ #define BANDLIM_RST_OPENPORT 4 /* No connection, listener */ -#define BANDLIM_MAX 4 +#define BANDLIM_ICMP6_UNREACH 5 +#define BANDLIM_MAX 5 #endif #endif diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index b330699..36cc020 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -888,7 +888,8 @@ badport_bandlim(int which) { "icmp ping response" }, { "icmp tstamp response" }, { "closed port RST response" }, - { "open port RST response" } + { "open port RST response" }, + { "icmp6 unreach response" } }; /* diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c index 2772f24..b57448b 100644 --- a/sys/netinet6/udp6_usrreq.c +++ b/sys/netinet6/udp6_usrreq.c @@ -65,6 +65,7 @@ #include "opt_inet.h" #include "opt_inet6.h" #include "opt_ipsec.h" +#include "opt_mac.h" #include #include @@ -92,7 +93,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -108,6 +111,8 @@ #include #endif /* IPSEC */ +#include + /* * UDP protocol inplementation. * Per RFC 768, August, 1980. @@ -133,7 +138,12 @@ udp6_append(struct inpcb *in6p, struct mbuf *n, int off, return; } #endif /* IPSEC */ - +#ifdef MAC + if (mac_check_inpcb_deliver(in6p, n) != 0) { + m_freem(n); + return; + } +#endif opts = NULL; if (in6p->in6p_flags & IN6P_CONTROLOPTS || in6p->inp_socket->so_options & SO_TIMESTAMP) @@ -184,6 +194,12 @@ udp6_input(struct mbuf **mp, int *offp, int proto) udpstat.udps_ipackets++; + /* + * Destination port of 0 is illegal, based on RFC768. + */ + if (uh->uh_dport == 0) + goto badunlocked; + plen = ntohs(ip6->ip6_plen) - off + sizeof(*ip6); ulen = ntohs((u_short)uh->uh_ulen); @@ -235,6 +251,15 @@ udp6_input(struct mbuf **mp, int *offp, int proto) continue; if (in6p->in6p_lport != uh->uh_dport) continue; + /* + * XXX: Do not check source port of incoming datagram + * unless inp_connect() has been called to bind the + * fport part of the 4-tuple; the source could be + * trying to talk to us with an ephemeral port. + */ + if (in6p->inp_fport != 0 && + in6p->inp_fport != uh->uh_sport) + continue; if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) { if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) @@ -310,6 +335,10 @@ udp6_input(struct mbuf **mp, int *offp, int proto) goto badheadlocked; } INP_INFO_RUNLOCK(&udbinfo); + if (udp_blackhole) + goto badunlocked; + if (badport_bandlim(BANDLIM_ICMP6_UNREACH) < 0) + goto badunlocked; icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0); return (IPPROTO_DONE); } @@ -318,6 +347,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto) INP_UNLOCK(in6p); INP_INFO_RUNLOCK(&udbinfo); return (IPPROTO_DONE); + badheadlocked: INP_INFO_RUNLOCK(&udbinfo); badunlocked: @@ -735,7 +765,9 @@ udp6_send(struct socket *so, int flags, struct mbuf *m, } } #endif - +#ifdef MAC + mac_create_mbuf_from_inpcb(inp, m); +#endif error = udp6_output(inp, m, addr, control, td); out: INP_UNLOCK(inp); -- cgit v1.1