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