control_server.c revision 224144
1224006Shrs/*- 2224006Shrs * Copyright (C) 2011 Hiroki Sato <hrs@FreeBSD.org> 3224006Shrs * All rights reserved. 4224006Shrs * 5224006Shrs * Redistribution and use in source and binary forms, with or without 6224006Shrs * modification, are permitted provided that the following conditions 7224006Shrs * are met: 8224006Shrs * 1. Redistributions of source code must retain the above copyright 9224006Shrs * notice, this list of conditions and the following disclaimer. 10224006Shrs * 2. Redistributions in binary form must reproduce the above copyright 11224006Shrs * notice, this list of conditions and the following disclaimer in the 12224006Shrs * documentation and/or other materials provided with the distribution. 13224006Shrs * 14224006Shrs * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 15224006Shrs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16224006Shrs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17224006Shrs * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS 18224006Shrs * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19224006Shrs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20224006Shrs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 21224006Shrs * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22224006Shrs * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23224006Shrs * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24224006Shrs * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25224006Shrs * 26224006Shrs * $FreeBSD: head/usr.sbin/rtadvd/control_server.c 224144 2011-07-17 19:24:54Z hrs $ 27224006Shrs * 28224006Shrs */ 29224006Shrs 30224006Shrs#include <sys/queue.h> 31224006Shrs#include <sys/types.h> 32224006Shrs#include <sys/socket.h> 33224006Shrs#include <sys/stat.h> 34224006Shrs#include <sys/un.h> 35224006Shrs#include <sys/uio.h> 36224006Shrs#include <net/if.h> 37224006Shrs#include <net/if_dl.h> 38224006Shrs#include <netinet/in.h> 39224006Shrs#include <netinet/icmp6.h> 40224006Shrs#include <fcntl.h> 41224006Shrs#include <errno.h> 42224006Shrs#include <netdb.h> 43224006Shrs#include <unistd.h> 44224006Shrs#include <signal.h> 45224006Shrs#include <string.h> 46224006Shrs#include <stdarg.h> 47224006Shrs#include <stdio.h> 48224006Shrs#include <stdlib.h> 49224006Shrs#include <syslog.h> 50224006Shrs 51224006Shrs#include "pathnames.h" 52224006Shrs#include "rtadvd.h" 53224006Shrs#include "if.h" 54224006Shrs#include "control.h" 55224006Shrs#include "control_server.h" 56224006Shrs#include "timer.h" 57224006Shrs 58224144Shrsstatic char *do_reload_ifname; 59224144Shrsstatic int do_reload; 60224144Shrsstatic int do_shutdown; 61224006Shrs 62224144Shrsvoid set_do_reload(int sig __unused) { do_reload = 1; } 63224144Shrsvoid set_do_reload_ifname(char *ifname){ do_reload_ifname = ifname; } 64224144Shrsvoid set_do_shutdown(int sig __unused) { do_shutdown = 1; } 65224144Shrsvoid reset_do_reload(void) { do_reload = 0; do_reload_ifname = NULL; } 66224144Shrsvoid reset_do_shutdown(void) { do_shutdown = 0; } 67224144Shrsint is_do_reload(void) { return (do_reload); } 68224144Shrsint is_do_shutdown(void) { return (do_shutdown); } 69224144Shrschar *reload_ifname(void) { return (do_reload_ifname); } 70224006Shrs 71224006Shrs#define DEF_PL_HANDLER(key) { #key, cmsg_getprop_##key } 72224006Shrs 73224006Shrsstatic int cmsg_getprop_echo(struct ctrl_msg_pl *); 74224006Shrsstatic int cmsg_getprop_version(struct ctrl_msg_pl *); 75224006Shrsstatic int cmsg_getprop_ifilist(struct ctrl_msg_pl *); 76224006Shrsstatic int cmsg_getprop_ifi(struct ctrl_msg_pl *); 77224144Shrsstatic int cmsg_getprop_ifi_ra_timer(struct ctrl_msg_pl *); 78224006Shrsstatic int cmsg_getprop_rai(struct ctrl_msg_pl *); 79224006Shrsstatic int cmsg_getprop_pfx(struct ctrl_msg_pl *); 80224006Shrsstatic int cmsg_getprop_rdnss(struct ctrl_msg_pl *); 81224006Shrsstatic int cmsg_getprop_dnssl(struct ctrl_msg_pl *); 82224006Shrsstatic int cmsg_getprop_rti(struct ctrl_msg_pl *); 83224006Shrs 84224144Shrsstatic int cmsg_setprop_reload(struct ctrl_msg_pl *); 85224144Shrsstatic int cmsg_setprop_enable(struct ctrl_msg_pl *); 86224144Shrsstatic int cmsg_setprop_disable(struct ctrl_msg_pl *); 87224144Shrs 88224006Shrsstatic struct dispatch_table { 89224006Shrs const char *dt_comm; 90224006Shrs int (*dt_act)(struct ctrl_msg_pl *cp); 91224006Shrs} getprop_dtable[] = { 92224006Shrs { "", cmsg_getprop_echo }, 93224006Shrs DEF_PL_HANDLER(echo), 94224006Shrs DEF_PL_HANDLER(version), 95224006Shrs DEF_PL_HANDLER(ifilist), 96224006Shrs DEF_PL_HANDLER(ifi), 97224144Shrs DEF_PL_HANDLER(ifi_ra_timer), 98224006Shrs DEF_PL_HANDLER(rai), 99224006Shrs DEF_PL_HANDLER(rti), 100224006Shrs DEF_PL_HANDLER(pfx), 101224006Shrs DEF_PL_HANDLER(rdnss), 102224006Shrs DEF_PL_HANDLER(dnssl), 103224006Shrs}; 104224006Shrs 105224006Shrsstatic int 106224006Shrscmsg_getprop_echo(struct ctrl_msg_pl *cp) 107224006Shrs{ 108224006Shrs 109224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 110224006Shrs cp->cp_val = strdup(""); 111224006Shrs cp->cp_val_len = strlen(cp->cp_val) + 1; 112224006Shrs 113224006Shrs return (0); 114224006Shrs} 115224006Shrs 116224006Shrsstatic int 117224006Shrscmsg_getprop_version(struct ctrl_msg_pl *cp) 118224006Shrs{ 119224006Shrs 120224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 121224006Shrs cp->cp_val = strdup(CM_VERSION_STR); 122224006Shrs cp->cp_val_len = strlen(cp->cp_val) + 1; 123224006Shrs 124224006Shrs return (0); 125224006Shrs} 126224006Shrs 127224006Shrsstatic int 128224006Shrscmsg_getprop_ifilist(struct ctrl_msg_pl *cp) 129224006Shrs{ 130224006Shrs struct ifinfo *ifi; 131224006Shrs char *p; 132224006Shrs size_t len; 133224006Shrs 134224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 135224006Shrs 136224006Shrs len = 0; 137224006Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 138224006Shrs len += strlen(ifi->ifi_ifname) + 1; 139224006Shrs } 140224006Shrs 141224144Shrs syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 142224006Shrs 143224006Shrs p = malloc(len); 144224006Shrs if (p == NULL) 145224006Shrs exit(1); 146224006Shrs memset(p, 0, len); 147224006Shrs cp->cp_val = p; 148224006Shrs 149224006Shrs if (len > 0) 150224006Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 151224006Shrs syslog(LOG_DEBUG, "<%s> add ifname=%s(%d)", 152224006Shrs __func__, ifi->ifi_ifname, ifi->ifi_ifindex); 153224006Shrs strcpy(p, ifi->ifi_ifname); 154224006Shrs p += strlen(ifi->ifi_ifname) + 1; 155224006Shrs } 156224006Shrs cp->cp_val_len = p - cp->cp_val; 157224006Shrs 158224006Shrs return (0); 159224006Shrs} 160224006Shrs 161224006Shrsstatic int 162224006Shrscmsg_getprop_ifi(struct ctrl_msg_pl *cp) 163224006Shrs{ 164224006Shrs struct ifinfo *ifi; 165224006Shrs char *p; 166224006Shrs size_t len; 167224006Shrs 168224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 169224006Shrs 170224006Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 171224006Shrs if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 172224006Shrs break; 173224006Shrs } 174224006Shrs if (ifi == NULL) { 175224006Shrs syslog(LOG_ERR, "<%s> %s not found", __func__, 176224006Shrs cp->cp_ifname); 177224006Shrs return (1); 178224006Shrs } 179224006Shrs 180224006Shrs p = malloc(sizeof(*ifi)); 181224006Shrs if (p == NULL) 182224006Shrs exit(1); 183224006Shrs len = cmsg_str2bin(p, ifi, sizeof(*ifi)); 184224006Shrs 185224144Shrs syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 186224006Shrs 187224006Shrs if (len == 0) 188224006Shrs return (1); 189224006Shrs 190224006Shrs cp->cp_val = p; 191224006Shrs cp->cp_val_len = len; 192224006Shrs 193224006Shrs return (0); 194224006Shrs} 195224006Shrs 196224006Shrsstatic int 197224006Shrscmsg_getprop_rai(struct ctrl_msg_pl *cp) 198224006Shrs{ 199224006Shrs struct ifinfo *ifi; 200224006Shrs struct rainfo *rai; 201224006Shrs char *p; 202224006Shrs size_t len; 203224006Shrs 204224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 205224006Shrs 206224006Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 207224006Shrs if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 208224006Shrs break; 209224006Shrs } 210224006Shrs if (ifi == NULL) { 211224006Shrs syslog(LOG_ERR, "<%s> %s not found", __func__, 212224006Shrs cp->cp_ifname); 213224006Shrs return (1); 214224006Shrs } 215224006Shrs if ((rai = ifi->ifi_rainfo) == NULL) { 216224006Shrs syslog(LOG_ERR, "<%s> %s has no rainfo", __func__, 217224006Shrs cp->cp_ifname); 218224006Shrs return (1); 219224006Shrs } 220224006Shrs 221224006Shrs p = malloc(sizeof(*rai)); 222224006Shrs if (p == NULL) 223224006Shrs exit(1); 224224006Shrs len = cmsg_str2bin(p, rai, sizeof(*rai)); 225224006Shrs 226224144Shrs syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 227224006Shrs 228224006Shrs if (len == 0) 229224006Shrs return (1); 230224006Shrs 231224006Shrs cp->cp_val = p; 232224006Shrs cp->cp_val_len = len; 233224006Shrs 234224006Shrs return (0); 235224006Shrs} 236224006Shrs 237224006Shrsstatic int 238224144Shrscmsg_getprop_ifi_ra_timer(struct ctrl_msg_pl *cp) 239224006Shrs{ 240224006Shrs struct ifinfo *ifi; 241224006Shrs struct rainfo *rai; 242224006Shrs struct rtadvd_timer *rtimer; 243224006Shrs char *p; 244224006Shrs size_t len; 245224006Shrs 246224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 247224006Shrs 248224006Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 249224006Shrs if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 250224006Shrs break; 251224006Shrs } 252224006Shrs if (ifi == NULL) { 253224006Shrs syslog(LOG_ERR, "<%s> %s not found", __func__, 254224006Shrs cp->cp_ifname); 255224006Shrs return (1); 256224006Shrs } 257224006Shrs if ((rai = ifi->ifi_rainfo) == NULL) { 258224006Shrs syslog(LOG_ERR, "<%s> %s has no rainfo", __func__, 259224006Shrs cp->cp_ifname); 260224006Shrs return (1); 261224006Shrs } 262224144Shrs if ((rtimer = ifi->ifi_ra_timer) == NULL) { 263224144Shrs syslog(LOG_ERR, "<%s> %s has no ifi_ra_timer", __func__, 264224006Shrs cp->cp_ifname); 265224006Shrs return (1); 266224006Shrs } 267224006Shrs p = malloc(sizeof(*rtimer)); 268224006Shrs if (p == NULL) 269224006Shrs exit(1); 270224006Shrs len = cmsg_str2bin(p, rtimer, sizeof(*rtimer)); 271224006Shrs 272224144Shrs syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 273224006Shrs 274224006Shrs if (len == 0) 275224006Shrs return (1); 276224006Shrs 277224006Shrs cp->cp_val = p; 278224006Shrs cp->cp_val_len = len; 279224006Shrs 280224006Shrs return (0); 281224006Shrs} 282224006Shrs 283224006Shrsstatic int 284224006Shrscmsg_getprop_rti(struct ctrl_msg_pl *cp) 285224006Shrs{ 286224006Shrs struct ifinfo *ifi; 287224006Shrs struct rainfo *rai; 288224006Shrs struct rtinfo *rti; 289224006Shrs char *p; 290224006Shrs size_t len; 291224006Shrs 292224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 293224006Shrs 294224006Shrs len = 0; 295224006Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 296224006Shrs if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 297224006Shrs break; 298224006Shrs } 299224006Shrs if (ifi == NULL) { 300224006Shrs syslog(LOG_ERR, "<%s> %s not found", __func__, 301224006Shrs cp->cp_ifname); 302224006Shrs return (1); 303224006Shrs } 304224006Shrs if (ifi->ifi_rainfo == NULL) { 305224006Shrs syslog(LOG_ERR, "<%s> %s has no rainfo", __func__, 306224006Shrs cp->cp_ifname); 307224006Shrs return (1); 308224006Shrs } 309224006Shrs rai = ifi->ifi_rainfo; 310224006Shrs TAILQ_FOREACH(rti, &rai->rai_route, rti_next) { 311224006Shrs len += sizeof(*rti); 312224006Shrs } 313224006Shrs 314224144Shrs syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 315224006Shrs 316224006Shrs p = malloc(len); 317224006Shrs if (p == NULL) 318224006Shrs exit(1); 319224006Shrs memset(p, 0, len); 320224006Shrs cp->cp_val = p; 321224006Shrs 322224006Shrs if (len > 0) 323224006Shrs TAILQ_FOREACH(rti, &rai->rai_route, rti_next) { 324224006Shrs memcpy(p, rti, sizeof(*rti)); 325224006Shrs p += sizeof(*rti); 326224006Shrs } 327224006Shrs cp->cp_val_len = p - cp->cp_val; 328224006Shrs 329224006Shrs return (0); 330224006Shrs} 331224006Shrs 332224006Shrsstatic int 333224006Shrscmsg_getprop_pfx(struct ctrl_msg_pl *cp) 334224006Shrs{ 335224006Shrs struct ifinfo *ifi; 336224006Shrs struct rainfo *rai; 337224006Shrs struct prefix *pfx; 338224006Shrs char *p; 339224006Shrs size_t len; 340224006Shrs 341224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 342224006Shrs 343224006Shrs len = 0; 344224006Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 345224006Shrs if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 346224006Shrs break; 347224006Shrs } 348224006Shrs if (ifi == NULL) { 349224006Shrs syslog(LOG_ERR, "<%s> %s not found", __func__, 350224006Shrs cp->cp_ifname); 351224006Shrs return (1); 352224006Shrs } 353224006Shrs if (ifi->ifi_rainfo == NULL) { 354224006Shrs syslog(LOG_ERR, "<%s> %s has no rainfo", __func__, 355224006Shrs cp->cp_ifname); 356224006Shrs return (1); 357224006Shrs } 358224006Shrs rai = ifi->ifi_rainfo; 359224006Shrs TAILQ_FOREACH(pfx, &rai->rai_prefix, pfx_next) { 360224006Shrs len += sizeof(*pfx); 361224006Shrs } 362224006Shrs 363224144Shrs syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 364224006Shrs 365224006Shrs p = malloc(len); 366224006Shrs if (p == NULL) 367224006Shrs exit(1); 368224006Shrs memset(p, 0, len); 369224006Shrs cp->cp_val = p; 370224006Shrs 371224006Shrs if (len > 0) 372224006Shrs TAILQ_FOREACH(pfx, &rai->rai_prefix, pfx_next) { 373224006Shrs memcpy(p, pfx, sizeof(*pfx)); 374224006Shrs p += sizeof(*pfx); 375224006Shrs } 376224006Shrs cp->cp_val_len = p - cp->cp_val; 377224006Shrs 378224006Shrs return (0); 379224006Shrs} 380224006Shrs 381224006Shrsstatic int 382224006Shrscmsg_getprop_rdnss(struct ctrl_msg_pl *cp) 383224006Shrs{ 384224006Shrs struct ifinfo *ifi; 385224006Shrs struct rainfo *rai; 386224006Shrs struct rdnss *rdn; 387224006Shrs struct rdnss_addr *rda; 388224006Shrs char *p; 389224006Shrs size_t len; 390224144Shrs uint16_t *rdn_cnt; 391224144Shrs uint16_t *rda_cnt; 392224006Shrs 393224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 394224006Shrs 395224006Shrs len = 0; 396224006Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 397224006Shrs if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 398224006Shrs break; 399224006Shrs } 400224006Shrs if (ifi == NULL) { 401224006Shrs syslog(LOG_ERR, "<%s> %s not found", __func__, 402224006Shrs cp->cp_ifname); 403224006Shrs return (1); 404224006Shrs } 405224006Shrs if (ifi->ifi_rainfo == NULL) { 406224006Shrs syslog(LOG_ERR, "<%s> %s has no rainfo", __func__, 407224006Shrs cp->cp_ifname); 408224006Shrs return (1); 409224006Shrs } 410224006Shrs rai = ifi->ifi_rainfo; 411224006Shrs 412224006Shrs len = sizeof(*rdn_cnt); 413224006Shrs TAILQ_FOREACH(rdn, &rai->rai_rdnss, rd_next) { 414224006Shrs len += sizeof(*rdn); 415224006Shrs len += sizeof(*rda_cnt); 416224006Shrs TAILQ_FOREACH(rda, &rdn->rd_list, ra_next) { 417224006Shrs len += sizeof(*rda); 418224006Shrs } 419224006Shrs } 420224006Shrs 421224144Shrs syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 422224006Shrs 423224006Shrs p = malloc(len); 424224006Shrs if (p == NULL) 425224006Shrs exit(1); 426224006Shrs memset(p, 0, len); 427224006Shrs cp->cp_val = p; 428224006Shrs 429224144Shrs rdn_cnt = (uint16_t *)p; 430224006Shrs p += sizeof(*rdn_cnt); 431224006Shrs TAILQ_FOREACH(rdn, &rai->rai_rdnss, rd_next) { 432224006Shrs *rdn_cnt += 1; 433224006Shrs memcpy(p, rdn, sizeof(*rdn)); 434224006Shrs p += sizeof(*rdn); 435224006Shrs 436224144Shrs rda_cnt = (uint16_t *)p; 437224006Shrs p += sizeof(*rda_cnt); 438224006Shrs TAILQ_FOREACH(rda, &rdn->rd_list, ra_next) { 439224006Shrs *rda_cnt += 1; 440224006Shrs memcpy(p, rda, sizeof(*rda)); 441224006Shrs p += sizeof(*rda); 442224006Shrs } 443224006Shrs } 444224006Shrs syslog(LOG_DEBUG, "<%s> rdn_cnt = %d", __func__, *rdn_cnt); 445224006Shrs cp->cp_val_len = p - cp->cp_val; 446224006Shrs 447224006Shrs return (0); 448224006Shrs} 449224006Shrs 450224006Shrsstatic int 451224006Shrscmsg_getprop_dnssl(struct ctrl_msg_pl *cp) 452224006Shrs{ 453224006Shrs struct ifinfo *ifi; 454224006Shrs struct rainfo *rai; 455224006Shrs struct dnssl *dns; 456224006Shrs struct dnssl_addr *dna; 457224006Shrs char *p; 458224006Shrs size_t len; 459224144Shrs uint16_t *dns_cnt; 460224144Shrs uint16_t *dna_cnt; 461224006Shrs 462224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 463224006Shrs 464224006Shrs len = 0; 465224006Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 466224006Shrs if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 467224006Shrs break; 468224006Shrs } 469224006Shrs if (ifi == NULL) { 470224006Shrs syslog(LOG_ERR, "<%s> %s not found", __func__, 471224006Shrs cp->cp_ifname); 472224006Shrs return (1); 473224006Shrs } 474224006Shrs if (ifi->ifi_rainfo == NULL) { 475224006Shrs syslog(LOG_ERR, "<%s> %s has no rainfo", __func__, 476224006Shrs cp->cp_ifname); 477224006Shrs return (1); 478224006Shrs } 479224006Shrs rai = ifi->ifi_rainfo; 480224006Shrs 481224006Shrs len = sizeof(*dns_cnt); 482224006Shrs TAILQ_FOREACH(dns, &rai->rai_dnssl, dn_next) { 483224006Shrs len += sizeof(*dns); 484224006Shrs len += sizeof(*dna_cnt); 485224006Shrs TAILQ_FOREACH(dna, &dns->dn_list, da_next) { 486224006Shrs len += sizeof(*dna); 487224006Shrs } 488224006Shrs } 489224006Shrs 490224144Shrs syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 491224006Shrs 492224006Shrs p = malloc(len); 493224006Shrs if (p == NULL) 494224006Shrs exit(1); 495224006Shrs memset(p, 0, len); 496224006Shrs cp->cp_val = p; 497224006Shrs 498224144Shrs dns_cnt = (uint16_t *)cp->cp_val; 499224006Shrs p += sizeof(*dns_cnt); 500224006Shrs TAILQ_FOREACH(dns, &rai->rai_dnssl, dn_next) { 501224006Shrs (*dns_cnt)++; 502224006Shrs memcpy(p, dns, sizeof(*dns)); 503224006Shrs p += sizeof(*dns); 504224006Shrs 505224144Shrs dna_cnt = (uint16_t *)p; 506224006Shrs p += sizeof(*dna_cnt); 507224006Shrs TAILQ_FOREACH(dna, &dns->dn_list, da_next) { 508224006Shrs (*dna_cnt)++; 509224006Shrs memcpy(p, dna, sizeof(*dna)); 510224006Shrs p += sizeof(*dna); 511224006Shrs } 512224006Shrs } 513224006Shrs cp->cp_val_len = p - cp->cp_val; 514224006Shrs 515224006Shrs return (0); 516224006Shrs} 517224006Shrs 518224006Shrsint 519224006Shrscmsg_getprop(struct ctrl_msg_pl *cp) 520224006Shrs{ 521224006Shrs size_t i; 522224006Shrs 523224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 524224006Shrs 525224006Shrs if (cp == NULL) 526224006Shrs return (1); 527224006Shrs 528224006Shrs for (i = 0; 529224006Shrs i < sizeof(getprop_dtable) / sizeof(getprop_dtable[0]); 530224006Shrs i++) { 531224006Shrs if (strcmp(cp->cp_key, getprop_dtable[i].dt_comm) == 0) 532224006Shrs return (getprop_dtable[i].dt_act(cp)); 533224006Shrs } 534224006Shrs return (1); 535224006Shrs} 536224006Shrs 537224006Shrsint 538224006Shrscmsg_setprop(struct ctrl_msg_pl *cp) 539224006Shrs{ 540224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 541224006Shrs 542224006Shrs if (cp == NULL || cp->cp_key == NULL) 543224006Shrs return (1); 544224006Shrs 545224144Shrs if (strncmp(cp->cp_key, "reload", sizeof("reload")) == 0) 546224144Shrs cmsg_setprop_reload(cp); 547224144Shrs else if (strncmp(cp->cp_key, "shutdown", sizeof("shutdown")) == 0) 548224144Shrs set_do_shutdown(0); 549224144Shrs else if (strncmp(cp->cp_key, "enable", sizeof("enable")) == 0) 550224144Shrs cmsg_setprop_enable(cp); 551224144Shrs else if (strncmp(cp->cp_key, "disable", sizeof("disable")) == 0) 552224144Shrs cmsg_setprop_disable(cp); 553224006Shrs else if (strncmp(cp->cp_key, "echo", 8) == 0) 554224006Shrs ; /* do nothing */ 555224006Shrs else 556224006Shrs return (1); 557224006Shrs 558224006Shrs return (0); 559224006Shrs} 560224006Shrs 561224144Shrsstatic int 562224144Shrscmsg_setprop_reload(struct ctrl_msg_pl *cp) 563224144Shrs{ 564224144Shrs 565224144Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 566224144Shrs 567224144Shrs set_do_reload_ifname(cp->cp_ifname); 568224144Shrs set_do_reload(1); 569224144Shrs 570224144Shrs return (0); 571224144Shrs} 572224144Shrs 573224144Shrsstatic int 574224144Shrscmsg_setprop_enable(struct ctrl_msg_pl *cp) 575224144Shrs{ 576224144Shrs struct ifinfo *ifi; 577224144Shrs 578224144Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 579224144Shrs 580224144Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 581224144Shrs if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 582224144Shrs break; 583224144Shrs } 584224144Shrs if (ifi == NULL) { 585224144Shrs syslog(LOG_ERR, "<%s> %s not found", __func__, 586224144Shrs cp->cp_ifname); 587224144Shrs return (1); 588224144Shrs } 589224144Shrs 590224144Shrs ifi->ifi_persist = 1; 591224144Shrs set_do_reload_ifname(ifi->ifi_ifname); 592224144Shrs set_do_reload(0); 593224144Shrs 594224144Shrs return (0); 595224144Shrs} 596224144Shrs 597224144Shrsstatic int 598224144Shrscmsg_setprop_disable(struct ctrl_msg_pl *cp) 599224144Shrs{ 600224144Shrs struct ifinfo *ifi; 601224144Shrs 602224144Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 603224144Shrs 604224144Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 605224144Shrs if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 606224144Shrs break; 607224144Shrs } 608224144Shrs if (ifi == NULL) { 609224144Shrs syslog(LOG_ERR, "<%s> %s not found", __func__, 610224144Shrs cp->cp_ifname); 611224144Shrs return (1); 612224144Shrs } 613224144Shrs 614224144Shrs ifi->ifi_persist = 0; 615224144Shrs 616224144Shrs return (0); 617224144Shrs} 618224144Shrs 619224006Shrsint 620224006Shrscmsg_handler_server(int fd) 621224006Shrs{ 622224006Shrs int state; 623224006Shrs char *msg; 624224006Shrs struct ctrl_msg_hdr *cm; 625224006Shrs struct ctrl_msg_pl cp; 626224006Shrs char buf[CM_MSG_MAXLEN]; 627224006Shrs char pbuf[CM_MSG_MAXLEN]; 628224006Shrs int error; 629224006Shrs 630224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 631224006Shrs 632224006Shrs memset(buf, 0, sizeof(buf)); 633224006Shrs memset(pbuf, 0, sizeof(pbuf)); 634224006Shrs cm = (struct ctrl_msg_hdr *)buf; 635224006Shrs msg = (char *)buf + sizeof(*cm); 636224006Shrs 637224006Shrs state = CM_STATE_INIT; 638224006Shrs while (state != CM_STATE_EOM) { 639224006Shrs syslog(LOG_DEBUG, "<%s> state = %d", __func__, state); 640224006Shrs 641224006Shrs switch (state) { 642224006Shrs case CM_STATE_INIT: 643224006Shrs state = CM_STATE_MSG_RECV; 644224006Shrs break; 645224006Shrs case CM_STATE_MSG_DISPATCH: 646224006Shrs cm->cm_version = CM_VERSION; 647224006Shrs error = cmsg_send(fd, buf); 648224006Shrs if (error) 649224006Shrs syslog(LOG_WARNING, 650224006Shrs "<%s> cmsg_send()", __func__); 651224006Shrs state = CM_STATE_EOM; 652224006Shrs break; 653224006Shrs case CM_STATE_ACK_WAIT: 654224006Shrs error = cmsg_recv(fd, buf); 655224006Shrs if (error) { 656224006Shrs syslog(LOG_ERR, 657224006Shrs "<%s> cmsg_recv()", __func__); 658224006Shrs close(fd); 659224006Shrs return (-1); 660224006Shrs } 661224006Shrs 662224006Shrs switch (cm->cm_type) { 663224006Shrs case CM_TYPE_ACK: 664224006Shrs break; 665224006Shrs case CM_TYPE_ERR: 666224006Shrs syslog(LOG_DEBUG, 667224006Shrs "<%s> CM_TYPE_ERR", __func__); 668224006Shrs close(fd); 669224006Shrs return (-1); 670224006Shrs default: 671224006Shrs syslog(LOG_DEBUG, 672224006Shrs "<%s> unknown status", __func__); 673224006Shrs close(fd); 674224006Shrs return (-1); 675224006Shrs } 676224006Shrs state = CM_STATE_EOM; 677224006Shrs break; 678224006Shrs case CM_STATE_MSG_RECV: 679224006Shrs error = cmsg_recv(fd, buf); 680224006Shrs 681224006Shrs if (error) { 682224006Shrs syslog(LOG_ERR, 683224006Shrs "<%s> cmsg_recv()", __func__); 684224006Shrs close(fd); 685224006Shrs return (-1); 686224006Shrs } 687224006Shrs memset(&cp, 0, sizeof(cp)); 688224006Shrs 689224006Shrs syslog(LOG_DEBUG, 690224006Shrs "<%s> cm->cm_type = %d", __func__, cm->cm_type); 691224006Shrs syslog(LOG_DEBUG, 692224144Shrs "<%s> cm->cm_len = %zu", __func__, cm->cm_len); 693224006Shrs 694224006Shrs switch (cm->cm_type) { 695224006Shrs case CM_TYPE_EOM: 696224006Shrs state = CM_STATE_EOM; 697224006Shrs case CM_TYPE_NUL: 698224006Shrs cm->cm_type = CM_TYPE_ACK; 699224006Shrs cm->cm_len = sizeof(*cm); 700224006Shrs break; 701224006Shrs case CM_TYPE_REQ_GET_PROP: 702224006Shrs cmsg_bin2pl(msg, &cp); 703224006Shrs error = cmsg_getprop(&cp); 704224006Shrs if (error) { 705224006Shrs cm->cm_type = CM_TYPE_ERR; 706224006Shrs cm->cm_len = sizeof(*cm); 707224006Shrs } else { 708224006Shrs cm->cm_type = CM_TYPE_ACK; 709224006Shrs cm->cm_len = sizeof(*cm); 710224006Shrs cm->cm_len += cmsg_pl2bin(msg, &cp); 711224006Shrs } 712224144Shrs if (cp.cp_val != NULL) 713224144Shrs free(cp.cp_val); 714224006Shrs break; 715224006Shrs case CM_TYPE_REQ_SET_PROP: 716224006Shrs cmsg_bin2pl(msg, &cp); 717224006Shrs error = cmsg_setprop(&cp); 718224006Shrs if (error) { 719224006Shrs cm->cm_type = CM_TYPE_ERR; 720224006Shrs cm->cm_len = sizeof(*cm); 721224006Shrs } else { 722224006Shrs cm->cm_type = CM_TYPE_ACK; 723224006Shrs cm->cm_len = sizeof(*cm); 724224006Shrs } 725224006Shrs break; 726224006Shrs default: 727224006Shrs cm->cm_type = CM_TYPE_ERR; 728224006Shrs cm->cm_len = sizeof(*cm); 729224006Shrs } 730224006Shrs 731224006Shrs switch (cm->cm_type) { 732224006Shrs case CM_TYPE_ERR: 733224006Shrs case CM_TYPE_ACK: 734224006Shrs state = CM_STATE_MSG_DISPATCH; 735224006Shrs break; 736224006Shrs } 737224006Shrs } 738224006Shrs } 739224006Shrs syslog(LOG_DEBUG, "<%s> leave", __func__); 740224006Shrs 741224006Shrs return (0); 742224006Shrs} 743