/* * netquota match (libipt_netquota.c) * netfilter userspace part (iptables) * * by Olaf Rempel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include /* offsetof() ... */ #include #include #include #include #include #include static void help(void) { printf("netquota v%s options:\n" "--nq-name name\n" " defines name of this netquota. defaults to \"DEFAULT\".\n" "--nq-src network/netmask\n" " defines a netquota by source IP address.\n" "--nq-dst network/netmask\n" " defines a netquota by destination IP address.\n", IPTABLES_VERSION); }; static struct option opts[] = { {"nq-src", 1, NULL, 's'}, {"nq-dst", 1, NULL, 'd'}, {"nq-name", 1, NULL, 'n'}, {0} }; /* Function which initializes the match */ static void init(struct ipt_entry_match *match, unsigned int *nfcache) { struct ipt_netquota_info *info = (struct ipt_netquota_info *)match->data; /* set default table name to DEFAULT */ strncpy(info->name, "DEFAULT", IPT_NETQUOTA_NAME_LEN); *nfcache |= NFC_UNKNOWN; } /* Function which parses the match's arguments */ 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_netquota_info *info = (struct ipt_netquota_info *)(*match)->data; struct in_addr *addrs = NULL, mask; unsigned int naddrs = 0, i; switch (c) { case 'n': /* --nq-name */ if (strlen(optarg) < IPT_NETQUOTA_NAME_LEN) strncpy(info->name, optarg, IPT_NETQUOTA_NAME_LEN); else exit_error(PARAMETER_PROBLEM, "netquota: Quota name too long"); break; case 's': /* --nq-src */ parse_hostnetworkmask(optarg, &addrs, &mask, &naddrs); if (naddrs > 0) { info->network = ntohl(addrs->s_addr); info->netmask = ntohl(mask.s_addr); info->mode |= IPT_NETQUOTA_SRC_MATCH; for (i = 0; i < naddrs; i++) free(&addrs[i]); *flags |= 1; } else { exit_error(PARAMETER_PROBLEM, "netquota: Invalid '--nq-src' parameter"); } break; case 'd': /* --nq-dst */ parse_hostnetworkmask(optarg, &addrs, &mask, &naddrs); if (naddrs > 0) { info->network = ntohl(addrs->s_addr); info->netmask = ntohl(mask.s_addr); info->mode |= IPT_NETQUOTA_DST_MATCH; for (i = 0; i < naddrs; i++) free(&addrs[i]); *flags |= 2; } else { exit_error(PARAMETER_PROBLEM, "netquota: Invalid '--nq-dst' parameter"); } break; default: return 0; } return 1; } /* Final check whether network/netmask was specified */ static void final_check(unsigned int flags) { switch (flags) { case 0: exit_error(PARAMETER_PROBLEM, "netquota: You must specify a '--nq-src' or '--nq-dst' " "parameter"); break; case 1: case 2: return; break; case 3: exit_error(PARAMETER_PROBLEM, "netquota: You can only specify either a" " '--nq-src' or a '--nq-dst' parameter"); break; } } /* Host byte order IP address to dotted string */ static char *haddr_to_dotted(u_int32_t ip) { struct in_addr tmp; tmp.s_addr = htonl(ip); return addr_to_dotted(&tmp); } /* Host byte order network mask to CIDR / dotted string */ static char *hmask_to_dotted(u_int32_t mask) { struct in_addr tmp; tmp.s_addr = htonl(mask); return mask_to_dotted(&tmp); } /* Function used for printing a rule with iptables -L */ static void print(const struct ipt_ip *ip, const struct ipt_entry_match *match, int numeric) { struct ipt_netquota_info *info = (struct ipt_netquota_info *)match->data; printf("netquota: %s ", info->name); switch (info->mode) { case IPT_NETQUOTA_SRC_MATCH: printf("src"); break; case IPT_NETQUOTA_DST_MATCH: printf("dst"); break; } printf("(%s%s)", haddr_to_dotted(info->network), hmask_to_dotted(info->netmask)); } /* Function used for saving a rule with iptables-save */ static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match) { struct ipt_netquota_info *info = (struct ipt_netquota_info *)match->data; printf("--nq-name %s ", info->name); switch (info->mode) { case IPT_NETQUOTA_SRC_MATCH: printf("--nq-src "); break; case IPT_NETQUOTA_DST_MATCH: printf("--nq-dst "); break; } printf("%s%s", haddr_to_dotted(info->network), hmask_to_dotted(info->netmask)); } static struct iptables_match netquota = { NULL, "netquota", IPTABLES_VERSION, IPT_ALIGN(sizeof(struct ipt_netquota_info)), offsetof(struct ipt_netquota_info, mode), &help, &init, &parse, &final_check, &print, &save, opts }; /* Function which registers the match */ void _init(void) { register_match(&netquota); }