aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/ndisc.h7
-rw-r--r--net/ipv6/ndisc.c17
2 files changed, 24 insertions, 0 deletions
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 7af1ea893038..23b3a7c58783 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -78,6 +78,13 @@ struct ra_msg {
78 __be32 retrans_timer; 78 __be32 retrans_timer;
79}; 79};
80 80
81struct rd_msg {
82 struct icmp6hdr icmph;
83 struct in6_addr target;
84 struct in6_addr dest;
85 __u8 opt[0];
86};
87
81struct nd_opt_hdr { 88struct nd_opt_hdr {
82 __u8 nd_opt_type; 89 __u8 nd_opt_type;
83 __u8 nd_opt_len; 90 __u8 nd_opt_len;
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index f2a007b7bde3..6574175795df 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1314,6 +1314,12 @@ out:
1314 1314
1315static void ndisc_redirect_rcv(struct sk_buff *skb) 1315static void ndisc_redirect_rcv(struct sk_buff *skb)
1316{ 1316{
1317 u8 *hdr;
1318 struct ndisc_options ndopts;
1319 struct rd_msg *msg = (struct rd_msg *)skb_transport_header(skb);
1320 u32 ndoptlen = skb->tail - (skb->transport_header +
1321 offsetof(struct rd_msg, opt));
1322
1317#ifdef CONFIG_IPV6_NDISC_NODETYPE 1323#ifdef CONFIG_IPV6_NDISC_NODETYPE
1318 switch (skb->ndisc_nodetype) { 1324 switch (skb->ndisc_nodetype) {
1319 case NDISC_NODETYPE_HOST: 1325 case NDISC_NODETYPE_HOST:
@@ -1330,6 +1336,17 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
1330 return; 1336 return;
1331 } 1337 }
1332 1338
1339 if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts))
1340 return;
1341
1342 if (!ndopts.nd_opts_rh)
1343 return;
1344
1345 hdr = (u8 *)ndopts.nd_opts_rh;
1346 hdr += 8;
1347 if (!pskb_pull(skb, hdr - skb_transport_header(skb)))
1348 return;
1349
1333 icmpv6_notify(skb, NDISC_REDIRECT, 0, 0); 1350 icmpv6_notify(skb, NDISC_REDIRECT, 0, 0);
1334} 1351}
1335 1352