xref: /openbsd-src/usr.sbin/ldpd/neighbor.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*	$OpenBSD: neighbor.c,v 1.43 2013/10/17 17:47:04 renato Exp $ */
2 
3 /*
4  * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
5  * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
6  * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org>
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 #include <sys/types.h>
22 #include <sys/ioctl.h>
23 #include <sys/time.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27 #include <net/if.h>
28 
29 #include <ctype.h>
30 #include <err.h>
31 #include <errno.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <event.h>
36 #include <unistd.h>
37 
38 #include "ldpd.h"
39 #include "ldp.h"
40 #include "ldpe.h"
41 #include "control.h"
42 #include "log.h"
43 #include "lde.h"
44 
45 void	nbr_send_labelmappings(struct nbr *);
46 int	nbr_act_session_operational(struct nbr *);
47 
48 static __inline int nbr_id_compare(struct nbr *, struct nbr *);
49 static __inline int nbr_pid_compare(struct nbr *, struct nbr *);
50 
51 RB_HEAD(nbr_id_head, nbr);
52 RB_PROTOTYPE(nbr_id_head, nbr, id_tree, nbr_id_compare)
53 RB_GENERATE(nbr_id_head, nbr, id_tree, nbr_id_compare)
54 RB_HEAD(nbr_pid_head, nbr);
55 RB_PROTOTYPE(nbr_pid_head, nbr, pid_tree, nbr_pid_compare)
56 RB_GENERATE(nbr_pid_head, nbr, pid_tree, nbr_pid_compare)
57 
58 static __inline int
59 nbr_id_compare(struct nbr *a, struct nbr *b)
60 {
61 	return (ntohl(a->id.s_addr) - ntohl(b->id.s_addr));
62 }
63 
64 static __inline int
65 nbr_pid_compare(struct nbr *a, struct nbr *b)
66 {
67 	return (a->peerid - b->peerid);
68 }
69 
70 struct nbr_id_head nbrs_by_id = RB_INITIALIZER(&nbrs_by_id);
71 struct nbr_pid_head nbrs_by_pid = RB_INITIALIZER(&nbrs_by_pid);
72 
73 u_int32_t	peercnt = NBR_CNTSTART;
74 
75 extern struct ldpd_conf	*leconf;
76 
77 struct {
78 	int		state;
79 	enum nbr_event	event;
80 	enum nbr_action	action;
81 	int		new_state;
82 } nbr_fsm_tbl[] = {
83     /* current state	event that happened	action to take		resulting state */
84 /* Passive Role */
85     {NBR_STA_PRESENT,	NBR_EVT_MATCH_ADJ,	NBR_ACT_NOTHING,	NBR_STA_INITIAL},
86     {NBR_STA_INITIAL,	NBR_EVT_INIT_RCVD,	NBR_ACT_PASSIVE_INIT,	NBR_STA_OPENREC},
87     {NBR_STA_OPENREC,	NBR_EVT_KEEPALIVE_RCVD,	NBR_ACT_SESSION_EST,	NBR_STA_OPER},
88 /* Active Role */
89     {NBR_STA_PRESENT,	NBR_EVT_CONNECT_UP,	NBR_ACT_CONNECT_SETUP,	NBR_STA_INITIAL},
90     {NBR_STA_INITIAL,	NBR_EVT_INIT_SENT,	NBR_ACT_NOTHING,	NBR_STA_OPENSENT},
91     {NBR_STA_OPENSENT,	NBR_EVT_INIT_RCVD,	NBR_ACT_KEEPALIVE_SEND,	NBR_STA_OPENREC},
92 /* Session Maintenance */
93     {NBR_STA_OPER,	NBR_EVT_PDU_RCVD,	NBR_ACT_RST_KTIMEOUT,	0},
94     {NBR_STA_OPER,	NBR_EVT_PDU_SENT,	NBR_ACT_RST_KTIMER,	0},
95 /* Session Close */
96     {NBR_STA_PRESENT,	NBR_EVT_CLOSE_SESSION,	NBR_ACT_NOTHING,	0},
97     {NBR_STA_SESSION,	NBR_EVT_CLOSE_SESSION,	NBR_ACT_CLOSE_SESSION,	NBR_STA_PRESENT},
98     {-1,		NBR_EVT_NOTHING,	NBR_ACT_NOTHING,	0},
99 };
100 
101 const char * const nbr_event_names[] = {
102 	"NOTHING",
103 	"ADJACENCY MATCHED",
104 	"CONNECTION UP",
105 	"SESSION CLOSE",
106 	"INIT RECEIVED",
107 	"KEEPALIVE RECEIVED",
108 	"PDU RECEIVED",
109 	"PDU SENT",
110 	"INIT SENT"
111 };
112 
113 const char * const nbr_action_names[] = {
114 	"NOTHING",
115 	"RESET KEEPALIVE TIMEOUT",
116 	"START NEIGHBOR SESSION",
117 	"RESET KEEPALIVE TIMER",
118 	"SETUP NEIGHBOR CONNECTION",
119 	"SEND INIT AND KEEPALIVE",
120 	"SEND KEEPALIVE",
121 	"CLOSE SESSION"
122 };
123 
124 int
125 nbr_fsm(struct nbr *nbr, enum nbr_event event)
126 {
127 	struct timeval	now;
128 	int		old_state;
129 	int		new_state = 0;
130 	int		i;
131 
132 	old_state = nbr->state;
133 	for (i = 0; nbr_fsm_tbl[i].state != -1; i++)
134 		if ((nbr_fsm_tbl[i].state & old_state) &&
135 		    (nbr_fsm_tbl[i].event == event)) {
136 			new_state = nbr_fsm_tbl[i].new_state;
137 			break;
138 		}
139 
140 	if (nbr_fsm_tbl[i].state == -1) {
141 		/* event outside of the defined fsm, ignore it. */
142 		log_warnx("nbr_fsm: neighbor ID %s, "
143 		    "event %s not expected in state %s",
144 		    inet_ntoa(nbr->id), nbr_event_names[event],
145 		    nbr_state_name(old_state));
146 		return (0);
147 	}
148 
149 	if (new_state != 0)
150 		nbr->state = new_state;
151 
152 	if (old_state != nbr->state) {
153 		log_debug("nbr_fsm: event %s resulted in action %s and "
154 		    "changing state for neighbor ID %s from %s to %s",
155 		    nbr_event_names[event],
156 		    nbr_action_names[nbr_fsm_tbl[i].action],
157 		    inet_ntoa(nbr->id), nbr_state_name(old_state),
158 		    nbr_state_name(nbr->state));
159 
160 		if (nbr->state == NBR_STA_OPER) {
161 			gettimeofday(&now, NULL);
162 			nbr->uptime = now.tv_sec;
163 		}
164 	}
165 
166 	switch (nbr_fsm_tbl[i].action) {
167 	case NBR_ACT_RST_KTIMEOUT:
168 		nbr_start_ktimeout(nbr);
169 		break;
170 	case NBR_ACT_RST_KTIMER:
171 		nbr_start_ktimer(nbr);
172 		break;
173 	case NBR_ACT_SESSION_EST:
174 		nbr_act_session_operational(nbr);
175 		nbr_start_ktimer(nbr);
176 		nbr_start_ktimeout(nbr);
177 		send_address(nbr, NULL);
178 		nbr_send_labelmappings(nbr);
179 		break;
180 	case NBR_ACT_CONNECT_SETUP:
181 		nbr->tcp = tcp_new(nbr->fd, nbr);
182 
183 		/* trigger next state */
184 		send_init(nbr);
185 		nbr_fsm(nbr, NBR_EVT_INIT_SENT);
186 		break;
187 	case NBR_ACT_PASSIVE_INIT:
188 		send_init(nbr);
189 		send_keepalive(nbr);
190 		break;
191 	case NBR_ACT_KEEPALIVE_SEND:
192 		nbr_start_ktimeout(nbr);
193 		send_keepalive(nbr);
194 		break;
195 	case NBR_ACT_CLOSE_SESSION:
196 		ldpe_imsg_compose_lde(IMSG_NEIGHBOR_DOWN, nbr->peerid, 0,
197 		    NULL, 0);
198 		session_close(nbr);
199 		break;
200 	case NBR_ACT_NOTHING:
201 		/* do nothing */
202 		break;
203 	}
204 
205 	return (0);
206 }
207 
208 struct nbr *
209 nbr_new(struct in_addr id, struct in_addr addr)
210 {
211 	struct nbr	*nbr;
212 
213 	log_debug("nbr_new: LSR ID %s", inet_ntoa(id));
214 
215 	if ((nbr = calloc(1, sizeof(*nbr))) == NULL)
216 		fatal("nbr_new");
217 
218 	nbr->state = NBR_STA_PRESENT;
219 	nbr->id.s_addr = id.s_addr;
220 	nbr->addr.s_addr = addr.s_addr;
221 
222 	/* get next unused peerid */
223 	while (nbr_find_peerid(++peercnt))
224 		;
225 	nbr->peerid = peercnt;
226 
227 	if (RB_INSERT(nbr_pid_head, &nbrs_by_pid, nbr) != NULL)
228 		fatalx("nbr_new: RB_INSERT(nbrs_by_pid) failed");
229 	if (RB_INSERT(nbr_id_head, &nbrs_by_id, nbr) != NULL)
230 		fatalx("nbr_new: RB_INSERT(nbrs_by_id) failed");
231 
232 	TAILQ_INIT(&nbr->mapping_list);
233 	TAILQ_INIT(&nbr->withdraw_list);
234 	TAILQ_INIT(&nbr->request_list);
235 	TAILQ_INIT(&nbr->release_list);
236 	TAILQ_INIT(&nbr->abortreq_list);
237 
238 	/* set event structures */
239 	evtimer_set(&nbr->keepalive_timeout, nbr_ktimeout, nbr);
240 	evtimer_set(&nbr->keepalive_timer, nbr_ktimer, nbr);
241 	evtimer_set(&nbr->initdelay_timer, nbr_idtimer, nbr);
242 
243 	return (nbr);
244 }
245 
246 void
247 nbr_del(struct nbr *nbr)
248 {
249 	log_debug("nbr_del: LSR ID %s", inet_ntoa(nbr->id));
250 
251 	nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
252 
253 	if (event_pending(&nbr->ev_connect, EV_WRITE, NULL))
254 		event_del(&nbr->ev_connect);
255 	nbr_stop_ktimer(nbr);
256 	nbr_stop_ktimeout(nbr);
257 	nbr_stop_idtimer(nbr);
258 
259 	mapping_list_clr(&nbr->mapping_list);
260 	mapping_list_clr(&nbr->withdraw_list);
261 	mapping_list_clr(&nbr->request_list);
262 	mapping_list_clr(&nbr->release_list);
263 	mapping_list_clr(&nbr->abortreq_list);
264 
265 	RB_REMOVE(nbr_pid_head, &nbrs_by_pid, nbr);
266 	RB_REMOVE(nbr_id_head, &nbrs_by_id, nbr);
267 
268 	free(nbr);
269 }
270 
271 struct nbr *
272 nbr_find_peerid(u_int32_t peerid)
273 {
274 	struct nbr	n;
275 	n.peerid = peerid;
276 	return (RB_FIND(nbr_pid_head, &nbrs_by_pid, &n));
277 }
278 
279 struct nbr *
280 nbr_find_ldpid(u_int32_t rtr_id)
281 {
282 	struct nbr	n;
283 	n.id.s_addr = rtr_id;
284 	return (RB_FIND(nbr_id_head, &nbrs_by_id, &n));
285 }
286 
287 int
288 nbr_session_active_role(struct nbr *nbr)
289 {
290 	if (ntohl(ldpe_router_id()) > ntohl(nbr->addr.s_addr))
291 		return (1);
292 
293 	return (0);
294 }
295 
296 /* timers */
297 
298 /* Keepalive timer: timer to send keepalive message to neighbors */
299 
300 void
301 nbr_ktimer(int fd, short event, void *arg)
302 {
303 	struct nbr	*nbr = arg;
304 	struct timeval	 tv;
305 
306 	send_keepalive(nbr);
307 
308 	timerclear(&tv);
309 	tv.tv_sec = (time_t)(nbr->keepalive / KEEPALIVE_PER_PERIOD);
310 	if (evtimer_add(&nbr->keepalive_timer, &tv) == -1)
311 		fatal("nbr_ktimer");
312 }
313 
314 void
315 nbr_start_ktimer(struct nbr *nbr)
316 {
317 	struct timeval	tv;
318 
319 	timerclear(&tv);
320 
321 	/* XXX: just to be sure it will send three keepalives per period */
322 	tv.tv_sec = (time_t)(nbr->keepalive / KEEPALIVE_PER_PERIOD);
323 
324 	if (evtimer_add(&nbr->keepalive_timer, &tv) == -1)
325 		fatal("nbr_start_ktimer");
326 }
327 
328 void
329 nbr_stop_ktimer(struct nbr *nbr)
330 {
331 	if (evtimer_pending(&nbr->keepalive_timer, NULL) &&
332 	    evtimer_del(&nbr->keepalive_timer) == -1)
333 		fatal("nbr_stop_ktimer");
334 }
335 
336 /* Keepalive timeout: if the nbr hasn't sent keepalive */
337 
338 void
339 nbr_ktimeout(int fd, short event, void *arg)
340 {
341 	struct nbr *nbr = arg;
342 
343 	log_debug("nbr_ktimeout: neighbor ID %s peerid %u", inet_ntoa(nbr->id),
344 	    nbr->peerid);
345 
346 	session_shutdown(nbr, S_KEEPALIVE_TMR, 0, 0);
347 }
348 
349 void
350 nbr_start_ktimeout(struct nbr *nbr)
351 {
352 	struct timeval	tv;
353 
354 	timerclear(&tv);
355 	tv.tv_sec = nbr->keepalive;
356 
357 	if (evtimer_add(&nbr->keepalive_timeout, &tv) == -1)
358 		fatal("nbr_start_ktimeout");
359 }
360 
361 void
362 nbr_stop_ktimeout(struct nbr *nbr)
363 {
364 	if (evtimer_pending(&nbr->keepalive_timeout, NULL) &&
365 	    evtimer_del(&nbr->keepalive_timeout) == -1)
366 		fatal("nbr_stop_ktimeout");
367 }
368 
369 /* Init delay timer: timer to retry to iniziatize session */
370 
371 void
372 nbr_idtimer(int fd, short event, void *arg)
373 {
374 	struct nbr *nbr = arg;
375 
376 	log_debug("nbr_idtimer: neighbor ID %s peerid %u", inet_ntoa(nbr->id),
377 	    nbr->peerid);
378 
379 	if (nbr_session_active_role(nbr))
380 		nbr_establish_connection(nbr);
381 	else if (nbr->state == NBR_STA_INITIAL)
382 		nbr_fsm(nbr, NBR_EVT_INIT_RCVD);
383 }
384 
385 void
386 nbr_start_idtimer(struct nbr *nbr)
387 {
388 	struct timeval	tv;
389 
390 	timerclear(&tv);
391 
392 	tv.tv_sec = INIT_DELAY_TMR;
393 	switch(nbr->idtimer_cnt) {
394 	default:
395 		/* do not further increase the counter */
396 		tv.tv_sec = MAX_DELAY_TMR;
397 		break;
398 	case 2:
399 		tv.tv_sec *= 2;
400 		/* FALLTHROUGH */
401 	case 1:
402 		tv.tv_sec *= 2;
403 		/* FALLTHROUGH */
404 	case 0:
405 		nbr->idtimer_cnt++;
406 		break;
407 	}
408 
409 	if (evtimer_add(&nbr->initdelay_timer, &tv) == -1)
410 		fatal("nbr_start_idtimer");
411 }
412 
413 void
414 nbr_stop_idtimer(struct nbr *nbr)
415 {
416 	if (evtimer_pending(&nbr->initdelay_timer, NULL) &&
417 	    evtimer_del(&nbr->initdelay_timer) == -1)
418 		fatal("nbr_stop_idtimer");
419 }
420 
421 int
422 nbr_pending_idtimer(struct nbr *nbr)
423 {
424 	if (evtimer_pending(&nbr->initdelay_timer, NULL))
425 		return (1);
426 
427 	return (0);
428 }
429 
430 int
431 nbr_pending_connect(struct nbr *nbr)
432 {
433 	if (event_initialized(&nbr->ev_connect) &&
434 	    event_pending(&nbr->ev_connect, EV_WRITE, NULL))
435 		return (1);
436 
437 	return (0);
438 }
439 
440 static void
441 nbr_connect_cb(int fd, short event, void *arg)
442 {
443 	struct nbr	*nbr = arg;
444 	int		 error;
445 	socklen_t	 len;
446 
447 	len = sizeof(error);
448 	if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
449 		log_warn("nbr_connect_cb getsockopt SOL_SOCKET SO_ERROR");
450 		return;
451 	}
452 
453 	if (error) {
454 		close(nbr->fd);
455 		errno = error;
456 		log_debug("nbr_connect_cb: error while "
457 		    "connecting to %s: %s", inet_ntoa(nbr->addr),
458 		    strerror(errno));
459 		return;
460 	}
461 
462 	nbr_fsm(nbr, NBR_EVT_CONNECT_UP);
463 }
464 
465 int
466 nbr_establish_connection(struct nbr *nbr)
467 {
468 	struct sockaddr_in	local_sa;
469 	struct sockaddr_in	remote_sa;
470 	struct adj		*adj;
471 
472 	nbr->fd = socket(AF_INET, SOCK_STREAM, 0);
473 	if (nbr->fd == -1) {
474 		log_warn("nbr_establish_connection: error while "
475 		    "creating socket");
476 		return (-1);
477 	}
478 
479 	session_socket_blockmode(nbr->fd, BM_NONBLOCK);
480 
481 	bzero(&local_sa, sizeof(local_sa));
482 	local_sa.sin_family = AF_INET;
483 	local_sa.sin_port = htons(0);
484 	local_sa.sin_addr.s_addr = ldpe_router_id();
485 
486 	if (bind(nbr->fd, (struct sockaddr *) &local_sa,
487 	    sizeof(struct sockaddr_in)) == -1) {
488 		log_warn("nbr_establish_connection: error while "
489 		    "binding socket to %s", inet_ntoa(local_sa.sin_addr));
490 		close(nbr->fd);
491 		return (-1);
492 	}
493 
494 	bzero(&remote_sa, sizeof(remote_sa));
495 	remote_sa.sin_family = AF_INET;
496 	remote_sa.sin_port = htons(LDP_PORT);
497 	remote_sa.sin_addr.s_addr = nbr->addr.s_addr;
498 
499 	/*
500 	 * Send an extra hello to guarantee that the remote peer has formed
501 	 * an adjacency as well.
502 	 */
503 	LIST_FOREACH(adj, &nbr->adj_list, nbr_entry)
504 		send_hello(adj->source.type, adj->source.link.iface,
505 		    adj->source.target);
506 
507 	if (connect(nbr->fd, (struct sockaddr *)&remote_sa,
508 	    sizeof(remote_sa)) == -1) {
509 		if (errno == EINPROGRESS) {
510 			event_set(&nbr->ev_connect, nbr->fd, EV_WRITE,
511 			    nbr_connect_cb, nbr);
512 			event_add(&nbr->ev_connect, NULL);
513 			return (0);
514 		}
515 		log_warn("nbr_establish_connection: error while "
516 		    "connecting to %s", inet_ntoa(nbr->addr));
517 		close(nbr->fd);
518 		return (-1);
519 	}
520 
521 	/* connection completed immediately */
522 	nbr_fsm(nbr, NBR_EVT_CONNECT_UP);
523 
524 	return (0);
525 }
526 
527 int
528 nbr_act_session_operational(struct nbr *nbr)
529 {
530 	nbr->idtimer_cnt = 0;
531 
532 	return (ldpe_imsg_compose_lde(IMSG_NEIGHBOR_UP, nbr->peerid, 0,
533 	    &nbr->id, sizeof(nbr->id)));
534 }
535 
536 void
537 nbr_send_labelmappings(struct nbr *nbr)
538 {
539 	if (leconf->mode & MODE_ADV_UNSOLICITED) {
540 		ldpe_imsg_compose_lde(IMSG_LABEL_MAPPING_FULL, nbr->peerid, 0,
541 		    NULL, 0);
542 	}
543 }
544 
545 void
546 nbr_mapping_add(struct nbr *nbr, struct mapping_head *mh, struct map *map)
547 {
548 	struct mapping_entry	*me;
549 
550 	me = calloc(1, sizeof(*me));
551 	if (me == NULL)
552 		fatal("nbr_mapping_add");
553 	me->map = *map;
554 
555 	TAILQ_INSERT_TAIL(mh, me, entry);
556 }
557 
558 struct mapping_entry *
559 nbr_mapping_find(struct nbr *nbr, struct mapping_head *mh, struct map *map)
560 {
561 	struct mapping_entry	*me = NULL;
562 
563 	TAILQ_FOREACH(me, mh, entry) {
564 		if (me->map.prefix.s_addr == map->prefix.s_addr &&
565 		    me->map.prefixlen == map->prefixlen)
566 			return (me);
567 	}
568 
569 	return (NULL);
570 }
571 
572 void
573 nbr_mapping_del(struct nbr *nbr, struct mapping_head *mh, struct map *map)
574 {
575 	struct mapping_entry	*me;
576 
577 	me = nbr_mapping_find(nbr, mh, map);
578 	if (me == NULL)
579 		return;
580 
581 	TAILQ_REMOVE(mh, me, entry);
582 	free(me);
583 }
584 
585 void
586 mapping_list_clr(struct mapping_head *mh)
587 {
588 	struct mapping_entry	*me;
589 
590 	while ((me = TAILQ_FIRST(mh)) != NULL) {
591 		TAILQ_REMOVE(mh, me, entry);
592 		free(me);
593 	}
594 }
595 
596 struct ctl_nbr *
597 nbr_to_ctl(struct nbr *nbr)
598 {
599 	static struct ctl_nbr	 nctl;
600 	struct timeval		 now;
601 
602 	memcpy(&nctl.id, &nbr->id, sizeof(nctl.id));
603 	memcpy(&nctl.addr, &nbr->addr, sizeof(nctl.addr));
604 	nctl.nbr_state = nbr->state;
605 
606 	gettimeofday(&now, NULL);
607 	if (nbr->state == NBR_STA_OPER) {
608 		nctl.uptime = now.tv_sec - nbr->uptime;
609 	} else
610 		nctl.uptime = 0;
611 
612 	return (&nctl);
613 }
614 
615 void
616 ldpe_nbr_ctl(struct ctl_conn *c)
617 {
618 	struct nbr	*nbr;
619 	struct ctl_nbr	*nctl;
620 
621 	RB_FOREACH(nbr, nbr_pid_head, &nbrs_by_pid) {
622 		nctl = nbr_to_ctl(nbr);
623 		imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
624 		    sizeof(struct ctl_nbr));
625 	}
626 	imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
627 }
628