Skip to content

Commit

Permalink
netfilter: avoid using skb->nf_bridge directly
Browse files Browse the repository at this point in the history
This pointer is going to be removed soon, so use the existing helpers in
more places to avoid noise when the removal happens.

Signed-off-by: Florian Westphal <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Florian Westphal authored and davem330 committed Dec 19, 2018
1 parent 8239d57 commit c4b0e77
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 66 deletions.
33 changes: 24 additions & 9 deletions include/linux/netfilter_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,43 +17,58 @@ static inline void br_drop_fake_rtable(struct sk_buff *skb)
skb_dst_drop(skb);
}

static inline struct nf_bridge_info *
nf_bridge_info_get(const struct sk_buff *skb)
{
return skb->nf_bridge;
}

static inline bool nf_bridge_info_exists(const struct sk_buff *skb)
{
return skb->nf_bridge != NULL;
}

static inline int nf_bridge_get_physinif(const struct sk_buff *skb)
{
struct nf_bridge_info *nf_bridge;
const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);

if (skb->nf_bridge == NULL)
if (!nf_bridge)
return 0;

nf_bridge = skb->nf_bridge;
return nf_bridge->physindev ? nf_bridge->physindev->ifindex : 0;
}

static inline int nf_bridge_get_physoutif(const struct sk_buff *skb)
{
struct nf_bridge_info *nf_bridge;
const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);

if (skb->nf_bridge == NULL)
if (!nf_bridge)
return 0;

nf_bridge = skb->nf_bridge;
return nf_bridge->physoutdev ? nf_bridge->physoutdev->ifindex : 0;
}

static inline struct net_device *
nf_bridge_get_physindev(const struct sk_buff *skb)
{
return skb->nf_bridge ? skb->nf_bridge->physindev : NULL;
const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);

return nf_bridge ? nf_bridge->physindev : NULL;
}

static inline struct net_device *
nf_bridge_get_physoutdev(const struct sk_buff *skb)
{
return skb->nf_bridge ? skb->nf_bridge->physoutdev : NULL;
const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);

return nf_bridge ? nf_bridge->physoutdev : NULL;
}

static inline bool nf_bridge_in_prerouting(const struct sk_buff *skb)
{
return skb->nf_bridge && skb->nf_bridge->in_prerouting;
const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);

return nf_bridge && nf_bridge->in_prerouting;
}
#else
#define br_drop_fake_rtable(skb) do { } while (0)
Expand Down
6 changes: 0 additions & 6 deletions include/net/netfilter/br_netfilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@ int br_nf_hook_thresh(unsigned int hook, struct net *net, struct sock *sk,
int (*okfn)(struct net *, struct sock *,
struct sk_buff *));

static inline struct nf_bridge_info *
nf_bridge_info_get(const struct sk_buff *skb)
{
return skb->nf_bridge;
}

unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb);

static inline void nf_bridge_push_encap_header(struct sk_buff *skb)
Expand Down
19 changes: 14 additions & 5 deletions net/bridge/br_netfilter_hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,9 @@ static int br_validate_ipv4(struct net *net, struct sk_buff *skb)

