linux/net/netfilter/nf_nat_proto_dccp.c
<<
>>
Prefs
   1/*
   2 * DCCP NAT protocol helper
   3 *
   4 * Copyright (c) 2005, 2006, 2008 Patrick McHardy <kaber@trash.net>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 *
  10 */
  11
  12#include <linux/kernel.h>
  13#include <linux/module.h>
  14#include <linux/init.h>
  15#include <linux/skbuff.h>
  16#include <linux/dccp.h>
  17
  18#include <net/netfilter/nf_conntrack.h>
  19#include <net/netfilter/nf_nat.h>
  20#include <net/netfilter/nf_nat_l3proto.h>
  21#include <net/netfilter/nf_nat_l4proto.h>
  22
  23static u_int16_t dccp_port_rover;
  24
  25static void
  26dccp_unique_tuple(const struct nf_nat_l3proto *l3proto,
  27                  struct nf_conntrack_tuple *tuple,
  28                  const struct nf_nat_range *range,
  29                  enum nf_nat_manip_type maniptype,
  30                  const struct nf_conn *ct)
  31{
  32        nf_nat_l4proto_unique_tuple(l3proto, tuple, range, maniptype, ct,
  33                                    &dccp_port_rover);
  34}
  35
  36static bool
  37dccp_manip_pkt(struct sk_buff *skb,
  38               const struct nf_nat_l3proto *l3proto,
  39               unsigned int iphdroff, unsigned int hdroff,
  40               const struct nf_conntrack_tuple *tuple,
  41               enum nf_nat_manip_type maniptype)
  42{
  43        struct dccp_hdr *hdr;
  44        __be16 *portptr, oldport, newport;
  45        int hdrsize = 8; /* DCCP connection tracking guarantees this much */
  46
  47        if (skb->len >= hdroff + sizeof(struct dccp_hdr))
  48                hdrsize = sizeof(struct dccp_hdr);
  49
  50        if (!skb_make_writable(skb, hdroff + hdrsize))
  51                return false;
  52
  53        hdr = (struct dccp_hdr *)(skb->data + hdroff);
  54
  55        if (maniptype == NF_NAT_MANIP_SRC) {
  56                newport = tuple->src.u.dccp.port;
  57                portptr = &hdr->dccph_sport;
  58        } else {
  59                newport = tuple->dst.u.dccp.port;
  60                portptr = &hdr->dccph_dport;
  61        }
  62
  63        oldport = *portptr;
  64        *portptr = newport;
  65
  66        if (hdrsize < sizeof(*hdr))
  67                return true;
  68
  69        l3proto->csum_update(skb, iphdroff, &hdr->dccph_checksum,
  70                             tuple, maniptype);
  71        inet_proto_csum_replace2(&hdr->dccph_checksum, skb, oldport, newport,
  72                                 0);
  73        return true;
  74}
  75
  76static const struct nf_nat_l4proto nf_nat_l4proto_dccp = {
  77        .l4proto                = IPPROTO_DCCP,
  78        .manip_pkt              = dccp_manip_pkt,
  79        .in_range               = nf_nat_l4proto_in_range,
  80        .unique_tuple           = dccp_unique_tuple,
  81#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
  82        .nlattr_to_range        = nf_nat_l4proto_nlattr_to_range,
  83#endif
  84};
  85
  86static int __init nf_nat_proto_dccp_init(void)
  87{
  88        int err;
  89
  90        err = nf_nat_l4proto_register(NFPROTO_IPV4, &nf_nat_l4proto_dccp);
  91        if (err < 0)
  92                goto err1;
  93        err = nf_nat_l4proto_register(NFPROTO_IPV6, &nf_nat_l4proto_dccp);
  94        if (err < 0)
  95                goto err2;
  96        return 0;
  97
  98err2:
  99        nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_dccp);
 100err1:
 101        return err;
 102}
 103
 104static void __exit nf_nat_proto_dccp_fini(void)
 105{
 106        nf_nat_l4proto_unregister(NFPROTO_IPV6, &nf_nat_l4proto_dccp);
 107        nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_dccp);
 108
 109}
 110
 111module_init(nf_nat_proto_dccp_init);
 112module_exit(nf_nat_proto_dccp_fini);
 113
 114MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
 115MODULE_DESCRIPTION("DCCP NAT protocol helper");
 116MODULE_LICENSE("GPL");
 117