From e3e06688b3bce45ca7449d9c6f1c9d1c11c978a8 Mon Sep 17 00:00:00 2001 From: gandalf Date: Wed, 7 May 2003 16:51:40 +0000 Subject: Add addrtype match (Patrick McHardy) --- extensions/.addrtype-test | 5 + extensions/libipt_addrtype.c | 214 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 219 insertions(+) create mode 100755 extensions/.addrtype-test create mode 100644 extensions/libipt_addrtype.c diff --git a/extensions/.addrtype-test b/extensions/.addrtype-test new file mode 100755 index 0000000..cda582b --- /dev/null +++ b/extensions/.addrtype-test @@ -0,0 +1,5 @@ +#!/bin/bash + +if test -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_addrtype.h; then + echo "addrtype" +fi diff --git a/extensions/libipt_addrtype.c b/extensions/libipt_addrtype.c new file mode 100644 index 0000000..093e915 --- /dev/null +++ b/extensions/libipt_addrtype.c @@ -0,0 +1,214 @@ +/* Shared library add-on to iptables to add addrtype matching support + * + * This program is released under the terms of GNU GPL */ + +#include +#include +#include +#include +#include + +#include +#include + +/* from linux/rtnetlink.h, must match order of enumeration */ +static char *rtn_names[] = { + "UNSPEC", + "UNICAST", + "LOCAL", + "BROADCAST", + "ANYCAST", + "MULTICAST", + "BLACKHOLE", + "UNREACHABLE", + "PROHIBIT", + "THROW", + "NAT", + "XRESOLVE", + NULL +}; + +static void help_types(void) +{ + int i; + + for (i = 0; rtn_names[i]; i++) + printf(" %s\n", rtn_names[i]); +} + +static void help(void) +{ + printf( +"Address type match v%s options:\n" +" [!] --src-type type[,...] Match source address type\n" +" [!] --dst-type type[,...] Match destination address type\n" +"\n" +"Valid types: \n" +, IPTABLES_VERSION); + help_types(); +} + +static void init(struct ipt_entry_match *m, unsigned int *nfcache) +{ + /* caching not yet implemented */ + *nfcache |= NFC_UNKNOWN; +} + +static int +parse_type(const char *name, size_t strlen, u_int16_t *mask) +{ + int i; + + for (i = 0; rtn_names[i]; i++) + if (strncasecmp(name, rtn_names[i], strlen) == 0) { + /* build up bitmask for kernel module */ + *mask |= (1 << i); + return 1; + } + + return 0; +} + +static void parse_types(const char *arg, u_int16_t *mask) +{ + const char *comma; + + while ((comma = strchr(arg, ',')) != NULL) { + if (comma == arg || !parse_type(arg, comma-arg, mask)) + exit_error(PARAMETER_PROBLEM, + "addrtype: bad type `%s'", arg); + arg = comma + 1; + } + + if (strlen(arg) == 0 || !parse_type(arg, strlen(arg), mask)) + exit_error(PARAMETER_PROBLEM, "addrtype: bad type `%s'", arg); +} + +#define IPT_ADDRTYPE_OPT_SRCTYPE 0x1 +#define IPT_ADDRTYPE_OPT_DSTTYPE 0x2 + +static int parse(int c, char **argv, int invert, unsigned int *flags, + const struct ipt_entry *entry, unsigned int *nfcache, + struct ipt_entry_match **match) +{ + struct ipt_addrtype_info *info = + (struct ipt_addrtype_info *) (*match)->data; + + switch (c) { + case '1': + if (*flags&IPT_ADDRTYPE_OPT_SRCTYPE) + exit_error(PARAMETER_PROBLEM, + "addrtype: can't specify src-type twice"); + check_inverse(optarg, &invert, &optind, 0); + parse_types(argv[optind-1], &info->source); + if (invert) + info->invert_source = 1; + *flags |= IPT_ADDRTYPE_OPT_SRCTYPE; + break; + case '2': + if (*flags&IPT_ADDRTYPE_OPT_DSTTYPE) + exit_error(PARAMETER_PROBLEM, + "addrtype: can't specify dst-type twice"); + check_inverse(optarg, &invert, &optind, 0); + parse_types(argv[optind-1], &info->dest); + if (invert) + info->invert_dest = 1; + *flags |= IPT_ADDRTYPE_OPT_DSTTYPE; + break; + default: + return 0; + } + + return 1; +} + +static void final_check(unsigned int flags) +{ + if (!(flags & (IPT_ADDRTYPE_OPT_SRCTYPE|IPT_ADDRTYPE_OPT_DSTTYPE))) + exit_error(PARAMETER_PROBLEM, + "addrtype: you must specify --src-type or --dst-type"); +} + +static void print_types(u_int16_t mask) +{ + const char *sep = ""; + int i; + + for (i = 0; rtn_names[i]; i++) + if (mask & (1 << i)) { + printf("%s%s", sep, rtn_names[i]); + sep = ","; + } + + printf(" "); +} + +static void print(const struct ipt_ip *ip, + const struct ipt_entry_match *match, + int numeric) +{ + const struct ipt_addrtype_info *info = + (struct ipt_addrtype_info *) match->data; + + printf("ADDRTYPE match "); + if (info->source) { + printf("src-type "); + if (info->invert_source) + printf("!"); + print_types(info->source); + } + if (info->dest) { + printf("dst-type "); + if (info->invert_dest) + printf("!"); + print_types(info->dest); + } +} + +static void save(const struct ipt_ip *ip, + const struct ipt_entry_match *match) +{ + const struct ipt_addrtype_info *info = + (struct ipt_addrtype_info *) match->data; + + if (info->source) { + printf("--src-type "); + if (info->invert_source) + printf("! "); + print_types(info->source); + } + if (info->dest) { + printf("--dst-type "); + if (info->invert_dest) + printf("! "); + print_types(info->dest); + } +} + +static struct option opts[] = { + { "src-type", 1, 0, '1' }, + { "dst-type", 1, 0, '2' }, + { 0 } +}; + +static +struct iptables_match addrtype = { + NULL, + "addrtype", + IPTABLES_VERSION, + IPT_ALIGN(sizeof(struct ipt_addrtype_info)), + IPT_ALIGN(sizeof(struct ipt_addrtype_info)), + &help, + &init, + &parse, + &final_check, + &print, + &save, + opts +}; + + +void _init(void) +{ + register_match(&addrtype); +} -- cgit v1.2.3