linux/net/ipv4/netfilter/nf_nat_proto_sctp.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 */
   8
   9#include <linux/types.h>
  10#include <linux/init.h>
  11#include <linux/ip.h>
  12#include <linux/sctp.h>
  13#include <net/sctp/checksum.h>
  14
  15#include <net/netfilter/nf_nat_protocol.h>
  16
  17static u_int16_t nf_sctp_port_rover;
  18
  19static bool
  20sctp_unique_tuple(struct nf_conntrack_tuple *tuple,
  21                  const struct nf_nat_range *range,
  22                  enum nf_nat_manip_type maniptype,
  23                  const struct nf_conn *ct)
  24{
  25        return nf_nat_proto_unique_tuple(tuple, range, maniptype, ct,
  26                                         &nf_sctp_port_rover);
  27}
  28
  29static bool
  30sctp_manip_pkt(struct sk_buff *skb,
  31               unsigned int iphdroff,
  32               const struct nf_conntrack_tuple *tuple,
  33               enum nf_nat_manip_type maniptype)
  34{
  35        const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
  36        struct sk_buff *frag;
  37        sctp_sctphdr_t *hdr;
  38        unsigned int hdroff = iphdroff + iph->ihl*4;
  39        __be32 oldip, newip;
  40        __be32 crc32;
  41
  42        if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
  43                return false;
  44
  45        iph = (struct iphdr *)(skb->data + iphdroff);
  46        hdr = (struct sctphdr *)(skb->data + hdroff);
  47
  48        if (maniptype == IP_NAT_MANIP_SRC) {
  49                /* Get rid of src ip and src pt */
  50                oldip = iph->saddr;
  51                newip = tuple->src.u3.ip;
  52                hdr->source = tuple->src.u.sctp.port;
  53        } else {
  54                /* Get rid of dst ip and dst pt */
  55                oldip = iph->daddr;
  56                newip = tuple->dst.u3.ip;
  57                hdr->dest = tuple->dst.u.sctp.port;
  58        }
  59
  60        crc32 = sctp_start_cksum((u8 *)hdr, skb_headlen(skb) - hdroff);
  61        skb_walk_frags(skb, frag)
  62                crc32 = sctp_update_cksum((u8 *)frag->data, skb_headlen(frag),
  63                                          crc32);
  64        crc32 = sctp_end_cksum(crc32);
  65        hdr->checksum = crc32;
  66
  67        return true;
  68}
  69
  70static const struct nf_nat_protocol nf_nat_protocol_sctp = {
  71        .protonum               = IPPROTO_SCTP,
  72        .me                     = THIS_MODULE,
  73        .manip_pkt              = sctp_manip_pkt,
  74        .in_range               = nf_nat_proto_in_range,
  75        .unique_tuple           = sctp_unique_tuple,
  76#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
  77        .range_to_nlattr        = nf_nat_proto_range_to_nlattr,
  78        .nlattr_to_range        = nf_nat_proto_nlattr_to_range,
  79#endif
  80};
  81
  82static int __init nf_nat_proto_sctp_init(void)
  83{
  84        return nf_nat_protocol_register(&nf_nat_protocol_sctp);
  85}
  86
  87static void __exit nf_nat_proto_sctp_exit(void)
  88{
  89        nf_nat_protocol_unregister(&nf_nat_protocol_sctp);
  90}
  91
  92module_init(nf_nat_proto_sctp_init);
  93module_exit(nf_nat_proto_sctp_exit);
  94
  95MODULE_LICENSE("GPL");
  96MODULE_DESCRIPTION("SCTP NAT protocol helper");
  97MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
  98