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 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 < nitems(getprop_dtable); 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 } 753