void nf_bridge_update_protocol(struct sk_buff *skb)
{
switch (skb->nf_bridge->orig_proto) {
const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);

switch (nf_bridge->orig_proto) {
case BRNF_PROTO_8021Q:
skb->protocol = htons(ETH_P_8021Q);
break;
Expand Down Expand Up @@ -569,7 +571,8 @@ static unsigned int br_nf_forward_ip(void *priv,
struct net_device *parent;
u_int8_t pf;

if (!skb->nf_bridge)
nf_bridge = nf_bridge_info_get(skb);
if (!nf_bridge)
return NF_ACCEPT;

/* Need exclusive nf_bridge_info since we might have multiple
Expand Down Expand Up @@ -701,7 +704,9 @@ br_nf_ip_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,

static unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb)
{
if (skb->nf_bridge->orig_proto == BRNF_PROTO_PPPOE)
const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);

if (nf_bridge->orig_proto == BRNF_PROTO_PPPOE)
return PPPOE_SES_HLEN;
return 0;
}
Expand Down Expand Up @@ -839,7 +844,9 @@ static unsigned int ip_sabotage_in(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
if (skb->nf_bridge && !skb->nf_bridge->in_prerouting &&
struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);

if (nf_bridge && !nf_bridge->in_prerouting &&
!netif_is_l3_master(skb->dev)) {
state->okfn(state->net, state->sk, skb);
return NF_STOLEN;
Expand Down Expand Up @@ -877,7 +884,9 @@ static void br_nf_pre_routing_finish_bridge_slow(struct sk_buff *skb)

static int br_nf_dev_xmit(struct sk_buff *skb)
{
if (skb->nf_bridge && skb->nf_bridge->bridged_dnat) {
const struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);

if (nf_bridge && nf_bridge->bridged_dnat) {
br_nf_pre_routing_finish_bridge_slow(skb);
return 1;
}
Expand Down
6 changes: 4 additions & 2 deletions net/ipv4/netfilter/nf_reject_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ EXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_put);
/* Send RST reply */
void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)
{
struct net_device *br_indev __maybe_unused;
struct sk_buff *nskb;
struct iphdr *niph;
const struct tcphdr *oth;
Expand Down Expand Up @@ -147,10 +148,11 @@ void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)
* build the eth header using the original destination's MAC as the
* source, and send the RST packet directly.
*/
if (oldskb->nf_bridge) {
br_indev = nf_bridge_get_physindev(oldskb);
if (br_indev) {
struct ethhdr *oeth = eth_hdr(oldskb);

nskb->dev = nf_bridge_get_physindev(oldskb);
nskb->dev = br_indev;
niph->tot_len = htons(nskb->len);
ip_send_check(niph);
if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
Expand Down
10 changes: 7 additions & 3 deletions net/ipv6/netfilter/nf_reject_ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ EXPORT_SYMBOL_GPL(nf_reject_ip6_tcphdr_put);

void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
{
struct net_device *br_indev __maybe_unused;
struct sk_buff *nskb;
struct tcphdr _otcph;
const struct tcphdr *otcph;
Expand Down Expand Up @@ -197,15 +198,18 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
* build the eth header using the original destination's MAC as the
* source, and send the RST packet directly.
*/
if (oldskb->nf_bridge) {
br_indev = nf_bridge_get_physindev(oldskb);
if (br_indev) {
struct ethhdr *oeth = eth_hdr(oldskb);

nskb->dev = nf_bridge_get_physindev(oldskb);
nskb->dev = br_indev;
nskb->protocol = htons(ETH_P_IPV6);
ip6h->payload_len = htons(sizeof(struct tcphdr));
if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
oeth->h_source, oeth->h_dest, nskb->len) < 0)
oeth->h_source, oeth->h_dest, nskb->len) < 0) {
kfree_skb(nskb);
return;
}
dev_queue_xmit(nskb);
} else
#endif
Expand Down
20 changes: 9 additions & 11 deletions net/netfilter/nf_log_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,22 +156,20 @@ nf_log_dump_packet_common(struct nf_log_buf *m, u_int8_t pf,
const struct net_device *out,
const struct nf_loginfo *loginfo, const char *prefix)
{
const struct net_device *physoutdev __maybe_unused;
const struct net_device *physindev __maybe_unused;

nf_log_buf_add(m, KERN_SOH "%c%sIN=%s OUT=%s ",
'0' + loginfo->u.log.level, prefix,
in ? in->name : "",
out ? out->name : "");
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
if (skb->nf_bridge) {
const struct net_device *physindev;
const struct net_device *physoutdev;

physindev = nf_bridge_get_physindev(skb);
if (physindev && in != physindev)
nf_log_buf_add(m, "PHYSIN=%s ", physindev->name);
physoutdev = nf_bridge_get_physoutdev(skb);
if (physoutdev && out != physoutdev)
nf_log_buf_add(m, "PHYSOUT=%s ", physoutdev->name);
}
physindev = nf_bridge_get_physindev(skb);
if (physindev && in != physindev)
nf_log_buf_add(m, "PHYSIN=%s ", physindev->name);
physoutdev = nf_bridge_get_physoutdev(skb);
if (physoutdev && out != physoutdev)
nf_log_buf_add(m, "PHYSOUT=%s ", physoutdev->name);
#endif
}
EXPORT_SYMBOL_GPL(nf_log_dump_packet_common);
Expand Down
50 changes: 33 additions & 17 deletions net/netfilter/nf_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,24 @@ void nf_unregister_queue_handler(struct net *net)
}
EXPORT_SYMBOL(nf_unregister_queue_handler);

static void nf_queue_entry_release_br_nf_refs(struct sk_buff *skb)
{
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);

if (nf_bridge) {
struct net_device *physdev;

physdev = nf_bridge_get_physindev(skb);
if (physdev)
dev_put(physdev);
physdev = nf_bridge_get_physoutdev(skb);
if (physdev)
dev_put(physdev);
}
#endif
}

