summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2004-03-02 19:45:05 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2004-03-02 19:45:05 +0000
commit97d3bc17a77f84f39949facde64b9ce764d17fa6 (patch)
treec4ecba8cd70e15fb00fffd58360f84f1e25a6747 /usr.sbin
parent5b258471b908015322203a6e9bbf7a85659e9044 (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.h5
-rw-r--r--usr.sbin/bgpd/config.c89
-rw-r--r--usr.sbin/bgpd/parse.y112
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($$));