control_server.c revision 224144
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: head/usr.sbin/rtadvd/control_server.c 224144 2011-07-17 19:24:54Z hrs $
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 "control.h"
55#include "control_server.h"
56#include "timer.h"
57
58static char *do_reload_ifname;
59static int do_reload;
60static int do_shutdown;
61
62void set_do_reload(int sig __unused)	{ do_reload = 1; }
63void set_do_reload_ifname(char *ifname){ do_reload_ifname = ifname; }
64void set_do_shutdown(int sig __unused)	{ do_shutdown = 1; }
65void reset_do_reload(void)	{ do_reload = 0; do_reload_ifname = NULL; }
66void reset_do_shutdown(void)	{ do_shutdown = 0; }
67int is_do_reload(void)		{ return (do_reload); }
68int is_do_shutdown(void)	{ return (do_shutdown); }
69char *reload_ifname(void)	{ return (do_reload_ifname); }
70
71#define	DEF_PL_HANDLER(key)	{ #key, cmsg_getprop_##key }
72
73static int cmsg_getprop_echo(struct ctrl_msg_pl *);
74static int cmsg_getprop_version(struct ctrl_msg_pl *);
75static int cmsg_getprop_ifilist(struct ctrl_msg_pl *);
76static int cmsg_getprop_ifi(struct ctrl_msg_pl *);
77static int cmsg_getprop_ifi_ra_timer(struct ctrl_msg_pl *);
78static int cmsg_getprop_rai(struct ctrl_msg_pl *);
79static int cmsg_getprop_pfx(struct ctrl_msg_pl *);
80static int cmsg_getprop_rdnss(struct ctrl_msg_pl *);
81static int cmsg_getprop_dnssl(struct ctrl_msg_pl *);
82static int cmsg_getprop_rti(struct ctrl_msg_pl *);
83
84static int cmsg_setprop_reload(struct ctrl_msg_pl *);
85static int cmsg_setprop_enable(struct ctrl_msg_pl *);
86static int cmsg_setprop_disable(struct ctrl_msg_pl *);
87
88static struct dispatch_table {
89	const char	*dt_comm;
90	int		(*dt_act)(struct ctrl_msg_pl *cp);
91} getprop_dtable[] = {
92	{ "",	cmsg_getprop_echo },
93	DEF_PL_HANDLER(echo),
94	DEF_PL_HANDLER(version),
95	DEF_PL_HANDLER(ifilist),
96	DEF_PL_HANDLER(ifi),
97	DEF_PL_HANDLER(ifi_ra_timer),
98	DEF_PL_HANDLER(rai),
99	DEF_PL_HANDLER(rti),
100	DEF_PL_HANDLER(pfx),
101	DEF_PL_HANDLER(rdnss),
102	DEF_PL_HANDLER(dnssl),
103};
104
105static int
106cmsg_getprop_echo(struct ctrl_msg_pl *cp)
107{
108
109	syslog(LOG_DEBUG, "<%s> enter", __func__);
110	cp->cp_val = strdup("");
111	cp->cp_val_len = strlen(cp->cp_val) + 1;
112
113	return (0);
114}
115
116static int
117cmsg_getprop_version(struct ctrl_msg_pl *cp)
118{
119
120	syslog(LOG_DEBUG, "<%s> enter", __func__);
121	cp->cp_val = strdup(CM_VERSION_STR);
122	cp->cp_val_len = strlen(cp->cp_val) + 1;
123
124	return (0);
125}
126
127static int
128cmsg_getprop_ifilist(struct ctrl_msg_pl *cp)
129{
130	struct ifinfo *ifi;
131	char *p;
132	size_t len;
133
134	syslog(LOG_DEBUG, "<%s> enter", __func__);
135
136	len = 0;
137	TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
138		len += strlen(ifi->ifi_ifname) + 1;
139	}
140
141	syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
142
143	p = malloc(len);
144	if (p == NULL)
145		exit(1);
146	memset(p, 0, len);
147	cp->cp_val = p;
148
149	if (len > 0)
150		TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
151			syslog(LOG_DEBUG, "<%s> add ifname=%s(%d)",
152			    __func__, ifi->ifi_ifname, ifi->ifi_ifindex);
153			strcpy(p, ifi->ifi_ifname);
154			p += strlen(ifi->ifi_ifname) + 1;
155		}
156	cp->cp_val_len = p - cp->cp_val;
157
158	return (0);
159}
160
161static int
162cmsg_getprop_ifi(struct ctrl_msg_pl *cp)
163{
164	struct ifinfo *ifi;
165	char *p;
166	size_t len;
167
168	syslog(LOG_DEBUG, "<%s> enter", __func__);
169
170	TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
171		if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
172			break;
173	}
174	if (ifi == NULL) {
175		syslog(LOG_ERR, "<%s> %s not found", __func__,
176		    cp->cp_ifname);
177		return (1);
178	}
179
180	p = malloc(sizeof(*ifi));
181	if (p == NULL)
182		exit(1);
183	len = cmsg_str2bin(p, ifi, sizeof(*ifi));
184
185	syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
186
187	if (len == 0)
188		return (1);
189
190	cp->cp_val = p;
191	cp->cp_val_len = len;
192
193	return (0);
194}
195
196static int
197cmsg_getprop_rai(struct ctrl_msg_pl *cp)
198{
199	struct ifinfo *ifi;
200	struct rainfo *rai;
201	char *p;
202	size_t len;
203
204	syslog(LOG_DEBUG, "<%s> enter", __func__);
205
206	TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
207		if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
208			break;
209	}
210	if (ifi == NULL) {
211		syslog(LOG_ERR, "<%s> %s not found", __func__,
212		    cp->cp_ifname);
213		return (1);
214	}
215	if ((rai = ifi->ifi_rainfo) == NULL) {
216		syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
217		    cp->cp_ifname);
218		return (1);
219	}
220
221	p = malloc(sizeof(*rai));
222	if (p == NULL)
223		exit(1);
224	len = cmsg_str2bin(p, rai, sizeof(*rai));
225
226	syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
227
228	if (len == 0)
229		return (1);
230
231	cp->cp_val = p;
232	cp->cp_val_len = len;
233
234	return (0);
235}
236
237static int
238cmsg_getprop_ifi_ra_timer(struct ctrl_msg_pl *cp)
239{
240	struct ifinfo *ifi;
241	struct rainfo *rai;
242	struct rtadvd_timer	*rtimer;
243	char *p;
244	size_t len;
245
246	syslog(LOG_DEBUG, "<%s> enter", __func__);
247
248	TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
249		if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
250			break;
251	}
252	if (ifi == NULL) {
253		syslog(LOG_ERR, "<%s> %s not found", __func__,
254		    cp->cp_ifname);
255		return (1);
256	}
257	if ((rai = ifi->ifi_rainfo) == NULL) {
258		syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
259		    cp->cp_ifname);
260		return (1);
261	}
262	if ((rtimer = ifi->ifi_ra_timer) == NULL) {
263		syslog(LOG_ERR, "<%s> %s has no ifi_ra_timer", __func__,
264		    cp->cp_ifname);
265		return (1);
266	}
267	p = malloc(sizeof(*rtimer));
268	if (p == NULL)
269		exit(1);
270	len = cmsg_str2bin(p, rtimer, sizeof(*rtimer));
271
272	syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
273
274	if (len == 0)
275		return (1);
276
277	cp->cp_val = p;
278	cp->cp_val_len = len;
279
280	return (0);
281}
282
283static int
284cmsg_getprop_rti(struct ctrl_msg_pl *cp)
285{
286	struct ifinfo *ifi;
287	struct rainfo *rai;
288	struct rtinfo *rti;
289	char *p;
290	size_t len;
291
292	syslog(LOG_DEBUG, "<%s> enter", __func__);
293
294	len = 0;
295	TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
296		if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
297			break;
298	}
299	if (ifi == NULL) {
300		syslog(LOG_ERR, "<%s> %s not found", __func__,
301		    cp->cp_ifname);
302		return (1);
303	}
304	if (ifi->ifi_rainfo == NULL) {
305		syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
306		    cp->cp_ifname);
307		return (1);
308	}
309	rai = ifi->ifi_rainfo;
310	TAILQ_FOREACH(rti, &rai->rai_route, rti_next) {
311		len += sizeof(*rti);
312	}
313
314	syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
315
316	p = malloc(len);
317	if (p == NULL)
318		exit(1);
319	memset(p, 0, len);
320	cp->cp_val = p;
321
322	if (len > 0)
323		TAILQ_FOREACH(rti, &rai->rai_route, rti_next) {
324			memcpy(p, rti, sizeof(*rti));
325			p += sizeof(*rti);
326		}
327	cp->cp_val_len = p - cp->cp_val;
328
329	return (0);
330}
331
332static int
333cmsg_getprop_pfx(struct ctrl_msg_pl *cp)
334{
335	struct ifinfo *ifi;
336	struct rainfo *rai;
337	struct prefix *pfx;
338	char *p;
339	size_t len;
340
341	syslog(LOG_DEBUG, "<%s> enter", __func__);
342
343	len = 0;
344	TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
345		if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
346			break;
347	}
348	if (ifi == NULL) {
349		syslog(LOG_ERR, "<%s> %s not found", __func__,
350		    cp->cp_ifname);
351		return (1);
352	}
353	if (ifi->ifi_rainfo == NULL) {
354		syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
355		    cp->cp_ifname);
356		return (1);
357	}
358	rai = ifi->ifi_rainfo;
359	TAILQ_FOREACH(pfx, &rai->rai_prefix, pfx_next) {
360		len += sizeof(*pfx);
361	}
362
363	syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
364
365	p = malloc(len);
366	if (p == NULL)
367		exit(1);
368	memset(p, 0, len);
369	cp->cp_val = p;
370
371	if (len > 0)
372		TAILQ_FOREACH(pfx, &rai->rai_prefix, pfx_next) {
373			memcpy(p, pfx, sizeof(*pfx));
374			p += sizeof(*pfx);
375		}
376	cp->cp_val_len = p - cp->cp_val;
377
378	return (0);
379}
380
381static int
382cmsg_getprop_rdnss(struct ctrl_msg_pl *cp)
383{
384	struct ifinfo *ifi;
385	struct rainfo *rai;
386	struct rdnss *rdn;
387	struct rdnss_addr *rda;
388	char *p;
389	size_t len;
390	uint16_t *rdn_cnt;
391	uint16_t *rda_cnt;
392
393	syslog(LOG_DEBUG, "<%s> enter", __func__);
394
395	len = 0;
396	TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
397		if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
398			break;
399	}
400	if (ifi == NULL) {
401		syslog(LOG_ERR, "<%s> %s not found", __func__,
402		    cp->cp_ifname);
403		return (1);
404	}
405	if (ifi->ifi_rainfo == NULL) {
406		syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
407		    cp->cp_ifname);
408		return (1);
409	}
410	rai = ifi->ifi_rainfo;
411
412	len = sizeof(*rdn_cnt);
413	TAILQ_FOREACH(rdn, &rai->rai_rdnss, rd_next) {
414		len += sizeof(*rdn);
415		len += sizeof(*rda_cnt);
416		TAILQ_FOREACH(rda, &rdn->rd_list, ra_next) {
417			len += sizeof(*rda);
418		}
419	}
420
421	syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
422
423	p = malloc(len);
424	if (p == NULL)
425		exit(1);
426	memset(p, 0, len);
427	cp->cp_val = p;
428
429	rdn_cnt = (uint16_t *)p;
430	p += sizeof(*rdn_cnt);
431	TAILQ_FOREACH(rdn, &rai->rai_rdnss, rd_next) {
432		*rdn_cnt += 1;
433		memcpy(p, rdn, sizeof(*rdn));
434		p += sizeof(*rdn);
435
436		rda_cnt = (uint16_t *)p;
437		p += sizeof(*rda_cnt);
438		TAILQ_FOREACH(rda, &rdn->rd_list, ra_next) {
439			*rda_cnt += 1;
440			memcpy(p, rda, sizeof(*rda));
441			p += sizeof(*rda);
442		}
443	}
444	syslog(LOG_DEBUG, "<%s> rdn_cnt = %d", __func__, *rdn_cnt);
445	cp->cp_val_len = p - cp->cp_val;
446
447	return (0);
448}
449
450static int
451cmsg_getprop_dnssl(struct ctrl_msg_pl *cp)
452{
453	struct ifinfo *ifi;
454	struct rainfo *rai;
455	struct dnssl *dns;
456	struct dnssl_addr *dna;
457	char *p;
458	size_t len;
459	uint16_t *dns_cnt;
460	uint16_t *dna_cnt;
461
462	syslog(LOG_DEBUG, "<%s> enter", __func__);
463
464	len = 0;
465	TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
466		if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
467			break;
468	}
469	if (ifi == NULL) {
470		syslog(LOG_ERR, "<%s> %s not found", __func__,
471		    cp->cp_ifname);
472		return (1);
473	}
474	if (ifi->ifi_rainfo == NULL) {
475		syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
476		    cp->cp_ifname);
477		return (1);
478	}
479	rai = ifi->ifi_rainfo;
480
481	len = sizeof(*dns_cnt);
482	TAILQ_FOREACH(dns, &rai->rai_dnssl, dn_next) {
483		len += sizeof(*dns);
484		len += sizeof(*dna_cnt);
485		TAILQ_FOREACH(dna, &dns->dn_list, da_next) {
486			len += sizeof(*dna);
487		}
488	}
489
490	syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
491
492	p = malloc(len);
493	if (p == NULL)
494		exit(1);
495	memset(p, 0, len);
496	cp->cp_val = p;
497
498	dns_cnt = (uint16_t *)cp->cp_val;
499	p += sizeof(*dns_cnt);
500	TAILQ_FOREACH(dns, &rai->rai_dnssl, dn_next) {
501		(*dns_cnt)++;
502		memcpy(p, dns, sizeof(*dns));
503		p += sizeof(*dns);
504
505		dna_cnt = (uint16_t *)p;
506		p += sizeof(*dna_cnt);
507		TAILQ_FOREACH(dna, &dns->dn_list, da_next) {
508			(*dna_cnt)++;
509			memcpy(p, dna, sizeof(*dna));
510			p += sizeof(*dna);
511		}
512	}
513	cp->cp_val_len = p - cp->cp_val;
514
515	return (0);
516}
517
518int
519cmsg_getprop(struct ctrl_msg_pl *cp)
520{
521	size_t i;
522
523	syslog(LOG_DEBUG, "<%s> enter", __func__);
524
525	if (cp == NULL)
526		return (1);
527
528	for (i = 0;
529	     i < sizeof(getprop_dtable) / sizeof(getprop_dtable[0]);
530	     i++) {
531		if (strcmp(cp->cp_key, getprop_dtable[i].dt_comm) == 0)
532			return (getprop_dtable[i].dt_act(cp));
533	}
534	return (1);
535}
536
537int
538cmsg_setprop(struct ctrl_msg_pl *cp)
539{
540	syslog(LOG_DEBUG, "<%s> enter", __func__);
541
542	if (cp == NULL || cp->cp_key == NULL)
543		return (1);
544
545	if (strncmp(cp->cp_key, "reload", sizeof("reload")) == 0)
546		cmsg_setprop_reload(cp);
547	else if (strncmp(cp->cp_key, "shutdown", sizeof("shutdown")) == 0)
548		set_do_shutdown(0);
549	else if (strncmp(cp->cp_key, "enable", sizeof("enable")) == 0)
550		cmsg_setprop_enable(cp);
551	else if (strncmp(cp->cp_key, "disable", sizeof("disable")) == 0)
552		cmsg_setprop_disable(cp);
553	else if (strncmp(cp->cp_key, "echo", 8) == 0)
554		; 		/* do nothing */
555	else
556		return (1);
557
558	return (0);
559}
560
561static int
562cmsg_setprop_reload(struct ctrl_msg_pl *cp)
563{
564
565	syslog(LOG_DEBUG, "<%s> enter", __func__);
566
567	set_do_reload_ifname(cp->cp_ifname);
568	set_do_reload(1);
569
570	return (0);
571}
572
573static int
574cmsg_setprop_enable(struct ctrl_msg_pl *cp)
575{
576	struct ifinfo *ifi;
577
578	syslog(LOG_DEBUG, "<%s> enter", __func__);
579
580	TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
581		if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
582			break;
583	}
584	if (ifi == NULL) {
585		syslog(LOG_ERR, "<%s> %s not found", __func__,
586		    cp->cp_ifname);
587		return (1);
588	}
589
590	ifi->ifi_persist = 1;
591	set_do_reload_ifname(ifi->ifi_ifname);
592	set_do_reload(0);
593
594	return (0);
595}
596
597static int
598cmsg_setprop_disable(struct ctrl_msg_pl *cp)
599{
600	struct ifinfo *ifi;
601
602	syslog(LOG_DEBUG, "<%s> enter", __func__);
603
604	TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
605		if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
606			break;
607	}
608	if (ifi == NULL) {
609		syslog(LOG_ERR, "<%s> %s not found", __func__,
610		    cp->cp_ifname);
611		return (1);
612	}
613
614	ifi->ifi_persist = 0;
615
616	return (0);
617}
618
619int
620cmsg_handler_server(int fd)
621{
622	int state;
623	char *msg;
624	struct ctrl_msg_hdr *cm;
625	struct ctrl_msg_pl cp;
626	char buf[CM_MSG_MAXLEN];
627	char pbuf[CM_MSG_MAXLEN];
628	int error;
629
630	syslog(LOG_DEBUG, "<%s> enter", __func__);
631
632	memset(buf, 0, sizeof(buf));
633	memset(pbuf, 0, sizeof(pbuf));
634	cm = (struct ctrl_msg_hdr *)buf;
635	msg = (char *)buf + sizeof(*cm);
636
637	state = CM_STATE_INIT;
638	while (state != CM_STATE_EOM) {
639		syslog(LOG_DEBUG, "<%s> state = %d", __func__, state);
640
641		switch (state) {
642		case CM_STATE_INIT:
643			state = CM_STATE_MSG_RECV;
644			break;
645		case CM_STATE_MSG_DISPATCH:
646			cm->cm_version = CM_VERSION;
647			error = cmsg_send(fd, buf);
648			if (error)
649				syslog(LOG_WARNING,
650				    "<%s> cmsg_send()", __func__);
651			state = CM_STATE_EOM;
652			break;
653		case CM_STATE_ACK_WAIT:
654			error = cmsg_recv(fd, buf);
655			if (error) {
656				syslog(LOG_ERR,
657				    "<%s> cmsg_recv()", __func__);
658				close(fd);
659				return (-1);
660			}
661
662			switch (cm->cm_type) {
663			case CM_TYPE_ACK:
664				break;
665			case CM_TYPE_ERR:
666				syslog(LOG_DEBUG,
667				    "<%s> CM_TYPE_ERR", __func__);
668				close(fd);
669				return (-1);
670			default:
671				syslog(LOG_DEBUG,
672				    "<%s> unknown status", __func__);
673				close(fd);
674				return (-1);
675			}
676			state = CM_STATE_EOM;
677			break;
678		case CM_STATE_MSG_RECV:
679			error = cmsg_recv(fd, buf);
680
681			if (error) {
682				syslog(LOG_ERR,
683				    "<%s> cmsg_recv()", __func__);
684				close(fd);
685				return (-1);
686			}
687			memset(&cp, 0, sizeof(cp));
688
689			syslog(LOG_DEBUG,
690			    "<%s> cm->cm_type = %d", __func__, cm->cm_type);
691			syslog(LOG_DEBUG,
692			    "<%s> cm->cm_len = %zu", __func__, cm->cm_len);
693
694			switch (cm->cm_type) {
695			case CM_TYPE_EOM:
696				state = CM_STATE_EOM;
697			case CM_TYPE_NUL:
698				cm->cm_type = CM_TYPE_ACK;
699				cm->cm_len = sizeof(*cm);
700				break;
701			case CM_TYPE_REQ_GET_PROP:
702				cmsg_bin2pl(msg, &cp);
703				error = cmsg_getprop(&cp);
704				if (error) {
705					cm->cm_type = CM_TYPE_ERR;
706					cm->cm_len = sizeof(*cm);
707				} else {
708					cm->cm_type = CM_TYPE_ACK;
709					cm->cm_len = sizeof(*cm);
710					cm->cm_len += cmsg_pl2bin(msg, &cp);
711				}
712				if (cp.cp_val != NULL)
713					free(cp.cp_val);
714				break;
715			case CM_TYPE_REQ_SET_PROP:
716				cmsg_bin2pl(msg, &cp);
717				error = cmsg_setprop(&cp);
718				if (error) {
719					cm->cm_type = CM_TYPE_ERR;
720					cm->cm_len = sizeof(*cm);
721				} else {
722					cm->cm_type = CM_TYPE_ACK;
723					cm->cm_len = sizeof(*cm);
724				}
725				break;
726			default:
727				cm->cm_type = CM_TYPE_ERR;
728				cm->cm_len = sizeof(*cm);
729			}
730
731			switch (cm->cm_type) {
732			case CM_TYPE_ERR:
733			case CM_TYPE_ACK:
734				state = CM_STATE_MSG_DISPATCH;
735				break;
736			}
737		}
738	}
739	syslog(LOG_DEBUG, "<%s> leave", __func__);
740
741	return (0);
742}
743