diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2003-01-14 21:58:13 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2003-01-14 21:58:13 +0000 |
commit | 0483320cc2bd3bd941b2b7b29ab9c37b1e05eb47 (patch) | |
tree | 98dfc33c34fae3108a13893cc07adf2ad85a2fee /sbin/pfctl | |
parent | b17b2726dbea15de0f41eb62e24c7e199c77384f (diff) |
unified IP parser:
-move host(), set_ipmask and the ifa_* functions to pfctl_parser.[c|h]
-extend host() to handle /mask itself, plus minor adjustments
-use that in pfctl_table.c instead of coding the same shit again
discussed w/ cedric@
ok cedric@ dhartmei@
Diffstat (limited to 'sbin/pfctl')
-rw-r--r-- | sbin/pfctl/parse.y | 330 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.c | 331 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.h | 34 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_table.c | 93 |
4 files changed, 402 insertions, 386 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index ec54698609f..a9ca033366e 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.288 2003/01/13 08:17:47 camield Exp $ */ +/* $OpenBSD: parse.y,v 1.289 2003/01/14 21:58:11 henning Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -43,7 +43,6 @@ #include <stdio.h> #include <stdlib.h> -#include <ifaddrs.h> #include <netdb.h> #include <stdarg.h> #include <errno.h> @@ -79,38 +78,12 @@ enum { PFCTL_STATE_FILTER }; -enum pfctl_iflookup_mode { - PFCTL_IFLOOKUP_HOST, - PFCTL_IFLOOKUP_NET, - PFCTL_IFLOOKUP_BCAST -}; - -struct node_if { - char ifname[IFNAMSIZ]; - u_int8_t not; - u_int ifa_flags; - struct node_if *next; - struct node_if *tail; -}; - struct node_proto { u_int8_t proto; struct node_proto *next; struct node_proto *tail; }; -struct node_host { - struct pf_addr_wrap addr; - struct pf_addr bcast; - sa_family_t af; - u_int8_t not; - u_int32_t ifindex; /* link-local IPv6 addrs */ - char *ifname; - u_int ifa_flags; - struct node_host *next; - struct node_host *tail; -}; - struct node_port { u_int16_t port[2]; u_int8_t op; @@ -242,7 +215,6 @@ int rule_consistent(struct pf_rule *); int nat_consistent(struct pf_rule *); int rdr_consistent(struct pf_rule *); int yyparse(void); -void set_ipmask(struct node_host *, u_int8_t); void expand_rdr(struct pf_rule *, struct node_if *, struct node_proto *, struct node_host *, struct node_host *, struct node_host *); void expand_nat(struct pf_rule *, struct node_if *, struct node_proto *, @@ -272,7 +244,6 @@ int lgetc(FILE *); int lungetc(int); int findeol(void); int yylex(void); -struct node_host *host(char *, int); int atoul(char *, u_long *); int getservice(char *); @@ -287,9 +258,6 @@ struct sym *symhead = NULL; int symset(const char *, const char *); char *symget(const char *); -void ifa_load(void); -struct node_host *ifa_exists(char *); -struct node_host *ifa_lookup(char *, enum pfctl_iflookup_mode); void decide_address_family(struct node_host *, sa_family_t *); void remove_invalid_hosts(struct node_host **, @@ -3901,32 +3869,6 @@ parse_rules(FILE *input, struct pfctl *xpf, int opts) return (errors ? -1 : 0); } -void -set_ipmask(struct node_host *h, u_int8_t b) -{ - struct pf_addr *m, *n; - int i, j = 0; - - m = &h->addr.v.a.mask; - - for (i = 0; i < 4; i++) - m->addr32[i] = 0; - - while (b >= 32) { - m->addr32[j++] = 0xffffffff; - b -= 32; - } - for (i = 31; i > 31-b; --i) - m->addr32[j] |= (1 << i); - if (b) - m->addr32[j] = htonl(m->addr32[j]); - - /* Mask off bits of the address that will never be used. */ - n = &h->addr.v.a.addr; - for (i = 0; i < 4; i++) - n->addr32[i] = n->addr32[i] & m->addr32[i]; -} - /* * Over-designed efficiency is a French and German concept, so how about * we wait until they discover this ugliness and make it all fancy. @@ -3969,160 +3911,6 @@ symget(const char *nam) return (NULL); } -/* interface lookup routines */ - -struct node_host *iftab; - -void -ifa_load(void) -{ - struct ifaddrs *ifap, *ifa; - struct node_host *n = NULL, *h = NULL; - - if (getifaddrs(&ifap) < 0) - err(1, "getifaddrs"); - - for (ifa = ifap; ifa; ifa = ifa->ifa_next) { - if (!(ifa->ifa_addr->sa_family == AF_INET || - ifa->ifa_addr->sa_family == AF_INET6 || - ifa->ifa_addr->sa_family == AF_LINK)) - continue; - n = calloc(1, sizeof(struct node_host)); - if (n == NULL) - err(1, "address: calloc"); - n->af = ifa->ifa_addr->sa_family; - n->ifa_flags = ifa->ifa_flags; -#ifdef __KAME__ - if (n->af == AF_INET6 && - IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *) - ifa->ifa_addr)->sin6_addr) && - ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id == 0) { - struct sockaddr_in6 *sin6; - - sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; - sin6->sin6_scope_id = sin6->sin6_addr.s6_addr[2] << 8 | - sin6->sin6_addr.s6_addr[3]; - sin6->sin6_addr.s6_addr[2] = 0; - sin6->sin6_addr.s6_addr[3] = 0; - } -#endif - n->ifindex = 0; - if (n->af == AF_INET) { - memcpy(&n->addr.v.a.addr, &((struct sockaddr_in *) - ifa->ifa_addr)->sin_addr.s_addr, - sizeof(struct in_addr)); - memcpy(&n->addr.v.a.mask, &((struct sockaddr_in *) - ifa->ifa_netmask)->sin_addr.s_addr, - sizeof(struct in_addr)); - if (ifa->ifa_broadaddr != NULL) - memcpy(&n->bcast, &((struct sockaddr_in *) - ifa->ifa_broadaddr)->sin_addr.s_addr, - sizeof(struct in_addr)); - } else if (n->af == AF_INET6) { - memcpy(&n->addr.v.a.addr, &((struct sockaddr_in6 *) - ifa->ifa_addr)->sin6_addr.s6_addr, - sizeof(struct in6_addr)); - memcpy(&n->addr.v.a.mask, &((struct sockaddr_in6 *) - ifa->ifa_netmask)->sin6_addr.s6_addr, - sizeof(struct in6_addr)); - if (ifa->ifa_broadaddr != NULL) - memcpy(&n->bcast, &((struct sockaddr_in6 *) - ifa->ifa_broadaddr)->sin6_addr.s6_addr, - sizeof(struct in6_addr)); - n->ifindex = ((struct sockaddr_in6 *) - ifa->ifa_addr)->sin6_scope_id; - } - if ((n->ifname = strdup(ifa->ifa_name)) == NULL) - err(1, "ifa_load: strdup"); - n->next = NULL; - n->tail = n; - if (h == NULL) - h = n; - else { - h->tail->next = n; - h->tail = n; - } - } - iftab = h; - freeifaddrs(ifap); -} - -struct node_host * -ifa_exists(char *ifa_name) -{ - struct node_host *n; - - if (iftab == NULL) - ifa_load(); - - for (n = iftab; n; n = n->next) { - if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ)) - return (n); - } - return (NULL); -} - -struct node_host * -ifa_lookup(char *ifa_name, enum pfctl_iflookup_mode mode) -{ - struct node_host *p = NULL, *h = NULL, *n = NULL; - int return_all = 0; - - if (!strncmp(ifa_name, "self", IFNAMSIZ)) - return_all = 1; - - if (iftab == NULL) - ifa_load(); - - for (p = iftab; p; p = p->next) { - if (!((p->af == AF_INET || p->af == AF_INET6) && - (!strncmp(p->ifname, ifa_name, IFNAMSIZ) || return_all))) - continue; - if (mode == PFCTL_IFLOOKUP_BCAST && p->af != AF_INET) - continue; - if (mode == PFCTL_IFLOOKUP_NET && p->ifindex > 0) - continue; - n = calloc(1, sizeof(struct node_host)); - if (n == NULL) - err(1, "address: calloc"); - n->af = p->af; - if (mode == PFCTL_IFLOOKUP_BCAST) - memcpy(&n->addr.v.a.addr, &p->bcast, - sizeof(struct pf_addr)); - else - memcpy(&n->addr.v.a.addr, &p->addr.v.a.addr, - sizeof(struct pf_addr)); - if (mode == PFCTL_IFLOOKUP_NET) - set_ipmask(n, unmask(&p->addr.v.a.mask, n->af)); - else { - if (n->af == AF_INET) { - if (p->ifa_flags & IFF_LOOPBACK && - p->ifa_flags & IFF_LINK1) - memcpy(&n->addr.v.a.mask, - &p->addr.v.a.mask, - sizeof(struct pf_addr)); - else - set_ipmask(n, 32); - } else - set_ipmask(n, 128); - } - n->ifindex = p->ifindex; - - n->next = NULL; - n->tail = n; - if (h == NULL) - h = n; - else { - h->tail->next = n; - h->tail = n; - } - } - if (h == NULL && mode == PFCTL_IFLOOKUP_HOST) { - yyerror("no IP address found for %s", ifa_name); - } - return (h); -} - void decide_address_family(struct node_host *n, sa_family_t *af) { @@ -4180,122 +3968,6 @@ remove_invalid_hosts(struct node_host **nh, sa_family_t *af) "found."); } -struct node_host * -host(char *s, int mask) -{ - struct node_host *h = NULL, *n; - struct in_addr ina; - struct addrinfo hints, *res0, *res; - int bits, error, v4mask, v6mask; - char *buf = NULL; - - if (ifa_exists(s) || !strncmp(s, "self", IFNAMSIZ)) { - /* interface with this name exists */ - h = ifa_lookup(s, PFCTL_IFLOOKUP_HOST); - for (n = h; n != NULL && mask > -1; n = n->next) - set_ipmask(n, mask); - return (h); - } - - if (mask == -1) { - if (asprintf(&buf, "%s", s) == -1) - err(1, "host: asprintf"); - v4mask = 32; - v6mask = 128; - } else if (mask <= 128) { - if (asprintf(&buf, "%s/%d", s, mask) == -1) - err(1, "host: asprintf"); - v4mask = v6mask = mask; - } else { - yyerror("illegal mask"); - return (NULL); - } - - memset(&ina, 0, sizeof(struct in_addr)); - if ((bits = inet_net_pton(AF_INET, buf, &ina, sizeof(&ina))) > -1) { - h = calloc(1, sizeof(struct node_host)); - if (h == NULL) - err(1, "address: calloc"); - h->ifname = NULL; - h->af = AF_INET; - h->addr.v.a.addr.addr32[0] = ina.s_addr; - set_ipmask(h, bits); - h->next = NULL; - h->tail = h; - free(buf); - return (h); - } - free(buf); - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET6; - hints.ai_socktype = SOCK_DGRAM; /*dummy*/ - hints.ai_flags = AI_NUMERICHOST; - if (getaddrinfo(s, "0", &hints, &res) == 0) { - n = calloc(1, sizeof(struct node_host)); - if (n == NULL) - err(1, "address: calloc"); - n->ifname = NULL; - n->af = AF_INET6; - memcpy(&n->addr.v.a.addr, - &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, - sizeof(n->addr.v.a.addr)); - n->ifindex = ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; - set_ipmask(n, v6mask); - freeaddrinfo(res); - n->next = NULL; - n->tail = n; - return (n); - } - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; /* DUMMY */ - error = getaddrinfo(s, NULL, &hints, &res0); - if (error) { - yyerror("cannot resolve %s: %s", - s, gai_strerror(error)); - return (NULL); - } - for (res = res0; res; res = res->ai_next) { - if (res->ai_family != AF_INET && - res->ai_family != AF_INET6) - continue; - n = calloc(1, sizeof(struct node_host)); - if (n == NULL) - err(1, "address: calloc"); - n->ifname = NULL; - n->af = res->ai_family; - if (res->ai_family == AF_INET) { - memcpy(&n->addr.v.a.addr, - &((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr, - sizeof(struct in_addr)); - set_ipmask(n, v4mask); - } else { - memcpy(&n->addr.v.a.addr, - &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr.s6_addr, - sizeof(struct in6_addr)); - n->ifindex = - ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; - set_ipmask(n, v6mask); - } - n->next = NULL; - n->tail = n; - if (h == NULL) - h = n; - else { - h->tail->next = n; - h->tail = n; - } - } - freeaddrinfo(res0); - if (h == NULL) { - yyerror("no IP address found for %s", s); - return (NULL); - } - return (h); -} - int atoul(char *s, u_long *ulvalp) { diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index ad0d6774e86..b38a5d2affb 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.c,v 1.127 2003/01/05 22:14:23 dhartmei Exp $ */ +/* $OpenBSD: pfctl_parser.c,v 1.128 2003/01/14 21:58:12 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -49,6 +49,7 @@ #include <stdarg.h> #include <errno.h> #include <err.h> +#include <ifaddrs.h> #include "pfctl_parser.h" #include "pfctl.h" @@ -944,3 +945,331 @@ parse_flags(char *s) } return (f ? f : PF_TH_ALL); } + +void +set_ipmask(struct node_host *h, u_int8_t b) +{ + struct pf_addr *m, *n; + int i, j = 0; + + m = &h->addr.v.a.mask; + + for (i = 0; i < 4; i++) + m->addr32[i] = 0; + + while (b >= 32) { + m->addr32[j++] = 0xffffffff; + b -= 32; + } + for (i = 31; i > 31-b; --i) + m->addr32[j] |= (1 << i); + if (b) + m->addr32[j] = htonl(m->addr32[j]); + + /* Mask off bits of the address that will never be used. */ + n = &h->addr.v.a.addr; + for (i = 0; i < 4; i++) + n->addr32[i] = n->addr32[i] & m->addr32[i]; +} + +/* interface lookup routines */ + +struct node_host *iftab; + +void +ifa_load(void) +{ + struct ifaddrs *ifap, *ifa; + struct node_host *n = NULL, *h = NULL; + + if (getifaddrs(&ifap) < 0) + err(1, "getifaddrs"); + + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + if (!(ifa->ifa_addr->sa_family == AF_INET || + ifa->ifa_addr->sa_family == AF_INET6 || + ifa->ifa_addr->sa_family == AF_LINK)) + continue; + n = calloc(1, sizeof(struct node_host)); + if (n == NULL) + err(1, "address: calloc"); + n->af = ifa->ifa_addr->sa_family; + n->ifa_flags = ifa->ifa_flags; +#ifdef __KAME__ + if (n->af == AF_INET6 && + IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *) + ifa->ifa_addr)->sin6_addr) && + ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id == 0) { + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; + sin6->sin6_scope_id = sin6->sin6_addr.s6_addr[2] << 8 | + sin6->sin6_addr.s6_addr[3]; + sin6->sin6_addr.s6_addr[2] = 0; + sin6->sin6_addr.s6_addr[3] = 0; + } +#endif + n->ifindex = 0; + if (n->af == AF_INET) { + memcpy(&n->addr.v.a.addr, &((struct sockaddr_in *) + ifa->ifa_addr)->sin_addr.s_addr, + sizeof(struct in_addr)); + memcpy(&n->addr.v.a.mask, &((struct sockaddr_in *) + ifa->ifa_netmask)->sin_addr.s_addr, + sizeof(struct in_addr)); + if (ifa->ifa_broadaddr != NULL) + memcpy(&n->bcast, &((struct sockaddr_in *) + ifa->ifa_broadaddr)->sin_addr.s_addr, + sizeof(struct in_addr)); + } else if (n->af == AF_INET6) { + memcpy(&n->addr.v.a.addr, &((struct sockaddr_in6 *) + ifa->ifa_addr)->sin6_addr.s6_addr, + sizeof(struct in6_addr)); + memcpy(&n->addr.v.a.mask, &((struct sockaddr_in6 *) + ifa->ifa_netmask)->sin6_addr.s6_addr, + sizeof(struct in6_addr)); + if (ifa->ifa_broadaddr != NULL) + memcpy(&n->bcast, &((struct sockaddr_in6 *) + ifa->ifa_broadaddr)->sin6_addr.s6_addr, + sizeof(struct in6_addr)); + n->ifindex = ((struct sockaddr_in6 *) + ifa->ifa_addr)->sin6_scope_id; + } + if ((n->ifname = strdup(ifa->ifa_name)) == NULL) + err(1, "ifa_load: strdup"); + n->next = NULL; + n->tail = n; + if (h == NULL) + h = n; + else { + h->tail->next = n; + h->tail = n; + } + } + iftab = h; + freeifaddrs(ifap); +} + +struct node_host * +ifa_exists(char *ifa_name) +{ + struct node_host *n; + + if (iftab == NULL) + ifa_load(); + + for (n = iftab; n; n = n->next) { + if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ)) + return (n); + } + return (NULL); +} + +struct node_host * +ifa_lookup(char *ifa_name, enum pfctl_iflookup_mode mode) +{ + struct node_host *p = NULL, *h = NULL, *n = NULL; + int return_all = 0; + + if (!strncmp(ifa_name, "self", IFNAMSIZ)) + return_all = 1; + + if (iftab == NULL) + ifa_load(); + + for (p = iftab; p; p = p->next) { + if (!((p->af == AF_INET || p->af == AF_INET6) && + (!strncmp(p->ifname, ifa_name, IFNAMSIZ) || return_all))) + continue; + if (mode == PFCTL_IFLOOKUP_BCAST && p->af != AF_INET) + continue; + if (mode == PFCTL_IFLOOKUP_NET && p->ifindex > 0) + continue; + n = calloc(1, sizeof(struct node_host)); + if (n == NULL) + err(1, "address: calloc"); + n->af = p->af; + if (mode == PFCTL_IFLOOKUP_BCAST) + memcpy(&n->addr.v.a.addr, &p->bcast, + sizeof(struct pf_addr)); + else + memcpy(&n->addr.v.a.addr, &p->addr.v.a.addr, + sizeof(struct pf_addr)); + if (mode == PFCTL_IFLOOKUP_NET) + set_ipmask(n, unmask(&p->addr.v.a.mask, n->af)); + else { + if (n->af == AF_INET) { + if (p->ifa_flags & IFF_LOOPBACK && + p->ifa_flags & IFF_LINK1) + memcpy(&n->addr.v.a.mask, + &p->addr.v.a.mask, + sizeof(struct pf_addr)); + else + set_ipmask(n, 32); + } else + set_ipmask(n, 128); + } + n->ifindex = p->ifindex; + + n->next = NULL; + n->tail = n; + if (h == NULL) + h = n; + else { + h->tail->next = n; + h->tail = n; + } + } + if (h == NULL && mode == PFCTL_IFLOOKUP_HOST) { + fprintf(stderr, "no IP address found for %s\n", ifa_name); + } + return (h); +} + +struct node_host * +host(char *s, int mask) +{ + struct node_host *h = NULL, *n; + struct in_addr ina; + struct addrinfo hints, *res0, *res; + int bits, error, v4mask, v6mask; + char *buf = NULL, *p, *q, *ps; + + if (ifa_exists(s) || !strncmp(s, "self", IFNAMSIZ)) { + /* interface with this name exists */ + h = ifa_lookup(s, PFCTL_IFLOOKUP_HOST); + for (n = h; n != NULL && mask > -1; n = n->next) + set_ipmask(n, mask); + return (h); + } + + if ((p = strrchr(s, '/')) != NULL) { + if (mask != -1) { + fprintf(stderr, "address with netmask specified" + "and extra netmask supplied\n"); + return (NULL); + } + mask = strtol(p+1, &q, 0); + if (!q || *q) { + fprintf(stderr, "invalid netmask\n"); + return (NULL); + } + if (asprintf(&buf, "%s", s) == -1) + err(1, "host: asprintf"); + if ((ps = malloc(strlen(s) + 1)) == NULL) + err(1, "host: malloc"); + strlcpy(ps, s, strlen(s) - strlen(p) + 1); + v4mask = v6mask = mask; + } else { + if (asprintf(&ps, "%s", s) == -1) + err(1, "host: asprintf"); + if (mask == -1) { + if (asprintf(&buf, "%s", s) == -1) + err(1, "host: asprintf"); + v4mask = 32; + v6mask = 128; + } else if (mask <= 128) { + if (asprintf(&buf, "%s/%d", s, mask) == -1) + err(1, "host: asprintf"); + v4mask = v6mask = mask; + } else { + fprintf(stderr, "illegal mask\n"); + return (NULL); + } + } + + memset(&ina, 0, sizeof(struct in_addr)); + if ((bits = inet_net_pton(AF_INET, buf, &ina, sizeof(&ina))) > -1) { + h = calloc(1, sizeof(struct node_host)); + if (h == NULL) + err(1, "address: calloc"); + h->ifname = NULL; + h->af = AF_INET; + h->addr.v.a.addr.addr32[0] = ina.s_addr; + set_ipmask(h, bits); + h->next = NULL; + h->tail = h; + free(buf); + free(ps); + if (mask > -1 && mask != bits) { + fprintf(stderr, "illegal netmask %d\n", mask); + free (h); + return (NULL); + } + return (h); + } + free(buf); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + hints.ai_flags = AI_NUMERICHOST; + if (getaddrinfo(ps, "0", &hints, &res) == 0) { + n = calloc(1, sizeof(struct node_host)); + if (n == NULL) + err(1, "address: calloc"); + n->ifname = NULL; + n->af = AF_INET6; + memcpy(&n->addr.v.a.addr, + &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, + sizeof(n->addr.v.a.addr)); + n->ifindex = ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; + set_ipmask(n, v6mask); + freeaddrinfo(res); + n->next = NULL; + n->tail = n; + free(ps); + return (n); + } + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; /* DUMMY */ + error = getaddrinfo(ps, NULL, &hints, &res0); + if (error) { + fprintf(stderr, "cannot resolve %s: %s\n", + s, gai_strerror(error)); + free(ps); + return (NULL); + } + for (res = res0; res; res = res->ai_next) { + if (res->ai_family != AF_INET && + res->ai_family != AF_INET6) + continue; + n = calloc(1, sizeof(struct node_host)); + if (n == NULL) + err(1, "address: calloc"); + n->ifname = NULL; + n->af = res->ai_family; + if (res->ai_family == AF_INET) { + memcpy(&n->addr.v.a.addr, + &((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr, + sizeof(struct in_addr)); + set_ipmask(n, v4mask); + } else { + memcpy(&n->addr.v.a.addr, + &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr.s6_addr, + sizeof(struct in6_addr)); + n->ifindex = + ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; + set_ipmask(n, v6mask); + } + n->next = NULL; + n->tail = n; + if (h == NULL) + h = n; + else { + h->tail->next = n; + h->tail = n; + } + } + freeaddrinfo(res0); + free(ps); + + if (h == NULL) { + fprintf(stderr, "no IP address found for %s\n", s); + return (NULL); + } + return (h); +} + diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h index 07fd09c1c24..09c1a3cfa7d 100644 --- a/sbin/pfctl/pfctl_parser.h +++ b/sbin/pfctl/pfctl_parser.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.h,v 1.39 2003/01/09 10:40:44 cedric Exp $ */ +/* $OpenBSD: pfctl_parser.h,v 1.40 2003/01/14 21:58:12 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -64,6 +64,32 @@ struct pfctl { struct pfioc_queue *pqueue; }; +enum pfctl_iflookup_mode { + PFCTL_IFLOOKUP_HOST, + PFCTL_IFLOOKUP_NET, + PFCTL_IFLOOKUP_BCAST +}; + +struct node_if { + char ifname[IFNAMSIZ]; + u_int8_t not; + u_int ifa_flags; + struct node_if *next; + struct node_if *tail; +}; + +struct node_host { + struct pf_addr_wrap addr; + struct pf_addr bcast; + sa_family_t af; + u_int8_t not; + u_int32_t ifindex; /* link-local IPv6 addrs */ + char *ifname; + u_int ifa_flags; + struct node_host *next; + struct node_host *tail; +}; + int pfctl_add_rule(struct pfctl *, struct pf_rule *); int pfctl_add_altq(struct pfctl *, struct pf_altq *); int pfctl_add_pool(struct pfctl *, struct pf_pool *, sa_family_t); @@ -124,4 +150,10 @@ struct pf_timeout { extern const struct pf_timeout pf_timeouts[]; extern int loadopt; +void set_ipmask(struct node_host *, u_int8_t); +void ifa_load(void); +struct node_host *ifa_exists(char *); +struct node_host *ifa_lookup(char *, enum pfctl_iflookup_mode); +struct node_host *host(char *, int); + #endif /* _PFCTL_PARSER_H_ */ diff --git a/sbin/pfctl/pfctl_table.c b/sbin/pfctl/pfctl_table.c index 25fda8e2a68..108b12564ee 100644 --- a/sbin/pfctl/pfctl_table.c +++ b/sbin/pfctl/pfctl_table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_table.c,v 1.20 2003/01/14 10:42:32 cedric Exp $ */ +/* $OpenBSD: pfctl_table.c,v 1.21 2003/01/14 21:58:12 henning Exp $ */ /* * Copyright (c) 2002 Cedric Berger @@ -57,7 +57,7 @@ #define BUF_SIZE 256 -extern void usage(void); +extern void usage(void); static int pfctl_table(int, char *[], char *, char *, char *, int); static void grow_buffer(int, int); static void print_table(struct pfr_table *, int); @@ -445,74 +445,57 @@ next_token(char buf[BUF_SIZE], FILE *fp) void append_addr(char *s, int test) { - char buf[BUF_SIZE], *p, *q, *r; - struct addrinfo *res, *ai, hints; - int not = 0, net = -1, rv; - struct in_addr ina; + char buf[BUF_SIZE], *r; + int not = 0; + struct node_host *n, *h; for (r = s; *r == '!'; r++) not = !not; if (strlcpy(buf, r, sizeof(buf)) >= sizeof(buf)) errx(1, "address too long"); - p = strrchr(buf, '/'); - if (test && (not || p)) - errx(1, "illegal test address"); - - memset(&ina, 0, sizeof(struct in_addr)); - if ((net = inet_net_pton(AF_INET, buf, &ina, sizeof(&ina))) > -1) { - if (test && net != 32) - errx(1, "illegal test address"); + + if ((n = host(buf, -1)) == NULL) + exit (1); + + do { if (size >= msize) grow_buffer(sizeof(struct pfr_addr), 0); - buffer.addrs[size].pfra_ip4addr.s_addr = ina.s_addr; buffer.addrs[size].pfra_not = not; - buffer.addrs[size].pfra_net = net; - buffer.addrs[size].pfra_af = AF_INET; - size++; - return; - } - - if (p) { - net = strtol(p+1, &q, 0); - if (!q || *q) - errx(1, "illegal network: \"%s\"", p+1); - *p++ = '\0'; - } - - bzero(&hints, sizeof(hints)); - hints.ai_socktype = SOCK_DGRAM; - rv = getaddrinfo(buf, NULL, &hints, &res); - if (rv) - errx(1, "illegal address: \"%s\"", buf); - for (ai = res; ai; ai = ai->ai_next) { - switch (ai->ai_family) { + switch (n->af) { case AF_INET: - if (net > 32) - errx(1, "illegal netmask: \"%d\"", net); - if (size >= msize) - grow_buffer(sizeof(struct pfr_addr), 0); - buffer.addrs[size].pfra_ip4addr = - ((struct sockaddr_in *)ai->ai_addr)->sin_addr; - buffer.addrs[size].pfra_not = not; - buffer.addrs[size].pfra_net = (net >= 0) ? net : 32; buffer.addrs[size].pfra_af = AF_INET; - size++; + buffer.addrs[size].pfra_ip4addr.s_addr = + n->addr.v.a.addr.addr32[0]; + buffer.addrs[size].pfra_net = + unmask(&n->addr.v.a.mask, AF_INET); + if (test && (not || buffer.addrs[size].pfra_net != 32)) + errx(1, "illegal test address"); + if (buffer.addrs[size].pfra_net > 32) + errx(1, "illegal netmask %d", + buffer.addrs[size].pfra_net); break; case AF_INET6: - if (net > 128) - errx(1, "illegal netmask: \"%d\"", net); - if (size >= msize) - grow_buffer(sizeof(struct pfr_addr), 0); - buffer.addrs[size].pfra_ip6addr = - ((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr; - buffer.addrs[size].pfra_not = not; - buffer.addrs[size].pfra_net = (net >= 0) ? net : 128; buffer.addrs[size].pfra_af = AF_INET6; - size++; + memcpy(&buffer.addrs[size].pfra_ip6addr, + &n->addr.v.a.addr.v6, sizeof(struct in6_addr)); + buffer.addrs[size].pfra_net = + unmask(&n->addr.v.a.mask, AF_INET6); + if (test && (not || buffer.addrs[size].pfra_net != 128)) + errx(1, "illegal test address"); + if (buffer.addrs[size].pfra_net > 128) + errx(1, "illegal netmask %d", + buffer.addrs[size].pfra_net); + break; + break; + default: + errx(1, "unknown address family %d", n->af); break; } - } - freeaddrinfo(res); + size++; + h = n; + n = n->next; + free(h); + } while (n != NULL); } void |