View | Details | Raw Unified | Return to bug 223835 | Differences between
and this patch

Collapse All | Expand All

(-)bgpd/session.c (-464 / +787 lines)
Lines 1-4 Link Here
1
/*	$OpenBSD: session.c,v 1.293 2009/06/07 05:56:24 eric Exp $ */
1
/*	$OpenBSD: session.c,v 1.325 2012/09/18 09:45:50 claudio Exp $ */
2
2
3
/*
3
/*
4
 * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
4
 * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
Lines 21-38 Link Here
21
21
22
#include <sys/mman.h>
22
#include <sys/mman.h>
23
#include <sys/socket.h>
23
#include <sys/socket.h>
24
#include <sys/time.h>
25
#include <sys/resource.h>
24
#include <sys/un.h>
26
#include <sys/un.h>
27
#include <sys/queue.h>
25
#include <net/if_types.h>
28
#include <net/if_types.h>
26
#include <netinet/in.h>
29
#include <netinet/in.h>
27
#include <netinet/in_systm.h>
30
#include <netinet/in_systm.h>
28
#include <netinet/ip.h>
31
#include <netinet/ip.h>
29
#include <netinet/tcp.h>
32
#include <netinet/tcp.h>
33
#include <netinet/tcp_var.h>
30
#include <arpa/inet.h>
34
#include <arpa/inet.h>
31
35
32
#include <err.h>
36
#include <err.h>
33
#include <errno.h>
37
#include <errno.h>
34
#include <fcntl.h>
38
#include <fcntl.h>
35
#include <limits.h>
36
#include <poll.h>
39
#include <poll.h>
37
#include <pwd.h>
40
#include <pwd.h>
38
#include <signal.h>
41
#include <signal.h>
Lines 50-56 Link Here
50
#define PFD_PIPE_ROUTE_CTL	2
53
#define PFD_PIPE_ROUTE_CTL	2
51
#define PFD_SOCK_CTL		3
54
#define PFD_SOCK_CTL		3
52
#define PFD_SOCK_RCTL		4
55
#define PFD_SOCK_RCTL		4
53
#define PFD_LISTENERS_START	5
56
#define PFD_SOCK_PFKEY		5
57
#define PFD_LISTENERS_START	6
58
59
#if defined(__FreeBSD__) /* FreeBSD has no LINK_STATE_IS_UP macro. */
60
#define LINK_STATE_IS_UP(_s)  ((_s) >= LINK_STATE_UP)
61
#endif /* defined(__FreeBSD__) */ 
54
62
55
void	session_sighdlr(int);
63
void	session_sighdlr(int);
56
int	setup_listeners(u_int *);
64
int	setup_listeners(u_int *);
Lines 65-73 void session_accept(int); Link Here
65
int	session_connect(struct peer *);
73
int	session_connect(struct peer *);
66
void	session_tcp_established(struct peer *);
74
void	session_tcp_established(struct peer *);
67
void	session_capa_ann_none(struct peer *);
75
void	session_capa_ann_none(struct peer *);
68
int	session_capa_add(struct peer *, struct buf *, u_int8_t, u_int8_t,
76
int	session_capa_add(struct ibuf *, u_int8_t, u_int8_t);
69
	    u_int8_t *);
77
int	session_capa_add_mp(struct ibuf *, u_int8_t);
70
int	session_capa_add_mp(struct buf *, u_int16_t, u_int8_t);
78
int	session_capa_add_gr(struct peer *, struct ibuf *, u_int8_t);
71
struct bgp_msg	*session_newmsg(enum msg_type, u_int16_t);
79
struct bgp_msg	*session_newmsg(enum msg_type, u_int16_t);
72
int	session_sendmsg(struct bgp_msg *, struct peer *);
80
int	session_sendmsg(struct bgp_msg *, struct peer *);
73
void	session_open(struct peer *);
81
void	session_open(struct peer *);
Lines 75-104 void session_keepalive(struct peer *); Link Here
75
void	session_update(u_int32_t, void *, size_t);
83
void	session_update(u_int32_t, void *, size_t);
76
void	session_notification(struct peer *, u_int8_t, u_int8_t, void *,
84
void	session_notification(struct peer *, u_int8_t, u_int8_t, void *,
77
	    ssize_t);
85
	    ssize_t);
78
void	session_rrefresh(struct peer *, u_int16_t, u_int8_t);
86
void	session_rrefresh(struct peer *, u_int8_t);
87
int	session_graceful_restart(struct peer *);
88
int	session_graceful_is_restarting(struct peer *);
89
int	session_graceful_stop(struct peer *);
79
int	session_dispatch_msg(struct pollfd *, struct peer *);
90
int	session_dispatch_msg(struct pollfd *, struct peer *);
91
int	session_process_msg(struct peer *);
80
int	parse_header(struct peer *, u_char *, u_int16_t *, u_int8_t *);
92
int	parse_header(struct peer *, u_char *, u_int16_t *, u_int8_t *);
81
int	parse_open(struct peer *);
93
int	parse_open(struct peer *);
82
int	parse_update(struct peer *);
94
int	parse_update(struct peer *);
83
int	parse_refresh(struct peer *);
95
int	parse_refresh(struct peer *);
84
int	parse_notification(struct peer *);
96
int	parse_notification(struct peer *);
85
int	parse_capabilities(struct peer *, u_char *, u_int16_t, u_int32_t *);
97
int	parse_capabilities(struct peer *, u_char *, u_int16_t, u_int32_t *);
98
int	capa_neg_calc(struct peer *);
86
void	session_dispatch_imsg(struct imsgbuf *, int, u_int *);
99
void	session_dispatch_imsg(struct imsgbuf *, int, u_int *);
87
void	session_up(struct peer *);
100
void	session_up(struct peer *);
88
void	session_down(struct peer *);
101
void	session_down(struct peer *);
89
void	session_demote(struct peer *, int);
102
void	session_demote(struct peer *, int);
90
103
91
int			 la_cmp(struct listen_addr *, struct listen_addr *);
104
int		 la_cmp(struct listen_addr *, struct listen_addr *);
92
struct peer		*getpeerbyip(struct sockaddr *);
105
struct peer	*getpeerbyip(struct sockaddr *);
93
int			 session_match_mask(struct peer *, struct sockaddr *);
106
int		 session_match_mask(struct peer *, struct bgpd_addr *);
94
struct peer		*getpeerbyid(u_int32_t);
107
struct peer	*getpeerbyid(u_int32_t);
95
static struct sockaddr	*addr2sa(struct bgpd_addr *, u_int16_t);
96
108
97
struct bgpd_config	*conf, *nconf = NULL;
109
struct bgpd_config	*conf, *nconf;
98
struct bgpd_sysdep	 sysdep;
110
struct bgpd_sysdep	 sysdep;
99
struct peer		*npeers;
111
struct peer		*peers, *npeers;
100
volatile sig_atomic_t	 session_quit = 0;
112
volatile sig_atomic_t	 session_quit;
101
int			 pending_reconf = 0;
113
int			 pending_reconf;
102
int			 csock = -1, rcsock = -1;
114
int			 csock = -1, rcsock = -1;
103
u_int			 peer_cnt;
115
u_int			 peer_cnt;
104
struct imsgbuf		*ibuf_rde;
116
struct imsgbuf		*ibuf_rde;
Lines 106-111 struct imsgbuf *ibuf_rde_ctl; Link Here
106
struct imsgbuf		*ibuf_main;
118
struct imsgbuf		*ibuf_main;
107
119
108
struct mrt_head		 mrthead;
120
struct mrt_head		 mrthead;
121
time_t			 pauseaccept;
109
122
110
void
123
void
111
session_sighdlr(int sig)
124
session_sighdlr(int sig)
Lines 175-186 setup_listeners(u_int *la_cnt) Link Here
175
}
206
}
176
207
177
pid_t
208
pid_t
178
session_main(struct bgpd_config *config, struct peer *cpeers,
209
session_main(int pipe_m2s[2], int pipe_s2r[2], int pipe_m2r[2],
179
    struct network_head *net_l, struct filter_head *rules,
210
    int pipe_s2rctl[2])
180
    struct mrt_head *m_l, struct rib_names *rib_l, int pipe_m2s[2],
181
    int pipe_s2r[2], int pipe_m2r[2], int pipe_s2rctl[2])
