X-Git-Url: http://developer.intra2net.com/git/?p=ipt_ACCOUNT;a=blobdiff_plain;f=iptables%2Fextensions%2Flibipt_ACCOUNT.c;fp=iptables%2Fextensions%2Flibipt_ACCOUNT.c;h=084c31f4011013a052af6640879e48d6ddfb5b0a;hp=0000000000000000000000000000000000000000;hb=146aa6772bdd87b14a91ac0a50df80a79a0ab7f8;hpb=ab1449e79dc308983a3ba1608cdb42be92bfc359 diff --git a/iptables/extensions/libipt_ACCOUNT.c b/iptables/extensions/libipt_ACCOUNT.c new file mode 100644 index 0000000..084c31f --- /dev/null +++ b/iptables/extensions/libipt_ACCOUNT.c @@ -0,0 +1,174 @@ +/* Shared library add-on to iptables to add ACCOUNT(ing) support. + Author: Intra2net AG +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct option opts[] = { + { .name = "addr", .has_arg = 1, .flag = 0, .val = 'a' }, + { .name = "tname", .has_arg = 1, .flag = 0, .val = 't' }, + { .name = 0 } +}; + +/* Function which prints out usage message. */ +static void help(void) +{ + printf( +"ACCOUNT v%s options:\n" +" --%s ip/netmask\t\tBase network IP and netmask used for this table\n" +" --%s name\t\t\tTable name for the userspace library\n", +IPTABLES_VERSION, opts[0].name, opts[1].name); +} + +/* Initialize the target. */ +static void +init(struct ipt_entry_target *t, unsigned int *nfcache) +{ + struct ipt_acc_info *accountinfo = (struct ipt_acc_info *)t->data; + + accountinfo->table_nr = -1; + + /* Can't cache this */ + *nfcache |= NFC_UNKNOWN; +} + +#define IPT_ACCOUNT_OPT_ADDR 0x01 +#define IPT_ACCOUNT_OPT_TABLE 0x02 + +/* Function which parses command options; returns true if it + ate an option */ +static int +parse(int c, char **argv, int invert, unsigned int *flags, + const struct ipt_entry *entry, + struct ipt_entry_target **target) +{ + struct ipt_acc_info *accountinfo = (struct ipt_acc_info *)(*target)->data; + struct in_addr *addrs = NULL, mask; + unsigned int naddrs = 0; + + switch (c) { + case 'a': + if (*flags & IPT_ACCOUNT_OPT_ADDR) + exit_error(PARAMETER_PROBLEM, "Can't specify --%s twice", + opts[0].name); + + if (check_inverse(optarg, &invert, NULL, 0)) + exit_error(PARAMETER_PROBLEM, "Unexpected `!' after --%s", + opts[0].name); + + //loginfo->level = parse_level(optarg); + parse_hostnetworkmask(optarg, &addrs, &mask, &naddrs); + + if (naddrs > 1) + exit_error(PARAMETER_PROBLEM, "multiple IP addresses not allowed"); + + accountinfo->net_ip = addrs[0].s_addr; + accountinfo->net_mask = mask.s_addr; + + *flags |= IPT_ACCOUNT_OPT_ADDR; + break; + + case 't': + if (*flags & IPT_ACCOUNT_OPT_TABLE) + exit_error(PARAMETER_PROBLEM, + "Can't specify --%s twice", opts[1].name); + + if (check_inverse(optarg, &invert, NULL, 0)) + exit_error(PARAMETER_PROBLEM, + "Unexpected `!' after --%s", opts[1].name); + + if (strlen(optarg) > ACCOUNT_TABLE_NAME_LEN - 1) + exit_error(PARAMETER_PROBLEM, + "Maximum table name length %u for --%s", + ACCOUNT_TABLE_NAME_LEN - 1, opts[1].name); + + strcpy(accountinfo->table_name, optarg); + *flags |= IPT_ACCOUNT_OPT_TABLE; + break; + + default: + return 0; + } + return 1; +} + +/* Final check; nothing. */ +static void final_check(unsigned int flags) +{ + if (!(flags&IPT_ACCOUNT_OPT_ADDR) || !(flags&IPT_ACCOUNT_OPT_TABLE)) + exit_error(PARAMETER_PROBLEM, "ACCOUNT: needs --%s and --%s", + opts[0].name, opts[1].name); +} + +static void print_it(const struct ipt_ip *ip, + const struct ipt_entry_target *target, char do_prefix) +{ + const struct ipt_acc_info *accountinfo + = (const struct ipt_acc_info *)target->data; + struct in_addr a; + + if (!do_prefix) + printf("ACCOUNT "); + + // Network information + if (do_prefix) + printf("--"); + printf("%s ", opts[0].name); + + a.s_addr = accountinfo->net_ip; + printf("%s", addr_to_dotted(&a)); + a.s_addr = accountinfo->net_mask; + printf("%s", mask_to_dotted(&a)); + + printf(" "); + if (do_prefix) + printf("--"); + + printf("%s %s", opts[1].name, accountinfo->table_name); +} + +/* Prints out the targinfo. */ +static void +print(const struct ipt_ip *ip, + const struct ipt_entry_target *target, + int numeric) +{ + print_it (ip, target, 0); +} + +/* Saves the union ipt_targinfo in parsable form to stdout. */ +static void +save(const struct ipt_ip *ip, const struct ipt_entry_target *target) +{ + print_it(ip, target, 1); +} + +static +struct iptables_target account += { + .next = NULL, + .name = "ACCOUNT", + .version = IPTABLES_VERSION, + .size = IPT_ALIGN(sizeof(struct ipt_acc_info)), + .userspacesize = IPT_ALIGN(sizeof(struct ipt_acc_info)), + .help = &help, + .init = &init, + .parse = &parse, + .final_check = &final_check, + .print = &print, + .save = &save, + .extra_opts = opts +}; + +void _init(void) +{ + register_target(&account); +}