File: | src/usr.sbin/ospfd/ospfe.c |
Warning: | line 439, column 9 Access to field 'flags' results in a dereference of a null pointer (loaded from variable 'noeconf') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: ospfe.c,v 1.114 2023/12/13 15:34:27 claudio Exp $ */ | |||
2 | ||||
3 | /* | |||
4 | * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> | |||
5 | * Copyright (c) 2004 Esben Norby <norby@openbsd.org> | |||
6 | * Copyright (c) 2003, 2004 Henning Brauer <henning@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/socket.h> | |||
23 | #include <sys/queue.h> | |||
24 | #include <netinet/in.h> | |||
25 | #include <arpa/inet.h> | |||
26 | #include <net/if_types.h> | |||
27 | #include <stdlib.h> | |||
28 | #include <signal.h> | |||
29 | #include <string.h> | |||
30 | #include <fcntl.h> | |||
31 | #include <pwd.h> | |||
32 | #include <unistd.h> | |||
33 | #include <event.h> | |||
34 | #include <err.h> | |||
35 | #include <errno(*__errno()).h> | |||
36 | #include <stdio.h> | |||
37 | ||||
38 | #include "ospf.h" | |||
39 | #include "ospfd.h" | |||
40 | #include "ospfe.h" | |||
41 | #include "rde.h" | |||
42 | #include "control.h" | |||
43 | #include "log.h" | |||
44 | ||||
45 | void ospfe_sig_handler(int, short, void *); | |||
46 | __dead__attribute__((__noreturn__)) void ospfe_shutdown(void); | |||
47 | void orig_rtr_lsa_all(struct area *); | |||
48 | struct iface *find_vlink(struct abr_rtr *); | |||
49 | ||||
50 | struct ospfd_conf *oeconf = NULL((void *)0), *noeconf; | |||
51 | static struct imsgev *iev_main; | |||
52 | static struct imsgev *iev_rde; | |||
53 | int oe_nofib; | |||
54 | ||||
55 | void | |||
56 | ospfe_sig_handler(int sig, short event, void *bula) | |||
57 | { | |||
58 | switch (sig) { | |||
59 | case SIGINT2: | |||
60 | case SIGTERM15: | |||
61 | ospfe_shutdown(); | |||
62 | /* NOTREACHED */ | |||
63 | default: | |||
64 | fatalx("unexpected signal"); | |||
65 | } | |||
66 | } | |||
67 | ||||
68 | /* ospf engine */ | |||
69 | pid_t | |||
70 | ospfe(struct ospfd_conf *xconf, int pipe_parent2ospfe[2], int pipe_ospfe2rde[2], | |||
71 | int pipe_parent2rde[2]) | |||
72 | { | |||
73 | struct area *area; | |||
74 | struct iface *iface; | |||
75 | struct redistribute *r; | |||
76 | struct passwd *pw; | |||
77 | struct event ev_sigint, ev_sigterm; | |||
78 | pid_t pid; | |||
79 | ||||
80 | switch (pid = fork()) { | |||
81 | case -1: | |||
82 | fatal("cannot fork"); | |||
83 | case 0: | |||
84 | break; | |||
85 | default: | |||
86 | return (pid); | |||
87 | } | |||
88 | ||||
89 | /* cleanup a bit */ | |||
90 | kif_clear(); | |||
91 | ||||
92 | /* create the raw ip socket */ | |||
93 | if ((xconf->ospf_socket = socket(AF_INET2, | |||
94 | SOCK_RAW3 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000, | |||
95 | IPPROTO_OSPF89)) == -1) | |||
96 | fatal("error creating raw socket"); | |||
97 | ||||
98 | /* set some defaults */ | |||
99 | if (if_set_mcast_loop(xconf->ospf_socket) == -1) | |||
100 | fatal("if_set_mcast_loop"); | |||
101 | if (if_set_ip_hdrincl(xconf->ospf_socket) == -1) | |||
102 | fatal("if_set_ip_hdrincl"); | |||
103 | if (if_set_recvif(xconf->ospf_socket, 1) == -1) | |||
104 | fatal("if_set_recvif"); | |||
105 | if_set_sockbuf(xconf->ospf_socket); | |||
106 | ||||
107 | oeconf = xconf; | |||
108 | if (oeconf->flags & OSPFD_FLAG_NO_FIB_UPDATE0x0001) | |||
109 | oe_nofib = 1; | |||
110 | ||||
111 | if ((pw = getpwnam(OSPFD_USER"_ospfd")) == NULL((void *)0)) | |||
112 | fatal("getpwnam"); | |||
113 | ||||
114 | if (chroot(pw->pw_dir) == -1) | |||
115 | fatal("chroot"); | |||
116 | if (chdir("/") == -1) | |||
117 | fatal("chdir(\"/\")"); | |||
118 | ||||
119 | setproctitle("ospf engine"); | |||
120 | /* | |||
121 | * XXX needed with fork+exec | |||
122 | * log_init(debug, LOG_DAEMON); | |||
123 | * log_setverbose(verbose); | |||
124 | */ | |||
125 | ||||
126 | ospfd_process = PROC_OSPF_ENGINE; | |||
127 | log_procinit(log_procnames[ospfd_process]); | |||
128 | ||||
129 | if (setgroups(1, &pw->pw_gid) || | |||
130 | setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || | |||
131 | setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) | |||
132 | fatal("can't drop privileges"); | |||
133 | ||||
134 | if (pledge("stdio inet mcast recvfd", NULL((void *)0)) == -1) | |||
135 | fatal("pledge"); | |||
136 | ||||
137 | event_init(); | |||
138 | nbr_init(NBR_HASHSIZE128); | |||
139 | lsa_cache_init(LSA_HASHSIZE512); | |||
140 | ||||
141 | /* setup signal handler */ | |||
142 | signal_set(&ev_sigint, SIGINT, ospfe_sig_handler, NULL)event_set(&ev_sigint, 2, 0x08|0x10, ospfe_sig_handler, (( void *)0)); | |||
143 | signal_set(&ev_sigterm, SIGTERM, ospfe_sig_handler, NULL)event_set(&ev_sigterm, 15, 0x08|0x10, ospfe_sig_handler, ( (void *)0)); | |||
144 | signal_add(&ev_sigint, NULL)event_add(&ev_sigint, ((void *)0)); | |||
145 | signal_add(&ev_sigterm, NULL)event_add(&ev_sigterm, ((void *)0)); | |||
146 | signal(SIGPIPE13, SIG_IGN(void (*)(int))1); | |||
147 | signal(SIGHUP1, SIG_IGN(void (*)(int))1); | |||
148 | ||||
149 | /* setup pipes */ | |||
150 | close(pipe_parent2ospfe[0]); | |||
151 | close(pipe_ospfe2rde[1]); | |||
152 | close(pipe_parent2rde[0]); | |||
153 | close(pipe_parent2rde[1]); | |||
154 | ||||
155 | if ((iev_rde = malloc(sizeof(struct imsgev))) == NULL((void *)0) || | |||
156 | (iev_main = malloc(sizeof(struct imsgev))) == NULL((void *)0)) | |||
157 | fatal(NULL((void *)0)); | |||
158 | imsg_init(&iev_rde->ibuf, pipe_ospfe2rde[0]); | |||
159 | iev_rde->handler = ospfe_dispatch_rde; | |||
160 | imsg_init(&iev_main->ibuf, pipe_parent2ospfe[1]); | |||
161 | iev_main->handler = ospfe_dispatch_main; | |||
162 | ||||
163 | /* setup event handler */ | |||
164 | iev_rde->events = EV_READ0x02; | |||
165 | event_set(&iev_rde->ev, iev_rde->ibuf.fd, iev_rde->events, | |||
166 | iev_rde->handler, iev_rde); | |||
167 | event_add(&iev_rde->ev, NULL((void *)0)); | |||
168 | ||||
169 | iev_main->events = EV_READ0x02; | |||
170 | event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, | |||
171 | iev_main->handler, iev_main); | |||
172 | event_add(&iev_main->ev, NULL((void *)0)); | |||
173 | ||||
174 | event_set(&oeconf->ev, oeconf->ospf_socket, EV_READ0x02|EV_PERSIST0x10, | |||
175 | recv_packet, oeconf); | |||
176 | event_add(&oeconf->ev, NULL((void *)0)); | |||
177 | ||||
178 | /* remove unneeded config stuff */ | |||
179 | conf_clear_redist_list(&oeconf->redist_list); | |||
180 | LIST_FOREACH(area, &oeconf->area_list, entry)for((area) = ((&oeconf->area_list)->lh_first); (area )!= ((void *)0); (area) = ((area)->entry.le_next)) { | |||
181 | while ((r = SIMPLEQ_FIRST(&area->redist_list)((&area->redist_list)->sqh_first)) != NULL((void *)0)) { | |||
182 | SIMPLEQ_REMOVE_HEAD(&area->redist_list, entry)do { if (((&area->redist_list)->sqh_first = (&area ->redist_list)->sqh_first->entry.sqe_next) == ((void *)0)) (&area->redist_list)->sqh_last = &(& area->redist_list)->sqh_first; } while (0); | |||
183 | free(r); | |||
184 | } | |||
185 | } | |||
186 | ||||
187 | /* start interfaces */ | |||
188 | LIST_FOREACH(area, &oeconf->area_list, entry)for((area) = ((&oeconf->area_list)->lh_first); (area )!= ((void *)0); (area) = ((area)->entry.le_next)) { | |||
189 | ospfe_demote_area(area, 0); | |||
190 | LIST_FOREACH(iface, &area->iface_list, entry)for((iface) = ((&area->iface_list)->lh_first); (iface )!= ((void *)0); (iface) = ((iface)->entry.le_next)) { | |||
191 | if_init(xconf, iface); | |||
192 | if (if_fsm(iface, IF_EVT_UP)) { | |||
193 | log_debug("error starting interface %s", | |||
194 | iface->name); | |||
195 | } | |||
196 | } | |||
197 | } | |||
198 | ||||
199 | event_dispatch(); | |||
200 | ||||
201 | ospfe_shutdown(); | |||
202 | /* NOTREACHED */ | |||
203 | return (0); | |||
204 | } | |||
205 | ||||
206 | __dead__attribute__((__noreturn__)) void | |||
207 | ospfe_shutdown(void) | |||
208 | { | |||
209 | struct area *area; | |||
210 | struct iface *iface; | |||
211 | ||||
212 | /* close pipes */ | |||
213 | msgbuf_write(&iev_rde->ibuf.w); | |||
214 | msgbuf_clear(&iev_rde->ibuf.w); | |||
215 | close(iev_rde->ibuf.fd); | |||
216 | msgbuf_write(&iev_main->ibuf.w); | |||
217 | msgbuf_clear(&iev_main->ibuf.w); | |||
218 | close(iev_main->ibuf.fd); | |||
219 | ||||
220 | /* stop all interfaces and remove all areas */ | |||
221 | while ((area = LIST_FIRST(&oeconf->area_list)((&oeconf->area_list)->lh_first)) != NULL((void *)0)) { | |||
222 | LIST_FOREACH(iface, &area->iface_list, entry)for((iface) = ((&area->iface_list)->lh_first); (iface )!= ((void *)0); (iface) = ((iface)->entry.le_next)) { | |||
223 | if (if_fsm(iface, IF_EVT_DOWN)) { | |||
224 | log_debug("error stopping interface %s", | |||
225 | iface->name); | |||
226 | } | |||
227 | } | |||
228 | LIST_REMOVE(area, entry)do { if ((area)->entry.le_next != ((void *)0)) (area)-> entry.le_next->entry.le_prev = (area)->entry.le_prev; * (area)->entry.le_prev = (area)->entry.le_next; ; ; } while (0); | |||
229 | area_del(area); | |||
230 | } | |||
231 | ||||
232 | nbr_del(nbr_find_peerid(NBR_IDSELF1)); | |||
233 | close(oeconf->ospf_socket); | |||
234 | ||||
235 | /* clean up */ | |||
236 | free(iev_rde); | |||
237 | free(iev_main); | |||
238 | free(oeconf); | |||
239 | ||||
240 | log_info("ospf engine exiting"); | |||
241 | _exit(0); | |||
242 | } | |||
243 | ||||
244 | /* imesg */ | |||
245 | int | |||
246 | ospfe_imsg_compose_parent(int type, pid_t pid, void *data, u_int16_t datalen) | |||
247 | { | |||
248 | return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen)); | |||
249 | } | |||
250 | ||||
251 | int | |||
252 | ospfe_imsg_compose_rde(int type, u_int32_t peerid, pid_t pid, | |||
253 | void *data, u_int16_t datalen) | |||
254 | { | |||
255 | return (imsg_compose_event(iev_rde, type, peerid, pid, -1, | |||
256 | data, datalen)); | |||
257 | } | |||
258 | ||||
259 | void | |||
260 | ospfe_dispatch_main(int fd, short event, void *bula) | |||
261 | { | |||
262 | static struct area *narea; | |||
263 | static struct iface *niface; | |||
264 | struct ifaddrchange *ifc; | |||
265 | struct imsg imsg; | |||
266 | struct imsgev *iev = bula; | |||
267 | struct imsgbuf *ibuf = &iev->ibuf; | |||
268 | struct area *area = NULL((void *)0); | |||
269 | struct iface *iface = NULL((void *)0); | |||
270 | struct kif *kif; | |||
271 | struct auth_md md; | |||
272 | int n, link_ok, stub_changed, shut = 0; | |||
273 | ||||
274 | if (event & EV_READ0x02) { | |||
| ||||
275 | if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35) | |||
276 | fatal("imsg_read error"); | |||
277 | if (n == 0) /* connection closed */ | |||
278 | shut = 1; | |||
279 | } | |||
280 | if (event & EV_WRITE0x04) { | |||
281 | if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35) | |||
282 | fatal("msgbuf_write"); | |||
283 | if (n == 0) /* connection closed */ | |||
284 | shut = 1; | |||
285 | } | |||
286 | ||||
287 | for (;;) { | |||
288 | if ((n = imsg_get(ibuf, &imsg)) == -1) | |||
289 | fatal("ospfe_dispatch_main: imsg_get error"); | |||
290 | if (n == 0) | |||
291 | break; | |||
292 | ||||
293 | switch (imsg.hdr.type) { | |||
294 | case IMSG_IFINFO: | |||
295 | if (imsg.hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + | |||
296 | sizeof(struct kif)) | |||
297 | fatalx("IFINFO imsg with wrong len"); | |||
298 | kif = imsg.data; | |||
299 | link_ok = (kif->flags & IFF_UP0x1) && | |||
300 | LINK_STATE_IS_UP(kif->link_state)((kif->link_state) >= 4 || (kif->link_state) == 0); | |||
301 | ||||
302 | LIST_FOREACH(area, &oeconf->area_list, entry)for((area) = ((&oeconf->area_list)->lh_first); (area )!= ((void *)0); (area) = ((area)->entry.le_next)) { | |||
303 | LIST_FOREACH(iface, &area->iface_list, entry)for((iface) = ((&area->iface_list)->lh_first); (iface )!= ((void *)0); (iface) = ((iface)->entry.le_next)) { | |||
304 | if (kif->ifindex == iface->ifindex && | |||
305 | iface->type != | |||
306 | IF_TYPE_VIRTUALLINK) { | |||
307 | int prev_link_state = | |||
308 | (iface->flags & IFF_UP0x1) && | |||
309 | LINK_STATE_IS_UP(iface->linkstate)((iface->linkstate) >= 4 || (iface->linkstate) == 0); | |||
310 | ||||
311 | iface->flags = kif->flags; | |||
312 | iface->linkstate = | |||
313 | kif->link_state; | |||
314 | iface->mtu = kif->mtu; | |||
315 | ||||
316 | if (link_ok == prev_link_state) | |||
317 | break; | |||
318 | ||||
319 | if (link_ok) { | |||
320 | if_fsm(iface, | |||
321 | IF_EVT_UP); | |||
322 | log_warnx("interface %s" | |||
323 | " up", iface->name); | |||
324 | } else { | |||
325 | if_fsm(iface, | |||
326 | IF_EVT_DOWN); | |||
327 | log_warnx("interface %s" | |||
328 | " down", | |||
329 | iface->name); | |||
330 | } | |||
331 | } | |||
332 | if (strcmp(kif->ifname, | |||
333 | iface->dependon) == 0) { | |||
334 | log_warnx("interface %s" | |||
335 | " changed state, %s" | |||
336 | " depends on it", | |||
337 | kif->ifname, | |||
338 | iface->name); | |||
339 | iface->depend_ok = | |||
340 | ifstate_is_up(kif); | |||
341 | ||||
342 | if ((iface->flags & | |||
343 | IFF_UP0x1) && | |||
344 | LINK_STATE_IS_UP(iface->linkstate)((iface->linkstate) >= 4 || (iface->linkstate) == 0)) | |||
345 | orig_rtr_lsa(iface->area); | |||
346 | } | |||
347 | } | |||
348 | } | |||
349 | break; | |||
350 | case IMSG_IFADDRADD: | |||
351 | if (imsg.hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + | |||
352 | sizeof(struct ifaddrchange)) | |||
353 | fatalx("IFADDRADD imsg with wrong len"); | |||
354 | ifc = imsg.data; | |||
355 | ||||
356 | LIST_FOREACH(area, &oeconf->area_list, entry)for((area) = ((&oeconf->area_list)->lh_first); (area )!= ((void *)0); (area) = ((area)->entry.le_next)) { | |||
357 | LIST_FOREACH(iface, &area->iface_list, entry)for((iface) = ((&area->iface_list)->lh_first); (iface )!= ((void *)0); (iface) = ((iface)->entry.le_next)) { | |||
358 | if (ifc->ifindex == iface->ifindex && | |||
359 | ifc->addr.s_addr == | |||
360 | iface->addr.s_addr) { | |||
361 | iface->mask = ifc->mask; | |||
362 | iface->dst = ifc->dst; | |||
363 | /* | |||
364 | * Previous down event might | |||
365 | * have failed if the address | |||
366 | * was not present at that | |||
367 | * time. | |||
368 | */ | |||
369 | if_fsm(iface, IF_EVT_DOWN); | |||
370 | if_fsm(iface, IF_EVT_UP); | |||
371 | log_warnx("interface %s:%s " | |||
372 | "returned", iface->name, | |||
373 | inet_ntoa(iface->addr)); | |||
374 | break; | |||
375 | } | |||
376 | } | |||
377 | } | |||
378 | break; | |||
379 | case IMSG_IFADDRDEL: | |||
380 | if (imsg.hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + | |||
381 | sizeof(struct ifaddrchange)) | |||
382 | fatalx("IFADDRDEL imsg with wrong len"); | |||
383 | ifc = imsg.data; | |||
384 | ||||
385 | LIST_FOREACH(area, &oeconf->area_list, entry)for((area) = ((&oeconf->area_list)->lh_first); (area )!= ((void *)0); (area) = ((area)->entry.le_next)) { | |||
386 | LIST_FOREACH(iface, &area->iface_list, entry)for((iface) = ((&area->iface_list)->lh_first); (iface )!= ((void *)0); (iface) = ((iface)->entry.le_next)) { | |||
387 | if (ifc->ifindex == iface->ifindex && | |||
388 | ifc->addr.s_addr == | |||
389 | iface->addr.s_addr) { | |||
390 | if_fsm(iface, IF_EVT_DOWN); | |||
391 | log_warnx("interface %s:%s " | |||
392 | "gone", iface->name, | |||
393 | inet_ntoa(iface->addr)); | |||
394 | break; | |||
395 | } | |||
396 | } | |||
397 | } | |||
398 | break; | |||
399 | case IMSG_RECONF_CONF: | |||
400 | if ((noeconf = malloc(sizeof(struct ospfd_conf))) == | |||
401 | NULL((void *)0)) | |||
402 | fatal(NULL((void *)0)); | |||
403 | memcpy(noeconf, imsg.data, sizeof(struct ospfd_conf)); | |||
404 | ||||
405 | LIST_INIT(&noeconf->area_list)do { ((&noeconf->area_list)->lh_first) = ((void *)0 ); } while (0); | |||
406 | LIST_INIT(&noeconf->cand_list)do { ((&noeconf->cand_list)->lh_first) = ((void *)0 ); } while (0); | |||
407 | break; | |||
408 | case IMSG_RECONF_AREA: | |||
409 | if ((narea = area_new()) == NULL((void *)0)) | |||
410 | fatal(NULL((void *)0)); | |||
411 | memcpy(narea, imsg.data, sizeof(struct area)); | |||
412 | ||||
413 | LIST_INIT(&narea->iface_list)do { ((&narea->iface_list)->lh_first) = ((void *)0) ; } while (0); | |||
414 | LIST_INIT(&narea->nbr_list)do { ((&narea->nbr_list)->lh_first) = ((void *)0); } while (0); | |||
415 | RB_INIT(&narea->lsa_tree)do { (&narea->lsa_tree)->rbh_root = ((void *)0); } while (0); | |||
416 | SIMPLEQ_INIT(&narea->redist_list)do { (&narea->redist_list)->sqh_first = ((void *)0) ; (&narea->redist_list)->sqh_last = &(&narea ->redist_list)->sqh_first; } while (0); | |||
417 | ||||
418 | LIST_INSERT_HEAD(&noeconf->area_list, narea, entry)do { if (((narea)->entry.le_next = (&noeconf->area_list )->lh_first) != ((void *)0)) (&noeconf->area_list)-> lh_first->entry.le_prev = &(narea)->entry.le_next; ( &noeconf->area_list)->lh_first = (narea); (narea)-> entry.le_prev = &(&noeconf->area_list)->lh_first ; } while (0); | |||
419 | break; | |||
420 | case IMSG_RECONF_IFACE: | |||
421 | if ((niface = malloc(sizeof(struct iface))) == NULL((void *)0)) | |||
422 | fatal(NULL((void *)0)); | |||
423 | memcpy(niface, imsg.data, sizeof(struct iface)); | |||
424 | ||||
425 | LIST_INIT(&niface->nbr_list)do { ((&niface->nbr_list)->lh_first) = ((void *)0); } while (0); | |||
426 | TAILQ_INIT(&niface->ls_ack_list)do { (&niface->ls_ack_list)->tqh_first = ((void *)0 ); (&niface->ls_ack_list)->tqh_last = &(&niface ->ls_ack_list)->tqh_first; } while (0); | |||
427 | TAILQ_INIT(&niface->auth_md_list)do { (&niface->auth_md_list)->tqh_first = ((void *) 0); (&niface->auth_md_list)->tqh_last = &(& niface->auth_md_list)->tqh_first; } while (0); | |||
428 | RB_INIT(&niface->lsa_tree)do { (&niface->lsa_tree)->rbh_root = ((void *)0); } while (0); | |||
429 | ||||
430 | niface->area = narea; | |||
431 | LIST_INSERT_HEAD(&narea->iface_list, niface, entry)do { if (((niface)->entry.le_next = (&narea->iface_list )->lh_first) != ((void *)0)) (&narea->iface_list)-> lh_first->entry.le_prev = &(niface)->entry.le_next; (&narea->iface_list)->lh_first = (niface); (niface )->entry.le_prev = &(&narea->iface_list)->lh_first ; } while (0); | |||
432 | break; | |||
433 | case IMSG_RECONF_AUTHMD: | |||
434 | memcpy(&md, imsg.data, sizeof(struct auth_md)); | |||
435 | md_list_add(&niface->auth_md_list, md.keyid, md.key); | |||
436 | break; | |||
437 | case IMSG_RECONF_END: | |||
438 | if ((oeconf->flags & OSPFD_FLAG_STUB_ROUTER0x0002) != | |||
439 | (noeconf->flags & OSPFD_FLAG_STUB_ROUTER0x0002)) | |||
| ||||
440 | stub_changed = 1; | |||
441 | else | |||
442 | stub_changed = 0; | |||
443 | merge_config(oeconf, noeconf); | |||
444 | noeconf = NULL((void *)0); | |||
445 | if (stub_changed
| |||
446 | orig_rtr_lsa_all(NULL((void *)0)); | |||
447 | break; | |||
448 | case IMSG_CTL_KROUTE: | |||
449 | case IMSG_CTL_KROUTE_ADDR: | |||
450 | case IMSG_CTL_IFINFO: | |||
451 | case IMSG_CTL_END: | |||
452 | control_imsg_relay(&imsg); | |||
453 | break; | |||
454 | case IMSG_CONTROLFD: | |||
455 | if ((fd = imsg_get_fd(&imsg)) == -1) | |||
456 | fatalx("%s: expected to receive imsg control" | |||
457 | "fd but didn't receive any", __func__); | |||
458 | /* Listen on control socket. */ | |||
459 | control_listen(fd); | |||
460 | if (pledge("stdio inet mcast", NULL((void *)0)) == -1) | |||
461 | fatal("pledge"); | |||
462 | break; | |||
463 | default: | |||
464 | log_debug("ospfe_dispatch_main: error handling imsg %d", | |||
465 | imsg.hdr.type); | |||
466 | break; | |||
467 | } | |||
468 | imsg_free(&imsg); | |||
469 | } | |||
470 | if (!shut) | |||
471 | imsg_event_add(iev); | |||
472 | else { | |||
473 | /* this pipe is dead, so remove the event handler */ | |||
474 | event_del(&iev->ev); | |||
475 | event_loopexit(NULL((void *)0)); | |||
476 | } | |||
477 | } | |||
478 | ||||
479 | void | |||
480 | ospfe_dispatch_rde(int fd, short event, void *bula) | |||
481 | { | |||
482 | struct lsa_hdr lsa_hdr; | |||
483 | struct imsgev *iev = bula; | |||
484 | struct imsgbuf *ibuf = &iev->ibuf; | |||
485 | struct nbr *nbr; | |||
486 | struct lsa_hdr *lhp; | |||
487 | struct lsa_ref *ref; | |||
488 | struct area *area; | |||
489 | struct iface *iface; | |||
490 | struct lsa_entry *le; | |||
491 | struct imsg imsg; | |||
492 | struct abr_rtr ar; | |||
493 | int n, noack = 0, shut = 0; | |||
494 | u_int16_t l, age; | |||
495 | ||||
496 | if (event & EV_READ0x02) { | |||
497 | if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35) | |||
498 | fatal("imsg_read error"); | |||
499 | if (n == 0) /* connection closed */ | |||
500 | shut = 1; | |||
501 | } | |||
502 | if (event & EV_WRITE0x04) { | |||
503 | if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35) | |||
504 | fatal("msgbuf_write"); | |||
505 | if (n == 0) /* connection closed */ | |||
506 | shut = 1; | |||
507 | } | |||
508 | ||||
509 | for (;;) { | |||
510 | if ((n = imsg_get(ibuf, &imsg)) == -1) | |||
511 | fatal("ospfe_dispatch_rde: imsg_get error"); | |||
512 | if (n == 0) | |||
513 | break; | |||
514 | ||||
515 | switch (imsg.hdr.type) { | |||
516 | case IMSG_DD: | |||
517 | nbr = nbr_find_peerid(imsg.hdr.peerid); | |||
518 | if (nbr == NULL((void *)0)) | |||
519 | break; | |||
520 | ||||
521 | /* | |||
522 | * Ignore imsg when in the wrong state because a | |||
523 | * NBR_EVT_SEQ_NUM_MIS may have been issued in between. | |||
524 | * Luckily regetting the DB snapshot acts as a barrier | |||
525 | * for both state and process synchronisation. | |||
526 | */ | |||
527 | if ((nbr->state & NBR_STA_FLOOD(0x0040 | 0x0080 | 0x0100)) == 0) | |||
528 | break; | |||
529 | ||||
530 | /* put these on my ls_req_list for retrieval */ | |||
531 | lhp = lsa_hdr_new(); | |||
532 | memcpy(lhp, imsg.data, sizeof(*lhp)); | |||
533 | ls_req_list_add(nbr, lhp); | |||
534 | break; | |||
535 | case IMSG_DD_END: | |||
536 | nbr = nbr_find_peerid(imsg.hdr.peerid); | |||
537 | if (nbr == NULL((void *)0)) | |||
538 | break; | |||
539 | ||||
540 | /* see above */ | |||
541 | if ((nbr->state & NBR_STA_FLOOD(0x0040 | 0x0080 | 0x0100)) == 0) | |||
542 | break; | |||
543 | ||||
544 | nbr->dd_pending--; | |||
545 | if (nbr->dd_pending == 0 && nbr->state & NBR_STA_LOAD0x0080) { | |||
546 | if (ls_req_list_empty(nbr)) | |||
547 | nbr_fsm(nbr, NBR_EVT_LOAD_DONE); | |||
548 | else | |||
549 | start_ls_req_tx_timer(nbr); | |||
550 | } | |||
551 | break; | |||
552 | case IMSG_DD_BADLSA: | |||
553 | nbr = nbr_find_peerid(imsg.hdr.peerid); | |||
554 | if (nbr == NULL((void *)0)) | |||
555 | break; | |||
556 | ||||
557 | if (nbr->iface->self == nbr) | |||
558 | fatalx("ospfe_dispatch_rde: " | |||
559 | "dummy neighbor got BADREQ"); | |||
560 | ||||
561 | nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS); | |||
562 | break; | |||
563 | case IMSG_DB_SNAPSHOT: | |||
564 | nbr = nbr_find_peerid(imsg.hdr.peerid); | |||
565 | if (nbr == NULL((void *)0)) | |||
566 | break; | |||
567 | if (nbr->state != NBR_STA_SNAP0x0020) /* discard */ | |||
568 | break; | |||
569 | ||||
570 | /* add LSA header to the neighbor db_sum_list */ | |||
571 | lhp = lsa_hdr_new(); | |||
572 | memcpy(lhp, imsg.data, sizeof(*lhp)); | |||
573 | db_sum_list_add(nbr, lhp); | |||
574 | break; | |||
575 | case IMSG_DB_END: | |||
576 | nbr = nbr_find_peerid(imsg.hdr.peerid); | |||
577 | if (nbr == NULL((void *)0)) | |||
578 | break; | |||
579 | ||||
580 | nbr->dd_snapshot = 0; | |||
581 | if (nbr->state != NBR_STA_SNAP0x0020) | |||
582 | break; | |||
583 | ||||
584 | /* snapshot done, start tx of dd packets */ | |||
585 | nbr_fsm(nbr, NBR_EVT_SNAP_DONE); | |||
586 | break; | |||
587 | case IMSG_LS_FLOOD: | |||
588 | nbr = nbr_find_peerid(imsg.hdr.peerid); | |||
589 | if (nbr == NULL((void *)0)) | |||
590 | break; | |||
591 | ||||
592 | l = imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr); | |||
593 | if (l < sizeof(lsa_hdr)) | |||
594 | fatalx("ospfe_dispatch_rde: " | |||
595 | "bad imsg size"); | |||
596 | memcpy(&lsa_hdr, imsg.data, sizeof(lsa_hdr)); | |||
597 | ||||
598 | ref = lsa_cache_add(imsg.data, l); | |||
599 | ||||
600 | if (lsa_hdr.type == LSA_TYPE_EXTERNAL5) { | |||
601 | /* | |||
602 | * flood on all areas but stub areas and | |||
603 | * virtual links | |||
604 | */ | |||
605 | LIST_FOREACH(area, &oeconf->area_list, entry)for((area) = ((&oeconf->area_list)->lh_first); (area )!= ((void *)0); (area) = ((area)->entry.le_next)) { | |||
606 | if (area->stub) | |||
607 | continue; | |||
608 | LIST_FOREACH(iface, &area->iface_list,for((iface) = ((&area->iface_list)->lh_first); (iface )!= ((void *)0); (iface) = ((iface)->entry.le_next)) | |||
609 | entry)for((iface) = ((&area->iface_list)->lh_first); (iface )!= ((void *)0); (iface) = ((iface)->entry.le_next)) { | |||
610 | noack += lsa_flood(iface, nbr, | |||
611 | &lsa_hdr, imsg.data); | |||
612 | } | |||
613 | } | |||
614 | } else if (lsa_hdr.type == LSA_TYPE_LINK_OPAQ9) { | |||
615 | /* | |||
616 | * Flood on interface only | |||
617 | */ | |||
618 | noack += lsa_flood(nbr->iface, nbr, | |||
619 | &lsa_hdr, imsg.data); | |||
620 | } else { | |||
621 | /* | |||
622 | * Flood on all area interfaces. For | |||
623 | * area 0.0.0.0 include the virtual links. | |||
624 | */ | |||
625 | area = nbr->iface->area; | |||
626 | LIST_FOREACH(iface, &area->iface_list, entry)for((iface) = ((&area->iface_list)->lh_first); (iface )!= ((void *)0); (iface) = ((iface)->entry.le_next)) { | |||
627 | noack += lsa_flood(iface, nbr, | |||
628 | &lsa_hdr, imsg.data); | |||
629 | } | |||
630 | /* XXX virtual links */ | |||
631 | } | |||
632 | ||||
633 | /* remove from ls_req_list */ | |||
634 | le = ls_req_list_get(nbr, &lsa_hdr); | |||
635 | if (!(nbr->state & NBR_STA_FULL0x0100) && le != NULL((void *)0)) { | |||
636 | ls_req_list_free(nbr, le); | |||
637 | /* | |||
638 | * XXX no need to ack requested lsa | |||
639 | * the problem is that the RFC is very | |||
640 | * unclear about this. | |||
641 | */ | |||
642 | noack = 1; | |||
643 | } | |||
644 | ||||
645 | if (!noack && nbr->iface != NULL((void *)0) && | |||
646 | nbr->iface->self != nbr) { | |||
647 | if (!(nbr->iface->state & IF_STA_BACKUP0x20) || | |||
648 | nbr->iface->dr == nbr) { | |||
649 | /* delayed ack */ | |||
650 | lhp = lsa_hdr_new(); | |||
651 | memcpy(lhp, &lsa_hdr, sizeof(*lhp)); | |||
652 | ls_ack_list_add(nbr->iface, lhp); | |||
653 | } | |||
654 | } | |||
655 | ||||
656 | lsa_cache_put(ref, nbr); | |||
657 | break; | |||
658 | case IMSG_LS_UPD: | |||
659 | case IMSG_LS_SNAP: | |||
660 | /* | |||
661 | * IMSG_LS_UPD is used in two cases: | |||
662 | * 1. as response to ls requests | |||
663 | * 2. as response to ls updates where the DB | |||
664 | * is newer then the sent LSA | |||
665 | * IMSG_LS_SNAP is used in one case: | |||
666 | * in EXSTART when the LSA has age MaxAge | |||
667 | */ | |||
668 | l = imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr); | |||
669 | if (l < sizeof(lsa_hdr)) | |||
670 | fatalx("ospfe_dispatch_rde: " | |||
671 | "bad imsg size"); | |||
672 | ||||
673 | nbr = nbr_find_peerid(imsg.hdr.peerid); | |||
674 | if (nbr == NULL((void *)0)) | |||
675 | break; | |||
676 | ||||
677 | if (nbr->iface->self == nbr) | |||
678 | break; | |||
679 | ||||
680 | if (imsg.hdr.type == IMSG_LS_SNAP && | |||
681 | nbr->state != NBR_STA_SNAP0x0020) | |||
682 | break; | |||
683 | ||||
684 | memcpy(&age, imsg.data, sizeof(age)); | |||
685 | ref = lsa_cache_add(imsg.data, l); | |||
686 | if (ntohs(age)(__uint16_t)(__builtin_constant_p(age) ? (__uint16_t)(((__uint16_t )(age) & 0xffU) << 8 | ((__uint16_t)(age) & 0xff00U ) >> 8) : __swap16md(age)) >= MAX_AGE3600) | |||
687 | /* add to retransmit list */ | |||
688 | ls_retrans_list_add(nbr, imsg.data, 0, 0); | |||
689 | else | |||
690 | ls_retrans_list_add(nbr, imsg.data, 0, 1); | |||
691 | ||||
692 | lsa_cache_put(ref, nbr); | |||
693 | break; | |||
694 | case IMSG_LS_ACK: | |||
695 | /* | |||
696 | * IMSG_LS_ACK is used in two cases: | |||
697 | * 1. LSA was a duplicate | |||
698 | * 2. LS age is MaxAge and there is no current | |||
699 | * instance in the DB plus no neighbor in state | |||
700 | * Exchange or Loading | |||
701 | */ | |||
702 | nbr = nbr_find_peerid(imsg.hdr.peerid); | |||
703 | if (nbr == NULL((void *)0)) | |||
704 | break; | |||
705 | ||||
706 | if (nbr->iface->self == nbr) | |||
707 | break; | |||
708 | ||||
709 | if (imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr) != sizeof(lsa_hdr)) | |||
710 | fatalx("ospfe_dispatch_rde: bad imsg size"); | |||
711 | memcpy(&lsa_hdr, imsg.data, sizeof(lsa_hdr)); | |||
712 | ||||
713 | /* for case one check for implied acks */ | |||
714 | if (nbr->iface->state & IF_STA_DROTHER0x10) | |||
715 | if (ls_retrans_list_del(nbr->iface->self, | |||
716 | &lsa_hdr) == 0) | |||
717 | break; | |||
718 | if (ls_retrans_list_del(nbr, &lsa_hdr) == 0) | |||
719 | break; | |||
720 | ||||
721 | /* send a direct acknowledgement */ | |||
722 | send_direct_ack(nbr->iface, nbr->addr, imsg.data, | |||
723 | imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr)); | |||
724 | ||||
725 | break; | |||
726 | case IMSG_LS_BADREQ: | |||
727 | nbr = nbr_find_peerid(imsg.hdr.peerid); | |||
728 | if (nbr == NULL((void *)0)) | |||
729 | break; | |||
730 | ||||
731 | if (nbr->iface->self == nbr) | |||
732 | fatalx("ospfe_dispatch_rde: " | |||
733 | "dummy neighbor got BADREQ"); | |||
734 | ||||
735 | nbr_fsm(nbr, NBR_EVT_BAD_LS_REQ); | |||
736 | break; | |||
737 | case IMSG_ABR_UP: | |||
738 | memcpy(&ar, imsg.data, sizeof(ar)); | |||
739 | ||||
740 | if ((iface = find_vlink(&ar)) != NULL((void *)0) && | |||
741 | iface->state == IF_STA_DOWN0x01) | |||
742 | if (if_fsm(iface, IF_EVT_UP)) { | |||
743 | log_debug("error starting interface %s", | |||
744 | iface->name); | |||
745 | } | |||
746 | break; | |||
747 | case IMSG_ABR_DOWN: | |||
748 | memcpy(&ar, imsg.data, sizeof(ar)); | |||
749 | ||||
750 | if ((iface = find_vlink(&ar)) != NULL((void *)0) && | |||
751 | iface->state == IF_STA_POINTTOPOINT0x08) | |||
752 | if (if_fsm(iface, IF_EVT_DOWN)) { | |||
753 | log_debug("error stopping interface %s", | |||
754 | iface->name); | |||
755 | } | |||
756 | break; | |||
757 | case IMSG_CTL_AREA: | |||
758 | case IMSG_CTL_IFACE: | |||
759 | case IMSG_CTL_END: | |||
760 | case IMSG_CTL_SHOW_DATABASE: | |||
761 | case IMSG_CTL_SHOW_DB_EXT: | |||
762 | case IMSG_CTL_SHOW_DB_NET: | |||
763 | case IMSG_CTL_SHOW_DB_RTR: | |||
764 | case IMSG_CTL_SHOW_DB_SELF: | |||
765 | case IMSG_CTL_SHOW_DB_SUM: | |||
766 | case IMSG_CTL_SHOW_DB_ASBR: | |||
767 | case IMSG_CTL_SHOW_DB_OPAQ: | |||
768 | case IMSG_CTL_SHOW_RIB: | |||
769 | case IMSG_CTL_SHOW_SUM: | |||
770 | case IMSG_CTL_SHOW_SUM_AREA: | |||
771 | control_imsg_relay(&imsg); | |||
772 | break; | |||
773 | default: | |||
774 | log_debug("ospfe_dispatch_rde: error handling imsg %d", | |||
775 | imsg.hdr.type); | |||
776 | break; | |||
777 | } | |||
778 | imsg_free(&imsg); | |||
779 | } | |||
780 | if (!shut) | |||
781 | imsg_event_add(iev); | |||
782 | else { | |||
783 | /* this pipe is dead, so remove the event handler */ | |||
784 | event_del(&iev->ev); | |||
785 | event_loopexit(NULL((void *)0)); | |||
786 | } | |||
787 | } | |||
788 | ||||
789 | struct iface * | |||
790 | find_vlink(struct abr_rtr *ar) | |||
791 | { | |||
792 | struct area *area; | |||
793 | struct iface *iface = NULL((void *)0); | |||
794 | ||||
795 | LIST_FOREACH(area, &oeconf->area_list, entry)for((area) = ((&oeconf->area_list)->lh_first); (area )!= ((void *)0); (area) = ((area)->entry.le_next)) | |||
796 | LIST_FOREACH(iface, &area->iface_list, entry)for((iface) = ((&area->iface_list)->lh_first); (iface )!= ((void *)0); (iface) = ((iface)->entry.le_next)) | |||
797 | if (iface->abr_id.s_addr == ar->abr_id.s_addr && | |||
798 | iface->type == IF_TYPE_VIRTUALLINK && | |||
799 | iface->area->id.s_addr == ar->area.s_addr) { | |||
800 | iface->dst.s_addr = ar->dst_ip.s_addr; | |||
801 | iface->addr.s_addr = ar->addr.s_addr; | |||
802 | iface->metric = ar->metric; | |||
803 | ||||
804 | return (iface); | |||
805 | } | |||
806 | ||||
807 | return (iface); | |||
808 | } | |||
809 | ||||
810 | void | |||
811 | orig_rtr_lsa_all(struct area *area) | |||
812 | { | |||
813 | struct area *a; | |||
814 | ||||
815 | /* | |||
816 | * update all router LSA in all areas except area itself, | |||
817 | * as this update is already running. | |||
818 | */ | |||
819 | LIST_FOREACH(a, &oeconf->area_list, entry)for((a) = ((&oeconf->area_list)->lh_first); (a)!= ( (void *)0); (a) = ((a)->entry.le_next)) | |||
820 | if (a != area) | |||
821 | orig_rtr_lsa(a); | |||
822 | } | |||
823 | ||||
824 | void | |||
825 | orig_rtr_lsa(struct area *area) | |||
826 | { | |||
827 | struct lsa_hdr lsa_hdr; | |||
828 | struct lsa_rtr lsa_rtr; | |||
829 | struct lsa_rtr_link rtr_link; | |||
830 | struct iface *iface; | |||
831 | struct ibuf *buf; | |||
832 | struct nbr *nbr, *self = NULL((void *)0); | |||
833 | u_int16_t num_links = 0; | |||
834 | u_int16_t chksum; | |||
835 | u_int8_t border, virtual = 0; | |||
836 | ||||
837 | log_debug("orig_rtr_lsa: area %s", inet_ntoa(area->id)); | |||
838 | ||||
839 | if ((buf = ibuf_dynamic(sizeof(lsa_hdr), | |||
840 | IP_MAXPACKET65535 - sizeof(struct ip) - sizeof(struct ospf_hdr) - | |||
841 | sizeof(u_int32_t) - MD5_DIGEST_LENGTH16)) == NULL((void *)0)) | |||
842 | fatal("orig_rtr_lsa"); | |||
843 | ||||
844 | /* reserve space for LSA header and LSA Router header */ | |||
845 | if (ibuf_add_zero(buf, sizeof(lsa_hdr)) == -1) | |||
846 | fatal("orig_rtr_lsa: ibuf_add_zero failed"); | |||
847 | ||||
848 | if (ibuf_add_zero(buf, sizeof(lsa_rtr)) == -1) | |||
849 | fatal("orig_rtr_lsa: ibuf_add_zero failed"); | |||
850 | ||||
851 | /* links */ | |||
852 | LIST_FOREACH(iface, &area->iface_list, entry)for((iface) = ((&area->iface_list)->lh_first); (iface )!= ((void *)0); (iface) = ((iface)->entry.le_next)) { | |||
853 | if (self == NULL((void *)0) && iface->self != NULL((void *)0)) | |||
854 | self = iface->self; | |||
855 | ||||
856 | bzero(&rtr_link, sizeof(rtr_link)); | |||
857 | ||||
858 | if (iface->state & IF_STA_LOOPBACK0x02) { | |||
859 | rtr_link.id = iface->addr.s_addr; | |||
860 | rtr_link.data = 0xffffffff; | |||
861 | rtr_link.type = LINK_TYPE_STUB_NET3; | |||
862 | rtr_link.metric = htons(iface->metric)(__uint16_t)(__builtin_constant_p(iface->metric) ? (__uint16_t )(((__uint16_t)(iface->metric) & 0xffU) << 8 | ( (__uint16_t)(iface->metric) & 0xff00U) >> 8) : __swap16md (iface->metric)); | |||
863 | num_links++; | |||
864 | if (ibuf_add(buf, &rtr_link, sizeof(rtr_link))) | |||
865 | fatalx("orig_rtr_lsa: ibuf_add failed"); | |||
866 | continue; | |||
867 | } | |||
868 | ||||
869 | switch (iface->type) { | |||
870 | case IF_TYPE_POINTOPOINT: | |||
871 | LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!= ((void *)0); (nbr) = ((nbr)->entry.le_next)) | |||
872 | if (nbr != iface->self && | |||
873 | nbr->state & NBR_STA_FULL0x0100) | |||
874 | break; | |||
875 | if (nbr) { | |||
876 | log_debug("orig_rtr_lsa: point-to-point, " | |||
877 | "interface %s", iface->name); | |||
878 | rtr_link.id = nbr->id.s_addr; | |||
879 | rtr_link.data = iface->addr.s_addr; | |||
880 | rtr_link.type = LINK_TYPE_POINTTOPOINT1; | |||
881 | /* RFC 3137: stub router support */ | |||
882 | if (oeconf->flags & OSPFD_FLAG_STUB_ROUTER0x0002 || | |||
883 | oe_nofib) | |||
884 | rtr_link.metric = MAX_METRIC65535; | |||
885 | else if (iface->dependon[0] != '\0' && | |||
886 | iface->depend_ok == 0) | |||
887 | rtr_link.metric = MAX_METRIC65535; | |||
888 | else | |||
889 | rtr_link.metric = htons(iface->metric)(__uint16_t)(__builtin_constant_p(iface->metric) ? (__uint16_t )(((__uint16_t)(iface->metric) & 0xffU) << 8 | ( (__uint16_t)(iface->metric) & 0xff00U) >> 8) : __swap16md (iface->metric)); | |||
890 | num_links++; | |||
891 | if (ibuf_add(buf, &rtr_link, sizeof(rtr_link))) | |||
892 | fatalx("orig_rtr_lsa: ibuf_add failed"); | |||
893 | } | |||
894 | if ((iface->flags & IFF_UP0x1) && | |||
895 | LINK_STATE_IS_UP(iface->linkstate)((iface->linkstate) >= 4 || (iface->linkstate) == 0)) { | |||
896 | log_debug("orig_rtr_lsa: stub net, " | |||
897 | "interface %s", iface->name); | |||
898 | bzero(&rtr_link, sizeof(rtr_link)); | |||
899 | if (nbr) { | |||
900 | rtr_link.id = nbr->addr.s_addr; | |||
901 | rtr_link.data = 0xffffffff; | |||
902 | } else { | |||
903 | rtr_link.id = iface->addr.s_addr & | |||
904 | iface->mask.s_addr; | |||
905 | rtr_link.data = iface->mask.s_addr; | |||
906 | } | |||
907 | rtr_link.type = LINK_TYPE_STUB_NET3; | |||
908 | if (iface->dependon[0] != '\0' && | |||
909 | iface->depend_ok == 0) | |||
910 | rtr_link.metric = MAX_METRIC65535; | |||
911 | else | |||
912 | rtr_link.metric = htons(iface->metric)(__uint16_t)(__builtin_constant_p(iface->metric) ? (__uint16_t )(((__uint16_t)(iface->metric) & 0xffU) << 8 | ( (__uint16_t)(iface->metric) & 0xff00U) >> 8) : __swap16md (iface->metric)); | |||
913 | num_links++; | |||
914 | if (ibuf_add(buf, &rtr_link, sizeof(rtr_link))) | |||
915 | fatalx("orig_rtr_lsa: ibuf_add failed"); | |||
916 | } | |||
917 | continue; | |||
918 | case IF_TYPE_BROADCAST: | |||
919 | case IF_TYPE_NBMA: | |||
920 | if ((iface->state & IF_STA_MULTI(0x10 | 0x20 | 0x40))) { | |||
921 | if (iface->dr == iface->self) { | |||
922 | LIST_FOREACH(nbr, &iface->nbr_list,for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!= ((void *)0); (nbr) = ((nbr)->entry.le_next)) | |||
923 | entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!= ((void *)0); (nbr) = ((nbr)->entry.le_next)) | |||
924 | if (nbr != iface->self && | |||
925 | nbr->state & NBR_STA_FULL0x0100) | |||
926 | break; | |||
927 | } else | |||
928 | nbr = iface->dr; | |||
929 | ||||
930 | if (nbr && nbr->state & NBR_STA_FULL0x0100) { | |||
931 | log_debug("orig_rtr_lsa: transit net, " | |||
932 | "interface %s", iface->name); | |||
933 | ||||
934 | rtr_link.id = iface->dr->addr.s_addr; | |||
935 | rtr_link.data = iface->addr.s_addr; | |||
936 | rtr_link.type = LINK_TYPE_TRANSIT_NET2; | |||
937 | break; | |||
938 | } | |||
939 | } | |||
940 | ||||
941 | /* | |||
942 | * do not add a stub net LSA for interfaces that are: | |||
943 | * - down | |||
944 | * - have a linkstate which is down, apart from carp: | |||
945 | * backup carp interfaces have linkstate down, but | |||
946 | * we still announce them. | |||
947 | */ | |||
948 | if (!(iface->flags & IFF_UP0x1) || | |||
949 | (!LINK_STATE_IS_UP(iface->linkstate)((iface->linkstate) >= 4 || (iface->linkstate) == 0) && | |||
950 | !(iface->if_type == IFT_CARP0xf7 && | |||
951 | iface->linkstate == LINK_STATE_DOWN2))) | |||
952 | continue; | |||
953 | log_debug("orig_rtr_lsa: stub net, " | |||
954 | "interface %s", iface->name); | |||
955 | ||||
956 | rtr_link.id = | |||
957 | iface->addr.s_addr & iface->mask.s_addr; | |||
958 | rtr_link.data = iface->mask.s_addr; | |||
959 | rtr_link.type = LINK_TYPE_STUB_NET3; | |||
960 | ||||
961 | rtr_link.num_tos = 0; | |||
962 | /* | |||
963 | * backup carp interfaces and interfaces that depend | |||
964 | * on an interface that is down are announced with | |||
965 | * high metric for faster failover. | |||
966 | */ | |||
967 | if (iface->if_type == IFT_CARP0xf7 && | |||
968 | iface->linkstate == LINK_STATE_DOWN2) | |||
969 | rtr_link.metric = MAX_METRIC65535; | |||
970 | else if (iface->dependon[0] != '\0' && | |||
971 | iface->depend_ok == 0) | |||
972 | rtr_link.metric = MAX_METRIC65535; | |||
973 | else | |||
974 | rtr_link.metric = htons(iface->metric)(__uint16_t)(__builtin_constant_p(iface->metric) ? (__uint16_t )(((__uint16_t)(iface->metric) & 0xffU) << 8 | ( (__uint16_t)(iface->metric) & 0xff00U) >> 8) : __swap16md (iface->metric)); | |||
975 | num_links++; | |||
976 | if (ibuf_add(buf, &rtr_link, sizeof(rtr_link))) | |||
977 | fatalx("orig_rtr_lsa: ibuf_add failed"); | |||
978 | continue; | |||
979 | case IF_TYPE_VIRTUALLINK: | |||
980 | LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!= ((void *)0); (nbr) = ((nbr)->entry.le_next)) { | |||
981 | if (nbr != iface->self && | |||
982 | nbr->state & NBR_STA_FULL0x0100) | |||
983 | break; | |||
984 | } | |||
985 | if (nbr) { | |||
986 | rtr_link.id = nbr->id.s_addr; | |||
987 | rtr_link.data = iface->addr.s_addr; | |||
988 | rtr_link.type = LINK_TYPE_VIRTUAL4; | |||
989 | /* RFC 3137: stub router support */ | |||
990 | if (oeconf->flags & OSPFD_FLAG_STUB_ROUTER0x0002 || | |||
991 | oe_nofib) | |||
992 | rtr_link.metric = MAX_METRIC65535; | |||
993 | else | |||
994 | rtr_link.metric = htons(iface->metric)(__uint16_t)(__builtin_constant_p(iface->metric) ? (__uint16_t )(((__uint16_t)(iface->metric) & 0xffU) << 8 | ( (__uint16_t)(iface->metric) & 0xff00U) >> 8) : __swap16md (iface->metric)); | |||
995 | num_links++; | |||
996 | virtual = 1; | |||
997 | if (ibuf_add(buf, &rtr_link, sizeof(rtr_link))) | |||
998 | fatalx("orig_rtr_lsa: ibuf_add failed"); | |||
999 | ||||
1000 | log_debug("orig_rtr_lsa: virtual link, " | |||
1001 | "interface %s", iface->name); | |||
1002 | } | |||
1003 | continue; | |||
1004 | case IF_TYPE_POINTOMULTIPOINT: | |||
1005 | log_debug("orig_rtr_lsa: stub net, " | |||
1006 | "interface %s", iface->name); | |||
1007 | rtr_link.id = iface->addr.s_addr; | |||
1008 | rtr_link.data = 0xffffffff; | |||
1009 | rtr_link.type = LINK_TYPE_STUB_NET3; | |||
1010 | rtr_link.metric = htons(iface->metric)(__uint16_t)(__builtin_constant_p(iface->metric) ? (__uint16_t )(((__uint16_t)(iface->metric) & 0xffU) << 8 | ( (__uint16_t)(iface->metric) & 0xff00U) >> 8) : __swap16md (iface->metric)); | |||
1011 | num_links++; | |||
1012 | if (ibuf_add(buf, &rtr_link, sizeof(rtr_link))) | |||
1013 | fatalx("orig_rtr_lsa: ibuf_add failed"); | |||
1014 | ||||
1015 | LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!= ((void *)0); (nbr) = ((nbr)->entry.le_next)) { | |||
1016 | if (nbr != iface->self && | |||
1017 | nbr->state & NBR_STA_FULL0x0100) { | |||
1018 | bzero(&rtr_link, sizeof(rtr_link)); | |||
1019 | log_debug("orig_rtr_lsa: " | |||
1020 | "point-to-multipoint, interface %s", | |||
1021 | iface->name); | |||
1022 | rtr_link.id = nbr->addr.s_addr; | |||
1023 | rtr_link.data = iface->addr.s_addr; | |||
1024 | rtr_link.type = LINK_TYPE_POINTTOPOINT1; | |||
1025 | /* RFC 3137: stub router support */ | |||
1026 | if (oe_nofib || oeconf->flags & | |||
1027 | OSPFD_FLAG_STUB_ROUTER0x0002) | |||
1028 | rtr_link.metric = MAX_METRIC65535; | |||
1029 | else if (iface->dependon[0] != '\0' && | |||
1030 | iface->depend_ok == 0) | |||
1031 | rtr_link.metric = MAX_METRIC65535; | |||
1032 | else | |||
1033 | rtr_link.metric = | |||
1034 | htons(iface->metric)(__uint16_t)(__builtin_constant_p(iface->metric) ? (__uint16_t )(((__uint16_t)(iface->metric) & 0xffU) << 8 | ( (__uint16_t)(iface->metric) & 0xff00U) >> 8) : __swap16md (iface->metric)); | |||
1035 | num_links++; | |||
1036 | if (ibuf_add(buf, &rtr_link, | |||
1037 | sizeof(rtr_link))) | |||
1038 | fatalx("orig_rtr_lsa: " | |||
1039 | "ibuf_add failed"); | |||
1040 | } | |||
1041 | } | |||
1042 | continue; | |||
1043 | default: | |||
1044 | fatalx("orig_rtr_lsa: unknown interface type"); | |||
1045 | } | |||
1046 | ||||
1047 | rtr_link.num_tos = 0; | |||
1048 | /* RFC 3137: stub router support */ | |||
1049 | if ((oeconf->flags & OSPFD_FLAG_STUB_ROUTER0x0002 || oe_nofib) && | |||
1050 | rtr_link.type != LINK_TYPE_STUB_NET3) | |||
1051 | rtr_link.metric = MAX_METRIC65535; | |||
1052 | else if (iface->dependon[0] != '\0' && iface->depend_ok == 0) | |||
1053 | rtr_link.metric = MAX_METRIC65535; | |||
1054 | else | |||
1055 | rtr_link.metric = htons(iface->metric)(__uint16_t)(__builtin_constant_p(iface->metric) ? (__uint16_t )(((__uint16_t)(iface->metric) & 0xffU) << 8 | ( (__uint16_t)(iface->metric) & 0xff00U) >> 8) : __swap16md (iface->metric)); | |||
1056 | num_links++; | |||
1057 | if (ibuf_add(buf, &rtr_link, sizeof(rtr_link))) | |||
1058 | fatalx("orig_rtr_lsa: ibuf_add failed"); | |||
1059 | } | |||
1060 | ||||
1061 | /* LSA router header */ | |||
1062 | lsa_rtr.flags = 0; | |||
1063 | /* | |||
1064 | * Set the E bit as soon as an as-ext lsa may be redistributed, only | |||
1065 | * setting it in case we redistribute something is not worth the fuss. | |||
1066 | * Do not set the E bit in case of a stub area. | |||
1067 | */ | |||
1068 | if (oeconf->redistribute && !area->stub) | |||
1069 | lsa_rtr.flags |= OSPF_RTR_E0x02; | |||
1070 | ||||
1071 | border = (area_border_router(oeconf) != 0); | |||
1072 | if (border != oeconf->border) { | |||
1073 | oeconf->border = border; | |||
1074 | orig_rtr_lsa_all(area); | |||
1075 | } | |||
1076 | if (oeconf->border) | |||
1077 | lsa_rtr.flags |= OSPF_RTR_B0x01; | |||
1078 | ||||
1079 | /* TODO set V flag if a active virtual link ends here and the | |||
1080 | * area is the transit area for this link. */ | |||
1081 | if (virtual) | |||
1082 | lsa_rtr.flags |= OSPF_RTR_V0x04; | |||
1083 | ||||
1084 | lsa_rtr.dummy = 0; | |||
1085 | lsa_rtr.nlinks = htons(num_links)(__uint16_t)(__builtin_constant_p(num_links) ? (__uint16_t)(( (__uint16_t)(num_links) & 0xffU) << 8 | ((__uint16_t )(num_links) & 0xff00U) >> 8) : __swap16md(num_links )); | |||
1086 | if (ibuf_set(buf, sizeof(lsa_hdr), &lsa_rtr, sizeof(lsa_rtr)) == | |||
1087 | -1) | |||
1088 | fatal("orig_rtr_lsa: ibuf_set failed"); | |||
1089 | ||||
1090 | /* LSA header */ | |||
1091 | lsa_hdr.age = htons(DEFAULT_AGE)(__uint16_t)(__builtin_constant_p(0) ? (__uint16_t)(((__uint16_t )(0) & 0xffU) << 8 | ((__uint16_t)(0) & 0xff00U ) >> 8) : __swap16md(0)); | |||
1092 | lsa_hdr.opts = area_ospf_options(area); | |||
1093 | lsa_hdr.type = LSA_TYPE_ROUTER1; | |||
1094 | lsa_hdr.ls_id = oeconf->rtr_id.s_addr; | |||
1095 | lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr; | |||
1096 | lsa_hdr.seq_num = htonl(INIT_SEQ_NUM)(__uint32_t)(__builtin_constant_p(0x80000001) ? (__uint32_t)( ((__uint32_t)(0x80000001) & 0xff) << 24 | ((__uint32_t )(0x80000001) & 0xff00) << 8 | ((__uint32_t)(0x80000001 ) & 0xff0000) >> 8 | ((__uint32_t)(0x80000001) & 0xff000000) >> 24) : __swap32md(0x80000001)); | |||
1097 | lsa_hdr.len = htons(ibuf_size(buf))(__uint16_t)(__builtin_constant_p(ibuf_size(buf)) ? (__uint16_t )(((__uint16_t)(ibuf_size(buf)) & 0xffU) << 8 | ((__uint16_t )(ibuf_size(buf)) & 0xff00U) >> 8) : __swap16md(ibuf_size (buf))); | |||
1098 | lsa_hdr.ls_chksum = 0; /* updated later */ | |||
1099 | if (ibuf_set(buf, 0, &lsa_hdr, sizeof(lsa_hdr)) == -1) | |||
1100 | fatal("orig_rtr_lsa: ibuf_set failed"); | |||
1101 | ||||
1102 | chksum = iso_cksum(ibuf_data(buf), ibuf_size(buf), LS_CKSUM_OFFSET__builtin_offsetof(struct lsa_hdr, ls_chksum)); | |||
1103 | if (ibuf_set_n16(buf, LS_CKSUM_OFFSET__builtin_offsetof(struct lsa_hdr, ls_chksum), chksum) == -1) | |||
1104 | fatal("orig_rtr_lsa: ibuf_set_n16 failed"); | |||
1105 | ||||
1106 | if (self && num_links) | |||
1107 | imsg_compose_event(iev_rde, IMSG_LS_UPD, self->peerid, 0, | |||
1108 | -1, ibuf_data(buf), ibuf_size(buf)); | |||
1109 | else | |||
1110 | log_warnx("orig_rtr_lsa: empty area %s", | |||
1111 | inet_ntoa(area->id)); | |||
1112 | ||||
1113 | ibuf_free(buf); | |||
1114 | } | |||
1115 | ||||
1116 | void | |||
1117 | orig_net_lsa(struct iface *iface) | |||
1118 | { | |||
1119 | struct lsa_hdr lsa_hdr; | |||
1120 | struct nbr *nbr; | |||
1121 | struct ibuf *buf; | |||
1122 | int num_rtr = 0; | |||
1123 | u_int16_t chksum; | |||
1124 | ||||
1125 | if ((buf = ibuf_dynamic(sizeof(lsa_hdr), | |||
1126 | IP_MAXPACKET65535 - sizeof(struct ip) - sizeof(struct ospf_hdr) - | |||
1127 | sizeof(u_int32_t) - MD5_DIGEST_LENGTH16)) == NULL((void *)0)) | |||
1128 | fatal("orig_net_lsa"); | |||
1129 | ||||
1130 | /* reserve space for LSA header and LSA Router header */ | |||
1131 | if (ibuf_add_zero(buf, sizeof(lsa_hdr)) == -1) | |||
1132 | fatal("orig_net_lsa: ibuf_add_zero failed"); | |||
1133 | ||||
1134 | /* LSA net mask and then all fully adjacent routers */ | |||
1135 | if (ibuf_add(buf, &iface->mask, sizeof(iface->mask))) | |||
1136 | fatal("orig_net_lsa: ibuf_add failed"); | |||
1137 | ||||
1138 | /* fully adjacent neighbors + self */ | |||
1139 | LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!= ((void *)0); (nbr) = ((nbr)->entry.le_next)) | |||
1140 | if (nbr->state & NBR_STA_FULL0x0100) { | |||
1141 | if (ibuf_add(buf, &nbr->id, sizeof(nbr->id))) | |||
1142 | fatal("orig_net_lsa: ibuf_add failed"); | |||
1143 | num_rtr++; | |||
1144 | } | |||
1145 | ||||
1146 | if (num_rtr == 1) { | |||
1147 | /* non transit net therefore no need to generate a net lsa */ | |||
1148 | ibuf_free(buf); | |||
1149 | return; | |||
1150 | } | |||
1151 | ||||
1152 | /* LSA header */ | |||
1153 | if (iface->state & IF_STA_DR0x40) | |||
1154 | lsa_hdr.age = htons(DEFAULT_AGE)(__uint16_t)(__builtin_constant_p(0) ? (__uint16_t)(((__uint16_t )(0) & 0xffU) << 8 | ((__uint16_t)(0) & 0xff00U ) >> 8) : __swap16md(0)); | |||
1155 | else | |||
1156 | lsa_hdr.age = htons(MAX_AGE)(__uint16_t)(__builtin_constant_p(3600) ? (__uint16_t)(((__uint16_t )(3600) & 0xffU) << 8 | ((__uint16_t)(3600) & 0xff00U ) >> 8) : __swap16md(3600)); | |||
1157 | ||||
1158 | lsa_hdr.opts = area_ospf_options(iface->area); | |||
1159 | lsa_hdr.type = LSA_TYPE_NETWORK2; | |||
1160 | lsa_hdr.ls_id = iface->addr.s_addr; | |||
1161 | lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr; | |||
1162 | lsa_hdr.seq_num = htonl(INIT_SEQ_NUM)(__uint32_t)(__builtin_constant_p(0x80000001) ? (__uint32_t)( ((__uint32_t)(0x80000001) & 0xff) << 24 | ((__uint32_t )(0x80000001) & 0xff00) << 8 | ((__uint32_t)(0x80000001 ) & 0xff0000) >> 8 | ((__uint32_t)(0x80000001) & 0xff000000) >> 24) : __swap32md(0x80000001)); | |||
1163 | lsa_hdr.len = htons(ibuf_size(buf))(__uint16_t)(__builtin_constant_p(ibuf_size(buf)) ? (__uint16_t )(((__uint16_t)(ibuf_size(buf)) & 0xffU) << 8 | ((__uint16_t )(ibuf_size(buf)) & 0xff00U) >> 8) : __swap16md(ibuf_size (buf))); | |||
1164 | lsa_hdr.ls_chksum = 0; /* updated later */ | |||
1165 | if (ibuf_set(buf, 0, &lsa_hdr, sizeof(lsa_hdr)) == -1) | |||
1166 | fatal("orig_net_lsa: ibuf_set failed"); | |||
1167 | ||||
1168 | chksum = iso_cksum(ibuf_data(buf), ibuf_size(buf), LS_CKSUM_OFFSET__builtin_offsetof(struct lsa_hdr, ls_chksum)); | |||
1169 | if (ibuf_set_n16(buf, LS_CKSUM_OFFSET__builtin_offsetof(struct lsa_hdr, ls_chksum), chksum) == -1) | |||
1170 | fatal("orig_net_lsa: ibuf_set_n16 failed"); | |||
1171 | ||||
1172 | imsg_compose_event(iev_rde, IMSG_LS_UPD, iface->self->peerid, 0, | |||
1173 | -1, ibuf_data(buf), ibuf_size(buf)); | |||
1174 | ||||
1175 | ibuf_free(buf); | |||
1176 | } | |||
1177 | ||||
1178 | u_int32_t | |||
1179 | ospfe_router_id(void) | |||
1180 | { | |||
1181 | return (oeconf->rtr_id.s_addr); | |||
1182 | } | |||
1183 | ||||
1184 | void | |||
1185 | ospfe_fib_update(int type) | |||
1186 | { | |||
1187 | int old = oe_nofib; | |||
1188 | ||||
1189 | if (type == IMSG_CTL_FIB_COUPLE) | |||
1190 | oe_nofib = 0; | |||
1191 | if (type == IMSG_CTL_FIB_DECOUPLE) | |||
1192 | oe_nofib = 1; | |||
1193 | if (old != oe_nofib) | |||
1194 | orig_rtr_lsa_all(NULL((void *)0)); | |||
1195 | } | |||
1196 | ||||
1197 | void | |||
1198 | ospfe_iface_ctl(struct ctl_conn *c, unsigned int idx) | |||
1199 | { | |||
1200 | struct area *area; | |||
1201 | struct iface *iface; | |||
1202 | struct ctl_iface *ictl; | |||
1203 | ||||
1204 | LIST_FOREACH(area, &oeconf->area_list, entry)for((area) = ((&oeconf->area_list)->lh_first); (area )!= ((void *)0); (area) = ((area)->entry.le_next)) | |||
1205 | LIST_FOREACH(iface, &area->iface_list, entry)for((iface) = ((&area->iface_list)->lh_first); (iface )!= ((void *)0); (iface) = ((iface)->entry.le_next)) | |||
1206 | if (idx == 0 || idx == iface->ifindex) { | |||
1207 | ictl = if_to_ctl(iface); | |||
1208 | imsg_compose_event(&c->iev, | |||
1209 | IMSG_CTL_SHOW_INTERFACE, 0, 0, -1, | |||
1210 | ictl, sizeof(struct ctl_iface)); | |||
1211 | } | |||
1212 | } | |||
1213 | ||||
1214 | void | |||
1215 | ospfe_nbr_ctl(struct ctl_conn *c) | |||
1216 | { | |||
1217 | struct area *area; | |||
1218 | struct iface *iface; | |||
1219 | struct nbr *nbr; | |||
1220 | struct ctl_nbr *nctl; | |||
1221 | ||||
1222 | LIST_FOREACH(area, &oeconf->area_list, entry)for((area) = ((&oeconf->area_list)->lh_first); (area )!= ((void *)0); (area) = ((area)->entry.le_next)) | |||
1223 | LIST_FOREACH(iface, &area->iface_list, entry)for((iface) = ((&area->iface_list)->lh_first); (iface )!= ((void *)0); (iface) = ((iface)->entry.le_next)) | |||
1224 | LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!= ((void *)0); (nbr) = ((nbr)->entry.le_next)) { | |||
1225 | if (iface->self != nbr) { | |||
1226 | nctl = nbr_to_ctl(nbr); | |||
1227 | imsg_compose_event(&c->iev, | |||
1228 | IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl, | |||
1229 | sizeof(struct ctl_nbr)); | |||
1230 | } | |||
1231 | } | |||
1232 | ||||
1233 | imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL((void *)0), 0); | |||
1234 | } | |||
1235 | ||||
1236 | void | |||
1237 | ospfe_demote_area(struct area *area, int active) | |||
1238 | { | |||
1239 | struct demote_msg dmsg; | |||
1240 | ||||
1241 | if (ospfd_process != PROC_OSPF_ENGINE || | |||
1242 | area->demote_group[0] == '\0') | |||
1243 | return; | |||
1244 | ||||
1245 | bzero(&dmsg, sizeof(dmsg)); | |||
1246 | strlcpy(dmsg.demote_group, area->demote_group, | |||
1247 | sizeof(dmsg.demote_group)); | |||
1248 | dmsg.level = area->demote_level; | |||
1249 | if (active) | |||
1250 | dmsg.level = -dmsg.level; | |||
1251 | ||||
1252 | ospfe_imsg_compose_parent(IMSG_DEMOTE, 0, &dmsg, sizeof(dmsg)); | |||
1253 | } | |||
1254 | ||||
1255 | void | |||
1256 | ospfe_demote_iface(struct iface *iface, int active) | |||
1257 | { | |||
1258 | struct demote_msg dmsg; | |||
1259 | ||||
1260 | if (ospfd_process != PROC_OSPF_ENGINE || | |||
1261 | iface->demote_group[0] == '\0') | |||
1262 | return; | |||
1263 | ||||
1264 | bzero(&dmsg, sizeof(dmsg)); | |||
1265 | strlcpy(dmsg.demote_group, iface->demote_group, | |||
1266 | sizeof(dmsg.demote_group)); | |||
1267 | if (active) | |||
1268 | dmsg.level = -1; | |||
1269 | else | |||
1270 | dmsg.level = 1; | |||
1271 | ||||
1272 | log_warnx("ospfe_demote_iface: group %s level %d", dmsg.demote_group, | |||
1273 | dmsg.level); | |||
1274 | ||||
1275 | ospfe_imsg_compose_parent(IMSG_DEMOTE, 0, &dmsg, sizeof(dmsg)); | |||
1276 | } |