diff options
| -rw-r--r-- | include/net/ip6_route.h | 2 | ||||
| -rw-r--r-- | net/ipv6/ndisc.c | 4 | ||||
| -rw-r--r-- | net/ipv6/route.c | 21 |
3 files changed, 26 insertions, 1 deletions
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 260f83f16bcf..f667248202b6 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h | |||
| @@ -135,6 +135,8 @@ extern void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, | |||
| 135 | extern void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, | 135 | extern void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, |
| 136 | __be32 mtu); | 136 | __be32 mtu); |
| 137 | extern void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark); | 137 | extern void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark); |
| 138 | extern void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif, | ||
| 139 | u32 mark); | ||
| 138 | extern void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk); | 140 | extern void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk); |
| 139 | 141 | ||
| 140 | struct netlink_callback; | 142 | struct netlink_callback; |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 79aa9652ed86..04d31c2fbef1 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
| @@ -1369,8 +1369,10 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
| 1369 | if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) | 1369 | if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) |
| 1370 | return; | 1370 | return; |
| 1371 | 1371 | ||
| 1372 | if (!ndopts.nd_opts_rh) | 1372 | if (!ndopts.nd_opts_rh) { |
| 1373 | ip6_redirect_no_header(skb, dev_net(skb->dev), 0, 0); | ||
| 1373 | return; | 1374 | return; |
| 1375 | } | ||
| 1374 | 1376 | ||
| 1375 | hdr = (u8 *)ndopts.nd_opts_rh; | 1377 | hdr = (u8 *)ndopts.nd_opts_rh; |
| 1376 | hdr += 8; | 1378 | hdr += 8; |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index b70f8979003b..8d9a93ed9c59 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -1178,6 +1178,27 @@ void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark) | |||
| 1178 | } | 1178 | } |
| 1179 | EXPORT_SYMBOL_GPL(ip6_redirect); | 1179 | EXPORT_SYMBOL_GPL(ip6_redirect); |
| 1180 | 1180 | ||
| 1181 | void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif, | ||
| 1182 | u32 mark) | ||
| 1183 | { | ||
| 1184 | const struct ipv6hdr *iph = ipv6_hdr(skb); | ||
| 1185 | const struct rd_msg *msg = (struct rd_msg *)icmp6_hdr(skb); | ||
| 1186 | struct dst_entry *dst; | ||
| 1187 | struct flowi6 fl6; | ||
| 1188 | |||
| 1189 | memset(&fl6, 0, sizeof(fl6)); | ||
| 1190 | fl6.flowi6_oif = oif; | ||
| 1191 | fl6.flowi6_mark = mark; | ||
| 1192 | fl6.flowi6_flags = 0; | ||
| 1193 | fl6.daddr = msg->dest; | ||
| 1194 | fl6.saddr = iph->daddr; | ||
| 1195 | |||
| 1196 | dst = ip6_route_output(net, NULL, &fl6); | ||
| 1197 | if (!dst->error) | ||
| 1198 | rt6_do_redirect(dst, NULL, skb); | ||
| 1199 | dst_release(dst); | ||
| 1200 | } | ||
| 1201 | |||
| 1181 | void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk) | 1202 | void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk) |
| 1182 | { | 1203 | { |
| 1183 | ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark); | 1204 | ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark); |
