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
set_do_reload(int sig __unused)6337241896SHiroki Sato void set_do_reload(int sig __unused) { do_reload = 1; }
set_do_reload_ifname(char * ifname)6437241896SHiroki Sato void set_do_reload_ifname(char *ifname){ do_reload_ifname = ifname; }
set_do_shutdown(int sig __unused)6537241896SHiroki Sato void set_do_shutdown(int sig __unused) { do_shutdown = 1; }
reset_do_reload(void)6637241896SHiroki Sato void reset_do_reload(void) { do_reload = 0; do_reload_ifname = NULL; }
reset_do_shutdown(void)6737241896SHiroki Sato void reset_do_shutdown(void) { do_shutdown = 0; }
is_do_reload(void)6837241896SHiroki Sato int is_do_reload(void) { return (do_reload); }
is_do_shutdown(void)6937241896SHiroki Sato int is_do_shutdown(void) { return (do_shutdown); }
reload_ifname(void)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
cm_getprop_echo(struct ctrl_msg_pl * cp)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
cm_getprop_version(struct ctrl_msg_pl * cp)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
cm_getprop_ifilist(struct ctrl_msg_pl * cp)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
cm_getprop_ifi(struct ctrl_msg_pl * cp)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
cm_getprop_rai(struct ctrl_msg_pl * cp)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
cm_getprop_ifi_ra_timer(struct ctrl_msg_pl * cp)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
cm_getprop_rti(struct ctrl_msg_pl * cp)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
cm_getprop_pfx(struct ctrl_msg_pl * cp)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
cm_getprop_rdnss(struct ctrl_msg_pl * cp)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
cm_getprop_dnssl(struct ctrl_msg_pl * cp)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
cm_getprop(struct ctrl_msg_pl * cp)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
cm_setprop(struct ctrl_msg_pl * cp)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
cm_setprop_reload(struct ctrl_msg_pl * cp)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
cm_setprop_enable(struct ctrl_msg_pl * cp)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
cm_setprop_disable(struct ctrl_msg_pl * cp)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
cm_handler_server(int fd)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