aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/tcp_ipv6.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@vyatta.com>2010-04-22 18:24:53 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-22 18:24:53 -0400
commite802af9cabb011f09b9c19a82faef3dd315f27eb (patch)
tree9a8ef1163b9b40fef8860b08ea4dcb4ff3916098 /net/ipv6/tcp_ipv6.c
parent9ccb8975940c4ee51161152e37058e3d9e06c62f (diff)
IPv6: Generic TTL Security Mechanism (final version)
This patch adds IPv6 support for RFC5082 Generalized TTL Security Mechanism. Not to users of mapped address; the IPV6 and IPV4 socket options are seperate. The server does have to deal with both IPv4 and IPv6 socket options and the client has to handle the different for each family. On client: int ttl = 255; getaddrinfo(argv[1], argv[2], &hint, &result); for (rp = result; rp != NULL; rp = rp->ai_next) { s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (s < 0) continue; if (rp->ai_family == AF_INET) { setsockopt(s, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); } else if (rp->ai_family == AF_INET6) { setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl))) } if (connect(s, rp->ai_addr, rp->ai_addrlen) == 0) { ... On server: int minttl = 255 - maxhops; getaddrinfo(NULL, port, &hints, &result); for (rp = result; rp != NULL; rp = rp->ai_next) { s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (s < 0) continue; if (rp->ai_family == AF_INET6) setsockopt(s, IPPROTO_IPV6, IPV6_MINHOPCOUNT, &minttl, sizeof(minttl)); setsockopt(s, IPPROTO_IP, IP_MINTTL, &minttl, sizeof(minttl)); if (bind(s, rp->ai_addr, rp->ai_addrlen) == 0) break ... Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r--net/ipv6/tcp_ipv6.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 1ababbb41131..6603511e3673 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -353,6 +353,11 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
353 if (sk->sk_state == TCP_CLOSE) 353 if (sk->sk_state == TCP_CLOSE)
354 goto out; 354 goto out;
355 355
356 if (ipv6_hdr(skb)->hop_limit < inet6_sk(sk)->min_hopcount) {
357 NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
358 goto out;
359 }
360
356 tp = tcp_sk(sk); 361 tp = tcp_sk(sk);
357 seq = ntohl(th->seq); 362 seq = ntohl(th->seq);
358 if (sk->sk_state != TCP_LISTEN && 363 if (sk->sk_state != TCP_LISTEN &&
@@ -1678,6 +1683,7 @@ ipv6_pktoptions:
1678static int tcp_v6_rcv(struct sk_buff *skb) 1683static int tcp_v6_rcv(struct sk_buff *skb)
1679{ 1684{
1680 struct tcphdr *th; 1685 struct tcphdr *th;
1686 struct ipv6hdr *hdr;
1681 struct sock *sk; 1687 struct sock *sk;
1682 int ret; 1688 int ret;
1683 struct net *net = dev_net(skb->dev); 1689 struct net *net = dev_net(skb->dev);
@@ -1704,12 +1710,13 @@ static int tcp_v6_rcv(struct sk_buff *skb)
1704 goto bad_packet; 1710 goto bad_packet;
1705 1711
1706 th = tcp_hdr(skb); 1712 th = tcp_hdr(skb);
1713 hdr = ipv6_hdr(skb);
1707 TCP_SKB_CB(skb)->seq = ntohl(th->seq); 1714 TCP_SKB_CB(skb)->seq = ntohl(th->seq);
1708 TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + 1715 TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
1709 skb->len - th->doff*4); 1716 skb->len - th->doff*4);
1710 TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); 1717 TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
1711 TCP_SKB_CB(skb)->when = 0; 1718 TCP_SKB_CB(skb)->when = 0;
1712 TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb)); 1719 TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(hdr);
1713 TCP_SKB_CB(skb)->sacked = 0; 1720 TCP_SKB_CB(skb)->sacked = 0;
1714 1721
1715 sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest); 1722 sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest);
@@ -1720,6 +1727,11 @@ process:
1720 if (sk->sk_state == TCP_TIME_WAIT) 1727 if (sk->sk_state == TCP_TIME_WAIT)
1721 goto do_time_wait; 1728 goto do_time_wait;
1722 1729
1730 if (hdr->hop_limit < inet6_sk(sk)->min_hopcount) {
1731 NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
1732 goto discard_and_relse;
1733 }
1734
1723 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) 1735 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
1724 goto discard_and_relse; 1736 goto discard_and_relse;
1725 1737