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
36static __inline int	 nbr_id_compare(struct nbr *, struct nbr *);
37static __inline int	 nbr_addr_compare(struct nbr *, struct nbr *);
38static __inline int	 nbr_pid_compare(struct nbr *, struct nbr *);
39static void		 nbr_update_peerid(struct nbr *);
40static void		 nbr_ktimer(int, short, void *);
41static void		 nbr_start_ktimer(struct nbr *);
42static void		 nbr_ktimeout(int, short, void *);
43static void		 nbr_start_ktimeout(struct nbr *);
44static void		 nbr_itimeout(int, short, void *);
45static void		 nbr_start_itimeout(struct nbr *);
46static void		 nbr_idtimer(int, short, void *);
47static int		 nbr_act_session_operational(struct nbr *);
48static void		 nbr_send_labelmappings(struct nbr *);
49
50RB_GENERATE(nbr_id_head, nbr, id_tree, nbr_id_compare)
51RB_GENERATE(nbr_addr_head, nbr, addr_tree, nbr_addr_compare)
52RB_GENERATE(nbr_pid_head, nbr, pid_tree, nbr_pid_compare)
53
54struct {
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
80const 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
92const 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
103struct nbr_id_head nbrs_by_id = RB_INITIALIZER(&nbrs_by_id);
104struct nbr_addr_head nbrs_by_addr = RB_INITIALIZER(&nbrs_by_addr);
105struct nbr_pid_head nbrs_by_pid = RB_INITIALIZER(&nbrs_by_pid);
106
107static __inline int
108nbr_id_compare(struct nbr *a, struct nbr *b)
109{
110	return (ntohl(a->id.s_addr) - ntohl(b->id.s_addr));
111}
112
113static __inline int
114nbr_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
124static __inline int
125nbr_pid_compare(struct nbr *a, struct nbr *b)
126{
127	return (a->peerid - b->peerid);
128}
129
130int
131nbr_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
221struct nbr *
222nbr_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
286void
287nbr_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
315static void
316nbr_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
332struct nbr *
333nbr_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
340struct nbr *
341nbr_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
349struct nbr *
350nbr_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
357int
358nbr_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
370int
371nbr_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
383static void
384nbr_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
392static void
393nbr_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
404void
405nbr_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
414static void
415nbr_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
424static void
425nbr_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
436void
437nbr_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
446static void
447nbr_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
456static void
457nbr_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
467void
468nbr_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
477static void
478nbr_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
487void
488nbr_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
515void
516nbr_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
523int
524nbr_pending_idtimer(struct nbr *nbr)
525{
526	if (evtimer_pending(&nbr->initdelay_timer, NULL))
527		return (1);
528
529	return (0);
530}
531
532int
533nbr_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
542static void
543nbr_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
566int
567nbr_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
644int
645nbr_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
666int
667nbr_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
696int
697nbr_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
727static int
728nbr_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
746static void
747nbr_send_labelmappings(struct nbr *nbr)
748{
749	ldpe_imsg_compose_lde(IMSG_LABEL_MAPPING_FULL, nbr->peerid, 0,
750	    NULL, 0);
751}
752
753struct nbr_params *
754nbr_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
766struct nbr_params *
767nbr_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
778uint16_t
779nbr_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
790struct ctl_nbr *
791nbr_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
811void
812nbr_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