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_pref64(struct ctrl_msg_pl *); 84 static int cm_getprop_rti(struct ctrl_msg_pl *); 85 86 static int cm_setprop_reload(struct ctrl_msg_pl *); 87 static int cm_setprop_enable(struct ctrl_msg_pl *); 88 static int cm_setprop_disable(struct ctrl_msg_pl *); 89 90 static struct dispatch_table { 91 const char *dt_comm; 92 int (*dt_act)(struct ctrl_msg_pl *cp); 93 } getprop_dtable[] = { 94 { "", cm_getprop_echo }, 95 DEF_PL_HANDLER(echo), 96 DEF_PL_HANDLER(version), 97 DEF_PL_HANDLER(ifilist), 98 DEF_PL_HANDLER(ifi), 99 DEF_PL_HANDLER(ifi_ra_timer), 100 DEF_PL_HANDLER(rai), 101 DEF_PL_HANDLER(rti), 102 DEF_PL_HANDLER(pfx), 103 DEF_PL_HANDLER(rdnss), 104 DEF_PL_HANDLER(dnssl), 105 DEF_PL_HANDLER(pref64), 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 static int 522 cm_getprop_pref64(struct ctrl_msg_pl *cp) 523 { 524 struct ifinfo *ifi; 525 struct rainfo *rai; 526 struct pref64 *prf64; 527 char *p; 528 size_t len; 529 uint16_t *prf64_cnt; 530 531 syslog(LOG_DEBUG, "<%s> enter", __func__); 532 533 len = 0; 534 TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 535 if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 536 break; 537 } 538 if (ifi == NULL) { 539 syslog(LOG_ERR, "<%s> %s not found", __func__, 540 cp->cp_ifname); 541 return (1); 542 } 543 if (ifi->ifi_rainfo == NULL) { 544 syslog(LOG_ERR, "<%s> %s has no rainfo", __func__, 545 cp->cp_ifname); 546 return (1); 547 } 548 rai = ifi->ifi_rainfo; 549 550 len = sizeof(*prf64_cnt); 551 TAILQ_FOREACH(prf64, &rai->rai_pref64, p64_next) 552 len += sizeof(*prf64); 553 554 syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 555 556 p = malloc(len); 557 if (p == NULL) 558 exit(1); 559 memset(p, 0, len); 560 cp->cp_val = p; 561 562 prf64_cnt = (uint16_t *)cp->cp_val; 563 p += sizeof(*prf64_cnt); 564 TAILQ_FOREACH(prf64, &rai->rai_pref64, p64_next) { 565 (*prf64_cnt)++; 566 memcpy(p, prf64, sizeof(*prf64)); 567 p += sizeof(*prf64); 568 } 569 cp->cp_val_len = p - cp->cp_val; 570 571 return (0); 572 } 573 574 575 int 576 cm_getprop(struct ctrl_msg_pl *cp) 577 { 578 size_t i; 579 580 syslog(LOG_DEBUG, "<%s> enter", __func__); 581 582 if (cp == NULL) 583 return (1); 584 585 for (i = 0; 586 i < nitems(getprop_dtable); 587 i++) { 588 if (strcmp(cp->cp_key, getprop_dtable[i].dt_comm) == 0) 589 return (getprop_dtable[i].dt_act(cp)); 590 } 591 return (1); 592 } 593 594 int 595 cm_setprop(struct ctrl_msg_pl *cp) 596 { 597 syslog(LOG_DEBUG, "<%s> enter", __func__); 598 599 if (cp == NULL || cp->cp_key == NULL) 600 return (1); 601 602 if (strncmp(cp->cp_key, "reload", sizeof("reload")) == 0) 603 cm_setprop_reload(cp); 604 else if (strncmp(cp->cp_key, "shutdown", sizeof("shutdown")) == 0) 605 set_do_shutdown(0); 606 else if (strncmp(cp->cp_key, "enable", sizeof("enable")) == 0) 607 cm_setprop_enable(cp); 608 else if (strncmp(cp->cp_key, "disable", sizeof("disable")) == 0) 609 cm_setprop_disable(cp); 610 else if (strncmp(cp->cp_key, "echo", 8) == 0) 611 ; /* do nothing */ 612 else 613 return (1); 614 615 return (0); 616 } 617 618 static int 619 cm_setprop_reload(struct ctrl_msg_pl *cp) 620 { 621 622 syslog(LOG_DEBUG, "<%s> enter", __func__); 623 624 set_do_reload_ifname(cp->cp_ifname); 625 set_do_reload(1); 626 627 return (0); 628 } 629 630 static int 631 cm_setprop_enable(struct ctrl_msg_pl *cp) 632 { 633 struct ifinfo *ifi; 634 635 syslog(LOG_DEBUG, "<%s> enter", __func__); 636 637 TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 638 if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 639 break; 640 } 641 if (ifi == NULL) { 642 syslog(LOG_ERR, "<%s> %s not found", __func__, 643 cp->cp_ifname); 644 return (1); 645 } 646 647 ifi->ifi_persist = 1; 648 set_do_reload_ifname(ifi->ifi_ifname); 649 set_do_reload(0); 650 651 return (0); 652 } 653 654 static int 655 cm_setprop_disable(struct ctrl_msg_pl *cp) 656 { 657 struct ifinfo *ifi; 658 659 syslog(LOG_DEBUG, "<%s> enter", __func__); 660 661 TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 662 if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 663 break; 664 } 665 if (ifi == NULL) { 666 syslog(LOG_ERR, "<%s> %s not found", __func__, 667 cp->cp_ifname); 668 return (1); 669 } 670 671 if (ifi->ifi_persist == 1) { 672 ifi->ifi_persist = 0; 673 rm_ifinfo(ifi); 674 675 /* MC leaving needed here */ 676 sock_mc_leave(&sock, ifi->ifi_ifindex); 677 678 set_do_reload_ifname(ifi->ifi_ifname); 679 set_do_reload(0); 680 } 681 682 return (0); 683 } 684 685 int 686 cm_handler_server(int fd) 687 { 688 int state; 689 char *msg; 690 struct ctrl_msg_hdr *cm; 691 struct ctrl_msg_pl cp; 692 char buf[CM_MSG_MAXLEN]; 693 char pbuf[CM_MSG_MAXLEN]; 694 int error; 695 696 syslog(LOG_DEBUG, "<%s> enter", __func__); 697 698 memset(buf, 0, sizeof(buf)); 699 memset(pbuf, 0, sizeof(pbuf)); 700 cm = (struct ctrl_msg_hdr *)buf; 701 msg = (char *)buf + sizeof(*cm); 702 703 state = CM_STATE_INIT; 704 while (state != CM_STATE_EOM) { 705 syslog(LOG_DEBUG, "<%s> state = %d", __func__, state); 706 707 switch (state) { 708 case CM_STATE_INIT: 709 state = CM_STATE_MSG_RECV; 710 break; 711 case CM_STATE_MSG_DISPATCH: 712 cm->cm_version = CM_VERSION; 713 error = cm_send(fd, buf); 714 if (error) 715 syslog(LOG_WARNING, 716 "<%s> cm_send()", __func__); 717 state = CM_STATE_EOM; 718 break; 719 case CM_STATE_ACK_WAIT: 720 error = cm_recv(fd, buf); 721 if (error) { 722 syslog(LOG_ERR, 723 "<%s> cm_recv()", __func__); 724 close(fd); 725 return (-1); 726 } 727 728 switch (cm->cm_type) { 729 case CM_TYPE_ACK: 730 break; 731 case CM_TYPE_ERR: 732 syslog(LOG_DEBUG, 733 "<%s> CM_TYPE_ERR", __func__); 734 close(fd); 735 return (-1); 736 default: 737 syslog(LOG_DEBUG, 738 "<%s> unknown status", __func__); 739 close(fd); 740 return (-1); 741 } 742 state = CM_STATE_EOM; 743 break; 744 case CM_STATE_MSG_RECV: 745 error = cm_recv(fd, buf); 746 747 if (error) { 748 syslog(LOG_ERR, 749 "<%s> cm_recv()", __func__); 750 close(fd); 751 return (-1); 752 } 753 memset(&cp, 0, sizeof(cp)); 754 755 syslog(LOG_DEBUG, 756 "<%s> cm->cm_type = %d", __func__, cm->cm_type); 757 syslog(LOG_DEBUG, 758 "<%s> cm->cm_len = %zu", __func__, cm->cm_len); 759 760 switch (cm->cm_type) { 761 case CM_TYPE_EOM: 762 state = CM_STATE_EOM; 763 case CM_TYPE_NUL: 764 cm->cm_type = CM_TYPE_ACK; 765 cm->cm_len = sizeof(*cm); 766 break; 767 case CM_TYPE_REQ_GET_PROP: 768 cm_bin2pl(msg, &cp); 769 error = cm_getprop(&cp); 770 if (error) { 771 cm->cm_type = CM_TYPE_ERR; 772 cm->cm_len = sizeof(*cm); 773 } else { 774 cm->cm_type = CM_TYPE_ACK; 775 cm->cm_len = sizeof(*cm); 776 cm->cm_len += cm_pl2bin(msg, &cp); 777 } 778 if (cp.cp_val != NULL) 779 free(cp.cp_val); 780 break; 781 case CM_TYPE_REQ_SET_PROP: 782 cm_bin2pl(msg, &cp); 783 error = cm_setprop(&cp); 784 if (error) { 785 cm->cm_type = CM_TYPE_ERR; 786 cm->cm_len = sizeof(*cm); 787 } else { 788 cm->cm_type = CM_TYPE_ACK; 789 cm->cm_len = sizeof(*cm); 790 } 791 break; 792 default: 793 cm->cm_type = CM_TYPE_ERR; 794 cm->cm_len = sizeof(*cm); 795 } 796 797 switch (cm->cm_type) { 798 case CM_TYPE_ERR: 799 case CM_TYPE_ACK: 800 state = CM_STATE_MSG_DISPATCH; 801 break; 802 } 803 } 804 } 805 syslog(LOG_DEBUG, "<%s> leave", __func__); 806 807 return (0); 808 } 809