|
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 |
} |