1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (C) 2011 Hiroki Sato <[email protected]>
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 * $FreeBSD$
29 *
30 */
31
32 #include <sys/queue.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <sys/stat.h>
36 #include <sys/un.h>
37 #include <sys/uio.h>
38 #include <net/if.h>
39 #include <net/if_dl.h>
40 #include <netinet/in.h>
41 #include <netinet/icmp6.h>
42 #include <fcntl.h>
43 #include <errno.h>
44 #include <netdb.h>
45 #include <unistd.h>
46 #include <signal.h>
47 #include <string.h>
48 #include <stdarg.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <syslog.h>
52
53 #include "pathnames.h"
54 #include "rtadvd.h"
55 #include "if.h"
56 #include "config.h"
57 #include "control.h"
58 #include "control_server.h"
59 #include "timer.h"
60
61 static char *do_reload_ifname;
62 static int do_reload;
63 static int do_shutdown;
64
set_do_reload(int sig __unused)65 void set_do_reload(int sig __unused) { do_reload = 1; }
set_do_reload_ifname(char * ifname)66 void set_do_reload_ifname(char *ifname){ do_reload_ifname = ifname; }
set_do_shutdown(int sig __unused)67 void set_do_shutdown(int sig __unused) { do_shutdown = 1; }
reset_do_reload(void)68 void reset_do_reload(void) { do_reload = 0; do_reload_ifname = NULL; }
reset_do_shutdown(void)69 void reset_do_shutdown(void) { do_shutdown = 0; }
is_do_reload(void)70 int is_do_reload(void) { return (do_reload); }
is_do_shutdown(void)71 int is_do_shutdown(void) { return (do_shutdown); }
reload_ifname(void)72 char *reload_ifname(void) { return (do_reload_ifname); }
73
74 #define DEF_PL_HANDLER(key) { #key, cm_getprop_##key }
75
76 static int cm_getprop_echo(struct ctrl_msg_pl *);
77 static int cm_getprop_version(struct ctrl_msg_pl *);
78 static int cm_getprop_ifilist(struct ctrl_msg_pl *);
79 static int cm_getprop_ifi(struct ctrl_msg_pl *);
80 static int cm_getprop_ifi_ra_timer(struct ctrl_msg_pl *);
81 static int cm_getprop_rai(struct ctrl_msg_pl *);
82 static int cm_getprop_pfx(struct ctrl_msg_pl *);
83 static int cm_getprop_rdnss(struct ctrl_msg_pl *);
84 static int cm_getprop_dnssl(struct ctrl_msg_pl *);
85 static int cm_getprop_rti(struct ctrl_msg_pl *);
86
87 static int cm_setprop_reload(struct ctrl_msg_pl *);
88 static int cm_setprop_enable(struct ctrl_msg_pl *);
89 static int cm_setprop_disable(struct ctrl_msg_pl *);
90
91 static struct dispatch_table {
92 const char *dt_comm;
93 int (*dt_act)(struct ctrl_msg_pl *cp);
94 } getprop_dtable[] = {
95 { "", cm_getprop_echo },
96 DEF_PL_HANDLER(echo),
97 DEF_PL_HANDLER(version),
98 DEF_PL_HANDLER(ifilist),
99 DEF_PL_HANDLER(ifi),
100 DEF_PL_HANDLER(ifi_ra_timer),
101 DEF_PL_HANDLER(rai),
102 DEF_PL_HANDLER(rti),
103 DEF_PL_HANDLER(pfx),
104 DEF_PL_HANDLER(rdnss),
105 DEF_PL_HANDLER(dnssl),
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 int
cm_getprop(struct ctrl_msg_pl * cp)522 cm_getprop(struct ctrl_msg_pl *cp)
523 {
524 size_t i;
525
526 syslog(LOG_DEBUG, "<%s> enter", __func__);
527
528 if (cp == NULL)
529 return (1);
530
531 for (i = 0;
532 i < sizeof(getprop_dtable) / sizeof(getprop_dtable[0]);
533 i++) {
534 if (strcmp(cp->cp_key, getprop_dtable[i].dt_comm) == 0)
535 return (getprop_dtable[i].dt_act(cp));
536 }
537 return (1);
538 }
539
540 int
cm_setprop(struct ctrl_msg_pl * cp)541 cm_setprop(struct ctrl_msg_pl *cp)
542 {
543 syslog(LOG_DEBUG, "<%s> enter", __func__);
544
545 if (cp == NULL || cp->cp_key == NULL)
546 return (1);
547
548 if (strncmp(cp->cp_key, "reload", sizeof("reload")) == 0)
549 cm_setprop_reload(cp);
550 else if (strncmp(cp->cp_key, "shutdown", sizeof("shutdown")) == 0)
551 set_do_shutdown(0);
552 else if (strncmp(cp->cp_key, "enable", sizeof("enable")) == 0)
553 cm_setprop_enable(cp);
554 else if (strncmp(cp->cp_key, "disable", sizeof("disable")) == 0)
555 cm_setprop_disable(cp);
556 else if (strncmp(cp->cp_key, "echo", 8) == 0)
557 ; /* do nothing */
558 else
559 return (1);
560
561 return (0);
562 }
563
564 static int
cm_setprop_reload(struct ctrl_msg_pl * cp)565 cm_setprop_reload(struct ctrl_msg_pl *cp)
566 {
567
568 syslog(LOG_DEBUG, "<%s> enter", __func__);
569
570 set_do_reload_ifname(cp->cp_ifname);
571 set_do_reload(1);
572
573 return (0);
574 }
575
576 static int
cm_setprop_enable(struct ctrl_msg_pl * cp)577 cm_setprop_enable(struct ctrl_msg_pl *cp)
578 {
579 struct ifinfo *ifi;
580
581 syslog(LOG_DEBUG, "<%s> enter", __func__);
582
583 TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
584 if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
585 break;
586 }
587 if (ifi == NULL) {
588 syslog(LOG_ERR, "<%s> %s not found", __func__,
589 cp->cp_ifname);
590 return (1);
591 }
592
593 ifi->ifi_persist = 1;
594 set_do_reload_ifname(ifi->ifi_ifname);
595 set_do_reload(0);
596
597 return (0);
598 }
599
600 static int
cm_setprop_disable(struct ctrl_msg_pl * cp)601 cm_setprop_disable(struct ctrl_msg_pl *cp)
602 {
603 struct ifinfo *ifi;
604
605 syslog(LOG_DEBUG, "<%s> enter", __func__);
606
607 TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
608 if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
609 break;
610 }
611 if (ifi == NULL) {
612 syslog(LOG_ERR, "<%s> %s not found", __func__,
613 cp->cp_ifname);
614 return (1);
615 }
616
617 if (ifi->ifi_persist == 1) {
618 ifi->ifi_persist = 0;
619 rm_ifinfo(ifi);
620
621 /* MC leaving needed here */
622 sock_mc_leave(&sock, ifi->ifi_ifindex);
623
624 set_do_reload_ifname(ifi->ifi_ifname);
625 set_do_reload(0);
626 }
627
628 return (0);
629 }
630
631 int
cm_handler_server(int fd)632 cm_handler_server(int fd)
633 {
634 int state;
635 char *msg;
636 struct ctrl_msg_hdr *cm;
637 struct ctrl_msg_pl cp;
638 char buf[CM_MSG_MAXLEN];
639 char pbuf[CM_MSG_MAXLEN];
640 int error;
641
642 syslog(LOG_DEBUG, "<%s> enter", __func__);
643
644 memset(buf, 0, sizeof(buf));
645 memset(pbuf, 0, sizeof(pbuf));
646 cm = (struct ctrl_msg_hdr *)buf;
647 msg = (char *)buf + sizeof(*cm);
648
649 state = CM_STATE_INIT;
650 while (state != CM_STATE_EOM) {
651 syslog(LOG_DEBUG, "<%s> state = %d", __func__, state);
652
653 switch (state) {
654 case CM_STATE_INIT:
655 state = CM_STATE_MSG_RECV;
656 break;
657 case CM_STATE_MSG_DISPATCH:
658 cm->cm_version = CM_VERSION;
659 error = cm_send(fd, buf);
660 if (error)
661 syslog(LOG_WARNING,
662 "<%s> cm_send()", __func__);
663 state = CM_STATE_EOM;
664 break;
665 case CM_STATE_ACK_WAIT:
666 error = cm_recv(fd, buf);
667 if (error) {
668 syslog(LOG_ERR,
669 "<%s> cm_recv()", __func__);
670 close(fd);
671 return (-1);
672 }
673
674 switch (cm->cm_type) {
675 case CM_TYPE_ACK:
676 break;
677 case CM_TYPE_ERR:
678 syslog(LOG_DEBUG,
679 "<%s> CM_TYPE_ERR", __func__);
680 close(fd);
681 return (-1);
682 default:
683 syslog(LOG_DEBUG,
684 "<%s> unknown status", __func__);
685 close(fd);
686 return (-1);
687 }
688 state = CM_STATE_EOM;
689 break;
690 case CM_STATE_MSG_RECV:
691 error = cm_recv(fd, buf);
692
693 if (error) {
694 syslog(LOG_ERR,
695 "<%s> cm_recv()", __func__);
696 close(fd);
697 return (-1);
698 }
699 memset(&cp, 0, sizeof(cp));
700
701 syslog(LOG_DEBUG,
702 "<%s> cm->cm_type = %d", __func__, cm->cm_type);
703 syslog(LOG_DEBUG,
704 "<%s> cm->cm_len = %zu", __func__, cm->cm_len);
705
706 switch (cm->cm_type) {
707 case CM_TYPE_EOM:
708 state = CM_STATE_EOM;
709 case CM_TYPE_NUL:
710 cm->cm_type = CM_TYPE_ACK;
711 cm->cm_len = sizeof(*cm);
712 break;
713 case CM_TYPE_REQ_GET_PROP:
714 cm_bin2pl(msg, &cp);
715 error = cm_getprop(&cp);
716 if (error) {
717 cm->cm_type = CM_TYPE_ERR;
718 cm->cm_len = sizeof(*cm);
719 } else {
720 cm->cm_type = CM_TYPE_ACK;
721 cm->cm_len = sizeof(*cm);
722 cm->cm_len += cm_pl2bin(msg, &cp);
723 }
724 if (cp.cp_val != NULL)
725 free(cp.cp_val);
726 break;
727 case CM_TYPE_REQ_SET_PROP:
728 cm_bin2pl(msg, &cp);
729 error = cm_setprop(&cp);
730 if (error) {
731 cm->cm_type = CM_TYPE_ERR;
732 cm->cm_len = sizeof(*cm);
733 } else {
734 cm->cm_type = CM_TYPE_ACK;
735 cm->cm_len = sizeof(*cm);
736 }
737 break;
738 default:
739 cm->cm_type = CM_TYPE_ERR;
740 cm->cm_len = sizeof(*cm);
741 }
742
743 switch (cm->cm_type) {
744 case CM_TYPE_ERR:
745 case CM_TYPE_ACK:
746 state = CM_STATE_MSG_DISPATCH;
747 break;
748 }
749 }
750 }
751 syslog(LOG_DEBUG, "<%s> leave", __func__);
752
753 return (0);
754 }
755