[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
BGPD and its listening sockets
currently, bgpd has two listening sockets, one for IPv4 and one for
IPv6. There is no way to have it listen on only one address family, or
on more than one address for address family.
if you have
listen on 127.0.0.1
in your config file, it will listen in 127.0.0.1:179 and [::1]:179
if you have
listen 10.0.0.1
listen 10.0.0.2
listen 10.0.0.3
it will listen on 10.0.0.3 and ::1
now, of course this is a bit fucked and needs fixing; and I finally got
around to do it.
use a TAILQ for the listeners, pt the sockaddr and fd and such in a
little struct. works beautifully for my limited testing.
now, by default, we listen on wildcard sockets for both v4 and v6 -
like before. if you specify
listen on 127.0.0.1
in your config, we will listen on 127.0.0.1, and that's it. No v6. If
you have 4 listen statemenst we'll have 4 listening sockets... and so
on.
reconfig is a major issue. we cannot bind to port 179 after we dropped
privs. I have not fixed that yet; the solution is obviosuly to do the
bind() in the parent process and pass the fd to the SE, which then does
the listen() and continues like always. I hope to do that soonish.
But even without that this diff fixes a lot of issues around the
listeners and is an improvement over what we have now. pls test &
comment...
Index: bgpd.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.c,v
retrieving revision 1.94
diff -u -r1.94 bgpd.c
--- bgpd.c 21 May 2004 11:48:56 -0000 1.94
+++ bgpd.c 4 Jun 2004 18:08:03 -0000
@@ -100,6 +100,7 @@
struct network *net;
struct filter_rule *r;
struct mrt *(mrt[POLL_MAX]), *m;
+ struct listen_addr *la;
struct pollfd pfd[POLL_MAX];
pid_t io_pid = 0, rde_pid = 0, pid;
char *conffile;
@@ -228,6 +229,11 @@
free(r);
}
+ while ((la = TAILQ_FIRST(conf.listen_addrs)) != NULL) {
+ TAILQ_REMOVE(conf.listen_addrs, la, entry);
+ free(la);
+ }
+
while (quit == 0) {
pfd[PFD_PIPE_SESSION].fd = ibuf_se.fd;
pfd[PFD_PIPE_SESSION].events = POLLIN;
@@ -368,6 +374,7 @@
struct network *n;
struct peer *p;
struct filter_rule *r;
+ struct listen_addr *la;
if (parse_config(conffile, conf, mrt_l, peer_l, &net_l, rules_l)) {
log_warnx("config file %s has errors, not reloading",
@@ -399,6 +406,16 @@
TAILQ_REMOVE(rules_l, r, entries);
free(r);
}
+ while ((la = TAILQ_FIRST(conf->listen_addrs)) != NULL) {
+ if (imsg_compose(&ibuf_se, IMSG_RECONF_LISTENER, 0,
+ la, sizeof(struct listen_addr)) == -1)
+ return (-1);
+ TAILQ_REMOVE(conf->listen_addrs, la, entry);
+ free(la);
+ }
+ free(conf->listen_addrs);
+ conf->listen_addrs = NULL;
+
if (imsg_compose(&ibuf_se, IMSG_RECONF_DONE, 0, NULL, 0) == -1 ||
imsg_compose(&ibuf_rde, IMSG_RECONF_DONE, 0, NULL, 0) == -1)
return (-1);
Index: bgpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v
retrieving revision 1.125
diff -u -r1.125 bgpd.h
--- bgpd.h 21 May 2004 15:36:40 -0000 1.125
+++ bgpd.h 4 Jun 2004 18:08:04 -0000
@@ -108,17 +108,28 @@
#define addr32 ba.addr32
};
+#define DEFAULT_LISTENER 0x01
+
+struct listen_addr {
+ TAILQ_ENTRY(listen_addr) entry;
+ struct sockaddr_storage sa;
+ int fd;
+ enum reconf_action reconf;
+ u_int8_t flags;
+};
+
+TAILQ_HEAD(listen_addrs, listen_addr);
+
struct bgpd_config {
- int opts;
- u_int16_t as;
- u_int32_t bgpid;
- u_int32_t clusterid;
- u_int16_t holdtime;
- u_int16_t min_holdtime;
- int flags;
- int log;
- struct sockaddr_in listen_addr;
- struct sockaddr_in6 listen6_addr;
+ int opts;
+ u_int16_t as;
+ u_int32_t bgpid;
+ u_int32_t clusterid;
+ u_int16_t holdtime;
+ u_int16_t min_holdtime;
+ int flags;
+ int log;
+ struct listen_addrs *listen_addrs;
};
struct buf_read {
@@ -239,6 +250,7 @@
IMSG_RECONF_CONF,
IMSG_RECONF_PEER,
IMSG_RECONF_FILTER,
+ IMSG_RECONF_LISTENER,
IMSG_RECONF_DONE,
IMSG_UPDATE,
IMSG_UPDATE_ERR,
Index: config.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/config.c,v
retrieving revision 1.37
diff -u -r1.37 config.c
--- config.c 21 May 2004 15:36:40 -0000 1.37
+++ config.c 4 Jun 2004 18:08:04 -0000
@@ -37,10 +37,11 @@
int
merge_config(struct bgpd_config *xconf, struct bgpd_config *conf,
- struct peer *peer_l)
+ struct peer *peer_l, struct listen_addrs *listen_addrs)
{
- struct peer *p;
- int errs = 0;
+ struct peer *p;
+ struct listen_addr *la;
+ int errs = 0;
/* preserve cmd line opts */
conf->opts = xconf->opts;
@@ -75,7 +76,17 @@
}
}
+ if (xconf->listen_addrs != NULL) {
+ while ((la = TAILQ_FIRST(xconf->listen_addrs)) != NULL) {
+ TAILQ_REMOVE(xconf->listen_addrs, la, entry);
+ free(la);
+ }
+ free(xconf->listen_addrs);
+ }
+
memcpy(xconf, conf, sizeof(struct bgpd_config));
+
+ xconf->listen_addrs = listen_addrs;
return (errs);
}
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v
retrieving revision 1.112
diff -u -r1.112 parse.y
--- parse.y 21 May 2004 15:36:40 -0000 1.112
+++ parse.y 4 Jun 2004 18:08:04 -0000
@@ -45,6 +45,7 @@
static struct peer *curpeer;
static struct peer *curgroup;
static struct filter_head *filter_l;
+static struct listen_addrs *listen_addrs;
static FILE *fin = NULL;
static int lineno = 1;
static int errors = 0;
@@ -226,20 +227,37 @@
conf->min_holdtime = $3;
}
| LISTEN ON address {
+ struct listen_addr *la;
+ struct sockaddr_in *in;
+ struct sockaddr_in6 *in6;
+
+ if ((la = calloc(1, sizeof(struct listen_addr))) ==
+ NULL)
+ fatal("parse conf_main listen on calloc");
+
+ la->fd = -1;
+ la->sa.ss_family = $3.af;
switch ($3.af) {
case AF_INET:
- conf->listen_addr.sin_addr.s_addr =
- $3.v4.s_addr;
+ la->sa.ss_len = sizeof(struct sockaddr_in);
+ in = (struct sockaddr_in *)&la->sa;
+ in->sin_addr.s_addr = $3.v4.s_addr;
+ in->sin_port = htons(BGP_PORT);
break;
case AF_INET6:
- memcpy(&conf->listen6_addr.sin6_addr, &$3.v6,
- sizeof(conf->listen6_addr.sin6_addr));
+ la->sa.ss_len = sizeof(struct sockaddr_in6);
+ in6 = (struct sockaddr_in6 *)&la->sa;
+ memcpy(&in6->sin6_addr, &$3.v6,
+ sizeof(in6->sin6_addr));
+ in6->sin6_port = htons(BGP_PORT);
break;
default:
yyerror("king bula does not like family %u",
$3.af);
YYERROR;
}
+
+ TAILQ_INSERT_TAIL(listen_addrs, la, entry);
}
| FIBUPDATE yesno {
if ($2 == 0)
@@ -1279,9 +1297,12 @@
fatal(NULL);
if ((mrtconf = calloc(1, sizeof(struct mrt_head))) == NULL)
fatal(NULL);
+ if ((listen_addrs = calloc(1, sizeof(struct listen_addrs))) == NULL)
+ fatal(NULL);
LIST_INIT(mrtconf);
netconf = nc;
TAILQ_INIT(netconf);
+ TAILQ_INIT(listen_addrs);
peer_l = NULL;
peer_l_old = *xpeers;
@@ -1293,16 +1314,6 @@
filter_l = xfilter_l;
TAILQ_INIT(filter_l);
- conf->listen_addr.sin_len = sizeof(conf->listen_addr);
- conf->listen_addr.sin_family = AF_INET;
- conf->listen_addr.sin_addr.s_addr = INADDR_ANY;
- conf->listen_addr.sin_port = htons(BGP_PORT);
-
- bzero(&conf->listen6_addr, sizeof(conf->listen6_addr));
- conf->listen6_addr.sin6_len = sizeof(conf->listen6_addr);
- conf->listen6_addr.sin6_family = AF_INET6;
- conf->listen6_addr.sin6_port = htons(BGP_PORT);
-
if ((fin = fopen(filename, "r")) == NULL) {
warn("%s", filename);
free(conf);
@@ -1336,7 +1347,7 @@
}
}
- errors += merge_config(xconf, conf, peer_l);
+ errors += merge_config(xconf, conf, peer_l, listen_addrs);
errors += mrt_mergeconfig(xmconf, mrtconf);
*xpeers = peer_l;
Index: printconf.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/printconf.c,v
retrieving revision 1.20
diff -u -r1.20 printconf.c
--- printconf.c 8 May 2004 19:17:20 -0000 1.20
+++ printconf.c 4 Jun 2004 18:08:04 -0000
@@ -88,8 +88,8 @@
void
print_mainconf(struct bgpd_config *conf)
{
- struct in_addr ina;
- struct in6_addr ina6;
+ struct in_addr ina;
+ struct listen_addr *la;
printf("AS %u\n", conf->as);
ina.s_addr = conf->bgpid;
@@ -110,13 +110,9 @@
if (conf->log & BGPD_LOG_UPDATES)
printf("log updates\n");
- if (conf->listen_addr.sin_addr.s_addr != INADDR_ANY)
- printf("listen on %s\n", inet_ntoa(conf->listen_addr.sin_addr));
-
- bzero(&ina6, sizeof(ina6));
- if (bcmp(&ina6, &conf->listen6_addr.sin6_addr, sizeof(ina6)))
+ TAILQ_FOREACH(la, conf->listen_addrs, entry)
printf("listen on %s\n",
- log_sockaddr((struct sockaddr *)&conf->listen6_addr));
+ log_sockaddr((struct sockaddr *)&la->sa));
}
void
Index: rde.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
retrieving revision 1.115
diff -u -r1.115 rde.c
--- rde.c 21 May 2004 15:36:40 -0000 1.115
+++ rde.c 4 Jun 2004 18:08:05 -0000
@@ -104,11 +104,12 @@
struct filter_head *rules, struct mrt_head *mrt_l,
int pipe_m2r[2], int pipe_s2r[2])
{
- pid_t pid;
- struct passwd *pw;
- struct mrt *m;
- struct pollfd pfd[2];
- int nfds;
+ pid_t pid;
+ struct passwd *pw;
+ struct mrt *m;
+ struct listen_addr *la;
+ struct pollfd pfd[2];
+ int nfds;
switch (pid = fork()) {
case -1:
@@ -150,11 +151,16 @@
imsg_init(&ibuf_se, pipe_s2r[1]);
imsg_init(&ibuf_main, pipe_m2r[1]);
- /* main mrt list is not used in the SE */
+ /* main mrt list and listener list are not used in the SE */
while ((m = LIST_FIRST(mrt_l)) != NULL) {
LIST_REMOVE(m, list);
free(m);
}
+ while ((la = TAILQ_FIRST(config->listen_addrs)) != NULL) {
+ TAILQ_REMOVE(config->listen_addrs, la, entry);
+ free(la);
+ }
+ free(config->listen_addrs);
pt_init();
path_init(pathhashsize);
Index: session.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/session.c,v
retrieving revision 1.172
diff -u -r1.172 session.c
--- session.c 28 May 2004 18:39:09 -0000 1.172
+++ session.c 4 Jun 2004 18:08:06 -0000
@@ -44,15 +44,13 @@
#include "mrt.h"
#include "session.h"
-#define PFD_LISTEN 0
-#define PFD_LISTEN6 1
-#define PFD_PIPE_MAIN 2
-#define PFD_PIPE_ROUTE 3
-#define PFD_SOCK_CTL 4
-#define PFD_PEERS_START 5
+#define PFD_PIPE_MAIN 0
+#define PFD_PIPE_ROUTE 1
+#define PFD_SOCK_CTL 2
+#define PFD_LISTENERS_START 3
void session_sighdlr(int);
-int setup_listener(struct sockaddr *);
+int setup_listeners(void);
void init_conf(struct bgpd_config *);
void init_peer(struct peer *);
int timer_due(time_t);
@@ -81,6 +79,7 @@
void session_up(struct peer *);
void session_down(struct peer *);
+int la_cmp(struct listen_addr *, struct listen_addr *);
struct peer *getpeerbyip(struct sockaddr *);
int session_match_mask(struct peer *, struct sockaddr *);
struct peer *getpeerbyid(u_int32_t);
@@ -91,8 +90,6 @@
struct peer *npeers;
volatile sig_atomic_t session_quit = 0;
int pending_reconf = 0;
-int sock = -1;
-int sock6 = -1;
int csock = -1;
struct imsgbuf ibuf_rde;
struct imsgbuf ibuf_main;
@@ -111,41 +108,77 @@
}
int
-setup_listener(struct sockaddr *sa)
+setup_listeners(void)
{
- int fd, opt;
-
- if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
- fatal("king bula sez: unknown address family");
+ int opt;
+ struct listen_addr *la;
- if ((fd = socket(sa->sa_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
- log_warn("error setting up %s listener",
- sa->sa_family == AF_INET ? "IPv4" : "IPv6");
- return (fd);
+ if (TAILQ_EMPTY(conf->listen_addrs)) {
+ if ((la = calloc(1, sizeof(struct listen_addr))) == NULL)
+ fatal("setup_listeners calloc");
+ la->fd = -1;
+ la->flags = DEFAULT_LISTENER;
+ la->sa.ss_len = sizeof(struct sockaddr_in);
+ ((struct sockaddr_in *)&la->sa)->sin_family = AF_INET;
+ ((struct sockaddr_in *)&la->sa)->sin_addr.s_addr =
+ htonl(INADDR_ANY);
+ ((struct sockaddr_in *)&la->sa)->sin_port = htons(BGP_PORT);
+ TAILQ_INSERT_TAIL(conf->listen_addrs, la, entry);
+
+ if ((la = calloc(1, sizeof(struct listen_addr))) == NULL)
+ fatal("setup_listeners calloc");
+ la->fd = -1;
+ la->flags = DEFAULT_LISTENER;
+ la->sa.ss_len = sizeof(struct sockaddr_in6);
+ ((struct sockaddr_in6 *)&la->sa)->sin6_family = AF_INET6;
+ ((struct sockaddr_in6 *)&la->sa)->sin6_port = htons(BGP_PORT);
+ TAILQ_INSERT_TAIL(conf->listen_addrs, la, entry);
}
- opt = 1;
- if (setsockopt(fd, IPPROTO_TCP, TCP_MD5SIG, &opt, sizeof(opt)) == -1) {
- if (errno == ENOPROTOOPT) { /* system w/o md5sig support */
- log_warnx("md5 signatures not available, disabling");
- sysdep.no_md5sig = 1;
- } else
- fatal("setsockopt TCP_MD5SIG");
- }
+ TAILQ_FOREACH(la, conf->listen_addrs, entry) {
+ la->reconf = RECONF_NONE;
- if (bind(fd, sa, sa->sa_len)) {
- close(fd);
- fatal("bind");
- }
+ if (la->fd != -1)
+ continue;
+
+ if ((la->fd = socket(la->sa.ss_family, SOCK_STREAM,
+ IPPROTO_TCP)) == -1)
+ fatal("socket");
+
+ opt = 1;
+ if (setsockopt(la->fd, IPPROTO_TCP, TCP_MD5SIG,
+ &opt, sizeof(opt)) == -1) {
+ if (errno == ENOPROTOOPT) { /* system w/o md5sig */
+ log_warnx("md5sig not available, disabling");
+ sysdep.no_md5sig = 1;
+ } else
+ fatal("setsockopt TCP_MD5SIG");
+ }
+
+ if (bind(la->fd, (struct sockaddr *)&la->sa, la->sa.ss_len) ==
+ -1) {
+ if (errno == EACCES) {
+ log_warnx("can't establish listener on %s",
+ log_sockaddr((struct sockaddr *)&la->sa));
+ close(la->fd);
+ la->fd = -1;
+ return (-1);
+ } else
+ fatal("bind");
+ }
+
+ session_socket_blockmode(la->fd, BM_NONBLOCK);
- session_socket_blockmode(fd, BM_NONBLOCK);
+ if (listen(la->fd, MAX_BACKLOG)) {
+ close(la->fd);
+ fatal("listen");
+ }
- if (listen(fd, MAX_BACKLOG)) {
- close(fd);
- fatal("listen");
+ log_info("listening on %s",
+ log_sockaddr((struct sockaddr *)&la->sa));
}
- return (fd);
+ return (0);
}
int
@@ -153,7 +186,7 @@
struct network_head *net_l, struct filter_head *rules,
struct mrt_head *m_l, int pipe_m2s[2], int pipe_s2r[2])
{
- int nfds, i, j, timeout, idx_peers;
+ int nfds, i, j, timeout, idx_peers, idx_listeners;
pid_t pid;
time_t nextaction;
struct passwd *pw;
@@ -164,6 +197,7 @@
struct filter_rule *r;
struct pollfd pfd[OPEN_MAX];
struct ctl_conn *ctl_conn;
+ struct listen_addr *la;
short events;
conf = config;
@@ -193,8 +227,7 @@
setproctitle("session engine");
bgpd_process = PROC_SE;
- sock = setup_listener((struct sockaddr *)&conf->listen_addr);
- sock6 = setup_listener((struct sockaddr *)&conf->listen6_addr);
+ setup_listeners();
if (pfkey_init(&sysdep) == -1)
fatalx("pfkey setup failed");
@@ -240,10 +273,6 @@
while (session_quit == 0) {
bzero(&pfd, sizeof(pfd));
- pfd[PFD_LISTEN].fd = sock;
- pfd[PFD_LISTEN].events = POLLIN;
- pfd[PFD_LISTEN6].fd = sock6;
- pfd[PFD_LISTEN6].events = POLLIN;
pfd[PFD_PIPE_MAIN].fd = ibuf_main.fd;
pfd[PFD_PIPE_MAIN].events = POLLIN;
if (ibuf_main.w.queued > 0)
@@ -256,7 +285,15 @@
pfd[PFD_SOCK_CTL].events = POLLIN;
nextaction = time(NULL) + 240; /* loop every 240s at least */
- i = PFD_PEERS_START;
+ i = PFD_LISTENERS_START;
+
+ TAILQ_FOREACH(la, conf->listen_addrs, entry) {
+ pfd[i].fd = la->fd;
+ pfd[i].events = POLLIN;
+ i++;
+ }
+
+ idx_listeners = i;
last = NULL;
for (p = peers; p != NULL; p = next) {
@@ -353,16 +390,6 @@
if (errno != EINTR)
fatal("poll error");
- if (nfds > 0 && pfd[PFD_LISTEN].revents & POLLIN) {
- nfds--;
- session_accept(sock);
- }
-
- if (nfds > 0 && pfd[PFD_LISTEN6].revents & POLLIN) {
- nfds--;
- session_accept(sock6);
- }
-
if (nfds > 0 && pfd[PFD_PIPE_MAIN].revents & POLLOUT)
if (msgbuf_write(&ibuf_main.w) < 0)
fatal("pipe write error");
@@ -386,7 +413,14 @@
control_accept(csock);
}
- for (j = PFD_PEERS_START; nfds > 0 && j < idx_peers; j++)
+ for (j = PFD_LISTENERS_START; nfds > 0 && j < idx_listeners;
+ j++)
+ if (pfd[j].revents & POLLIN) {
+ nfds--;
+ session_accept(pfd[j].fd);
+ }
+
+ for (; nfds > 0 && j < idx_peers; j++)
nfds -= session_dispatch_msg(&pfd[j], peer_l[j]);
for (; nfds > 0 && j < i; j++)
@@ -405,6 +439,12 @@
free(mrt);
}
+ while ((la = TAILQ_FIRST(conf->listen_addrs)) != NULL) {
+ TAILQ_REMOVE(conf->listen_addrs, la, entry);
+ free(la);
+ }
+ free(conf->listen_addrs);
+
msgbuf_write(&ibuf_rde.w);
msgbuf_clear(&ibuf_rde.w);
msgbuf_write(&ibuf_main.w);
@@ -1914,6 +1954,7 @@
struct mrt_config *mrt;
struct peer_config *pconf;
struct peer *p, *next;
+ struct listen_addr *la, *nla;
u_char *data;
enum reconf_action reconf;
int n;
@@ -1940,6 +1981,10 @@
NULL)
fatal(NULL);
memcpy(nconf, imsg.data, sizeof(struct bgpd_config));
+ if ((nconf->listen_addrs = calloc(1,
+ sizeof(struct listen_addrs))) == NULL)
+ fatal(NULL);
+ TAILQ_INIT(nconf->listen_addrs);
npeers = NULL;
init_conf(nconf);
pending_reconf = 1;
@@ -1963,6 +2008,29 @@
memcpy(&p->conf, pconf, sizeof(struct peer_config));
p->conf.reconf_action = reconf;
break;
+ case IMSG_RECONF_LISTENER:
+ if (idx != PFD_PIPE_MAIN)
+ fatalx("reconf request not from parent");
+ nla = imsg.data;
+ TAILQ_FOREACH(la, conf->listen_addrs, entry) {
+ if (!la_cmp(la, nla))
+ break;
+ }
+
+ if (la == NULL) {
+ la = calloc(1, sizeof(struct listen_addr));
+ if (la == NULL)
+ fatal(NULL);
+ memcpy(&la->sa, &nla->sa, sizeof(la->sa));
+ la->fd = nla->fd;
+ la->flags = nla->flags;
+ la->reconf = RECONF_REINIT;
+ TAILQ_INSERT_TAIL(nconf->listen_addrs, la,
+ entry);
+ } else {
+ la->reconf = RECONF_KEEP;
+ }
+ break;
case IMSG_RECONF_DONE:
if (idx != PFD_PIPE_MAIN)
fatalx("reconf request not from parent");
@@ -1972,17 +2040,50 @@
conf->holdtime = nconf->holdtime;
conf->bgpid = nconf->bgpid;
conf->min_holdtime = nconf->min_holdtime;
+
/* add new peers */
for (p = npeers; p != NULL; p = next) {
next = p->next;
p->next = peers;
peers = p;
}
- /* find peers to be deleted */
+ /* find ones to be deleted */
for (p = peers; p != NULL; p = p->next)
if (p->conf.reconf_action == RECONF_NONE &&
!p->conf.cloned)
p->conf.reconf_action = RECONF_DELETE;
+
+ /* if there are no new listeners, keep default ones */
+ if (TAILQ_EMPTY(nconf->listen_addrs))
+ TAILQ_FOREACH(la, conf->listen_addrs, entry)
+ if (la->flags & DEFAULT_LISTENER)
+ la->reconf = RECONF_KEEP;
+
+ /* delete old listeners */
+ for (la = TAILQ_FIRST(conf->listen_addrs); la != NULL;
+ la = nla) {
+ nla = TAILQ_NEXT(la, entry);
+ if (la->reconf == RECONF_NONE) {
+ log_info("not listening on %s any more",
+ log_sockaddr(
+ (struct sockaddr *)&la->sa));
+ TAILQ_REMOVE(conf->listen_addrs, la,
+ entry);
+ close(la->fd);
+ free(la);
+ }
+ }
+
+ /* add new listeners */
+ while ((la = TAILQ_FIRST(nconf->listen_addrs)) !=
+ NULL) {
+ TAILQ_REMOVE(nconf->listen_addrs, la, entry);
+ TAILQ_INSERT_TAIL(conf->listen_addrs, la,
+ entry);
+ }
+
+ setup_listeners();
+ free(nconf->listen_addrs);
free(nconf);
nconf = NULL;
pending_reconf = 0;
@@ -2066,6 +2167,41 @@
}
imsg_free(&imsg);
}
+}
+
+int
+la_cmp(struct listen_addr *a, struct listen_addr *b)
+{
+ struct sockaddr_in *in_a, *in_b;
+ struct sockaddr_in6 *in6_a, *in6_b;
+
+ if (a->sa.ss_family != b->sa.ss_family)
+ return (1);
+
+ switch (a->sa.ss_family) {
+ case AF_INET:
+ in_a = (struct sockaddr_in *)&a->sa;
+ in_b = (struct sockaddr_in *)&b->sa;
+ if (in_a->sin_addr.s_addr != in_b->sin_addr.s_addr)
+ return (1);
+ if (in_a->sin_port != in_b->sin_port)
+ return (1);
+ break;
+ case AF_INET6:
+ in6_a = (struct sockaddr_in6 *)&a->sa;
+ in6_b = (struct sockaddr_in6 *)&b->sa;
+ if (bcmp(&in6_a->sin6_addr, &in6_b->sin6_addr,
+ sizeof(struct in6_addr)))
+ return (1);
+ if (in6_a->sin6_port != in6_b->sin6_port)
+ return (1);
+ break;
+ default:
+ fatal("king bula sez: unknown address family");
+ /* not reached */
+ }
+
+ return (0);
}
struct peer *
Index: session.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/session.h,v
retrieving revision 1.53
diff -u -r1.53 session.h
--- session.h 28 May 2004 18:39:09 -0000 1.53
+++ session.h 4 Jun 2004 18:08:06 -0000
@@ -207,7 +207,7 @@
/* config.c */
int merge_config(struct bgpd_config *, struct bgpd_config *,
- struct peer *);
+ struct peer *, struct listen_addrs *);
/* rde.c */
int rde_main(struct bgpd_config *, struct network_head *,