1 /* $OpenBSD: neighbor.c,v 1.81 2019/06/28 13:32:48 deraadt Exp $ */
2
3 /*
4 * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
5 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
6 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
7 * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org>
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 */
21
22 #include <sys/types.h>
23 #include <sys/time.h>
24 #include <netinet/tcp.h>
25 #include <arpa/inet.h>
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30
31 #include "ldpd.h"
32 #include "ldpe.h"
33 #include "lde.h"
34 #include "log.h"
35
36 static __inline int nbr_id_compare(struct nbr *, struct nbr *);
37 static __inline int nbr_addr_compare(struct nbr *, struct nbr *);
38 static __inline int nbr_pid_compare(struct nbr *, struct nbr *);
39 static void nbr_update_peerid(struct nbr *);
40 static void nbr_ktimer(int, short, void *);
41 static void nbr_start_ktimer(struct nbr *);
42 static void nbr_ktimeout(int, short, void *);
43 static void nbr_start_ktimeout(struct nbr *);
44 static void nbr_itimeout(int, short, void *);
45 static void nbr_start_itimeout(struct nbr *);
46 static void nbr_idtimer(int, short, void *);
47 static int nbr_act_session_operational(struct nbr *);
48 static void nbr_send_labelmappings(struct nbr *);
49
50 RB_GENERATE(nbr_id_head, nbr, id_tree, nbr_id_compare)
51 RB_GENERATE(nbr_addr_head, nbr, addr_tree, nbr_addr_compare)
52 RB_GENERATE(nbr_pid_head, nbr, pid_tree, nbr_pid_compare)
53
54 struct {
55 int state;
56 enum nbr_event event;
57 enum nbr_action action;
58 int new_state;
59 } nbr_fsm_tbl[] = {
60 /* current state event that happened action to take resulting state */
61 /* Passive Role */
62 {NBR_STA_PRESENT, NBR_EVT_MATCH_ADJ, NBR_ACT_NOTHING, NBR_STA_INITIAL},
63 {NBR_STA_INITIAL, NBR_EVT_INIT_RCVD, NBR_ACT_PASSIVE_INIT, NBR_STA_OPENREC},
64 {NBR_STA_OPENREC, NBR_EVT_KEEPALIVE_RCVD, NBR_ACT_SESSION_EST, NBR_STA_OPER},
65 /* Active Role */
66 {NBR_STA_PRESENT, NBR_EVT_CONNECT_UP, NBR_ACT_CONNECT_SETUP, NBR_STA_INITIAL},
67 {NBR_STA_INITIAL, NBR_EVT_INIT_SENT, NBR_ACT_NOTHING, NBR_STA_OPENSENT},
68 {NBR_STA_OPENSENT, NBR_EVT_INIT_RCVD, NBR_ACT_KEEPALIVE_SEND, NBR_STA_OPENREC},
69 /* Session Maintenance */
70 {NBR_STA_OPER, NBR_EVT_PDU_RCVD, NBR_ACT_RST_KTIMEOUT, 0},
71 {NBR_STA_SESSION, NBR_EVT_PDU_RCVD, NBR_ACT_NOTHING, 0},
72 {NBR_STA_OPER, NBR_EVT_PDU_SENT, NBR_ACT_RST_KTIMER, 0},
73 {NBR_STA_SESSION, NBR_EVT_PDU_SENT, NBR_ACT_NOTHING, 0},
74 /* Session Close */
75 {NBR_STA_PRESENT, NBR_EVT_CLOSE_SESSION, NBR_ACT_NOTHING, 0},
76 {NBR_STA_SESSION, NBR_EVT_CLOSE_SESSION, NBR_ACT_CLOSE_SESSION, NBR_STA_PRESENT},
77 {-1, NBR_EVT_NOTHING, NBR_ACT_NOTHING, 0},
78 };
79
80 const char * const nbr_event_names[] = {
81 "NOTHING",
82 "ADJACENCY MATCHED",
83 "CONNECTION UP",
84 "SESSION CLOSE",
85 "INIT RECEIVED",
86 "KEEPALIVE RECEIVED",
87 "PDU RECEIVED",
88 "PDU SENT",
89 "INIT SENT"
90 };
91
92 const char * const nbr_action_names[] = {
93 "NOTHING",
94 "RESET KEEPALIVE TIMEOUT",
95 "START NEIGHBOR SESSION",
96 "RESET KEEPALIVE TIMER",
97 "SETUP NEIGHBOR CONNECTION",
98 "SEND INIT AND KEEPALIVE",
99 "SEND KEEPALIVE",
100 "CLOSE SESSION"
101 };
102
103 struct nbr_id_head nbrs_by_id = RB_INITIALIZER(&nbrs_by_id);
104 struct nbr_addr_head nbrs_by_addr = RB_INITIALIZER(&nbrs_by_addr);
105 struct nbr_pid_head nbrs_by_pid = RB_INITIALIZER(&nbrs_by_pid);
106
107 static __inline int
nbr_id_compare(struct nbr * a,struct nbr * b)108 nbr_id_compare(struct nbr *a, struct nbr *b)
109 {
110 return (ntohl(a->id.s_addr) - ntohl(b->id.s_addr));
111 }
112
113 static __inline int
nbr_addr_compare(struct nbr * a,struct nbr * b)114 nbr_addr_compare(struct nbr *a, struct nbr *b)
115 {
116 if (a->af < b->af)
117 return (-1);
118 if (a->af > b->af)
119 return (1);
120
121 return (ldp_addrcmp(a->af, &a->raddr, &b->raddr));
122 }
123
124 static __inline int
nbr_pid_compare(struct nbr * a,struct nbr * b)125 nbr_pid_compare(struct nbr *a, struct nbr *b)
126 {
127 return (a->peerid - b->peerid);
128 }
129
130 int
nbr_fsm(struct nbr * nbr,enum nbr_event event)131 nbr_fsm(struct nbr *nbr, enum nbr_event event)
132 {
133 struct timeval now;
134 int old_state;
135 int new_state = 0;
136 int i;
137
138 old_state = nbr->state;
139 for (i = 0; nbr_fsm_tbl[i].state != -1; i++)
140 if ((nbr_fsm_tbl[i].state & old_state) &&
141 (nbr_fsm_tbl[i].event == event)) {
142 new_state = nbr_fsm_tbl[i].new_state;
143 break;
144 }
145
146 if (nbr_fsm_tbl[i].state == -1) {
147 /* event outside of the defined fsm, ignore it. */
148 log_warnx("%s: lsr-id %s, event %s not expected in "
149 "state %s", __func__, inet_ntoa(nbr->id),
150 nbr_event_names[event], nbr_state_name(old_state));
151 return (0);
152 }
153
154 if (new_state != 0)
155 nbr->state = new_state;
156
157 if (old_state != nbr->state) {
158 log_debug("%s: event %s resulted in action %s and "
159 "changing state for lsr-id %s from %s to %s",
160 __func__, nbr_event_names[event],
161 nbr_action_names[nbr_fsm_tbl[i].action],
162 inet_ntoa(nbr->id), nbr_state_name(old_state),
163 nbr_state_name(nbr->state));
164
165 if (nbr->state == NBR_STA_OPER) {
166 gettimeofday(&now, NULL);
167 nbr->uptime = now.tv_sec;
168 }
169 }
170
171 if (nbr->state == NBR_STA_OPER || nbr->state == NBR_STA_PRESENT)
172 nbr_stop_itimeout(nbr);
173 else
174 nbr_start_itimeout(nbr);
175
176 switch (nbr_fsm_tbl[i].action) {
177 case NBR_ACT_RST_KTIMEOUT:
178 nbr_start_ktimeout(nbr);
179 break;
180 case NBR_ACT_RST_KTIMER:
181 nbr_start_ktimer(nbr);
182 break;
183 case NBR_ACT_SESSION_EST:
184 nbr_act_session_operational(nbr);
185 nbr_start_ktimer(nbr);
186 nbr_start_ktimeout(nbr);
187 if (nbr->v4_enabled)
188 send_address_all(nbr, AF_INET);
189 if (nbr->v6_enabled)
190 send_address_all(nbr, AF_INET6);
191 nbr_send_labelmappings(nbr);
192 break;
193 case NBR_ACT_CONNECT_SETUP:
194 nbr->tcp = tcp_new(nbr->fd, nbr);
195
196 /* trigger next state */
197 send_init(nbr);
198 nbr_fsm(nbr, NBR_EVT_INIT_SENT);
199 break;
200 case NBR_ACT_PASSIVE_INIT:
201 send_init(nbr);
202 send_keepalive(nbr);
203 break;
204 case NBR_ACT_KEEPALIVE_SEND:
205 nbr_start_ktimeout(nbr);
206 send_keepalive(nbr);
207 break;
208 case NBR_ACT_CLOSE_SESSION:
209 ldpe_imsg_compose_lde(IMSG_NEIGHBOR_DOWN, nbr->peerid, 0,
210 NULL, 0);
211 session_close(nbr);
212 break;
213 case NBR_ACT_NOTHING:
214 /* do nothing */
215 break;
216 }
217
218 return (0);
219 }
220
221 struct nbr *
nbr_new(struct in_addr id,int af,int ds_tlv,union ldpd_addr * addr,uint32_t scope_id)222 nbr_new(struct in_addr id, int af, int ds_tlv, union ldpd_addr *addr,
223 uint32_t scope_id)
224 {
225 struct nbr *nbr;
226 struct adj *adj;
227 struct pending_conn *pconn;
228
229 log_debug("%s: lsr-id %s transport-address %s", __func__,
230 inet_ntoa(id), log_addr(af, addr));
231
232 if ((nbr = calloc(1, sizeof(*nbr))) == NULL)
233 fatal(__func__);
234
235 LIST_INIT(&nbr->adj_list);
236 nbr->state = NBR_STA_PRESENT;
237 nbr->peerid = 0;
238 nbr->af = af;
239 nbr->ds_tlv = ds_tlv;
240 if (af == AF_INET || ds_tlv)
241 nbr->v4_enabled = 1;
242 if (af == AF_INET6 || ds_tlv)
243 nbr->v6_enabled = 1;
244 nbr->id = id;
245 nbr->laddr = (ldp_af_conf_get(leconf, af))->trans_addr;
246 nbr->raddr = *addr;
247 nbr->raddr_scope = scope_id;
248 nbr->conf_seqnum = 0;
249
250 LIST_FOREACH(adj, &global.adj_list, global_entry) {
251 if (adj->lsr_id.s_addr == nbr->id.s_addr) {
252 adj->nbr = nbr;
253 LIST_INSERT_HEAD(&nbr->adj_list, adj, nbr_entry);
254 }
255 }
256
257 if (RB_INSERT(nbr_id_head, &nbrs_by_id, nbr) != NULL)
258 fatalx("nbr_new: RB_INSERT(nbrs_by_id) failed");
259 if (RB_INSERT(nbr_addr_head, &nbrs_by_addr, nbr) != NULL)
260 fatalx("nbr_new: RB_INSERT(nbrs_by_addr) failed");
261
262 TAILQ_INIT(&nbr->mapping_list);
263 TAILQ_INIT(&nbr->withdraw_list);
264 TAILQ_INIT(&nbr->request_list);
265 TAILQ_INIT(&nbr->release_list);
266 TAILQ_INIT(&nbr->abortreq_list);
267
268 /* set event structures */
269 evtimer_set(&nbr->keepalive_timeout, nbr_ktimeout, nbr);
270 evtimer_set(&nbr->keepalive_timer, nbr_ktimer, nbr);
271 evtimer_set(&nbr->init_timeout, nbr_itimeout, nbr);
272 evtimer_set(&nbr->initdelay_timer, nbr_idtimer, nbr);
273
274 if (pfkey_establish(leconf, nbr) == -1)
275 fatalx("pfkey setup failed");
276
277 pconn = pending_conn_find(nbr->af, &nbr->raddr);
278 if (pconn) {
279 session_accept_nbr(nbr, pconn->fd);
280 pending_conn_del(pconn);
281 }
282
283 return (nbr);
284 }
285
286 void
nbr_del(struct nbr * nbr)287 nbr_del(struct nbr *nbr)
288 {
289 log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
290
291 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
292 pfkey_remove(nbr);
293
294 if (nbr_pending_connect(nbr))
295 event_del(&nbr->ev_connect);
296 nbr_stop_ktimer(nbr);
297 nbr_stop_ktimeout(nbr);
298 nbr_stop_itimeout(nbr);
299 nbr_stop_idtimer(nbr);
300
301 mapping_list_clr(&nbr->mapping_list);
302 mapping_list_clr(&nbr->withdraw_list);
303 mapping_list_clr(&nbr->request_list);
304 mapping_list_clr(&nbr->release_list);
305 mapping_list_clr(&nbr->abortreq_list);
306
307 if (nbr->peerid)
308 RB_REMOVE(nbr_pid_head, &nbrs_by_pid, nbr);
309 RB_REMOVE(nbr_id_head, &nbrs_by_id, nbr);
310 RB_REMOVE(nbr_addr_head, &nbrs_by_addr, nbr);
311
312 free(nbr);
313 }
314
315 static void
nbr_update_peerid(struct nbr * nbr)316 nbr_update_peerid(struct nbr *nbr)
317 {
318 static uint32_t peercnt = 1;
319
320 if (nbr->peerid)
321 RB_REMOVE(nbr_pid_head, &nbrs_by_pid, nbr);
322
323 /* get next unused peerid */
324 while (nbr_find_peerid(++peercnt))
325 ;
326 nbr->peerid = peercnt;
327
328 if (RB_INSERT(nbr_pid_head, &nbrs_by_pid, nbr) != NULL)
329 fatalx("nbr_update_peerid: RB_INSERT(nbrs_by_pid) failed");
330 }
331
332 struct nbr *
nbr_find_ldpid(uint32_t lsr_id)333 nbr_find_ldpid(uint32_t lsr_id)
334 {
335 struct nbr n;
336 n.id.s_addr = lsr_id;
337 return (RB_FIND(nbr_id_head, &nbrs_by_id, &n));
338 }
339
340 struct nbr *
nbr_find_addr(int af,union ldpd_addr * addr)341 nbr_find_addr(int af, union ldpd_addr *addr)
342 {
343 struct nbr n;
344 n.af = af;
345 n.raddr = *addr;
346 return (RB_FIND(nbr_addr_head, &nbrs_by_addr, &n));
347 }
348
349 struct nbr *
nbr_find_peerid(uint32_t peerid)350 nbr_find_peerid(uint32_t peerid)
351 {
352 struct nbr n;
353 n.peerid = peerid;
354 return (RB_FIND(nbr_pid_head, &nbrs_by_pid, &n));
355 }
356
357 int
nbr_adj_count(struct nbr * nbr,int af)358 nbr_adj_count(struct nbr *nbr, int af)
359 {
360 struct adj *adj;
361 int total = 0;
362
363 LIST_FOREACH(adj, &nbr->adj_list, nbr_entry)
364 if (adj_get_af(adj) == af)
365 total++;
366
367 return (total);
368 }
369
370 int
nbr_session_active_role(struct nbr * nbr)371 nbr_session_active_role(struct nbr *nbr)
372 {
373 if (ldp_addrcmp(nbr->af, &nbr->laddr, &nbr->raddr) > 0)
374 return (1);
375
376 return (0);
377 }
378
379 /* timers */
380
381 /* Keepalive timer: timer to send keepalive message to neighbors */
382
383 static void
nbr_ktimer(int fd,short event,void * arg)384 nbr_ktimer(int fd, short event, void *arg)
385 {
386 struct nbr *nbr = arg;
387
388 send_keepalive(nbr);
389 nbr_start_ktimer(nbr);
390 }
391
392 static void
nbr_start_ktimer(struct nbr * nbr)393 nbr_start_ktimer(struct nbr *nbr)
394 {
395 struct timeval tv;
396
397 /* send three keepalives per period */
398 timerclear(&tv);
399 tv.tv_sec = (time_t)(nbr->keepalive / KEEPALIVE_PER_PERIOD);
400 if (evtimer_add(&nbr->keepalive_timer, &tv) == -1)
401 fatal(__func__);
402 }
403
404 void
nbr_stop_ktimer(struct nbr * nbr)405 nbr_stop_ktimer(struct nbr *nbr)
406 {
407 if (evtimer_pending(&nbr->keepalive_timer, NULL) &&
408 evtimer_del(&nbr->keepalive_timer) == -1)
409 fatal(__func__);
410 }
411
412 /* Keepalive timeout: if the nbr hasn't sent keepalive */
413
414 static void
nbr_ktimeout(int fd,short event,void * arg)415 nbr_ktimeout(int fd, short event, void *arg)
416 {
417 struct nbr *nbr = arg;
418
419 log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
420
421 session_shutdown(nbr, S_KEEPALIVE_TMR, 0, 0);
422 }
423
424 static void
nbr_start_ktimeout(struct nbr * nbr)425 nbr_start_ktimeout(struct nbr *nbr)
426 {
427 struct timeval tv;
428
429 timerclear(&tv);
430 tv.tv_sec = nbr->keepalive;
431
432 if (evtimer_add(&nbr->keepalive_timeout, &tv) == -1)
433 fatal(__func__);
434 }
435
436 void
nbr_stop_ktimeout(struct nbr * nbr)437 nbr_stop_ktimeout(struct nbr *nbr)
438 {
439 if (evtimer_pending(&nbr->keepalive_timeout, NULL) &&
440 evtimer_del(&nbr->keepalive_timeout) == -1)
441 fatal(__func__);
442 }
443
444 /* Session initialization timeout: if nbr got stuck in the initialization FSM */
445
446 static void
nbr_itimeout(int fd,short event,void * arg)447 nbr_itimeout(int fd, short event, void *arg)
448 {
449 struct nbr *nbr = arg;
450
451 log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
452
453 nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
454 }
455
456 static void
nbr_start_itimeout(struct nbr * nbr)457 nbr_start_itimeout(struct nbr *nbr)
458 {
459 struct timeval tv;
460
461 timerclear(&tv);
462 tv.tv_sec = INIT_FSM_TIMEOUT;
463 if (evtimer_add(&nbr->init_timeout, &tv) == -1)
464 fatal(__func__);
465 }
466
467 void
nbr_stop_itimeout(struct nbr * nbr)468 nbr_stop_itimeout(struct nbr *nbr)
469 {
470 if (evtimer_pending(&nbr->init_timeout, NULL) &&
471 evtimer_del(&nbr->init_timeout) == -1)
472 fatal(__func__);
473 }
474
475 /* Init delay timer: timer to retry to iniziatize session */
476
477 static void
nbr_idtimer(int fd,short event,void * arg)478 nbr_idtimer(int fd, short event, void *arg)
479 {
480 struct nbr *nbr = arg;
481
482 log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
483
484 nbr_establish_connection(nbr);
485 }
486
487 void
nbr_start_idtimer(struct nbr * nbr)488 nbr_start_idtimer(struct nbr *nbr)
489 {
490 struct timeval tv;
491
492 timerclear(&tv);
493
494 tv.tv_sec = INIT_DELAY_TMR;
495 switch(nbr->idtimer_cnt) {
496 default:
497 /* do not further increase the counter */
498 tv.tv_sec = MAX_DELAY_TMR;
499 break;
500 case 2:
501 tv.tv_sec *= 2;
502 /* FALLTHROUGH */
503 case 1:
504 tv.tv_sec *= 2;
505 /* FALLTHROUGH */
506 case 0:
507 nbr->idtimer_cnt++;
508 break;
509 }
510
511 if (evtimer_add(&nbr->initdelay_timer, &tv) == -1)
512 fatal(__func__);
513 }
514
515 void
nbr_stop_idtimer(struct nbr * nbr)516 nbr_stop_idtimer(struct nbr *nbr)
517 {
518 if (evtimer_pending(&nbr->initdelay_timer, NULL) &&
519 evtimer_del(&nbr->initdelay_timer) == -1)
520 fatal(__func__);
521 }
522
523 int
nbr_pending_idtimer(struct nbr * nbr)524 nbr_pending_idtimer(struct nbr *nbr)
525 {
526 if (evtimer_pending(&nbr->initdelay_timer, NULL))
527 return (1);
528
529 return (0);
530 }
531
532 int
nbr_pending_connect(struct nbr * nbr)533 nbr_pending_connect(struct nbr *nbr)
534 {
535 if (event_initialized(&nbr->ev_connect) &&
536 event_pending(&nbr->ev_connect, EV_WRITE, NULL))
537 return (1);
538
539 return (0);
540 }
541
542 static void
nbr_connect_cb(int fd,short event,void * arg)543 nbr_connect_cb(int fd, short event, void *arg)
544 {
545 struct nbr *nbr = arg;
546 int error;
547 socklen_t len;
548
549 len = sizeof(error);
550 if (getsockopt(nbr->fd, SOL_SOCKET, SO_ERROR, &error, &len) == -1) {
551 log_warn("%s: getsockopt SOL_SOCKET SO_ERROR", __func__);
552 return;
553 }
554
555 if (error) {
556 close(nbr->fd);
557 errno = error;
558 log_debug("%s: error while connecting to %s: %s", __func__,
559 log_addr(nbr->af, &nbr->raddr), strerror(errno));
560 return;
561 }
562
563 nbr_fsm(nbr, NBR_EVT_CONNECT_UP);
564 }
565
566 int
nbr_establish_connection(struct nbr * nbr)567 nbr_establish_connection(struct nbr *nbr)
568 {
569 struct sockaddr_storage local_sa;
570 struct sockaddr_storage remote_sa;
571 struct adj *adj;
572 struct nbr_params *nbrp;
573 int opt = 1;
574
575 nbr->fd = socket(nbr->af,
576 SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
577 if (nbr->fd == -1) {
578 log_warn("%s: error while creating socket", __func__);
579 return (-1);
580 }
581
582 if (nbr->auth_established) {
583 if (sysdep.no_pfkey || sysdep.no_md5sig) {
584 log_warnx("md5sig configured but not available");
585 close(nbr->fd);
586 return (-1);
587 }
588 if (setsockopt(nbr->fd, IPPROTO_TCP, TCP_MD5SIG,
589 &opt, sizeof(opt)) == -1) {
590 log_warn("setsockopt md5sig");
591 close(nbr->fd);
592 return (-1);
593 }
594 }
595
596 memcpy(&local_sa, addr2sa(nbr->af, &nbr->laddr, 0), sizeof(local_sa));
597 memcpy(&remote_sa, addr2sa(nbr->af, &nbr->raddr, LDP_PORT),
598 sizeof(local_sa));
599 if (nbr->af == AF_INET6 && nbr->raddr_scope)
600 addscope((struct sockaddr_in6 *)&remote_sa, nbr->raddr_scope);
601
602 if (bind(nbr->fd, (struct sockaddr *)&local_sa,
603 local_sa.ss_len) == -1) {
604 log_warn("%s: error while binding socket to %s", __func__,
605 log_sockaddr((struct sockaddr *)&local_sa));
606 close(nbr->fd);
607 return (-1);
608 }
609
610 nbrp = nbr_params_find(leconf, nbr->id);
611 if (nbr_gtsm_check(nbr->fd, nbr, nbrp)) {
612 close(nbr->fd);
613 return (-1);
614 }
615
616 /*
617 * Send an extra hello to guarantee that the remote peer has formed
618 * an adjacency as well.
619 */
620 LIST_FOREACH(adj, &nbr->adj_list, nbr_entry)
621 send_hello(adj->source.type, adj->source.link.ia,
622 adj->source.target);
623
624 if (connect(nbr->fd, (struct sockaddr *)&remote_sa,
625 remote_sa.ss_len) == -1) {
626 if (errno == EINPROGRESS) {
627 event_set(&nbr->ev_connect, nbr->fd, EV_WRITE,
628 nbr_connect_cb, nbr);
629 event_add(&nbr->ev_connect, NULL);
630 return (0);
631 }
632 log_warn("%s: error while connecting to %s", __func__,
633 log_sockaddr((struct sockaddr *)&remote_sa));
634 close(nbr->fd);
635 return (-1);
636 }
637
638 /* connection completed immediately */
639 nbr_fsm(nbr, NBR_EVT_CONNECT_UP);
640
641 return (0);
642 }
643
644 int
nbr_gtsm_enabled(struct nbr * nbr,struct nbr_params * nbrp)645 nbr_gtsm_enabled(struct nbr *nbr, struct nbr_params *nbrp)
646 {
647 /*
648 * RFC 6720 - Section 3:
649 * "This document allows for the implementation to provide an option to
650 * statically (e.g., via configuration) and/or dynamically override the
651 * default behavior and enable/disable GTSM on a per-peer basis".
652 */
653 if (nbrp && (nbrp->flags & F_NBRP_GTSM))
654 return (nbrp->gtsm_enabled);
655
656 if ((ldp_af_conf_get(leconf, nbr->af))->flags & F_LDPD_AF_NO_GTSM)
657 return (0);
658
659 /* By default, GTSM support has to be negotiated for LDPv4 */
660 if (nbr->af == AF_INET && !(nbr->flags & F_NBR_GTSM_NEGOTIATED))
661 return (0);
662
663 return (1);
664 }
665
666 int
nbr_gtsm_setup(int fd,int af,struct nbr_params * nbrp)667 nbr_gtsm_setup(int fd, int af, struct nbr_params *nbrp)
668 {
669 int ttl = 255;
670
671 if (nbrp && (nbrp->flags & F_NBRP_GTSM_HOPS))
672 ttl = 256 - nbrp->gtsm_hops;
673
674 switch (af) {
675 case AF_INET:
676 if (sock_set_ipv4_minttl(fd, ttl) == -1)
677 return (-1);
678 ttl = 255;
679 if (sock_set_ipv4_ucast_ttl(fd, ttl) == -1)
680 return (-1);
681 break;
682 case AF_INET6:
683 if (sock_set_ipv6_minhopcount(fd, ttl) == -1)
684 return (-1);
685 ttl = 255;
686 if (sock_set_ipv6_ucast_hops(fd, ttl) == -1)
687 return (-1);
688 break;
689 default:
690 fatalx("nbr_gtsm_setup: unknown af");
691 }
692
693 return (0);
694 }
695
696 int
nbr_gtsm_check(int fd,struct nbr * nbr,struct nbr_params * nbrp)697 nbr_gtsm_check(int fd, struct nbr *nbr, struct nbr_params *nbrp)
698 {
699 if (!nbr_gtsm_enabled(nbr, nbrp)) {
700 switch (nbr->af) {
701 case AF_INET:
702 sock_set_ipv4_ucast_ttl(fd, -1);
703 break;
704 case AF_INET6:
705 /*
706 * Send packets with a Hop Limit of 255 even when GSTM
707 * is disabled to guarantee interoperability.
708 */
709 sock_set_ipv6_ucast_hops(fd, 255);
710 break;
711 default:
712 fatalx("nbr_gtsm_check: unknown af");
713 break;
714 }
715 return (0);
716 }
717
718 if (nbr_gtsm_setup(fd, nbr->af, nbrp) == -1) {
719 log_warnx("%s: error enabling GTSM for lsr-id %s", __func__,
720 inet_ntoa(nbr->id));
721 return (-1);
722 }
723
724 return (0);
725 }
726
727 static int
nbr_act_session_operational(struct nbr * nbr)728 nbr_act_session_operational(struct nbr *nbr)
729 {
730 struct lde_nbr lde_nbr;
731
732 nbr->idtimer_cnt = 0;
733
734 /* this is necessary to avoid ipc synchronization issues */
735 nbr_update_peerid(nbr);
736
737 memset(&lde_nbr, 0, sizeof(lde_nbr));
738 lde_nbr.id = nbr->id;
739 lde_nbr.v4_enabled = nbr->v4_enabled;
740 lde_nbr.v6_enabled = nbr->v6_enabled;
741 lde_nbr.flags = nbr->flags;
742 return (ldpe_imsg_compose_lde(IMSG_NEIGHBOR_UP, nbr->peerid, 0,
743 &lde_nbr, sizeof(lde_nbr)));
744 }
745
746 static void
nbr_send_labelmappings(struct nbr * nbr)747 nbr_send_labelmappings(struct nbr *nbr)
748 {
749 ldpe_imsg_compose_lde(IMSG_LABEL_MAPPING_FULL, nbr->peerid, 0,
750 NULL, 0);
751 }
752
753 struct nbr_params *
nbr_params_new(struct in_addr lsr_id)754 nbr_params_new(struct in_addr lsr_id)
755 {
756 struct nbr_params *nbrp;
757
758 if ((nbrp = calloc(1, sizeof(*nbrp))) == NULL)
759 fatal(__func__);
760
761 nbrp->lsr_id = lsr_id;
762
763 return (nbrp);
764 }
765
766 struct nbr_params *
nbr_params_find(struct ldpd_conf * xconf,struct in_addr lsr_id)767 nbr_params_find(struct ldpd_conf *xconf, struct in_addr lsr_id)
768 {
769 struct nbr_params *nbrp;
770
771 LIST_FOREACH(nbrp, &xconf->nbrp_list, entry)
772 if (nbrp->lsr_id.s_addr == lsr_id.s_addr)
773 return (nbrp);
774
775 return (NULL);
776 }
777
778 uint16_t
nbr_get_keepalive(int af,struct in_addr lsr_id)779 nbr_get_keepalive(int af, struct in_addr lsr_id)
780 {
781 struct nbr_params *nbrp;
782
783 nbrp = nbr_params_find(leconf, lsr_id);
784 if (nbrp && (nbrp->flags & F_NBRP_KEEPALIVE))
785 return (nbrp->keepalive);
786
787 return ((ldp_af_conf_get(leconf, af))->keepalive);
788 }
789
790 struct ctl_nbr *
nbr_to_ctl(struct nbr * nbr)791 nbr_to_ctl(struct nbr *nbr)
792 {
793 static struct ctl_nbr nctl;
794 struct timeval now;
795
796 nctl.af = nbr->af;
797 nctl.id = nbr->id;
798 nctl.laddr = nbr->laddr;
799 nctl.raddr = nbr->raddr;
800 nctl.nbr_state = nbr->state;
801
802 gettimeofday(&now, NULL);
803 if (nbr->state == NBR_STA_OPER) {
804 nctl.uptime = now.tv_sec - nbr->uptime;
805 } else
806 nctl.uptime = 0;
807
808 return (&nctl);
809 }
810
811 void
nbr_clear_ctl(struct ctl_nbr * nctl)812 nbr_clear_ctl(struct ctl_nbr *nctl)
813 {
814 struct nbr *nbr;
815
816 RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) {
817 if (ldp_addrisset(nctl->af, &nctl->raddr) &&
818 ldp_addrcmp(nctl->af, &nctl->raddr, &nbr->raddr))
819 continue;
820
821 log_debug("%s: neighbor %s manually cleared", __func__,
822 log_addr(nbr->af, &nbr->raddr));
823 session_shutdown(nbr, S_SHUTDOWN, 0, 0);
824 }
825 }
826