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 } 755