summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandre <andre@FreeBSD.org>2005-08-22 16:13:08 +0000
committerandre <andre@FreeBSD.org>2005-08-22 16:13:08 +0000
commit573a9535a81268ee8fa937d020dad86235127d2c (patch)
treee4fae08b9c2716f53ec0fdfe0bc72046c99f26b9
parentef76245e903c6da9b4359edf312f385c9d1ab002 (diff)
downloadFreeBSD-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.h1
-rw-r--r--sys/netinet/in_pcb.h1
-rw-r--r--sys/netinet/ip_output.c14
-rw-r--r--sys/netinet/raw_ip.c3
-rw-r--r--sys/netinet/tcp_input.c5
-rw-r--r--sys/netinet/tcp_reass.c5
-rw-r--r--sys/netinet/udp_usrreq.c3
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);
OpenPOWER on IntegriCloud