nf_nat_helper.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* nf_nat_helper.c - generic support functions for NAT helpers
  3. *
  4. * (C) 2000-2002 Harald Welte <laforge@netfilter.org>
  5. * (C) 2003-2006 Netfilter Core Team <coreteam@netfilter.org>
  6. * (C) 2007-2012 Patrick McHardy <kaber@trash.net>
  7. */
  8. #include <linux/module.h>
  9. #include <linux/gfp.h>
  10. #include <linux/types.h>
  11. #include <linux/skbuff.h>
  12. #include <linux/tcp.h>
  13. #include <linux/udp.h>
  14. #include <net/tcp.h>
  15. #include <net/netfilter/nf_conntrack.h>
  16. #include <net/netfilter/nf_conntrack_helper.h>
  17. #include <net/netfilter/nf_conntrack_ecache.h>
  18. #include <net/netfilter/nf_conntrack_expect.h>
  19. #include <net/netfilter/nf_conntrack_seqadj.h>
  20. #include <net/netfilter/nf_nat.h>
  21. #include <net/netfilter/nf_nat_helper.h>
  22. /* Frobs data inside this packet, which is linear. */
  23. static void mangle_contents(struct sk_buff *skb,
  24. unsigned int dataoff,
  25. unsigned int match_offset,
  26. unsigned int match_len,
  27. const char *rep_buffer,
  28. unsigned int rep_len)
  29. {
  30. unsigned char *data;
  31. SKB_LINEAR_ASSERT(skb);
  32. data = skb_network_header(skb) + dataoff;
  33. /* move post-replacement */
  34. memmove(data + match_offset + rep_len,
  35. data + match_offset + match_len,
  36. skb_tail_pointer(skb) - (skb_network_header(skb) + dataoff +
  37. match_offset + match_len));
  38. /* insert data from buffer */
  39. memcpy(data + match_offset, rep_buffer, rep_len);
  40. /* update skb info */
  41. if (rep_len > match_len) {
  42. pr_debug("nf_nat_mangle_packet: Extending packet by "
  43. "%u from %u bytes\n", rep_len - match_len, skb->len);
  44. skb_put(skb, rep_len - match_len);
  45. } else {
  46. pr_debug("nf_nat_mangle_packet: Shrinking packet from "
  47. "%u from %u bytes\n", match_len - rep_len, skb->len);
  48. __skb_trim(skb, skb->len + rep_len - match_len);
  49. }
  50. if (nf_ct_l3num((struct nf_conn *)skb_nfct(skb)) == NFPROTO_IPV4) {
  51. /* fix IP hdr checksum information */
  52. ip_hdr(skb)->tot_len = htons(skb->len);
  53. ip_send_check(ip_hdr(skb));
  54. } else
  55. ipv6_hdr(skb)->payload_len =
  56. htons(skb->len - sizeof(struct ipv6hdr));
  57. }
  58. /* Unusual, but possible case. */
  59. static bool enlarge_skb(struct sk_buff *skb, unsigned int extra)
  60. {
  61. if (skb->len + extra > 65535)
  62. return false;
  63. if (pskb_expand_head(skb, 0, extra - skb_tailroom(skb), GFP_ATOMIC))
  64. return false;
  65. return true;
  66. }
  67. /* Generic function for mangling variable-length address changes inside
  68. * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
  69. * command in FTP).
  70. *
  71. * Takes care about all the nasty sequence number changes, checksumming,
  72. * skb enlargement, ...
  73. *
  74. * */
  75. bool __nf_nat_mangle_tcp_packet(struct sk_buff *skb,
  76. struct nf_conn *ct,
  77. enum ip_conntrack_info ctinfo,
  78. unsigned int protoff,
  79. unsigned int match_offset,
  80. unsigned int match_len,
  81. const char *rep_buffer,
  82. unsigned int rep_len, bool adjust)
  83. {
  84. struct tcphdr *tcph;
  85. int oldlen, datalen;
  86. if (skb_ensure_writable(skb, skb->len))
  87. return false;
  88. if (rep_len > match_len &&
  89. rep_len - match_len > skb_tailroom(skb) &&
  90. !enlarge_skb(skb, rep_len - match_len))
  91. return false;
  92. tcph = (void *)skb->data + protoff;
  93. oldlen = skb->len - protoff;
  94. mangle_contents(skb, protoff + tcph->doff*4,
  95. match_offset, match_len, rep_buffer, rep_len);
  96. datalen = skb->len - protoff;
  97. nf_nat_csum_recalc(skb, nf_ct_l3num(ct), IPPROTO_TCP,
  98. tcph, &tcph->check, datalen, oldlen);
  99. if (adjust && rep_len != match_len)
  100. nf_ct_seqadj_set(ct, ctinfo, tcph->seq,
  101. (int)rep_len - (int)match_len);
  102. return true;
  103. }
  104. EXPORT_SYMBOL(__nf_nat_mangle_tcp_packet);
  105. /* Generic function for mangling variable-length address changes inside
  106. * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
  107. * command in the Amanda protocol)
  108. *
  109. * Takes care about all the nasty sequence number changes, checksumming,
  110. * skb enlargement, ...
  111. *
  112. * XXX - This function could be merged with nf_nat_mangle_tcp_packet which
  113. * should be fairly easy to do.
  114. */
  115. bool
  116. nf_nat_mangle_udp_packet(struct sk_buff *skb,
  117. struct nf_conn *ct,
  118. enum ip_conntrack_info ctinfo,
  119. unsigned int protoff,
  120. unsigned int match_offset,
  121. unsigned int match_len,
  122. const char *rep_buffer,
  123. unsigned int rep_len)
  124. {
  125. struct udphdr *udph;
  126. int datalen, oldlen;
  127. if (skb_ensure_writable(skb, skb->len))
  128. return false;
  129. if (rep_len > match_len &&
  130. rep_len - match_len > skb_tailroom(skb) &&
  131. !enlarge_skb(skb, rep_len - match_len))
  132. return false;
  133. udph = (void *)skb->data + protoff;
  134. oldlen = skb->len - protoff;
  135. mangle_contents(skb, protoff + sizeof(*udph),
  136. match_offset, match_len, rep_buffer, rep_len);
  137. /* update the length of the UDP packet */
  138. datalen = skb->len - protoff;
  139. udph->len = htons(datalen);
  140. /* fix udp checksum if udp checksum was previously calculated */
  141. if (!udph->check && skb->ip_summed != CHECKSUM_PARTIAL)
  142. return true;
  143. nf_nat_csum_recalc(skb, nf_ct_l3num(ct), IPPROTO_UDP,
  144. udph, &udph->check, datalen, oldlen);
  145. return true;
  146. }
  147. EXPORT_SYMBOL(nf_nat_mangle_udp_packet);
  148. /* Setup NAT on this expected conntrack so it follows master. */
  149. /* If we fail to get a free NAT slot, we'll get dropped on confirm */
  150. void nf_nat_follow_master(struct nf_conn *ct,
  151. struct nf_conntrack_expect *exp)
  152. {
  153. struct nf_nat_range2 range;
  154. /* This must be a fresh one. */
  155. BUG_ON(ct->status & IPS_NAT_DONE_MASK);
  156. /* Change src to where master sends to */
  157. range.flags = NF_NAT_RANGE_MAP_IPS;
  158. range.min_addr = range.max_addr
  159. = ct->master->tuplehash[!exp->dir].tuple.dst.u3;
  160. nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC);
  161. /* For DST manip, map port here to where it's expected. */
  162. range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
  163. range.min_proto = range.max_proto = exp->saved_proto;
  164. range.min_addr = range.max_addr
  165. = ct->master->tuplehash[!exp->dir].tuple.src.u3;
  166. nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
  167. }
  168. EXPORT_SYMBOL(nf_nat_follow_master);