182
{
211
{
183
	int			 nfds, timeout;
212
	int			 nfds, timeout, pfkeysock;
184
	unsigned int		 i, j, idx_peers, idx_listeners, idx_mrts;
213
	unsigned int		 i, j, idx_peers, idx_listeners, idx_mrts;
185
	pid_t			 pid;
214
	pid_t			 pid;
186
	u_int			 pfd_elms = 0, peer_l_elms = 0, mrt_l_elms = 0;
215
	u_int			 pfd_elms = 0, peer_l_elms = 0, mrt_l_elms = 0;
Lines 189-207 session_main(struct bgpd_config *config, Link Here
189
	u_int32_t		 ctl_queued;
218
	u_int32_t		 ctl_queued;
190
	struct passwd		*pw;
219
	struct passwd		*pw;
191
	struct peer		*p, **peer_l = NULL, *last, *next;
220
	struct peer		*p, **peer_l = NULL, *last, *next;
192
	struct network		*net;
221
	struct mrt		*m, *xm, **mrt_l = NULL;
193
	struct mrt		*m, **mrt_l = NULL;
194
	struct filter_rule	*r;
195
	struct pollfd		*pfd = NULL;
222
	struct pollfd		*pfd = NULL;
196
	struct ctl_conn		*ctl_conn;
223
	struct ctl_conn		*ctl_conn;
197
	struct listen_addr	*la;
224
	struct listen_addr	*la;
198
	struct rde_rib		*rr;
199
	void			*newp;
225
	void			*newp;
200
	short			 events;
226
	short			 events;
201
227
202
	conf = config;
203
	peers = cpeers;
204
205
	switch (pid = fork()) {
228
	switch (pid = fork()) {
206
	case -1:
229
	case -1:
207
		fatal("cannot fork");
230
		fatal("cannot fork");
Lines 211-223 session_main(struct bgpd_config *config, Link Here
211
		return (pid);
234
		return (pid);
212
	}
235
	}
213
236
214
	/* control socket is outside chroot */
215
	if ((csock = control_init(0, conf->csock)) == -1)
216
		fatalx("control socket setup failed");
217
	if (conf->rcsock != NULL &&
218
	    (rcsock = control_init(1, conf->rcsock)) == -1)
219
		fatalx("control socket setup failed");
220
221
	if ((pw = getpwnam(BGPD_USER)) == NULL)
237
	if ((pw = getpwnam(BGPD_USER)) == NULL)
222
		fatal(NULL);
238
		fatal(NULL);
223
239
Lines 228-256 session_main(struct bgpd_config *config, Link Here
228
244
229
	setproctitle("session engine");
245
	setproctitle("session engine");
230
	bgpd_process = PROC_SE;
246
	bgpd_process = PROC_SE;
231
247
	pfkeysock = pfkey_init(&sysdep);
232
	if (pfkey_init(&sysdep) == -1)
233
		fatalx("pfkey setup failed");
234
248
235
	if (setgroups(1, &pw->pw_gid) ||
249
	if (setgroups(1, &pw->pw_gid) ||
236
	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
250
	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
237
	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
251
	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
238
		fatal("can't drop privileges");
252
		fatal("can't drop privileges");
239
253
240
	listener_cnt = 0;
241
	setup_listeners(&listener_cnt);
242
243
	signal(SIGTERM, session_sighdlr);
254
	signal(SIGTERM, session_sighdlr);
244
	signal(SIGINT, session_sighdlr);
255
	signal(SIGINT, session_sighdlr);
245
	signal(SIGPIPE, SIG_IGN);
256
	signal(SIGPIPE, SIG_IGN);
246
	signal(SIGHUP, SIG_IGN);
257
	signal(SIGHUP, SIG_IGN);
247
	log_info("session engine ready");
258
	signal(SIGALRM, SIG_IGN);
259
	signal(SIGUSR1, SIG_IGN);
260
248
	close(pipe_m2s[0]);
261
	close(pipe_m2s[0]);
249
	close(pipe_s2r[1]);
262
	close(pipe_s2r[1]);
250
	close(pipe_s2rctl[1]);
263
	close(pipe_s2rctl[1]);
251
	close(pipe_m2r[0]);
264
	close(pipe_m2r[0]);
252
	close(pipe_m2r[1]);
265
	close(pipe_m2r[1]);
253
	init_conf(conf);
254
	if ((ibuf_rde = malloc(sizeof(struct imsgbuf))) == NULL ||
266
	if ((ibuf_rde = malloc(sizeof(struct imsgbuf))) == NULL ||
255
	    (ibuf_rde_ctl = malloc(sizeof(struct imsgbuf))) == NULL ||
267
	    (ibuf_rde_ctl = malloc(sizeof(struct imsgbuf))) == NULL ||
256
	    (ibuf_main = malloc(sizeof(struct imsgbuf))) == NULL)
268
	    (ibuf_main = malloc(sizeof(struct imsgbuf))) == NULL)
Lines 258-294 session_main(struct bgpd_config *config, Link Here
258
	imsg_init(ibuf_rde, pipe_s2r[0]);
270
	imsg_init(ibuf_rde, pipe_s2r[0]);
259
	imsg_init(ibuf_rde_ctl, pipe_s2rctl[0]);
271
	imsg_init(ibuf_rde_ctl, pipe_s2rctl[0]);
260
	imsg_init(ibuf_main, pipe_m2s[1]);
272
	imsg_init(ibuf_main, pipe_m2s[1]);
273
261
	TAILQ_INIT(&ctl_conns);
274
	TAILQ_INIT(&ctl_conns);
262
	control_listen(csock);
263
	control_listen(rcsock);
264
	LIST_INIT(&mrthead);
275
	LIST_INIT(&mrthead);
276
	listener_cnt = 0;
265
	peer_cnt = 0;
277
	peer_cnt = 0;
266
	ctl_cnt = 0;
278
	ctl_cnt = 0;
267
279
268
	/* filter rules are not used in the SE */
280
	if ((conf = calloc(1, sizeof(struct bgpd_config))) == NULL)
269
	while ((r = TAILQ_FIRST(rules)) != NULL) {
281
		fatal(NULL);
270
		TAILQ_REMOVE(rules, r, entry);
282
	if ((conf->listen_addrs = calloc(1, sizeof(struct listen_addrs))) ==
271
		free(r);
283
	    NULL)
272
	}
284
		fatal(NULL);
273
	free(rules);
285
	TAILQ_INIT(conf->listen_addrs);
274
275
	/* network list is not used in the SE */
276
	while ((net = TAILQ_FIRST(net_l)) != NULL) {
277
		TAILQ_REMOVE(net_l, net, entry);
278
		filterset_free(&net->net.attrset);
279
		free(net);
280
	}
281
286
282
	/* main mrt list is not used in the SE */
287
	log_info("session engine ready");
283
	while ((m = LIST_FIRST(m_l)) != NULL) {
284
		LIST_REMOVE(m, entry);
285
		free(m);
286
	}
287
	/* rib names not used in the SE */
288
	while ((rr = SIMPLEQ_FIRST(&ribnames))) {
289
		SIMPLEQ_REMOVE_HEAD(&ribnames, entry);
290
		free(rr);
291
	}
292
288
293
	while (session_quit == 0) {
289
	while (session_quit == 0) {
294
		/* check for peers to be initialized or deleted */
290
		/* check for peers to be initialized or deleted */
Lines 308-315 session_main(struct bgpd_config *config, Link Here
308
304
309
				/* reinit due? */
305
				/* reinit due? */
310
				if (p->conf.reconf_action == RECONF_REINIT) {
306
				if (p->conf.reconf_action == RECONF_REINIT) {
311
					bgp_fsm(p, EVNT_STOP);
307
					session_stop(p, ERR_CEASE_ADMIN_RESET);
312
					timer_set(p, Timer_IdleHold, 0);
308
					if (!p->conf.down)
309
						timer_set(p, Timer_IdleHold, 0);
313
				}
310
				}
314
311
315
				/* deletion due? */
312
				/* deletion due? */
Lines 317-323 session_main(struct bgpd_config *config, Link Here
317
					if (p->demoted)
314
					if (p->demoted)
318
						session_demote(p, -1);
315
						session_demote(p, -1);
319
					p->conf.demote_group[0] = 0;
316
					p->conf.demote_group[0] = 0;
320
					bgp_fsm(p, EVNT_STOP);
317
					session_stop(p, ERR_CEASE_PEER_UNCONF);
321
					log_peer_warnx(&p->conf, "removed");
318
					log_peer_warnx(&p->conf, "removed");
322
					if (last != NULL)
319
					if (last != NULL)
323
						last->next = next;
320
						last->next = next;
Lines 346-354 session_main(struct bgpd_config *config, Link Here
346
		}
343
		}
347
344
348
		mrt_cnt = 0;
345
		mrt_cnt = 0;
349
		LIST_FOREACH(m, &mrthead, entry)
346
		for (m = LIST_FIRST(&mrthead); m != NULL; m = xm) {
347
			xm = LIST_NEXT(m, entry);
348
			if (m->state == MRT_STATE_REMOVE) {
349
				mrt_clean(m);
350
				LIST_REMOVE(m, entry);
351
				free(m);
352
				continue;
353
			}
350
			if (m->wbuf.queued)
354
			if (m->wbuf.queued)
351
				mrt_cnt++;
355
				mrt_cnt++;
356
		}
352
357
353
		if (mrt_cnt > mrt_l_elms) {
358
		if (mrt_cnt > mrt_l_elms) {
354
			if ((newp = realloc(mrt_l, sizeof(struct mrt *) *
359
			if ((newp = realloc(mrt_l, sizeof(struct mrt *) *
Lines 394-411 session_main(struct bgpd_config *config, Link Here
394
		if (ctl_queued < SESSION_CTL_QUEUE_MAX)
399
		if (ctl_queued < SESSION_CTL_QUEUE_MAX)
395
			/*
400
			/*
396
			 * Do not act as unlimited buffer. Don't read in more
401
			 * Do not act as unlimited buffer. Don't read in more
397
			 * messages if the ctl sockets are getting full. 
402
			 * messages if the ctl sockets are getting full.
398
			 */
403
			 */
399
			pfd[PFD_PIPE_ROUTE_CTL].events = POLLIN;
404
			pfd[PFD_PIPE_ROUTE_CTL].events = POLLIN;
400
		pfd[PFD_SOCK_CTL].fd = csock;
405
		if (pauseaccept == 0) {
401
		pfd[PFD_SOCK_CTL].events = POLLIN;
406
			pfd[PFD_SOCK_CTL].fd = csock;
402
		pfd[PFD_SOCK_RCTL].fd = rcsock;
407
			pfd[PFD_SOCK_CTL].events = POLLIN;
403
		pfd[PFD_SOCK_RCTL].events = POLLIN;
408
			pfd[PFD_SOCK_RCTL].fd = rcsock;
404
409
			pfd[PFD_SOCK_RCTL].events = POLLIN;
410
		} else {
411
			pfd[PFD_SOCK_CTL].fd = -1;
412
			pfd[PFD_SOCK_RCTL].fd = -1;
413
		}
414
		pfd[PFD_SOCK_PFKEY].fd = pfkeysock;
415
#if !defined(__FreeBSD__)
416
		pfd[PFD_SOCK_PFKEY].events = POLLIN;
417
#else
418
		pfd[PFD_SOCK_PFKEY].events = 0;
419
#endif
405
		i = PFD_LISTENERS_START;
420
		i = PFD_LISTENERS_START;
406
		TAILQ_FOREACH(la, conf->listen_addrs, entry) {
421
		TAILQ_FOREACH(la, conf->listen_addrs, entry) {
407
			pfd[i].fd = la->fd;
422
			if (pauseaccept == 0) {
408
			pfd[i].events = POLLIN;
423
				pfd[i].fd = la->fd;
424
				pfd[i].events = POLLIN;
425
			} else
426
				pfd[i].fd = -1;
409
			i++;
427
			i++;
410
		}
428
		}
411
		idx_listeners = i;
429
		idx_listeners = i;
Lines 450-455 session_main(struct bgpd_config *config, Link Here
450
					    p->state == STATE_ESTABLISHED)
468
					    p->state == STATE_ESTABLISHED)
451
						session_demote(p, -1);
469
						session_demote(p, -1);
452
					break;
470
					break;
471
				case Timer_RestartTimeout:
472
					timer_stop(p, Timer_RestartTimeout);
473
					session_graceful_stop(p);
474
					break;
453
				default:
475
				default:
454
					fatalx("King Bula lost in time");
476
					fatalx("King Bula lost in time");
455
				}
477
				}
Lines 462-467 session_main(struct bgpd_config *config, Link Here
462
			events = POLLIN;
484
			events = POLLIN;
463
			if (p->wbuf.queued > 0 || p->state == STATE_CONNECT)
485
			if (p->wbuf.queued > 0 || p->state == STATE_CONNECT)
464
				events |= POLLOUT;
486
				events |= POLLOUT;
487
			/* is there still work to do? */
488
			if (p->rbuf && p->rbuf->wpos)
489
				timeout = 0;
465
490
466
			/* poll events */
491
			/* poll events */
467
			if (p->fd != -1 && events != 0) {
492
			if (p->fd != -1 && events != 0) {
Lines 492-503 session_main(struct bgpd_config *config, Link Here
492
			i++;
517
			i++;
493
		}
518
		}
494
519
520
		if (pauseaccept && timeout > 1)
521
			timeout = 1;
495
		if (timeout < 0)
522
		if (timeout < 0)
496
			timeout = 0;
523
			timeout = 0;
497
		if ((nfds = poll(pfd, i, timeout * 1000)) == -1)
524
		if ((nfds = poll(pfd, i, timeout * 1000)) == -1)
498
			if (errno != EINTR)
525
			if (errno != EINTR)
499
				fatal("poll error");
526
				fatal("poll error");
500
527
528
		/*
529
		 * If we previously saw fd exhaustion, we stop accept()
530
		 * for 1 second to throttle the accept() loop.
531
		 */
532
		if (pauseaccept && getmonotime() > pauseaccept + 1)
533
			pauseaccept = 0;
534
501
		if (nfds > 0 && pfd[PFD_PIPE_MAIN].revents & POLLOUT)
535
		if (nfds > 0 && pfd[PFD_PIPE_MAIN].revents & POLLOUT)
502
			if (msgbuf_write(&ibuf_main->w) < 0)
536
			if (msgbuf_write(&ibuf_main->w) < 0)
503
				fatal("pipe write error");
537
				fatal("pipe write error");
Lines 534-539 session_main(struct bgpd_config *config, Link Here
534
			ctl_cnt += control_accept(rcsock, 1);
568
			ctl_cnt += control_accept(rcsock, 1);
535
		}
569
		}
536
570
571
		if (nfds > 0 && pfd[PFD_SOCK_PFKEY].revents & POLLIN) {
572
			nfds--;
573
			if (pfkey_read(pfkeysock, NULL) == -1) {
574
				log_warnx("pfkey_read failed, exiting...");
575
				session_quit = 1;
576
			}
577
		}
578
537
		for (j = PFD_LISTENERS_START; nfds > 0 && j < idx_listeners;
579
		for (j = PFD_LISTENERS_START; nfds > 0 && j < idx_listeners;
538
		    j++)
580
		    j++)
539
			if (pfd[j].revents & POLLIN) {
581
			if (pfd[j].revents & POLLIN) {
Lines 545-550 session_main(struct bgpd_config *config, Link Here
545
			nfds -= session_dispatch_msg(&pfd[j],
587
			nfds -= session_dispatch_msg(&pfd[j],
546
			    peer_l[j - idx_listeners]);
588
			    peer_l[j - idx_listeners]);
547
589
590
		for (p = peers; p != NULL; p = p->next)
591
			if (p->rbuf && p->rbuf->wpos)
592
				session_process_msg(p);
593
548
		for (; nfds > 0 && j < idx_mrts; j++)
594
		for (; nfds > 0 && j < idx_mrts; j++)
549
			if (pfd[j].revents & POLLOUT) {
595
			if (pfd[j].revents & POLLOUT) {
550
				nfds--;
596
				nfds--;
Lines 557-563 session_main(struct bgpd_config *config, Link Here
557
603
558
	while ((p = peers) != NULL) {
604
	while ((p = peers) != NULL) {
559
		peers = p->next;
605
		peers = p->next;
560
		bgp_fsm(p, EVNT_STOP);
606
		session_stop(p, ERR_CEASE_ADMIN_DOWN);
561
		pfkey_remove(p);
607
		pfkey_remove(p);
562
		free(p);
608
		free(p);
563
	}
609
	}
Lines 643-652 bgp_fsm(struct peer *peer, enum session_ Link Here
643
			timer_stop(peer, Timer_IdleHold);
689
			timer_stop(peer, Timer_IdleHold);
644
690
645
			/* allocate read buffer */
691
			/* allocate read buffer */
646
			peer->rbuf = calloc(1, sizeof(struct buf_read));
692
			peer->rbuf = calloc(1, sizeof(struct ibuf_read));
647
			if (peer->rbuf == NULL)
693
			if (peer->rbuf == NULL)
648
				fatal(NULL);
694
				fatal(NULL);
649
			peer->rbuf->wpos = 0;
650
695
651
			/* init write buffer */
696
			/* init write buffer */
652
			msgbuf_init(&peer->wbuf);
697
			msgbuf_init(&peer->wbuf);
Lines 746-752 bgp_fsm(struct peer *peer, enum session_ Link Here
746
			/* ignore */
791
			/* ignore */
747
			break;
792
			break;
748
		case EVNT_STOP:
793
		case EVNT_STOP:
749
			session_notification(peer, ERR_CEASE, 0, NULL, 0);
750
			change_state(peer, STATE_IDLE, event);
794
			change_state(peer, STATE_IDLE, event);
751
			break;
795
			break;
752
		case EVNT_CON_CLOSED:
796
		case EVNT_CON_CLOSED:
Lines 780-786 bgp_fsm(struct peer *peer, enum session_ Link Here
780
				change_state(peer, STATE_IDLE, event);
824
				change_state(peer, STATE_IDLE, event);
781
			break;
825
			break;
782
		default:
826
		default:
783
			session_notification(peer, ERR_FSM, 0, NULL, 0);
827
			session_notification(peer,
828
			    ERR_FSM, ERR_FSM_UNEX_OPENSENT, NULL, 0);
784
			change_state(peer, STATE_IDLE, event);
829
			change_state(peer, STATE_IDLE, event);
785
			break;
830
			break;
786
		}
831
		}
Lines 791-797 bgp_fsm(struct peer *peer, enum session_ Link Here
791
			/* ignore */
836
			/* ignore */
792
			break;
837
			break;
793
		case EVNT_STOP:
838
		case EVNT_STOP:
794
			session_notification(peer, ERR_CEASE, 0, NULL, 0);
795
			change_state(peer, STATE_IDLE, event);
839
			change_state(peer, STATE_IDLE, event);
796
			break;
840
			break;
797
		case EVNT_CON_CLOSED:
841
		case EVNT_CON_CLOSED:
Lines 815-821 bgp_fsm(struct peer *peer, enum session_ Link Here
815
			change_state(peer, STATE_IDLE, event);
859
			change_state(peer, STATE_IDLE, event);
816
			break;
860
			break;
817
		default:
861
		default:
818
			session_notification(peer, ERR_FSM, 0, NULL, 0);
862
			session_notification(peer,
863
			    ERR_FSM, ERR_FSM_UNEX_OPENCONFIRM, NULL, 0);
819
			change_state(peer, STATE_IDLE, event);
864
			change_state(peer, STATE_IDLE, event);
820
			break;
865
			break;
821
		}
866
		}
Lines 826-832 bgp_fsm(struct peer *peer, enum session_ Link Here
826
			/* ignore */
871
			/* ignore */
827
			break;
872
			break;
828
		case EVNT_STOP:
873
		case EVNT_STOP:
829
			session_notification(peer, ERR_CEASE, 0, NULL, 0);
830
			change_state(peer, STATE_IDLE, event);
874
			change_state(peer, STATE_IDLE, event);
831
			break;
875
			break;
832
		case EVNT_CON_CLOSED:
876
		case EVNT_CON_CLOSED:
Lines 856-862 bgp_fsm(struct peer *peer, enum session_ Link Here
856
			change_state(peer, STATE_IDLE, event);
900
			change_state(peer, STATE_IDLE, event);
857
			break;
901
			break;
858
		default:
902
		default:
859
			session_notification(peer, ERR_FSM, 0, NULL, 0);
903
			session_notification(peer,
904
			    ERR_FSM, ERR_FSM_UNEX_ESTABLISHED, NULL, 0);
860
			change_state(peer, STATE_IDLE, event);
905
			change_state(peer, STATE_IDLE, event);
861
			break;
906
			break;
862
		}
907
		}
Lines 885-893 start_timer_keepalive(struct peer *peer) Link Here
885
void
930
void
886
session_close_connection(struct peer *peer)
931
session_close_connection(struct peer *peer)
887
{
932
{
888
	if (peer->fd != -1)
933
	if (peer->fd != -1) {
889
		close(peer->fd);
934
		close(peer->fd);
890
935
		pauseaccept = 0;
936
	}
891
	peer->fd = peer->wbuf.fd = -1;
937
	peer->fd = peer->wbuf.fd = -1;
892
}
938
}
893
939
Lines 923-942 change_state(struct peer *peer, enum ses Link Here
923
		timer_stop(peer, Timer_ConnectRetry);
969
		timer_stop(peer, Timer_ConnectRetry);
924
		timer_stop(peer, Timer_Keepalive);
970
		timer_stop(peer, Timer_Keepalive);
925
		timer_stop(peer, Timer_Hold);
971
		timer_stop(peer, Timer_Hold);
972
		timer_stop(peer, Timer_IdleHold);
926
		timer_stop(peer, Timer_IdleHoldReset);
973
		timer_stop(peer, Timer_IdleHoldReset);
927
		session_close_connection(peer);
974
		session_close_connection(peer);
928
		msgbuf_clear(&peer->wbuf);
975
		msgbuf_clear(&peer->wbuf);
929
		free(peer->rbuf);
976
		free(peer->rbuf);
930
		peer->rbuf = NULL;
977
		peer->rbuf = NULL;
931
		bzero(&peer->capa.peer, sizeof(peer->capa.peer));
978
		bzero(&peer->capa.peer, sizeof(peer->capa.peer));
932
		if (peer->state == STATE_ESTABLISHED)
979
933
			session_down(peer);
934
		if (event != EVNT_STOP) {
980
		if (event != EVNT_STOP) {
935
			timer_set(peer, Timer_IdleHold, peer->IdleHoldTime);
981
			timer_set(peer, Timer_IdleHold, peer->IdleHoldTime);
936
			if (event != EVNT_NONE &&
982
			if (event != EVNT_NONE &&
937
			    peer->IdleHoldTime < MAX_IDLE_HOLD/2)
983
			    peer->IdleHoldTime < MAX_IDLE_HOLD/2)
938
				peer->IdleHoldTime *= 2;
984
				peer->IdleHoldTime *= 2;
939
		}
985
		}
986
		if (peer->state == STATE_ESTABLISHED) {
987
			if (peer->capa.neg.grestart.restart == 2 &&
988
			    (event == EVNT_CON_CLOSED ||
989
			    event == EVNT_CON_FATAL)) {
990
				/* don't punish graceful restart */
991
				timer_set(peer, Timer_IdleHold, 0);
992
				peer->IdleHoldTime /= 2;
993
				session_graceful_restart(peer);
994
			} else
995
				session_down(peer);
996
		}
940
		if (peer->state == STATE_NONE ||
997
		if (peer->state == STATE_NONE ||
941
		    peer->state == STATE_ESTABLISHED) {
998
		    peer->state == STATE_ESTABLISHED) {
942
			/* initialize capability negotiation structures */
999
			/* initialize capability negotiation structures */
Lines 947-952 change_state(struct peer *peer, enum ses Link Here
947
		}
1004
		}
948
		break;
1005
		break;
949
	case STATE_CONNECT:
1006
	case STATE_CONNECT:
1007
		if (peer->state == STATE_ESTABLISHED &&
1008
		    peer->capa.neg.grestart.restart == 2) {
1009
			/* do the graceful restart dance */
1010
			session_graceful_restart(peer);
1011
			peer->holdtime = INTERVAL_HOLD_INITIAL;
1012
			timer_stop(peer, Timer_ConnectRetry);
1013
			timer_stop(peer, Timer_Keepalive);
1014
			timer_stop(peer, Timer_Hold);
1015
			timer_stop(peer, Timer_IdleHold);
1016
			timer_stop(peer, Timer_IdleHoldReset);
1017
			session_close_connection(peer);
1018
			msgbuf_clear(&peer->wbuf);
1019
			bzero(&peer->capa.peer, sizeof(peer->capa.peer));
1020
		}
950
		break;
1021
		break;
951
	case STATE_ACTIVE:
1022
	case STATE_ACTIVE:
952
		break;
1023
		break;
Lines 990-996 session_accept(int listenfd) Link Here
990
	len = sizeof(cliaddr);
1061
	len = sizeof(cliaddr);
991
	if ((connfd = accept(listenfd,
1062
	if ((connfd = accept(listenfd,
992
	    (struct sockaddr *)&cliaddr, &len)) == -1) {
1063
	    (struct sockaddr *)&cliaddr, &len)) == -1) {
993
		if (errno == EWOULDBLOCK || errno == EINTR)
1064
		if (errno == ENFILE || errno == EMFILE) {
1065
			pauseaccept = getmonotime();
1066
			return;
1067
		} else if (errno == EWOULDBLOCK || errno == EINTR)
994
			return;
1068
			return;
995
		else
1069
		else
996
			log_warn("accept");
1070
			log_warn("accept");
Lines 1017-1022 session_accept(int listenfd) Link Here
1017
			}
1091
			}
1018
		}
1092
		}
1019
1093
1094
open:
1020
		if (p->conf.auth.method != AUTH_NONE && sysdep.no_pfkey) {
1095
		if (p->conf.auth.method != AUTH_NONE && sysdep.no_pfkey) {
1021
			log_peer_warnx(&p->conf,
1096
			log_peer_warnx(&p->conf,
1022
			    "ipsec or md5sig configured but not available");
1097
			    "ipsec or md5sig configured but not available");
Lines 1049-1054 session_accept(int listenfd) Link Here
1049
		}
1124
		}
1050
		session_socket_blockmode(connfd, BM_NONBLOCK);
1125
		session_socket_blockmode(connfd, BM_NONBLOCK);
1051
		bgp_fsm(p, EVNT_CON_OPEN);
1126
		bgp_fsm(p, EVNT_CON_OPEN);
1127
		return;
1128
	} else if (p != NULL && p->state == STATE_ESTABLISHED &&
1129
	    p->capa.neg.grestart.restart == 2) {
1130
		/* first do the graceful restart dance */
1131
		change_state(p, STATE_CONNECT, EVNT_CON_CLOSED);
1132
		/* then do part of the open dance */
1133
		goto open;
1052
	} else {
1134
	} else {
1053
		log_conn_attempt(p, (struct sockaddr *)&cliaddr);
1135
		log_conn_attempt(p, (struct sockaddr *)&cliaddr);
1054
		close(connfd);
1136
		close(connfd);
Lines 1069-1075 session_connect(struct peer *peer) Link Here
1069
	if (peer->fd != -1)
1151
	if (peer->fd != -1)
1070
		return (-1);
1152
		return (-1);
1071
1153
1072
	if ((peer->fd = socket(peer->conf.remote_addr.af, SOCK_STREAM,
1154
	if ((peer->fd = socket(aid2af(peer->conf.remote_addr.aid), SOCK_STREAM,
1073
	    IPPROTO_TCP)) == -1) {
1155
	    IPPROTO_TCP)) == -1) {
1074
		log_peer_warn(&peer->conf, "session_connect socket");
1156
		log_peer_warn(&peer->conf, "session_connect socket");
1075
		bgp_fsm(peer, EVNT_CON_OPENFAIL);
1157
		bgp_fsm(peer, EVNT_CON_OPENFAIL);
Lines 1100-1107 session_connect(struct peer *peer) Link Here
1100
	peer->wbuf.fd = peer->fd;
1182
	peer->wbuf.fd = peer->fd;
1101
1183
1102
	/* if update source is set we need to bind() */
1184
	/* if update source is set we need to bind() */
1103
	if (peer->conf.local_addr.af) {
1185
	if ((sa = addr2sa(&peer->conf.local_addr, 0)) != NULL) {
1104
		sa = addr2sa(&peer->conf.local_addr, 0);
1105
		if (bind(peer->fd, sa, sa->sa_len) == -1) {
1186
		if (bind(peer->fd, sa, sa->sa_len) == -1) {
1106
			log_peer_warn(&peer->conf, "session_connect bind");
1187
			log_peer_warn(&peer->conf, "session_connect bind");
1107
			bgp_fsm(peer, EVNT_CON_OPENFAIL);
1188
			bgp_fsm(peer, EVNT_CON_OPENFAIL);
Lines 1139-1180 session_setup_socket(struct peer *p) Link Here
1139
	int	nodelay = 1;
1220
	int	nodelay = 1;
1140
	int	bsize;
1221
	int	bsize;
1141
1222
1142
	if (p->conf.ebgp && p->conf.remote_addr.af == AF_INET) {
1223
	switch (p->conf.remote_addr.aid) {
1143
		/* set TTL to foreign router's distance - 1=direct n=multihop
1224
	case AID_INET:
1144
		   with ttlsec, we always use 255 */
1225
		/* set precedence, see RFC 1771 appendix 5 */
1145
		if (p->conf.ttlsec) {
1226
		if (setsockopt(p->fd, IPPROTO_IP, IP_TOS, &pre, sizeof(pre)) ==
1146
			ttl = 256 - p->conf.distance;
1227
		    -1) {
1147
			if (setsockopt(p->fd, IPPROTO_IP, IP_MINTTL, &ttl,
1228
			log_peer_warn(&p->conf,
1229
			    "session_setup_socket setsockopt TOS");
1230
			return (-1);
1231
		}
1232
1233
		if (p->conf.ebgp) {
1234
			/* set TTL to foreign router's distance
1235
			   1=direct n=multihop with ttlsec, we always use 255 */
1236
			if (p->conf.ttlsec) {
1237
				ttl = 256 - p->conf.distance;
1238
				if (setsockopt(p->fd, IPPROTO_IP, IP_MINTTL,
1239
				    &ttl, sizeof(ttl)) == -1) {
1240
					log_peer_warn(&p->conf,
1241
					    "session_setup_socket: "
1242
					    "setsockopt MINTTL");
1243
					return (-1);
1244
				}
1245
				ttl = 255;
1246
			}
1247
1248
			if (setsockopt(p->fd, IPPROTO_IP, IP_TTL, &ttl,
1148
			    sizeof(ttl)) == -1) {
1249
			    sizeof(ttl)) == -1) {
1149
				log_peer_warn(&p->conf,
1250
				log_peer_warn(&p->conf,
1150
				    "session_setup_socket setsockopt MINTTL");
1251
				    "session_setup_socket setsockopt TTL");
1151
				return (-1);
1252
				return (-1);
1152
			}
1253
			}
1153
			ttl = 255;
1154
		}
1155
1156
		if (setsockopt(p->fd, IPPROTO_IP, IP_TTL, &ttl,
1157
		    sizeof(ttl)) == -1) {
1158
			log_peer_warn(&p->conf,
1159
			    "session_setup_socket setsockopt TTL");
1160
			return (-1);
1161
		}
1254
		}
1162
	}
1255
		break;
1163
1256
	case AID_INET6:
1164
	if (p->conf.ebgp && p->conf.remote_addr.af == AF_INET6)
1257
		if (p->conf.ebgp) {
1165
		/* set hoplimit to foreign router's distance */
1258
			/* set hoplimit to foreign router's distance */
1166
		if (setsockopt(p->fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl,
1259
			if (setsockopt(p->fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
1167
		    sizeof(ttl)) == -1) {
1260
			    &ttl, sizeof(ttl)) == -1) {
1168
			log_peer_warn(&p->conf,
1261
				log_peer_warn(&p->conf,
1169
			    "session_setup_socket setsockopt hoplimit");
1262
				    "session_setup_socket setsockopt hoplimit");
1170
			return (-1);
1263
				return (-1);
1264
			}
1171
		}
1265
		}
1172
1266
		break;
1173
	/* if ttlsec is in use, set minttl */
1174
	if (p->conf.ttlsec) {
1175
		ttl = 256 - p->conf.distance;
1176
		setsockopt(p->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl));
1177
1178
	}
1267
	}
1179
1268
1180
	/* set TCP_NODELAY */
1269
	/* set TCP_NODELAY */
Lines 1185-1208 session_setup_socket(struct peer *p) Link Here
1185
		return (-1);
1274
		return (-1);
1186
	}
1275
	}
1187
1276
1188
	/* set precedence, see RFC 1771 appendix 5 */
1189
	if (p->conf.remote_addr.af == AF_INET &&
1190
	    setsockopt(p->fd, IPPROTO_IP, IP_TOS, &pre, sizeof(pre)) == -1) {
1191
		log_peer_warn(&p->conf,
1192
		    "session_setup_socket setsockopt TOS");
1193
		return (-1);
1194
	}
1195
1196
	/* only increase bufsize (and thus window) if md5 or ipsec is in use */
1277
	/* only increase bufsize (and thus window) if md5 or ipsec is in use */
1197
	if (p->conf.auth.method != AUTH_NONE) {
1278
	if (p->conf.auth.method != AUTH_NONE) {
1198
		/* try to increase bufsize. no biggie if it fails */
1279
		/* try to increase bufsize. no biggie if it fails */
1199
		bsize = 65535;
1280
		bsize = 65535;
1200
		while (setsockopt(p->fd, SOL_SOCKET, SO_RCVBUF, &bsize,
1281
		while (bsize > 8192 &&
1201
		    sizeof(bsize)) == -1)
1282
		    setsockopt(p->fd, SOL_SOCKET, SO_RCVBUF, &bsize,
1283
		    sizeof(bsize)) == -1 && errno != EINVAL)
1202
			bsize /= 2;
1284
			bsize /= 2;
1203
		bsize = 65535;
1285
		bsize = 65535;
1204
		while (setsockopt(p->fd, SOL_SOCKET, SO_SNDBUF, &bsize,
1286
		while (bsize > 8192 &&
1205
		    sizeof(bsize)) == -1)
1287
		    setsockopt(p->fd, SOL_SOCKET, SO_SNDBUF, &bsize,
1288
		    sizeof(bsize)) == -1 && errno != EINVAL)
1206
			bsize /= 2;
1289
			bsize /= 2;
1207
	}
1290
	}
1208
1291
Lines 1244-1283 session_tcp_established(struct peer *pee Link Here
1244
void
1327
void
1245
session_capa_ann_none(struct peer *peer)
1328
session_capa_ann_none(struct peer *peer)
1246
{
1329
{
1247
	peer->capa.ann.mp_v4 = SAFI_NONE;
1330
	bzero(&peer->capa.ann, sizeof(peer->capa.ann));
1248
	peer->capa.ann.mp_v4 = SAFI_NONE;
1249
	peer->capa.ann.refresh = 0;
1250
	peer->capa.ann.restart = 0;
1251
	peer->capa.ann.as4byte = 0;
1252
}
1331
}
1253
1332
1254
int
1333
int
1255
session_capa_add(struct peer *p, struct buf *opb, u_int8_t capa_code,
1334
session_capa_add(struct ibuf *opb, u_int8_t capa_code, u_int8_t capa_len)
1256
    u_int8_t capa_len, u_int8_t *optparamlen)
1335
{
1257
{
1336
	int errs = 0;
1258
	u_int8_t	op_type, op_len, tot_len, errs = 0;
1337
1259
1338
	errs += ibuf_add(opb, &capa_code, sizeof(capa_code));
1260
	op_type = OPT_PARAM_CAPABILITIES;
1339
	errs += ibuf_add(opb, &capa_len, sizeof(capa_len));
1261
	op_len = sizeof(capa_code) + sizeof(capa_len) + capa_len;
1262
	tot_len = sizeof(op_type) + sizeof(op_len) + op_len;
1263
	errs += buf_add(opb, &op_type, sizeof(op_type));
1264
	errs += buf_add(opb, &op_len, sizeof(op_len));
1265
	errs += buf_add(opb, &capa_code, sizeof(capa_code));
1266
	errs += buf_add(opb, &capa_len, sizeof(capa_len));
1267
	*optparamlen += tot_len;
1268
	return (errs);
1340
	return (errs);
1269
}
1341
}
1270
1342
1271
int
1343
int
1272
session_capa_add_mp(struct buf *buf, u_int16_t afi, u_int8_t safi)
1344
session_capa_add_mp(struct ibuf *buf, u_int8_t aid)
1273
{
1345
{
1274
	u_int8_t		 pad = 0;
1346
	u_int8_t		 safi, pad = 0;
1347
	u_int16_t		 afi;
1275
	int			 errs = 0;
1348
	int			 errs = 0;
1276
1349
1350
	if (aid2afi(aid, &afi, &safi) == -1)
1351
		fatalx("session_capa_add_mp: bad afi/safi pair");
1352
	afi = htons(afi);
1353
	errs += ibuf_add(buf, &afi, sizeof(afi));
1354
	errs += ibuf_add(buf, &pad, sizeof(pad));
1355
	errs += ibuf_add(buf, &safi, sizeof(safi));
1356
1357
	return (errs);
1358
}
1359
1360
int
1361
session_capa_add_gr(struct peer *p, struct ibuf *b, u_int8_t aid)
1362
{
1363
	u_int		errs = 0;
1364
	u_int16_t	afi;
1365
	u_int8_t	flags, safi;
1366
1367
	if (aid2afi(aid, &afi, &safi)) {
1368
		log_warn("session_capa_add_gr: bad AID");
1369
		return (1);
1370
	}
1371
	if (p->capa.neg.grestart.flags[aid] & CAPA_GR_RESTARTING)
1372
		flags = CAPA_GR_F_FLAG;
1373
	else
1374
		flags = 0;
1375
1277
	afi = htons(afi);
1376
	afi = htons(afi);
1278
	errs += buf_add(buf, &afi, sizeof(afi));
1377
	errs += ibuf_add(b, &afi, sizeof(afi));
1279
	errs += buf_add(buf, &pad, sizeof(pad));
1378
	errs += ibuf_add(b, &safi, sizeof(safi));
1280
	errs += buf_add(buf, &safi, sizeof(safi));
1379
	errs += ibuf_add(b, &flags, sizeof(flags));
1281
1380
1282
	return (errs);
1381
	return (errs);
1283
}
1382
}
Lines 1287-1309 session_newmsg(enum msg_type msgtype, u_ Link Here
1287
{
1386
{
1288
	struct bgp_msg		*msg;
1387
	struct bgp_msg		*msg;
1289
	struct msg_header	 hdr;
1388
	struct msg_header	 hdr;
1290
	struct buf		*buf;
1389
	struct ibuf		*buf;
1291
	int			 errs = 0;
1390
	int			 errs = 0;
1292
1391
1293
	memset(&hdr.marker, 0xff, sizeof(hdr.marker));
1392
	memset(&hdr.marker, 0xff, sizeof(hdr.marker));
1294
	hdr.len = htons(len);
1393
	hdr.len = htons(len);
1295
	hdr.type = msgtype;
1394
	hdr.type = msgtype;
1296
1395
1297
	if ((buf = buf_open(len)) == NULL)
1396
	if ((buf = ibuf_open(len)) == NULL)
1298
		return (NULL);
1397
		return (NULL);
1299
1398
1300
	errs += buf_add(buf, &hdr.marker, sizeof(hdr.marker));
1399
	errs += ibuf_add(buf, &hdr.marker, sizeof(hdr.marker));
1301
	errs += buf_add(buf, &hdr.len, sizeof(hdr.len));
1400
	errs += ibuf_add(buf, &hdr.len, sizeof(hdr.len));
1302
	errs += buf_add(buf, &hdr.type, sizeof(hdr.type));
1401
	errs += ibuf_add(buf, &hdr.type, sizeof(hdr.type));
1303
1402
1304
	if (errs > 0 ||
1403
	if (errs || (msg = calloc(1, sizeof(*msg))) == NULL) {
1305
	    (msg = calloc(1, sizeof(*msg))) == NULL) {
1404
		ibuf_free(buf);
1306
		buf_free(buf);
1307
		return (NULL);
1405
		return (NULL);
1308
	}
1406
	}
1309
1407
Lines 1329-1335 session_sendmsg(struct bgp_msg *msg, str Link Here
1329
			mrt_dump_bgp_msg(mrt, msg->buf->buf, msg->len, p);
1427
			mrt_dump_bgp_msg(mrt, msg->buf->buf, msg->len, p);
1330
	}
1428
	}
1331
1429
1332
	buf_close(&p->wbuf, msg->buf);
1430
	ibuf_close(&p->wbuf, msg->buf);
1333
	free(msg);
1431
	free(msg);
1334
	return (0);
1432
	return (0);
1335
}
1433
}
Lines 1338-1377 void Link Here
1338
session_open(struct peer *p)
1436
session_open(struct peer *p)
1339
{
1437
{
1340
	struct bgp_msg		*buf;
1438
	struct bgp_msg		*buf;
1341
	struct buf		*opb;
1439
	struct ibuf		*opb;
1342
	struct msg_open		 msg;
1440
	struct msg_open		 msg;
1343
	u_int16_t		 len;
1441
	u_int16_t		 len;
1344
	u_int8_t		 optparamlen = 0;
1442
	u_int8_t		 i, op_type, optparamlen = 0;
1345
	u_int			 errs = 0;
1443
	int			 errs = 0;
1444
	int			 mpcapa = 0;
1346
1445
1347
1446
1348
	if ((opb = buf_dynamic(0, MAX_PKTSIZE - MSGSIZE_OPEN_MIN)) == NULL) {
1447
	if ((opb = ibuf_dynamic(0, UCHAR_MAX - sizeof(op_type) -
1448
	    sizeof(optparamlen))) == NULL) {
1349
		bgp_fsm(p, EVNT_CON_FATAL);
1449
		bgp_fsm(p, EVNT_CON_FATAL);
1350
		return;
1450
		return;
1351
	}
1451
	}
1352
1452
1353
	/* multiprotocol extensions, RFC 4760 */
1453
	/* multiprotocol extensions, RFC 4760 */
1354
	if (p->capa.ann.mp_v4) {	/* 4 bytes data */
1454
	for (i = 0; i < AID_MAX; i++)
1355
		errs += session_capa_add(p, opb, CAPA_MP, 4, &optparamlen);
1455
		if (p->capa.ann.mp[i]) {	/* 4 bytes data */
1356
		errs += session_capa_add_mp(opb, AFI_IPv4, p->capa.ann.mp_v4);
1456
			errs += session_capa_add(opb, CAPA_MP, 4);
1357
	}
1457
			errs += session_capa_add_mp(opb, i);
1358
	if (p->capa.ann.mp_v6) {	/* 4 bytes data */
1458
			mpcapa++;
1359
		errs += session_capa_add(p, opb, CAPA_MP, 4, &optparamlen);
1459
		}
1360
		errs += session_capa_add_mp(opb, AFI_IPv6, p->capa.ann.mp_v6);
1361
	}
1362
1460
1363
	/* route refresh, RFC 2918 */
1461
	/* route refresh, RFC 2918 */
1364
	if (p->capa.ann.refresh)	/* no data */
1462
	if (p->capa.ann.refresh)	/* no data */
1365
		errs += session_capa_add(p, opb, CAPA_REFRESH, 0, &optparamlen);
1463
		errs += session_capa_add(opb, CAPA_REFRESH, 0);
1366
1464
1367
	/* End-of-RIB marker, RFC 4724 */
1465
	/* graceful restart and End-of-RIB marker, RFC 4724 */
1368
	if (p->capa.ann.restart) {	/* 2 bytes data */
1466
	if (p->capa.ann.grestart.restart) {
1369
		u_char		c[2];
1467
		int		rst = 0;
1370
1468
		u_int16_t	hdr;
1371
		bzero(&c, 2);
1469
		u_int8_t	grlen;
1372
		c[0] = 0x80; /* we're always restarting */
1470
1373
		errs += session_capa_add(p, opb, CAPA_RESTART, 2, &optparamlen);
1471
		if (mpcapa) {
1374
		errs += buf_add(opb, &c, 2);
1472
			grlen = 2 + 4 * mpcapa;
1473
			for (i = 0; i < AID_MAX; i++) {
1474
				if (p->capa.neg.grestart.flags[i] &
1475
				    CAPA_GR_RESTARTING)
1476
					rst++;
1477
			}
1478
		} else {	/* AID_INET */
1479
			grlen = 2 + 4;
1480
			if (p->capa.neg.grestart.flags[AID_INET] &
1481
			    CAPA_GR_RESTARTING)
1482
				rst++;
1483
		}
1484
1485
		hdr = conf->holdtime;		/* default timeout */
1486
		/* if client does graceful restart don't set R flag */
1487
		if (!rst)
1488
			hdr |= CAPA_GR_R_FLAG;
1489
		hdr = htons(hdr);
1490
1491
		errs += session_capa_add(opb, CAPA_RESTART, grlen);
1492
		errs += ibuf_add(opb, &hdr, sizeof(hdr));
1493
1494
		if (mpcapa) {
1495
			for (i = 0; i < AID_MAX; i++) {
1496
				if (p->capa.ann.mp[i]) {
1497
					errs += session_capa_add_gr(p, opb, i);
1498
				}
1499
			}
1500
		} else {	/* AID_INET */
1501
			errs += session_capa_add_gr(p, opb, AID_INET);
1502
		}
1375
	}
1503
	}
1376
1504
1377
	/* 4-bytes AS numbers, draft-ietf-idr-as4bytes-13 */
1505
	/* 4-bytes AS numbers, draft-ietf-idr-as4bytes-13 */
Lines 1379-1391 session_open(struct peer *p) Link Here
1379
		u_int32_t	nas;
1507
		u_int32_t	nas;
1380
1508
1381
		nas = htonl(conf->as);
1509
		nas = htonl(conf->as);
1382
		errs += session_capa_add(p, opb, CAPA_AS4BYTE, 4, &optparamlen);
1510
		errs += session_capa_add(opb, CAPA_AS4BYTE, sizeof(nas));
1383
		errs += buf_add(opb, &nas, 4);
1511
		errs += ibuf_add(opb, &nas, sizeof(nas));
1384
	}
1512
	}
1385
1513
1514
	if (ibuf_size(opb))
1515
		optparamlen = ibuf_size(opb) + sizeof(op_type) +
1516
		    sizeof(optparamlen);
1517
1386
	len = MSGSIZE_OPEN_MIN + optparamlen;
1518
	len = MSGSIZE_OPEN_MIN + optparamlen;
1387
	if (errs || (buf = session_newmsg(OPEN, len)) == NULL) {
1519
	if (errs || (buf = session_newmsg(OPEN, len)) == NULL) {
1388
		buf_free(opb);
1520
		ibuf_free(opb);
1389
		bgp_fsm(p, EVNT_CON_FATAL);
1521
		bgp_fsm(p, EVNT_CON_FATAL);
1390
		return;
1522
		return;
1391
	}
1523
	}
Lines 1399-1417 session_open(struct peer *p) Link Here
1399
	msg.bgpid = conf->bgpid;	/* is already in network byte order */
1531
	msg.bgpid = conf->bgpid;	/* is already in network byte order */
1400
	msg.optparamlen = optparamlen;
1532
	msg.optparamlen = optparamlen;
1401
1533
1402
	errs += buf_add(buf->buf, &msg.version, sizeof(msg.version));
1534
	errs += ibuf_add(buf->buf, &msg.version, sizeof(msg.version));
1403
	errs += buf_add(buf->buf, &msg.myas, sizeof(msg.myas));
1535
	errs += ibuf_add(buf->buf, &msg.myas, sizeof(msg.myas));
1404
	errs += buf_add(buf->buf, &msg.holdtime, sizeof(msg.holdtime));
1536
	errs += ibuf_add(buf->buf, &msg.holdtime, sizeof(msg.holdtime));
1405
	errs += buf_add(buf->buf, &msg.bgpid, sizeof(msg.bgpid));
1537
	errs += ibuf_add(buf->buf, &msg.bgpid, sizeof(msg.bgpid));
1406
	errs += buf_add(buf->buf, &msg.optparamlen, sizeof(msg.optparamlen));
1538
	errs += ibuf_add(buf->buf, &msg.optparamlen, sizeof(msg.optparamlen));
1407
1539
1408
	if (optparamlen)
1540
	if (optparamlen) {
1409
		errs += buf_add(buf->buf, opb->buf, optparamlen);
1541
		op_type = OPT_PARAM_CAPABILITIES;
1542
		optparamlen = ibuf_size(opb);
1543
		errs += ibuf_add(buf->buf, &op_type, sizeof(op_type));
1544
		errs += ibuf_add(buf->buf, &optparamlen, sizeof(optparamlen));
1545
		errs += ibuf_add(buf->buf, opb->buf, ibuf_size(opb));
1546
	}
1410
1547
1411
	buf_free(opb);
1548
	ibuf_free(opb);
1412
1549
1413
	if (errs > 0) {
1550
	if (errs) {
1414
		buf_free(buf->buf);
1551
		ibuf_free(buf->buf);
1415
		free(buf);
1552
		free(buf);
1416
		bgp_fsm(p, EVNT_CON_FATAL);
1553
		bgp_fsm(p, EVNT_CON_FATAL);
1417
		return;
1554
		return;
Lines 1459-1466 session_update(u_int32_t peerid, void *d Link Here
1459
		return;
1596
		return;
1460
	}
1597
	}
1461
1598
1462
	if (buf_add(buf->buf, data, datalen)) {
1599
	if (ibuf_add(buf->buf, data, datalen)) {
1463
		buf_free(buf->buf);
1600
		ibuf_free(buf->buf);
1464
		free(buf);
1601
		free(buf);
1465
		bgp_fsm(p, EVNT_CON_FATAL);
1602
		bgp_fsm(p, EVNT_CON_FATAL);
1466
		return;
1603
		return;
Lines 1480-1508 session_notification(struct peer *p, u_i Link Here
1480
    void *data, ssize_t datalen)
1617
    void *data, ssize_t datalen)
1481
{
1618
{
1482
	struct bgp_msg		*buf;
1619
	struct bgp_msg		*buf;
1483
	u_int			 errs = 0;
1620
	int			 errs = 0;
1484
	u_int8_t		 null8 = 0;
1485
1621
1486
	if (p->stats.last_sent_errcode)	/* some notification already sent */
1622
	if (p->stats.last_sent_errcode)	/* some notification already sent */
1487
		return;
1623
		return;
1488
1624
1625
	log_notification(p, errcode, subcode, data, datalen, "sending");
1626
1489
	if ((buf = session_newmsg(NOTIFICATION,
1627
	if ((buf = session_newmsg(NOTIFICATION,
1490
	    MSGSIZE_NOTIFICATION_MIN + datalen)) == NULL) {
1628
	    MSGSIZE_NOTIFICATION_MIN + datalen)) == NULL) {
1491
		bgp_fsm(p, EVNT_CON_FATAL);
1629
		bgp_fsm(p, EVNT_CON_FATAL);
1492
		return;
1630
		return;
1493
	}
1631
	}
1494
1632
1495
	errs += buf_add(buf->buf, &errcode, sizeof(errcode));
1633
	errs += ibuf_add(buf->buf, &errcode, sizeof(errcode));
1496
	if (errcode == ERR_CEASE)
1634
	errs += ibuf_add(buf->buf, &subcode, sizeof(subcode));
1497
		errs += buf_add(buf->buf, &null8, sizeof(null8));
1498
	else
1499
		errs += buf_add(buf->buf, &subcode, sizeof(subcode));
1500
1635
1501
	if (datalen > 0)
1636
	if (datalen > 0)
1502
		errs += buf_add(buf->buf, data, datalen);
1637
		errs += ibuf_add(buf->buf, data, datalen);
1503
1638
1504
	if (errs > 0) {
1639
	if (errs) {
1505
		buf_free(buf->buf);
1640
		ibuf_free(buf->buf);
1506
		free(buf);
1641
		free(buf);
1507
		bgp_fsm(p, EVNT_CON_FATAL);
1642
		bgp_fsm(p, EVNT_CON_FATAL);
1508
		return;
1643
		return;
Lines 1521-1543 session_notification(struct peer *p, u_i Link Here
1521
int
1656
int
1522
session_neighbor_rrefresh(struct peer *p)
1657
session_neighbor_rrefresh(struct peer *p)
1523
{
1658
{
1659
	u_int8_t	i;
1660
1524
	if (!p->capa.peer.refresh)
1661
	if (!p->capa.peer.refresh)
1525
		return (-1);
1662
		return (-1);
1526
1663
1527
	if (p->capa.peer.mp_v4 != SAFI_NONE)
1664
	for (i = 0; i < AID_MAX; i++) {
1528
		session_rrefresh(p, AFI_IPv4, p->capa.peer.mp_v4);
1665
		if (p->capa.peer.mp[i] != 0)
1529
	if (p->capa.peer.mp_v6 != SAFI_NONE)
1666
			session_rrefresh(p, i);
1530
		session_rrefresh(p, AFI_IPv6, p->capa.peer.mp_v6);
1667
	}
1531
1668
1532
	return (0);
1669
	return (0);
1533
}
1670
}
1534
1671
1535
void
1672
void
1536
session_rrefresh(struct peer *p, u_int16_t afi, u_int8_t safi)
1673
session_rrefresh(struct peer *p, u_int8_t aid)
1537
{
1674
{
1538
	struct bgp_msg		*buf;
1675
	struct bgp_msg		*buf;
1539
	int			 errs = 0;
1676
	int			 errs = 0;
1540
	u_int8_t		 null8 = 0;
1677
	u_int16_t		 afi;
1678
	u_int8_t		 safi, null8 = 0;
1679
1680
	if (aid2afi(aid, &afi, &safi) == -1)
1681
		fatalx("session_rrefresh: bad afi/safi pair");
1541
1682
1542
	if ((buf = session_newmsg(RREFRESH, MSGSIZE_RREFRESH)) == NULL) {
1683
	if ((buf = session_newmsg(RREFRESH, MSGSIZE_RREFRESH)) == NULL) {
1543
		bgp_fsm(p, EVNT_CON_FATAL);
1684
		bgp_fsm(p, EVNT_CON_FATAL);
Lines 1545-1556 session_rrefresh(struct peer *p, u_int16 Link Here
1545
	}
1686
	}
1546
1687
1547
	afi = htons(afi);
1688
	afi = htons(afi);
1548
	errs += buf_add(buf->buf, &afi, sizeof(afi));
1689
	errs += ibuf_add(buf->buf, &afi, sizeof(afi));
1549
	errs += buf_add(buf->buf, &null8, sizeof(null8));
1690
	errs += ibuf_add(buf->buf, &null8, sizeof(null8));
1550
	errs += buf_add(buf->buf, &safi, sizeof(safi));
1691
	errs += ibuf_add(buf->buf, &safi, sizeof(safi));
1551
1692
1552
	if (errs > 0) {
1693
	if (errs) {
1553
		buf_free(buf->buf);
1694
		ibuf_free(buf->buf);
1554
		free(buf);
1695
		free(buf);
1555
		bgp_fsm(p, EVNT_CON_FATAL);
1696
		bgp_fsm(p, EVNT_CON_FATAL);
1556
		return;
1697
		return;
Lines 1565-1577 session_rrefresh(struct peer *p, u_int16 Link Here
1565
}
1706
}
1566
1707
1567
int
1708
int
1709
session_graceful_restart(struct peer *p)
1710
{
1711
	u_int8_t	i;
1712
1713
	timer_set(p, Timer_RestartTimeout, p->capa.neg.grestart.timeout);
1714
1715
	for (i = 0; i < AID_MAX; i++) {
1716
		if (p->capa.neg.grestart.flags[i] & CAPA_GR_PRESENT) {
1717
			if (imsg_compose(ibuf_rde, IMSG_SESSION_STALE,
1718
			    p->conf.id, 0, -1, &i, sizeof(i)) == -1)
1719
				return (-1);
1720
			log_peer_warnx(&p->conf,
1721
			    "graceful restart of %s, keeping routes",
1722
			    aid2str(i));
1723
			p->capa.neg.grestart.flags[i] |= CAPA_GR_RESTARTING;
1724
		} else if (p->capa.neg.mp[i]) {
1725
			if (imsg_compose(ibuf_rde, IMSG_SESSION_FLUSH,
1726
			    p->conf.id, 0, -1, &i, sizeof(i)) == -1)
1727
				return (-1);
1728
			log_peer_warnx(&p->conf,
1729
			    "graceful restart of %s, flushing routes",
1730
			    aid2str(i));
1731
		}
1732
	}
1733
	return (0);
1734
}
1735
1736
int
1737
session_graceful_is_restarting(struct peer *p)
1738
{
1739
	u_int8_t	i;
1740
1741
	for (i = 0; i < AID_MAX; i++)
1742
		if (p->capa.neg.grestart.flags[i] & CAPA_GR_RESTARTING)
1743
			return (1);
1744
	return (0);
1745
}
1746
1747
int
1748
session_graceful_stop(struct peer *p)
1749
{
1750
	u_int8_t	i;
1751
1752
	for (i = 0; i < AID_MAX; i++) {
1753
		/*
1754
		 * Only flush if the peer is restarting and the peer indicated
1755
		 * it hold the forwarding state. In all other cases the
1756
		 * session was already flushed when the session came up.
1757
		 */
1758
		if (p->capa.neg.grestart.flags[i] & CAPA_GR_RESTARTING &&
1759
		    p->capa.neg.grestart.flags[i] & CAPA_GR_FORWARD) {
1760
			log_peer_warnx(&p->conf, "graceful restart of %s, "
1761
			    "time-out, flushing", aid2str(i));
1762
			if (imsg_compose(ibuf_rde, IMSG_SESSION_FLUSH,
1763
			    p->conf.id, 0, -1, &i, sizeof(i)) == -1)
1764
				return (-1);
1765
		}
1766
		p->capa.neg.grestart.flags[i] &= ~CAPA_GR_RESTARTING;
1767
	}
1768
	return (0);
1769
}
1770
1771
int
1568
session_dispatch_msg(struct pollfd *pfd, struct peer *p)
1772
session_dispatch_msg(struct pollfd *pfd, struct peer *p)
1569
{
1773
{
1570
	ssize_t		n, rpos, av, left;
1774
	ssize_t		n;
1571
	socklen_t	len;
1775
	socklen_t	len;
1572
	int		error, processed = 0;
1776
	int		error;
1573
	u_int16_t	msglen;
1574
	u_int8_t	msgtype;
1575
1777
1576
	if (p->state == STATE_CONNECT) {
1778
	if (p->state == STATE_CONNECT) {
1577
		if (pfd->revents & POLLOUT) {
1779
		if (pfd->revents & POLLOUT) {
Lines 1641-1711 session_dispatch_msg(struct pollfd *pfd, Link Here
1641
			return (1);
1843
			return (1);
1642
		}
1844
		}
1643
1845
1644
		rpos = 0;
1846
		p->rbuf->wpos += n;
1645
		av = p->rbuf->wpos + n;
1646
		p->stats.last_read = time(NULL);
1847
		p->stats.last_read = time(NULL);
1848
		return (1);
1849
	}
1850
	return (0);
1851
}
1647
1852
1648
		/*
1853
int
1649
		 * session might drop to IDLE -> buffers deallocated
1854
session_process_msg(struct peer *p)
1650
		 * we MUST check rbuf != NULL before use
1855
{
1651
		 */
1856
	ssize_t		rpos, av, left;
1652
		for (;;) {
1857
	int		processed = 0;
1653
			if (rpos + MSGSIZE_HEADER > av)
1858
	u_int16_t	msglen;
1654
				break;
1859
	u_int8_t	msgtype;
1655
			if (p->rbuf == NULL)
1656
				break;
1657
			if (parse_header(p, p->rbuf->buf + rpos, &msglen,
1658
			    &msgtype) == -1)
1659
				return (0);
1660
			if (rpos + msglen > av)
1661
				break;
1662
			p->rbuf->rptr = p->rbuf->buf + rpos;
1663
1664
			switch (msgtype) {
1665
			case OPEN:
1666
				bgp_fsm(p, EVNT_RCVD_OPEN);
1667
				p->stats.msg_rcvd_open++;
1668
				break;
1669
			case UPDATE:
1670
				bgp_fsm(p, EVNT_RCVD_UPDATE);
1671
				p->stats.msg_rcvd_update++;
1672
				break;
1673
			case NOTIFICATION:
1674
				bgp_fsm(p, EVNT_RCVD_NOTIFICATION);
1675
				p->stats.msg_rcvd_notification++;
1676
				break;
1677
			case KEEPALIVE:
1678
				bgp_fsm(p, EVNT_RCVD_KEEPALIVE);
1679
				p->stats.msg_rcvd_keepalive++;
1680
				break;
1681
			case RREFRESH:
1682
				parse_refresh(p);
1683
				p->stats.msg_rcvd_rrefresh++;
1684
				break;
1685
			default:	/* cannot happen */
1686
				session_notification(p, ERR_HEADER,
1687
				    ERR_HDR_TYPE, &msgtype, 1);
1688
				log_warnx("received message with "
1689
				    "unknown type %u", msgtype);
1690
				bgp_fsm(p, EVNT_CON_FATAL);
1691
			}
1692
			rpos += msglen;
1693
			if (++processed > MSG_PROCESS_LIMIT)
1694
				break;
1695
		}
1696
		if (p->rbuf == NULL)
1697
			return (1);
1698
1860
1699
		if (rpos < av) {
1861
	rpos = 0;
1700
			left = av - rpos;
1862
	av = p->rbuf->wpos;
1701
			memcpy(&p->rbuf->buf, p->rbuf->buf + rpos, left);
1702
			p->rbuf->wpos = left;
1703
		} else
1704
			p->rbuf->wpos = 0;
1705
1863
1706
		return (1);
1864
	/*
1865
	 * session might drop to IDLE -> buffers deallocated
1866
	 * we MUST check rbuf != NULL before use
1867
	 */
1868
	for (;;) {
1869
		if (rpos + MSGSIZE_HEADER > av)
1870
			break;
1871
		if (p->rbuf == NULL)
1872
			break;
1873
		if (parse_header(p, p->rbuf->buf + rpos, &msglen,
1874
		    &msgtype) == -1)
1875
			return (0);
1876
		if (rpos + msglen > av)
1877
			break;
1878
		p->rbuf->rptr = p->rbuf->buf + rpos;
1879
1880
		switch (msgtype) {
1881
		case OPEN:
1882
			bgp_fsm(p, EVNT_RCVD_OPEN);
1883
			p->stats.msg_rcvd_open++;
1884
			break;
1885
		case UPDATE:
1886
			bgp_fsm(p, EVNT_RCVD_UPDATE);
1887
			p->stats.msg_rcvd_update++;
1888
			break;
1889
		case NOTIFICATION:
1890
			bgp_fsm(p, EVNT_RCVD_NOTIFICATION);
1891
			p->stats.msg_rcvd_notification++;
1892
			break;
1893
		case KEEPALIVE:
1894
			bgp_fsm(p, EVNT_RCVD_KEEPALIVE);
1895
			p->stats.msg_rcvd_keepalive++;
1896
			break;
1897
		case RREFRESH:
1898
			parse_refresh(p);
1899
			p->stats.msg_rcvd_rrefresh++;
1900
			break;
1901
		default:	/* cannot happen */
1902
			session_notification(p, ERR_HEADER, ERR_HDR_TYPE,
1903
			    &msgtype, 1);
1904
			log_warnx("received message with unknown type %u",
1905
			    msgtype);
1906
			bgp_fsm(p, EVNT_CON_FATAL);
1907
		}
1908
		rpos += msglen;
1909
		if (++processed > MSG_PROCESS_LIMIT)
1910
			break;
1707
	}
1911
	}
1708
	return (0);
1912
	if (p->rbuf == NULL)
1913
		return (1);
1914
1915
	if (rpos < av) {
1916
		left = av - rpos;
1917
		memcpy(&p->rbuf->buf, p->rbuf->buf + rpos, left);
1918
		p->rbuf->wpos = left;
1919
	} else
1920
		p->rbuf->wpos = 0;
1921
1922
	return (1);
1709
}
1923
}
1710
1924
1711
int
1925
int
Lines 1853-1864 parse_open(struct peer *peer) Link Here
1853
	p += sizeof(short_as);
2067
	p += sizeof(short_as);
1854
	as = peer->short_as = ntohs(short_as);
2068
	as = peer->short_as = ntohs(short_as);
1855
2069
1856
	/* if remote-as is zero and it's a cloned neighbor, accept any */
1857
	if (peer->conf.cloned && !peer->conf.remote_as && as != AS_TRANS) {
1858
		peer->conf.remote_as = as;
1859
		peer->conf.ebgp = (peer->conf.remote_as != conf->as);
1860
	}
1861
1862
	memcpy(&oholdtime, p, sizeof(oholdtime));
2070
	memcpy(&oholdtime, p, sizeof(oholdtime));
1863
	p += sizeof(oholdtime);
2071
	p += sizeof(oholdtime);
1864
2072
Lines 1966-1971 parse_open(struct peer *peer) Link Here
1966
		}
2174
		}
1967
	}
2175
	}
1968
2176
2177
	/* if remote-as is zero and it's a cloned neighbor, accept any */
2178
	if (peer->conf.cloned && !peer->conf.remote_as && as != AS_TRANS) {
2179
		peer->conf.remote_as = as;
2180
		peer->conf.ebgp = (peer->conf.remote_as != conf->as);
2181
		if (!peer->conf.ebgp)
2182
			/* force enforce_as off for iBGP sessions */
2183
			peer->conf.enforce_as = ENFORCE_AS_OFF;
2184
	}
2185
1969
	if (peer->conf.remote_as != as) {
2186
	if (peer->conf.remote_as != as) {
1970
		log_peer_warnx(&peer->conf, "peer sent wrong AS %s",
2187
		log_peer_warnx(&peer->conf, "peer sent wrong AS %s",
1971
		    log_as(as));
2188
		    log_as(as));
Lines 1974-1979 parse_open(struct peer *peer) Link Here
1974
		return (-1);
2191
		return (-1);
1975
	}
2192
	}
1976
2193
2194
	if (capa_neg_calc(peer) == -1) {
2195
		log_peer_warnx(&peer->conf,
2196
		    "capability negotiation calculation failed");
2197
		session_notification(peer, ERR_OPEN, 0, NULL, 0);
2198
		change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN);
2199
		return (-1);
2200
	}
2201
1977
	return (0);
2202
	return (0);
1978
}
2203
}
1979
2204
Lines 2008-2031 int Link Here
2008
parse_refresh(struct peer *peer)
2233
parse_refresh(struct peer *peer)
2009
{
2234
{
2010
	u_char		*p;
2235
	u_char		*p;
2011
	struct rrefresh	 r;
2236
	u_int16_t	 afi;
2237
	u_int8_t	 aid, safi;
2012
2238
2013
	p = peer->rbuf->rptr;
2239
	p = peer->rbuf->rptr;
2014
	p += MSGSIZE_HEADER;	/* header is already checked */
2240
	p += MSGSIZE_HEADER;	/* header is already checked */
2015
2241
2242
	/*
2243
	 * We could check if we actually announced the capability but
2244
	 * as long as the message is correctly encoded we don't care.
2245
	 */
2246
2016
	/* afi, 2 byte */
2247
	/* afi, 2 byte */
2017
	memcpy(&r.afi, p, sizeof(r.afi));
2248
	memcpy(&afi, p, sizeof(afi));
2018
	r.afi = ntohs(r.afi);
2249
	afi = ntohs(afi);
2019
	p += 2;
2250
	p += 2;
2020
	/* reserved, 1 byte */
2251
	/* reserved, 1 byte */
2021
	p += 1;
2252
	p += 1;
2022
	/* safi, 1 byte */
2253
	/* safi, 1 byte */
2023
	memcpy(&r.safi, p, sizeof(r.safi));
2254
	memcpy(&safi, p, sizeof(safi));
2024
2255
2025
	/* afi/safi unchecked -	unrecognized values will be ignored anyway */
2256
	/* afi/safi unchecked -	unrecognized values will be ignored anyway */
2257
	if (afi2aid(afi, safi, &aid) == -1) {
2258
		log_peer_warnx(&peer->conf, "peer sent bad refresh, "
2259
		    "invalid afi/safi pair");
2260
		return (0);
2261
	}
2026
2262
2027
	if (imsg_compose(ibuf_rde, IMSG_REFRESH, peer->conf.id, 0, -1, &r,
2263
	if (imsg_compose(ibuf_rde, IMSG_REFRESH, peer->conf.id, 0, -1, &aid,
2028
	    sizeof(r)) == -1)
2264
	    sizeof(aid)) == -1)
2029
		return (-1);
2265
		return (-1);
2030
2266
2031
	return (0);
2267
	return (0);
Lines 2035-2045 int Link Here
2035
parse_notification(struct peer *peer)
2271
parse_notification(struct peer *peer)
2036
{
2272
{
2037
	u_char		*p;
2273
	u_char		*p;
2274
	u_int16_t	 datalen;
2038
	u_int8_t	 errcode;
2275
	u_int8_t	 errcode;
2039
	u_int8_t	 subcode;
2276
	u_int8_t	 subcode;
2040
	u_int16_t	 datalen;
2041
	u_int8_t	 capa_code;
2277
	u_int8_t	 capa_code;
2042
	u_int8_t	 capa_len;
2278
	u_int8_t	 capa_len;
2279
	u_int8_t	 i;
2043
2280
2044
	/* just log */
2281
	/* just log */
2045
	p = peer->rbuf->rptr;
2282
	p = peer->rbuf->rptr;
Lines 2059-2065 parse_notification(struct peer *peer) Link Here
2059
	p += sizeof(subcode);
2296
	p += sizeof(subcode);
2060
	datalen -= sizeof(subcode);
2297
	datalen -= sizeof(subcode);
2061
2298
2062
	log_notification(peer, errcode, subcode, p, datalen);
2299
	log_notification(peer, errcode, subcode, p, datalen, "received");
2063
	peer->errcnt++;
2300
	peer->errcnt++;
2064
2301
2065
	if (errcode == ERR_OPEN && subcode == ERR_OPEN_CAPA) {
2302
	if (errcode == ERR_OPEN && subcode == ERR_OPEN_CAPA) {
Lines 2094-2101 parse_notification(struct peer *peer) Link Here
2094
			datalen -= capa_len;
2331
			datalen -= capa_len;
2095
			switch (capa_code) {
2332
			switch (capa_code) {
2096
			case CAPA_MP:
2333
			case CAPA_MP:
2097
				peer->capa.ann.mp_v4 = SAFI_NONE;
2334
				for (i = 0; i < AID_MAX; i++)
2098
				peer->capa.ann.mp_v6 = SAFI_NONE;
2335
					peer->capa.ann.mp[i] = 0;
2099
				log_peer_warnx(&peer->conf,
2336
				log_peer_warnx(&peer->conf,
2100
				    "disabling multiprotocol capability");
2337
				    "disabling multiprotocol capability");
2101
				break;
2338
				break;
Lines 2105-2111 parse_notification(struct peer *peer) Link Here
2105
				    "disabling route refresh capability");
2342
				    "disabling route refresh capability");
2106
				break;
2343
				break;
2107
			case CAPA_RESTART:
2344
			case CAPA_RESTART:
2108
				peer->capa.ann.restart = 0;
2345
				peer->capa.ann.grestart.restart = 0;
2109
				log_peer_warnx(&peer->conf,
2346
				log_peer_warnx(&peer->conf,
2110
				    "disabling restart capability");
2347
				    "disabling restart capability");
2111
				break;
2348
				break;
Lines 2139-2157 parse_notification(struct peer *peer) Link Here
2139
int
2376
int
2140
parse_capabilities(struct peer *peer, u_char *d, u_int16_t dlen, u_int32_t *as)
2377
parse_capabilities(struct peer *peer, u_char *d, u_int16_t dlen, u_int32_t *as)
2141
{
2378
{
2379
	u_char		*capa_val;
2380
	u_int32_t	 remote_as;
2142
	u_int16_t	 len;
2381
	u_int16_t	 len;
2382
	u_int16_t	 afi;
2383
	u_int16_t	 gr_header;
2384
	u_int8_t	 safi;
2385
	u_int8_t	 aid;
2386
	u_int8_t	 gr_flags;
2143
	u_int8_t	 capa_code;
2387
	u_int8_t	 capa_code;
2144
	u_int8_t	 capa_len;
2388
	u_int8_t	 capa_len;
2145
	u_char		*capa_val;
2389
	u_int8_t	 i;
2146
	u_int16_t	 mp_afi;
2147
	u_int8_t	 mp_safi;
2148
	u_int32_t	 remote_as;
2149
2390
2150
	len = dlen;
2391
	len = dlen;
2151
	while (len > 0) {
2392
	while (len > 0) {
2152
		if (len < 2) {
2393
		if (len < 2) {
2153
			log_peer_warnx(&peer->conf, "parse_capabilities: "
2394
			log_peer_warnx(&peer->conf, "Bad capabilities attr "
2154
			    "expect len >= 2, len is %u", len);
2395
			    "length: %u, too short", len);
2155
			return (-1);
2396
			return (-1);
2156
		}
2397
		}
2157
		memcpy(&capa_code, d, sizeof(capa_code));
2398
		memcpy(&capa_code, d, sizeof(capa_code));
Lines 2163-2169 parse_capabilities(struct peer *peer, u_ Link Here
2163
		if (capa_len > 0) {
2404
		if (capa_len > 0) {
2164
			if (len < capa_len) {
2405
			if (len < capa_len) {
2165
				log_peer_warnx(&peer->conf,
2406
				log_peer_warnx(&peer->conf,
2166
				    "parse_capabilities: "
2407
				    "Bad capabilities attr length: "
2167
				    "len %u smaller than capa_len %u",
2408
				    "len %u smaller than capa_len %u",
2168
				    len, capa_len);
2409
				    len, capa_len);
2169
				return (-1);
2410
				return (-1);
Lines 2178-2224 parse_capabilities(struct peer *peer, u_ Link Here
2178
		case CAPA_MP:			/* RFC 4760 */
2419
		case CAPA_MP:			/* RFC 4760 */
2179
			if (capa_len != 4) {
2420
			if (capa_len != 4) {
2180
				log_peer_warnx(&peer->conf,
2421
				log_peer_warnx(&peer->conf,
2181
				    "parse_capabilities: "
2422
				    "Bad multi protocol capability length: "
2182
				    "expect len 4, len is %u", capa_len);
2423
				    "%u", capa_len);
2183
				return (-1);
2184
			}
2185
			memcpy(&mp_afi, capa_val, sizeof(mp_afi));
2186
			mp_afi = ntohs(mp_afi);
2187
			memcpy(&mp_safi, capa_val + 3, sizeof(mp_safi));
2188
			switch (mp_afi) {
2189
			case AFI_IPv4:
2190
				if (mp_safi < 1 || mp_safi > 3)
2191
					log_peer_warnx(&peer->conf,
2192
					    "parse_capabilities: AFI IPv4, "
2193
					    "mp_safi %u unknown", mp_safi);
2194
				else
2195
					peer->capa.peer.mp_v4 = mp_safi;
2196
				break;
2424
				break;
2197
			case AFI_IPv6:
2425
			}
2198
				if (mp_safi < 1 || mp_safi > 3)
2426
			memcpy(&afi, capa_val, sizeof(afi));
2199
					log_peer_warnx(&peer->conf,
2427
			afi = ntohs(afi);
2200
					    "parse_capabilities: AFI IPv6, "
2428
			memcpy(&safi, capa_val + 3, sizeof(safi));
2201
					    "mp_safi %u unknown", mp_safi);
2429
			if (afi2aid(afi, safi, &aid) == -1) {
2202
				else
2430
				log_peer_warnx(&peer->conf,
2203
					peer->capa.peer.mp_v6 = mp_safi;
2431
				    "Received multi protocol capability: "
2204
				break;
2432
				    " unknown AFI %u, safi %u pair",
2205
			default:			/* ignore */
2433
				    afi, safi);
2206
				break;
2434
				break;
2207
			}
2435
			}
2436
			peer->capa.peer.mp[aid] = 1;
2208
			break;
2437
			break;
2209
		case CAPA_REFRESH:
2438
		case CAPA_REFRESH:
2210
			peer->capa.peer.refresh = 1;
2439
			peer->capa.peer.refresh = 1;
2211
			break;
2440
			break;
2212
		case CAPA_RESTART:
2441
		case CAPA_RESTART:
2213
			peer->capa.peer.restart = 1;
2442
			if (capa_len == 2) {
2214
			/* we don't care about the further restart capas yet */
2443
				/* peer only supports EoR marker */
2444
				peer->capa.peer.grestart.restart = 1;
2445
				peer->capa.peer.grestart.timeout = 0;
2446
				break;
2447
			} else if (capa_len % 4 != 2) {
2448
				log_peer_warnx(&peer->conf,
2449
				    "Bad graceful restart capability length: "
2450
				    "%u", capa_len);
2451
				peer->capa.peer.grestart.restart = 0;
2452
				peer->capa.peer.grestart.timeout = 0;
2453
				break;
2454
			}
2455
2456
			memcpy(&gr_header, capa_val, sizeof(gr_header));
2457
			gr_header = ntohs(gr_header);
2458
			peer->capa.peer.grestart.timeout =
2459
			    gr_header & CAPA_GR_TIMEMASK;
2460
			if (peer->capa.peer.grestart.timeout == 0) {
2461
				log_peer_warnx(&peer->conf, "Received "
2462
				    "graceful restart timeout is zero");
2463
				peer->capa.peer.grestart.restart = 0;
2464
				break;
2465
			}
2466
2467
			for (i = 2; i <= capa_len - 4; i += 4) {
2468
				memcpy(&afi, capa_val + i, sizeof(afi));
2469
				afi = ntohs(afi);
2470
				memcpy(&safi, capa_val + i + 2, sizeof(safi));
2471
				if (afi2aid(afi, safi, &aid) == -1) {
2472
					log_peer_warnx(&peer->conf,
2473
					    "Received graceful restart capa: "
2474
					    " unknown AFI %u, safi %u pair",
2475
					    afi, safi);
2476
					continue;
2477
				}
2478
				memcpy(&gr_flags, capa_val + i + 3,
2479
				    sizeof(gr_flags));
2480
				peer->capa.peer.grestart.flags[aid] |=
2481
				    CAPA_GR_PRESENT;
2482
				if (gr_flags & CAPA_GR_F_FLAG)
2483
					peer->capa.peer.grestart.flags[aid] |=
2484
					    CAPA_GR_FORWARD;
2485
				if (gr_header & CAPA_GR_R_FLAG)
2486
					peer->capa.peer.grestart.flags[aid] |=
2487
					    CAPA_GR_RESTART;
2488
				peer->capa.peer.grestart.restart = 2;
2489
			}
2215
			break;
2490
			break;
2216
		case CAPA_AS4BYTE:
2491
		case CAPA_AS4BYTE:
2217
			if (capa_len != 4) {
2492
			if (capa_len != 4) {
2218
				log_peer_warnx(&peer->conf,
2493
				log_peer_warnx(&peer->conf,
2219
				    "parse_capabilities: "
2494
				    "Bad AS4BYTE capability length: "
2220
				    "expect len 4, len is %u", capa_len);
2495
				    "%u", capa_len);
2221
				return (-1);
2496
				peer->capa.peer.as4byte = 0;
2497
				break;
2222
			}
2498
			}
2223
			memcpy(&remote_as, capa_val, sizeof(remote_as));
2499
			memcpy(&remote_as, capa_val, sizeof(remote_as));
2224
			*as = ntohl(remote_as);
2500
			*as = ntohl(remote_as);
Lines 2232-2237 parse_capabilities(struct peer *peer, u_ Link Here
2232
	return (0);
2508
	return (0);
2233
}
2509
}
2234
2510
2511
int
2512
capa_neg_calc(struct peer *p)
2513
{
2514
	u_int8_t	i, hasmp = 0;
2515
2516
	/* refresh: does not realy matter here, use peer setting */
2517
	p->capa.neg.refresh = p->capa.peer.refresh;
2518
2519
	/* as4byte: both side must announce capability */
2520
	if (p->capa.ann.as4byte && p->capa.peer.as4byte)
2521
		p->capa.neg.as4byte = 1;
2522
	else
2523
		p->capa.neg.as4byte = 0;
2524
2525
	/* MP: both side must announce capability */
2526
	for (i = 0; i < AID_MAX; i++) {
2527
		if (p->capa.ann.mp[i] && p->capa.peer.mp[i]) {
2528
			p->capa.neg.mp[i] = 1;
2529
			hasmp = 1;
2530
		} else
2531
			p->capa.neg.mp[i] = 0;
2532
	}
2533
	/* if no MP capability present default to IPv4 unicast mode */
2534
	if (!hasmp)
2535
		p->capa.neg.mp[AID_INET] = 1;
2536
2537
	/*
2538
	 * graceful restart: only the peer capabilities are of interest here.
2539
	 * It is necessary to compare the new values with the previous ones
2540
	 * and act acordingly. AFI/SAFI that are not part in the MP capability
2541
	 * are treated as not being present.
2542
	 */
2543
2544
	for (i = 0; i < AID_MAX; i++) {
2545
		/* disable GR if the AFI/SAFI is not present */
2546
		if (p->capa.peer.grestart.flags[i] & CAPA_GR_PRESENT &&
2547
		    p->capa.neg.mp[i] == 0)
2548
			p->capa.peer.grestart.flags[i] = 0;	/* disable */
2549
		/* look at current GR state and decide what to do */
2550
		if (p->capa.neg.grestart.flags[i] & CAPA_GR_RESTARTING) {
2551
			if (!(p->capa.peer.grestart.flags[i] &
2552
			    CAPA_GR_FORWARD)) {
2553
				if (imsg_compose(ibuf_rde, IMSG_SESSION_FLUSH,
2554
				    p->conf.id, 0, -1, &i, sizeof(i)) == -1)
2555
					return (-1);
2556
				log_peer_warnx(&p->conf, "graceful restart of "
2557
				    "%s, not restarted, flushing", aid2str(i));
2558
			}
2559
			p->capa.neg.grestart.flags[i] =
2560
			    p->capa.peer.grestart.flags[i] | CAPA_GR_RESTARTING;
2561
		} else
2562
			p->capa.neg.grestart.flags[i] =
2563
			    p->capa.peer.grestart.flags[i];
2564
	}
2565
	p->capa.neg.grestart.timeout = p->capa.peer.grestart.timeout;
2566
	p->capa.neg.grestart.restart = p->capa.peer.grestart.restart;
2567
2568
	return (0);
2569
}
2570
2235
void
2571
void
2236
session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
2572
session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
2237
{
2573
{
Lines 2244-2251 session_dispatch_imsg(struct imsgbuf *ib Link Here
2244
	struct kif		*kif;
2580
	struct kif		*kif;
2245
	u_char			*data;
2581
	u_char			*data;
2246
	enum reconf_action	 reconf;
2582
	enum reconf_action	 reconf;
2247
	int			 n, depend_ok;
2583
	int			 n, depend_ok, restricted;
2248
	u_int8_t		 errcode, subcode;
2584
	u_int8_t		 aid, errcode, subcode;
2249
2585
2250
	if ((n = imsg_read(ibuf)) == -1)
2586
	if ((n = imsg_read(ibuf)) == -1)
2251
		fatal("session_dispatch_imsg: imsg_read error");
2587
		fatal("session_dispatch_imsg: imsg_read error");
Lines 2332-2346 session_dispatch_imsg(struct imsgbuf *ib Link Here
2332
			}
2668
			}
2333
2669
2334
			break;
2670
			break;
2671
		case IMSG_RECONF_CTRL:
2672
			if (idx != PFD_PIPE_MAIN)
2673
				fatalx("reconf request not from parent");
2674
			if (imsg.hdr.len != IMSG_HEADER_SIZE +
2675
			    sizeof(restricted))
2676
				fatalx("IFINFO imsg with wrong len");
2677
			memcpy(&restricted, imsg.data, sizeof(restricted));
2678
			if (imsg.fd == -1) {
2679
				log_warnx("expected to receive fd for control "
2680
				    "socket but didn't receive any");
2681
				break;
2682
			}
2683
			if (restricted) {
2684
				control_shutdown(rcsock);
2685
				rcsock = imsg.fd;
2686
				control_listen(rcsock);
2687
			} else {
2688
				control_shutdown(csock);
2689
				csock = imsg.fd;
2690
				control_listen(csock);
2691
			}
2692
			break;
2335
		case IMSG_RECONF_DONE:
2693
		case IMSG_RECONF_DONE:
2336
			if (idx != PFD_PIPE_MAIN)
2694
			if (idx != PFD_PIPE_MAIN)
2337
				fatalx("reconf request not from parent");
2695
				fatalx("reconf request not from parent");
2338
			if (nconf == NULL)
2696
			if (nconf == NULL)
2339
				fatalx("got IMSG_RECONF_DONE but no config");
2697
				fatalx("got IMSG_RECONF_DONE but no config");
2698
			conf->flags = nconf->flags;
2699
			conf->log = nconf->log;
2700
			conf->bgpid = nconf->bgpid;
2701
			conf->clusterid = nconf->clusterid;
2340
			conf->as = nconf->as;
2702
			conf->as = nconf->as;
2703
			conf->short_as = nconf->short_as;
2341
			conf->holdtime = nconf->holdtime;
2704
			conf->holdtime = nconf->holdtime;
2342
			conf->bgpid = nconf->bgpid;
2343
			conf->min_holdtime = nconf->min_holdtime;
2705
			conf->min_holdtime = nconf->min_holdtime;
2706
			conf->connectretry = nconf->connectretry;
2344
2707
2345
			/* add new peers */
2708
			/* add new peers */
2346
			for (p = npeers; p != NULL; p = next) {
2709
			for (p = npeers; p != NULL; p = next) {
Lines 2388-2393 session_dispatch_imsg(struct imsgbuf *ib Link Here
2388
			nconf = NULL;
2751
			nconf = NULL;
2389
			pending_reconf = 0;
2752
			pending_reconf = 0;
2390
			log_info("SE reconfigured");
2753
			log_info("SE reconfigured");
2754
			imsg_compose(ibuf_main, IMSG_RECONF_DONE, 0, 0,
2755
			    -1, NULL, 0);
2391
			break;
2756
			break;
2392
		case IMSG_IFINFO:
2757
		case IMSG_IFINFO:
2393
			if (idx != PFD_PIPE_MAIN)
2758
			if (idx != PFD_PIPE_MAIN)
Lines 2397-2405 session_dispatch_imsg(struct imsgbuf *ib Link Here
2397
				fatalx("IFINFO imsg with wrong len");
2762
				fatalx("IFINFO imsg with wrong len");
2398
			kif = imsg.data;
2763
			kif = imsg.data;
2399
			depend_ok = (kif->flags & IFF_UP) &&
2764
			depend_ok = (kif->flags & IFF_UP) &&
2400
			    (LINK_STATE_IS_UP(kif->link_state) ||
2765
			    LINK_STATE_IS_UP(kif->link_state);
2401
			    (kif->link_state == LINK_STATE_UNKNOWN &&
2402
			    kif->media_type != IFT_CARP));
2403
2766
2404
			for (p = peers; p != NULL; p = p->next)
2767
			for (p = peers; p != NULL; p = p->next)
2405
				if (!strcmp(p->conf.if_depend, kif->ifname)) {
2768
				if (!strcmp(p->conf.if_depend, kif->ifname)) {
Lines 2408-2414 session_dispatch_imsg(struct imsgbuf *ib Link Here
2408
						bgp_fsm(p, EVNT_START);
2771
						bgp_fsm(p, EVNT_START);
2409
					} else if (!depend_ok && p->depend_ok) {
2772
					} else if (!depend_ok && p->depend_ok) {
2410
						p->depend_ok = depend_ok;
2773
						p->depend_ok = depend_ok;
2411
						bgp_fsm(p, EVNT_STOP);
2774
						session_stop(p,
2775
						    ERR_CEASE_OTHER_CHANGE);
2412
					}
2776
					}
2413
				}
2777
				}
2414
			break;
2778
			break;
Lines 2456-2465 session_dispatch_imsg(struct imsgbuf *ib Link Here
2456
			}
2820
			}
2457
			break;
2821
			break;
2458
		case IMSG_CTL_KROUTE:
2822
		case IMSG_CTL_KROUTE:
2459
		case IMSG_CTL_KROUTE6:
2460
		case IMSG_CTL_KROUTE_ADDR:
2823
		case IMSG_CTL_KROUTE_ADDR:
2461
		case IMSG_CTL_SHOW_NEXTHOP:
2824
		case IMSG_CTL_SHOW_NEXTHOP:
2462
		case IMSG_CTL_SHOW_INTERFACE:
2825
		case IMSG_CTL_SHOW_INTERFACE:
2826
		case IMSG_CTL_SHOW_FIB_TABLES:
2463
			if (idx != PFD_PIPE_MAIN)
2827
			if (idx != PFD_PIPE_MAIN)
2464
				fatalx("ctl kroute request not from parent");
2828
				fatalx("ctl kroute request not from parent");
2465
			control_imsg_relay(&imsg);
2829
			control_imsg_relay(&imsg);
Lines 2469-2475 session_dispatch_imsg(struct imsgbuf *ib Link Here
2469
		case IMSG_CTL_SHOW_RIB_ATTR:
2833
		case IMSG_CTL_SHOW_RIB_ATTR:
2470
		case IMSG_CTL_SHOW_RIB_MEM:
2834
		case IMSG_CTL_SHOW_RIB_MEM:
2471
		case IMSG_CTL_SHOW_NETWORK:
2835
		case IMSG_CTL_SHOW_NETWORK:
2472
		case IMSG_CTL_SHOW_NETWORK6:
2473
		case IMSG_CTL_SHOW_NEIGHBOR:
2836
		case IMSG_CTL_SHOW_NEIGHBOR:
2474
			if (idx != PFD_PIPE_ROUTE_CTL)
2837
			if (idx != PFD_PIPE_ROUTE_CTL)
2475
				fatalx("ctl rib request not from RDE");
2838
				fatalx("ctl rib request not from RDE");
Lines 2531-2536 session_dispatch_imsg(struct imsgbuf *ib Link Here
2531
				break;
2894
				break;
2532
			}
2895
			}
2533
			break;
2896
			break;
2897
		case IMSG_SESSION_RESTARTED:
2898
			if (idx != PFD_PIPE_ROUTE)
2899
				fatalx("update request not from RDE");
2900
			if (imsg.hdr.len < IMSG_HEADER_SIZE + sizeof(aid)) {
2901
				log_warnx("RDE sent invalid restart msg");
2902
				break;
2903
			}
2904
			if ((p = getpeerbyid(imsg.hdr.peerid)) == NULL) {
2905
				log_warnx("no such peer: id=%u",
2906
				    imsg.hdr.peerid);
2907
				break;
2908
			}
2909
			memcpy(&aid, imsg.data, sizeof(aid));
2910
			if (aid >= AID_MAX)
2911
				fatalx("IMSG_SESSION_RESTARTED: bad AID");
2912
			if (p->capa.neg.grestart.flags[aid] &
2913
			    CAPA_GR_RESTARTING &&
2914
			    p->capa.neg.grestart.flags[aid] &
2915
			    CAPA_GR_FORWARD) {
2916
				log_peer_warnx(&p->conf,
2917
				    "graceful restart of %s finished",
2918
				    aid2str(aid));
2919
				p->capa.neg.grestart.flags[aid] &=
2920
				    ~CAPA_GR_RESTARTING;
2921
				timer_stop(p, Timer_RestartTimeout);
2922
2923
				/* signal back to RDE to cleanup stale routes */
2924
				if (imsg_compose(ibuf_rde,
2925
				    IMSG_SESSION_RESTARTED, imsg.hdr.peerid, 0,
2926
				    -1, &aid, sizeof(aid)) == -1)
2927
					fatal("imsg_compose: "
2928
					    "IMSG_SESSION_RESTARTED");
2929
			}
2930
			break;
2534
		default:
2931
		default:
2535
			break;
2932
			break;
2536
		}
2933
		}
Lines 2612-2640 getpeerbydesc(const char *descr) Link Here
2612
struct peer *
3009
struct peer *
2613
getpeerbyip(struct sockaddr *ip)
3010
getpeerbyip(struct sockaddr *ip)
2614
{
3011
{
3012
	struct bgpd_addr addr;
2615
	struct peer	*p, *newpeer, *loose = NULL;
3013
	struct peer	*p, *newpeer, *loose = NULL;
2616
	u_int32_t	 id;
3014
	u_int32_t	 id;
2617
3015
3016
	sa2addr(ip, &addr);
3017
2618
	/* we might want a more effective way to find peers by IP */
3018
	/* we might want a more effective way to find peers by IP */
2619
	for (p = peers; p != NULL; p = p->next)
3019
	for (p = peers; p != NULL; p = p->next)
2620
		if (!p->conf.template &&
3020
		if (!p->conf.template &&
2621
		    p->conf.remote_addr.af == ip->sa_family) {
3021
		    !memcmp(&addr, &p->conf.remote_addr, sizeof(addr)))
2622
			if (p->conf.remote_addr.af == AF_INET &&
3022
			return (p);
2623
			    p->conf.remote_addr.v4.s_addr ==
2624
			    ((struct sockaddr_in *)ip)->sin_addr.s_addr)
2625
				return (p);
2626
			if (p->conf.remote_addr.af == AF_INET6 &&
2627
			    !bcmp(&p->conf.remote_addr.v6,
2628
			    &((struct sockaddr_in6 *)ip)->sin6_addr,
2629
			    sizeof(p->conf.remote_addr.v6)))
2630
				return (p);
2631
		}
2632
3023
2633
	/* try template matching */
3024
	/* try template matching */
2634
	for (p = peers; p != NULL; p = p->next)
3025
	for (p = peers; p != NULL; p = p->next)
2635
		if (p->conf.template &&
3026
		if (p->conf.template &&
2636
		    p->conf.remote_addr.af == ip->sa_family &&
3027
		    p->conf.remote_addr.aid == addr.aid &&
2637
		    session_match_mask(p, ip))
3028
		    session_match_mask(p, &addr))
2638
			if (loose == NULL || loose->conf.remote_masklen <
3029
			if (loose == NULL || loose->conf.remote_masklen <
2639
			    p->conf.remote_masklen)
3030
			    p->conf.remote_masklen)
2640
				loose = p;
3031
				loose = p;
Lines 2653-2673 getpeerbyip(struct sockaddr *ip) Link Here
2653
				break;
3044
				break;
2654
			}
3045
			}
2655
		}
3046
		}
2656
		if (newpeer->conf.remote_addr.af == AF_INET) {
3047
		sa2addr(ip, &newpeer->conf.remote_addr);
2657
			newpeer->conf.remote_addr.v4.s_addr =
3048
		switch (ip->sa_family) {
2658
			    ((struct sockaddr_in *)ip)->sin_addr.s_addr;
3049
		case AF_INET:
2659
			newpeer->conf.remote_masklen = 32;
3050
			newpeer->conf.remote_masklen = 32;
2660
		}
3051
			break;
2661
		if (newpeer->conf.remote_addr.af == AF_INET6) {
3052
		case AF_INET6:
2662
			memcpy(&p->conf.remote_addr.v6,
2663
			    &((struct sockaddr_in6 *)ip)->sin6_addr,
2664
			    sizeof(newpeer->conf.remote_addr.v6));
2665
			newpeer->conf.remote_masklen = 128;
3053
			newpeer->conf.remote_masklen = 128;
3054
			break;
2666
		}
3055
		}
2667
		newpeer->conf.template = 0;
3056
		newpeer->conf.template = 0;
2668
		newpeer->conf.cloned = 1;
3057
		newpeer->conf.cloned = 1;
2669
		newpeer->state = newpeer->prev_state = STATE_NONE;
3058
		newpeer->state = newpeer->prev_state = STATE_NONE;
2670
		newpeer->conf.reconf_action = RECONF_REINIT;
3059
		newpeer->conf.reconf_action = RECONF_KEEP;
2671
		newpeer->rbuf = NULL;
3060
		newpeer->rbuf = NULL;
2672
		init_peer(newpeer);
3061
		init_peer(newpeer);
2673
		bgp_fsm(newpeer, EVNT_START);
3062
		bgp_fsm(newpeer, EVNT_START);
Lines 2680-2719 getpeerbyip(struct sockaddr *ip) Link Here
2680
}
3069
}
2681
3070
2682
int
3071
int
2683
session_match_mask(struct peer *p, struct sockaddr *ip)
3072
session_match_mask(struct peer *p, struct bgpd_addr *a)
2684
{
3073
{
2685
	int		 i;
2686
	in_addr_t	 v4mask;
3074
	in_addr_t	 v4mask;
2687
	struct in6_addr	*in;
3075
	struct in6_addr	 masked;
2688
	struct in6_addr	 mask;
2689
3076
2690
	if (p->conf.remote_addr.af == AF_INET) {
3077
	switch (p->conf.remote_addr.aid) {
3078
	case AID_INET:
2691
		v4mask = htonl(prefixlen2mask(p->conf.remote_masklen));
3079
		v4mask = htonl(prefixlen2mask(p->conf.remote_masklen));
2692
		if (p->conf.remote_addr.v4.s_addr ==
3080
		if (p->conf.remote_addr.v4.s_addr == (a->v4.s_addr & v4mask))
2693
		    ((((struct sockaddr_in *)ip)->sin_addr.s_addr) & v4mask))
2694
			return (1);
3081
			return (1);
2695
		else
3082
		return (0);
2696
			return (0);
3083
	case AID_INET6:
2697
	}
3084
		inet6applymask(&masked, &a->v6, p->conf.remote_masklen);
2698
2699
	if (p->conf.remote_addr.af == AF_INET6) {
2700
		bzero(&mask, sizeof(mask));
2701
		for (i = 0; i < p->conf.remote_masklen / 8; i++)
2702
			mask.s6_addr[i] = 0xff;
2703
		i = p->conf.remote_masklen % 8;
2704
		if (i)
2705
			mask.s6_addr[p->conf.remote_masklen / 8] = 0xff00 >> i;
2706
2707
		in = &((struct sockaddr_in6 *)ip)->sin6_addr;
2708
2709
		for (i = 0; i < 16; i++)
2710
			if ((in->s6_addr[i] & mask.s6_addr[i]) !=
2711
			    p->conf.remote_addr.addr8[i])
2712
				return (0);
2713
3085
2714
		return (1);
3086
		if (!memcmp(&masked, &p->conf.remote_addr.v6, sizeof(masked)))
3087
			return (1);
3088
		return (0);
2715
	}
3089
	}
2716
2717
	return (0);
3090
	return (0);
2718
}
3091
}
2719
3092
Lines 2733-2738 getpeerbyid(u_int32_t peerid) Link Here
2733
void
3106
void
2734
session_down(struct peer *peer)
3107
session_down(struct peer *peer)
2735
{
3108
{
3109
	bzero(&peer->capa.neg, sizeof(peer->capa.neg));
2736
	peer->stats.last_updown = time(NULL);
3110
	peer->stats.last_updown = time(NULL);
2737
	if (imsg_compose(ibuf_rde, IMSG_SESSION_DOWN, peer->conf.id, 0, -1,
3111
	if (imsg_compose(ibuf_rde, IMSG_SESSION_DOWN, peer->conf.id, 0, -1,
2738
	    NULL, 0) == -1)
3112
	    NULL, 0) == -1)
Lines 2744-2782 session_up(struct peer *p) Link Here
2744
{
3118
{
2745
	struct session_up	 sup;
3119
	struct session_up	 sup;
2746
3120
2747
	if (imsg_compose(ibuf_rde, IMSG_SESSION_ADD, p->conf.id, 0, -1,
3121
	if (!session_graceful_is_restarting(p))
2748
	    &p->conf, sizeof(p->conf)) == -1)
3122
		if (imsg_compose(ibuf_rde, IMSG_SESSION_ADD, p->conf.id, 0, -1,
2749
		fatalx("imsg_compose error");
3123
		    &p->conf, sizeof(p->conf)) == -1)
3124
			fatalx("imsg_compose error");
2750
3125
2751
	switch (p->sa_local.ss_family) {
3126
	sa2addr((struct sockaddr *)&p->sa_local, &sup.local_addr);
2752
	case AF_INET:
3127
	sa2addr((struct sockaddr *)&p->sa_remote, &sup.remote_addr);
2753
		sup.local_addr.af = AF_INET;
2754
		memcpy(&sup.local_addr.v4,
2755
		    &((struct sockaddr_in *)&p->sa_local)->sin_addr,
2756
		    sizeof(sup.local_addr.v4));
2757
		sup.remote_addr.af = AF_INET;
2758
		memcpy(&sup.remote_addr.v4,
2759
		    &((struct sockaddr_in *)&p->sa_remote)->sin_addr,
2760
		    sizeof(sup.remote_addr.v4));
2761
		break;
2762
	case AF_INET6:
2763
		sup.local_addr.af = AF_INET6;
2764
		memcpy(&sup.local_addr.v6,
2765
		    &((struct sockaddr_in6 *)&p->sa_local)->sin6_addr,
2766
		    sizeof(sup.local_addr.v6));
2767
		sup.remote_addr.af = AF_INET6;
2768
		memcpy(&sup.remote_addr.v6,
2769
		    &((struct sockaddr_in6 *)&p->sa_remote)->sin6_addr,
2770
		    sizeof(sup.remote_addr.v6));
2771
		break;
2772
	default:
2773
		fatalx("session_up: unsupported address family");
2774
	}
2775
3128
2776
	sup.remote_bgpid = p->remote_bgpid;
3129
	sup.remote_bgpid = p->remote_bgpid;
2777
	sup.short_as = p->short_as;
3130
	sup.short_as = p->short_as;
2778
	memcpy(&sup.capa_announced, &p->capa.ann, sizeof(sup.capa_announced));
3131
	memcpy(&sup.capa, &p->capa.neg, sizeof(sup.capa));
2779
	memcpy(&sup.capa_received, &p->capa.peer, sizeof(sup.capa_received));
2780
	p->stats.last_updown = time(NULL);
3132
	p->stats.last_updown = time(NULL);
2781
	if (imsg_compose(ibuf_rde, IMSG_SESSION_UP, p->conf.id, 0, -1,
3133
	if (imsg_compose(ibuf_rde, IMSG_SESSION_UP, p->conf.id, 0, -1,
2782
	    &sup, sizeof(sup)) == -1)
3134
	    &sup, sizeof(sup)) == -1)
Lines 2784-2792 session_up(struct peer *p) Link Here
2784
}
3136
}
2785
3137
2786
int
3138
int
2787
imsg_compose_parent(int type, pid_t pid, void *data, u_int16_t datalen)
3139
imsg_compose_parent(int type, u_int32_t peerid, pid_t pid, void *data,
3140
    u_int16_t datalen)
2788
{
3141
{
2789
	return (imsg_compose(ibuf_main, type, 0, pid, -1, data, datalen));
3142
	return (imsg_compose(ibuf_main, type, peerid, pid, -1, data, datalen));
2790
}
3143
}
2791
3144
2792
int
3145
int
Lines 2795-2828 imsg_compose_rde(int type, pid_t pid, vo Link Here
2795
	return (imsg_compose(ibuf_rde, type, 0, pid, -1, data, datalen));
3148
	return (imsg_compose(ibuf_rde, type, 0, pid, -1, data, datalen));
2796
}
3149
}
2797
3150
2798
static struct sockaddr *
2799
addr2sa(struct bgpd_addr *addr, u_int16_t port)
2800
{
2801
	static struct sockaddr_storage	 ss;
2802
	struct sockaddr_in		*sa_in = (struct sockaddr_in *)&ss;
2803
	struct sockaddr_in6		*sa_in6 = (struct sockaddr_in6 *)&ss;
2804
2805
	bzero(&ss, sizeof(ss));
2806
	switch (addr->af) {
2807
	case AF_INET:
2808
		sa_in->sin_family = AF_INET;
2809
		sa_in->sin_len = sizeof(struct sockaddr_in);
2810
		sa_in->sin_addr.s_addr = addr->v4.s_addr;
2811
		sa_in->sin_port = htons(port);
2812
		break;
2813
	case AF_INET6:
2814
		sa_in6->sin6_family = AF_INET6;
2815
		sa_in6->sin6_len = sizeof(struct sockaddr_in6);
2816
		memcpy(&sa_in6->sin6_addr, &addr->v6,
2817
		    sizeof(sa_in6->sin6_addr));
2818
		sa_in6->sin6_port = htons(port);
2819
		sa_in6->sin6_scope_id = addr->scope_id;
2820
		break;
2821
	}
2822
2823
	return ((struct sockaddr *)&ss);
2824
}
2825
2826
void
3151
void
2827
session_demote(struct peer *p, int level)
3152
session_demote(struct peer *p, int level)
2828
{
3153
{
Lines 2837-2839 session_demote(struct peer *p, int level Link Here
2837
3162
2838
	p->demoted += level;
3163
	p->demoted += level;
2839
}
3164
}
3165
3166
void
3167
session_stop(struct peer *peer, u_int8_t subcode)
3168
{
3169
	switch (peer->state) {
3170
	case STATE_OPENSENT:
3171
	case STATE_OPENCONFIRM:
3172
	case STATE_ESTABLISHED:
3173
		session_notification(peer, ERR_CEASE, subcode, NULL, 0);
3174
		break;
3175
	default:
3176
		/* session not open, no need to send notification */
3177
		break;
3178
	}
3179
	bgp_fsm(peer, EVNT_STOP);
3180
}

Return to bug 223835