diff options
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 4 | ||||
-rw-r--r-- | usr.sbin/bgpd/buffer.c | 6 | ||||
-rw-r--r-- | usr.sbin/bgpd/mrt.c | 19 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.h | 21 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_rib.c | 208 |
5 files changed, 141 insertions, 117 deletions
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index 1f0f55cb02c..04ffa8aa3d5 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.6 2003/12/20 21:19:40 claudio Exp $ */ +/* $OpenBSD: bgpd.h,v 1.7 2003/12/21 16:11:33 claudio Exp $ */ /* * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> @@ -235,7 +235,7 @@ int session_main(struct bgpd_config *, int[2], int[2]); /* buffer.c */ struct buf *buf_open(struct peer *, int, ssize_t); int buf_add(struct buf *, void *, ssize_t); -u_char *buf_reserve(struct buf *, ssize_t); +void *buf_reserve(struct buf *, ssize_t); int buf_close(struct buf *); int buf_write(struct buf *); void buf_free(struct buf *buf); diff --git a/usr.sbin/bgpd/buffer.c b/usr.sbin/bgpd/buffer.c index 29c0d693c16..81b11dfec93 100644 --- a/usr.sbin/bgpd/buffer.c +++ b/usr.sbin/bgpd/buffer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: buffer.c,v 1.3 2003/12/20 21:14:55 henning Exp $ */ +/* $OpenBSD: buffer.c,v 1.4 2003/12/21 16:11:33 claudio Exp $ */ /* * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> @@ -62,10 +62,10 @@ buf_add(struct buf *buf, void *data, ssize_t len) return (0); } -u_char * +void * buf_reserve(struct buf *buf, ssize_t len) { - u_char *b; + void *b; if (buf->wpos + len > buf->size) return (NULL); diff --git a/usr.sbin/bgpd/mrt.c b/usr.sbin/bgpd/mrt.c index 284680a1b1e..5b46eb78f1d 100644 --- a/usr.sbin/bgpd/mrt.c +++ b/usr.sbin/bgpd/mrt.c @@ -1,7 +1,7 @@ -/* $OpenBSD: mrt.c,v 1.5 2003/12/20 21:43:45 claudio Exp $ */ +/* $OpenBSD: mrt.c,v 1.6 2003/12/21 16:11:33 claudio Exp $ */ /* - * Copyright (c) 2003 Claudio Jeker <cjeker@diehard.n-r-g.com> + * Copyright (c) 2003 Claudio Jeker <claudio@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -43,9 +43,12 @@ static int mrt_dump_entry(int, struct prefix *, u_int16_t, static void mrt_dump_header(struct buf *, u_int16_t, u_int16_t, u_int32_t); static int mrt_open(struct mrtdump_config *); -/* XXX breaks buf encapsulation */ #define DUMP_BYTE(x, b) \ - (x)->buf[buf->wpos++] = (b) + do { \ + u_char t = (b); \ + if (buf_add((x), &t, sizeof(t)) == -1) \ + fatal("buf_add error", 0); \ + } while (0) #define DUMP_SHORT(x, s) \ do { \ @@ -79,7 +82,7 @@ mrt_dump_bgp_msg(int fd, u_char *pkg, u_int16_t pkglen, int type, int i, n; u_int16_t len; - len = pkglen + MRT_BGP4MP_HEADER_SIZE + type>0?MSGSIZE_HEADER:0; + len = pkglen + MRT_BGP4MP_HEADER_SIZE + type > 0 ? MSGSIZE_HEADER : 0; hdr.len = len + IMSG_HEADER_SIZE + MRT_HEADER_SIZE; hdr.type = IMSG_MRT_MSG; @@ -121,7 +124,7 @@ mrt_dump_entry(int fd, struct prefix *p, u_int16_t snum, struct peer_config *peer, u_int32_t id) { struct buf *buf; - u_char *s; + void *bptr; struct imsg_hdr hdr; u_int16_t len, attr_len; int n; @@ -150,10 +153,10 @@ mrt_dump_entry(int fd, struct prefix *p, u_int16_t snum, DUMP_SHORT(buf, peer->remote_as); DUMP_SHORT(buf, attr_len); - if ((s = buf_reserve(buf, attr_len)) == NULL) + if ((bptr = buf_reserve(buf, attr_len)) == NULL) fatal("buf_reserve error", 0); - if (attr_dump(s, attr_len, &p->aspath->flags) == -1) + if (attr_dump(bptr, attr_len, &p->aspath->flags) == -1) fatal("attr_dump error", 0); if ((n = buf_close(buf)) == -1) diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h index 769f18da464..4f1766a2544 100644 --- a/usr.sbin/bgpd/rde.h +++ b/usr.sbin/bgpd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.3 2003/12/19 01:15:47 deraadt Exp $ */ +/* $OpenBSD: rde.h,v 1.4 2003/12/21 16:11:34 claudio Exp $ */ /* * Copyright (c) 2003 Claudio Jeker <cjeker@diehard.n-r-g.com> and @@ -52,21 +52,14 @@ LIST_HEAD(aspath_head, rde_aspath); struct rde_peer { LIST_ENTRY(rde_peer) hash_l; /* hash list over all peers */ LIST_ENTRY(rde_peer) peer_l; /* list of all peers */ - struct aspath_head path_h; /* list of all as pathes */ + struct aspath_head path_h; /* list of all as pathes */ struct peer_config conf; u_int32_t remote_bgpid; enum peer_state state; }; -struct as_segment { - u_int8_t type; /* type of as path segment */ #define AS_SET 1 #define AS_SEQUENCE 2 - u_int8_t len; /* size in u_int16_t of object*/ - u_int16_t as_num[1]; /* in network byte order */ - /* this beast is variable sized */ -}; - #define ASPATH_HEADER_SIZE sizeof(struct aspath_hdr) struct aspath_hdr { @@ -97,6 +90,10 @@ struct astags { u_int16_t value; } astag[1]; /* this beast is variable sized */ + /* + * XXX does not work. Because of possible unalignd access to + * u_int16_t. This needs to be solved somewhat differently. + */ }; enum attrtypes { @@ -198,13 +195,13 @@ struct prefix { int attr_equal(struct attr_flags *, struct attr_flags *); void attr_copy(struct attr_flags *, struct attr_flags *); u_int16_t attr_length(struct attr_flags *); -int attr_dump(u_char *, u_int16_t, struct attr_flags *); +int attr_dump(void *, u_int16_t, struct attr_flags *); -int aspath_verify(u_char *, u_int16_t, u_int16_t); +int aspath_verify(void *, u_int16_t, u_int16_t); #define AS_ERR_LEN -1 #define AS_ERR_TYPE -2 #define AS_ERR_LOOP -3 -struct aspath *aspath_create(u_char *, u_int16_t); +struct aspath *aspath_create(void *, u_int16_t); void aspath_destroy(struct aspath *); u_char *aspath_dump(struct aspath *); u_int16_t aspath_length(struct aspath *); diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c index 1185940b744..e7fbbf005c3 100644 --- a/usr.sbin/bgpd/rde_rib.c +++ b/usr.sbin/bgpd/rde_rib.c @@ -1,7 +1,7 @@ -/* $OpenBSD: rde_rib.c,v 1.3 2003/12/19 19:24:08 deraadt Exp $ */ +/* $OpenBSD: rde_rib.c,v 1.4 2003/12/21 16:11:34 claudio Exp $ */ /* - * Copyright (c) 2003 Claudio Jeker <cjeker@diehard.n-r-g.com> + * Copyright (c) 2003 Claudio Jeker <claudio@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -125,80 +125,81 @@ attr_length(struct attr_flags *attr) } int -attr_dump(u_char *p, u_int16_t len, struct attr_flags *a) +attr_dump(void *p, u_int16_t len, struct attr_flags *a) { -#define ATTR_WRITE(b, a, alen) \ - do { \ - if ((wlen += (alen)) > len) \ - return (-1); \ - memcpy((b), (a), (alen)); \ - (b) += (alen); \ + u_char *buf = p; + u_int32_t tmp32; + u_int16_t tmp16; + u_int16_t aslen, wlen = 0; + +#define ATTR_WRITE(b, a, alen) \ + do { \ + if ((wlen + (alen)) > len) \ + return (-1); \ + memcpy((b) + wlen, (a), (alen)); \ + wlen += (alen); \ } while (0) -#define ATTR_WRITEB(b, c) \ - do { \ - if (wlen++ == len) \ - return (-1); \ - *(b)++ = (u_char)(c); \ +#define ATTR_WRITEB(b, c) \ + do { \ + if (wlen == len || (c) > 0xff) \ + return (-1); \ + (b)[wlen++] = (c); \ } while (0) - u_int32_t tmp32; - u_int16_t tmp16; - u_int16_t aslen, wlen = 0; - /* origin */ - ATTR_WRITEB(p, ATTR_ORIGIN_FLAGS); - ATTR_WRITEB(p, ATTR_ORIGIN); - ATTR_WRITEB(p, 1); - ATTR_WRITEB(p, a->origin); + ATTR_WRITEB(buf, ATTR_ORIGIN_FLAGS); + ATTR_WRITEB(buf, ATTR_ORIGIN); + ATTR_WRITEB(buf, 1); + ATTR_WRITEB(buf, a->origin); /* aspath */ aslen = aspath_length(a->aspath); - ATTR_WRITEB(p, ATTR_TRANSITIVE | (aslen>255 ? ATTR_EXTLEN : 0)); - ATTR_WRITEB(p, ATTR_ASPATH); + ATTR_WRITEB(buf, ATTR_TRANSITIVE | (aslen>255 ? ATTR_EXTLEN : 0)); + ATTR_WRITEB(buf, ATTR_ASPATH); if (aslen > 255) { tmp16 = htonl(aslen); - ATTR_WRITE(p, &tmp16, 4); + ATTR_WRITE(buf, &tmp16, 4); } else - ATTR_WRITEB(p, aslen); - ATTR_WRITE(p, aspath_dump(a->aspath), aslen); + ATTR_WRITEB(buf, aslen); + ATTR_WRITE(buf, aspath_dump(a->aspath), aslen); /* nexthop */ - ATTR_WRITEB(p, ATTR_NEXTHOP_FLAGS); - ATTR_WRITEB(p, ATTR_NEXTHOP); - ATTR_WRITEB(p, 4); - ATTR_WRITE(p, &a->nexthop, 4); /* network byte order */ + ATTR_WRITEB(buf, ATTR_NEXTHOP_FLAGS); + ATTR_WRITEB(buf, ATTR_NEXTHOP); + ATTR_WRITEB(buf, 4); + ATTR_WRITE(buf, &a->nexthop, 4); /* network byte order */ /* MED */ if (a->med != 0) { - ATTR_WRITEB(p, ATTR_MED_FLAGS); - ATTR_WRITEB(p, ATTR_MED); - ATTR_WRITEB(p, 4); + ATTR_WRITEB(buf, ATTR_MED_FLAGS); + ATTR_WRITEB(buf, ATTR_MED); + ATTR_WRITEB(buf, 4); tmp32 = htonl(a->med); - ATTR_WRITE(p, &tmp32, 4); + ATTR_WRITE(buf, &tmp32, 4); } /* local preference */ - ATTR_WRITEB(p, ATTR_LOCALPREF_FLAGS); - ATTR_WRITEB(p, ATTR_LOCALPREF); - ATTR_WRITEB(p, 4); + ATTR_WRITEB(buf, ATTR_LOCALPREF_FLAGS); + ATTR_WRITEB(buf, ATTR_LOCALPREF); + ATTR_WRITEB(buf, 4); tmp32 = htonl(a->lpref); - ATTR_WRITE(p, &tmp32, 4); + ATTR_WRITE(buf, &tmp32, 4); /* atomic aggregate */ if (a->aggr_atm == 1) { - ATTR_WRITEB(p, ATTR_ATOMIC_AGGREGATE_FLAGS); - ATTR_WRITEB(p, ATTR_ATOMIC_AGGREGATE); - ATTR_WRITEB(p, 0); + ATTR_WRITEB(buf, ATTR_ATOMIC_AGGREGATE_FLAGS); + ATTR_WRITEB(buf, ATTR_ATOMIC_AGGREGATE); + ATTR_WRITEB(buf, 0); } /* aggregator */ if (a->aggr_as != 0) { - ATTR_WRITEB(p, ATTR_AGGREGATOR_FLAGS); - ATTR_WRITEB(p, ATTR_AGGREGATOR); - ATTR_WRITEB(p, 6); + ATTR_WRITEB(buf, ATTR_AGGREGATOR_FLAGS); + ATTR_WRITEB(buf, ATTR_AGGREGATOR); + ATTR_WRITEB(buf, 6); tmp16 = htons(a->aggr_as); - ATTR_WRITE(p, &tmp16, 2); - ATTR_WRITE(p, &a->aggr_ip, 4); /* network byte order */ + ATTR_WRITE(buf, &tmp16, 2); + ATTR_WRITE(buf, &a->aggr_ip, 4); /* network byte order */ } return wlen; @@ -213,43 +214,62 @@ attr_dump(u_char *p, u_int16_t len, struct attr_flags *a) * aspath regexp search, * aspath to string converter */ +static u_int16_t aspath_extract(void *, int); -int -aspath_verify(u_char *data, u_int16_t len, u_int16_t myAS) +/* + * Extract the asnum out of the as segement at the specified position. + * Direct access is not possible because of non-aligned reads. + */ +static u_int16_t +aspath_extract(void *seg, int pos) { - struct as_segment *seg; - u_int16_t pos; - u_int8_t i; + u_char *ptr = seg; + u_int16_t as = 0; + + ENSURE(0 <= pos && pos < 0xff); - for (pos = 0; pos + 1 < len; ) { - seg = (struct as_segment *)(data + pos); - if (seg->type != AS_SET && seg->type != AS_SEQUENCE) { + ptr += 2 + 2 * pos; + as = *ptr++; + as <<= 8; + as |= *ptr; + return as; +} + +int +aspath_verify(void *data, u_int16_t len, u_int16_t myAS) +{ + u_int8_t *seg = data; + u_int16_t seg_size; + u_int8_t i, seg_len, seg_type; + + for (; len > 0; len -= seg_size, seg += seg_size) { + seg_type = seg[0]; + seg_len = seg[1]; + if (seg_type != AS_SET && seg_type != AS_SEQUENCE) { return AS_ERR_TYPE; } + seg_size = 2 + 2 * seg_len; - if ((pos += 2 + 2 * seg->len) > len) + if (seg_size > len) return AS_ERR_LEN; - for (i = 0; i < seg->len; i++) { - if (myAS == seg->as_num[i]) + for (i = 0; i < seg_len; i++) { + if (myAS == aspath_extract(seg, i)) return AS_ERR_LOOP; } } - if (pos == len) - return 0; /* all OK */ - - return AS_ERR_LEN; + return 0; /* all OK */ } struct aspath * -aspath_create(u_char *data, u_int16_t len) +aspath_create(void *data, u_int16_t len) { struct aspath *aspath; RIB_STAT(aspath_create); - /* XXX we assume that the aspath was already checked for correctness */ - aspath = (struct aspath *)malloc(ASPATH_HEADER_SIZE + len); + /* The aspath must already have been checked for correctness. */ + aspath = malloc(ASPATH_HEADER_SIZE + len); if (aspath == NULL) fatal("aspath_create", errno); aspath->hdr.len = len; @@ -271,7 +291,7 @@ aspath_destroy(struct aspath *aspath) u_char * aspath_dump(struct aspath *aspath) { - return (u_char *)aspath->data; + return aspath->data; } u_int16_t @@ -283,19 +303,22 @@ aspath_length(struct aspath *aspath) u_int16_t aspath_count(struct aspath *aspath) { - struct as_segment *seg; - u_int16_t cnt, len, pos; + u_int8_t *seg; + u_int16_t cnt, len, seg_size; + u_int8_t seg_type, seg_len; - len = aspath->hdr.len; cnt = 0; - for (pos = 0; pos + 1 < len; ) { - seg = (struct as_segment *)(aspath->data + pos); - ENSURE(seg->type == AS_SET || seg->type == AS_SEQUENCE); - if (seg->type == AS_SET) + seg = aspath->data; + for (len = aspath->hdr.len; len > 0; len -= seg_size, seg += seg_size) { + seg_type = seg[0]; + seg_len = seg[1]; + ENSURE(seg_type == AS_SET || seg_type == AS_SEQUENCE); + seg_size = 2 + 2 * seg_len; + + if (seg_type == AS_SET) cnt += 1; else - cnt += seg->len; - pos += 2 + 2 * seg->len; + cnt += seg_len; } return cnt; } @@ -303,19 +326,17 @@ aspath_count(struct aspath *aspath) u_int16_t aspath_neighbour(struct aspath *aspath) { - struct as_segment *seg; /* * Empty aspath is OK -- internal as route. * But what is the neighbour? For now let's return 0 that * should not break anything. */ - ENSURE(aspath->hdr.len >= 2); - - seg = (struct as_segment *)aspath->data; - if (seg->len > 0) - return seg->as_num[0]; + if (aspath->hdr.len < 2) + fatal("aspath_neighbour: aspath has no data", 0); + if (aspath->data[1] > 0) + return aspath_extract(aspath->data, 0); return 0; } @@ -324,21 +345,24 @@ aspath_neighbour(struct aspath *aspath) u_long aspath_hash(struct aspath *aspath) { - struct as_segment *seg; - u_long hash; - u_int16_t len, pos; - u_int8_t i; + u_int8_t *seg; + u_long hash; + u_int16_t len, seg_size; + u_int8_t i, seg_len, seg_type; hash = AS_HASH_INITAL; - len = aspath->hdr.len; - for (pos = 0; pos < len; ) { - seg = (struct as_segment *)(aspath->data + pos); - ENSURE(pos + 2 + 2 * seg->len <= len); - for (i = 0; i < seg->len; i++) { + seg = aspath->data; + for (len = aspath->hdr.len; len > 0; len -= seg_size, seg += seg_size) { + seg_type = seg[0]; + seg_len = seg[1]; + ENSURE(seg_type == AS_SET || seg_type == AS_SEQUENCE); + seg_size = 2 + 2 * seg_len; + + ENSURE(seg_size <= len); + for (i = 0; i < seg_len; i++) { hash += (hash << 5); - hash ^= seg->as_num[i]; + hash ^= aspath_extract(seg, i); } - pos += 2 + 2 * seg->len; } return hash; } |