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 "control.h" 55 #include "control_server.h" 56 #include "timer.h" 57 58 static char *do_reload_ifname; 59 static int do_reload; 60 static int do_shutdown; 61 62 void set_do_reload(int sig __unused) { do_reload = 1; } 63 void set_do_reload_ifname(char *ifname){ do_reload_ifname = ifname; } 64 void set_do_shutdown(int sig __unused) { do_shutdown = 1; } 65 void reset_do_reload(void) { do_reload = 0; do_reload_ifname = NULL; } 66 void reset_do_shutdown(void) { do_shutdown = 0; } 67 int is_do_reload(void) { return (do_reload); } 68 int is_do_shutdown(void) { return (do_shutdown); } 69 char *reload_ifname(void) { return (do_reload_ifname); } 70 71 #define DEF_PL_HANDLER(key) { #key, cmsg_getprop_##key } 72 73 static int cmsg_getprop_echo(struct ctrl_msg_pl *); 74 static int cmsg_getprop_version(struct ctrl_msg_pl *); 75 static int cmsg_getprop_ifilist(struct ctrl_msg_pl *); 76 static int cmsg_getprop_ifi(struct ctrl_msg_pl *); 77 static int cmsg_getprop_ifi_ra_timer(struct ctrl_msg_pl *); 78 static int cmsg_getprop_rai(struct ctrl_msg_pl *); 79 static int cmsg_getprop_pfx(struct ctrl_msg_pl *); 80 static int cmsg_getprop_rdnss(struct ctrl_msg_pl *); 81 static int cmsg_getprop_dnssl(struct ctrl_msg_pl *); 82 static int cmsg_getprop_rti(struct ctrl_msg_pl *); 83 84 static int cmsg_setprop_reload(struct ctrl_msg_pl *); 85 static int cmsg_setprop_enable(struct ctrl_msg_pl *); 86 static int cmsg_setprop_disable(struct ctrl_msg_pl *); 87 88 static 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 105 static int 106 cmsg_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 116 static int 117 cmsg_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 127 static int 128 cmsg_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 161 static int 162 cmsg_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 196 static int 197 cmsg_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 237 static int 238 cmsg_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 283 static int 284 cmsg_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 332 static int 333 cmsg_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 381 static int 382 cmsg_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 450 static int 451 cmsg_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 518 int 519 cmsg_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 537 int 538 cmsg_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 561 static int 562 cmsg_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 573 static int 574 cmsg_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 597 static int 598 cmsg_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 619 int 620 cmsg_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