nf_conntrack_broadcast.c 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * broadcast connection tracking helper
  4. *
  5. * (c) 2005 Patrick McHardy <kaber@trash.net>
  6. */
  7. #include <linux/module.h>
  8. #include <linux/ip.h>
  9. #include <net/route.h>
  10. #include <linux/inetdevice.h>
  11. #include <linux/skbuff.h>
  12. #include <net/netfilter/nf_conntrack.h>
  13. #include <net/netfilter/nf_conntrack_helper.h>
  14. #include <net/netfilter/nf_conntrack_expect.h>
  15. int nf_conntrack_broadcast_help(struct sk_buff *skb,
  16. struct nf_conn *ct,
  17. enum ip_conntrack_info ctinfo,
  18. unsigned int timeout)
  19. {
  20. struct nf_conntrack_expect *exp;
  21. struct iphdr *iph = ip_hdr(skb);
  22. struct rtable *rt = skb_rtable(skb);
  23. struct in_device *in_dev;
  24. struct nf_conn_help *help = nfct_help(ct);
  25. __be32 mask = 0;
  26. /* we're only interested in locally generated packets */
  27. if (skb->sk == NULL || !net_eq(nf_ct_net(ct), sock_net(skb->sk)))
  28. goto out;
  29. if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST))
  30. goto out;
  31. if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
  32. goto out;
  33. in_dev = __in_dev_get_rcu(rt->dst.dev);
  34. if (in_dev != NULL) {
  35. const struct in_ifaddr *ifa;
  36. in_dev_for_each_ifa_rcu(ifa, in_dev) {
  37. if (ifa->ifa_flags & IFA_F_SECONDARY)
  38. continue;
  39. if (ifa->ifa_broadcast == iph->daddr) {
  40. mask = ifa->ifa_mask;
  41. break;
  42. }
  43. }
  44. }
  45. if (mask == 0)
  46. goto out;
  47. exp = nf_ct_expect_alloc(ct);
  48. if (exp == NULL)
  49. goto out;
  50. exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
  51. exp->tuple.src.u.udp.port = help->helper->tuple.src.u.udp.port;
  52. exp->mask.src.u3.ip = mask;
  53. exp->mask.src.u.udp.port = htons(0xFFFF);
  54. exp->expectfn = NULL;
  55. exp->flags = NF_CT_EXPECT_PERMANENT;
  56. exp->class = NF_CT_EXPECT_CLASS_DEFAULT;
  57. exp->helper = NULL;
  58. nf_ct_expect_related(exp, 0);
  59. nf_ct_expect_put(exp);
  60. nf_ct_refresh(ct, skb, timeout * HZ);
  61. out:
  62. return NF_ACCEPT;
  63. }
  64. EXPORT_SYMBOL_GPL(nf_conntrack_broadcast_help);
  65. MODULE_LICENSE("GPL");