137241896SHiroki Sato /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 31de7b4b8SPedro F. Giffuni * 437241896SHiroki Sato * Copyright (C) 2011 Hiroki Sato <hrs@FreeBSD.org> 537241896SHiroki Sato * All rights reserved. 637241896SHiroki Sato * 737241896SHiroki Sato * Redistribution and use in source and binary forms, with or without 837241896SHiroki Sato * modification, are permitted provided that the following conditions 937241896SHiroki Sato * are met: 1037241896SHiroki Sato * 1. Redistributions of source code must retain the above copyright 1137241896SHiroki Sato * notice, this list of conditions and the following disclaimer. 1237241896SHiroki Sato * 2. Redistributions in binary form must reproduce the above copyright 1337241896SHiroki Sato * notice, this list of conditions and the following disclaimer in the 1437241896SHiroki Sato * documentation and/or other materials provided with the distribution. 1537241896SHiroki Sato * 1637241896SHiroki Sato * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 1737241896SHiroki Sato * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1837241896SHiroki Sato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1937241896SHiroki Sato * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS 2037241896SHiroki Sato * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2137241896SHiroki Sato * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2237241896SHiroki Sato * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 2337241896SHiroki Sato * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 2437241896SHiroki Sato * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 2537241896SHiroki Sato * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 2637241896SHiroki Sato * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2737241896SHiroki Sato * 2837241896SHiroki Sato */ 2937241896SHiroki Sato 30*93e96d6cSElyes Haouas #include <sys/param.h> 3137241896SHiroki Sato #include <sys/queue.h> 3237241896SHiroki Sato #include <sys/socket.h> 3337241896SHiroki Sato #include <sys/stat.h> 3437241896SHiroki Sato #include <sys/un.h> 3537241896SHiroki Sato #include <sys/uio.h> 3637241896SHiroki Sato #include <net/if.h> 3737241896SHiroki Sato #include <net/if_dl.h> 3837241896SHiroki Sato #include <netinet/in.h> 3937241896SHiroki Sato #include <netinet/icmp6.h> 4037241896SHiroki Sato #include <fcntl.h> 4137241896SHiroki Sato #include <errno.h> 4237241896SHiroki Sato #include <netdb.h> 4337241896SHiroki Sato #include <unistd.h> 4437241896SHiroki Sato #include <signal.h> 4537241896SHiroki Sato #include <string.h> 4637241896SHiroki Sato #include <stdarg.h> 4737241896SHiroki Sato #include <stdio.h> 4837241896SHiroki Sato #include <stdlib.h> 4937241896SHiroki Sato #include <syslog.h> 5037241896SHiroki Sato 5137241896SHiroki Sato #include "pathnames.h" 5237241896SHiroki Sato #include "rtadvd.h" 5337241896SHiroki Sato #include "if.h" 54aed37872SHiroki Sato #include "config.h" 5537241896SHiroki Sato #include "control.h" 5637241896SHiroki Sato #include "control_server.h" 5737241896SHiroki Sato #include "timer.h" 5837241896SHiroki Sato 5937241896SHiroki Sato static char *do_reload_ifname; 6037241896SHiroki Sato static int do_reload; 6137241896SHiroki Sato static int do_shutdown; 6237241896SHiroki Sato 6337241896SHiroki Sato void set_do_reload(int sig __unused) { do_reload = 1; } 6437241896SHiroki Sato void set_do_reload_ifname(char *ifname){ do_reload_ifname = ifname; } 6537241896SHiroki Sato void set_do_shutdown(int sig __unused) { do_shutdown = 1; } 6637241896SHiroki Sato void reset_do_reload(void) { do_reload = 0; do_reload_ifname = NULL; } 6737241896SHiroki Sato void reset_do_shutdown(void) { do_shutdown = 0; } 6837241896SHiroki Sato int is_do_reload(void) { return (do_reload); } 6937241896SHiroki Sato int is_do_shutdown(void) { return (do_shutdown); } 7037241896SHiroki Sato char *reload_ifname(void) { return (do_reload_ifname); } 7137241896SHiroki Sato 72aed37872SHiroki Sato #define DEF_PL_HANDLER(key) { #key, cm_getprop_##key } 7337241896SHiroki Sato 74aed37872SHiroki Sato static int cm_getprop_echo(struct ctrl_msg_pl *); 75aed37872SHiroki Sato static int cm_getprop_version(struct ctrl_msg_pl *); 76aed37872SHiroki Sato static int cm_getprop_ifilist(struct ctrl_msg_pl *); 77aed37872SHiroki Sato static int cm_getprop_ifi(struct ctrl_msg_pl *); 78aed37872SHiroki Sato static int cm_getprop_ifi_ra_timer(struct ctrl_msg_pl *); 79aed37872SHiroki Sato static int cm_getprop_rai(struct ctrl_msg_pl *); 80aed37872SHiroki Sato static int cm_getprop_pfx(struct ctrl_msg_pl *); 81aed37872SHiroki Sato static int cm_getprop_rdnss(struct ctrl_msg_pl *); 82aed37872SHiroki Sato static int cm_getprop_dnssl(struct ctrl_msg_pl *); 83aed37872SHiroki Sato static int cm_getprop_rti(struct ctrl_msg_pl *); 8437241896SHiroki Sato 85aed37872SHiroki Sato static int cm_setprop_reload(struct ctrl_msg_pl *); 86aed37872SHiroki Sato static int cm_setprop_enable(struct ctrl_msg_pl *); 87aed37872SHiroki Sato static int cm_setprop_disable(struct ctrl_msg_pl *); 8837241896SHiroki Sato 8937241896SHiroki Sato static struct dispatch_table { 9037241896SHiroki Sato const char *dt_comm; 9137241896SHiroki Sato int (*dt_act)(struct ctrl_msg_pl *cp); 9237241896SHiroki Sato } getprop_dtable[] = { 93aed37872SHiroki Sato { "", cm_getprop_echo }, 9437241896SHiroki Sato DEF_PL_HANDLER(echo), 9537241896SHiroki Sato DEF_PL_HANDLER(version), 9637241896SHiroki Sato DEF_PL_HANDLER(ifilist), 9737241896SHiroki Sato DEF_PL_HANDLER(ifi), 9837241896SHiroki Sato DEF_PL_HANDLER(ifi_ra_timer), 9937241896SHiroki Sato DEF_PL_HANDLER(rai), 10037241896SHiroki Sato DEF_PL_HANDLER(rti), 10137241896SHiroki Sato DEF_PL_HANDLER(pfx), 10237241896SHiroki Sato DEF_PL_HANDLER(rdnss), 10337241896SHiroki Sato DEF_PL_HANDLER(dnssl), 10437241896SHiroki Sato }; 10537241896SHiroki Sato 10637241896SHiroki Sato static int 107aed37872SHiroki Sato cm_getprop_echo(struct ctrl_msg_pl *cp) 10837241896SHiroki Sato { 10937241896SHiroki Sato 11037241896SHiroki Sato syslog(LOG_DEBUG, "<%s> enter", __func__); 11137241896SHiroki Sato cp->cp_val = strdup(""); 11237241896SHiroki Sato cp->cp_val_len = strlen(cp->cp_val) + 1; 11337241896SHiroki Sato 11437241896SHiroki Sato return (0); 11537241896SHiroki Sato } 11637241896SHiroki Sato 11737241896SHiroki Sato static int 118aed37872SHiroki Sato cm_getprop_version(struct ctrl_msg_pl *cp) 11937241896SHiroki Sato { 12037241896SHiroki Sato 12137241896SHiroki Sato syslog(LOG_DEBUG, "<%s> enter", __func__); 12237241896SHiroki Sato cp->cp_val = strdup(CM_VERSION_STR); 12337241896SHiroki Sato cp->cp_val_len = strlen(cp->cp_val) + 1; 12437241896SHiroki Sato 12537241896SHiroki Sato return (0); 12637241896SHiroki Sato } 12737241896SHiroki Sato 12837241896SHiroki Sato static int 129aed37872SHiroki Sato cm_getprop_ifilist(struct ctrl_msg_pl *cp) 13037241896SHiroki Sato { 13137241896SHiroki Sato struct ifinfo *ifi; 13237241896SHiroki Sato char *p; 13337241896SHiroki Sato size_t len; 13437241896SHiroki Sato 13537241896SHiroki Sato syslog(LOG_DEBUG, "<%s> enter", __func__); 13637241896SHiroki Sato 13737241896SHiroki Sato len = 0; 13837241896SHiroki Sato TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 13937241896SHiroki Sato len += strlen(ifi->ifi_ifname) + 1; 14037241896SHiroki Sato } 14137241896SHiroki Sato 14237241896SHiroki Sato syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 14337241896SHiroki Sato 14437241896SHiroki Sato p = malloc(len); 14537241896SHiroki Sato if (p == NULL) 14637241896SHiroki Sato exit(1); 14737241896SHiroki Sato memset(p, 0, len); 14837241896SHiroki Sato cp->cp_val = p; 14937241896SHiroki Sato 15037241896SHiroki Sato if (len > 0) 15137241896SHiroki Sato TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 15237241896SHiroki Sato syslog(LOG_DEBUG, "<%s> add ifname=%s(%d)", 15337241896SHiroki Sato __func__, ifi->ifi_ifname, ifi->ifi_ifindex); 15437241896SHiroki Sato strcpy(p, ifi->ifi_ifname); 15537241896SHiroki Sato p += strlen(ifi->ifi_ifname) + 1; 15637241896SHiroki Sato } 15737241896SHiroki Sato cp->cp_val_len = p - cp->cp_val; 15837241896SHiroki Sato 15937241896SHiroki Sato return (0); 16037241896SHiroki Sato } 16137241896SHiroki Sato 16237241896SHiroki Sato static int 163aed37872SHiroki Sato cm_getprop_ifi(struct ctrl_msg_pl *cp) 16437241896SHiroki Sato { 16537241896SHiroki Sato struct ifinfo *ifi; 16637241896SHiroki Sato char *p; 16737241896SHiroki Sato size_t len; 16837241896SHiroki Sato 16937241896SHiroki Sato syslog(LOG_DEBUG, "<%s> enter", __func__); 17037241896SHiroki Sato 17137241896SHiroki Sato TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 17237241896SHiroki Sato if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 17337241896SHiroki Sato break; 17437241896SHiroki Sato } 17537241896SHiroki Sato if (ifi == NULL) { 17637241896SHiroki Sato syslog(LOG_ERR, "<%s> %s not found", __func__, 17737241896SHiroki Sato cp->cp_ifname); 17837241896SHiroki Sato return (1); 17937241896SHiroki Sato } 18037241896SHiroki Sato 18137241896SHiroki Sato p = malloc(sizeof(*ifi)); 18237241896SHiroki Sato if (p == NULL) 18337241896SHiroki Sato exit(1); 184aed37872SHiroki Sato len = cm_str2bin(p, ifi, sizeof(*ifi)); 18537241896SHiroki Sato 18637241896SHiroki Sato syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 18737241896SHiroki Sato 18837241896SHiroki Sato if (len == 0) 18937241896SHiroki Sato return (1); 19037241896SHiroki Sato 19137241896SHiroki Sato cp->cp_val = p; 19237241896SHiroki Sato cp->cp_val_len = len; 19337241896SHiroki Sato 19437241896SHiroki Sato return (0); 19537241896SHiroki Sato } 19637241896SHiroki Sato 19737241896SHiroki Sato static int 198aed37872SHiroki Sato cm_getprop_rai(struct ctrl_msg_pl *cp) 19937241896SHiroki Sato { 20037241896SHiroki Sato struct ifinfo *ifi; 20137241896SHiroki Sato struct rainfo *rai; 20237241896SHiroki Sato char *p; 20337241896SHiroki Sato size_t len; 20437241896SHiroki Sato 20537241896SHiroki Sato syslog(LOG_DEBUG, "<%s> enter", __func__); 20637241896SHiroki Sato 20737241896SHiroki Sato TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 20837241896SHiroki Sato if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 20937241896SHiroki Sato break; 21037241896SHiroki Sato } 21137241896SHiroki Sato if (ifi == NULL) { 21237241896SHiroki Sato syslog(LOG_ERR, "<%s> %s not found", __func__, 21337241896SHiroki Sato cp->cp_ifname); 21437241896SHiroki Sato return (1); 21537241896SHiroki Sato } 21637241896SHiroki Sato if ((rai = ifi->ifi_rainfo) == NULL) { 21737241896SHiroki Sato syslog(LOG_ERR, "<%s> %s has no rainfo", __func__, 21837241896SHiroki Sato cp->cp_ifname); 21937241896SHiroki Sato return (1); 22037241896SHiroki Sato } 22137241896SHiroki Sato 22237241896SHiroki Sato p = malloc(sizeof(*rai)); 22337241896SHiroki Sato if (p == NULL) 22437241896SHiroki Sato exit(1); 225aed37872SHiroki Sato len = cm_str2bin(p, rai, sizeof(*rai)); 22637241896SHiroki Sato 22737241896SHiroki Sato syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 22837241896SHiroki Sato 22937241896SHiroki Sato if (len == 0) 23037241896SHiroki Sato return (1); 23137241896SHiroki Sato 23237241896SHiroki Sato cp->cp_val = p; 23337241896SHiroki Sato cp->cp_val_len = len; 23437241896SHiroki Sato 23537241896SHiroki Sato return (0); 23637241896SHiroki Sato } 23737241896SHiroki Sato 23837241896SHiroki Sato static int 239aed37872SHiroki Sato cm_getprop_ifi_ra_timer(struct ctrl_msg_pl *cp) 24037241896SHiroki Sato { 24137241896SHiroki Sato struct ifinfo *ifi; 24237241896SHiroki Sato struct rainfo *rai; 24337241896SHiroki Sato struct rtadvd_timer *rtimer; 24437241896SHiroki Sato char *p; 24537241896SHiroki Sato size_t len; 24637241896SHiroki Sato 24737241896SHiroki Sato syslog(LOG_DEBUG, "<%s> enter", __func__); 24837241896SHiroki Sato 24937241896SHiroki Sato TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 25037241896SHiroki Sato if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 25137241896SHiroki Sato break; 25237241896SHiroki Sato } 25337241896SHiroki Sato if (ifi == NULL) { 25437241896SHiroki Sato syslog(LOG_ERR, "<%s> %s not found", __func__, 25537241896SHiroki Sato cp->cp_ifname); 25637241896SHiroki Sato return (1); 25737241896SHiroki Sato } 25837241896SHiroki Sato if ((rai = ifi->ifi_rainfo) == NULL) { 25937241896SHiroki Sato syslog(LOG_ERR, "<%s> %s has no rainfo", __func__, 26037241896SHiroki Sato cp->cp_ifname); 26137241896SHiroki Sato return (1); 26237241896SHiroki Sato } 26337241896SHiroki Sato if ((rtimer = ifi->ifi_ra_timer) == NULL) { 26437241896SHiroki Sato syslog(LOG_ERR, "<%s> %s has no ifi_ra_timer", __func__, 26537241896SHiroki Sato cp->cp_ifname); 26637241896SHiroki Sato return (1); 26737241896SHiroki Sato } 26837241896SHiroki Sato p = malloc(sizeof(*rtimer)); 26937241896SHiroki Sato if (p == NULL) 27037241896SHiroki Sato exit(1); 271aed37872SHiroki Sato len = cm_str2bin(p, rtimer, sizeof(*rtimer)); 27237241896SHiroki Sato 27337241896SHiroki Sato syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 27437241896SHiroki Sato 27537241896SHiroki Sato if (len == 0) 27637241896SHiroki Sato return (1); 27737241896SHiroki Sato 27837241896SHiroki Sato cp->cp_val = p; 27937241896SHiroki Sato cp->cp_val_len = len; 28037241896SHiroki Sato 28137241896SHiroki Sato return (0); 28237241896SHiroki Sato } 28337241896SHiroki Sato 28437241896SHiroki Sato static int 285aed37872SHiroki Sato cm_getprop_rti(struct ctrl_msg_pl *cp) 28637241896SHiroki Sato { 28737241896SHiroki Sato struct ifinfo *ifi; 28837241896SHiroki Sato struct rainfo *rai; 28937241896SHiroki Sato struct rtinfo *rti; 29037241896SHiroki Sato char *p; 29137241896SHiroki Sato size_t len; 29237241896SHiroki Sato 29337241896SHiroki Sato syslog(LOG_DEBUG, "<%s> enter", __func__); 29437241896SHiroki Sato 29537241896SHiroki Sato len = 0; 29637241896SHiroki Sato TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 29737241896SHiroki Sato if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 29837241896SHiroki Sato break; 29937241896SHiroki Sato } 30037241896SHiroki Sato if (ifi == NULL) { 30137241896SHiroki Sato syslog(LOG_ERR, "<%s> %s not found", __func__, 30237241896SHiroki Sato cp->cp_ifname); 30337241896SHiroki Sato return (1); 30437241896SHiroki Sato } 30537241896SHiroki Sato if (ifi->ifi_rainfo == NULL) { 30637241896SHiroki Sato syslog(LOG_ERR, "<%s> %s has no rainfo", __func__, 30737241896SHiroki Sato cp->cp_ifname); 30837241896SHiroki Sato return (1); 30937241896SHiroki Sato } 31037241896SHiroki Sato rai = ifi->ifi_rainfo; 31137241896SHiroki Sato TAILQ_FOREACH(rti, &rai->rai_route, rti_next) { 31237241896SHiroki Sato len += sizeof(*rti); 31337241896SHiroki Sato } 31437241896SHiroki Sato 31537241896SHiroki Sato syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 31637241896SHiroki Sato 31737241896SHiroki Sato p = malloc(len); 31837241896SHiroki Sato if (p == NULL) 31937241896SHiroki Sato exit(1); 32037241896SHiroki Sato memset(p, 0, len); 32137241896SHiroki Sato cp->cp_val = p; 32237241896SHiroki Sato 32337241896SHiroki Sato if (len > 0) 32437241896SHiroki Sato TAILQ_FOREACH(rti, &rai->rai_route, rti_next) { 32537241896SHiroki Sato memcpy(p, rti, sizeof(*rti)); 32637241896SHiroki Sato p += sizeof(*rti); 32737241896SHiroki Sato } 32837241896SHiroki Sato cp->cp_val_len = p - cp->cp_val; 32937241896SHiroki Sato 33037241896SHiroki Sato return (0); 33137241896SHiroki Sato } 33237241896SHiroki Sato 33337241896SHiroki Sato static int 334aed37872SHiroki Sato cm_getprop_pfx(struct ctrl_msg_pl *cp) 33537241896SHiroki Sato { 33637241896SHiroki Sato struct ifinfo *ifi; 33737241896SHiroki Sato struct rainfo *rai; 33837241896SHiroki Sato struct prefix *pfx; 33937241896SHiroki Sato char *p; 34037241896SHiroki Sato size_t len; 34137241896SHiroki Sato 34237241896SHiroki Sato syslog(LOG_DEBUG, "<%s> enter", __func__); 34337241896SHiroki Sato 34437241896SHiroki Sato len = 0; 34537241896SHiroki Sato TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 34637241896SHiroki Sato if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 34737241896SHiroki Sato break; 34837241896SHiroki Sato } 34937241896SHiroki Sato if (ifi == NULL) { 35037241896SHiroki Sato syslog(LOG_ERR, "<%s> %s not found", __func__, 35137241896SHiroki Sato cp->cp_ifname); 35237241896SHiroki Sato return (1); 35337241896SHiroki Sato } 35437241896SHiroki Sato if (ifi->ifi_rainfo == NULL) { 35537241896SHiroki Sato syslog(LOG_ERR, "<%s> %s has no rainfo", __func__, 35637241896SHiroki Sato cp->cp_ifname); 35737241896SHiroki Sato return (1); 35837241896SHiroki Sato } 35937241896SHiroki Sato rai = ifi->ifi_rainfo; 36037241896SHiroki Sato TAILQ_FOREACH(pfx, &rai->rai_prefix, pfx_next) { 36137241896SHiroki Sato len += sizeof(*pfx); 36237241896SHiroki Sato } 36337241896SHiroki Sato 36437241896SHiroki Sato syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 36537241896SHiroki Sato 36637241896SHiroki Sato p = malloc(len); 36737241896SHiroki Sato if (p == NULL) 36837241896SHiroki Sato exit(1); 36937241896SHiroki Sato memset(p, 0, len); 37037241896SHiroki Sato cp->cp_val = p; 37137241896SHiroki Sato 37237241896SHiroki Sato if (len > 0) 37337241896SHiroki Sato TAILQ_FOREACH(pfx, &rai->rai_prefix, pfx_next) { 37437241896SHiroki Sato memcpy(p, pfx, sizeof(*pfx)); 37537241896SHiroki Sato p += sizeof(*pfx); 37637241896SHiroki Sato } 37737241896SHiroki Sato cp->cp_val_len = p - cp->cp_val; 37837241896SHiroki Sato 37937241896SHiroki Sato return (0); 38037241896SHiroki Sato } 38137241896SHiroki Sato 38237241896SHiroki Sato static int 383aed37872SHiroki Sato cm_getprop_rdnss(struct ctrl_msg_pl *cp) 38437241896SHiroki Sato { 38537241896SHiroki Sato struct ifinfo *ifi; 38637241896SHiroki Sato struct rainfo *rai; 38737241896SHiroki Sato struct rdnss *rdn; 38837241896SHiroki Sato struct rdnss_addr *rda; 38937241896SHiroki Sato char *p; 39037241896SHiroki Sato size_t len; 39137241896SHiroki Sato uint16_t *rdn_cnt; 39237241896SHiroki Sato uint16_t *rda_cnt; 39337241896SHiroki Sato 39437241896SHiroki Sato syslog(LOG_DEBUG, "<%s> enter", __func__); 39537241896SHiroki Sato 39637241896SHiroki Sato len = 0; 39737241896SHiroki Sato TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 39837241896SHiroki Sato if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 39937241896SHiroki Sato break; 40037241896SHiroki Sato } 40137241896SHiroki Sato if (ifi == NULL) { 40237241896SHiroki Sato syslog(LOG_ERR, "<%s> %s not found", __func__, 40337241896SHiroki Sato cp->cp_ifname); 40437241896SHiroki Sato return (1); 40537241896SHiroki Sato } 40637241896SHiroki Sato if (ifi->ifi_rainfo == NULL) { 40737241896SHiroki Sato syslog(LOG_ERR, "<%s> %s has no rainfo", __func__, 40837241896SHiroki Sato cp->cp_ifname); 40937241896SHiroki Sato return (1); 41037241896SHiroki Sato } 41137241896SHiroki Sato rai = ifi->ifi_rainfo; 41237241896SHiroki Sato 41337241896SHiroki Sato len = sizeof(*rdn_cnt); 41437241896SHiroki Sato TAILQ_FOREACH(rdn, &rai->rai_rdnss, rd_next) { 41537241896SHiroki Sato len += sizeof(*rdn); 41637241896SHiroki Sato len += sizeof(*rda_cnt); 41737241896SHiroki Sato TAILQ_FOREACH(rda, &rdn->rd_list, ra_next) { 41837241896SHiroki Sato len += sizeof(*rda); 41937241896SHiroki Sato } 42037241896SHiroki Sato } 42137241896SHiroki Sato 42237241896SHiroki Sato syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 42337241896SHiroki Sato 42437241896SHiroki Sato p = malloc(len); 42537241896SHiroki Sato if (p == NULL) 42637241896SHiroki Sato exit(1); 42737241896SHiroki Sato memset(p, 0, len); 42837241896SHiroki Sato cp->cp_val = p; 42937241896SHiroki Sato 43037241896SHiroki Sato rdn_cnt = (uint16_t *)p; 43137241896SHiroki Sato p += sizeof(*rdn_cnt); 43237241896SHiroki Sato TAILQ_FOREACH(rdn, &rai->rai_rdnss, rd_next) { 43337241896SHiroki Sato *rdn_cnt += 1; 43437241896SHiroki Sato memcpy(p, rdn, sizeof(*rdn)); 43537241896SHiroki Sato p += sizeof(*rdn); 43637241896SHiroki Sato 43737241896SHiroki Sato rda_cnt = (uint16_t *)p; 43837241896SHiroki Sato p += sizeof(*rda_cnt); 43937241896SHiroki Sato TAILQ_FOREACH(rda, &rdn->rd_list, ra_next) { 44037241896SHiroki Sato *rda_cnt += 1; 44137241896SHiroki Sato memcpy(p, rda, sizeof(*rda)); 44237241896SHiroki Sato p += sizeof(*rda); 44337241896SHiroki Sato } 44437241896SHiroki Sato } 44537241896SHiroki Sato syslog(LOG_DEBUG, "<%s> rdn_cnt = %d", __func__, *rdn_cnt); 44637241896SHiroki Sato cp->cp_val_len = p - cp->cp_val; 44737241896SHiroki Sato 44837241896SHiroki Sato return (0); 44937241896SHiroki Sato } 45037241896SHiroki Sato 45137241896SHiroki Sato static int 452aed37872SHiroki Sato cm_getprop_dnssl(struct ctrl_msg_pl *cp) 45337241896SHiroki Sato { 45437241896SHiroki Sato struct ifinfo *ifi; 45537241896SHiroki Sato struct rainfo *rai; 45637241896SHiroki Sato struct dnssl *dns; 45737241896SHiroki Sato struct dnssl_addr *dna; 45837241896SHiroki Sato char *p; 45937241896SHiroki Sato size_t len; 46037241896SHiroki Sato uint16_t *dns_cnt; 46137241896SHiroki Sato uint16_t *dna_cnt; 46237241896SHiroki Sato 46337241896SHiroki Sato syslog(LOG_DEBUG, "<%s> enter", __func__); 46437241896SHiroki Sato 46537241896SHiroki Sato len = 0; 46637241896SHiroki Sato TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 46737241896SHiroki Sato if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 46837241896SHiroki Sato break; 46937241896SHiroki Sato } 47037241896SHiroki Sato if (ifi == NULL) { 47137241896SHiroki Sato syslog(LOG_ERR, "<%s> %s not found", __func__, 47237241896SHiroki Sato cp->cp_ifname); 47337241896SHiroki Sato return (1); 47437241896SHiroki Sato } 47537241896SHiroki Sato if (ifi->ifi_rainfo == NULL) { 47637241896SHiroki Sato syslog(LOG_ERR, "<%s> %s has no rainfo", __func__, 47737241896SHiroki Sato cp->cp_ifname); 47837241896SHiroki Sato return (1); 47937241896SHiroki Sato } 48037241896SHiroki Sato rai = ifi->ifi_rainfo; 48137241896SHiroki Sato 48237241896SHiroki Sato len = sizeof(*dns_cnt); 48337241896SHiroki Sato TAILQ_FOREACH(dns, &rai->rai_dnssl, dn_next) { 48437241896SHiroki Sato len += sizeof(*dns); 48537241896SHiroki Sato len += sizeof(*dna_cnt); 48637241896SHiroki Sato TAILQ_FOREACH(dna, &dns->dn_list, da_next) { 48737241896SHiroki Sato len += sizeof(*dna); 48837241896SHiroki Sato } 48937241896SHiroki Sato } 49037241896SHiroki Sato 49137241896SHiroki Sato syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len); 49237241896SHiroki Sato 49337241896SHiroki Sato p = malloc(len); 49437241896SHiroki Sato if (p == NULL) 49537241896SHiroki Sato exit(1); 49637241896SHiroki Sato memset(p, 0, len); 49737241896SHiroki Sato cp->cp_val = p; 49837241896SHiroki Sato 49937241896SHiroki Sato dns_cnt = (uint16_t *)cp->cp_val; 50037241896SHiroki Sato p += sizeof(*dns_cnt); 50137241896SHiroki Sato TAILQ_FOREACH(dns, &rai->rai_dnssl, dn_next) { 50237241896SHiroki Sato (*dns_cnt)++; 50337241896SHiroki Sato memcpy(p, dns, sizeof(*dns)); 50437241896SHiroki Sato p += sizeof(*dns); 50537241896SHiroki Sato 50637241896SHiroki Sato dna_cnt = (uint16_t *)p; 50737241896SHiroki Sato p += sizeof(*dna_cnt); 50837241896SHiroki Sato TAILQ_FOREACH(dna, &dns->dn_list, da_next) { 50937241896SHiroki Sato (*dna_cnt)++; 51037241896SHiroki Sato memcpy(p, dna, sizeof(*dna)); 51137241896SHiroki Sato p += sizeof(*dna); 51237241896SHiroki Sato } 51337241896SHiroki Sato } 51437241896SHiroki Sato cp->cp_val_len = p - cp->cp_val; 51537241896SHiroki Sato 51637241896SHiroki Sato return (0); 51737241896SHiroki Sato } 51837241896SHiroki Sato 51937241896SHiroki Sato int 520aed37872SHiroki Sato cm_getprop(struct ctrl_msg_pl *cp) 52137241896SHiroki Sato { 52237241896SHiroki Sato size_t i; 52337241896SHiroki Sato 52437241896SHiroki Sato syslog(LOG_DEBUG, "<%s> enter", __func__); 52537241896SHiroki Sato 52637241896SHiroki Sato if (cp == NULL) 52737241896SHiroki Sato return (1); 52837241896SHiroki Sato 52937241896SHiroki Sato for (i = 0; 530*93e96d6cSElyes Haouas i < nitems(getprop_dtable); 53137241896SHiroki Sato i++) { 53237241896SHiroki Sato if (strcmp(cp->cp_key, getprop_dtable[i].dt_comm) == 0) 53337241896SHiroki Sato return (getprop_dtable[i].dt_act(cp)); 53437241896SHiroki Sato } 53537241896SHiroki Sato return (1); 53637241896SHiroki Sato } 53737241896SHiroki Sato 53837241896SHiroki Sato int 539aed37872SHiroki Sato cm_setprop(struct ctrl_msg_pl *cp) 54037241896SHiroki Sato { 54137241896SHiroki Sato syslog(LOG_DEBUG, "<%s> enter", __func__); 54237241896SHiroki Sato 54337241896SHiroki Sato if (cp == NULL || cp->cp_key == NULL) 54437241896SHiroki Sato return (1); 54537241896SHiroki Sato 54637241896SHiroki Sato if (strncmp(cp->cp_key, "reload", sizeof("reload")) == 0) 547aed37872SHiroki Sato cm_setprop_reload(cp); 54837241896SHiroki Sato else if (strncmp(cp->cp_key, "shutdown", sizeof("shutdown")) == 0) 54937241896SHiroki Sato set_do_shutdown(0); 55037241896SHiroki Sato else if (strncmp(cp->cp_key, "enable", sizeof("enable")) == 0) 551aed37872SHiroki Sato cm_setprop_enable(cp); 55237241896SHiroki Sato else if (strncmp(cp->cp_key, "disable", sizeof("disable")) == 0) 553aed37872SHiroki Sato cm_setprop_disable(cp); 55437241896SHiroki Sato else if (strncmp(cp->cp_key, "echo", 8) == 0) 55537241896SHiroki Sato ; /* do nothing */ 55637241896SHiroki Sato else 55737241896SHiroki Sato return (1); 55837241896SHiroki Sato 55937241896SHiroki Sato return (0); 56037241896SHiroki Sato } 56137241896SHiroki Sato 56237241896SHiroki Sato static int 563aed37872SHiroki Sato cm_setprop_reload(struct ctrl_msg_pl *cp) 56437241896SHiroki Sato { 56537241896SHiroki Sato 56637241896SHiroki Sato syslog(LOG_DEBUG, "<%s> enter", __func__); 56737241896SHiroki Sato 56837241896SHiroki Sato set_do_reload_ifname(cp->cp_ifname); 56937241896SHiroki Sato set_do_reload(1); 57037241896SHiroki Sato 57137241896SHiroki Sato return (0); 57237241896SHiroki Sato } 57337241896SHiroki Sato 57437241896SHiroki Sato static int 575aed37872SHiroki Sato cm_setprop_enable(struct ctrl_msg_pl *cp) 57637241896SHiroki Sato { 57737241896SHiroki Sato struct ifinfo *ifi; 57837241896SHiroki Sato 57937241896SHiroki Sato syslog(LOG_DEBUG, "<%s> enter", __func__); 58037241896SHiroki Sato 58137241896SHiroki Sato TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 58237241896SHiroki Sato if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 58337241896SHiroki Sato break; 58437241896SHiroki Sato } 58537241896SHiroki Sato if (ifi == NULL) { 58637241896SHiroki Sato syslog(LOG_ERR, "<%s> %s not found", __func__, 58737241896SHiroki Sato cp->cp_ifname); 58837241896SHiroki Sato return (1); 58937241896SHiroki Sato } 59037241896SHiroki Sato 59137241896SHiroki Sato ifi->ifi_persist = 1; 59237241896SHiroki Sato set_do_reload_ifname(ifi->ifi_ifname); 59337241896SHiroki Sato set_do_reload(0); 59437241896SHiroki Sato 59537241896SHiroki Sato return (0); 59637241896SHiroki Sato } 59737241896SHiroki Sato 59837241896SHiroki Sato static int 599aed37872SHiroki Sato cm_setprop_disable(struct ctrl_msg_pl *cp) 60037241896SHiroki Sato { 60137241896SHiroki Sato struct ifinfo *ifi; 60237241896SHiroki Sato 60337241896SHiroki Sato syslog(LOG_DEBUG, "<%s> enter", __func__); 60437241896SHiroki Sato 60537241896SHiroki Sato TAILQ_FOREACH(ifi, &ifilist, ifi_next) { 60637241896SHiroki Sato if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0) 60737241896SHiroki Sato break; 60837241896SHiroki Sato } 60937241896SHiroki Sato if (ifi == NULL) { 61037241896SHiroki Sato syslog(LOG_ERR, "<%s> %s not found", __func__, 61137241896SHiroki Sato cp->cp_ifname); 61237241896SHiroki Sato return (1); 61337241896SHiroki Sato } 61437241896SHiroki Sato 615aed37872SHiroki Sato if (ifi->ifi_persist == 1) { 61637241896SHiroki Sato ifi->ifi_persist = 0; 617aed37872SHiroki Sato rm_ifinfo(ifi); 618aed37872SHiroki Sato 619aed37872SHiroki Sato /* MC leaving needed here */ 620aed37872SHiroki Sato sock_mc_leave(&sock, ifi->ifi_ifindex); 621aed37872SHiroki Sato 622aed37872SHiroki Sato set_do_reload_ifname(ifi->ifi_ifname); 623aed37872SHiroki Sato set_do_reload(0); 624aed37872SHiroki Sato } 62537241896SHiroki Sato 62637241896SHiroki Sato return (0); 62737241896SHiroki Sato } 62837241896SHiroki Sato 62937241896SHiroki Sato int 630aed37872SHiroki Sato cm_handler_server(int fd) 63137241896SHiroki Sato { 63237241896SHiroki Sato int state; 63337241896SHiroki Sato char *msg; 63437241896SHiroki Sato struct ctrl_msg_hdr *cm; 63537241896SHiroki Sato struct ctrl_msg_pl cp; 63637241896SHiroki Sato char buf[CM_MSG_MAXLEN]; 63737241896SHiroki Sato char pbuf[CM_MSG_MAXLEN]; 63837241896SHiroki Sato int error; 63937241896SHiroki Sato 64037241896SHiroki Sato syslog(LOG_DEBUG, "<%s> enter", __func__); 64137241896SHiroki Sato 64237241896SHiroki Sato memset(buf, 0, sizeof(buf)); 64337241896SHiroki Sato memset(pbuf, 0, sizeof(pbuf)); 64437241896SHiroki Sato cm = (struct ctrl_msg_hdr *)buf; 64537241896SHiroki Sato msg = (char *)buf + sizeof(*cm); 64637241896SHiroki Sato 64737241896SHiroki Sato state = CM_STATE_INIT; 64837241896SHiroki Sato while (state != CM_STATE_EOM) { 64937241896SHiroki Sato syslog(LOG_DEBUG, "<%s> state = %d", __func__, state); 65037241896SHiroki Sato 65137241896SHiroki Sato switch (state) { 65237241896SHiroki Sato case CM_STATE_INIT: 65337241896SHiroki Sato state = CM_STATE_MSG_RECV; 65437241896SHiroki Sato break; 65537241896SHiroki Sato case CM_STATE_MSG_DISPATCH: 65637241896SHiroki Sato cm->cm_version = CM_VERSION; 657aed37872SHiroki Sato error = cm_send(fd, buf); 65837241896SHiroki Sato if (error) 65937241896SHiroki Sato syslog(LOG_WARNING, 660aed37872SHiroki Sato "<%s> cm_send()", __func__); 66137241896SHiroki Sato state = CM_STATE_EOM; 66237241896SHiroki Sato break; 66337241896SHiroki Sato case CM_STATE_ACK_WAIT: 664aed37872SHiroki Sato error = cm_recv(fd, buf); 66537241896SHiroki Sato if (error) { 66637241896SHiroki Sato syslog(LOG_ERR, 667aed37872SHiroki Sato "<%s> cm_recv()", __func__); 66837241896SHiroki Sato close(fd); 66937241896SHiroki Sato return (-1); 67037241896SHiroki Sato } 67137241896SHiroki Sato 67237241896SHiroki Sato switch (cm->cm_type) { 67337241896SHiroki Sato case CM_TYPE_ACK: 67437241896SHiroki Sato break; 67537241896SHiroki Sato case CM_TYPE_ERR: 67637241896SHiroki Sato syslog(LOG_DEBUG, 67737241896SHiroki Sato "<%s> CM_TYPE_ERR", __func__); 67837241896SHiroki Sato close(fd); 67937241896SHiroki Sato return (-1); 68037241896SHiroki Sato default: 68137241896SHiroki Sato syslog(LOG_DEBUG, 68237241896SHiroki Sato "<%s> unknown status", __func__); 68337241896SHiroki Sato close(fd); 68437241896SHiroki Sato return (-1); 68537241896SHiroki Sato } 68637241896SHiroki Sato state = CM_STATE_EOM; 68737241896SHiroki Sato break; 68837241896SHiroki Sato case CM_STATE_MSG_RECV: 689aed37872SHiroki Sato error = cm_recv(fd, buf); 69037241896SHiroki Sato 69137241896SHiroki Sato if (error) { 69237241896SHiroki Sato syslog(LOG_ERR, 693aed37872SHiroki Sato "<%s> cm_recv()", __func__); 69437241896SHiroki Sato close(fd); 69537241896SHiroki Sato return (-1); 69637241896SHiroki Sato } 69737241896SHiroki Sato memset(&cp, 0, sizeof(cp)); 69837241896SHiroki Sato 69937241896SHiroki Sato syslog(LOG_DEBUG, 70037241896SHiroki Sato "<%s> cm->cm_type = %d", __func__, cm->cm_type); 70137241896SHiroki Sato syslog(LOG_DEBUG, 70237241896SHiroki Sato "<%s> cm->cm_len = %zu", __func__, cm->cm_len); 70337241896SHiroki Sato 70437241896SHiroki Sato switch (cm->cm_type) { 70537241896SHiroki Sato case CM_TYPE_EOM: 70637241896SHiroki Sato state = CM_STATE_EOM; 70737241896SHiroki Sato case CM_TYPE_NUL: 70837241896SHiroki Sato cm->cm_type = CM_TYPE_ACK; 70937241896SHiroki Sato cm->cm_len = sizeof(*cm); 71037241896SHiroki Sato break; 71137241896SHiroki Sato case CM_TYPE_REQ_GET_PROP: 712aed37872SHiroki Sato cm_bin2pl(msg, &cp); 713aed37872SHiroki Sato error = cm_getprop(&cp); 71437241896SHiroki Sato if (error) { 71537241896SHiroki Sato cm->cm_type = CM_TYPE_ERR; 71637241896SHiroki Sato cm->cm_len = sizeof(*cm); 71737241896SHiroki Sato } else { 71837241896SHiroki Sato cm->cm_type = CM_TYPE_ACK; 71937241896SHiroki Sato cm->cm_len = sizeof(*cm); 720aed37872SHiroki Sato cm->cm_len += cm_pl2bin(msg, &cp); 72137241896SHiroki Sato } 72237241896SHiroki Sato if (cp.cp_val != NULL) 72337241896SHiroki Sato free(cp.cp_val); 72437241896SHiroki Sato break; 72537241896SHiroki Sato case CM_TYPE_REQ_SET_PROP: 726aed37872SHiroki Sato cm_bin2pl(msg, &cp); 727aed37872SHiroki Sato error = cm_setprop(&cp); 72837241896SHiroki Sato if (error) { 72937241896SHiroki Sato cm->cm_type = CM_TYPE_ERR; 73037241896SHiroki Sato cm->cm_len = sizeof(*cm); 73137241896SHiroki Sato } else { 73237241896SHiroki Sato cm->cm_type = CM_TYPE_ACK; 73337241896SHiroki Sato cm->cm_len = sizeof(*cm); 73437241896SHiroki Sato } 73537241896SHiroki Sato break; 73637241896SHiroki Sato default: 73737241896SHiroki Sato cm->cm_type = CM_TYPE_ERR; 73837241896SHiroki Sato cm->cm_len = sizeof(*cm); 73937241896SHiroki Sato } 74037241896SHiroki Sato 74137241896SHiroki Sato switch (cm->cm_type) { 74237241896SHiroki Sato case CM_TYPE_ERR: 74337241896SHiroki Sato case CM_TYPE_ACK: 74437241896SHiroki Sato state = CM_STATE_MSG_DISPATCH; 74537241896SHiroki Sato break; 74637241896SHiroki Sato } 74737241896SHiroki Sato } 74837241896SHiroki Sato } 74937241896SHiroki Sato syslog(LOG_DEBUG, "<%s> leave", __func__); 75037241896SHiroki Sato 75137241896SHiroki Sato return (0); 75237241896SHiroki Sato } 753