]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/rtadvd/control_server.c
Add two missing eventhandler.h headers
[FreeBSD/FreeBSD.git] / usr.sbin / rtadvd / control_server.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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  * $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
65 void set_do_reload(int sig __unused)    { do_reload = 1; }
66 void set_do_reload_ifname(char *ifname){ do_reload_ifname = ifname; }
67 void set_do_shutdown(int sig __unused)  { do_shutdown = 1; }
68 void reset_do_reload(void)      { do_reload = 0; do_reload_ifname = NULL; }
69 void reset_do_shutdown(void)    { do_shutdown = 0; }
70 int is_do_reload(void)          { return (do_reload); }
71 int is_do_shutdown(void)        { return (do_shutdown); }
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }