diff options
Diffstat (limited to 'usr.sbin/dvmrpd/rde.c')
-rw-r--r-- | usr.sbin/dvmrpd/rde.c | 117 |
1 files changed, 116 insertions, 1 deletions
diff --git a/usr.sbin/dvmrpd/rde.c b/usr.sbin/dvmrpd/rde.c index af3823f9753..b1e3e9071a7 100644 --- a/usr.sbin/dvmrpd/rde.c +++ b/usr.sbin/dvmrpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.5 2007/03/21 19:33:48 michele Exp $ */ +/* $OpenBSD: rde.c,v 1.6 2008/12/02 13:42:44 michele Exp $ */ /* * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org> @@ -39,12 +39,19 @@ #include "log.h" #include "rde.h" +void rde_nbr_init(u_int32_t); +void rde_nbr_free(void); +struct rde_nbr *rde_nbr_find(u_int32_t); +struct rde_nbr *rde_nbr_new(u_int32_t, struct rde_nbr *); +void rde_nbr_del(struct rde_nbr *); + void rde_sig_handler(int sig, short, void *); void rde_shutdown(void); void rde_dispatch_imsg(int, short, void *); volatile sig_atomic_t rde_quit = 0; struct dvmrpd_conf *rdeconf = NULL; +struct rde_nbr *nbrself; struct imsgbuf *ibuf_dvmrpe; struct imsgbuf *ibuf_main; @@ -104,6 +111,7 @@ rde(struct dvmrpd_conf *xconf, int pipe_parent2rde[2], int pipe_dvmrpe2rde[2], endpwent(); event_init(); + rde_nbr_init(NBR_HASHSIZE); /* setup signal handler */ signal_set(&ev_sigint, SIGINT, rde_sig_handler, NULL); @@ -189,6 +197,7 @@ rde_dispatch_imsg(int fd, short event, void *bula) struct imsgbuf *ibuf = bula; struct imsg imsg; struct route_report rr; + struct rde_nbr rn; int i, n, connected = 0; struct iface *iface; @@ -267,6 +276,19 @@ rde_dispatch_imsg(int fd, short event, void *bula) mfc_delete(&mfc); #endif break; + case IMSG_NEIGHBOR_UP: + if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(rn)) + fatalx("invalid size of OE request"); + memcpy(&rn, imsg.data, sizeof(rn)); + + if (rde_nbr_find(imsg.hdr.peerid)); + fatalx("rde_rispatch_imsg: " + "neighbor already exists"); + rde_nbr_new(imsg.hdr.peerid, &rn); + break; + case IMSG_NEIGHBOR_DOWN: + rde_nbr_del(rde_nbr_find(imsg.hdr.peerid)); + break; default: log_debug("rde_dispatch_msg: unexpected imsg %d", imsg.hdr.type); @@ -276,3 +298,96 @@ rde_dispatch_imsg(int fd, short event, void *bula) } imsg_event_add(ibuf); } + +LIST_HEAD(rde_nbr_head, rde_nbr); + +struct nbr_table { + struct rde_nbr_head *hashtbl; + u_int32_t hashmask; +} rdenbrtable; + +#define RDE_NBR_HASH(x) \ + &rdenbrtable.hashtbl[(x) & rdenbrtable.hashmask] + +void +rde_nbr_init(u_int32_t hashsize) +{ + struct rde_nbr_head *head; + u_int32_t hs, i; + + for (hs = 1; hs < hashsize; hs <<= 1) + ; + rdenbrtable.hashtbl = calloc(hs, sizeof(struct rde_nbr_head)); + if (rdenbrtable.hashtbl == NULL) + fatal("rde_nbr_init"); + + for (i = 0; i < hs; i++) + LIST_INIT(&rdenbrtable.hashtbl[i]); + + rdenbrtable.hashmask = hs - 1; + + if ((nbrself = calloc(1, sizeof(*nbrself))) == NULL) + fatal("rde_nbr_init"); + + nbrself->peerid = NBR_IDSELF; + head = RDE_NBR_HASH(NBR_IDSELF); + LIST_INSERT_HEAD(head, nbrself, hash); +} + +void +rde_nbr_free(void) +{ + free(nbrself); + free(rdenbrtable.hashtbl); +} + +struct rde_nbr * +rde_nbr_find(u_int32_t peerid) +{ + struct rde_nbr_head *head; + struct rde_nbr *nbr; + + head = RDE_NBR_HASH(peerid); + + LIST_FOREACH(nbr, head, hash) { + if (nbr->peerid == peerid) + return (nbr); + } + + return (NULL); +} + +struct rde_nbr * +rde_nbr_new(u_int32_t peerid, struct rde_nbr *new) +{ + struct rde_nbr_head *head; + struct rde_nbr *nbr; + + if (rde_nbr_find(peerid)) + return (NULL); + + if ((nbr = calloc(1, sizeof(*nbr))) == NULL) + fatal("rde_nbr_new"); + + memcpy(nbr, new, sizeof(*nbr)); + nbr->peerid = peerid; + + head = RDE_NBR_HASH(peerid); + LIST_INSERT_HEAD(head, nbr, hash); + + return (nbr); +} + +void +rde_nbr_del(struct rde_nbr *nbr) +{ + if (nbr == NULL) + return; + + srt_expire_nbr(nbr->addr, nbr->iface); + + LIST_REMOVE(nbr, entry); + LIST_REMOVE(nbr, hash); + + free(nbr); +} |