linux-bk/net/ipv4/netfilter/ipt_multiport.c
<<
>>
Prefs
   1/* Kernel module to match one of a list of TCP/UDP ports: ports are in
   2   the same place so we can treat them as equal. */
   3
   4/* (C) 1999-2001 Paul `Rusty' Russell
   5 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
   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
  12#include <linux/module.h>
  13#include <linux/types.h>
  14#include <linux/udp.h>
  15#include <linux/skbuff.h>
  16
  17#include <linux/netfilter_ipv4/ipt_multiport.h>
  18#include <linux/netfilter_ipv4/ip_tables.h>
  19
  20MODULE_LICENSE("GPL");
  21MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
  22MODULE_DESCRIPTION("iptables multiple port match module");
  23
  24#if 0
  25#define duprintf(format, args...) printk(format , ## args)
  26#else
  27#define duprintf(format, args...)
  28#endif
  29
  30/* Returns 1 if the port is matched by the test, 0 otherwise. */
  31static inline int
  32ports_match(const u_int16_t *portlist, enum ipt_multiport_flags flags,
  33            u_int8_t count, u_int16_t src, u_int16_t dst)
  34{
  35        unsigned int i;
  36        for (i=0; i<count; i++) {
  37                if (flags != IPT_MULTIPORT_DESTINATION
  38                    && portlist[i] == src)
  39                        return 1;
  40
  41                if (flags != IPT_MULTIPORT_SOURCE
  42                    && portlist[i] == dst)
  43                        return 1;
  44        }
  45
  46        return 0;
  47}
  48
  49/* Returns 1 if the port is matched by the test, 0 otherwise. */
  50static inline int
  51ports_match_v1(const struct ipt_multiport_v1 *minfo,
  52               u_int16_t src, u_int16_t dst)
  53{
  54        unsigned int i;
  55        u_int16_t s, e;
  56
  57        for (i=0; i < minfo->count; i++) {
  58                s = minfo->ports[i];
  59
  60                if (minfo->pflags[i]) {
  61                        /* range port matching */
  62                        e = minfo->ports[++i];
  63                        duprintf("src or dst matches with %d-%d?\n", s, e);
  64
  65                        if (minfo->flags == IPT_MULTIPORT_SOURCE
  66                            && src >= s && src <= e)
  67                                return 1 ^ minfo->invert;
  68                        if (minfo->flags == IPT_MULTIPORT_DESTINATION
  69                            && dst >= s && dst <= e)
  70                                return 1 ^ minfo->invert;
  71                        if (minfo->flags == IPT_MULTIPORT_EITHER
  72                            && ((dst >= s && dst <= e)
  73                                || (src >= s && src <= e)))
  74                                return 1 ^ minfo->invert;
  75                } else {
  76                        /* exact port matching */
  77                        duprintf("src or dst matches with %d?\n", s);
  78
  79                        if (minfo->flags == IPT_MULTIPORT_SOURCE
  80                            && src == s)
  81                                return 1 ^ minfo->invert;
  82                        if (minfo->flags == IPT_MULTIPORT_DESTINATION
  83                            && dst == s)
  84                                return 1 ^ minfo->invert;
  85                        if (minfo->flags == IPT_MULTIPORT_EITHER
  86                            && (src == s || dst == s))
  87                                return 1 ^ minfo->invert;
  88                }
  89        }
  90 
  91        return minfo->invert;
  92}
  93
  94static int
  95match(const struct sk_buff *skb,
  96      const struct net_device *in,
  97      const struct net_device *out,
  98      const void *matchinfo,
  99      int offset,
 100      int *hotdrop)
 101{
 102        u16 _ports[2], *pptr;
 103        const struct ipt_multiport *multiinfo = matchinfo;
 104
 105        if (offset)
 106                return 0;
 107
 108        pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
 109                                  sizeof(_ports), _ports);
 110        if (pptr == NULL) {
 111                /* We've been asked to examine this packet, and we
 112                 * can't.  Hence, no choice but to drop.
 113                 */
 114                duprintf("ipt_multiport:"
 115                         " Dropping evil offset=0 tinygram.\n");
 116                *hotdrop = 1;
 117                return 0;
 118        }
 119
 120        return ports_match(multiinfo->ports,
 121                           multiinfo->flags, multiinfo->count,
 122                           ntohs(pptr[0]), ntohs(pptr[1]));
 123}
 124
 125static int
 126match_v1(const struct sk_buff *skb,
 127         const struct net_device *in,
 128         const struct net_device *out,
 129         const void *matchinfo,
 130         int offset,
 131         int *hotdrop)
 132{
 133        u16 _ports[2], *pptr;
 134        const struct ipt_multiport_v1 *multiinfo = matchinfo;
 135
 136        if (offset)
 137                return 0;
 138
 139        pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
 140                                  sizeof(_ports), _ports);
 141        if (pptr == NULL) {
 142                /* We've been asked to examine this packet, and we
 143                 * can't.  Hence, no choice but to drop.
 144                 */
 145                duprintf("ipt_multiport:"
 146                         " Dropping evil offset=0 tinygram.\n");
 147                *hotdrop = 1;
 148                return 0;
 149        }
 150
 151        return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
 152}
 153
 154/* Called when user tries to insert an entry of this type. */
 155static int
 156checkentry(const char *tablename,
 157           const struct ipt_ip *ip,
 158           void *matchinfo,
 159           unsigned int matchsize,
 160           unsigned int hook_mask)
 161{
 162        return (matchsize == IPT_ALIGN(sizeof(struct ipt_multiport)));
 163}
 164
 165static int
 166checkentry_v1(const char *tablename,
 167              const struct ipt_ip *ip,
 168              void *matchinfo,
 169              unsigned int matchsize,
 170              unsigned int hook_mask)
 171{
 172        return (matchsize == IPT_ALIGN(sizeof(struct ipt_multiport_v1)));
 173}
 174
 175static struct ipt_match multiport_match = {
 176        .name           = "multiport",
 177        .revision       = 0,
 178        .match          = &match,
 179        .checkentry     = &checkentry,
 180        .me             = THIS_MODULE,
 181};
 182
 183static struct ipt_match multiport_match_v1 = {
 184        .name           = "multiport",
 185        .revision       = 1,
 186        .match          = &match_v1,
 187        .checkentry     = &checkentry_v1,
 188        .me             = THIS_MODULE,
 189};
 190
 191static int __init init(void)
 192{
 193        int err;
 194
 195        err = ipt_register_match(&multiport_match);
 196        if (!err) {
 197                err = ipt_register_match(&multiport_match_v1);
 198                if (err)
 199                        ipt_unregister_match(&multiport_match);
 200        }
 201
 202        return err;
 203}
 204
 205static void __exit fini(void)
 206{
 207        ipt_unregister_match(&multiport_match);
 208        ipt_unregister_match(&multiport_match_v1);
 209}
 210
 211module_init(init);
 212module_exit(fini);
 213
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.