aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Frederic Sowa <hannes@stressinduktion.org>2013-08-26 19:36:51 -0400
committerDavid S. Miller <davem@davemloft.net>2013-08-29 15:32:08 -0400
commitb800c3b966bcf004bd8592293a49ed5cb7ea67a9 (patch)
treee10eef87a5dc18bc16745adde12dae6ff104240b
parenta3a975b1dfe999f3e5d38d38f2387894c4332d96 (diff)
ipv6: drop fragmented ndisc packets by default (RFC 6980)
This patch implements RFC6980: Drop fragmented ndisc packets by default. If a fragmented ndisc packet is received the user is informed that it is possible to disable the check. Cc: Fernando Gont <fernando@gont.com.ar> Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/networking/ip-sysctl.txt6
-rw-r--r--include/linux/ipv6.h1
-rw-r--r--include/uapi/linux/ipv6.h1
-rw-r--r--net/ipv6/addrconf.c10
-rw-r--r--net/ipv6/ndisc.c17
5 files changed, 35 insertions, 0 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index debfe857d8f9..a2be556032c9 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -1349,6 +1349,12 @@ mldv2_unsolicited_report_interval - INTEGER
1349 MLDv2 report retransmit will take place. 1349 MLDv2 report retransmit will take place.
1350 Default: 1000 (1 second) 1350 Default: 1000 (1 second)
1351 1351
1352suppress_frag_ndisc - INTEGER
1353 Control RFC 6980 (Security Implications of IPv6 Fragmentation
1354 with IPv6 Neighbor Discovery) behavior:
1355 1 - (default) discard fragmented neighbor discovery packets
1356 0 - allow fragmented neighbor discovery packets
1357
1352icmp/*: 1358icmp/*:
1353ratelimit - INTEGER 1359ratelimit - INTEGER
1354 Limit the maximal rates for sending ICMPv6 packets. 1360 Limit the maximal rates for sending ICMPv6 packets.
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 9ac5047062c8..28ea38439313 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -50,6 +50,7 @@ struct ipv6_devconf {
50 __s32 accept_dad; 50 __s32 accept_dad;
51 __s32 force_tllao; 51 __s32 force_tllao;
52 __s32 ndisc_notify; 52 __s32 ndisc_notify;
53 __s32 suppress_frag_ndisc;
53 void *sysctl; 54 void *sysctl;
54}; 55};
55 56
diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h
index d07ac6903e59..593b0e32d956 100644
--- a/include/uapi/linux/ipv6.h
+++ b/include/uapi/linux/ipv6.h
@@ -162,6 +162,7 @@ enum {
162 DEVCONF_NDISC_NOTIFY, 162 DEVCONF_NDISC_NOTIFY,
163 DEVCONF_MLDV1_UNSOLICITED_REPORT_INTERVAL, 163 DEVCONF_MLDV1_UNSOLICITED_REPORT_INTERVAL,
164 DEVCONF_MLDV2_UNSOLICITED_REPORT_INTERVAL, 164 DEVCONF_MLDV2_UNSOLICITED_REPORT_INTERVAL,
165 DEVCONF_SUPPRESS_FRAG_NDISC,
165 DEVCONF_MAX 166 DEVCONF_MAX
166}; 167};
167 168
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 2d6d1793bbfe..a7183fc9bbc2 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -204,6 +204,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
204 .accept_source_route = 0, /* we do not accept RH0 by default. */ 204 .accept_source_route = 0, /* we do not accept RH0 by default. */
205 .disable_ipv6 = 0, 205 .disable_ipv6 = 0,
206 .accept_dad = 1, 206 .accept_dad = 1,
207 .suppress_frag_ndisc = 1,
207}; 208};
208 209
209static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { 210static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
@@ -241,6 +242,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
241 .accept_source_route = 0, /* we do not accept RH0 by default. */ 242 .accept_source_route = 0, /* we do not accept RH0 by default. */
242 .disable_ipv6 = 0, 243 .disable_ipv6 = 0,
243 .accept_dad = 1, 244 .accept_dad = 1,
245 .suppress_frag_ndisc = 1,
244}; 246};
245 247
246/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ 248/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
@@ -4188,6 +4190,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
4188 array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad; 4190 array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad;
4189 array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao; 4191 array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao;
4190 array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify; 4192 array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify;
4193 array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc;
4191} 4194}
4192 4195
4193static inline size_t inet6_ifla6_size(void) 4196static inline size_t inet6_ifla6_size(void)
@@ -5002,6 +5005,13 @@ static struct addrconf_sysctl_table
5002 .proc_handler = proc_dointvec 5005 .proc_handler = proc_dointvec
5003 }, 5006 },
5004 { 5007 {
5008 .procname = "suppress_frag_ndisc",
5009 .data = &ipv6_devconf.suppress_frag_ndisc,
5010 .maxlen = sizeof(int),
5011 .mode = 0644,
5012 .proc_handler = proc_dointvec
5013 },
5014 {
5005 /* sentinel */ 5015 /* sentinel */
5006 } 5016 }
5007 }, 5017 },
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 04d31c2fbef1..41720feeaa64 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1519,10 +1519,27 @@ static void pndisc_redo(struct sk_buff *skb)
1519 kfree_skb(skb); 1519 kfree_skb(skb);
1520} 1520}
1521 1521
1522static bool ndisc_suppress_frag_ndisc(struct sk_buff *skb)
1523{
1524 struct inet6_dev *idev = __in6_dev_get(skb->dev);
1525
1526 if (!idev)
1527 return true;
1528 if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED &&
1529 idev->cnf.suppress_frag_ndisc) {
1530 net_warn_ratelimited("Received fragmented ndisc packet. Carefully consider disabling suppress_frag_ndisc.\n");
1531 return true;
1532 }
1533 return false;
1534}
1535
1522int ndisc_rcv(struct sk_buff *skb) 1536int ndisc_rcv(struct sk_buff *skb)
1523{ 1537{
1524 struct nd_msg *msg; 1538 struct nd_msg *msg;
1525 1539
1540 if (ndisc_suppress_frag_ndisc(skb))
1541 return 0;
1542
1526 if (skb_linearize(skb)) 1543 if (skb_linearize(skb))
1527 return 0; 1544 return 0;
1528 1545