mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-27 11:55:06 +00:00
aed378729e
- Fix an abnormal termination caused by twice of "rtadvctl disable". (r224303) - Use poll() to wait for the control message socket instead of a spin loop. (r224304) - s/cmsg_/cm_/ to avoid conflict with CMSG_* symbols for struct cmsghdr. (r224619) - Ignore an interface that never sent RAs for graceful shut-down. (r224620) - Refine log messages. (r225148) - Fix SIGSEGV when receiving RAs that contain RDNSS and/or DNSSL options. (r225149) Approved by: re (kib)
753 lines
16 KiB
C
753 lines
16 KiB
C
/*-
|
|
* Copyright (C) 2011 Hiroki Sato <hrs@FreeBSD.org>
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
|
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* $FreeBSD$
|
|
*
|
|
*/
|
|
|
|
#include <sys/queue.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/un.h>
|
|
#include <sys/uio.h>
|
|
#include <net/if.h>
|
|
#include <net/if_dl.h>
|
|
#include <netinet/in.h>
|
|
#include <netinet/icmp6.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <netdb.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <syslog.h>
|
|
|
|
#include "pathnames.h"
|
|
#include "rtadvd.h"
|
|
#include "if.h"
|
|
#include "config.h"
|
|
#include "control.h"
|
|
#include "control_server.h"
|
|
#include "timer.h"
|
|
|
|
static char *do_reload_ifname;
|
|
static int do_reload;
|
|
static int do_shutdown;
|
|
|
|
void set_do_reload(int sig __unused) { do_reload = 1; }
|
|
void set_do_reload_ifname(char *ifname){ do_reload_ifname = ifname; }
|
|
void set_do_shutdown(int sig __unused) { do_shutdown = 1; }
|
|
void reset_do_reload(void) { do_reload = 0; do_reload_ifname = NULL; }
|
|
void reset_do_shutdown(void) { do_shutdown = 0; }
|
|
int is_do_reload(void) { return (do_reload); }
|
|
int is_do_shutdown(void) { return (do_shutdown); }
|
|
char *reload_ifname(void) { return (do_reload_ifname); }
|
|
|
|
#define DEF_PL_HANDLER(key) { #key, cm_getprop_##key }
|
|
|
|
static int cm_getprop_echo(struct ctrl_msg_pl *);
|
|
static int cm_getprop_version(struct ctrl_msg_pl *);
|
|
static int cm_getprop_ifilist(struct ctrl_msg_pl *);
|
|
static int cm_getprop_ifi(struct ctrl_msg_pl *);
|
|
static int cm_getprop_ifi_ra_timer(struct ctrl_msg_pl *);
|
|
static int cm_getprop_rai(struct ctrl_msg_pl *);
|
|
static int cm_getprop_pfx(struct ctrl_msg_pl *);
|
|
static int cm_getprop_rdnss(struct ctrl_msg_pl *);
|
|
static int cm_getprop_dnssl(struct ctrl_msg_pl *);
|
|
static int cm_getprop_rti(struct ctrl_msg_pl *);
|
|
|
|
static int cm_setprop_reload(struct ctrl_msg_pl *);
|
|
static int cm_setprop_enable(struct ctrl_msg_pl *);
|
|
static int cm_setprop_disable(struct ctrl_msg_pl *);
|
|
|
|
static struct dispatch_table {
|
|
const char *dt_comm;
|
|
int (*dt_act)(struct ctrl_msg_pl *cp);
|
|
} getprop_dtable[] = {
|
|
{ "", cm_getprop_echo },
|
|
DEF_PL_HANDLER(echo),
|
|
DEF_PL_HANDLER(version),
|
|
DEF_PL_HANDLER(ifilist),
|
|
DEF_PL_HANDLER(ifi),
|
|
DEF_PL_HANDLER(ifi_ra_timer),
|
|
DEF_PL_HANDLER(rai),
|
|
DEF_PL_HANDLER(rti),
|
|
DEF_PL_HANDLER(pfx),
|
|
DEF_PL_HANDLER(rdnss),
|
|
DEF_PL_HANDLER(dnssl),
|
|
};
|
|
|
|
static int
|
|
cm_getprop_echo(struct ctrl_msg_pl *cp)
|
|
{
|
|
|
|
syslog(LOG_DEBUG, "<%s> enter", __func__);
|
|
cp->cp_val = strdup("");
|
|
cp->cp_val_len = strlen(cp->cp_val) + 1;
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
cm_getprop_version(struct ctrl_msg_pl *cp)
|
|
{
|
|
|
|
syslog(LOG_DEBUG, "<%s> enter", __func__);
|
|
cp->cp_val = strdup(CM_VERSION_STR);
|
|
cp->cp_val_len = strlen(cp->cp_val) + 1;
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
cm_getprop_ifilist(struct ctrl_msg_pl *cp)
|
|
{
|
|
struct ifinfo *ifi;
|
|
char *p;
|
|
size_t len;
|
|
|
|
syslog(LOG_DEBUG, "<%s> enter", __func__);
|
|
|
|
len = 0;
|
|
TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
|
|
len += strlen(ifi->ifi_ifname) + 1;
|
|
}
|
|
|
|
syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
|
|
|
|
p = malloc(len);
|
|
if (p == NULL)
|
|
exit(1);
|
|
memset(p, 0, len);
|
|
cp->cp_val = p;
|
|
|
|
if (len > 0)
|
|
TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
|
|
syslog(LOG_DEBUG, "<%s> add ifname=%s(%d)",
|
|
__func__, ifi->ifi_ifname, ifi->ifi_ifindex);
|
|
strcpy(p, ifi->ifi_ifname);
|
|
p += strlen(ifi->ifi_ifname) + 1;
|
|
}
|
|
cp->cp_val_len = p - cp->cp_val;
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
cm_getprop_ifi(struct ctrl_msg_pl *cp)
|
|
{
|
|
struct ifinfo *ifi;
|
|
char *p;
|
|
size_t len;
|
|
|
|
syslog(LOG_DEBUG, "<%s> enter", __func__);
|
|
|
|
TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
|
|
if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
|
|
break;
|
|
}
|
|
if (ifi == NULL) {
|
|
syslog(LOG_ERR, "<%s> %s not found", __func__,
|
|
cp->cp_ifname);
|
|
return (1);
|
|
}
|
|
|
|
p = malloc(sizeof(*ifi));
|
|
if (p == NULL)
|
|
exit(1);
|
|
len = cm_str2bin(p, ifi, sizeof(*ifi));
|
|
|
|
syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
|
|
|
|
if (len == 0)
|
|
return (1);
|
|
|
|
cp->cp_val = p;
|
|
cp->cp_val_len = len;
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
cm_getprop_rai(struct ctrl_msg_pl *cp)
|
|
{
|
|
struct ifinfo *ifi;
|
|
struct rainfo *rai;
|
|
char *p;
|
|
size_t len;
|
|
|
|
syslog(LOG_DEBUG, "<%s> enter", __func__);
|
|
|
|
TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
|
|
if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
|
|
break;
|
|
}
|
|
if (ifi == NULL) {
|
|
syslog(LOG_ERR, "<%s> %s not found", __func__,
|
|
cp->cp_ifname);
|
|
return (1);
|
|
}
|
|
if ((rai = ifi->ifi_rainfo) == NULL) {
|
|
syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
|
|
cp->cp_ifname);
|
|
return (1);
|
|
}
|
|
|
|
p = malloc(sizeof(*rai));
|
|
if (p == NULL)
|
|
exit(1);
|
|
len = cm_str2bin(p, rai, sizeof(*rai));
|
|
|
|
syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
|
|
|
|
if (len == 0)
|
|
return (1);
|
|
|
|
cp->cp_val = p;
|
|
cp->cp_val_len = len;
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
cm_getprop_ifi_ra_timer(struct ctrl_msg_pl *cp)
|
|
{
|
|
struct ifinfo *ifi;
|
|
struct rainfo *rai;
|
|
struct rtadvd_timer *rtimer;
|
|
char *p;
|
|
size_t len;
|
|
|
|
syslog(LOG_DEBUG, "<%s> enter", __func__);
|
|
|
|
TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
|
|
if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
|
|
break;
|
|
}
|
|
if (ifi == NULL) {
|
|
syslog(LOG_ERR, "<%s> %s not found", __func__,
|
|
cp->cp_ifname);
|
|
return (1);
|
|
}
|
|
if ((rai = ifi->ifi_rainfo) == NULL) {
|
|
syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
|
|
cp->cp_ifname);
|
|
return (1);
|
|
}
|
|
if ((rtimer = ifi->ifi_ra_timer) == NULL) {
|
|
syslog(LOG_ERR, "<%s> %s has no ifi_ra_timer", __func__,
|
|
cp->cp_ifname);
|
|
return (1);
|
|
}
|
|
p = malloc(sizeof(*rtimer));
|
|
if (p == NULL)
|
|
exit(1);
|
|
len = cm_str2bin(p, rtimer, sizeof(*rtimer));
|
|
|
|
syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
|
|
|
|
if (len == 0)
|
|
return (1);
|
|
|
|
cp->cp_val = p;
|
|
cp->cp_val_len = len;
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
cm_getprop_rti(struct ctrl_msg_pl *cp)
|
|
{
|
|
struct ifinfo *ifi;
|
|
struct rainfo *rai;
|
|
struct rtinfo *rti;
|
|
char *p;
|
|
size_t len;
|
|
|
|
syslog(LOG_DEBUG, "<%s> enter", __func__);
|
|
|
|
len = 0;
|
|
TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
|
|
if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
|
|
break;
|
|
}
|
|
if (ifi == NULL) {
|
|
syslog(LOG_ERR, "<%s> %s not found", __func__,
|
|
cp->cp_ifname);
|
|
return (1);
|
|
}
|
|
if (ifi->ifi_rainfo == NULL) {
|
|
syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
|
|
cp->cp_ifname);
|
|
return (1);
|
|
}
|
|
rai = ifi->ifi_rainfo;
|
|
TAILQ_FOREACH(rti, &rai->rai_route, rti_next) {
|
|
len += sizeof(*rti);
|
|
}
|
|
|
|
syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
|
|
|
|
p = malloc(len);
|
|
if (p == NULL)
|
|
exit(1);
|
|
memset(p, 0, len);
|
|
cp->cp_val = p;
|
|
|
|
if (len > 0)
|
|
TAILQ_FOREACH(rti, &rai->rai_route, rti_next) {
|
|
memcpy(p, rti, sizeof(*rti));
|
|
p += sizeof(*rti);
|
|
}
|
|
cp->cp_val_len = p - cp->cp_val;
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
cm_getprop_pfx(struct ctrl_msg_pl *cp)
|
|
{
|
|
struct ifinfo *ifi;
|
|
struct rainfo *rai;
|
|
struct prefix *pfx;
|
|
char *p;
|
|
size_t len;
|
|
|
|
syslog(LOG_DEBUG, "<%s> enter", __func__);
|
|
|
|
len = 0;
|
|
TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
|
|
if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
|
|
break;
|
|
}
|
|
if (ifi == NULL) {
|
|
syslog(LOG_ERR, "<%s> %s not found", __func__,
|
|
cp->cp_ifname);
|
|
return (1);
|
|
}
|
|
if (ifi->ifi_rainfo == NULL) {
|
|
syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
|
|
cp->cp_ifname);
|
|
return (1);
|
|
}
|
|
rai = ifi->ifi_rainfo;
|
|
TAILQ_FOREACH(pfx, &rai->rai_prefix, pfx_next) {
|
|
len += sizeof(*pfx);
|
|
}
|
|
|
|
syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
|
|
|
|
p = malloc(len);
|
|
if (p == NULL)
|
|
exit(1);
|
|
memset(p, 0, len);
|
|
cp->cp_val = p;
|
|
|
|
if (len > 0)
|
|
TAILQ_FOREACH(pfx, &rai->rai_prefix, pfx_next) {
|
|
memcpy(p, pfx, sizeof(*pfx));
|
|
p += sizeof(*pfx);
|
|
}
|
|
cp->cp_val_len = p - cp->cp_val;
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
cm_getprop_rdnss(struct ctrl_msg_pl *cp)
|
|
{
|
|
struct ifinfo *ifi;
|
|
struct rainfo *rai;
|
|
struct rdnss *rdn;
|
|
struct rdnss_addr *rda;
|
|
char *p;
|
|
size_t len;
|
|
uint16_t *rdn_cnt;
|
|
uint16_t *rda_cnt;
|
|
|
|
syslog(LOG_DEBUG, "<%s> enter", __func__);
|
|
|
|
len = 0;
|
|
TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
|
|
if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
|
|
break;
|
|
}
|
|
if (ifi == NULL) {
|
|
syslog(LOG_ERR, "<%s> %s not found", __func__,
|
|
cp->cp_ifname);
|
|
return (1);
|
|
}
|
|
if (ifi->ifi_rainfo == NULL) {
|
|
syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
|
|
cp->cp_ifname);
|
|
return (1);
|
|
}
|
|
rai = ifi->ifi_rainfo;
|
|
|
|
len = sizeof(*rdn_cnt);
|
|
TAILQ_FOREACH(rdn, &rai->rai_rdnss, rd_next) {
|
|
len += sizeof(*rdn);
|
|
len += sizeof(*rda_cnt);
|
|
TAILQ_FOREACH(rda, &rdn->rd_list, ra_next) {
|
|
len += sizeof(*rda);
|
|
}
|
|
}
|
|
|
|
syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
|
|
|
|
p = malloc(len);
|
|
if (p == NULL)
|
|
exit(1);
|
|
memset(p, 0, len);
|
|
cp->cp_val = p;
|
|
|
|
rdn_cnt = (uint16_t *)p;
|
|
p += sizeof(*rdn_cnt);
|
|
TAILQ_FOREACH(rdn, &rai->rai_rdnss, rd_next) {
|
|
*rdn_cnt += 1;
|
|
memcpy(p, rdn, sizeof(*rdn));
|
|
p += sizeof(*rdn);
|
|
|
|
rda_cnt = (uint16_t *)p;
|
|
p += sizeof(*rda_cnt);
|
|
TAILQ_FOREACH(rda, &rdn->rd_list, ra_next) {
|
|
*rda_cnt += 1;
|
|
memcpy(p, rda, sizeof(*rda));
|
|
p += sizeof(*rda);
|
|
}
|
|
}
|
|
syslog(LOG_DEBUG, "<%s> rdn_cnt = %d", __func__, *rdn_cnt);
|
|
cp->cp_val_len = p - cp->cp_val;
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
cm_getprop_dnssl(struct ctrl_msg_pl *cp)
|
|
{
|
|
struct ifinfo *ifi;
|
|
struct rainfo *rai;
|
|
struct dnssl *dns;
|
|
struct dnssl_addr *dna;
|
|
char *p;
|
|
size_t len;
|
|
uint16_t *dns_cnt;
|
|
uint16_t *dna_cnt;
|
|
|
|
syslog(LOG_DEBUG, "<%s> enter", __func__);
|
|
|
|
len = 0;
|
|
TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
|
|
if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
|
|
break;
|
|
}
|
|
if (ifi == NULL) {
|
|
syslog(LOG_ERR, "<%s> %s not found", __func__,
|
|
cp->cp_ifname);
|
|
return (1);
|
|
}
|
|
if (ifi->ifi_rainfo == NULL) {
|
|
syslog(LOG_ERR, "<%s> %s has no rainfo", __func__,
|
|
cp->cp_ifname);
|
|
return (1);
|
|
}
|
|
rai = ifi->ifi_rainfo;
|
|
|
|
len = sizeof(*dns_cnt);
|
|
TAILQ_FOREACH(dns, &rai->rai_dnssl, dn_next) {
|
|
len += sizeof(*dns);
|
|
len += sizeof(*dna_cnt);
|
|
TAILQ_FOREACH(dna, &dns->dn_list, da_next) {
|
|
len += sizeof(*dna);
|
|
}
|
|
}
|
|
|
|
syslog(LOG_DEBUG, "<%s> len = %zu", __func__, len);
|
|
|
|
p = malloc(len);
|
|
if (p == NULL)
|
|
exit(1);
|
|
memset(p, 0, len);
|
|
cp->cp_val = p;
|
|
|
|
dns_cnt = (uint16_t *)cp->cp_val;
|
|
p += sizeof(*dns_cnt);
|
|
TAILQ_FOREACH(dns, &rai->rai_dnssl, dn_next) {
|
|
(*dns_cnt)++;
|
|
memcpy(p, dns, sizeof(*dns));
|
|
p += sizeof(*dns);
|
|
|
|
dna_cnt = (uint16_t *)p;
|
|
p += sizeof(*dna_cnt);
|
|
TAILQ_FOREACH(dna, &dns->dn_list, da_next) {
|
|
(*dna_cnt)++;
|
|
memcpy(p, dna, sizeof(*dna));
|
|
p += sizeof(*dna);
|
|
}
|
|
}
|
|
cp->cp_val_len = p - cp->cp_val;
|
|
|
|
return (0);
|
|
}
|
|
|
|
int
|
|
cm_getprop(struct ctrl_msg_pl *cp)
|
|
{
|
|
size_t i;
|
|
|
|
syslog(LOG_DEBUG, "<%s> enter", __func__);
|
|
|
|
if (cp == NULL)
|
|
return (1);
|
|
|
|
for (i = 0;
|
|
i < sizeof(getprop_dtable) / sizeof(getprop_dtable[0]);
|
|
i++) {
|
|
if (strcmp(cp->cp_key, getprop_dtable[i].dt_comm) == 0)
|
|
return (getprop_dtable[i].dt_act(cp));
|
|
}
|
|
return (1);
|
|
}
|
|
|
|
int
|
|
cm_setprop(struct ctrl_msg_pl *cp)
|
|
{
|
|
syslog(LOG_DEBUG, "<%s> enter", __func__);
|
|
|
|
if (cp == NULL || cp->cp_key == NULL)
|
|
return (1);
|
|
|
|
if (strncmp(cp->cp_key, "reload", sizeof("reload")) == 0)
|
|
cm_setprop_reload(cp);
|
|
else if (strncmp(cp->cp_key, "shutdown", sizeof("shutdown")) == 0)
|
|
set_do_shutdown(0);
|
|
else if (strncmp(cp->cp_key, "enable", sizeof("enable")) == 0)
|
|
cm_setprop_enable(cp);
|
|
else if (strncmp(cp->cp_key, "disable", sizeof("disable")) == 0)
|
|
cm_setprop_disable(cp);
|
|
else if (strncmp(cp->cp_key, "echo", 8) == 0)
|
|
; /* do nothing */
|
|
else
|
|
return (1);
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
cm_setprop_reload(struct ctrl_msg_pl *cp)
|
|
{
|
|
|
|
syslog(LOG_DEBUG, "<%s> enter", __func__);
|
|
|
|
set_do_reload_ifname(cp->cp_ifname);
|
|
set_do_reload(1);
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
cm_setprop_enable(struct ctrl_msg_pl *cp)
|
|
{
|
|
struct ifinfo *ifi;
|
|
|
|
syslog(LOG_DEBUG, "<%s> enter", __func__);
|
|
|
|
TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
|
|
if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
|
|
break;
|
|
}
|
|
if (ifi == NULL) {
|
|
syslog(LOG_ERR, "<%s> %s not found", __func__,
|
|
cp->cp_ifname);
|
|
return (1);
|
|
}
|
|
|
|
ifi->ifi_persist = 1;
|
|
set_do_reload_ifname(ifi->ifi_ifname);
|
|
set_do_reload(0);
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
cm_setprop_disable(struct ctrl_msg_pl *cp)
|
|
{
|
|
struct ifinfo *ifi;
|
|
|
|
syslog(LOG_DEBUG, "<%s> enter", __func__);
|
|
|
|
TAILQ_FOREACH(ifi, &ifilist, ifi_next) {
|
|
if (strcmp(cp->cp_ifname, ifi->ifi_ifname) == 0)
|
|
break;
|
|
}
|
|
if (ifi == NULL) {
|
|
syslog(LOG_ERR, "<%s> %s not found", __func__,
|
|
cp->cp_ifname);
|
|
return (1);
|
|
}
|
|
|
|
if (ifi->ifi_persist == 1) {
|
|
ifi->ifi_persist = 0;
|
|
rm_ifinfo(ifi);
|
|
|
|
/* MC leaving needed here */
|
|
sock_mc_leave(&sock, ifi->ifi_ifindex);
|
|
|
|
set_do_reload_ifname(ifi->ifi_ifname);
|
|
set_do_reload(0);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int
|
|
cm_handler_server(int fd)
|
|
{
|
|
int state;
|
|
char *msg;
|
|
struct ctrl_msg_hdr *cm;
|
|
struct ctrl_msg_pl cp;
|
|
char buf[CM_MSG_MAXLEN];
|
|
char pbuf[CM_MSG_MAXLEN];
|
|
int error;
|
|
|
|
syslog(LOG_DEBUG, "<%s> enter", __func__);
|
|
|
|
memset(buf, 0, sizeof(buf));
|
|
memset(pbuf, 0, sizeof(pbuf));
|
|
cm = (struct ctrl_msg_hdr *)buf;
|
|
msg = (char *)buf + sizeof(*cm);
|
|
|
|
state = CM_STATE_INIT;
|
|
while (state != CM_STATE_EOM) {
|
|
syslog(LOG_DEBUG, "<%s> state = %d", __func__, state);
|
|
|
|
switch (state) {
|
|
case CM_STATE_INIT:
|
|
state = CM_STATE_MSG_RECV;
|
|
break;
|
|
case CM_STATE_MSG_DISPATCH:
|
|
cm->cm_version = CM_VERSION;
|
|
error = cm_send(fd, buf);
|
|
if (error)
|
|
syslog(LOG_WARNING,
|
|
"<%s> cm_send()", __func__);
|
|
state = CM_STATE_EOM;
|
|
break;
|
|
case CM_STATE_ACK_WAIT:
|
|
error = cm_recv(fd, buf);
|
|
if (error) {
|
|
syslog(LOG_ERR,
|
|
"<%s> cm_recv()", __func__);
|
|
close(fd);
|
|
return (-1);
|
|
}
|
|
|
|
switch (cm->cm_type) {
|
|
case CM_TYPE_ACK:
|
|
break;
|
|
case CM_TYPE_ERR:
|
|
syslog(LOG_DEBUG,
|
|
"<%s> CM_TYPE_ERR", __func__);
|
|
close(fd);
|
|
return (-1);
|
|
default:
|
|
syslog(LOG_DEBUG,
|
|
"<%s> unknown status", __func__);
|
|
close(fd);
|
|
return (-1);
|
|
}
|
|
state = CM_STATE_EOM;
|
|
break;
|
|
case CM_STATE_MSG_RECV:
|
|
error = cm_recv(fd, buf);
|
|
|
|
if (error) {
|
|
syslog(LOG_ERR,
|
|
"<%s> cm_recv()", __func__);
|
|
close(fd);
|
|
return (-1);
|
|
}
|
|
memset(&cp, 0, sizeof(cp));
|
|
|
|
syslog(LOG_DEBUG,
|
|
"<%s> cm->cm_type = %d", __func__, cm->cm_type);
|
|
syslog(LOG_DEBUG,
|
|
"<%s> cm->cm_len = %zu", __func__, cm->cm_len);
|
|
|
|
switch (cm->cm_type) {
|
|
case CM_TYPE_EOM:
|
|
state = CM_STATE_EOM;
|
|
case CM_TYPE_NUL:
|
|
cm->cm_type = CM_TYPE_ACK;
|
|
cm->cm_len = sizeof(*cm);
|
|
break;
|
|
case CM_TYPE_REQ_GET_PROP:
|
|
cm_bin2pl(msg, &cp);
|
|
error = cm_getprop(&cp);
|
|
if (error) {
|
|
cm->cm_type = CM_TYPE_ERR;
|
|
cm->cm_len = sizeof(*cm);
|
|
} else {
|
|
cm->cm_type = CM_TYPE_ACK;
|
|
cm->cm_len = sizeof(*cm);
|
|
cm->cm_len += cm_pl2bin(msg, &cp);
|
|
}
|
|
if (cp.cp_val != NULL)
|
|
free(cp.cp_val);
|
|
break;
|
|
case CM_TYPE_REQ_SET_PROP:
|
|
cm_bin2pl(msg, &cp);
|
|
error = cm_setprop(&cp);
|
|
if (error) {
|
|
cm->cm_type = CM_TYPE_ERR;
|
|
cm->cm_len = sizeof(*cm);
|
|
} else {
|
|
cm->cm_type = CM_TYPE_ACK;
|
|
cm->cm_len = sizeof(*cm);
|
|
}
|
|
break;
|
|
default:
|
|
cm->cm_type = CM_TYPE_ERR;
|
|
cm->cm_len = sizeof(*cm);
|
|
}
|
|
|
|
switch (cm->cm_type) {
|
|
case CM_TYPE_ERR:
|
|
case CM_TYPE_ACK:
|
|
state = CM_STATE_MSG_DISPATCH;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
syslog(LOG_DEBUG, "<%s> leave", __func__);
|
|
|
|
return (0);
|
|
}
|