diff options
author | andre <andre@FreeBSD.org> | 2005-08-22 16:13:08 +0000 |
---|---|---|
committer | andre <andre@FreeBSD.org> | 2005-08-22 16:13:08 +0000 |
commit | 573a9535a81268ee8fa937d020dad86235127d2c (patch) | |
tree | e4fae08b9c2716f53ec0fdfe0bc72046c99f26b9 | |
parent | ef76245e903c6da9b4359edf312f385c9d1ab002 (diff) | |
download | FreeBSD-src-573a9535a81268ee8fa937d020dad86235127d2c.zip FreeBSD-src-573a9535a81268ee8fa937d020dad86235127d2c.tar.gz |
Add socketoption IP_MINTTL. May be used to set the minimum acceptable
TTL a packet must have when received on a socket. All packets with a
lower TTL are silently dropped. Works on already connected/connecting
and listening sockets for RAW/UDP/TCP.
This option is only really useful when set to 255 preventing packets
from outside the directly connected networks reaching local listeners
on sockets.
Allows userland implementation of 'The Generalized TTL Security Mechanism
(GTSM)' according to RFC3682. Examples of such use include the Cisco IOS
BGP implementation command "neighbor ttl-security".
MFC after: 2 weeks
Sponsored by: TCP/IP Optimization Fundraise 2005
-rw-r--r-- | sys/netinet/in.h | 1 | ||||
-rw-r--r-- | sys/netinet/in_pcb.h | 1 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 14 | ||||
-rw-r--r-- | sys/netinet/raw_ip.c | 3 | ||||
-rw-r--r-- | sys/netinet/tcp_input.c | 5 | ||||
-rw-r--r-- | sys/netinet/tcp_reass.c | 5 | ||||
-rw-r--r-- | sys/netinet/udp_usrreq.c | 3 |
7 files changed, 32 insertions, 0 deletions
diff --git a/sys/netinet/in.h b/sys/netinet/in.h index 45c269c..f006ae3 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -415,6 +415,7 @@ __END_DECLS #define IP_DUMMYNET_GET 64 /* get entire dummynet pipes */ #define IP_RECVTTL 65 /* bool; receive IP TTL w/dgram */ +#define IP_MINTTL 66 /* minimum TTL for packet or drop */ /* * Defaults and limits for options diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index 99e12ad..3d267ae 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -133,6 +133,7 @@ struct inpcb { #define INP_ONESBCAST 0x10 /* send all-ones broadcast */ u_char inp_ip_ttl; /* time to live proto */ u_char inp_ip_p; /* protocol proto */ + u_char inp_ip_minttl; /* minimum TTL or drop */ /* protocol dependent part; options */ struct { diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 90c50a3..b292d80 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -1189,6 +1189,7 @@ ip_ctloutput(so, sopt) case IP_TOS: case IP_TTL: + case IP_MINTTL: case IP_RECVOPTS: case IP_RECVRETOPTS: case IP_RECVDSTADDR: @@ -1209,6 +1210,14 @@ ip_ctloutput(so, sopt) case IP_TTL: inp->inp_ip_ttl = optval; break; + + case IP_MINTTL: + if (optval > 0 && optval <= MAXTTL) + inp->inp_ip_minttl = optval; + else + error = EINVAL; + break; + #define OPTSET(bit) do { \ INP_LOCK(inp); \ if (optval) \ @@ -1333,6 +1342,7 @@ ip_ctloutput(so, sopt) case IP_TOS: case IP_TTL: + case IP_MINTTL: case IP_RECVOPTS: case IP_RECVRETOPTS: case IP_RECVDSTADDR: @@ -1351,6 +1361,10 @@ ip_ctloutput(so, sopt) optval = inp->inp_ip_ttl; break; + case IP_MINTTL: + optval = inp->inp_ip_minttl; + break; + #define OPTBIT(bit) (inp->inp_flags & bit ? 1 : 0) case IP_RECVOPTS: diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 3d2c6d2..8a128eb 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -157,6 +157,9 @@ raw_append(struct inpcb *last, struct ip *ip, struct mbuf *n) if (!policyfail && mac_check_inpcb_deliver(last, n) != 0) policyfail = 1; #endif + /* Check the minimum TTL for socket. */ + if (last->inp_ip_minttl && last->inp_ip_minttl > ip->ip_ttl) + policyfail = 1; if (!policyfail) { struct mbuf *opts = NULL; struct socket *so; diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index c86a3ec..369315d 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -740,6 +740,11 @@ findpcb: goto dropwithreset; } INP_LOCK(inp); + + /* Check the minimum TTL for socket. */ + if (inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl) + goto drop; + if (inp->inp_vflag & INP_TIMEWAIT) { /* * The only option of relevance is TOF_CC, and only if diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index c86a3ec..369315d 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -740,6 +740,11 @@ findpcb: goto dropwithreset; } INP_LOCK(inp); + + /* Check the minimum TTL for socket. */ + if (inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl) + goto drop; + if (inp->inp_vflag & INP_TIMEWAIT) { /* * The only option of relevance is TOF_CC, and only if diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 0ffb004..6de2d7b 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -384,6 +384,9 @@ udp_input(m, off) return; } INP_LOCK(inp); + /* Check the minimum TTL for socket. */ + if (inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl) + goto badheadlocked; udp_append(inp, ip, m, iphlen + sizeof(struct udphdr), &udp_in); INP_UNLOCK(inp); INP_INFO_RUNLOCK(&udbinfo); |