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$ 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" 54225519Shrs#include "config.h" 55224006Shrs#include "control.h" 56224006Shrs#include "control_server.h" 57224006Shrs#include "timer.h" 58224006Shrs 59224144Shrsstatic char *do_reload_ifname; 60224144Shrsstatic int do_reload; 61224144Shrsstatic int do_shutdown; 62224006Shrs 63224144Shrsvoid set_do_reload(int sig __unused) { do_reload = 1; } 64224144Shrsvoid set_do_reload_ifname(char *ifname){ do_reload_ifname = ifname; } 65224144Shrsvoid set_do_shutdown(int sig __unused) { do_shutdown = 1; } 66224144Shrsvoid reset_do_reload(void) { do_reload = 0; do_reload_ifname = NULL; } 67224144Shrsvoid reset_do_shutdown(void) { do_shutdown = 0; } 68224144Shrsint is_do_reload(void) { return (do_reload); } 69224144Shrsint is_do_shutdown(void) { return (do_shutdown); } 70224144Shrschar *reload_ifname(void) { return (do_reload_ifname); } 71224006Shrs 72225519Shrs#define DEF_PL_HANDLER(key) { #key, cm_getprop_##key } 73224006Shrs 74225519Shrsstatic int cm_getprop_echo(struct ctrl_msg_pl *); 75225519Shrsstatic int cm_getprop_version(struct ctrl_msg_pl *); 76225519Shrsstatic int cm_getprop_ifilist(struct ctrl_msg_pl *); 77225519Shrsstatic int cm_getprop_ifi(struct ctrl_msg_pl *); 78225519Shrsstatic int cm_getprop_ifi_ra_timer(struct ctrl_msg_pl *); 79225519Shrsstatic int cm_getprop_rai(struct ctrl_msg_pl *); 80225519Shrsstatic int cm_getprop_pfx(struct ctrl_msg_pl *); 81225519Shrsstatic int cm_getprop_rdnss(struct ctrl_msg_pl *); 82225519Shrsstatic int cm_getprop_dnssl(struct ctrl_msg_pl *); 83225519Shrsstatic int cm_getprop_rti(struct ctrl_msg_pl *); 84224006Shrs 85225519Shrsstatic int cm_setprop_reload(struct ctrl_msg_pl *); 86225519Shrsstatic int cm_setprop_enable(struct ctrl_msg_pl *); 87225519Shrsstatic int cm_setprop_disable(struct ctrl_msg_pl *); 88224144Shrs 89224006Shrsstatic struct dispatch_table { 90224006Shrs const char *dt_comm; 91224006Shrs int (*dt_act)(struct ctrl_msg_pl *cp); 92224006Shrs} getprop_dtable[] = { 93225519Shrs { "", cm_getprop_echo }, 94224006Shrs DEF_PL_HANDLER(echo), 95224006Shrs DEF_PL_HANDLER(version), 96224006Shrs DEF_PL_HANDLER(ifilist), 97224006Shrs DEF_PL_HANDLER(ifi), 98224144Shrs DEF_PL_HANDLER(ifi_ra_timer), 99224006Shrs DEF_PL_HANDLER(rai), 100224006Shrs DEF_PL_HANDLER(rti), 101224006Shrs DEF_PL_HANDLER(pfx), 102224006Shrs DEF_PL_HANDLER(rdnss), 103224006Shrs DEF_PL_HANDLER(dnssl), 104224006Shrs}; 105224006Shrs 106224006Shrsstatic int 107225519Shrscm_getprop_echo(struct ctrl_msg_pl *cp) 108224006Shrs{ 109224006Shrs 110224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 111224006Shrs cp->cp_val = strdup(""); 112224006Shrs cp->cp_val_len = strlen(cp->cp_val) + 1; 113224006Shrs 114224006Shrs return (0); 115224006Shrs} 116224006Shrs 117224006Shrsstatic int 118225519Shrscm_getprop_version(struct ctrl_msg_pl *cp) 119224006Shrs{ 120224006Shrs 121224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 122224006Shrs cp->cp_val = strdup(CM_VERSION_STR); 123224006Shrs cp->cp_val_len = strlen(cp->cp_val) + 1; 124224006Shrs 125224006Shrs return (0); 126224006Shrs} 127224006Shrs 128224006Shrsstatic int 129225519Shrscm_getprop_ifilist(struct ctrl_msg_pl *cp) 130224006Shrs{ 131224006Shrs struct ifinfo *ifi; 132224006Shrs char *p; 133224006Shrs size_t len; 134224006Shrs 135224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 136224006Shrs 137224006Shrs len = 0; 138224006Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 139224006Shrs len += strlen(ifi->ifi_ifname) + 1; 140224006Shrs } 141224006Shrs 142224144Shrs syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 143224006Shrs 144224006Shrs p = malloc(len); 145224006Shrs if (p == NULL) 146224006Shrs exit(1); 147224006Shrs memset(p, 0, len); 148224006Shrs cp->cp_val = p; 149224006Shrs 150224006Shrs if (len > 0) 151224006Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 152224006Shrs syslog(LOG_DEBUG, "<%s> add ifname=%s(%d)", 153224006Shrs __func__, ifi->ifi_ifname, ifi->ifi_ifindex); 154224006Shrs strcpy(p, ifi->ifi_ifname); 155224006Shrs p += strlen(ifi->ifi_ifname) + 1; 156224006Shrs } 157224006Shrs cp->cp_val_len = p - cp->cp_val; 158224006Shrs 159224006Shrs return (0); 160224006Shrs} 161224006Shrs 162224006Shrsstatic int 163225519Shrscm_getprop_ifi(struct ctrl_msg_pl *cp) 164224006Shrs{ 165224006Shrs struct ifinfo *ifi; 166224006Shrs char *p; 167224006Shrs size_t len; 168224006Shrs 169224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 170224006Shrs 171224006Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 172224006Shrs if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 173224006Shrs break; 174224006Shrs } 175224006Shrs if (ifi == NULL) { 176224006Shrs syslog(LOG_ERR, "<%s> %s not found", __func__, 177224006Shrs cp->cp_ifname); 178224006Shrs return (1); 179224006Shrs } 180224006Shrs 181224006Shrs p = malloc(sizeof(*ifi)); 182224006Shrs if (p == NULL) 183224006Shrs exit(1); 184225519Shrs len = cm_str2bin(p, ifi, sizeof(*ifi)); 185224006Shrs 186224144Shrs syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 187224006Shrs 188224006Shrs if (len == 0) 189224006Shrs return (1); 190224006Shrs 191224006Shrs cp->cp_val = p; 192224006Shrs cp->cp_val_len = len; 193224006Shrs 194224006Shrs return (0); 195224006Shrs} 196224006Shrs 197224006Shrsstatic int 198225519Shrscm_getprop_rai(struct ctrl_msg_pl *cp) 199224006Shrs{ 200224006Shrs struct ifinfo *ifi; 201224006Shrs struct rainfo *rai; 202224006Shrs char *p; 203224006Shrs size_t len; 204224006Shrs 205224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 206224006Shrs 207224006Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 208224006Shrs if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 209224006Shrs break; 210224006Shrs } 211224006Shrs if (ifi == NULL) { 212224006Shrs syslog(LOG_ERR, "<%s> %s not found", __func__, 213224006Shrs cp->cp_ifname); 214224006Shrs return (1); 215224006Shrs } 216224006Shrs if ((rai = ifi->ifi_rainfo) == NULL) { 217224006Shrs syslog(LOG_ERR, "<%s> %s has no rainfo", __func__, 218224006Shrs cp->cp_ifname); 219224006Shrs return (1); 220224006Shrs } 221224006Shrs 222224006Shrs p = malloc(sizeof(*rai)); 223224006Shrs if (p == NULL) 224224006Shrs exit(1); 225225519Shrs len = cm_str2bin(p, rai, sizeof(*rai)); 226224006Shrs 227224144Shrs syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 228224006Shrs 229224006Shrs if (len == 0) 230224006Shrs return (1); 231224006Shrs 232224006Shrs cp->cp_val = p; 233224006Shrs cp->cp_val_len = len; 234224006Shrs 235224006Shrs return (0); 236224006Shrs} 237224006Shrs 238224006Shrsstatic int 239225519Shrscm_getprop_ifi_ra_timer(struct ctrl_msg_pl *cp) 240224006Shrs{ 241224006Shrs struct ifinfo *ifi; 242224006Shrs struct rainfo *rai; 243224006Shrs struct rtadvd_timer *rtimer; 244224006Shrs char *p; 245224006Shrs size_t len; 246224006Shrs 247224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 248224006Shrs 249224006Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 250224006Shrs if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 251224006Shrs break; 252224006Shrs } 253224006Shrs if (ifi == NULL) { 254224006Shrs syslog(LOG_ERR, "<%s> %s not found", __func__, 255224006Shrs cp->cp_ifname); 256224006Shrs return (1); 257224006Shrs } 258224006Shrs if ((rai = ifi->ifi_rainfo) == NULL) { 259224006Shrs syslog(LOG_ERR, "<%s> %s has no rainfo", __func__, 260224006Shrs cp->cp_ifname); 261224006Shrs return (1); 262224006Shrs } 263224144Shrs if ((rtimer = ifi->ifi_ra_timer) == NULL) { 264224144Shrs syslog(LOG_ERR, "<%s> %s has no ifi_ra_timer", __func__, 265224006Shrs cp->cp_ifname); 266224006Shrs return (1); 267224006Shrs } 268224006Shrs p = malloc(sizeof(*rtimer)); 269224006Shrs if (p == NULL) 270224006Shrs exit(1); 271225519Shrs len = cm_str2bin(p, rtimer, sizeof(*rtimer)); 272224006Shrs 273224144Shrs syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 274224006Shrs 275224006Shrs if (len == 0) 276224006Shrs return (1); 277224006Shrs 278224006Shrs cp->cp_val = p; 279224006Shrs cp->cp_val_len = len; 280224006Shrs 281224006Shrs return (0); 282224006Shrs} 283224006Shrs 284224006Shrsstatic int 285225519Shrscm_getprop_rti(struct ctrl_msg_pl *cp) 286224006Shrs{ 287224006Shrs struct ifinfo *ifi; 288224006Shrs struct rainfo *rai; 289224006Shrs struct rtinfo *rti; 290224006Shrs char *p; 291224006Shrs size_t len; 292224006Shrs 293224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 294224006Shrs 295224006Shrs len = 0; 296224006Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 297224006Shrs if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 298224006Shrs break; 299224006Shrs } 300224006Shrs if (ifi == NULL) { 301224006Shrs syslog(LOG_ERR, "<%s> %s not found", __func__, 302224006Shrs cp->cp_ifname); 303224006Shrs return (1); 304224006Shrs } 305224006Shrs if (ifi->ifi_rainfo == NULL) { 306224006Shrs syslog(LOG_ERR, "<%s> %s has no rainfo", __func__, 307224006Shrs cp->cp_ifname); 308224006Shrs return (1); 309224006Shrs } 310224006Shrs rai = ifi->ifi_rainfo; 311224006Shrs TAILQ_FOREACH(rti, &rai->rai_route, rti_next) { 312224006Shrs len += sizeof(*rti); 313224006Shrs } 314224006Shrs 315224144Shrs syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 316224006Shrs 317224006Shrs p = malloc(len); 318224006Shrs if (p == NULL) 319224006Shrs exit(1); 320224006Shrs memset(p, 0, len); 321224006Shrs cp->cp_val = p; 322224006Shrs 323224006Shrs if (len > 0) 324224006Shrs TAILQ_FOREACH(rti, &rai->rai_route, rti_next) { 325224006Shrs memcpy(p, rti, sizeof(*rti)); 326224006Shrs p += sizeof(*rti); 327224006Shrs } 328224006Shrs cp->cp_val_len = p - cp->cp_val; 329224006Shrs 330224006Shrs return (0); 331224006Shrs} 332224006Shrs 333224006Shrsstatic int 334225519Shrscm_getprop_pfx(struct ctrl_msg_pl *cp) 335224006Shrs{ 336224006Shrs struct ifinfo *ifi; 337224006Shrs struct rainfo *rai; 338224006Shrs struct prefix *pfx; 339224006Shrs char *p; 340224006Shrs size_t len; 341224006Shrs 342224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 343224006Shrs 344224006Shrs len = 0; 345224006Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 346224006Shrs if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 347224006Shrs break; 348224006Shrs } 349224006Shrs if (ifi == NULL) { 350224006Shrs syslog(LOG_ERR, "<%s> %s not found", __func__, 351224006Shrs cp->cp_ifname); 352224006Shrs return (1); 353224006Shrs } 354224006Shrs if (ifi->ifi_rainfo == NULL) { 355224006Shrs syslog(LOG_ERR, "<%s> %s has no rainfo", __func__, 356224006Shrs cp->cp_ifname); 357224006Shrs return (1); 358224006Shrs } 359224006Shrs rai = ifi->ifi_rainfo; 360224006Shrs TAILQ_FOREACH(pfx, &rai->rai_prefix, pfx_next) { 361224006Shrs len += sizeof(*pfx); 362224006Shrs } 363224006Shrs 364224144Shrs syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 365224006Shrs 366224006Shrs p = malloc(len); 367224006Shrs if (p == NULL) 368224006Shrs exit(1); 369224006Shrs memset(p, 0, len); 370224006Shrs cp->cp_val = p; 371224006Shrs 372224006Shrs if (len > 0) 373224006Shrs TAILQ_FOREACH(pfx, &rai->rai_prefix, pfx_next) { 374224006Shrs memcpy(p, pfx, sizeof(*pfx)); 375224006Shrs p += sizeof(*pfx); 376224006Shrs } 377224006Shrs cp->cp_val_len = p - cp->cp_val; 378224006Shrs 379224006Shrs return (0); 380224006Shrs} 381224006Shrs 382224006Shrsstatic int 383225519Shrscm_getprop_rdnss(struct ctrl_msg_pl *cp) 384224006Shrs{ 385224006Shrs struct ifinfo *ifi; 386224006Shrs struct rainfo *rai; 387224006Shrs struct rdnss *rdn; 388224006Shrs struct rdnss_addr *rda; 389224006Shrs char *p; 390224006Shrs size_t len; 391224144Shrs uint16_t *rdn_cnt; 392224144Shrs uint16_t *rda_cnt; 393224006Shrs 394224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 395224006Shrs 396224006Shrs len = 0; 397224006Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 398224006Shrs if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 399224006Shrs break; 400224006Shrs } 401224006Shrs if (ifi == NULL) { 402224006Shrs syslog(LOG_ERR, "<%s> %s not found", __func__, 403224006Shrs cp->cp_ifname); 404224006Shrs return (1); 405224006Shrs } 406224006Shrs if (ifi->ifi_rainfo == NULL) { 407224006Shrs syslog(LOG_ERR, "<%s> %s has no rainfo", __func__, 408224006Shrs cp->cp_ifname); 409224006Shrs return (1); 410224006Shrs } 411224006Shrs rai = ifi->ifi_rainfo; 412224006Shrs 413224006Shrs len = sizeof(*rdn_cnt); 414224006Shrs TAILQ_FOREACH(rdn, &rai->rai_rdnss, rd_next) { 415224006Shrs len += sizeof(*rdn); 416224006Shrs len += sizeof(*rda_cnt); 417224006Shrs TAILQ_FOREACH(rda, &rdn->rd_list, ra_next) { 418224006Shrs len += sizeof(*rda); 419224006Shrs } 420224006Shrs } 421224006Shrs 422224144Shrs syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 423224006Shrs 424224006Shrs p = malloc(len); 425224006Shrs if (p == NULL) 426224006Shrs exit(1); 427224006Shrs memset(p, 0, len); 428224006Shrs cp->cp_val = p; 429224006Shrs 430224144Shrs rdn_cnt = (uint16_t *)p; 431224006Shrs p += sizeof(*rdn_cnt); 432224006Shrs TAILQ_FOREACH(rdn, &rai->rai_rdnss, rd_next) { 433224006Shrs *rdn_cnt += 1; 434224006Shrs memcpy(p, rdn, sizeof(*rdn)); 435224006Shrs p += sizeof(*rdn); 436224006Shrs 437224144Shrs rda_cnt = (uint16_t *)p; 438224006Shrs p += sizeof(*rda_cnt); 439224006Shrs TAILQ_FOREACH(rda, &rdn->rd_list, ra_next) { 440224006Shrs *rda_cnt += 1; 441224006Shrs memcpy(p, rda, sizeof(*rda)); 442224006Shrs p += sizeof(*rda); 443224006Shrs } 444224006Shrs } 445224006Shrs syslog(LOG_DEBUG, "<%s> rdn_cnt = %d", __func__, *rdn_cnt); 446224006Shrs cp->cp_val_len = p - cp->cp_val; 447224006Shrs 448224006Shrs return (0); 449224006Shrs} 450224006Shrs 451224006Shrsstatic int 452225519Shrscm_getprop_dnssl(struct ctrl_msg_pl *cp) 453224006Shrs{ 454224006Shrs struct ifinfo *ifi; 455224006Shrs struct rainfo *rai; 456224006Shrs struct dnssl *dns; 457224006Shrs struct dnssl_addr *dna; 458224006Shrs char *p; 459224006Shrs size_t len; 460224144Shrs uint16_t *dns_cnt; 461224144Shrs uint16_t *dna_cnt; 462224006Shrs 463224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 464224006Shrs 465224006Shrs len = 0; 466224006Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 467224006Shrs if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 468224006Shrs break; 469224006Shrs } 470224006Shrs if (ifi == NULL) { 471224006Shrs syslog(LOG_ERR, "<%s> %s not found", __func__, 472224006Shrs cp->cp_ifname); 473224006Shrs return (1); 474224006Shrs } 475224006Shrs if (ifi->ifi_rainfo == NULL) { 476224006Shrs syslog(LOG_ERR, "<%s> %s has no rainfo", __func__, 477224006Shrs cp->cp_ifname); 478224006Shrs return (1); 479224006Shrs } 480224006Shrs rai = ifi->ifi_rainfo; 481224006Shrs 482224006Shrs len = sizeof(*dns_cnt); 483224006Shrs TAILQ_FOREACH(dns, &rai->rai_dnssl, dn_next) { 484224006Shrs len += sizeof(*dns); 485224006Shrs len += sizeof(*dna_cnt); 486224006Shrs TAILQ_FOREACH(dna, &dns->dn_list, da_next) { 487224006Shrs len += sizeof(*dna); 488224006Shrs } 489224006Shrs } 490224006Shrs 491224144Shrs syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 492224006Shrs 493224006Shrs p = malloc(len); 494224006Shrs if (p == NULL) 495224006Shrs exit(1); 496224006Shrs memset(p, 0, len); 497224006Shrs cp->cp_val = p; 498224006Shrs 499224144Shrs dns_cnt = (uint16_t *)cp->cp_val; 500224006Shrs p += sizeof(*dns_cnt); 501224006Shrs TAILQ_FOREACH(dns, &rai->rai_dnssl, dn_next) { 502224006Shrs (*dns_cnt)++; 503224006Shrs memcpy(p, dns, sizeof(*dns)); 504224006Shrs p += sizeof(*dns); 505224006Shrs 506224144Shrs dna_cnt = (uint16_t *)p; 507224006Shrs p += sizeof(*dna_cnt); 508224006Shrs TAILQ_FOREACH(dna, &dns->dn_list, da_next) { 509224006Shrs (*dna_cnt)++; 510224006Shrs memcpy(p, dna, sizeof(*dna)); 511224006Shrs p += sizeof(*dna); 512224006Shrs } 513224006Shrs } 514224006Shrs cp->cp_val_len = p - cp->cp_val; 515224006Shrs 516224006Shrs return (0); 517224006Shrs} 518224006Shrs 519224006Shrsint 520225519Shrscm_getprop(struct ctrl_msg_pl *cp) 521224006Shrs{ 522224006Shrs size_t i; 523224006Shrs 524224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 525224006Shrs 526224006Shrs if (cp == NULL) 527224006Shrs return (1); 528224006Shrs 529224006Shrs for (i = 0; 530224006Shrs i < sizeof(getprop_dtable) / sizeof(getprop_dtable[0]); 531224006Shrs i++) { 532224006Shrs if (strcmp(cp->cp_key, getprop_dtable[i].dt_comm) == 0) 533224006Shrs return (getprop_dtable[i].dt_act(cp)); 534224006Shrs } 535224006Shrs return (1); 536224006Shrs} 537224006Shrs 538224006Shrsint 539225519Shrscm_setprop(struct ctrl_msg_pl *cp) 540224006Shrs{ 541224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 542224006Shrs 543224006Shrs if (cp == NULL || cp->cp_key == NULL) 544224006Shrs return (1); 545224006Shrs 546224144Shrs if (strncmp(cp->cp_key, "reload", sizeof("reload")) == 0) 547225519Shrs cm_setprop_reload(cp); 548224144Shrs else if (strncmp(cp->cp_key, "shutdown", sizeof("shutdown")) == 0) 549224144Shrs set_do_shutdown(0); 550224144Shrs else if (strncmp(cp->cp_key, "enable", sizeof("enable")) == 0) 551225519Shrs cm_setprop_enable(cp); 552224144Shrs else if (strncmp(cp->cp_key, "disable", sizeof("disable")) == 0) 553225519Shrs cm_setprop_disable(cp); 554224006Shrs else if (strncmp(cp->cp_key, "echo", 8) == 0) 555224006Shrs ; /* do nothing */ 556224006Shrs else 557224006Shrs return (1); 558224006Shrs 559224006Shrs return (0); 560224006Shrs} 561224006Shrs 562224144Shrsstatic int 563225519Shrscm_setprop_reload(struct ctrl_msg_pl *cp) 564224144Shrs{ 565224144Shrs 566224144Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 567224144Shrs 568224144Shrs set_do_reload_ifname(cp->cp_ifname); 569224144Shrs set_do_reload(1); 570224144Shrs 571224144Shrs return (0); 572224144Shrs} 573224144Shrs 574224144Shrsstatic int 575225519Shrscm_setprop_enable(struct ctrl_msg_pl *cp) 576224144Shrs{ 577224144Shrs struct ifinfo *ifi; 578224144Shrs 579224144Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 580224144Shrs 581224144Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 582224144Shrs if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 583224144Shrs break; 584224144Shrs } 585224144Shrs if (ifi == NULL) { 586224144Shrs syslog(LOG_ERR, "<%s> %s not found", __func__, 587224144Shrs cp->cp_ifname); 588224144Shrs return (1); 589224144Shrs } 590224144Shrs 591224144Shrs ifi->ifi_persist = 1; 592224144Shrs set_do_reload_ifname(ifi->ifi_ifname); 593224144Shrs set_do_reload(0); 594224144Shrs 595224144Shrs return (0); 596224144Shrs} 597224144Shrs 598224144Shrsstatic int 599225519Shrscm_setprop_disable(struct ctrl_msg_pl *cp) 600224144Shrs{ 601224144Shrs struct ifinfo *ifi; 602224144Shrs 603224144Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 604224144Shrs 605224144Shrs TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 606224144Shrs if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 607224144Shrs break; 608224144Shrs } 609224144Shrs if (ifi == NULL) { 610224144Shrs syslog(LOG_ERR, "<%s> %s not found", __func__, 611224144Shrs cp->cp_ifname); 612224144Shrs return (1); 613224144Shrs } 614224144Shrs 615225519Shrs if (ifi->ifi_persist == 1) { 616225519Shrs ifi->ifi_persist = 0; 617225519Shrs rm_ifinfo(ifi); 618224144Shrs 619225519Shrs /* MC leaving needed here */ 620225519Shrs sock_mc_leave(&sock, ifi->ifi_ifindex); 621225519Shrs 622225519Shrs set_do_reload_ifname(ifi->ifi_ifname); 623225519Shrs set_do_reload(0); 624225519Shrs } 625225519Shrs 626224144Shrs return (0); 627224144Shrs} 628224144Shrs 629224006Shrsint 630225519Shrscm_handler_server(int fd) 631224006Shrs{ 632224006Shrs int state; 633224006Shrs char *msg; 634224006Shrs struct ctrl_msg_hdr *cm; 635224006Shrs struct ctrl_msg_pl cp; 636224006Shrs char buf[CM_MSG_MAXLEN]; 637224006Shrs char pbuf[CM_MSG_MAXLEN]; 638224006Shrs int error; 639224006Shrs 640224006Shrs syslog(LOG_DEBUG, "<%s> enter", __func__); 641224006Shrs 642224006Shrs memset(buf, 0, sizeof(buf)); 643224006Shrs memset(pbuf, 0, sizeof(pbuf)); 644224006Shrs cm = (struct ctrl_msg_hdr *)buf; 645224006Shrs msg = (char *)buf + sizeof(*cm); 646224006Shrs 647224006Shrs state = CM_STATE_INIT; 648224006Shrs while (state != CM_STATE_EOM) { 649224006Shrs syslog(LOG_DEBUG, "<%s> state = %d", __func__, state); 650224006Shrs 651224006Shrs switch (state) { 652224006Shrs case CM_STATE_INIT: 653224006Shrs state = CM_STATE_MSG_RECV; 654224006Shrs break; 655224006Shrs case CM_STATE_MSG_DISPATCH: 656224006Shrs cm->cm_version = CM_VERSION; 657225519Shrs error = cm_send(fd, buf); 658224006Shrs if (error) 659224006Shrs syslog(LOG_WARNING, 660225519Shrs "<%s> cm_send()", __func__); 661224006Shrs state = CM_STATE_EOM; 662224006Shrs break; 663224006Shrs case CM_STATE_ACK_WAIT: 664225519Shrs error = cm_recv(fd, buf); 665224006Shrs if (error) { 666224006Shrs syslog(LOG_ERR, 667225519Shrs "<%s> cm_recv()", __func__); 668224006Shrs close(fd); 669224006Shrs return (-1); 670224006Shrs } 671224006Shrs 672224006Shrs switch (cm->cm_type) { 673224006Shrs case CM_TYPE_ACK: 674224006Shrs break; 675224006Shrs case CM_TYPE_ERR: 676224006Shrs syslog(LOG_DEBUG, 677224006Shrs "<%s> CM_TYPE_ERR", __func__); 678224006Shrs close(fd); 679224006Shrs return (-1); 680224006Shrs default: 681224006Shrs syslog(LOG_DEBUG, 682224006Shrs "<%s> unknown status", __func__); 683224006Shrs close(fd); 684224006Shrs return (-1); 685224006Shrs } 686224006Shrs state = CM_STATE_EOM; 687224006Shrs break; 688224006Shrs case CM_STATE_MSG_RECV: 689225519Shrs error = cm_recv(fd, buf); 690224006Shrs 691224006Shrs if (error) { 692224006Shrs syslog(LOG_ERR, 693225519Shrs "<%s> cm_recv()", __func__); 694224006Shrs close(fd); 695224006Shrs return (-1); 696224006Shrs } 697224006Shrs memset(&cp, 0, sizeof(cp)); 698224006Shrs 699224006Shrs syslog(LOG_DEBUG, 700224006Shrs "<%s> cm->cm_type = %d", __func__, cm->cm_type); 701224006Shrs syslog(LOG_DEBUG, 702224144Shrs "<%s> cm->cm_len = %zu", __func__, cm->cm_len); 703224006Shrs 704224006Shrs switch (cm->cm_type) { 705224006Shrs case CM_TYPE_EOM: 706224006Shrs state = CM_STATE_EOM; 707224006Shrs case CM_TYPE_NUL: 708224006Shrs cm->cm_type = CM_TYPE_ACK; 709224006Shrs cm->cm_len = sizeof(*cm); 710224006Shrs break; 711224006Shrs case CM_TYPE_REQ_GET_PROP: 712225519Shrs cm_bin2pl(msg, &cp); 713225519Shrs error = cm_getprop(&cp); 714224006Shrs if (error) { 715224006Shrs cm->cm_type = CM_TYPE_ERR; 716224006Shrs cm->cm_len = sizeof(*cm); 717224006Shrs } else { 718224006Shrs cm->cm_type = CM_TYPE_ACK; 719224006Shrs cm->cm_len = sizeof(*cm); 720225519Shrs cm->cm_len += cm_pl2bin(msg, &cp); 721224006Shrs } 722224144Shrs if (cp.cp_val != NULL) 723224144Shrs free(cp.cp_val); 724224006Shrs break; 725224006Shrs case CM_TYPE_REQ_SET_PROP: 726225519Shrs cm_bin2pl(msg, &cp); 727225519Shrs error = cm_setprop(&cp); 728224006Shrs if (error) { 729224006Shrs cm->cm_type = CM_TYPE_ERR; 730224006Shrs cm->cm_len = sizeof(*cm); 731224006Shrs } else { 732224006Shrs cm->cm_type = CM_TYPE_ACK; 733224006Shrs cm->cm_len = sizeof(*cm); 734224006Shrs } 735224006Shrs break; 736224006Shrs default: 737224006Shrs cm->cm_type = CM_TYPE_ERR; 738224006Shrs cm->cm_len = sizeof(*cm); 739224006Shrs } 740224006Shrs 741224006Shrs switch (cm->cm_type) { 742224006Shrs case CM_TYPE_ERR: 743224006Shrs case CM_TYPE_ACK: 744224006Shrs state = CM_STATE_MSG_DISPATCH; 745224006Shrs break; 746224006Shrs } 747224006Shrs } 748224006Shrs } 749224006Shrs syslog(LOG_DEBUG, "<%s> leave", __func__); 750224006Shrs 751224006Shrs return (0); 752224006Shrs} 753