summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--iptables/xtables-arp.c243
1 files changed, 30 insertions, 213 deletions
diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c
index 35844a9b..1a260e75 100644
--- a/iptables/xtables-arp.c
+++ b/iptables/xtables-arp.c
@@ -317,89 +317,10 @@ static int get16_and_mask(char *from, uint16_t *to, uint16_t *mask, int base)
return 0;
}
-static 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 && min <= number && number <= max) {
- *ret = number;
- return 0;
- }
- }
- return -1;
-}
-
/*********************************************/
/* ARPTABLES SPECIFIC NEW FUNCTIONS END HERE */
/*********************************************/
-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;
-}
-
-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 void
-inaddrcpy(struct in_addr *dst, struct in_addr *src)
-{
- /* memcpy(dst, src, sizeof(struct in_addr)); */
- dst->s_addr = src->s_addr;
-}
-
static void
exit_tryhelp(int status)
{
@@ -588,127 +509,6 @@ check_inverse(const char option[], int *invert, int *optidx, int argc)
return FALSE;
}
-static struct in_addr *
-host_to_addr(const char *name, unsigned int *naddr)
-{
- struct in_addr *addr;
- struct addrinfo hints = {
- .ai_flags = AI_CANONNAME,
- .ai_family = AF_INET,
- .ai_socktype = SOCK_RAW,
- };;
- struct addrinfo *res, *p;
- int err;
- unsigned int i;
-
- *naddr = 0;
- err = getaddrinfo(name, NULL, &hints, &res);
- if (err != 0)
- return NULL;
- else {
- for (p = res; p != NULL; p = p->ai_next)
- (*naddr)++;
- addr = xtables_calloc(*naddr, sizeof(struct in_addr));
- for (i = 0, p = res; p != NULL; p = p->ai_next)
- memcpy(&addr[i++],
- &((const struct sockaddr_in *)p->ai_addr)->sin_addr,
- sizeof(struct in_addr));
- freeaddrinfo(res);
- return addr;
- }
-
- return (struct in_addr *) NULL;
-}
-
-/*
- * All functions starting with "parse" should succeed, otherwise
- * the program fails.
- * Most routines return pointers to static data that may change
- * between calls to the same or other routines with a few exceptions:
- * "host_to_addr", "parse_hostnetwork", and "parse_hostnetworkmask"
- * return global static data.
-*/
-
-static struct in_addr *
-parse_hostnetwork(const char *name, unsigned int *naddrs)
-{
- struct in_addr *addrp, *addrptmp;
-
- if ((addrptmp = dotted_to_addr(name)) != NULL ||
- (addrptmp = network_to_addr(name)) != NULL) {
- addrp = xtables_malloc(sizeof(struct in_addr));
- inaddrcpy(addrp, addrptmp);
- *naddrs = 1;
- return addrp;
- }
- if ((addrp = host_to_addr(name, naddrs)) != NULL)
- return addrp;
-
- xtables_error(PARAMETER_PROBLEM, "host/network `%s' not found", name);
-}
-
-static struct in_addr *
-parse_mask(char *mask)
-{
- static struct in_addr maskaddr;
- struct in_addr *addrp;
- unsigned int bits;
-
- if (mask == NULL) {
- /* no mask at all defaults to 32 bits */
- maskaddr.s_addr = 0xFFFFFFFF;
- return &maskaddr;
- }
- if ((addrp = dotted_to_addr(mask)) != NULL)
- /* dotted_to_addr already returns a network byte order addr */
- return addrp;
- if (string_to_number(mask, 0, 32, &bits) == -1)
- xtables_error(PARAMETER_PROBLEM,
- "invalid mask `%s' specified", mask);
- if (bits != 0) {
- maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits));
- return &maskaddr;
- }
-
- maskaddr.s_addr = 0L;
- return &maskaddr;
-}
-
-static void
-parse_hostnetworkmask(const char *name, struct in_addr **addrpp,
- struct in_addr *maskp, unsigned int *naddrs)
-{
- struct in_addr *addrp;
- char buf[256];
- char *p;
- int i, j, k, n;
-
- strncpy(buf, name, sizeof(buf) - 1);
- if ((p = strrchr(buf, '/')) != NULL) {
- *p = '\0';
- addrp = parse_mask(p + 1);
- } else
- addrp = parse_mask(NULL);
- inaddrcpy(maskp, addrp);
-
- /* if a null mask is given, the name is ignored, like in "any/0" */
- if (maskp->s_addr == 0L)
- strcpy(buf, "0.0.0.0");
-
- addrp = *addrpp = parse_hostnetwork(buf, naddrs);
- n = *naddrs;
- for (i = 0, j = 0; i < n; i++) {
- addrp[j++].s_addr &= maskp->s_addr;
- for (k = 0; k < j - 1; k++) {
- if (addrp[k].s_addr == addrp[j - 1].s_addr) {
- (*naddrs)--;
- j--;
- break;
- }
- }
- }
-}
-
static void
parse_interface(const char *arg, char *vianame, unsigned char *mask)
{
@@ -814,8 +614,10 @@ append_entry(struct nft_handle *h,
int rulenum,
unsigned int nsaddrs,
const struct in_addr saddrs[],
+ const struct in_addr smasks[],
unsigned int ndaddrs,
const struct in_addr daddrs[],
+ const struct in_addr dmasks[],
bool verbose, bool append)
{
unsigned int i, j;
@@ -823,8 +625,10 @@ append_entry(struct nft_handle *h,
for (i = 0; i < nsaddrs; i++) {
cs->arp.arp.src.s_addr = saddrs[i].s_addr;
+ cs->arp.arp.smsk.s_addr = smasks[i].s_addr;
for (j = 0; j < ndaddrs; j++) {
cs->arp.arp.tgt.s_addr = daddrs[j].s_addr;
+ cs->arp.arp.tmsk.s_addr = dmasks[j].s_addr;
if (append) {
ret = nft_rule_append(h, chain, table, cs, NULL,
verbose);
@@ -844,11 +648,15 @@ replace_entry(const char *chain,
struct iptables_command_state *cs,
unsigned int rulenum,
const struct in_addr *saddr,
+ const struct in_addr *smask,
const struct in_addr *daddr,
+ const struct in_addr *dmask,
bool verbose, struct nft_handle *h)
{
cs->arp.arp.src.s_addr = saddr->s_addr;
cs->arp.arp.tgt.s_addr = daddr->s_addr;
+ cs->arp.arp.smsk.s_addr = smask->s_addr;
+ cs->arp.arp.tmsk.s_addr = dmask->s_addr;
return nft_rule_replace(h, chain, table, cs, rulenum, verbose);
}
@@ -859,8 +667,10 @@ delete_entry(const char *chain,
struct iptables_command_state *cs,
unsigned int nsaddrs,
const struct in_addr saddrs[],
+ const struct in_addr smasks[],
unsigned int ndaddrs,
const struct in_addr daddrs[],
+ const struct in_addr dmasks[],
bool verbose, struct nft_handle *h)
{
unsigned int i, j;
@@ -868,8 +678,10 @@ delete_entry(const char *chain,
for (i = 0; i < nsaddrs; i++) {
cs->arp.arp.src.s_addr = saddrs[i].s_addr;
+ cs->arp.arp.smsk.s_addr = smasks[i].s_addr;
for (j = 0; j < ndaddrs; j++) {
cs->arp.arp.tgt.s_addr = daddrs[j].s_addr;
+ cs->arp.arp.tmsk.s_addr = dmasks[j].s_addr;
ret = nft_rule_delete(h, chain, table, cs, verbose);
}
}
@@ -919,7 +731,8 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
};
int invert = 0;
unsigned int nsaddrs = 0, ndaddrs = 0;
- struct in_addr *saddrs = NULL, *daddrs = NULL;
+ struct in_addr *saddrs = NULL, *smasks = NULL;
+ struct in_addr *daddrs = NULL, *dmasks = NULL;
int c, verbose = 0;
const char *chain = NULL;
@@ -1292,12 +1105,12 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
}
if (shostnetworkmask)
- parse_hostnetworkmask(shostnetworkmask, &saddrs,
- &(cs.arp.arp.smsk), &nsaddrs);
+ xtables_ipparse_multiple(shostnetworkmask, &saddrs,
+ &smasks, &nsaddrs);
if (dhostnetworkmask)
- parse_hostnetworkmask(dhostnetworkmask, &daddrs,
- &(cs.arp.arp.tmsk), &ndaddrs);
+ xtables_ipparse_multiple(dhostnetworkmask, &daddrs,
+ &dmasks, &ndaddrs);
if ((nsaddrs > 1 || ndaddrs > 1) &&
(cs.arp.arp.invflags & (ARPT_INV_SRCIP | ARPT_INV_TGTIP)))
@@ -1343,12 +1156,14 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
switch (command) {
case CMD_APPEND:
ret = append_entry(h, chain, *table, &cs, 0,
- nsaddrs, saddrs, ndaddrs, daddrs,
+ nsaddrs, saddrs, smasks,
+ ndaddrs, daddrs, dmasks,
options&OPT_VERBOSE, true);
break;
case CMD_DELETE:
ret = delete_entry(chain, *table, &cs,
- nsaddrs, saddrs, ndaddrs, daddrs,
+ nsaddrs, saddrs, smasks,
+ ndaddrs, daddrs, dmasks,
options&OPT_VERBOSE, h);
break;
case CMD_DELETE_NUM:
@@ -1356,11 +1171,13 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
break;
case CMD_REPLACE:
ret = replace_entry(chain, *table, &cs, rulenum - 1,
- saddrs, daddrs, options&OPT_VERBOSE, h);
+ saddrs, smasks, daddrs, dmasks,
+ options&OPT_VERBOSE, h);
break;
case CMD_INSERT:
ret = append_entry(h, chain, *table, &cs, rulenum - 1,
- nsaddrs, saddrs, ndaddrs, daddrs,
+ nsaddrs, saddrs, smasks,
+ ndaddrs, daddrs, dmasks,
options&OPT_VERBOSE, false);
break;
case CMD_LIST:
@@ -1409,10 +1226,10 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
exit_tryhelp(2);
}
- if (nsaddrs)
- free(saddrs);
- if (ndaddrs)
- free(daddrs);
+ free(saddrs);
+ free(smasks);
+ free(daddrs);
+ free(dmasks);
if (cs.target)
free(cs.target->t);