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