ipt_netquota/iptables/extensions/libipt_netquota.c

216 lines
4.8 KiB
C

/*
* netquota match (libipt_netquota.c)
* netfilter userspace part (iptables)
*
* by Olaf Rempel <razzor at kopf minus tisch dot de>
*
* 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 <stddef.h> /* offsetof() ... */
#include <stdio.h>
#include <stdlib.h>
#include <iptables.h>
#include <string.h>
#include <getopt.h>
#include <linux/netfilter_ipv4/ipt_netquota.h>
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);
}