xref: /freebsd/usr.sbin/rtadvd/control_server.c (revision 93e96d6c87dc8dd84cdfc56a155dc0611f55ac86)
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