📄 classifiernetfilter.cc
字号:
/*!\file ClassifierNetfilter.cc Copyright 2003-2004 Fraunhofer Institute for Open Communication Systems (FOKUS), Berlin, Germany This file is part of Network Measurement and Accounting System (NETMATE). NETMATE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. NETMATE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this software; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Description: implementation for ClassifierNetfilter class $Id: ClassifierNetfilter.cc,v 1.1.1.1 2004/12/23 05:52:35 s_zander Exp $*/#include "ClassifierNetfilter.h"/* defines section mostly from iptables.c */#define MYBUFSIZ 256000#ifndef IPT_LIB_DIR#define IPT_LIB_DIR "/usr/local/lib/iptables"#endif#ifndef TRUE#define TRUE 1#endif#ifndef FALSE#define FALSE 0#endif#ifndef PROC_SYS_MODPROBE#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"#endif#define FMT_NUMERIC 0x0001#define FMT_NOCOUNTS 0x0002#define FMT_KILOMEGAGIGA 0x0004#define FMT_OPTIONS 0x0008#define FMT_NOTABLE 0x0010#define FMT_NOTARGET 0x0020#define FMT_VIA 0x0040#define FMT_NONEWLINE 0x0080#define FMT_LINENUMBERS 0x0100#define FMT_PRINT_RULE (FMT_NOCOUNTS | FMT_OPTIONS | FMT_VIA | FMT_NUMERIC | FMT_NOTABLE)#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab))// default valuesconst char *def_tablename = "meter";const char *def_chainname = "meter_base";const char *def_targetname = "ULOG";const int def_nlgroup = 4;const int def_cprange = 100;const int def_rtqt = 1;const int def_nonrtqt = 50; //! limited to 50, see ipt_ulog.cconst char *def_modprobe = "modprobe";const char *inv_symbol = "!";//const char *program_name = "iptables";/* globals, dont use static because they are extern in iptables.h */struct iptables_match *iptables_matches = NULL;struct iptables_target *iptables_targets = NULL;#define OPTION_OFFSET 256static struct option original_opts[] = { { 0 }};static struct option *opts = original_opts;static unsigned int global_option_offset = 0;/* default iptables and ULOG parameters */enum def_parameters { defp_srcipmask, defp_dstipmask, defp_prot, defp_iniface, defp_outiface, defp_nlgroup, defp_cprange, defp_prefix, defp_qthreshold, defp_match, defp_bidir};static const char *param_names[] = { { "srcip" }, { "dstip" }, { "proto" }, { "iiface" }, { "oiface" }, { "ulog-nlgroup" }, { "ulog-cprange" }, { "ulog-prefix" }, { "ulog-qthreshold" }, { "match" }, { "bidir" }, { 0 }};/* which basic params are allowed inverse */static int inverse_for_params[] = { /* srpip */ IPT_INV_SRCIP, /* dstip */ IPT_INV_DSTIP, /* proto */ IPT_INV_PROTO, /* iiface */ IPT_INV_VIA_IN, /* oiface */ IPT_INV_VIA_OUT, 0, 0, 0, 0, 0, };/* mapping table, map mcl parameter to netfilter modules paramter */struct opt_map { char *mcl; char *iptables;};static const struct opt_map option_map[] = { { "srcport", "sport" }, { "dstport", "dport" }, { "snaplen", "ulog-cprange" }, { "qthresh", "ulog-qthreshold" }, { 0 }};/* A few hardcoded protocols for 'all' and in case the user has no /etc/protocols */struct pprot { char *name; u_int8_t num;};static const struct pprot chain_protos[] = { { "tcp", IPPROTO_TCP }, { "udp", IPPROTO_UDP }, { "icmp", IPPROTO_ICMP }, { "esp", IPPROTO_ESP }, { "ah", IPPROTO_AH }, { "all", 0 },};/* ------------------- memory alloc helper functions ------------------ */// FIXME: use new and delete// FIXME: check for mem leaksstatic void *fw_calloc(size_t count, size_t size){ void *p; if ((p = calloc(count, size)) == NULL) { throw MyErr("calloc failed: %s", strerror(errno)); } return p;}static void *fw_malloc(size_t size){ void *p; if ((p = malloc(size)) == NULL) { throw MyErr("malloc failed: %s", strerror(errno)); } return p;}/* -------------- iptables functions called by modules -------------------- *//*static*/ struct option *merge_options(struct option *oldopts, const struct option *newopts, unsigned int *option_offset){ unsigned int num_old, num_new, i; struct option *merge; for (num_old = 0; oldopts[num_old].name; num_old++); for (num_new = 0; newopts[num_new].name; num_new++); global_option_offset += OPTION_OFFSET; *option_offset = global_option_offset; merge = (struct option *) fw_malloc(sizeof(struct option) * (num_new + num_old + 1)); memcpy(merge, oldopts, num_old * sizeof(struct option)); for (i = 0; i < num_new; i++) { merge[num_old + i] = newopts[i]; merge[num_old + i].val += *option_offset; } memset(merge + num_old + num_new, 0, sizeof(struct option)); return merge;}extern "C" {void exit_error(enum exittype status, char *msg, ...){ va_list args; char err_msg[1024]; va_start(args, msg); vsprintf(err_msg, msg, args); va_end(args); if (status == PARAMETER_PROBLEM) strcat(err_msg, "\nRead the manual for more information.\n"); if (status == VERSION_PROBLEM) strcat(err_msg, "\nPerhaps netmate or your kernel needs to be upgraded.\n"); // FIXME: currently exceptions are not catched if thrown from within a C module fprintf(stderr, "%s", err_msg); throw MyErr(err_msg);}int string_to_number(const char *s, unsigned int min, unsigned int max, unsigned int *ret){ long number; char *end; /* Handle hex, octal, etc. */ errno = 0; number = strtol(s, &end, 0); if ((*end == '\0') && (end != s)) { /* we parsed a number, let's see if we want this */ if ((errno != ERANGE) && ((long)min <= number) && (number <= (long)max)) { *ret = number; return 0; } } return -1;} int check_inverse(const char option[], int *invert, int *optind, int argc){ if (option && strcmp(option, "!") == 0) { if (*invert) exit_error(PARAMETER_PROBLEM, "Multiple `!' flags not allowed"); *invert = TRUE; if (optind) { *optind = *optind+1; if (argc && *optind > argc) exit_error(PARAMETER_PROBLEM, "no argument following `!'"); } return TRUE; } return FALSE;}/*int check_inverse(const char option[], int *invert) { if (option && strcmp(option, "!") == 0) { if (*invert) exit_error(PARAMETER_PROBLEM, "Multiple `!' flags not allowed"); *invert = TRUE; return TRUE; } return FALSE; }*/void register_match(struct iptables_match *me){ struct iptables_match **i; if (strcmp(me->version, PROGRAM_VERSION) != 0) { exit_error(VERSION_PROBLEM, "match `%s' v%s (I'm v%s).\n", me->name, me->version, PROGRAM_VERSION); } if (find_match(me->name, DONT_LOAD)) { exit_error(PARAMETER_PROBLEM, "match `%s' already registered.\n", me->name); } if (me->size != IPT_ALIGN(me->size)) { exit_error(PARAMETER_PROBLEM, "match `%s' has invalid size %u.\n", me->name, me->size); } /* Append to list. */ for (i = &iptables_matches; *i; i = &(*i)->next); me->next = NULL; *i = me; me->m = NULL; me->mflags = 0; opts = merge_options(opts, me->extra_opts, &me->option_offset);}void register_target(struct iptables_target *me){ if (strcmp(me->version, PROGRAM_VERSION) != 0) { exit_error(VERSION_PROBLEM, "target `%s' v%s (I'm v%s).\n", me->name, me->version, PROGRAM_VERSION); } if (find_target(me->name, DONT_LOAD)) { exit_error(PARAMETER_PROBLEM, "target `%s' already registered.\n", me->name); } if (me->size != IPT_ALIGN(me->size)) { exit_error(PARAMETER_PROBLEM, "target `%s' has invalid size %u.\n", me->name, me->size); } /* Prepend to list. */ me->next = iptables_targets; iptables_targets = me; me->t = NULL; me->tflags = 0; opts = merge_options(opts, me->extra_opts, &me->option_offset);}}/* ---------------------- iptables helper functions ----------------------- *//* translate module options from mcl to iptables *//*static*/ int translate_option(char *rule_param, int offset){ int num = 0; num = 0; while (option_map[num].mcl) { if (!strcmp(option_map[num].mcl, rule_param)) rule_param = option_map[num].iptables; num++; } num = 0; while (opts[num].name) { if ((opts[num].val >= offset) && (opts[num].val < offset+OPTION_OFFSET) && !strcmp(opts[num].name, rule_param)) return opts[num].val; num++; } return -1;}/*static*/ void inaddrcpy(struct in_addr *dst, struct in_addr *src){ /* memcpy(dst, src, sizeof(struct in_addr)); */ dst->s_addr = src->s_addr;}/*static*/ struct in_addr *network_to_addr(const char *name){ struct netent *net; static struct in_addr addr; if ((net = getnetbyname(name)) != NULL) { if (net->n_addrtype != AF_INET) return (struct in_addr *) NULL; addr.s_addr = htonl((unsigned long) net->n_net); return &addr; } return (struct in_addr *) NULL;}/*static*/ struct in_addr *host_to_addr(const char *name, unsigned int *naddr){ struct hostent *host; struct in_addr *addr; unsigned int i; *naddr = 0; if ((host = gethostbyname(name)) != NULL) { if (host->h_addrtype != AF_INET || host->h_length != sizeof(struct in_addr)) return (struct in_addr *) NULL; while (host->h_addr_list[*naddr] != (char *) NULL) (*naddr)++; addr = (struct in_addr *) fw_calloc(*naddr, sizeof(struct in_addr)); for (i = 0; i < *naddr; i++) inaddrcpy(&(addr[i]), (struct in_addr *) host->h_addr_list[i]); return addr; } return (struct in_addr *) NULL;}/*static*/ struct in_addr *dotted_to_addr(const char *dotted){ static struct in_addr addr; unsigned char *addrp; char *p, *q; unsigned int onebyte; int i; char buf[20]; /* copy dotted string, because we need to modify it */ strncpy(buf, dotted, sizeof(buf) - 1); addrp = (unsigned char *) &(addr.s_addr); p = buf; for (i = 0; i < 3; i++) { if ((q = strchr(p, '.')) == NULL) return (struct in_addr *) NULL; *q = '\0'; if (string_to_number(p, 0, 255, &onebyte) == -1) return (struct in_addr *) NULL; addrp[i] = (unsigned char) onebyte; p = q + 1; } /* we've checked 3 bytes, now we check the last one */ if (string_to_number(p, 0, 255, &onebyte) == -1) return (struct in_addr *) NULL; addrp[3] = (unsigned char) onebyte; return &addr;} #ifdef CLASS_DEBUG/*static*/ char *addr_to_host(const struct in_addr *addr){ struct hostent *host; if ((host = gethostbyaddr((char *) addr, sizeof(struct in_addr), AF_INET)) != NULL) return (char *) host->h_name; return (char *) NULL;}/*static*/ char *addr_to_network(const struct in_addr *addr){ struct netent *net; if ((net = getnetbyaddr((long) ntohl(addr->s_addr), AF_INET)) != NULL) return (char *) net->n_name; return (char *) NULL;}/*static*/ char *addr_to_dotted(const struct in_addr *addrp){ static char buf[20]; const unsigned char *bytep; bytep = (const unsigned char *) &(addrp->s_addr); sprintf(buf, "%d.%d.%d.%d", bytep[0], bytep[1], bytep[2], bytep[3]); return buf;}/*static*/ char *mask_to_dotted(const struct in_addr *mask){ int i; static char buf[20]; u_int32_t maskaddr, bits;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -