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