Bug Summary

File:src/usr.sbin/ldpd/lde.c
Warning:line 689, column 9
Access to field 'flags' results in a dereference of a null pointer (loaded from variable 'pw')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name lde.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/ldpd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/ldpd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/ldpd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/ldpd/lde.c
1/* $OpenBSD: lde.c,v 1.75 2021/01/19 15:23:25 claudio Exp $ */
2
3/*
4 * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
5 * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
6 * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
7 * Copyright (c) 2003, 2004 Henning Brauer <henning@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 <sys/socket.h>
25#include <netinet/in.h>
26#include <netmpls/mpls.h>
27#include <arpa/inet.h>
28#include <errno(*__errno()).h>
29#include <stdlib.h>
30#include <signal.h>
31#include <string.h>
32#include <pwd.h>
33#include <unistd.h>
34#include <limits.h>
35
36#include "ldp.h"
37#include "ldpd.h"
38#include "ldpe.h"
39#include "log.h"
40#include "lde.h"
41
42static void lde_sig_handler(int sig, short, void *);
43static __dead__attribute__((__noreturn__)) void lde_shutdown(void);
44static int lde_imsg_compose_parent(int, pid_t, void *, uint16_t);
45static void lde_dispatch_imsg(int, short, void *);
46static void lde_dispatch_parent(int, short, void *);
47static __inline int lde_nbr_compare(struct lde_nbr *,
48 struct lde_nbr *);
49static struct lde_nbr *lde_nbr_new(uint32_t, struct lde_nbr *);
50static void lde_nbr_del(struct lde_nbr *);
51static struct lde_nbr *lde_nbr_find(uint32_t);
52static void lde_nbr_clear(void);
53static void lde_nbr_addr_update(struct lde_nbr *,
54 struct lde_addr *, int);
55static void lde_map_free(void *);
56static int lde_address_add(struct lde_nbr *, struct lde_addr *);
57static int lde_address_del(struct lde_nbr *, struct lde_addr *);
58static void lde_address_list_free(struct lde_nbr *);
59
60RB_GENERATE(nbr_tree, lde_nbr, entry, lde_nbr_compare)void nbr_tree_RB_INSERT_COLOR(struct nbr_tree *head, struct lde_nbr
*elm) { struct lde_nbr *parent, *gparent, *tmp; while ((parent
= (elm)->entry.rbe_parent) && (parent)->entry.
rbe_color == 1) { gparent = (parent)->entry.rbe_parent; if
(parent == (gparent)->entry.rbe_left) { tmp = (gparent)->
entry.rbe_right; if (tmp && (tmp)->entry.rbe_color
== 1) { (tmp)->entry.rbe_color = 0; do { (parent)->entry
.rbe_color = 0; (gparent)->entry.rbe_color = 1; } while (0
); elm = gparent; continue; } if ((parent)->entry.rbe_right
== elm) { do { (tmp) = (parent)->entry.rbe_right; if (((parent
)->entry.rbe_right = (tmp)->entry.rbe_left)) { ((tmp)->
entry.rbe_left)->entry.rbe_parent = (parent); } do {} while
(0); if (((tmp)->entry.rbe_parent = (parent)->entry.rbe_parent
)) { if ((parent) == ((parent)->entry.rbe_parent)->entry
.rbe_left) ((parent)->entry.rbe_parent)->entry.rbe_left
= (tmp); else ((parent)->entry.rbe_parent)->entry.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->entry
.rbe_left = (parent); (parent)->entry.rbe_parent = (tmp); do
{} while (0); if (((tmp)->entry.rbe_parent)) do {} while (
0); } while (0); tmp = parent; parent = elm; elm = tmp; } do {
(parent)->entry.rbe_color = 0; (gparent)->entry.rbe_color
= 1; } while (0); do { (tmp) = (gparent)->entry.rbe_left;
if (((gparent)->entry.rbe_left = (tmp)->entry.rbe_right
)) { ((tmp)->entry.rbe_right)->entry.rbe_parent = (gparent
); } do {} while (0); if (((tmp)->entry.rbe_parent = (gparent
)->entry.rbe_parent)) { if ((gparent) == ((gparent)->entry
.rbe_parent)->entry.rbe_left) ((gparent)->entry.rbe_parent
)->entry.rbe_left = (tmp); else ((gparent)->entry.rbe_parent
)->entry.rbe_right = (tmp); } else (head)->rbh_root = (
tmp); (tmp)->entry.rbe_right = (gparent); (gparent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); } else { tmp = (gparent)->
entry.rbe_left; if (tmp && (tmp)->entry.rbe_color ==
1) { (tmp)->entry.rbe_color = 0; do { (parent)->entry.
rbe_color = 0; (gparent)->entry.rbe_color = 1; } while (0)
; elm = gparent; continue; } if ((parent)->entry.rbe_left ==
elm) { do { (tmp) = (parent)->entry.rbe_left; if (((parent
)->entry.rbe_left = (tmp)->entry.rbe_right)) { ((tmp)->
entry.rbe_right)->entry.rbe_parent = (parent); } do {} while
(0); if (((tmp)->entry.rbe_parent = (parent)->entry.rbe_parent
)) { if ((parent) == ((parent)->entry.rbe_parent)->entry
.rbe_left) ((parent)->entry.rbe_parent)->entry.rbe_left
= (tmp); else ((parent)->entry.rbe_parent)->entry.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->entry
.rbe_right = (parent); (parent)->entry.rbe_parent = (tmp);
do {} while (0); if (((tmp)->entry.rbe_parent)) do {} while
(0); } while (0); tmp = parent; parent = elm; elm = tmp; } do
{ (parent)->entry.rbe_color = 0; (gparent)->entry.rbe_color
= 1; } while (0); do { (tmp) = (gparent)->entry.rbe_right
; if (((gparent)->entry.rbe_right = (tmp)->entry.rbe_left
)) { ((tmp)->entry.rbe_left)->entry.rbe_parent = (gparent
); } do {} while (0); if (((tmp)->entry.rbe_parent = (gparent
)->entry.rbe_parent)) { if ((gparent) == ((gparent)->entry
.rbe_parent)->entry.rbe_left) ((gparent)->entry.rbe_parent
)->entry.rbe_left = (tmp); else ((gparent)->entry.rbe_parent
)->entry.rbe_right = (tmp); } else (head)->rbh_root = (
tmp); (tmp)->entry.rbe_left = (gparent); (gparent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); } } (head->rbh_root)->
entry.rbe_color = 0; } void nbr_tree_RB_REMOVE_COLOR(struct nbr_tree
*head, struct lde_nbr *parent, struct lde_nbr *elm) { struct
lde_nbr *tmp; while ((elm == ((void *)0) || (elm)->entry.
rbe_color == 0) && elm != (head)->rbh_root) { if (
(parent)->entry.rbe_left == elm) { tmp = (parent)->entry
.rbe_right; if ((tmp)->entry.rbe_color == 1) { do { (tmp)->
entry.rbe_color = 0; (parent)->entry.rbe_color = 1; } while
(0); do { (tmp) = (parent)->entry.rbe_right; if (((parent
)->entry.rbe_right = (tmp)->entry.rbe_left)) { ((tmp)->
entry.rbe_left)->entry.rbe_parent = (parent); } do {} while
(0); if (((tmp)->entry.rbe_parent = (parent)->entry.rbe_parent
)) { if ((parent) == ((parent)->entry.rbe_parent)->entry
.rbe_left) ((parent)->entry.rbe_parent)->entry.rbe_left
= (tmp); else ((parent)->entry.rbe_parent)->entry.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->entry
.rbe_left = (parent); (parent)->entry.rbe_parent = (tmp); do
{} while (0); if (((tmp)->entry.rbe_parent)) do {} while (
0); } while (0); tmp = (parent)->entry.rbe_right; } if (((
tmp)->entry.rbe_left == ((void *)0) || ((tmp)->entry.rbe_left
)->entry.rbe_color == 0) && ((tmp)->entry.rbe_right
== ((void *)0) || ((tmp)->entry.rbe_right)->entry.rbe_color
== 0)) { (tmp)->entry.rbe_color = 1; elm = parent; parent
= (elm)->entry.rbe_parent; } else { if ((tmp)->entry.rbe_right
== ((void *)0) || ((tmp)->entry.rbe_right)->entry.rbe_color
== 0) { struct lde_nbr *oleft; if ((oleft = (tmp)->entry.
rbe_left)) (oleft)->entry.rbe_color = 0; (tmp)->entry.rbe_color
= 1; do { (oleft) = (tmp)->entry.rbe_left; if (((tmp)->
entry.rbe_left = (oleft)->entry.rbe_right)) { ((oleft)->
entry.rbe_right)->entry.rbe_parent = (tmp); } do {} while (
0); if (((oleft)->entry.rbe_parent = (tmp)->entry.rbe_parent
)) { if ((tmp) == ((tmp)->entry.rbe_parent)->entry.rbe_left
) ((tmp)->entry.rbe_parent)->entry.rbe_left = (oleft); else
((tmp)->entry.rbe_parent)->entry.rbe_right = (oleft); }
else (head)->rbh_root = (oleft); (oleft)->entry.rbe_right
= (tmp); (tmp)->entry.rbe_parent = (oleft); do {} while (
0); if (((oleft)->entry.rbe_parent)) do {} while (0); } while
(0); tmp = (parent)->entry.rbe_right; } (tmp)->entry.rbe_color
= (parent)->entry.rbe_color; (parent)->entry.rbe_color
= 0; if ((tmp)->entry.rbe_right) ((tmp)->entry.rbe_right
)->entry.rbe_color = 0; do { (tmp) = (parent)->entry.rbe_right
; if (((parent)->entry.rbe_right = (tmp)->entry.rbe_left
)) { ((tmp)->entry.rbe_left)->entry.rbe_parent = (parent
); } do {} while (0); if (((tmp)->entry.rbe_parent = (parent
)->entry.rbe_parent)) { if ((parent) == ((parent)->entry
.rbe_parent)->entry.rbe_left) ((parent)->entry.rbe_parent
)->entry.rbe_left = (tmp); else ((parent)->entry.rbe_parent
)->entry.rbe_right = (tmp); } else (head)->rbh_root = (
tmp); (tmp)->entry.rbe_left = (parent); (parent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); elm = (head)->rbh_root; break
; } } else { tmp = (parent)->entry.rbe_left; if ((tmp)->
entry.rbe_color == 1) { do { (tmp)->entry.rbe_color = 0; (
parent)->entry.rbe_color = 1; } while (0); do { (tmp) = (parent
)->entry.rbe_left; if (((parent)->entry.rbe_left = (tmp
)->entry.rbe_right)) { ((tmp)->entry.rbe_right)->entry
.rbe_parent = (parent); } do {} while (0); if (((tmp)->entry
.rbe_parent = (parent)->entry.rbe_parent)) { if ((parent) ==
((parent)->entry.rbe_parent)->entry.rbe_left) ((parent
)->entry.rbe_parent)->entry.rbe_left = (tmp); else ((parent
)->entry.rbe_parent)->entry.rbe_right = (tmp); } else (
head)->rbh_root = (tmp); (tmp)->entry.rbe_right = (parent
); (parent)->entry.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry.rbe_parent)) do {} while (0); } while (0);
tmp = (parent)->entry.rbe_left; } if (((tmp)->entry.rbe_left
== ((void *)0) || ((tmp)->entry.rbe_left)->entry.rbe_color
== 0) && ((tmp)->entry.rbe_right == ((void *)0) ||
((tmp)->entry.rbe_right)->entry.rbe_color == 0)) { (tmp
)->entry.rbe_color = 1; elm = parent; parent = (elm)->entry
.rbe_parent; } else { if ((tmp)->entry.rbe_left == ((void *
)0) || ((tmp)->entry.rbe_left)->entry.rbe_color == 0) {
struct lde_nbr *oright; if ((oright = (tmp)->entry.rbe_right
)) (oright)->entry.rbe_color = 0; (tmp)->entry.rbe_color
= 1; do { (oright) = (tmp)->entry.rbe_right; if (((tmp)->
entry.rbe_right = (oright)->entry.rbe_left)) { ((oright)->
entry.rbe_left)->entry.rbe_parent = (tmp); } do {} while (
0); if (((oright)->entry.rbe_parent = (tmp)->entry.rbe_parent
)) { if ((tmp) == ((tmp)->entry.rbe_parent)->entry.rbe_left
) ((tmp)->entry.rbe_parent)->entry.rbe_left = (oright);
else ((tmp)->entry.rbe_parent)->entry.rbe_right = (oright
); } else (head)->rbh_root = (oright); (oright)->entry.
rbe_left = (tmp); (tmp)->entry.rbe_parent = (oright); do {
} while (0); if (((oright)->entry.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->entry.rbe_left; } (tmp)
->entry.rbe_color = (parent)->entry.rbe_color; (parent)
->entry.rbe_color = 0; if ((tmp)->entry.rbe_left) ((tmp
)->entry.rbe_left)->entry.rbe_color = 0; do { (tmp) = (
parent)->entry.rbe_left; if (((parent)->entry.rbe_left =
(tmp)->entry.rbe_right)) { ((tmp)->entry.rbe_right)->
entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->
entry.rbe_parent = (parent)->entry.rbe_parent)) { if ((parent
) == ((parent)->entry.rbe_parent)->entry.rbe_left) ((parent
)->entry.rbe_parent)->entry.rbe_left = (tmp); else ((parent
)->entry.rbe_parent)->entry.rbe_right = (tmp); } else (
head)->rbh_root = (tmp); (tmp)->entry.rbe_right = (parent
); (parent)->entry.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry.rbe_parent)) do {} while (0); } while (0);
elm = (head)->rbh_root; break; } } } if (elm) (elm)->entry
.rbe_color = 0; } struct lde_nbr * nbr_tree_RB_REMOVE(struct nbr_tree
*head, struct lde_nbr *elm) { struct lde_nbr *child, *parent
, *old = elm; int color; if ((elm)->entry.rbe_left == ((void
*)0)) child = (elm)->entry.rbe_right; else if ((elm)->
entry.rbe_right == ((void *)0)) child = (elm)->entry.rbe_left
; else { struct lde_nbr *left; elm = (elm)->entry.rbe_right
; while ((left = (elm)->entry.rbe_left)) elm = left; child
= (elm)->entry.rbe_right; parent = (elm)->entry.rbe_parent
; color = (elm)->entry.rbe_color; if (child) (child)->entry
.rbe_parent = parent; if (parent) { if ((parent)->entry.rbe_left
== elm) (parent)->entry.rbe_left = child; else (parent)->
entry.rbe_right = child; do {} while (0); } else (head)->rbh_root
= child; if ((elm)->entry.rbe_parent == old) parent = elm
; (elm)->entry = (old)->entry; if ((old)->entry.rbe_parent
) { if (((old)->entry.rbe_parent)->entry.rbe_left == old
) ((old)->entry.rbe_parent)->entry.rbe_left = elm; else
((old)->entry.rbe_parent)->entry.rbe_right = elm; do {
} while (0); } else (head)->rbh_root = elm; ((old)->entry
.rbe_left)->entry.rbe_parent = elm; if ((old)->entry.rbe_right
) ((old)->entry.rbe_right)->entry.rbe_parent = elm; if (
parent) { left = parent; do { do {} while (0); } while ((left
= (left)->entry.rbe_parent)); } goto color; } parent = (elm
)->entry.rbe_parent; color = (elm)->entry.rbe_color; if
(child) (child)->entry.rbe_parent = parent; if (parent) {
if ((parent)->entry.rbe_left == elm) (parent)->entry.rbe_left
= child; else (parent)->entry.rbe_right = child; do {} while
(0); } else (head)->rbh_root = child; color: if (color ==
0) nbr_tree_RB_REMOVE_COLOR(head, parent, child); return (old
); } struct lde_nbr * nbr_tree_RB_INSERT(struct nbr_tree *head
, struct lde_nbr *elm) { struct lde_nbr *tmp; struct lde_nbr *
parent = ((void *)0); int comp = 0; tmp = (head)->rbh_root
; while (tmp) { parent = tmp; comp = (lde_nbr_compare)(elm, parent
); if (comp < 0) tmp = (tmp)->entry.rbe_left; else if (
comp > 0) tmp = (tmp)->entry.rbe_right; else return (tmp
); } do { (elm)->entry.rbe_parent = parent; (elm)->entry
.rbe_left = (elm)->entry.rbe_right = ((void *)0); (elm)->
entry.rbe_color = 1; } while (0); if (parent != ((void *)0)) {
if (comp < 0) (parent)->entry.rbe_left = elm; else (parent
)->entry.rbe_right = elm; do {} while (0); } else (head)->
rbh_root = elm; nbr_tree_RB_INSERT_COLOR(head, elm); return (
((void *)0)); } struct lde_nbr * nbr_tree_RB_FIND(struct nbr_tree
*head, struct lde_nbr *elm) { struct lde_nbr *tmp = (head)->
rbh_root; int comp; while (tmp) { comp = lde_nbr_compare(elm,
tmp); if (comp < 0) tmp = (tmp)->entry.rbe_left; else if
(comp > 0) tmp = (tmp)->entry.rbe_right; else return (
tmp); } return (((void *)0)); } struct lde_nbr * nbr_tree_RB_NFIND
(struct nbr_tree *head, struct lde_nbr *elm) { struct lde_nbr
*tmp = (head)->rbh_root; struct lde_nbr *res = ((void *)0
); int comp; while (tmp) { comp = lde_nbr_compare(elm, tmp); if
(comp < 0) { res = tmp; tmp = (tmp)->entry.rbe_left; }
else if (comp > 0) tmp = (tmp)->entry.rbe_right; else return
(tmp); } return (res); } struct lde_nbr * nbr_tree_RB_NEXT(struct
lde_nbr *elm) { if ((elm)->entry.rbe_right) { elm = (elm)
->entry.rbe_right; while ((elm)->entry.rbe_left) elm = (
elm)->entry.rbe_left; } else { if ((elm)->entry.rbe_parent
&& (elm == ((elm)->entry.rbe_parent)->entry.rbe_left
)) elm = (elm)->entry.rbe_parent; else { while ((elm)->
entry.rbe_parent && (elm == ((elm)->entry.rbe_parent
)->entry.rbe_right)) elm = (elm)->entry.rbe_parent; elm
= (elm)->entry.rbe_parent; } } return (elm); } struct lde_nbr
* nbr_tree_RB_PREV(struct lde_nbr *elm) { if ((elm)->entry
.rbe_left) { elm = (elm)->entry.rbe_left; while ((elm)->
entry.rbe_right) elm = (elm)->entry.rbe_right; } else { if
((elm)->entry.rbe_parent && (elm == ((elm)->entry
.rbe_parent)->entry.rbe_right)) elm = (elm)->entry.rbe_parent
; else { while ((elm)->entry.rbe_parent && (elm ==
((elm)->entry.rbe_parent)->entry.rbe_left)) elm = (elm
)->entry.rbe_parent; elm = (elm)->entry.rbe_parent; } }
return (elm); } struct lde_nbr * nbr_tree_RB_MINMAX(struct nbr_tree
*head, int val) { struct lde_nbr *tmp = (head)->rbh_root;
struct lde_nbr *parent = ((void *)0); while (tmp) { parent =
tmp; if (val < 0) tmp = (tmp)->entry.rbe_left; else tmp
= (tmp)->entry.rbe_right; } return (parent); }
61
62struct ldpd_conf *ldeconf;
63struct nbr_tree lde_nbrs = RB_INITIALIZER(&lde_nbrs){ ((void *)0) };
64
65static struct imsgev *iev_ldpe;
66static struct imsgev *iev_main;
67
68/* ARGSUSED */
69static void
70lde_sig_handler(int sig, short event, void *arg)
71{
72 /*
73 * signal handler rules don't apply, libevent decouples for us
74 */
75
76 switch (sig) {
77 case SIGINT2:
78 case SIGTERM15:
79 lde_shutdown();
80 /* NOTREACHED */
81 default:
82 fatalx("unexpected signal");
83 }
84}
85
86/* label decision engine */
87void
88lde(int debug, int verbose)
89{
90 struct event ev_sigint, ev_sigterm;
91 struct timeval now;
92 struct passwd *pw;
93
94 ldeconf = config_new_empty();
95
96 log_init(debug);
97 log_verbose(verbose);
98
99 setproctitle("label decision engine");
100 ldpd_process = PROC_LDE_ENGINE;
101 log_procname = "lde";
102
103 if ((pw = getpwnam(LDPD_USER"_ldpd")) == NULL((void *)0))
104 fatal("getpwnam");
105
106 if (chroot(pw->pw_dir) == -1)
107 fatal("chroot");
108 if (chdir("/") == -1)
109 fatal("chdir(\"/\")");
110
111 if (setgroups(1, &pw->pw_gid) ||
112 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
113 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
114 fatal("can't drop privileges");
115
116 if (pledge("stdio recvfd", NULL((void *)0)) == -1)
117 fatal("pledge");
118
119 event_init();
120
121 /* setup signal handler */
122 signal_set(&ev_sigint, SIGINT, lde_sig_handler, NULL)event_set(&ev_sigint, 2, 0x08|0x10, lde_sig_handler, ((void
*)0))
;
123 signal_set(&ev_sigterm, SIGTERM, lde_sig_handler, NULL)event_set(&ev_sigterm, 15, 0x08|0x10, lde_sig_handler, ((
void *)0))
;
124 signal_add(&ev_sigint, NULL)event_add(&ev_sigint, ((void *)0));
125 signal_add(&ev_sigterm, NULL)event_add(&ev_sigterm, ((void *)0));
126 signal(SIGPIPE13, SIG_IGN(void (*)(int))1);
127 signal(SIGHUP1, SIG_IGN(void (*)(int))1);
128
129 /* setup pipe and event handler to the parent process */
130 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL((void *)0))
131 fatal(NULL((void *)0));
132 imsg_init(&iev_main->ibuf, 3);
133 iev_main->handler = lde_dispatch_parent;
134 iev_main->events = EV_READ0x02;
135 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
136 iev_main->handler, iev_main);
137 event_add(&iev_main->ev, NULL((void *)0));
138
139 /* setup and start the LIB garbage collector */
140 evtimer_set(&gc_timer, lde_gc_timer, NULL)event_set(&gc_timer, -1, 0, lde_gc_timer, ((void *)0));
141 lde_gc_start_timer();
142
143 gettimeofday(&now, NULL((void *)0));
144 global.uptime = now.tv_sec;
145
146 event_dispatch();
147
148 lde_shutdown();
149}
150
151static __dead__attribute__((__noreturn__)) void
152lde_shutdown(void)
153{
154 /* close pipes */
155 msgbuf_clear(&iev_ldpe->ibuf.w);
156 close(iev_ldpe->ibuf.fd);
157 msgbuf_clear(&iev_main->ibuf.w);
158 close(iev_main->ibuf.fd);
159
160 lde_gc_stop_timer();
161 lde_nbr_clear();
162 fec_tree_clear();
163
164 config_clear(ldeconf);
165
166 free(iev_ldpe);
167 free(iev_main);
168
169 log_info("label decision engine exiting");
170 exit(0);
171}
172
173/* imesg */
174static int
175lde_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen)
176{
177 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
178}
179
180int
181lde_imsg_compose_ldpe(int type, uint32_t peerid, pid_t pid, void *data,
182 uint16_t datalen)
183{
184 return (imsg_compose_event(iev_ldpe, type, peerid, pid,
185 -1, data, datalen));
186}
187
188/* ARGSUSED */
189static void
190lde_dispatch_imsg(int fd, short event, void *bula)
191{
192 struct imsgev *iev = bula;
193 struct imsgbuf *ibuf = &iev->ibuf;
194 struct imsg imsg;
195 struct lde_nbr *ln;
196 struct map map;
197 struct lde_addr lde_addr;
198 struct notify_msg nm;
199 ssize_t n;
200 int shut = 0, verbose;
201
202 if (event & EV_READ0x02) {
1
Assuming the condition is false
2
Taking false branch
203 if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35)
204 fatal("imsg_read error");
205 if (n == 0) /* connection closed */
206 shut = 1;
207 }
208 if (event & EV_WRITE0x04) {
3
Assuming the condition is false
4
Taking false branch
209 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35)
210 fatal("msgbuf_write");
211 if (n == 0) /* connection closed */
212 shut = 1;
213 }
214
215 for (;;) {
5
Loop condition is true. Entering loop body
216 if ((n = imsg_get(ibuf, &imsg)) == -1)
6
Assuming the condition is false
7
Taking false branch
217 fatal("lde_dispatch_imsg: imsg_get error");
218 if (n == 0)
8
Assuming 'n' is not equal to 0
9
Taking false branch
219 break;
220
221 switch (imsg.hdr.type) {
10
Control jumps to 'case IMSG_NEIGHBOR_DOWN:' at line 337
222 case IMSG_LABEL_MAPPING_FULL:
223 ln = lde_nbr_find(imsg.hdr.peerid);
224 if (ln == NULL((void *)0)) {
225 log_debug("%s: cannot find lde neighbor",
226 __func__);
227 break;
228 }
229
230 fec_snap(ln);
231 break;
232 case IMSG_LABEL_MAPPING:
233 case IMSG_LABEL_REQUEST:
234 case IMSG_LABEL_RELEASE:
235 case IMSG_LABEL_WITHDRAW:
236 case IMSG_LABEL_ABORT:
237 if (imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr) != sizeof(map))
238 fatalx("lde_dispatch_imsg: wrong imsg len");
239 memcpy(&map, imsg.data, sizeof(map));
240
241 ln = lde_nbr_find(imsg.hdr.peerid);
242 if (ln == NULL((void *)0)) {
243 log_debug("%s: cannot find lde neighbor",
244 __func__);
245 break;
246 }
247
248 switch (imsg.hdr.type) {
249 case IMSG_LABEL_MAPPING:
250 lde_check_mapping(&map, ln);
251 break;
252 case IMSG_LABEL_REQUEST:
253 lde_check_request(&map, ln);
254 break;
255 case IMSG_LABEL_RELEASE:
256 lde_check_release(&map, ln);
257 break;
258 case IMSG_LABEL_WITHDRAW:
259 lde_check_withdraw(&map, ln);
260 break;
261 case IMSG_LABEL_ABORT:
262 /* not necessary */
263 break;
264 }
265 break;
266 case IMSG_ADDRESS_ADD:
267 if (imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr) != sizeof(lde_addr))
268 fatalx("lde_dispatch_imsg: wrong imsg len");
269 memcpy(&lde_addr, imsg.data, sizeof(lde_addr));
270
271 ln = lde_nbr_find(imsg.hdr.peerid);
272 if (ln == NULL((void *)0)) {
273 log_debug("%s: cannot find lde neighbor",
274 __func__);
275 break;
276 }
277 if (lde_address_add(ln, &lde_addr) < 0) {
278 log_debug("%s: cannot add address %s, it "
279 "already exists", __func__,
280 log_addr(lde_addr.af, &lde_addr.addr));
281 }
282 break;
283 case IMSG_ADDRESS_DEL:
284 if (imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr) != sizeof(lde_addr))
285 fatalx("lde_dispatch_imsg: wrong imsg len");
286 memcpy(&lde_addr, imsg.data, sizeof(lde_addr));
287
288 ln = lde_nbr_find(imsg.hdr.peerid);
289 if (ln == NULL((void *)0)) {
290 log_debug("%s: cannot find lde neighbor",
291 __func__);
292 break;
293 }
294 if (lde_address_del(ln, &lde_addr) < 0) {
295 log_debug("%s: cannot delete address %s, it "
296 "does not exist", __func__,
297 log_addr(lde_addr.af, &lde_addr.addr));
298 }
299 break;
300 case IMSG_NOTIFICATION:
301 if (imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr) != sizeof(nm))
302 fatalx("lde_dispatch_imsg: wrong imsg len");
303 memcpy(&nm, imsg.data, sizeof(nm));
304
305 ln = lde_nbr_find(imsg.hdr.peerid);
306 if (ln == NULL((void *)0)) {
307 log_debug("%s: cannot find lde neighbor",
308 __func__);
309 break;
310 }
311
312 switch (nm.status_code) {
313 case S_PW_STATUS0x00000028:
314 l2vpn_recv_pw_status(ln, &nm);
315 break;
316 case S_ENDOFLIB0x0000002F:
317 /*
318 * Do nothing for now. Should be useful in
319 * the future when we implement LDP-IGP
320 * Synchronization (RFC 5443) and Graceful
321 * Restart (RFC 3478).
322 */
323 default:
324 break;
325 }
326 break;
327 case IMSG_NEIGHBOR_UP:
328 if (imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr) !=
329 sizeof(struct lde_nbr))
330 fatalx("lde_dispatch_imsg: wrong imsg len");
331
332 if (lde_nbr_find(imsg.hdr.peerid))
333 fatalx("lde_dispatch_imsg: "
334 "neighbor already exists");
335 lde_nbr_new(imsg.hdr.peerid, imsg.data);
336 break;
337 case IMSG_NEIGHBOR_DOWN:
338 lde_nbr_del(lde_nbr_find(imsg.hdr.peerid));
11
Calling 'lde_nbr_del'
339 break;
340 case IMSG_CTL_SHOW_LIB:
341 rt_dump(imsg.hdr.pid);
342
343 lde_imsg_compose_ldpe(IMSG_CTL_END, 0,
344 imsg.hdr.pid, NULL((void *)0), 0);
345 break;
346 case IMSG_CTL_SHOW_L2VPN_PW:
347 l2vpn_pw_ctl(imsg.hdr.pid);
348
349 lde_imsg_compose_ldpe(IMSG_CTL_END, 0,
350 imsg.hdr.pid, NULL((void *)0), 0);
351 break;
352 case IMSG_CTL_SHOW_L2VPN_BINDING:
353 l2vpn_binding_ctl(imsg.hdr.pid);
354
355 lde_imsg_compose_ldpe(IMSG_CTL_END, 0,
356 imsg.hdr.pid, NULL((void *)0), 0);
357 break;
358 case IMSG_CTL_LOG_VERBOSE:
359 /* already checked by ldpe */
360 memcpy(&verbose, imsg.data, sizeof(verbose));
361 log_verbose(verbose);
362 break;
363 default:
364 log_debug("%s: unexpected imsg %d", __func__,
365 imsg.hdr.type);
366 break;
367 }
368 imsg_free(&imsg);
369 }
370 if (!shut)
371 imsg_event_add(iev);
372 else {
373 /* this pipe is dead, so remove the event handler */
374 event_del(&iev->ev);
375 event_loopexit(NULL((void *)0));
376 }
377}
378
379/* ARGSUSED */
380static void
381lde_dispatch_parent(int fd, short event, void *bula)
382{
383 static struct ldpd_conf *nconf;
384 struct iface *niface;
385 struct tnbr *ntnbr;
386 struct nbr_params *nnbrp;
387 static struct l2vpn *nl2vpn;
388 struct l2vpn_if *nlif;
389 struct l2vpn_pw *npw;
390 struct imsg imsg;
391 struct kroute kr;
392 struct imsgev *iev = bula;
393 struct imsgbuf *ibuf = &iev->ibuf;
394 ssize_t n;
395 int shut = 0;
396 struct fec fec;
397
398 if (event & EV_READ0x02) {
399 if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35)
400 fatal("imsg_read error");
401 if (n == 0) /* connection closed */
402 shut = 1;
403 }
404 if (event & EV_WRITE0x04) {
405 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35)
406 fatal("msgbuf_write");
407 if (n == 0) /* connection closed */
408 shut = 1;
409 }
410
411 for (;;) {
412 if ((n = imsg_get(ibuf, &imsg)) == -1)
413 fatal("lde_dispatch_parent: imsg_get error");
414 if (n == 0)
415 break;
416
417 switch (imsg.hdr.type) {
418 case IMSG_NETWORK_ADD:
419 case IMSG_NETWORK_DEL:
420 if (imsg.hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + sizeof(kr)) {
421 log_warnx("%s: wrong imsg len", __func__);
422 break;
423 }
424 memcpy(&kr, imsg.data, sizeof(kr));
425
426 switch (kr.af) {
427 case AF_INET2:
428 fec.type = FEC_TYPE_IPV4;
429 fec.u.ipv4.prefix = kr.prefix.v4;
430 fec.u.ipv4.prefixlen = kr.prefixlen;
431 break;
432 case AF_INET624:
433 fec.type = FEC_TYPE_IPV6;
434 fec.u.ipv6.prefix = kr.prefix.v6;
435 fec.u.ipv6.prefixlen = kr.prefixlen;
436 break;
437 default:
438 fatalx("lde_dispatch_parent: unknown af");
439 }
440
441 switch (imsg.hdr.type) {
442 case IMSG_NETWORK_ADD:
443 lde_kernel_insert(&fec, kr.af, &kr.nexthop,
444 kr.priority, kr.flags & F_CONNECTED0x0002, NULL((void *)0));
445 break;
446 case IMSG_NETWORK_DEL:
447 lde_kernel_remove(&fec, kr.af, &kr.nexthop,
448 kr.priority);
449 break;
450 }
451 break;
452 case IMSG_SOCKET_IPC:
453 if (iev_ldpe) {
454 log_warnx("%s: received unexpected imsg fd "
455 "to ldpe", __func__);
456 break;
457 }
458 if ((fd = imsg.fd) == -1) {
459 log_warnx("%s: expected to receive imsg fd to "
460 "ldpe but didn't receive any", __func__);
461 break;
462 }
463
464 if ((iev_ldpe = malloc(sizeof(struct imsgev))) == NULL((void *)0))
465 fatal(NULL((void *)0));
466 imsg_init(&iev_ldpe->ibuf, fd);
467 iev_ldpe->handler = lde_dispatch_imsg;
468 iev_ldpe->events = EV_READ0x02;
469 event_set(&iev_ldpe->ev, iev_ldpe->ibuf.fd,
470 iev_ldpe->events, iev_ldpe->handler, iev_ldpe);
471 event_add(&iev_ldpe->ev, NULL((void *)0));
472 break;
473 case IMSG_RECONF_CONF:
474 if ((nconf = malloc(sizeof(struct ldpd_conf))) ==
475 NULL((void *)0))
476 fatal(NULL((void *)0));
477 memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
478
479 LIST_INIT(&nconf->iface_list)do { ((&nconf->iface_list)->lh_first) = ((void *)0)
; } while (0)
;
480 LIST_INIT(&nconf->tnbr_list)do { ((&nconf->tnbr_list)->lh_first) = ((void *)0);
} while (0)
;
481 LIST_INIT(&nconf->nbrp_list)do { ((&nconf->nbrp_list)->lh_first) = ((void *)0);
} while (0)
;
482 LIST_INIT(&nconf->l2vpn_list)do { ((&nconf->l2vpn_list)->lh_first) = ((void *)0)
; } while (0)
;
483 LIST_INIT(&nconf->auth_list)do { ((&nconf->auth_list)->lh_first) = ((void *)0);
} while (0)
;
484 break;
485 case IMSG_RECONF_IFACE:
486 if ((niface = malloc(sizeof(struct iface))) == NULL((void *)0))
487 fatal(NULL((void *)0));
488 memcpy(niface, imsg.data, sizeof(struct iface));
489
490 LIST_INIT(&niface->addr_list)do { ((&niface->addr_list)->lh_first) = ((void *)0)
; } while (0)
;
491 LIST_INIT(&niface->ipv4.adj_list)do { ((&niface->ipv4.adj_list)->lh_first) = ((void *
)0); } while (0)
;
492 LIST_INIT(&niface->ipv6.adj_list)do { ((&niface->ipv6.adj_list)->lh_first) = ((void *
)0); } while (0)
;
493 niface->ipv4.iface = niface;
494 niface->ipv6.iface = niface;
495
496 LIST_INSERT_HEAD(&nconf->iface_list, niface, entry)do { if (((niface)->entry.le_next = (&nconf->iface_list
)->lh_first) != ((void *)0)) (&nconf->iface_list)->
lh_first->entry.le_prev = &(niface)->entry.le_next;
(&nconf->iface_list)->lh_first = (niface); (niface
)->entry.le_prev = &(&nconf->iface_list)->lh_first
; } while (0)
;
497 break;
498 case IMSG_RECONF_TNBR:
499 if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL((void *)0))
500 fatal(NULL((void *)0));
501 memcpy(ntnbr, imsg.data, sizeof(struct tnbr));
502
503 LIST_INSERT_HEAD(&nconf->tnbr_list, ntnbr, entry)do { if (((ntnbr)->entry.le_next = (&nconf->tnbr_list
)->lh_first) != ((void *)0)) (&nconf->tnbr_list)->
lh_first->entry.le_prev = &(ntnbr)->entry.le_next; (
&nconf->tnbr_list)->lh_first = (ntnbr); (ntnbr)->
entry.le_prev = &(&nconf->tnbr_list)->lh_first;
} while (0)
;
504 break;
505 case IMSG_RECONF_NBRP:
506 if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL((void *)0))
507 fatal(NULL((void *)0));
508 memcpy(nnbrp, imsg.data, sizeof(struct nbr_params));
509
510 LIST_INSERT_HEAD(&nconf->nbrp_list, nnbrp, entry)do { if (((nnbrp)->entry.le_next = (&nconf->nbrp_list
)->lh_first) != ((void *)0)) (&nconf->nbrp_list)->
lh_first->entry.le_prev = &(nnbrp)->entry.le_next; (
&nconf->nbrp_list)->lh_first = (nnbrp); (nnbrp)->
entry.le_prev = &(&nconf->nbrp_list)->lh_first;
} while (0)
;
511 break;
512 case IMSG_RECONF_L2VPN:
513 if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL((void *)0))
514 fatal(NULL((void *)0));
515 memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
516
517 LIST_INIT(&nl2vpn->if_list)do { ((&nl2vpn->if_list)->lh_first) = ((void *)0); }
while (0)
;
518 LIST_INIT(&nl2vpn->pw_list)do { ((&nl2vpn->pw_list)->lh_first) = ((void *)0); }
while (0)
;
519
520 LIST_INSERT_HEAD(&nconf->l2vpn_list, nl2vpn, entry)do { if (((nl2vpn)->entry.le_next = (&nconf->l2vpn_list
)->lh_first) != ((void *)0)) (&nconf->l2vpn_list)->
lh_first->entry.le_prev = &(nl2vpn)->entry.le_next;
(&nconf->l2vpn_list)->lh_first = (nl2vpn); (nl2vpn
)->entry.le_prev = &(&nconf->l2vpn_list)->lh_first
; } while (0)
;
521 break;
522 case IMSG_RECONF_L2VPN_IF:
523 if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL((void *)0))
524 fatal(NULL((void *)0));
525 memcpy(nlif, imsg.data, sizeof(struct l2vpn_if));
526
527 nlif->l2vpn = nl2vpn;
528 LIST_INSERT_HEAD(&nl2vpn->if_list, nlif, entry)do { if (((nlif)->entry.le_next = (&nl2vpn->if_list
)->lh_first) != ((void *)0)) (&nl2vpn->if_list)->
lh_first->entry.le_prev = &(nlif)->entry.le_next; (
&nl2vpn->if_list)->lh_first = (nlif); (nlif)->entry
.le_prev = &(&nl2vpn->if_list)->lh_first; } while
(0)
;
529 break;
530 case IMSG_RECONF_L2VPN_PW:
531 if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL((void *)0))
532 fatal(NULL((void *)0));
533 memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
534
535 npw->l2vpn = nl2vpn;
536 LIST_INSERT_HEAD(&nl2vpn->pw_list, npw, entry)do { if (((npw)->entry.le_next = (&nl2vpn->pw_list)
->lh_first) != ((void *)0)) (&nl2vpn->pw_list)->
lh_first->entry.le_prev = &(npw)->entry.le_next; (&
nl2vpn->pw_list)->lh_first = (npw); (npw)->entry.le_prev
= &(&nl2vpn->pw_list)->lh_first; } while (0)
;
537 break;
538 case IMSG_RECONF_CONF_AUTH: {
539 struct ldp_auth *auth;
540
541 auth = malloc(sizeof(*auth));
542 if (auth == NULL((void *)0))
543 fatal(NULL((void *)0));
544
545 memcpy(auth, imsg.data, sizeof(*auth));
546
547 LIST_INSERT_HEAD(&nconf->auth_list, auth, entry)do { if (((auth)->entry.le_next = (&nconf->auth_list
)->lh_first) != ((void *)0)) (&nconf->auth_list)->
lh_first->entry.le_prev = &(auth)->entry.le_next; (
&nconf->auth_list)->lh_first = (auth); (auth)->entry
.le_prev = &(&nconf->auth_list)->lh_first; } while
(0)
;
548 break;
549 }
550 case IMSG_RECONF_END:
551 merge_config(ldeconf, nconf);
552 nconf = NULL((void *)0);
553 break;
554 default:
555 log_debug("%s: unexpected imsg %d", __func__,
556 imsg.hdr.type);
557 break;
558 }
559 imsg_free(&imsg);
560 }
561 if (!shut)
562 imsg_event_add(iev);
563 else {
564 /* this pipe is dead, so remove the event handler */
565 event_del(&iev->ev);
566 event_loopexit(NULL((void *)0));
567 }
568}
569
570uint32_t
571lde_assign_label(void)
572{
573 static uint32_t label = MPLS_LABEL_RESERVED_MAX15;
574
575 /* XXX some checks needed */
576 label++;
577 return (label);
578}
579
580void
581lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh)
582{
583 struct kroute kr;
584 struct kpw kpw;
585 struct l2vpn_pw *pw;
586
587 switch (fn->fec.type) {
588 case FEC_TYPE_IPV4:
589 memset(&kr, 0, sizeof(kr));
590 kr.af = AF_INET2;
591 kr.prefix.v4 = fn->fec.u.ipv4.prefix;
592 kr.prefixlen = fn->fec.u.ipv4.prefixlen;
593 kr.nexthop.v4 = fnh->nexthop.v4;
594 kr.local_label = fn->local_label;
595 kr.remote_label = fnh->remote_label;
596 kr.priority = fnh->priority;
597
598 lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr,
599 sizeof(kr));
600
601 if (fn->fec.u.ipv4.prefixlen == 32)
602 l2vpn_sync_pws(AF_INET2, (union ldpd_addr *)
603 &fn->fec.u.ipv4.prefix);
604 break;
605 case FEC_TYPE_IPV6:
606 memset(&kr, 0, sizeof(kr));
607 kr.af = AF_INET624;
608 kr.prefix.v6 = fn->fec.u.ipv6.prefix;
609 kr.prefixlen = fn->fec.u.ipv6.prefixlen;
610 kr.nexthop.v6 = fnh->nexthop.v6;
611 kr.local_label = fn->local_label;
612 kr.remote_label = fnh->remote_label;
613 kr.priority = fnh->priority;
614
615 lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr,
616 sizeof(kr));
617
618 if (fn->fec.u.ipv6.prefixlen == 128)
619 l2vpn_sync_pws(AF_INET624, (union ldpd_addr *)
620 &fn->fec.u.ipv6.prefix);
621 break;
622 case FEC_TYPE_PWID:
623 if (fn->local_label == NO_LABEL0xffffffffU ||
624 fnh->remote_label == NO_LABEL0xffffffffU)
625 return;
626
627 pw = (struct l2vpn_pw *) fn->data;
628 pw->flags |= F_PW_STATUS_UP0x10;
629
630 memset(&kpw, 0, sizeof(kpw));
631 kpw.ifindex = pw->ifindex;
632 kpw.pw_type = fn->fec.u.pwid.type;
633 kpw.af = pw->af;
634 kpw.nexthop = pw->addr;
635 kpw.local_label = fn->local_label;
636 kpw.remote_label = fnh->remote_label;
637 kpw.flags = pw->flags;
638
639 lde_imsg_compose_parent(IMSG_KPWLABEL_CHANGE, 0, &kpw,
640 sizeof(kpw));
641 break;
642 }
643}
644
645void
646lde_send_delete_klabel(struct fec_node *fn, struct fec_nh *fnh)
647{
648 struct kroute kr;
649 struct kpw kpw;
650 struct l2vpn_pw *pw;
651
652 switch (fn->fec.type) {
24
Control jumps to 'case FEC_TYPE_PWID:' at line 687
653 case FEC_TYPE_IPV4:
654 memset(&kr, 0, sizeof(kr));
655 kr.af = AF_INET2;
656 kr.prefix.v4 = fn->fec.u.ipv4.prefix;
657 kr.prefixlen = fn->fec.u.ipv4.prefixlen;
658 kr.nexthop.v4 = fnh->nexthop.v4;
659 kr.local_label = fn->local_label;
660 kr.remote_label = fnh->remote_label;
661 kr.priority = fnh->priority;
662
663 lde_imsg_compose_parent(IMSG_KLABEL_DELETE, 0, &kr,
664 sizeof(kr));
665
666 if (fn->fec.u.ipv4.prefixlen == 32)
667 l2vpn_sync_pws(AF_INET2, (union ldpd_addr *)
668 &fn->fec.u.ipv4.prefix);
669 break;
670 case FEC_TYPE_IPV6:
671 memset(&kr, 0, sizeof(kr));
672 kr.af = AF_INET624;
673 kr.prefix.v6 = fn->fec.u.ipv6.prefix;
674 kr.prefixlen = fn->fec.u.ipv6.prefixlen;
675 kr.nexthop.v6 = fnh->nexthop.v6;
676 kr.local_label = fn->local_label;
677 kr.remote_label = fnh->remote_label;
678 kr.priority = fnh->priority;
679
680 lde_imsg_compose_parent(IMSG_KLABEL_DELETE, 0, &kr,
681 sizeof(kr));
682
683 if (fn->fec.u.ipv6.prefixlen == 128)
684 l2vpn_sync_pws(AF_INET624, (union ldpd_addr *)
685 &fn->fec.u.ipv6.prefix);
686 break;
687 case FEC_TYPE_PWID:
688 pw = (struct l2vpn_pw *) fn->data;
25
Null pointer value stored to 'pw'
689 if (!(pw->flags & F_PW_STATUS_UP0x10))
26
Access to field 'flags' results in a dereference of a null pointer (loaded from variable 'pw')
690 return;
691 pw->flags &= ~F_PW_STATUS_UP0x10;
692
693 memset(&kpw, 0, sizeof(kpw));
694 kpw.ifindex = pw->ifindex;
695 kpw.pw_type = fn->fec.u.pwid.type;
696 kpw.af = pw->af;
697 kpw.nexthop = pw->addr;
698 kpw.local_label = fn->local_label;
699 kpw.remote_label = fnh->remote_label;
700 kpw.flags = pw->flags;
701
702 lde_imsg_compose_parent(IMSG_KPWLABEL_DELETE, 0, &kpw,
703 sizeof(kpw));
704 break;
705 }
706}
707
708void
709lde_fec2map(struct fec *fec, struct map *map)
710{
711 memset(map, 0, sizeof(*map));
712
713 switch (fec->type) {
714 case FEC_TYPE_IPV4:
715 map->type = MAP_TYPE_PREFIX0x02;
716 map->fec.prefix.af = AF_INET2;
717 map->fec.prefix.prefix.v4 = fec->u.ipv4.prefix;
718 map->fec.prefix.prefixlen = fec->u.ipv4.prefixlen;
719 break;
720 case FEC_TYPE_IPV6:
721 map->type = MAP_TYPE_PREFIX0x02;
722 map->fec.prefix.af = AF_INET624;
723 map->fec.prefix.prefix.v6 = fec->u.ipv6.prefix;
724 map->fec.prefix.prefixlen = fec->u.ipv6.prefixlen;
725 break;
726 case FEC_TYPE_PWID:
727 map->type = MAP_TYPE_PWID0x80;
728 map->fec.pwid.type = fec->u.pwid.type;
729 map->fec.pwid.group_id = 0;
730 map->flags |= F_MAP_PW_ID0x08;
731 map->fec.pwid.pwid = fec->u.pwid.pwid;
732 break;
733 }
734}
735
736void
737lde_map2fec(struct map *map, struct in_addr lsr_id, struct fec *fec)
738{
739 memset(fec, 0, sizeof(*fec));
740
741 switch (map->type) {
742 case MAP_TYPE_PREFIX0x02:
743 switch (map->fec.prefix.af) {
744 case AF_INET2:
745 fec->type = FEC_TYPE_IPV4;
746 fec->u.ipv4.prefix = map->fec.prefix.prefix.v4;
747 fec->u.ipv4.prefixlen = map->fec.prefix.prefixlen;
748 break;
749 case AF_INET624:
750 fec->type = FEC_TYPE_IPV6;
751 fec->u.ipv6.prefix = map->fec.prefix.prefix.v6;
752 fec->u.ipv6.prefixlen = map->fec.prefix.prefixlen;
753 break;
754 default:
755 fatalx("lde_map2fec: unknown af");
756 break;
757 }
758 break;
759 case MAP_TYPE_PWID0x80:
760 fec->type = FEC_TYPE_PWID;
761 fec->u.pwid.type = map->fec.pwid.type;
762 fec->u.pwid.pwid = map->fec.pwid.pwid;
763 fec->u.pwid.lsr_id = lsr_id;
764 break;
765 }
766}
767
768void
769lde_send_labelmapping(struct lde_nbr *ln, struct fec_node *fn, int single)
770{
771 struct lde_req *lre;
772 struct lde_map *me;
773 struct map map;
774 struct l2vpn_pw *pw;
775
776 /*
777 * This function skips SL.1 - 3 and SL.9 - 14 because the label
778 * allocation is done way earlier (because of the merging nature of
779 * ldpd).
780 */
781
782 lde_fec2map(&fn->fec, &map);
783 switch (fn->fec.type) {
784 case FEC_TYPE_IPV4:
785 if (!ln->v4_enabled)
786 return;
787 break;
788 case FEC_TYPE_IPV6:
789 if (!ln->v6_enabled)
790 return;
791 break;
792 case FEC_TYPE_PWID:
793 pw = (struct l2vpn_pw *) fn->data;
794 if (pw == NULL((void *)0) || pw->lsr_id.s_addr != ln->id.s_addr)
795 /* not the remote end of the pseudowire */
796 return;
797
798 map.flags |= F_MAP_PW_IFMTU0x10;
799 map.fec.pwid.ifmtu = pw->l2vpn->mtu;
800 if (pw->flags & F_PW_CWORD0x08)
801 map.flags |= F_MAP_PW_CWORD0x04;
802 if (pw->flags & F_PW_STATUSTLV0x02) {
803 map.flags |= F_MAP_PW_STATUS0x20;
804 /* VPLS are always up */
805 map.pw_status = PW_FORWARDING0;
806 }
807 break;
808 }
809 map.label = fn->local_label;
810
811 /* SL.6: is there a pending request for this mapping? */
812 lre = (struct lde_req *)fec_find(&ln->recv_req, &fn->fec);
813 if (lre) {
814 /* set label request msg id in the mapping response. */
815 map.requestid = lre->msg_id;
816 map.flags = F_MAP_REQ_ID0x01;
817
818 /* SL.7: delete record of pending request */
819 lde_req_del(ln, lre, 0);
820 }
821
822 /* SL.4: send label mapping */
823 lde_imsg_compose_ldpe(IMSG_MAPPING_ADD, ln->peerid, 0,
824 &map, sizeof(map));
825 if (single)
826 lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid, 0,
827 NULL((void *)0), 0);
828
829 /* SL.5: record sent label mapping */
830 me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec);
831 if (me == NULL((void *)0))
832 me = lde_map_add(ln, fn, 1);
833 me->map = map;
834}
835
836void
837lde_send_labelwithdraw(struct lde_nbr *ln, struct fec_node *fn,
838 struct map *wcard, struct status_tlv *st)
839{
840 struct lde_wdraw *lw;
841 struct map map;
842 struct fec *f;
843 struct l2vpn_pw *pw;
844
845 if (fn) {
846 lde_fec2map(&fn->fec, &map);
847 switch (fn->fec.type) {
848 case FEC_TYPE_IPV4:
849 if (!ln->v4_enabled)
850 return;
851 break;
852 case FEC_TYPE_IPV6:
853 if (!ln->v6_enabled)
854 return;
855 break;
856 case FEC_TYPE_PWID:
857 pw = (struct l2vpn_pw *) fn->data;
858 if (pw == NULL((void *)0) || pw->lsr_id.s_addr != ln->id.s_addr)
859 /* not the remote end of the pseudowire */
860 return;
861
862 if (pw->flags & F_PW_CWORD0x08)
863 map.flags |= F_MAP_PW_CWORD0x04;
864 break;
865 }
866 map.label = fn->local_label;
867 } else
868 memcpy(&map, wcard, sizeof(map));
869
870 if (st) {
871 map.st.status_code = st->status_code;
872 map.st.msg_id = st->msg_id;
873 map.st.msg_type = st->msg_type;
874 map.flags |= F_MAP_STATUS0x02;
875 }
876
877 /* SWd.1: send label withdraw. */
878 lde_imsg_compose_ldpe(IMSG_WITHDRAW_ADD, ln->peerid, 0,
879 &map, sizeof(map));
880 lde_imsg_compose_ldpe(IMSG_WITHDRAW_ADD_END, ln->peerid, 0, NULL((void *)0), 0);
881
882 /* SWd.2: record label withdraw. */
883 if (fn) {
884 lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec);
885 if (lw == NULL((void *)0))
886 lw = lde_wdraw_add(ln, fn);
887 lw->label = map.label;
888 } else {
889 struct lde_map *me;
890
891 RB_FOREACH(f, fec_tree, &ft)for ((f) = fec_tree_RB_MINMAX(&ft, -1); (f) != ((void *)0
); (f) = fec_tree_RB_NEXT(f))
{
892 fn = (struct fec_node *)f;
893 me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec);
894 if (lde_wildcard_apply(wcard, &fn->fec, me) == 0)
895 continue;
896
897 lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw,
898 &fn->fec);
899 if (lw == NULL((void *)0))
900 lw = lde_wdraw_add(ln, fn);
901 lw->label = map.label;
902 }
903 }
904}
905
906void
907lde_send_labelwithdraw_wcard(struct lde_nbr *ln, uint32_t label)
908{
909 struct map wcard;
910
911 memset(&wcard, 0, sizeof(wcard));
912 wcard.type = MAP_TYPE_WILDCARD0x01;
913 wcard.label = label;
914 lde_send_labelwithdraw(ln, NULL((void *)0), &wcard, NULL((void *)0));
915}
916
917void
918lde_send_labelwithdraw_twcard_prefix(struct lde_nbr *ln, uint16_t af,
919 uint32_t label)
920{
921 struct map wcard;
922
923 memset(&wcard, 0, sizeof(wcard));
924 wcard.type = MAP_TYPE_TYPED_WCARD0x05;
925 wcard.fec.twcard.type = MAP_TYPE_PREFIX0x02;
926 wcard.fec.twcard.u.prefix_af = af;
927 wcard.label = label;
928 lde_send_labelwithdraw(ln, NULL((void *)0), &wcard, NULL((void *)0));
929}
930
931void
932lde_send_labelwithdraw_twcard_pwid(struct lde_nbr *ln, uint16_t pw_type,
933 uint32_t label)
934{
935 struct map wcard;
936
937 memset(&wcard, 0, sizeof(wcard));
938 wcard.type = MAP_TYPE_TYPED_WCARD0x05;
939 wcard.fec.twcard.type = MAP_TYPE_PWID0x80;
940 wcard.fec.twcard.u.pw_type = pw_type;
941 wcard.label = label;
942 lde_send_labelwithdraw(ln, NULL((void *)0), &wcard, NULL((void *)0));
943}
944
945void
946lde_send_labelwithdraw_pwid_wcard(struct lde_nbr *ln, uint16_t pw_type,
947 uint32_t group_id)
948{
949 struct map wcard;
950
951 memset(&wcard, 0, sizeof(wcard));
952 wcard.type = MAP_TYPE_PWID0x80;
953 wcard.fec.pwid.type = pw_type;
954 wcard.fec.pwid.group_id = group_id;
955 /* we can not append a Label TLV when using PWid group wildcards. */
956 wcard.label = NO_LABEL0xffffffffU;
957 lde_send_labelwithdraw(ln, NULL((void *)0), &wcard, NULL((void *)0));
958}
959
960void
961lde_send_labelrelease(struct lde_nbr *ln, struct fec_node *fn,
962 struct map *wcard, uint32_t label)
963{
964 struct map map;
965 struct l2vpn_pw *pw;
966
967 if (fn) {
968 lde_fec2map(&fn->fec, &map);
969 switch (fn->fec.type) {
970 case FEC_TYPE_IPV4:
971 if (!ln->v4_enabled)
972 return;
973 break;
974 case FEC_TYPE_IPV6:
975 if (!ln->v6_enabled)
976 return;
977 break;
978 case FEC_TYPE_PWID:
979 pw = (struct l2vpn_pw *) fn->data;
980 if (pw == NULL((void *)0) || pw->lsr_id.s_addr != ln->id.s_addr)
981 /* not the remote end of the pseudowire */
982 return;
983
984 if (pw->flags & F_PW_CWORD0x08)
985 map.flags |= F_MAP_PW_CWORD0x04;
986 break;
987 }
988 } else
989 memcpy(&map, wcard, sizeof(map));
990 map.label = label;
991
992 lde_imsg_compose_ldpe(IMSG_RELEASE_ADD, ln->peerid, 0,
993 &map, sizeof(map));
994 lde_imsg_compose_ldpe(IMSG_RELEASE_ADD_END, ln->peerid, 0, NULL((void *)0), 0);
995}
996
997void
998lde_send_notification(struct lde_nbr *ln, uint32_t status_code, uint32_t msg_id,
999 uint16_t msg_type)
1000{
1001 struct notify_msg nm;
1002
1003 memset(&nm, 0, sizeof(nm));
1004 nm.status_code = status_code;
1005 /* 'msg_id' and 'msg_type' should be in network byte order */
1006 nm.msg_id = msg_id;
1007 nm.msg_type = msg_type;
1008
1009 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0,
1010 &nm, sizeof(nm));
1011}
1012
1013void
1014lde_send_notification_eol_prefix(struct lde_nbr *ln, int af)
1015{
1016 struct notify_msg nm;
1017
1018 memset(&nm, 0, sizeof(nm));
1019 nm.status_code = S_ENDOFLIB0x0000002F;
1020 nm.fec.type = MAP_TYPE_TYPED_WCARD0x05;
1021 nm.fec.fec.twcard.type = MAP_TYPE_PREFIX0x02;
1022 nm.fec.fec.twcard.u.prefix_af = af;
1023 nm.flags |= F_NOTIF_FEC0x02;
1024
1025 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0,
1026 &nm, sizeof(nm));
1027}
1028
1029void
1030lde_send_notification_eol_pwid(struct lde_nbr *ln, uint16_t pw_type)
1031{
1032 struct notify_msg nm;
1033
1034 memset(&nm, 0, sizeof(nm));
1035 nm.status_code = S_ENDOFLIB0x0000002F;
1036 nm.fec.type = MAP_TYPE_TYPED_WCARD0x05;
1037 nm.fec.fec.twcard.type = MAP_TYPE_PWID0x80;
1038 nm.fec.fec.twcard.u.pw_type = pw_type;
1039 nm.flags |= F_NOTIF_FEC0x02;
1040
1041 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND, ln->peerid, 0,
1042 &nm, sizeof(nm));
1043}
1044
1045static __inline int
1046lde_nbr_compare(struct lde_nbr *a, struct lde_nbr *b)
1047{
1048 return (a->peerid - b->peerid);
1049}
1050
1051static struct lde_nbr *
1052lde_nbr_new(uint32_t peerid, struct lde_nbr *new)
1053{
1054 struct lde_nbr *ln;
1055
1056 if ((ln = calloc(1, sizeof(*ln))) == NULL((void *)0))
1057 fatal(__func__);
1058
1059 ln->id = new->id;
1060 ln->v4_enabled = new->v4_enabled;
1061 ln->v6_enabled = new->v6_enabled;
1062 ln->flags = new->flags;
1063 ln->peerid = peerid;
1064 fec_init(&ln->recv_map);
1065 fec_init(&ln->sent_map);
1066 fec_init(&ln->recv_req);
1067 fec_init(&ln->sent_req);
1068 fec_init(&ln->sent_wdraw);
1069
1070 TAILQ_INIT(&ln->addr_list)do { (&ln->addr_list)->tqh_first = ((void *)0); (&
ln->addr_list)->tqh_last = &(&ln->addr_list)
->tqh_first; } while (0)
;
1071
1072 if (RB_INSERT(nbr_tree, &lde_nbrs, ln)nbr_tree_RB_INSERT(&lde_nbrs, ln) != NULL((void *)0))
1073 fatalx("lde_nbr_new: RB_INSERT failed");
1074
1075 return (ln);
1076}
1077
1078static void
1079lde_nbr_del(struct lde_nbr *ln)
1080{
1081 struct fec *f;
1082 struct fec_node *fn;
1083 struct fec_nh *fnh;
1084 struct l2vpn_pw *pw;
1085
1086 if (ln
11.1
'ln' is not equal to NULL
== NULL((void *)0))
12
Taking false branch
1087 return;
1088
1089 /* uninstall received mappings */
1090 RB_FOREACH(f, fec_tree, &ft)for ((f) = fec_tree_RB_MINMAX(&ft, -1); (f) != ((void *)0
); (f) = fec_tree_RB_NEXT(f))
{
13
Assuming 'f' is not equal to null
14
Loop condition is true. Entering loop body
1091 fn = (struct fec_node *)f;
1092
1093 LIST_FOREACH(fnh, &fn->nexthops, entry)for((fnh) = ((&fn->nexthops)->lh_first); (fnh)!= ((
void *)0); (fnh) = ((fnh)->entry.le_next))
{
15
Assuming 'fnh' is not equal to null
16
Loop condition is true. Entering loop body
1094 switch (f->type) {
17
Control jumps to 'case FEC_TYPE_PWID:' at line 1101
1095 case FEC_TYPE_IPV4:
1096 case FEC_TYPE_IPV6:
1097 if (!lde_address_find(ln, fnh->af,
1098 &fnh->nexthop))
1099 continue;
1100 break;
1101 case FEC_TYPE_PWID:
1102 if (f->u.pwid.lsr_id.s_addr != ln->id.s_addr)
18
Assuming 'f->u.pwid.lsr_id.s_addr' is equal to 'ln->id.s_addr'
19
Taking false branch
1103 continue;
1104 pw = (struct l2vpn_pw *) fn->data;
1105 if (pw)
20
Assuming 'pw' is null
21
Taking false branch
1106 l2vpn_pw_reset(pw);
1107 break;
22
Execution continues on line 1112
1108 default:
1109 break;
1110 }
1111
1112 lde_send_delete_klabel(fn, fnh);
23
Calling 'lde_send_delete_klabel'
1113 fnh->remote_label = NO_LABEL0xffffffffU;
1114 }
1115 }
1116
1117 lde_address_list_free(ln);
1118
1119 fec_clear(&ln->recv_map, lde_map_free);
1120 fec_clear(&ln->sent_map, lde_map_free);
1121 fec_clear(&ln->recv_req, free);
1122 fec_clear(&ln->sent_req, free);
1123 fec_clear(&ln->sent_wdraw, free);
1124
1125 RB_REMOVE(nbr_tree, &lde_nbrs, ln)nbr_tree_RB_REMOVE(&lde_nbrs, ln);
1126
1127 free(ln);
1128}
1129
1130static struct lde_nbr *
1131lde_nbr_find(uint32_t peerid)
1132{
1133 struct lde_nbr ln;
1134
1135 ln.peerid = peerid;
1136
1137 return (RB_FIND(nbr_tree, &lde_nbrs, &ln)nbr_tree_RB_FIND(&lde_nbrs, &ln));
1138}
1139
1140struct lde_nbr *
1141lde_nbr_find_by_lsrid(struct in_addr addr)
1142{
1143 struct lde_nbr *ln;
1144
1145 RB_FOREACH(ln, nbr_tree, &lde_nbrs)for ((ln) = nbr_tree_RB_MINMAX(&lde_nbrs, -1); (ln) != ((
void *)0); (ln) = nbr_tree_RB_NEXT(ln))
1146 if (ln->id.s_addr == addr.s_addr)
1147 return (ln);
1148
1149 return (NULL((void *)0));
1150}
1151
1152struct lde_nbr *
1153lde_nbr_find_by_addr(int af, union ldpd_addr *addr)
1154{
1155 struct lde_nbr *ln;
1156
1157 RB_FOREACH(ln, nbr_tree, &lde_nbrs)for ((ln) = nbr_tree_RB_MINMAX(&lde_nbrs, -1); (ln) != ((
void *)0); (ln) = nbr_tree_RB_NEXT(ln))
1158 if (lde_address_find(ln, af, addr) != NULL((void *)0))
1159 return (ln);
1160
1161 return (NULL((void *)0));
1162}
1163
1164static void
1165lde_nbr_clear(void)
1166{
1167 struct lde_nbr *ln;
1168
1169 while ((ln = RB_ROOT(&lde_nbrs)(&lde_nbrs)->rbh_root) != NULL((void *)0))
1170 lde_nbr_del(ln);
1171}
1172
1173static void
1174lde_nbr_addr_update(struct lde_nbr *ln, struct lde_addr *lde_addr, int removed)
1175{
1176 struct fec *fec;
1177 struct fec_node *fn;
1178 struct fec_nh *fnh;
1179 struct lde_map *me;
1180
1181 RB_FOREACH(fec, fec_tree, &ln->recv_map)for ((fec) = fec_tree_RB_MINMAX(&ln->recv_map, -1); (fec
) != ((void *)0); (fec) = fec_tree_RB_NEXT(fec))
{
1182 fn = (struct fec_node *)fec_find(&ft, fec);
1183 switch (fec->type) {
1184 case FEC_TYPE_IPV4:
1185 if (lde_addr->af != AF_INET2)
1186 continue;
1187 break;
1188 case FEC_TYPE_IPV6:
1189 if (lde_addr->af != AF_INET624)
1190 continue;
1191 break;
1192 default:
1193 continue;
1194 }
1195
1196 LIST_FOREACH(fnh, &fn->nexthops, entry)for((fnh) = ((&fn->nexthops)->lh_first); (fnh)!= ((
void *)0); (fnh) = ((fnh)->entry.le_next))
{
1197 if (ldp_addrcmp(fnh->af, &fnh->nexthop,
1198 &lde_addr->addr))
1199 continue;
1200
1201 if (removed) {
1202 lde_send_delete_klabel(fn, fnh);
1203 fnh->remote_label = NO_LABEL0xffffffffU;
1204 } else {
1205 me = (struct lde_map *)fec;
1206 fnh->remote_label = me->map.label;
1207 lde_send_change_klabel(fn, fnh);
1208 }
1209 break;
1210 }
1211 }
1212}
1213
1214struct lde_map *
1215lde_map_add(struct lde_nbr *ln, struct fec_node *fn, int sent)
1216{
1217 struct lde_map *me;
1218
1219 me = calloc(1, sizeof(*me));
1220 if (me == NULL((void *)0))
1221 fatal(__func__);
1222
1223 me->fec = fn->fec;
1224 me->nexthop = ln;
1225
1226 if (sent) {
1227 LIST_INSERT_HEAD(&fn->upstream, me, entry)do { if (((me)->entry.le_next = (&fn->upstream)->
lh_first) != ((void *)0)) (&fn->upstream)->lh_first
->entry.le_prev = &(me)->entry.le_next; (&fn->
upstream)->lh_first = (me); (me)->entry.le_prev = &
(&fn->upstream)->lh_first; } while (0)
;
1228 if (fec_insert(&ln->sent_map, &me->fec))
1229 log_warnx("failed to add %s to sent map",
1230 log_fec(&me->fec));
1231 /* XXX on failure more cleanup is needed */
1232 } else {
1233 LIST_INSERT_HEAD(&fn->downstream, me, entry)do { if (((me)->entry.le_next = (&fn->downstream)->
lh_first) != ((void *)0)) (&fn->downstream)->lh_first
->entry.le_prev = &(me)->entry.le_next; (&fn->
downstream)->lh_first = (me); (me)->entry.le_prev = &
(&fn->downstream)->lh_first; } while (0)
;
1234 if (fec_insert(&ln->recv_map, &me->fec))
1235 log_warnx("failed to add %s to recv map",
1236 log_fec(&me->fec));
1237 }
1238
1239 return (me);
1240}
1241
1242void
1243lde_map_del(struct lde_nbr *ln, struct lde_map *me, int sent)
1244{
1245 if (sent)
1246 fec_remove(&ln->sent_map, &me->fec);
1247 else
1248 fec_remove(&ln->recv_map, &me->fec);
1249
1250 lde_map_free(me);
1251}
1252
1253static void
1254lde_map_free(void *ptr)
1255{
1256 struct lde_map *map = ptr;
1257
1258 LIST_REMOVE(map, entry)do { if ((map)->entry.le_next != ((void *)0)) (map)->entry
.le_next->entry.le_prev = (map)->entry.le_prev; *(map)->
entry.le_prev = (map)->entry.le_next; ; ; } while (0)
;
1259 free(map);
1260}
1261
1262struct lde_req *
1263lde_req_add(struct lde_nbr *ln, struct fec *fec, int sent)
1264{
1265 struct fec_tree *t;
1266 struct lde_req *lre;
1267
1268 t = sent ? &ln->sent_req : &ln->recv_req;
1269
1270 lre = calloc(1, sizeof(*lre));
1271 if (lre != NULL((void *)0)) {
1272 lre->fec = *fec;
1273
1274 if (fec_insert(t, &lre->fec)) {
1275 log_warnx("failed to add %s to %s req",
1276 log_fec(&lre->fec), sent ? "sent" : "recv");
1277 free(lre);
1278 return (NULL((void *)0));
1279 }
1280 }
1281
1282 return (lre);
1283}
1284
1285void
1286lde_req_del(struct lde_nbr *ln, struct lde_req *lre, int sent)
1287{
1288 if (sent)
1289 fec_remove(&ln->sent_req, &lre->fec);
1290 else
1291 fec_remove(&ln->recv_req, &lre->fec);
1292
1293 free(lre);
1294}
1295
1296struct lde_wdraw *
1297lde_wdraw_add(struct lde_nbr *ln, struct fec_node *fn)
1298{
1299 struct lde_wdraw *lw;
1300
1301 lw = calloc(1, sizeof(*lw));
1302 if (lw == NULL((void *)0))
1303 fatal(__func__);
1304
1305 lw->fec = fn->fec;
1306
1307 if (fec_insert(&ln->sent_wdraw, &lw->fec))
1308 log_warnx("failed to add %s to sent wdraw",
1309 log_fec(&lw->fec));
1310
1311 return (lw);
1312}
1313
1314void
1315lde_wdraw_del(struct lde_nbr *ln, struct lde_wdraw *lw)
1316{
1317 fec_remove(&ln->sent_wdraw, &lw->fec);
1318 free(lw);
1319}
1320
1321void
1322lde_change_egress_label(int af, int was_implicit)
1323{
1324 struct lde_nbr *ln;
1325 struct fec *f;
1326 struct fec_node *fn;
1327
1328 RB_FOREACH(ln, nbr_tree, &lde_nbrs)for ((ln) = nbr_tree_RB_MINMAX(&lde_nbrs, -1); (ln) != ((
void *)0); (ln) = nbr_tree_RB_NEXT(ln))
{
1329 /* explicit withdraw */
1330 if (was_implicit)
1331 lde_send_labelwithdraw_wcard(ln, MPLS_LABEL_IMPLNULL3);
1332 else {
1333 if (ln->v4_enabled)
1334 lde_send_labelwithdraw_wcard(ln,
1335 MPLS_LABEL_IPV4NULL0);
1336 if (ln->v6_enabled)
1337 lde_send_labelwithdraw_wcard(ln,
1338 MPLS_LABEL_IPV6NULL2);
1339 }
1340
1341 /* advertise new label of connected prefixes */
1342 RB_FOREACH(f, fec_tree, &ft)for ((f) = fec_tree_RB_MINMAX(&ft, -1); (f) != ((void *)0
); (f) = fec_tree_RB_NEXT(f))
{
1343 fn = (struct fec_node *)f;
1344 if (fn->local_label > MPLS_LABEL_RESERVED_MAX15)
1345 continue;
1346
1347 switch (af) {
1348 case AF_INET2:
1349 if (fn->fec.type != FEC_TYPE_IPV4)
1350 continue;
1351 break;
1352 case AF_INET624:
1353 if (fn->fec.type != FEC_TYPE_IPV6)
1354 continue;
1355 break;
1356 default:
1357 fatalx("lde_change_egress_label: unknown af");
1358 }
1359
1360 fn->local_label = egress_label(fn->fec.type);
1361 lde_send_labelmapping(ln, fn, 0);
1362 }
1363
1364 lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid, 0,
1365 NULL((void *)0), 0);
1366 }
1367}
1368
1369static int
1370lde_address_add(struct lde_nbr *ln, struct lde_addr *lde_addr)
1371{
1372 struct lde_addr *new;
1373
1374 if (lde_address_find(ln, lde_addr->af, &lde_addr->addr) != NULL((void *)0))
1375 return (-1);
1376
1377 if ((new = calloc(1, sizeof(*new))) == NULL((void *)0))
1378 fatal(__func__);
1379
1380 new->af = lde_addr->af;
1381 new->addr = lde_addr->addr;
1382 TAILQ_INSERT_TAIL(&ln->addr_list, new, entry)do { (new)->entry.tqe_next = ((void *)0); (new)->entry.
tqe_prev = (&ln->addr_list)->tqh_last; *(&ln->
addr_list)->tqh_last = (new); (&ln->addr_list)->
tqh_last = &(new)->entry.tqe_next; } while (0)
;
1383
1384 /* reevaluate the previously received mappings from this neighbor */
1385 lde_nbr_addr_update(ln, lde_addr, 0);
1386
1387 return (0);
1388}
1389
1390static int
1391lde_address_del(struct lde_nbr *ln, struct lde_addr *lde_addr)
1392{
1393 lde_addr = lde_address_find(ln, lde_addr->af, &lde_addr->addr);
1394 if (lde_addr == NULL((void *)0))
1395 return (-1);
1396
1397 /* reevaluate the previously received mappings from this neighbor */
1398 lde_nbr_addr_update(ln, lde_addr, 1);
1399
1400 TAILQ_REMOVE(&ln->addr_list, lde_addr, entry)do { if (((lde_addr)->entry.tqe_next) != ((void *)0)) (lde_addr
)->entry.tqe_next->entry.tqe_prev = (lde_addr)->entry
.tqe_prev; else (&ln->addr_list)->tqh_last = (lde_addr
)->entry.tqe_prev; *(lde_addr)->entry.tqe_prev = (lde_addr
)->entry.tqe_next; ; ; } while (0)
;
1401 free(lde_addr);
1402
1403 return (0);
1404}
1405
1406struct lde_addr *
1407lde_address_find(struct lde_nbr *ln, int af, union ldpd_addr *addr)
1408{
1409 struct lde_addr *lde_addr;
1410
1411 TAILQ_FOREACH(lde_addr, &ln->addr_list, entry)for((lde_addr) = ((&ln->addr_list)->tqh_first); (lde_addr
) != ((void *)0); (lde_addr) = ((lde_addr)->entry.tqe_next
))
1412 if (lde_addr->af == af &&
1413 ldp_addrcmp(af, &lde_addr->addr, addr) == 0)
1414 return (lde_addr);
1415
1416 return (NULL((void *)0));
1417}
1418
1419static void
1420lde_address_list_free(struct lde_nbr *ln)
1421{
1422 struct lde_addr *lde_addr;
1423
1424 while ((lde_addr = TAILQ_FIRST(&ln->addr_list)((&ln->addr_list)->tqh_first)) != NULL((void *)0)) {
1425 TAILQ_REMOVE(&ln->addr_list, lde_addr, entry)do { if (((lde_addr)->entry.tqe_next) != ((void *)0)) (lde_addr
)->entry.tqe_next->entry.tqe_prev = (lde_addr)->entry
.tqe_prev; else (&ln->addr_list)->tqh_last = (lde_addr
)->entry.tqe_prev; *(lde_addr)->entry.tqe_prev = (lde_addr
)->entry.tqe_next; ; ; } while (0)
;
1426 free(lde_addr);
1427 }
1428}