output_core.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /*
  2. * IPv6 library code, needed by static components when full IPv6 support is
  3. * not configured or static. These functions are needed by GSO/GRO implementation.
  4. */
  5. #include <linux/export.h>
  6. #include <net/ip.h>
  7. #include <net/ipv6.h>
  8. #include <net/ip6_fib.h>
  9. #include <net/addrconf.h>
  10. #include <net/secure_seq.h>
  11. /* This function exists only for tap drivers that must support broken
  12. * clients requesting UFO without specifying an IPv6 fragment ID.
  13. *
  14. * This is similar to ipv6_select_ident() but we use an independent hash
  15. * seed to limit information leakage.
  16. *
  17. * The network header must be set before calling this.
  18. */
  19. void ipv6_proxy_select_ident(struct sk_buff *skb)
  20. {
  21. static u32 ip6_proxy_idents_hashrnd __read_mostly;
  22. struct in6_addr buf[2];
  23. struct in6_addr *addrs;
  24. u32 hash, id;
  25. addrs = skb_header_pointer(skb,
  26. skb_network_offset(skb) +
  27. offsetof(struct ipv6hdr, saddr),
  28. sizeof(buf), buf);
  29. if (!addrs)
  30. return;
  31. net_get_random_once(&ip6_proxy_idents_hashrnd,
  32. sizeof(ip6_proxy_idents_hashrnd));
  33. hash = __ipv6_addr_jhash(&addrs[1], ip6_proxy_idents_hashrnd);
  34. hash = __ipv6_addr_jhash(&addrs[0], hash);
  35. id = ip_idents_reserve(hash, 1);
  36. skb_shinfo(skb)->ip6_frag_id = htonl(id);
  37. }
  38. EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident);
  39. int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
  40. {
  41. u16 offset = sizeof(struct ipv6hdr);
  42. struct ipv6_opt_hdr *exthdr =
  43. (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
  44. unsigned int packet_len = skb_tail_pointer(skb) -
  45. skb_network_header(skb);
  46. int found_rhdr = 0;
  47. *nexthdr = &ipv6_hdr(skb)->nexthdr;
  48. while (offset + 1 <= packet_len) {
  49. switch (**nexthdr) {
  50. case NEXTHDR_HOP:
  51. break;
  52. case NEXTHDR_ROUTING:
  53. found_rhdr = 1;
  54. break;
  55. case NEXTHDR_DEST:
  56. #if IS_ENABLED(CONFIG_IPV6_MIP6)
  57. if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
  58. break;
  59. #endif
  60. if (found_rhdr)
  61. return offset;
  62. break;
  63. default:
  64. return offset;
  65. }
  66. offset += ipv6_optlen(exthdr);
  67. *nexthdr = &exthdr->nexthdr;
  68. exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
  69. offset);
  70. }
  71. return offset;
  72. }
  73. EXPORT_SYMBOL(ip6_find_1stfragopt);
  74. #if IS_ENABLED(CONFIG_IPV6)
  75. int ip6_dst_hoplimit(struct dst_entry *dst)
  76. {
  77. int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT);
  78. if (hoplimit == 0) {
  79. struct net_device *dev = dst->dev;
  80. struct inet6_dev *idev;
  81. rcu_read_lock();
  82. idev = __in6_dev_get(dev);
  83. if (idev)
  84. hoplimit = idev->cnf.hop_limit;
  85. else
  86. hoplimit = dev_net(dev)->ipv6.devconf_all->hop_limit;
  87. rcu_read_unlock();
  88. }
  89. return hoplimit;
  90. }
  91. EXPORT_SYMBOL(ip6_dst_hoplimit);
  92. #endif
  93. int __ip6_local_out(struct sk_buff *skb)
  94. {
  95. int len;
  96. len = skb->len - sizeof(struct ipv6hdr);
  97. if (len > IPV6_MAXPLEN)
  98. len = 0;
  99. ipv6_hdr(skb)->payload_len = htons(len);
  100. IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
  101. return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL,
  102. skb_dst(skb)->dev, dst_output);
  103. }
  104. EXPORT_SYMBOL_GPL(__ip6_local_out);
  105. int ip6_local_out(struct sk_buff *skb)
  106. {
  107. int err;
  108. err = __ip6_local_out(skb);
  109. if (likely(err == 1))
  110. err = dst_output(skb);
  111. return err;
  112. }
  113. EXPORT_SYMBOL_GPL(ip6_local_out);