diff options
Diffstat (limited to 'net/ipv4/ip_output.c')
| -rw-r--r-- | net/ipv4/ip_output.c | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 358f2c82b030..9af2b7853be4 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
| @@ -74,6 +74,7 @@ | |||
| 74 | #include <net/checksum.h> | 74 | #include <net/checksum.h> |
| 75 | #include <net/inetpeer.h> | 75 | #include <net/inetpeer.h> |
| 76 | #include <net/lwtunnel.h> | 76 | #include <net/lwtunnel.h> |
| 77 | #include <linux/bpf-cgroup.h> | ||
| 77 | #include <linux/igmp.h> | 78 | #include <linux/igmp.h> |
| 78 | #include <linux/netfilter_ipv4.h> | 79 | #include <linux/netfilter_ipv4.h> |
| 79 | #include <linux/netfilter_bridge.h> | 80 | #include <linux/netfilter_bridge.h> |
| @@ -285,6 +286,13 @@ static int ip_finish_output_gso(struct net *net, struct sock *sk, | |||
| 285 | static int ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb) | 286 | static int ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb) |
| 286 | { | 287 | { |
| 287 | unsigned int mtu; | 288 | unsigned int mtu; |
| 289 | int ret; | ||
| 290 | |||
| 291 | ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb); | ||
| 292 | if (ret) { | ||
| 293 | kfree_skb(skb); | ||
| 294 | return ret; | ||
| 295 | } | ||
| 288 | 296 | ||
| 289 | #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) | 297 | #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM) |
| 290 | /* Policy lookup after SNAT yielded a new policy */ | 298 | /* Policy lookup after SNAT yielded a new policy */ |
| @@ -303,6 +311,20 @@ static int ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *sk | |||
| 303 | return ip_finish_output2(net, sk, skb); | 311 | return ip_finish_output2(net, sk, skb); |
| 304 | } | 312 | } |
| 305 | 313 | ||
| 314 | static int ip_mc_finish_output(struct net *net, struct sock *sk, | ||
| 315 | struct sk_buff *skb) | ||
| 316 | { | ||
| 317 | int ret; | ||
| 318 | |||
| 319 | ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb); | ||
| 320 | if (ret) { | ||
| 321 | kfree_skb(skb); | ||
| 322 | return ret; | ||
| 323 | } | ||
| 324 | |||
| 325 | return dev_loopback_xmit(net, sk, skb); | ||
| 326 | } | ||
| 327 | |||
| 306 | int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb) | 328 | int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb) |
| 307 | { | 329 | { |
| 308 | struct rtable *rt = skb_rtable(skb); | 330 | struct rtable *rt = skb_rtable(skb); |
| @@ -340,7 +362,7 @@ int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb) | |||
| 340 | if (newskb) | 362 | if (newskb) |
| 341 | NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, | 363 | NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, |
| 342 | net, sk, newskb, NULL, newskb->dev, | 364 | net, sk, newskb, NULL, newskb->dev, |
| 343 | dev_loopback_xmit); | 365 | ip_mc_finish_output); |
| 344 | } | 366 | } |
| 345 | 367 | ||
| 346 | /* Multicasts with ttl 0 must not go beyond the host */ | 368 | /* Multicasts with ttl 0 must not go beyond the host */ |
| @@ -356,7 +378,7 @@ int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb) | |||
| 356 | if (newskb) | 378 | if (newskb) |
| 357 | NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, | 379 | NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, |
| 358 | net, sk, newskb, NULL, newskb->dev, | 380 | net, sk, newskb, NULL, newskb->dev, |
| 359 | dev_loopback_xmit); | 381 | ip_mc_finish_output); |
| 360 | } | 382 | } |
| 361 | 383 | ||
| 362 | return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, | 384 | return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, |
