nf_nat_helper.c 6.2 KB

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