📄 br_netfilter.c
字号:
has_bridge_parent(realindev)) realindev = bridge_parent(realindev); NF_HOOK_THRESH(pf, NF_IP_FORWARD, skb, realindev, realoutdev, br_nf_local_out_finish, NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD + 1); } else {#ifdef CONFIG_NETFILTER_DEBUG skb->nf_debug ^= (1 << NF_IP_LOCAL_OUT);#endif NF_HOOK_THRESH(pf, NF_IP_LOCAL_OUT, skb, realindev, realoutdev, br_nf_local_out_finish, NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT + 1); }out: return NF_STOLEN;}/* PF_BRIDGE/POST_ROUTING ********************************************/static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)){ struct sk_buff *skb = *pskb; struct nf_bridge_info *nf_bridge = (*pskb)->nf_bridge; struct vlan_ethhdr *hdr = vlan_eth_hdr(skb); struct net_device *realoutdev = bridge_parent(skb->dev); int pf;#ifdef CONFIG_NETFILTER_DEBUG /* Be very paranoid. This probably won't happen anymore, but let's * keep the check just to be sure... */ if (skb->mac.raw < skb->head || skb->mac.raw + ETH_HLEN > skb->data) { printk(KERN_CRIT "br_netfilter: Argh!! br_nf_post_routing: " "bad mac.raw pointer."); goto print_error; }#endif if (!nf_bridge) return NF_ACCEPT; if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) pf = PF_INET; else pf = PF_INET6;#ifdef CONFIG_NETFILTER_DEBUG if (skb->dst == NULL) { printk(KERN_CRIT "br_netfilter: skb->dst == NULL."); goto print_error; } skb->nf_debug ^= (1 << NF_IP_POST_ROUTING);#endif /* We assume any code from br_dev_queue_push_xmit onwards doesn't care * about the value of skb->pkt_type. */ if (skb->pkt_type == PACKET_OTHERHOST) { skb->pkt_type = PACKET_HOST; nf_bridge->mask |= BRNF_PKT_TYPE; } if (skb->protocol == __constant_htons(ETH_P_8021Q)) { skb_pull(skb, VLAN_HLEN); skb->nh.raw += VLAN_HLEN; } nf_bridge_save_header(skb);#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) if (nf_bridge->netoutdev) realoutdev = nf_bridge->netoutdev;#endif NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev, br_dev_queue_push_xmit); return NF_STOLEN;#ifdef CONFIG_NETFILTER_DEBUGprint_error: if (skb->dev != NULL) { printk("[%s]", skb->dev->name); if (has_bridge_parent(skb->dev)) printk("[%s]", bridge_parent(skb->dev)->name); } printk(" head:%p, raw:%p, data:%p\n", skb->head, skb->mac.raw, skb->data); return NF_ACCEPT;#endif}/* IP/SABOTAGE *****************************************************//* Don't hand locally destined packets to PF_INET(6)/PRE_ROUTING * for the second time. */static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)){ if ((*pskb)->nf_bridge && !((*pskb)->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) { okfn(*pskb); return NF_STOLEN; } return NF_ACCEPT;}/* Postpone execution of PF_INET(6)/FORWARD, PF_INET(6)/LOCAL_OUT * and PF_INET(6)/POST_ROUTING until we have done the forwarding * decision in the bridge code and have determined nf_bridge->physoutdev. */static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)){ struct sk_buff *skb = *pskb;#ifdef CONFIG_SYSCTL if (!skb->nf_bridge) { struct vlan_ethhdr *hdr = vlan_eth_hdr(skb); if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) { if (!brnf_call_iptables) return NF_ACCEPT; } else if (!brnf_call_ip6tables) return NF_ACCEPT; }#endif if ((out->hard_start_xmit == br_dev_xmit && okfn != br_nf_forward_finish && okfn != br_nf_local_out_finish && okfn != br_dev_queue_push_xmit)#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) || ((out->priv_flags & IFF_802_1Q_VLAN) && VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit)#endif ) { struct nf_bridge_info *nf_bridge; if (!skb->nf_bridge && !nf_bridge_alloc(skb)) return NF_DROP; nf_bridge = skb->nf_bridge; /* This frame will arrive on PF_BRIDGE/LOCAL_OUT and we * will need the indev then. For a brouter, the real indev * can be a bridge port, so we make sure br_nf_local_out() * doesn't use the bridge parent of the indev by using * the BRNF_DONT_TAKE_PARENT mask. */ if (hook == NF_IP_FORWARD && nf_bridge->physindev == NULL) { nf_bridge->mask &= BRNF_DONT_TAKE_PARENT; nf_bridge->physindev = (struct net_device *)in; }#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) /* the iptables outdev is br0.x, not br0 */ if (out->priv_flags & IFF_802_1Q_VLAN) nf_bridge->netoutdev = (struct net_device *)out;#endif okfn(skb); return NF_STOLEN; } return NF_ACCEPT;}/* For br_nf_local_out we need (prio = NF_BR_PRI_FIRST), to insure that innocent * PF_BRIDGE/NF_BR_LOCAL_OUT functions don't get bridged traffic as input. * For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because * ip_refrag() can return NF_STOLEN. */static struct nf_hook_ops br_nf_ops[] = { { .hook = br_nf_pre_routing, .owner = THIS_MODULE, .pf = PF_BRIDGE, .hooknum = NF_BR_PRE_ROUTING, .priority = NF_BR_PRI_BRNF, }, { .hook = br_nf_local_in, .owner = THIS_MODULE, .pf = PF_BRIDGE, .hooknum = NF_BR_LOCAL_IN, .priority = NF_BR_PRI_BRNF, }, { .hook = br_nf_forward_ip, .owner = THIS_MODULE, .pf = PF_BRIDGE, .hooknum = NF_BR_FORWARD, .priority = NF_BR_PRI_BRNF - 1, }, { .hook = br_nf_forward_arp, .owner = THIS_MODULE, .pf = PF_BRIDGE, .hooknum = NF_BR_FORWARD, .priority = NF_BR_PRI_BRNF, }, { .hook = br_nf_local_out, .owner = THIS_MODULE, .pf = PF_BRIDGE, .hooknum = NF_BR_LOCAL_OUT, .priority = NF_BR_PRI_FIRST, }, { .hook = br_nf_post_routing, .owner = THIS_MODULE, .pf = PF_BRIDGE, .hooknum = NF_BR_POST_ROUTING, .priority = NF_BR_PRI_LAST, }, { .hook = ip_sabotage_in, .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_PRE_ROUTING, .priority = NF_IP_PRI_FIRST, }, { .hook = ip_sabotage_in, .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_IP6_PRE_ROUTING, .priority = NF_IP6_PRI_FIRST, }, { .hook = ip_sabotage_out, .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_FORWARD, .priority = NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD, }, { .hook = ip_sabotage_out, .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_IP6_FORWARD, .priority = NF_IP6_PRI_BRIDGE_SABOTAGE_FORWARD, }, { .hook = ip_sabotage_out, .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_LOCAL_OUT, .priority = NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT, }, { .hook = ip_sabotage_out, .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_IP6_LOCAL_OUT, .priority = NF_IP6_PRI_BRIDGE_SABOTAGE_LOCAL_OUT, }, { .hook = ip_sabotage_out, .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_POST_ROUTING, .priority = NF_IP_PRI_FIRST, }, { .hook = ip_sabotage_out, .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_IP6_POST_ROUTING, .priority = NF_IP6_PRI_FIRST, },};#ifdef CONFIG_SYSCTLstaticint brnf_sysctl_call_tables(ctl_table *ctl, int write, struct file * filp, void __user *buffer, size_t *lenp, loff_t *ppos){ int ret; ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); if (write && *(int *)(ctl->data)) *(int *)(ctl->data) = 1; return ret;}static ctl_table brnf_table[] = { { .ctl_name = NET_BRIDGE_NF_CALL_ARPTABLES, .procname = "bridge-nf-call-arptables", .data = &brnf_call_arptables, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &brnf_sysctl_call_tables, }, { .ctl_name = NET_BRIDGE_NF_CALL_IPTABLES, .procname = "bridge-nf-call-iptables", .data = &brnf_call_iptables, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &brnf_sysctl_call_tables, }, { .ctl_name = NET_BRIDGE_NF_CALL_IP6TABLES, .procname = "bridge-nf-call-ip6tables", .data = &brnf_call_ip6tables, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &brnf_sysctl_call_tables, }, { .ctl_name = NET_BRIDGE_NF_FILTER_VLAN_TAGGED, .procname = "bridge-nf-filter-vlan-tagged", .data = &brnf_filter_vlan_tagged, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &brnf_sysctl_call_tables, }, { .ctl_name = 0 }};static ctl_table brnf_bridge_table[] = { { .ctl_name = NET_BRIDGE, .procname = "bridge", .mode = 0555, .child = brnf_table, }, { .ctl_name = 0 }};static ctl_table brnf_net_table[] = { { .ctl_name = CTL_NET, .procname = "net", .mode = 0555, .child = brnf_bridge_table, }, { .ctl_name = 0 }};#endifint br_netfilter_init(void){ int i; for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++) { int ret; if ((ret = nf_register_hook(&br_nf_ops[i])) >= 0) continue; while (i--) nf_unregister_hook(&br_nf_ops[i]); return ret; }#ifdef CONFIG_SYSCTL brnf_sysctl_header = register_sysctl_table(brnf_net_table, 0); if (brnf_sysctl_header == NULL) { printk(KERN_WARNING "br_netfilter: can't register to sysctl.\n"); for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++) nf_unregister_hook(&br_nf_ops[i]); return -EFAULT; }#endif printk(KERN_NOTICE "Bridge firewalling registered\n"); return 0;}void br_netfilter_fini(void){ int i; for (i = ARRAY_SIZE(br_nf_ops) - 1; i >= 0; i--) nf_unregister_hook(&br_nf_ops[i]);#ifdef CONFIG_SYSCTL unregister_sysctl_table(brnf_sysctl_header);#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -