xref: /src/usr.sbin/rtadvd/control_server.c (revision 0951901814d1def721ac9a4fc3657af5c9694228)
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