void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
{
struct nf_hook_state *state = &entry->state;
Expand All @@ -57,20 +75,28 @@ void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
dev_put(state->out);
if (state->sk)
sock_put(state->sk);

nf_queue_entry_release_br_nf_refs(entry->skb);
}
EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs);

static void nf_queue_entry_get_br_nf_refs(struct sk_buff *skb)
{
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
if (entry->skb->nf_bridge) {
struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);

if (nf_bridge) {
struct net_device *physdev;

physdev = nf_bridge_get_physindev(entry->skb);
physdev = nf_bridge_get_physindev(skb);
if (physdev)
dev_put(physdev);
physdev = nf_bridge_get_physoutdev(entry->skb);
dev_hold(physdev);
physdev = nf_bridge_get_physoutdev(skb);
if (physdev)
dev_put(physdev);
dev_hold(physdev);
}
#endif
}
EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs);

/* Bump dev refs so they don't vanish while packet is out */
void nf_queue_entry_get_refs(struct nf_queue_entry *entry)
Expand All @@ -83,18 +109,8 @@ void nf_queue_entry_get_refs(struct nf_queue_entry *entry)
dev_hold(state->out);
if (state->sk)
sock_hold(state->sk);
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
if (entry->skb->nf_bridge) {
struct net_device *physdev;

physdev = nf_bridge_get_physindev(entry->skb);
if (physdev)
dev_hold(physdev);
physdev = nf_bridge_get_physoutdev(entry->skb);
if (physdev)
dev_hold(physdev);
}
#endif
nf_queue_entry_get_br_nf_refs(entry->skb);
}
EXPORT_SYMBOL_GPL(nf_queue_entry_get_refs);

Expand Down
23 changes: 11 additions & 12 deletions net/netfilter/nfnetlink_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -727,13 +727,13 @@ nf_queue_entry_dup(struct nf_queue_entry *e)
*/
static void nf_bridge_adjust_skb_data(struct sk_buff *skb)
{
if (skb->nf_bridge)
if (nf_bridge_info_get(skb))
__skb_push(skb, skb->network_header - skb->mac_header);
}

static void nf_bridge_adjust_segmented_data(struct sk_buff *skb)
{
if (skb->nf_bridge)
if (nf_bridge_info_get(skb))
__skb_pull(skb, skb->network_header - skb->mac_header);
}
#else
Expand Down Expand Up @@ -904,23 +904,22 @@ nfqnl_set_mode(struct nfqnl_instance *queue,
static int
dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
{
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
int physinif, physoutif;

physinif = nf_bridge_get_physinif(entry->skb);
physoutif = nf_bridge_get_physoutif(entry->skb);

if (physinif == ifindex || physoutif == ifindex)
return 1;
#endif
if (entry->state.in)
if (entry->state.in->ifindex == ifindex)
return 1;
if (entry->state.out)
if (entry->state.out->ifindex == ifindex)
return 1;
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
if (entry->skb->nf_bridge) {
int physinif, physoutif;

physinif = nf_bridge_get_physinif(entry->skb);
physoutif = nf_bridge_get_physoutif(entry->skb);

if (physinif == ifindex || physoutif == ifindex)
return 1;
}
#endif
return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion net/netfilter/xt_physdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ physdev_mt(const struct sk_buff *skb, struct xt_action_param *par)
/* Not a bridged IP packet or no info available yet:
* LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if
* the destination device will be a bridge. */
if (!skb->nf_bridge) {
if (!nf_bridge_info_exists(skb)) {
/* Return MATCH if the invert flags of the used options are on */
if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
!(info->invert & XT_PHYSDEV_OP_BRIDGED))
Expand Down

0 comments on commit c4b0e77

Please sign in to comment.