1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (C) 2011 Hiroki Sato <hrs@FreeBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30 #include <sys/param.h>
31 #include <sys/queue.h>
32 #include <sys/socket.h>
33 #include <sys/stat.h>
34 #include <sys/un.h>
35 #include <sys/uio.h>
36 #include <net/if.h>
37 #include <net/if_dl.h>
38 #include <netinet/in.h>
39 #include <netinet/icmp6.h>
40 #include <fcntl.h>
41 #include <errno.h>
42 #include <netdb.h>
43 #include <unistd.h>
44 #include <signal.h>
45 #include <string.h>
46 #include <stdarg.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <syslog.h>
50
51 #include "pathnames.h"
52 #include "rtadvd.h"
53 #include "if.h"
54 #include "config.h"
55 #include "control.h"
56 #include "control_server.h"
57 #include "timer.h"
58
59 static char *do_reload_ifname;
60 static int do_reload;
61 static int do_shutdown;
62
set_do_reload(int sig __unused)63 void set_do_reload(int sig __unused) { do_reload = 1; }
set_do_reload_ifname(char * ifname)64 void set_do_reload_ifname(char *ifname){ do_reload_ifname = ifname; }
set_do_shutdown(int sig __unused)65 void set_do_shutdown(int sig __unused) { do_shutdown = 1; }
reset_do_reload(void)66 void reset_do_reload(void) { do_reload = 0; do_reload_ifname = NULL; }
reset_do_shutdown(void)67 void reset_do_shutdown(void) { do_shutdown = 0; }
is_do_reload(void)68 int is_do_reload(void) { return (do_reload); }
is_do_shutdown(void)69 int is_do_shutdown(void) { return (do_shutdown); }
reload_ifname(void)70 char *reload_ifname(void) { return (do_reload_ifname); }
71
72 #define DEF_PL_HANDLER(key) { #key, cm_getprop_##key }
73
74 static int cm_getprop_echo(struct ctrl_msg_pl *);
75 static int cm_getprop_version(struct ctrl_msg_pl *);
76 static int cm_getprop_ifilist(struct ctrl_msg_pl *);
77 static int cm_getprop_ifi(struct ctrl_msg_pl *);
78 static int cm_getprop_ifi_ra_timer(struct ctrl_msg_pl *);
79 static int cm_getprop_rai(struct ctrl_msg_pl *);
80 static int cm_getprop_pfx(struct ctrl_msg_pl *);
81 static int cm_getprop_rdnss(struct ctrl_msg_pl *);
82 static int cm_getprop_dnssl(struct ctrl_msg_pl *);
83 static int cm_getprop_pref64(struct ctrl_msg_pl *);
84 static int cm_getprop_rti(struct ctrl_msg_pl *);
85
86 static int cm_setprop_reload(struct ctrl_msg_pl *);
87 static int cm_setprop_enable(struct ctrl_msg_pl *);
88 static int cm_setprop_disable(struct ctrl_msg_pl *);
89
90 static struct dispatch_table {
91 const char *dt_comm;
92 int (*dt_act)(struct ctrl_msg_pl *cp);
93 } getprop_dtable[] = {
94 { "", cm_getprop_echo },
95 DEF_PL_HANDLER(echo),
96 DEF_PL_HANDLER(version),
97 DEF_PL_HANDLER(ifilist),
98 DEF_PL_HANDLER(ifi),
99 DEF_PL_HANDLER(ifi_ra_timer),
100 DEF_PL_HANDLER(rai),
101 DEF_PL_HANDLER(rti),
102 DEF_PL_HANDLER(pfx),
103 DEF_PL_HANDLER(rdnss),
104 DEF_PL_HANDLER(dnssl),
105 DEF_PL_HANDLER(pref64),
106 };
107
108 static int
cm_getprop_echo(struct ctrl_msg_pl * cp)109 cm_getprop_echo(struct ctrl_msg_pl *cp)
110 {
111
112 syslog(LOG_DEBUG, "<%s> enter", __func__);
113 cp->cp_val = strdup("");
114 cp->cp_val_len = strlen(cp->cp_val) + 1;
115
116 return (0);
117 }
118
119 static int
cm_getprop_version(struct ctrl_msg_pl * cp)120 cm_getprop_version(struct ctrl_msg_pl *cp)
121 {
122
123 syslog(LOG_DEBUG, "<%s> enter", __func__);
124 cp->cp_val = strdup(CM_VERSION_STR);
125 cp->cp_val_len = strlen(cp->cp_val) + 1;
126
127 return (0);
128 }
129
130 static int
cm_getprop_ifilist(struct ctrl_msg_pl * cp)131 cm_getprop_ifilist(struct ctrl_msg_pl *cp)
132 {
133 struct ifinfo *ifi;
134 char *p;
135 size_t len;
136
137 syslog(LOG_DEBUG, "<%s> enter", __func__);
138
139 len = 0;
140 TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
141 len += strlen(ifi->ifi_ifname) + 1;
142 }
143
144 syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
145
146 p = malloc(len);
147 if (p == NULL)
148 exit(1);
149 memset(p, 0, len);
150 cp->cp_val = p;
151
152 if (len > 0)
153 TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
154 syslog(LOG_DEBUG, "<%s> add ifname=%s(%d)",
155 __func__, ifi->ifi_ifname, ifi->ifi_ifindex);
156 strcpy(p, ifi->ifi_ifname);
157 p += strlen(ifi->ifi_ifname) + 1;
158 }
159 cp->cp_val_len = p - cp->cp_val;
160
161 return (0);
162 }
163
164 static int
cm_getprop_ifi(struct ctrl_msg_pl * cp)165 cm_getprop_ifi(struct ctrl_msg_pl *cp)
166 {
167 struct ifinfo *ifi;
168 char *p;
169 size_t len;
170
171 syslog(LOG_DEBUG, "<%s> enter", __func__);
172
173 TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
174 if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
175 break;
176 }
177 if (ifi == NULL) {
178 syslog(LOG_ERR, "<%s> %s not found", __func__,
179 cp->cp_ifname);
180 return (1);
181 }
182
183 p = malloc(sizeof(*ifi));
184 if (p == NULL)
185 exit(1);
186 len = cm_str2bin(p, ifi, sizeof(*ifi));
187
188 syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
189
190 if (len == 0)
191 return (1);
192
193 cp->cp_val = p;
194 cp->cp_val_len = len;
195
196 return (0);
197 }
198
199 static int
cm_getprop_rai(struct ctrl_msg_pl * cp)200 cm_getprop_rai(struct ctrl_msg_pl *cp)
201 {
202 struct ifinfo *ifi;
203 struct rainfo *rai;
204 char *p;
205 size_t len;
206
207 syslog(LOG_DEBUG, "<%s> enter", __func__);
208
209 TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
210 if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
211 break;
212 }
213 if (ifi == NULL) {
214 syslog(LOG_ERR, "<%s> %s not found", __func__,
215 cp->cp_ifname);
216 return (1);
217 }
218 if ((rai = ifi->ifi_rainfo) == NULL) {
219 syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
220 cp->cp_ifname);
221 return (1);
222 }
223
224 p = malloc(sizeof(*rai));
225 if (p == NULL)
226 exit(1);
227 len = cm_str2bin(p, rai, sizeof(*rai));
228
229 syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
230
231 if (len == 0)
232 return (1);
233
234 cp->cp_val = p;
235 cp->cp_val_len = len;
236
237 return (0);
238 }
239
240 static int
cm_getprop_ifi_ra_timer(struct ctrl_msg_pl * cp)241 cm_getprop_ifi_ra_timer(struct ctrl_msg_pl *cp)
242 {
243 struct ifinfo *ifi;
244 struct rainfo *rai;
245 struct rtadvd_timer *rtimer;
246 char *p;
247 size_t len;
248
249 syslog(LOG_DEBUG, "<%s> enter", __func__);
250
251 TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
252 if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
253 break;
254 }
255 if (ifi == NULL) {
256 syslog(LOG_ERR, "<%s> %s not found", __func__,
257 cp->cp_ifname);
258 return (1);
259 }
260 if ((rai = ifi->ifi_rainfo) == NULL) {
261 syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
262 cp->cp_ifname);
263 return (1);
264 }
265 if ((rtimer = ifi->ifi_ra_timer) == NULL) {
266 syslog(LOG_ERR, "<%s> %s has no ifi_ra_timer", __func__,
267 cp->cp_ifname);
268 return (1);
269 }
270 p = malloc(sizeof(*rtimer));
271 if (p == NULL)
272 exit(1);
273 len = cm_str2bin(p, rtimer, sizeof(*rtimer));
274
275 syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
276
277 if (len == 0)
278 return (1);
279
280 cp->cp_val = p;
281 cp->cp_val_len = len;
282
283 return (0);
284 }
285
286 static int
cm_getprop_rti(struct ctrl_msg_pl * cp)287 cm_getprop_rti(struct ctrl_msg_pl *cp)
288 {
289 struct ifinfo *ifi;
290 struct rainfo *rai;
291 struct rtinfo *rti;
292 char *p;
293 size_t len;
294
295 syslog(LOG_DEBUG, "<%s> enter", __func__);
296
297 len = 0;
298 TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
299 if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
300 break;
301 }
302 if (ifi == NULL) {
303 syslog(LOG_ERR, "<%s> %s not found", __func__,
304 cp->cp_ifname);
305 return (1);
306 }
307 if (ifi->ifi_rainfo == NULL) {
308 syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
309 cp->cp_ifname);
310 return (1);
311 }
312 rai = ifi->ifi_rainfo;
313 TAILQ_FOREACH(rti, &rai->rai_route, rti_next) {
314 len += sizeof(*rti);
315 }
316
317 syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
318
319 p = malloc(len);
320 if (p == NULL)
321 exit(1);
322 memset(p, 0, len);
323 cp->cp_val = p;
324
325 if (len > 0)
326 TAILQ_FOREACH(rti, &rai->rai_route, rti_next) {
327 memcpy(p, rti, sizeof(*rti));
328 p += sizeof(*rti);
329 }
330 cp->cp_val_len = p - cp->cp_val;
331
332 return (0);
333 }
334
335 static int
cm_getprop_pfx(struct ctrl_msg_pl * cp)336 cm_getprop_pfx(struct ctrl_msg_pl *cp)
337 {
338 struct ifinfo *ifi;
339 struct rainfo *rai;
340 struct prefix *pfx;
341 char *p;
342 size_t len;
343
344 syslog(LOG_DEBUG, "<%s> enter", __func__);
345
346 len = 0;
347 TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
348 if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
349 break;
350 }
351 if (ifi == NULL) {
352 syslog(LOG_ERR, "<%s> %s not found", __func__,
353 cp->cp_ifname);
354 return (1);
355 }
356 if (ifi->ifi_rainfo == NULL) {
357 syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
358 cp->cp_ifname);
359 return (1);
360 }
361 rai = ifi->ifi_rainfo;
362 TAILQ_FOREACH(pfx, &rai->rai_prefix, pfx_next) {
363 len += sizeof(*pfx);
364 }
365
366 syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
367
368 p = malloc(len);
369 if (p == NULL)
370 exit(1);
371 memset(p, 0, len);
372 cp->cp_val = p;
373
374 if (len > 0)
375 TAILQ_FOREACH(pfx, &rai->rai_prefix, pfx_next) {
376 memcpy(p, pfx, sizeof(*pfx));
377 p += sizeof(*pfx);
378 }
379 cp->cp_val_len = p - cp->cp_val;
380
381 return (0);
382 }
383
384 static int
cm_getprop_rdnss(struct ctrl_msg_pl * cp)385 cm_getprop_rdnss(struct ctrl_msg_pl *cp)
386 {
387 struct ifinfo *ifi;
388 struct rainfo *rai;
389 struct rdnss *rdn;
390 struct rdnss_addr *rda;
391 char *p;
392 size_t len;
393 uint16_t *rdn_cnt;
394 uint16_t *rda_cnt;
395
396 syslog(LOG_DEBUG, "<%s> enter", __func__);
397
398 len = 0;
399 TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
400 if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
401 break;
402 }
403 if (ifi == NULL) {
404 syslog(LOG_ERR, "<%s> %s not found", __func__,
405 cp->cp_ifname);
406 return (1);
407 }
408 if (ifi->ifi_rainfo == NULL) {
409 syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
410 cp->cp_ifname);
411 return (1);
412 }
413 rai = ifi->ifi_rainfo;
414
415 len = sizeof(*rdn_cnt);
416 TAILQ_FOREACH(rdn, &rai->rai_rdnss, rd_next) {
417 len += sizeof(*rdn);
418 len += sizeof(*rda_cnt);
419 TAILQ_FOREACH(rda, &rdn->rd_list, ra_next) {
420 len += sizeof(*rda);
421 }
422 }
423
424 syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
425
426 p = malloc(len);
427 if (p == NULL)
428 exit(1);
429 memset(p, 0, len);
430 cp->cp_val = p;
431
432 rdn_cnt = (uint16_t *)p;
433 p += sizeof(*rdn_cnt);
434 TAILQ_FOREACH(rdn, &rai->rai_rdnss, rd_next) {
435 *rdn_cnt += 1;
436 memcpy(p, rdn, sizeof(*rdn));
437 p += sizeof(*rdn);
438
439 rda_cnt = (uint16_t *)p;
440 p += sizeof(*rda_cnt);
441 TAILQ_FOREACH(rda, &rdn->rd_list, ra_next) {
442 *rda_cnt += 1;
443 memcpy(p, rda, sizeof(*rda));
444 p += sizeof(*rda);
445 }
446 }
447 syslog(LOG_DEBUG, "<%s> rdn_cnt = %d", __func__, *rdn_cnt);
448 cp->cp_val_len = p - cp->cp_val;
449
450 return (0);
451 }
452
453 static int
cm_getprop_dnssl(struct ctrl_msg_pl * cp)454 cm_getprop_dnssl(struct ctrl_msg_pl *cp)
455 {
456 struct ifinfo *ifi;
457 struct rainfo *rai;
458 struct dnssl *dns;
459 struct dnssl_addr *dna;
460 char *p;
461 size_t len;
462 uint16_t *dns_cnt;
463 uint16_t *dna_cnt;
464
465 syslog(LOG_DEBUG, "<%s> enter", __func__);
466
467 len = 0;
468 TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
469 if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
470 break;
471 }
472 if (ifi == NULL) {
473 syslog(LOG_ERR, "<%s> %s not found", __func__,
474 cp->cp_ifname);
475 return (1);
476 }
477 if (ifi->ifi_rainfo == NULL) {
478 syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
479 cp->cp_ifname);
480 return (1);
481 }
482 rai = ifi->ifi_rainfo;
483
484 len = sizeof(*dns_cnt);
485 TAILQ_FOREACH(dns, &rai->rai_dnssl, dn_next) {
486 len += sizeof(*dns);
487 len += sizeof(*dna_cnt);
488 TAILQ_FOREACH(dna, &dns->dn_list, da_next) {
489 len += sizeof(*dna);
490 }
491 }
492
493 syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
494
495 p = malloc(len);
496 if (p == NULL)
497 exit(1);
498 memset(p, 0, len);
499 cp->cp_val = p;
500
501 dns_cnt = (uint16_t *)cp->cp_val;
502 p += sizeof(*dns_cnt);
503 TAILQ_FOREACH(dns, &rai->rai_dnssl, dn_next) {
504 (*dns_cnt)++;
505 memcpy(p, dns, sizeof(*dns));
506 p += sizeof(*dns);
507
508 dna_cnt = (uint16_t *)p;
509 p += sizeof(*dna_cnt);
510 TAILQ_FOREACH(dna, &dns->dn_list, da_next) {
511 (*dna_cnt)++;
512 memcpy(p, dna, sizeof(*dna));
513 p += sizeof(*dna);
514 }
515 }
516 cp->cp_val_len = p - cp->cp_val;
517
518 return (0);
519 }
520
521 static int
cm_getprop_pref64(struct ctrl_msg_pl * cp)522 cm_getprop_pref64(struct ctrl_msg_pl *cp)
523 {
524 struct ifinfo *ifi;
525 struct rainfo *rai;
526 struct pref64 *prf64;
527 char *p;
528 size_t len;
529 uint16_t *prf64_cnt;
530
531 syslog(LOG_DEBUG, "<%s> enter", __func__);
532
533 len = 0;
534 TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
535 if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
536 break;
537 }
538 if (ifi == NULL) {
539 syslog(LOG_ERR, "<%s> %s not found", __func__,
540 cp->cp_ifname);
541 return (1);
542 }
543 if (ifi->ifi_rainfo == NULL) {
544 syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
545 cp->cp_ifname);
546 return (1);
547 }
548 rai = ifi->ifi_rainfo;
549
550 len = sizeof(*prf64_cnt);
551 TAILQ_FOREACH(prf64, &rai->rai_pref64, p64_next)
552 len += sizeof(*prf64);
553
554 syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
555
556 p = malloc(len);
557 if (p == NULL)
558 exit(1);
559 memset(p, 0, len);
560 cp->cp_val = p;
561
562 prf64_cnt = (uint16_t *)cp->cp_val;
563 p += sizeof(*prf64_cnt);
564 TAILQ_FOREACH(prf64, &rai->rai_pref64, p64_next) {
565 (*prf64_cnt)++;
566 memcpy(p, prf64, sizeof(*prf64));
567 p += sizeof(*prf64);
568 }
569 cp->cp_val_len = p - cp->cp_val;
570
571 return (0);
572 }
573
574
575 int
cm_getprop(struct ctrl_msg_pl * cp)576 cm_getprop(struct ctrl_msg_pl *cp)
577 {
578 size_t i;
579
580 syslog(LOG_DEBUG, "<%s> enter", __func__);
581
582 if (cp == NULL)
583 return (1);
584
585 for (i = 0;
586 i < nitems(getprop_dtable);
587 i++) {
588 if (strcmp(cp->cp_key, getprop_dtable[i].dt_comm) == 0)
589 return (getprop_dtable[i].dt_act(cp));
590 }
591 return (1);
592 }
593
594 int
cm_setprop(struct ctrl_msg_pl * cp)595 cm_setprop(struct ctrl_msg_pl *cp)
596 {
597 syslog(LOG_DEBUG, "<%s> enter", __func__);
598
599 if (cp == NULL || cp->cp_key == NULL)
600 return (1);
601
602 if (strncmp(cp->cp_key, "reload", sizeof("reload")) == 0)
603 cm_setprop_reload(cp);
604 else if (strncmp(cp->cp_key, "shutdown", sizeof("shutdown")) == 0)
605 set_do_shutdown(0);
606 else if (strncmp(cp->cp_key, "enable", sizeof("enable")) == 0)
607 cm_setprop_enable(cp);
608 else if (strncmp(cp->cp_key, "disable", sizeof("disable")) == 0)
609 cm_setprop_disable(cp);
610 else if (strncmp(cp->cp_key, "echo", 8) == 0)
611 ; /* do nothing */
612 else
613 return (1);
614
615 return (0);
616 }
617
618 static int
cm_setprop_reload(struct ctrl_msg_pl * cp)619 cm_setprop_reload(struct ctrl_msg_pl *cp)
620 {
621
622 syslog(LOG_DEBUG, "<%s> enter", __func__);
623
624 set_do_reload_ifname(cp->cp_ifname);
625 set_do_reload(1);
626
627 return (0);
628 }
629
630 static int
cm_setprop_enable(struct ctrl_msg_pl * cp)631 cm_setprop_enable(struct ctrl_msg_pl *cp)
632 {
633 struct ifinfo *ifi;
634
635 syslog(LOG_DEBUG, "<%s> enter", __func__);
636
637 TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
638 if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
639 break;
640 }
641 if (ifi == NULL) {
642 syslog(LOG_ERR, "<%s> %s not found", __func__,
643 cp->cp_ifname);
644 return (1);
645 }
646
647 ifi->ifi_persist = 1;
648 set_do_reload_ifname(ifi->ifi_ifname);
649 set_do_reload(0);
650
651 return (0);
652 }
653
654 static int
cm_setprop_disable(struct ctrl_msg_pl * cp)655 cm_setprop_disable(struct ctrl_msg_pl *cp)
656 {
657 struct ifinfo *ifi;
658
659 syslog(LOG_DEBUG, "<%s> enter", __func__);
660
661 TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
662 if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
663 break;
664 }
665 if (ifi == NULL) {
666 syslog(LOG_ERR, "<%s> %s not found", __func__,
667 cp->cp_ifname);
668 return (1);
669 }
670
671 if (ifi->ifi_persist == 1) {
672 ifi->ifi_persist = 0;
673 rm_ifinfo(ifi);
674
675 /* MC leaving needed here */
676 sock_mc_leave(&sock, ifi->ifi_ifindex);
677
678 set_do_reload_ifname(ifi->ifi_ifname);
679 set_do_reload(0);
680 }
681
682 return (0);
683 }
684
685 int
cm_handler_server(int fd)686 cm_handler_server(int fd)
687 {
688 int state;
689 char *msg;
690 struct ctrl_msg_hdr *cm;
691 struct ctrl_msg_pl cp;
692 char buf[CM_MSG_MAXLEN];
693 char pbuf[CM_MSG_MAXLEN];
694 int error;
695
696 syslog(LOG_DEBUG, "<%s> enter", __func__);
697
698 memset(buf, 0, sizeof(buf));
699 memset(pbuf, 0, sizeof(pbuf));
700 cm = (struct ctrl_msg_hdr *)buf;
701 msg = (char *)buf + sizeof(*cm);
702
703 state = CM_STATE_INIT;
704 while (state != CM_STATE_EOM) {
705 syslog(LOG_DEBUG, "<%s> state = %d", __func__, state);
706
707 switch (state) {
708 case CM_STATE_INIT:
709 state = CM_STATE_MSG_RECV;
710 break;
711 case CM_STATE_MSG_DISPATCH:
712 cm->cm_version = CM_VERSION;
713 error = cm_send(fd, buf);
714 if (error)
715 syslog(LOG_WARNING,
716 "<%s> cm_send()", __func__);
717 state = CM_STATE_EOM;
718 break;
719 case CM_STATE_ACK_WAIT:
720 error = cm_recv(fd, buf);
721 if (error) {
722 syslog(LOG_ERR,
723 "<%s> cm_recv()", __func__);
724 close(fd);
725 return (-1);
726 }
727
728 switch (cm->cm_type) {
729 case CM_TYPE_ACK:
730 break;
731 case CM_TYPE_ERR:
732 syslog(LOG_DEBUG,
733 "<%s> CM_TYPE_ERR", __func__);
734 close(fd);
735 return (-1);
736 default:
737 syslog(LOG_DEBUG,
738 "<%s> unknown status", __func__);
739 close(fd);
740 return (-1);
741 }
742 state = CM_STATE_EOM;
743 break;
744 case CM_STATE_MSG_RECV:
745 error = cm_recv(fd, buf);
746
747 if (error) {
748 syslog(LOG_ERR,
749 "<%s> cm_recv()", __func__);
750 close(fd);
751 return (-1);
752 }
753 memset(&cp, 0, sizeof(cp));
754
755 syslog(LOG_DEBUG,
756 "<%s> cm->cm_type = %d", __func__, cm->cm_type);
757 syslog(LOG_DEBUG,
758 "<%s> cm->cm_len = %zu", __func__, cm->cm_len);
759
760 switch (cm->cm_type) {
761 case CM_TYPE_EOM:
762 state = CM_STATE_EOM;
763 case CM_TYPE_NUL:
764 cm->cm_type = CM_TYPE_ACK;
765 cm->cm_len = sizeof(*cm);
766 break;
767 case CM_TYPE_REQ_GET_PROP:
768 cm_bin2pl(msg, &cp);
769 error = cm_getprop(&cp);
770 if (error) {
771 cm->cm_type = CM_TYPE_ERR;
772 cm->cm_len = sizeof(*cm);
773 } else {
774 cm->cm_type = CM_TYPE_ACK;
775 cm->cm_len = sizeof(*cm);
776 cm->cm_len += cm_pl2bin(msg, &cp);
777 }
778 if (cp.cp_val != NULL)
779 free(cp.cp_val);
780 break;
781 case CM_TYPE_REQ_SET_PROP:
782 cm_bin2pl(msg, &cp);
783 error = cm_setprop(&cp);
784 if (error) {
785 cm->cm_type = CM_TYPE_ERR;
786 cm->cm_len = sizeof(*cm);
787 } else {
788 cm->cm_type = CM_TYPE_ACK;
789 cm->cm_len = sizeof(*cm);
790 }
791 break;
792 default:
793 cm->cm_type = CM_TYPE_ERR;
794 cm->cm_len = sizeof(*cm);
795 }
796
797 switch (cm->cm_type) {
798 case CM_TYPE_ERR:
799 case CM_TYPE_ACK:
800 state = CM_STATE_MSG_DISPATCH;
801 break;
802 }
803 }
804 }
805 syslog(LOG_DEBUG, "<%s> leave", __func__);
806
807 return (0);
808 }
809