diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2004-03-02 19:45:05 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2004-03-02 19:45:05 +0000 |
commit | 97d3bc17a77f84f39949facde64b9ce764d17fa6 (patch) | |
tree | c4ecba8cd70e15fb00fffd58360f84f1e25a6747 /usr.sbin | |
parent | 5b258471b908015322203a6e9bbf7a85659e9044 (diff) |
flesh out the address and prefix parsing, include v6 code, but reject v6
upwards, claudio ok
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 5 | ||||
-rw-r--r-- | usr.sbin/bgpd/config.c | 89 | ||||
-rw-r--r-- | usr.sbin/bgpd/parse.y | 112 |
3 files changed, 164 insertions, 42 deletions
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index 4220ae093ff..7f94cb412c3 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.103 2004/03/02 19:29:01 claudio Exp $ */ +/* $OpenBSD: bgpd.h,v 1.104 2004/03/02 19:45:04 henning Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -454,7 +454,8 @@ const char *log_addr(const struct bgpd_addr *); int cmdline_symset(char *); /* config.c */ -int check_file_secrecy(int fd, const char *fname); +int check_file_secrecy(int, const char *); +int host(const char *, struct bgpd_addr *, u_int8_t *); /* imsg.c */ void imsg_init(struct imsgbuf *, int); diff --git a/usr.sbin/bgpd/config.c b/usr.sbin/bgpd/config.c index 45120a2cbd5..23497417e5f 100644 --- a/usr.sbin/bgpd/config.c +++ b/usr.sbin/bgpd/config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.29 2004/02/26 14:00:33 claudio Exp $ */ +/* $OpenBSD: config.c,v 1.30 2004/03/02 19:45:04 henning Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -23,6 +23,7 @@ #include <errno.h> #include <ifaddrs.h> +#include <netdb.h> #include <stdlib.h> #include <string.h> #include <unistd.h> @@ -33,6 +34,8 @@ void *sconf; u_int32_t get_bgpid(void); +int host_v4(const char *, struct bgpd_addr *, u_int8_t *); +int host_v6(const char *, struct bgpd_addr *); int merge_config(struct bgpd_config *xconf, struct bgpd_config *conf, @@ -116,3 +119,87 @@ check_file_secrecy(int fd, const char *fname) return (0); } + +int +host(const char *s, struct bgpd_addr *h, u_int8_t *len) +{ + int done = 0; + int mask; + char *p, *q, *ps; + + if ((p = strrchr(s, '/')) != NULL) { + mask = strtol(p+1, &q, 0); + if (!q || *q || mask > 128 || q == (p+1)) { + log_warnx("invalid netmask"); + return (0); + } + if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL) + fatal("host: malloc"); + strlcpy(ps, s, strlen(s) - strlen(p) + 1); + } else { + if ((ps = strdup(s)) == NULL) + fatal("host: strdup"); + mask = 128; + } + + bzero(h, sizeof(struct bgpd_addr)); + + /* IPv4 address? */ + if (!done) + done = host_v4(s, h, len); + + /* IPv6 address? */ + if (!done) { + done = host_v6(ps, h); + *len = mask; + } + + free(ps); + + return (done); +} + +int +host_v4(const char *s, struct bgpd_addr *h, u_int8_t *len) +{ + struct in_addr ina; + int bits = 32; + + memset(&ina, 0, sizeof(struct in_addr)); + if (strrchr(s, '/') != NULL) { + if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1) + return (0); + } else { + if (inet_pton(AF_INET, s, &ina) != 1) + return (0); + } + + h->af = AF_INET; + h->v4.s_addr = ina.s_addr; + *len = bits; + + return (1); +} + +int +host_v6(const char *s, struct bgpd_addr *h) +{ + struct addrinfo hints, *res; + + 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) { + h->af = AF_INET6; + memcpy(&h->v6, + &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, + sizeof(h->v6)); + h->scope_id = + ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; + + return (1); + } + + return (0); +} diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index e532266a7b3..2f99598fcf4 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.67 2004/03/01 22:58:12 henning Exp $ */ +/* $OpenBSD: parse.y,v 1.68 2004/03/02 19:45:04 henning Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -91,6 +91,10 @@ typedef struct { struct filter_peers filter_peers; struct filter_match filter_match; struct filter_set filter_set; + struct { + struct bgpd_addr prefix; + u_int8_t len; + } prefix; } v; int lineno; } YYSTYPE; @@ -114,6 +118,7 @@ typedef struct { %type <v.number> number asnumber optnumber yesno inout %type <v.string> string %type <v.addr> address +%type <v.prefix> prefix %type <v.u8> action quick direction %type <v.filter_peers> filter_peer %type <v.filter_match> filter_match prefixlenop @@ -227,18 +232,19 @@ conf_main : AS asnumber { else YYERROR; } - | NETWORK address '/' number filter_set { + | NETWORK prefix filter_set { struct network *n; - if ((n = calloc(1, sizeof(struct network))) == NULL) - fatal("new_network"); - memcpy(&n->net.prefix, &$2, sizeof(n->net.prefix)); - if ($4 > 32) { - yyerror("invalid netmask"); + if ($2.prefix.af != AF_INET) { + yyerror("king bula sez: AF_INET only for now"); YYERROR; } - n->net.prefixlen = $4; - memcpy(&n->net.attrset, &$5, + if ((n = calloc(1, sizeof(struct network))) == NULL) + fatal("new_network"); + memcpy(&n->net.prefix, &$2.prefix, + sizeof(n->net.prefix)); + n->net.prefixlen = $2.len; + memcpy(&n->net.attrset, &$3, sizeof(n->net.attrset)); TAILQ_INSERT_TAIL(netconf, n, network_l); @@ -271,19 +277,38 @@ inout : IN { $$ = 1; } ; address : STRING { - int n; + u_int8_t len; - bzero(&$$, sizeof($$)); - $$.af = AF_INET; - if ((n = inet_pton(AF_INET, $1, &$$.v4)) == -1) { - yyerror("inet_pton: %s", strerror(errno)); - YYERROR; - } - if (n == 0) { + if (!host($1, &$$, &len)) { yyerror("could not parse address spec \"%s\"", $1); YYERROR; } + + if (($$.af == AF_INET && len != 32) || + ($$.af == AF_INET6 && len != 128)) { + /* unreachable */ + yyerror("got prefixlen %u, expected %u", + len, $$.af == AF_INET ? 32 : 128); + YYERROR; + } + } + ; + +prefix : STRING '/' number { + char *s; + + if (asprintf(&s, "%s/%u", $1, $3) == -1) + fatal(NULL); + + if (!host(s, &$$.prefix, &$$.len)) { + free(s); + yyerror("could not parse address \"%s/%s\"", + $1, $3); + YYERROR; + } + + free(s); } ; @@ -300,7 +325,10 @@ optnumber : /* empty */ { $$ = 0; } neighbor : { curpeer = new_peer(); } NEIGHBOR address optnl '{' optnl { - curpeer->conf.remote_addr.af = AF_INET; + if ($3.af != AF_INET) { + yyerror("king bula sez: IPv4 transport only"); + YYERROR; + } memcpy(&curpeer->conf.remote_addr, &$3, sizeof(curpeer->conf.remote_addr)); if (get_id(curpeer)) { @@ -467,6 +495,11 @@ filterrule : action quick direction filter_peer filter_match filter_set { struct filter_rule r; + if ($5.prefix.addr.af && $5.prefix.addr.af != AF_INET) { + yyerror("king bula sez: AF_INET only for now"); + YYERROR; + } + bzero(&r, sizeof(r)); r.action = $1; r.quick = $2; @@ -523,30 +556,31 @@ filter_peer : ANY { $$.peerid = $$.groupid = 0; } ; filter_match : /* empty */ { bzero(&$$, sizeof($$)); } - | PREFIX address '/' number { + | PREFIX prefix { bzero(&$$, sizeof($$)); - memcpy(&$$.prefix.addr, &$2, sizeof($$.prefix.addr)); - if ($4 > 32) { - yyerror("prefixlength must be <= 32"); - YYERROR; - } - $$.prefix.len = $4; + memcpy(&$$.prefix.addr, &$2.prefix, + sizeof($$.prefix.addr)); + $$.prefix.len = $2.len; } - | PREFIX address '/' number PREFIXLEN prefixlenop { + | PREFIX prefix PREFIXLEN prefixlenop { bzero(&$$, sizeof($$)); - memcpy(&$$.prefix.addr, &$2, sizeof($$.prefix.addr)); - if ($4 > 32) { - yyerror("prefixlength must be <= 32"); - YYERROR; - } - $$.prefix.len = $4; - $$.prefixlen = $6.prefixlen; - $$.prefixlen.af = AF_INET; - if ($$.prefixlen.len_max > 32 || - $$.prefixlen.len_min > 32) { - yyerror("prefixlength must be <= 32"); - YYERROR; - } + memcpy(&$$.prefix.addr, &$2.prefix, + sizeof($$.prefix.addr)); + $$.prefix.len = $2.len; + $$.prefixlen = $4.prefixlen; + $$.prefixlen.af = $2.prefix.af; + if ($$.prefixlen.af == AF_INET) + if ($$.prefixlen.len_max > 32 || + $$.prefixlen.len_min > 32) { + yyerror("prefixlen must be <= 32"); + YYERROR; + } + if ($$.prefixlen.af == AF_INET6) + if ($$.prefixlen.len_max > 128 || + $$.prefixlen.len_min > 128) { + yyerror("prefixlen must be <= 128"); + YYERROR; + } } | PREFIXLEN prefixlenop { bzero(&$$, sizeof($$)); |