ip_nat_core.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:30k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* NAT for netfilter; shared with compatibility layer. */
  2. /* (c) 1999 Paul `Rusty' Russell.  Licenced under the GNU General
  3.    Public Licence. */
  4. #ifdef MODULE
  5. #define __NO_VERSION__
  6. #endif
  7. #include <linux/version.h>
  8. #include <linux/module.h>
  9. #include <linux/types.h>
  10. #include <linux/timer.h>
  11. #include <linux/skbuff.h>
  12. #include <linux/netfilter_ipv4.h>
  13. #include <linux/brlock.h>
  14. #include <linux/vmalloc.h>
  15. #include <net/checksum.h>
  16. #include <net/icmp.h>
  17. #include <net/ip.h>
  18. #include <net/tcp.h>  /* For tcp_prot in getorigdst */
  19. #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
  20. #define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
  21. #include <linux/netfilter_ipv4/ip_conntrack.h>
  22. #include <linux/netfilter_ipv4/ip_conntrack_core.h>
  23. #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
  24. #include <linux/netfilter_ipv4/ip_nat.h>
  25. #include <linux/netfilter_ipv4/ip_nat_protocol.h>
  26. #include <linux/netfilter_ipv4/ip_nat_core.h>
  27. #include <linux/netfilter_ipv4/ip_nat_helper.h>
  28. #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
  29. #include <linux/netfilter_ipv4/listhelp.h>
  30. #if 0
  31. #define DEBUGP printk
  32. #else
  33. #define DEBUGP(format, args...)
  34. #endif
  35. DECLARE_RWLOCK(ip_nat_lock);
  36. DECLARE_RWLOCK_EXTERN(ip_conntrack_lock);
  37. /* Calculated at init based on memory size */
  38. static unsigned int ip_nat_htable_size;
  39. static struct list_head *bysource;
  40. static struct list_head *byipsproto;
  41. LIST_HEAD(protos);
  42. LIST_HEAD(helpers);
  43. extern struct ip_nat_protocol unknown_nat_protocol;
  44. /* We keep extra hashes for each conntrack, for fast searching. */
  45. static inline size_t
  46. hash_by_ipsproto(u_int32_t src, u_int32_t dst, u_int16_t proto)
  47. {
  48. /* Modified src and dst, to ensure we don't create two
  49.            identical streams. */
  50. return (src + dst + proto) % ip_nat_htable_size;
  51. }
  52. static inline size_t
  53. hash_by_src(const struct ip_conntrack_manip *manip, u_int16_t proto)
  54. {
  55. /* Original src, to ensure we map it consistently if poss. */
  56. return (manip->ip + manip->u.all + proto) % ip_nat_htable_size;
  57. }
  58. /* Noone using conntrack by the time this called. */
  59. static void ip_nat_cleanup_conntrack(struct ip_conntrack *conn)
  60. {
  61. struct ip_nat_info *info = &conn->nat.info;
  62. if (!info->initialized)
  63. return;
  64. IP_NF_ASSERT(info->bysource.conntrack);
  65. IP_NF_ASSERT(info->byipsproto.conntrack);
  66. WRITE_LOCK(&ip_nat_lock);
  67. LIST_DELETE(&bysource[hash_by_src(&conn->tuplehash[IP_CT_DIR_ORIGINAL]
  68.   .tuple.src,
  69.   conn->tuplehash[IP_CT_DIR_ORIGINAL]
  70.   .tuple.dst.protonum)],
  71.     &info->bysource);
  72. LIST_DELETE(&byipsproto
  73.     [hash_by_ipsproto(conn->tuplehash[IP_CT_DIR_REPLY]
  74.       .tuple.src.ip,
  75.       conn->tuplehash[IP_CT_DIR_REPLY]
  76.       .tuple.dst.ip,
  77.       conn->tuplehash[IP_CT_DIR_REPLY]
  78.       .tuple.dst.protonum)],
  79.     &info->byipsproto);
  80. WRITE_UNLOCK(&ip_nat_lock);
  81. }
  82. /* We do checksum mangling, so if they were wrong before they're still
  83.  * wrong.  Also works for incomplete packets (eg. ICMP dest
  84.  * unreachables.) */
  85. u_int16_t
  86. ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
  87. {
  88. u_int32_t diffs[] = { oldvalinv, newval };
  89. return csum_fold(csum_partial((char *)diffs, sizeof(diffs),
  90.       oldcheck^0xFFFF));
  91. }
  92. static inline int cmp_proto(const struct ip_nat_protocol *i, int proto)
  93. {
  94. return i->protonum == proto;
  95. }
  96. struct ip_nat_protocol *
  97. find_nat_proto(u_int16_t protonum)
  98. {
  99. struct ip_nat_protocol *i;
  100. MUST_BE_READ_LOCKED(&ip_nat_lock);
  101. i = LIST_FIND(&protos, cmp_proto, struct ip_nat_protocol *, protonum);
  102. if (!i)
  103. i = &unknown_nat_protocol;
  104. return i;
  105. }
  106. /* Is this tuple already taken? (not by us) */
  107. int
  108. ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
  109.   const struct ip_conntrack *ignored_conntrack)
  110. {
  111. /* Conntrack tracking doesn't keep track of outgoing tuples; only
  112.    incoming ones.  NAT means they don't have a fixed mapping,
  113.    so we invert the tuple and look for the incoming reply.
  114.    We could keep a separate hash if this proves too slow. */
  115. struct ip_conntrack_tuple reply;
  116. invert_tuplepr(&reply, tuple);
  117. return ip_conntrack_tuple_taken(&reply, ignored_conntrack);
  118. }
  119. /* Does tuple + the source manip come within the range mr */
  120. static int
  121. in_range(const struct ip_conntrack_tuple *tuple,
  122.  const struct ip_conntrack_manip *manip,
  123.  const struct ip_nat_multi_range *mr)
  124. {
  125. struct ip_nat_protocol *proto = find_nat_proto(tuple->dst.protonum);
  126. unsigned int i;
  127. struct ip_conntrack_tuple newtuple = { *manip, tuple->dst };
  128. for (i = 0; i < mr->rangesize; i++) {
  129. /* If we are allowed to map IPs, then we must be in the
  130.    range specified, otherwise we must be unchanged. */
  131. if (mr->range[i].flags & IP_NAT_RANGE_MAP_IPS) {
  132. if (ntohl(newtuple.src.ip) < ntohl(mr->range[i].min_ip)
  133.     || (ntohl(newtuple.src.ip)
  134. > ntohl(mr->range[i].max_ip)))
  135. continue;
  136. } else {
  137. if (newtuple.src.ip != tuple->src.ip)
  138. continue;
  139. }
  140. if ((mr->range[i].flags & IP_NAT_RANGE_PROTO_SPECIFIED)
  141.     && proto->in_range(&newtuple, IP_NAT_MANIP_SRC,
  142.        &mr->range[i].min, &mr->range[i].max))
  143. return 1;
  144. }
  145. return 0;
  146. }
  147. static inline int
  148. src_cmp(const struct ip_nat_hash *i,
  149. const struct ip_conntrack_tuple *tuple,
  150. const struct ip_nat_multi_range *mr)
  151. {
  152. return (i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum
  153. == tuple->dst.protonum
  154. && i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip
  155. == tuple->src.ip
  156. && i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.all
  157. == tuple->src.u.all
  158. && in_range(tuple,
  159.     &i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
  160.     .tuple.src,
  161.     mr));
  162. }
  163. /* Only called for SRC manip */
  164. static struct ip_conntrack_manip *
  165. find_appropriate_src(const struct ip_conntrack_tuple *tuple,
  166.      const struct ip_nat_multi_range *mr)
  167. {
  168. unsigned int h = hash_by_src(&tuple->src, tuple->dst.protonum);
  169. struct ip_nat_hash *i;
  170. MUST_BE_READ_LOCKED(&ip_nat_lock);
  171. i = LIST_FIND(&bysource[h], src_cmp, struct ip_nat_hash *, tuple, mr);
  172. if (i)
  173. return &i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src;
  174. else
  175. return NULL;
  176. }
  177. #ifdef CONFIG_IP_NF_NAT_LOCAL
  178. /* If it's really a local destination manip, it may need to do a
  179.    source manip too. */
  180. static int
  181. do_extra_mangle(u_int32_t var_ip, u_int32_t *other_ipp)
  182. {
  183. struct rtable *rt;
  184. /* FIXME: IPTOS_TOS(iph->tos) --RR */
  185. if (ip_route_output(&rt, var_ip, 0, 0, 0) != 0) {
  186. DEBUGP("do_extra_mangle: Can't get route to %u.%u.%u.%un",
  187.        NIPQUAD(var_ip));
  188. return 0;
  189. }
  190. *other_ipp = rt->rt_src;
  191. ip_rt_put(rt);
  192. return 1;
  193. }
  194. #endif
  195. /* Simple way to iterate through all. */
  196. static inline int fake_cmp(const struct ip_nat_hash *i,
  197.    u_int32_t src, u_int32_t dst, u_int16_t protonum,
  198.    unsigned int *score,
  199.    const struct ip_conntrack *conntrack)
  200. {
  201. /* Compare backwards: we're dealing with OUTGOING tuples, and
  202.            inside the conntrack is the REPLY tuple.  Don't count this
  203.            conntrack. */
  204. if (i->conntrack != conntrack
  205.     && i->conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == dst
  206.     && i->conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip == src
  207.     && (i->conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum
  208. == protonum))
  209. (*score)++;
  210. return 0;
  211. }
  212. static inline unsigned int
  213. count_maps(u_int32_t src, u_int32_t dst, u_int16_t protonum,
  214.    const struct ip_conntrack *conntrack)
  215. {
  216. unsigned int score = 0;
  217. MUST_BE_READ_LOCKED(&ip_nat_lock);
  218. LIST_FIND(&byipsproto[hash_by_ipsproto(src, dst, protonum)],
  219.   fake_cmp, struct ip_nat_hash *, src, dst, protonum, &score,
  220.   conntrack);
  221. return score;
  222. }
  223. /* For [FUTURE] fragmentation handling, we want the least-used
  224.    src-ip/dst-ip/proto triple.  Fairness doesn't come into it.  Thus
  225.    if the range specifies 1.2.3.4 ports 10000-10005 and 1.2.3.5 ports
  226.    1-65535, we don't do pro-rata allocation based on ports; we choose
  227.    the ip with the lowest src-ip/dst-ip/proto usage.
  228.    If an allocation then fails (eg. all 6 ports used in the 1.2.3.4
  229.    range), we eliminate that and try again.  This is not the most
  230.    efficient approach, but if you're worried about that, don't hand us
  231.    ranges you don't really have.  */
  232. static struct ip_nat_range *
  233. find_best_ips_proto(struct ip_conntrack_tuple *tuple,
  234.     const struct ip_nat_multi_range *mr,
  235.     const struct ip_conntrack *conntrack,
  236.     unsigned int hooknum)
  237. {
  238. unsigned int i;
  239. struct {
  240. const struct ip_nat_range *range;
  241. unsigned int score;
  242. struct ip_conntrack_tuple tuple;
  243. } best = { NULL,  0xFFFFFFFF };
  244. u_int32_t *var_ipp, *other_ipp, saved_ip, orig_dstip;
  245. static unsigned int randomness = 0;
  246. if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
  247. var_ipp = &tuple->src.ip;
  248. saved_ip = tuple->dst.ip;
  249. other_ipp = &tuple->dst.ip;
  250. } else {
  251. var_ipp = &tuple->dst.ip;
  252. saved_ip = tuple->src.ip;
  253. other_ipp = &tuple->src.ip;
  254. }
  255. /* Don't do do_extra_mangle unless neccessary (overrides
  256.            explicit socket bindings, for example) */
  257. orig_dstip = tuple->dst.ip;
  258. IP_NF_ASSERT(mr->rangesize >= 1);
  259. for (i = 0; i < mr->rangesize; i++) {
  260. /* Host order */
  261. u_int32_t minip, maxip, j;
  262. /* Don't do ranges which are already eliminated. */
  263. if (mr->range[i].flags & IP_NAT_RANGE_FULL) {
  264. continue;
  265. }
  266. if (mr->range[i].flags & IP_NAT_RANGE_MAP_IPS) {
  267. minip = ntohl(mr->range[i].min_ip);
  268. maxip = ntohl(mr->range[i].max_ip);
  269. } else
  270. minip = maxip = ntohl(*var_ipp);
  271. randomness++;
  272. for (j = 0; j < maxip - minip + 1; j++) {
  273. unsigned int score;
  274. *var_ipp = htonl(minip + (randomness + j) 
  275.  % (maxip - minip + 1));
  276. /* Reset the other ip in case it was mangled by
  277.  * do_extra_mangle last time. */
  278. *other_ipp = saved_ip;
  279. #ifdef CONFIG_IP_NF_NAT_LOCAL
  280. if (hooknum == NF_IP_LOCAL_OUT
  281.     && *var_ipp != orig_dstip
  282.     && !do_extra_mangle(*var_ipp, other_ipp)) {
  283. DEBUGP("Range %u %u.%u.%u.%u rt failed!n",
  284.        i, NIPQUAD(*var_ipp));
  285. /* Can't route?  This whole range part is
  286.  * probably screwed, but keep trying
  287.  * anyway. */
  288. continue;
  289. }
  290. #endif
  291. /* Count how many others map onto this. */
  292. score = count_maps(tuple->src.ip, tuple->dst.ip,
  293.    tuple->dst.protonum, conntrack);
  294. if (score < best.score) {
  295. /* Optimization: doesn't get any better than
  296.    this. */
  297. if (score == 0)
  298. return (struct ip_nat_range *)
  299. &mr->range[i];
  300. best.score = score;
  301. best.tuple = *tuple;
  302. best.range = &mr->range[i];
  303. }
  304. }
  305. }
  306. *tuple = best.tuple;
  307. /* Discard const. */
  308. return (struct ip_nat_range *)best.range;
  309. }
  310. /* Fast version doesn't iterate through hash chains, but only handles
  311.    common case of single IP address (null NAT, masquerade) */
  312. static struct ip_nat_range *
  313. find_best_ips_proto_fast(struct ip_conntrack_tuple *tuple,
  314.  const struct ip_nat_multi_range *mr,
  315.  const struct ip_conntrack *conntrack,
  316.  unsigned int hooknum)
  317. {
  318. if (mr->rangesize != 1
  319.     || (mr->range[0].flags & IP_NAT_RANGE_FULL)
  320.     || ((mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)
  321. && mr->range[0].min_ip != mr->range[0].max_ip))
  322. return find_best_ips_proto(tuple, mr, conntrack, hooknum);
  323. if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
  324. if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
  325. tuple->src.ip = mr->range[0].min_ip;
  326. else {
  327. /* Only do extra mangle when required (breaks
  328.                            socket binding) */
  329. #ifdef CONFIG_IP_NF_NAT_LOCAL
  330. if (tuple->dst.ip != mr->range[0].min_ip
  331.     && hooknum == NF_IP_LOCAL_OUT
  332.     && !do_extra_mangle(mr->range[0].min_ip,
  333. &tuple->src.ip))
  334. return NULL;
  335. #endif
  336. tuple->dst.ip = mr->range[0].min_ip;
  337. }
  338. }
  339. /* Discard const. */
  340. return (struct ip_nat_range *)&mr->range[0];
  341. }
  342. static int
  343. get_unique_tuple(struct ip_conntrack_tuple *tuple,
  344.  const struct ip_conntrack_tuple *orig_tuple,
  345.  const struct ip_nat_multi_range *mrr,
  346.  struct ip_conntrack *conntrack,
  347.  unsigned int hooknum)
  348. {
  349. struct ip_nat_protocol *proto
  350. = find_nat_proto(orig_tuple->dst.protonum);
  351. struct ip_nat_range *rptr;
  352. unsigned int i;
  353. int ret;
  354. /* We temporarily use flags for marking full parts, but we
  355.    always clean up afterwards */
  356. struct ip_nat_multi_range *mr = (void *)mrr;
  357. /* 1) If this srcip/proto/src-proto-part is currently mapped,
  358.    and that same mapping gives a unique tuple within the given
  359.    range, use that.
  360.    This is only required for source (ie. NAT/masq) mappings.
  361.    So far, we don't do local source mappings, so multiple
  362.    manips not an issue.  */
  363. if (hooknum == NF_IP_POST_ROUTING) {
  364. struct ip_conntrack_manip *manip;
  365. manip = find_appropriate_src(orig_tuple, mr);
  366. if (manip) {
  367. /* Apply same source manipulation. */
  368. *tuple = ((struct ip_conntrack_tuple)
  369.   { *manip, orig_tuple->dst });
  370. DEBUGP("get_unique_tuple: Found current src mapn");
  371. return 1;
  372. }
  373. }
  374. /* 2) Select the least-used IP/proto combination in the given
  375.    range.
  376. */
  377. *tuple = *orig_tuple;
  378. while ((rptr = find_best_ips_proto_fast(tuple, mr, conntrack, hooknum))
  379.        != NULL) {
  380. DEBUGP("Found best for "); DUMP_TUPLE(tuple);
  381. /* 3) The per-protocol part of the manip is made to
  382.    map into the range to make a unique tuple. */
  383. /* Only bother mapping if it's not already in range
  384.    and unique */
  385. if ((!(rptr->flags & IP_NAT_RANGE_PROTO_SPECIFIED)
  386.      || proto->in_range(tuple, HOOK2MANIP(hooknum),
  387. &rptr->min, &rptr->max))
  388.     && !ip_nat_used_tuple(tuple, conntrack)) {
  389. ret = 1;
  390. goto clear_fulls;
  391. } else {
  392. if (proto->unique_tuple(tuple, rptr,
  393. HOOK2MANIP(hooknum),
  394. conntrack)) {
  395. /* Must be unique. */
  396. IP_NF_ASSERT(!ip_nat_used_tuple(tuple,
  397. conntrack));
  398. ret = 1;
  399. goto clear_fulls;
  400. } else if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
  401. /* Try implicit source NAT; protocol
  402.                                    may be able to play with ports to
  403.                                    make it unique. */
  404. struct ip_nat_range r
  405. = { IP_NAT_RANGE_MAP_IPS, 
  406.     tuple->src.ip, tuple->src.ip,
  407.     { 0 }, { 0 } };
  408. DEBUGP("Trying implicit mappingn");
  409. if (proto->unique_tuple(tuple, &r,
  410. IP_NAT_MANIP_SRC,
  411. conntrack)) {
  412. /* Must be unique. */
  413. IP_NF_ASSERT(!ip_nat_used_tuple
  414.      (tuple, conntrack));
  415. ret = 1;
  416. goto clear_fulls;
  417. }
  418. }
  419. DEBUGP("Protocol can't get unique tuple %u.n",
  420.        hooknum);
  421. }
  422. /* Eliminate that from range, and try again. */
  423. rptr->flags |= IP_NAT_RANGE_FULL;
  424. *tuple = *orig_tuple;
  425. }
  426. ret = 0;
  427.  clear_fulls:
  428. /* Clear full flags. */
  429. IP_NF_ASSERT(mr->rangesize >= 1);
  430. for (i = 0; i < mr->rangesize; i++)
  431. mr->range[i].flags &= ~IP_NAT_RANGE_FULL;
  432. return ret;
  433. }
  434. static inline int
  435. helper_cmp(const struct ip_nat_helper *helper,
  436.    const struct ip_conntrack_tuple *tuple)
  437. {
  438. return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask);
  439. }
  440. /* Where to manip the reply packets (will be reverse manip). */
  441. static unsigned int opposite_hook[NF_IP_NUMHOOKS]
  442. = { [NF_IP_PRE_ROUTING] = NF_IP_POST_ROUTING,
  443.     [NF_IP_POST_ROUTING] = NF_IP_PRE_ROUTING,
  444. #ifdef CONFIG_IP_NF_NAT_LOCAL
  445.     [NF_IP_LOCAL_OUT] = NF_IP_LOCAL_IN,
  446.     [NF_IP_LOCAL_IN] = NF_IP_LOCAL_OUT,
  447. #endif
  448. };
  449. unsigned int
  450. ip_nat_setup_info(struct ip_conntrack *conntrack,
  451.   const struct ip_nat_multi_range *mr,
  452.   unsigned int hooknum)
  453. {
  454. struct ip_conntrack_tuple new_tuple, inv_tuple, reply;
  455. struct ip_conntrack_tuple orig_tp;
  456. struct ip_nat_info *info = &conntrack->nat.info;
  457. MUST_BE_WRITE_LOCKED(&ip_nat_lock);
  458. IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING
  459.      || hooknum == NF_IP_POST_ROUTING
  460.      || hooknum == NF_IP_LOCAL_OUT);
  461. IP_NF_ASSERT(info->num_manips < IP_NAT_MAX_MANIPS);
  462. /* What we've got will look like inverse of reply. Normally
  463.    this is what is in the conntrack, except for prior
  464.    manipulations (future optimization: if num_manips == 0,
  465.    orig_tp =
  466.    conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple) */
  467. invert_tuplepr(&orig_tp,
  468.        &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple);
  469. #if 0
  470. {
  471. unsigned int i;
  472. DEBUGP("Hook %u (%s), ", hooknum,
  473.        HOOK2MANIP(hooknum)==IP_NAT_MANIP_SRC ? "SRC" : "DST");
  474. DUMP_TUPLE(&orig_tp);
  475. DEBUGP("Range %p: ", mr);
  476. for (i = 0; i < mr->rangesize; i++) {
  477. DEBUGP("%u:%s%s%s %u.%u.%u.%u - %u.%u.%u.%u %u - %un",
  478.        i,
  479.        (mr->range[i].flags & IP_NAT_RANGE_MAP_IPS)
  480.        ? " MAP_IPS" : "",
  481.        (mr->range[i].flags
  482. & IP_NAT_RANGE_PROTO_SPECIFIED)
  483.        ? " PROTO_SPECIFIED" : "",
  484.        (mr->range[i].flags & IP_NAT_RANGE_FULL)
  485.        ? " FULL" : "",
  486.        NIPQUAD(mr->range[i].min_ip),
  487.        NIPQUAD(mr->range[i].max_ip),
  488.        mr->range[i].min.all,
  489.        mr->range[i].max.all);
  490. }
  491. }
  492. #endif
  493. do {
  494. if (!get_unique_tuple(&new_tuple, &orig_tp, mr, conntrack,
  495.       hooknum)) {
  496. DEBUGP("ip_nat_setup_info: Can't get unique for %p.n",
  497.        conntrack);
  498. return NF_DROP;
  499. }
  500. #if 0
  501. DEBUGP("Hook %u (%s) %pn", hooknum,
  502.        HOOK2MANIP(hooknum)==IP_NAT_MANIP_SRC ? "SRC" : "DST",
  503.        conntrack);
  504. DEBUGP("Original: ");
  505. DUMP_TUPLE(&orig_tp);
  506. DEBUGP("New: ");
  507. DUMP_TUPLE(&new_tuple);
  508. #endif
  509. /* We now have two tuples (SRCIP/SRCPT/DSTIP/DSTPT):
  510.    the original (A/B/C/D') and the mangled one (E/F/G/H').
  511.    We're only allowed to work with the SRC per-proto
  512.    part, so we create inverses of both to start, then
  513.    derive the other fields we need.  */
  514. /* Reply connection: simply invert the new tuple
  515.                    (G/H/E/F') */
  516. invert_tuplepr(&reply, &new_tuple);
  517. /* Alter conntrack table so it recognizes replies.
  518.                    If fail this race (reply tuple now used), repeat. */
  519. } while (!ip_conntrack_alter_reply(conntrack, &reply));
  520. /* FIXME: We can simply used existing conntrack reply tuple
  521.            here --RR */
  522. /* Create inverse of original: C/D/A/B' */
  523. invert_tuplepr(&inv_tuple, &orig_tp);
  524. /* Has source changed?. */
  525. if (!ip_ct_tuple_src_equal(&new_tuple, &orig_tp)) {
  526. /* In this direction, a source manip. */
  527. info->manips[info->num_manips++] =
  528. ((struct ip_nat_info_manip)
  529.  { IP_CT_DIR_ORIGINAL, hooknum,
  530.    IP_NAT_MANIP_SRC, new_tuple.src });
  531. IP_NF_ASSERT(info->num_manips < IP_NAT_MAX_MANIPS);
  532. /* In the reverse direction, a destination manip. */
  533. info->manips[info->num_manips++] =
  534. ((struct ip_nat_info_manip)
  535.  { IP_CT_DIR_REPLY, opposite_hook[hooknum],
  536.    IP_NAT_MANIP_DST, orig_tp.src });
  537. IP_NF_ASSERT(info->num_manips <= IP_NAT_MAX_MANIPS);
  538. }
  539. /* Has destination changed? */
  540. if (!ip_ct_tuple_dst_equal(&new_tuple, &orig_tp)) {
  541. /* In this direction, a destination manip */
  542. info->manips[info->num_manips++] =
  543. ((struct ip_nat_info_manip)
  544.  { IP_CT_DIR_ORIGINAL, hooknum,
  545.    IP_NAT_MANIP_DST, reply.src });
  546. IP_NF_ASSERT(info->num_manips < IP_NAT_MAX_MANIPS);
  547. /* In the reverse direction, a source manip. */
  548. info->manips[info->num_manips++] =
  549. ((struct ip_nat_info_manip)
  550.  { IP_CT_DIR_REPLY, opposite_hook[hooknum],
  551.    IP_NAT_MANIP_SRC, inv_tuple.src });
  552. IP_NF_ASSERT(info->num_manips <= IP_NAT_MAX_MANIPS);
  553. }
  554. /* If there's a helper, assign it; based on new tuple. */
  555. if (!conntrack->master)
  556. info->helper = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,
  557.  &reply);
  558. /* It's done. */
  559. info->initialized |= (1 << HOOK2MANIP(hooknum));
  560. return NF_ACCEPT;
  561. }
  562. void replace_in_hashes(struct ip_conntrack *conntrack,
  563.        struct ip_nat_info *info)
  564. {
  565. /* Source has changed, so replace in hashes. */
  566. unsigned int srchash
  567. = hash_by_src(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
  568.       .tuple.src,
  569.       conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
  570.       .tuple.dst.protonum);
  571. /* We place packet as seen OUTGOUNG in byips_proto hash
  572.            (ie. reverse dst and src of reply packet. */
  573. unsigned int ipsprotohash
  574. = hash_by_ipsproto(conntrack->tuplehash[IP_CT_DIR_REPLY]
  575.    .tuple.dst.ip,
  576.    conntrack->tuplehash[IP_CT_DIR_REPLY]
  577.    .tuple.src.ip,
  578.    conntrack->tuplehash[IP_CT_DIR_REPLY]
  579.    .tuple.dst.protonum);
  580. IP_NF_ASSERT(info->bysource.conntrack == conntrack);
  581. MUST_BE_WRITE_LOCKED(&ip_nat_lock);
  582. list_del(&info->bysource.list);
  583. list_del(&info->byipsproto.list);
  584. list_prepend(&bysource[srchash], &info->bysource);
  585. list_prepend(&byipsproto[ipsprotohash], &info->byipsproto);
  586. }
  587. void place_in_hashes(struct ip_conntrack *conntrack,
  588.      struct ip_nat_info *info)
  589. {
  590. unsigned int srchash
  591. = hash_by_src(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
  592.       .tuple.src,
  593.       conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
  594.       .tuple.dst.protonum);
  595. /* We place packet as seen OUTGOUNG in byips_proto hash
  596.            (ie. reverse dst and src of reply packet. */
  597. unsigned int ipsprotohash
  598. = hash_by_ipsproto(conntrack->tuplehash[IP_CT_DIR_REPLY]
  599.    .tuple.dst.ip,
  600.    conntrack->tuplehash[IP_CT_DIR_REPLY]
  601.    .tuple.src.ip,
  602.    conntrack->tuplehash[IP_CT_DIR_REPLY]
  603.    .tuple.dst.protonum);
  604. IP_NF_ASSERT(!info->bysource.conntrack);
  605. MUST_BE_WRITE_LOCKED(&ip_nat_lock);
  606. info->byipsproto.conntrack = conntrack;
  607. info->bysource.conntrack = conntrack;
  608. list_prepend(&bysource[srchash], &info->bysource);
  609. list_prepend(&byipsproto[ipsprotohash], &info->byipsproto);
  610. }
  611. static void
  612. manip_pkt(u_int16_t proto, struct iphdr *iph, size_t len,
  613.   const struct ip_conntrack_manip *manip,
  614.   enum ip_nat_manip_type maniptype,
  615.   __u32 *nfcache)
  616. {
  617. *nfcache |= NFC_ALTERED;
  618. find_nat_proto(proto)->manip_pkt(iph, len, manip, maniptype);
  619. if (maniptype == IP_NAT_MANIP_SRC) {
  620. iph->check = ip_nat_cheat_check(~iph->saddr, manip->ip,
  621. iph->check);
  622. iph->saddr = manip->ip;
  623. } else {
  624. iph->check = ip_nat_cheat_check(~iph->daddr, manip->ip,
  625. iph->check);
  626. iph->daddr = manip->ip;
  627. }
  628. #if 0
  629. if (ip_fast_csum((u8 *)iph, iph->ihl) != 0)
  630. DEBUGP("IP: checksum on packet bad.n");
  631. if (proto == IPPROTO_TCP) {
  632. void *th = (u_int32_t *)iph + iph->ihl;
  633. if (tcp_v4_check(th, len - 4*iph->ihl, iph->saddr, iph->daddr,
  634.  csum_partial((char *)th, len-4*iph->ihl, 0)))
  635. DEBUGP("TCP: checksum on packet badn");
  636. }
  637. #endif
  638. }
  639. static inline int exp_for_packet(struct ip_conntrack_expect *exp,
  640.          struct sk_buff **pskb)
  641. {
  642. struct ip_conntrack_protocol *proto;
  643. int ret = 1;
  644. MUST_BE_READ_LOCKED(&ip_conntrack_lock);
  645. proto = __ip_ct_find_proto((*pskb)->nh.iph->protocol);
  646. if (proto->exp_matches_pkt)
  647. ret = proto->exp_matches_pkt(exp, pskb);
  648. return ret;
  649. }
  650. /* Do packet manipulations according to binding. */
  651. unsigned int
  652. do_bindings(struct ip_conntrack *ct,
  653.     enum ip_conntrack_info ctinfo,
  654.     struct ip_nat_info *info,
  655.     unsigned int hooknum,
  656.     struct sk_buff **pskb)
  657. {
  658. unsigned int i;
  659. struct ip_nat_helper *helper;
  660. enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
  661. int is_tcp = (*pskb)->nh.iph->protocol == IPPROTO_TCP;
  662. /* Need nat lock to protect against modification, but neither
  663.    conntrack (referenced) and helper (deleted with
  664.    synchronize_bh()) can vanish. */
  665. READ_LOCK(&ip_nat_lock);
  666. for (i = 0; i < info->num_manips; i++) {
  667. /* raw socket (tcpdump) may have clone of incoming
  668.                    skb: don't disturb it --RR */
  669. if (skb_cloned(*pskb) && !(*pskb)->sk) {
  670. struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC);
  671. if (!nskb) {
  672. READ_UNLOCK(&ip_nat_lock);
  673. return NF_DROP;
  674. }
  675. kfree_skb(*pskb);
  676. *pskb = nskb;
  677. }
  678. if (info->manips[i].direction == dir
  679.     && info->manips[i].hooknum == hooknum) {
  680. DEBUGP("Mangling %p: %s to %u.%u.%u.%u %un",
  681.        *pskb,
  682.        info->manips[i].maniptype == IP_NAT_MANIP_SRC
  683.        ? "SRC" : "DST",
  684.        NIPQUAD(info->manips[i].manip.ip),
  685.        htons(info->manips[i].manip.u.all));
  686. manip_pkt((*pskb)->nh.iph->protocol,
  687.   (*pskb)->nh.iph,
  688.   (*pskb)->len,
  689.   &info->manips[i].manip,
  690.   info->manips[i].maniptype,
  691.   &(*pskb)->nfcache);
  692. }
  693. }
  694. helper = info->helper;
  695. READ_UNLOCK(&ip_nat_lock);
  696. if (helper) {
  697. struct ip_conntrack_expect *exp = NULL;
  698. struct list_head *cur_item;
  699. int ret = NF_ACCEPT;
  700. DEBUGP("do_bindings: helper existing for (%p)n", ct);
  701. /* Always defragged for helpers */
  702. IP_NF_ASSERT(!((*pskb)->nh.iph->frag_off
  703.        & htons(IP_MF|IP_OFFSET)));
  704. /* Have to grab read lock before sibling_list traversal */
  705. READ_LOCK(&ip_conntrack_lock);
  706. list_for_each(cur_item, &ct->sibling_list) { 
  707. exp = list_entry(cur_item, struct ip_conntrack_expect, 
  708.  expected_list);
  709.  
  710. /* if this expectation is already established, skip */
  711. if (exp->sibling)
  712. continue;
  713. if (exp_for_packet(exp, pskb)) {
  714. /* FIXME: May be true multiple times in the case of UDP!! */
  715. DEBUGP("calling nat helper (exp=%p) for packetn",
  716. exp);
  717. ret = helper->help(ct, exp, info, ctinfo, 
  718.    hooknum, pskb);
  719. if (ret != NF_ACCEPT) {
  720. READ_UNLOCK(&ip_conntrack_lock);
  721. return ret;
  722. }
  723. }
  724. }
  725. /* Helper might want to manip the packet even when there is no expectation */
  726. if (!exp && helper->flags & IP_NAT_HELPER_F_ALWAYS) {
  727. DEBUGP("calling nat helper for packet without expectationn");
  728. ret = helper->help(ct, NULL, info, ctinfo, 
  729.    hooknum, pskb);
  730. if (ret != NF_ACCEPT) {
  731. READ_UNLOCK(&ip_conntrack_lock);
  732. return ret;
  733. }
  734. }
  735. READ_UNLOCK(&ip_conntrack_lock);
  736. /* Adjust sequence number only once per packet 
  737.  * (helper is called at all hooks) */
  738. if (is_tcp && (hooknum == NF_IP_POST_ROUTING
  739.        || hooknum == NF_IP_LOCAL_IN)) {
  740. DEBUGP("ip_nat_core: adjusting sequence numbern");
  741. /* future: put this in a l4-proto specific function,
  742.  * and call this function here. */
  743. ip_nat_seq_adjust(*pskb, ct, ctinfo);
  744. }
  745. return ret;
  746. } else 
  747. return NF_ACCEPT;
  748. /* not reached */
  749. }
  750. unsigned int
  751. icmp_reply_translation(struct sk_buff *skb,
  752.        struct ip_conntrack *conntrack,
  753.        unsigned int hooknum,
  754.        int dir)
  755. {
  756. struct iphdr *iph = skb->nh.iph;
  757. struct icmphdr *hdr = (struct icmphdr *)((u_int32_t *)iph + iph->ihl);
  758. struct iphdr *inner = (struct iphdr *)(hdr + 1);
  759. size_t datalen = skb->len - ((void *)inner - (void *)iph);
  760. unsigned int i;
  761. struct ip_nat_info *info = &conntrack->nat.info;
  762. IP_NF_ASSERT(skb->len >= iph->ihl*4 + sizeof(struct icmphdr));
  763. /* Must be RELATED */
  764. IP_NF_ASSERT(skb->nfct - (struct ip_conntrack *)skb->nfct->master
  765.      == IP_CT_RELATED
  766.      || skb->nfct - (struct ip_conntrack *)skb->nfct->master
  767.      == IP_CT_RELATED+IP_CT_IS_REPLY);
  768. /* Redirects on non-null nats must be dropped, else they'll
  769.            start talking to each other without our translation, and be
  770.            confused... --RR */
  771. if (hdr->type == ICMP_REDIRECT) {
  772. /* Don't care about races here. */
  773. if (info->initialized
  774.     != ((1 << IP_NAT_MANIP_SRC) | (1 << IP_NAT_MANIP_DST))
  775.     || info->num_manips != 0)
  776. return NF_DROP;
  777. }
  778. DEBUGP("icmp_reply_translation: translating error %p hook %u dir %sn",
  779.        skb, hooknum, dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");
  780. /* Note: May not be from a NAT'd host, but probably safest to
  781.    do translation always as if it came from the host itself
  782.    (even though a "host unreachable" coming from the host
  783.    itself is a bit weird).
  784.    More explanation: some people use NAT for anonymizing.
  785.    Also, CERT recommends dropping all packets from private IP
  786.    addresses (although ICMP errors from internal links with
  787.    such addresses are not too uncommon, as Alan Cox points
  788.    out) */
  789. READ_LOCK(&ip_nat_lock);
  790. for (i = 0; i < info->num_manips; i++) {
  791. DEBUGP("icmp_reply: manip %u dir %s hook %un",
  792.        i, info->manips[i].direction == IP_CT_DIR_ORIGINAL ?
  793.        "ORIG" : "REPLY", info->manips[i].hooknum);
  794. if (info->manips[i].direction != dir)
  795. continue;
  796. /* Mapping the inner packet is just like a normal
  797.    packet, except it was never src/dst reversed, so
  798.    where we would normally apply a dst manip, we apply
  799.    a src, and vice versa. */
  800. if (info->manips[i].hooknum == opposite_hook[hooknum]) {
  801. DEBUGP("icmp_reply: inner %s -> %u.%u.%u.%u %un",
  802.        info->manips[i].maniptype == IP_NAT_MANIP_SRC
  803.        ? "DST" : "SRC",
  804.        NIPQUAD(info->manips[i].manip.ip),
  805.        ntohs(info->manips[i].manip.u.udp.port));
  806. manip_pkt(inner->protocol, inner,
  807.   skb->len - ((void *)inner - (void *)iph),
  808.   &info->manips[i].manip,
  809.   !info->manips[i].maniptype,
  810.   &skb->nfcache);
  811. /* Outer packet needs to have IP header NATed like
  812.                    it's a reply. */
  813. } else if (info->manips[i].hooknum == hooknum) {
  814. /* Use mapping to map outer packet: 0 give no
  815.                            per-proto mapping */
  816. DEBUGP("icmp_reply: outer %s -> %u.%u.%u.%un",
  817.        info->manips[i].maniptype == IP_NAT_MANIP_SRC
  818.        ? "SRC" : "DST",
  819.        NIPQUAD(info->manips[i].manip.ip));
  820. manip_pkt(0, iph, skb->len,
  821.   &info->manips[i].manip,
  822.   info->manips[i].maniptype,
  823.   &skb->nfcache);
  824. }
  825. }
  826. READ_UNLOCK(&ip_nat_lock);
  827. /* Since we mangled inside ICMP packet, recalculate its
  828.    checksum from scratch.  (Hence the handling of incorrect
  829.    checksums in conntrack, so we don't accidentally fix one.)  */
  830. hdr->checksum = 0;
  831. hdr->checksum = ip_compute_csum((unsigned char *)hdr,
  832. sizeof(*hdr) + datalen);
  833. return NF_ACCEPT;
  834. }
  835. int __init ip_nat_init(void)
  836. {
  837. size_t i;
  838. /* Leave them the same for the moment. */
  839. ip_nat_htable_size = ip_conntrack_htable_size;
  840. /* One vmalloc for both hash tables */
  841. bysource = vmalloc(sizeof(struct list_head) * ip_nat_htable_size*2);
  842. if (!bysource) {
  843. return -ENOMEM;
  844. }
  845. byipsproto = bysource + ip_nat_htable_size;
  846. /* Sew in builtin protocols. */
  847. WRITE_LOCK(&ip_nat_lock);
  848. list_append(&protos, &ip_nat_protocol_tcp);
  849. list_append(&protos, &ip_nat_protocol_udp);
  850. list_append(&protos, &ip_nat_protocol_icmp);
  851. WRITE_UNLOCK(&ip_nat_lock);
  852. for (i = 0; i < ip_nat_htable_size; i++) {
  853. INIT_LIST_HEAD(&bysource[i]);
  854. INIT_LIST_HEAD(&byipsproto[i]);
  855. }
  856. /* FIXME: Man, this is a hack.  <SIGH> */
  857. IP_NF_ASSERT(ip_conntrack_destroyed == NULL);
  858. ip_conntrack_destroyed = &ip_nat_cleanup_conntrack;
  859. return 0;
  860. }
  861. /* Clear NAT section of all conntracks, in case we're loaded again. */
  862. static int clean_nat(const struct ip_conntrack *i, void *data)
  863. {
  864. memset((void *)&i->nat, 0, sizeof(i->nat));
  865. return 0;
  866. }
  867. /* Not __exit: called from ip_nat_standalone.c:init_or_cleanup() --RR */
  868. void ip_nat_cleanup(void)
  869. {
  870. ip_ct_selective_cleanup(&clean_nat, NULL);
  871. ip_conntrack_destroyed = NULL;
  872. vfree(bysource);
  873. }