mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00
zebra: support DNS configuration options in rtadv
Add support for the RDNSS and DNSSL router advertisement options described in RFC 8106. Signed-off-by: Lars Seipel <ls@slrz.net>
This commit is contained in:
parent
41e8603bfa
commit
3eb4fbb0f5
|
@ -1738,7 +1738,8 @@ AC_CHECK_TYPES([
|
|||
vifi_t, struct sioc_vif_req, struct igmpmsg,
|
||||
struct ifaliasreq, struct if6_aliasreq, struct in6_aliasreq,
|
||||
struct nd_opt_adv_interval, struct rt_addrinfo,
|
||||
struct nd_opt_homeagent_info, struct nd_opt_adv_interval],
|
||||
struct nd_opt_homeagent_info, struct nd_opt_adv_interval,
|
||||
struct nd_opt_rdnss, struct nd_opt_dnssl],
|
||||
[], [], FRR_INCLUDES)
|
||||
|
||||
AC_CHECK_MEMBERS([struct sockaddr.sa_len,
|
||||
|
|
|
@ -135,6 +135,8 @@ static int if_zebra_new_hook(struct interface *ifp)
|
|||
rtadv->DefaultPreference = RTADV_PREF_MEDIUM;
|
||||
|
||||
rtadv->AdvPrefixList = list_new();
|
||||
rtadv->AdvRDNSSList = list_new();
|
||||
rtadv->AdvDNSSLList = list_new();
|
||||
}
|
||||
#endif /* HAVE_RTADV */
|
||||
|
||||
|
@ -175,6 +177,8 @@ static int if_zebra_delete_hook(struct interface *ifp)
|
|||
|
||||
rtadv = &zebra_if->rtadv;
|
||||
list_delete(&rtadv->AdvPrefixList);
|
||||
list_delete(&rtadv->AdvRDNSSList);
|
||||
list_delete(&rtadv->AdvDNSSLList);
|
||||
#endif /* HAVE_RTADV */
|
||||
|
||||
THREAD_OFF(zebra_if->speed_update);
|
||||
|
|
|
@ -168,6 +168,22 @@ struct rtadvconf {
|
|||
int DefaultPreference;
|
||||
#define RTADV_PREF_MEDIUM 0x0 /* Per RFC4191. */
|
||||
|
||||
/*
|
||||
* List of recursive DNS servers to include in the RDNSS option.
|
||||
* See [RFC8106 5.1]
|
||||
*
|
||||
* Default: empty list; do not emit RDNSS option
|
||||
*/
|
||||
struct list *AdvRDNSSList;
|
||||
|
||||
/*
|
||||
* List of DNS search domains to include in the DNSSL option.
|
||||
* See [RFC8106 5.2]
|
||||
*
|
||||
* Default: empty list; do not emit DNSSL option
|
||||
*/
|
||||
struct list *AdvDNSSLList;
|
||||
|
||||
uint8_t inFastRexmit; /* True if we're rexmits faster than usual */
|
||||
|
||||
/* Track if RA was configured by BGP or by the Operator or both */
|
||||
|
@ -182,6 +198,41 @@ struct rtadvconf {
|
|||
#define RTADV_NUM_FAST_REXMITS 4 /* Fast Rexmit RA 4 times on certain events */
|
||||
};
|
||||
|
||||
struct rtadv_rdnss {
|
||||
/* Address of recursive DNS server to advertise */
|
||||
struct in6_addr addr;
|
||||
|
||||
/*
|
||||
* Lifetime in seconds; all-ones means infinity, zero
|
||||
* stop using it.
|
||||
*/
|
||||
uint32_t lifetime;
|
||||
|
||||
/* If lifetime not set, use a default of 3*MaxRtrAdvInterval */
|
||||
int lifetime_set;
|
||||
};
|
||||
|
||||
/*
|
||||
* [RFC1035 2.3.4] sets the maximum length of a domain name (a sequence of
|
||||
* labels, each prefixed by a length octet) at 255 octets.
|
||||
*/
|
||||
#define RTADV_MAX_ENCODED_DOMAIN_NAME 255
|
||||
|
||||
struct rtadv_dnssl {
|
||||
/* Domain name without trailing root zone dot (NUL-terminated) */
|
||||
char name[RTADV_MAX_ENCODED_DOMAIN_NAME - 1];
|
||||
|
||||
/* Name encoded as in [RFC1035 3.1] */
|
||||
uint8_t encoded_name[RTADV_MAX_ENCODED_DOMAIN_NAME];
|
||||
|
||||
/* Actual length of encoded_name */
|
||||
size_t encoded_len;
|
||||
|
||||
/* Lifetime as for RDNSS */
|
||||
uint32_t lifetime;
|
||||
int lifetime_set;
|
||||
};
|
||||
|
||||
#endif /* HAVE_RTADV */
|
||||
|
||||
/* Zebra interface type - ones of interest. */
|
||||
|
|
378
zebra/rtadv.c
378
zebra/rtadv.c
|
@ -355,6 +355,53 @@ static void rtadv_send_packet(int sock, struct interface *ifp)
|
|||
len += sizeof(struct nd_opt_mtu);
|
||||
}
|
||||
|
||||
/* Recursive DNS servers */
|
||||
struct rtadv_rdnss *rdnss;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvRDNSSList, node, rdnss)) {
|
||||
struct nd_opt_rdnss *opt = (struct nd_opt_rdnss *)(buf + len);
|
||||
|
||||
opt->nd_opt_rdnss_type = ND_OPT_RDNSS;
|
||||
opt->nd_opt_rdnss_len = 3;
|
||||
opt->nd_opt_rdnss_reserved = 0;
|
||||
opt->nd_opt_rdnss_lifetime = htonl(
|
||||
rdnss->lifetime_set
|
||||
? rdnss->lifetime
|
||||
: MAX(1, 0.003 * zif->rtadv.MaxRtrAdvInterval));
|
||||
|
||||
len += sizeof(struct nd_opt_rdnss);
|
||||
IPV6_ADDR_COPY(buf + len, &rdnss->addr);
|
||||
len += sizeof(struct in6_addr);
|
||||
}
|
||||
|
||||
/* DNS search list */
|
||||
struct rtadv_dnssl *dnssl;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvDNSSLList, node, dnssl)) {
|
||||
size_t names_start;
|
||||
struct nd_opt_dnssl *opt = (struct nd_opt_dnssl *)(buf + len);
|
||||
|
||||
opt->nd_opt_dnssl_type = ND_OPT_DNSSL;
|
||||
opt->nd_opt_dnssl_len = 1;
|
||||
opt->nd_opt_dnssl_reserved = 0;
|
||||
opt->nd_opt_dnssl_lifetime = htonl(
|
||||
dnssl->lifetime_set
|
||||
? dnssl->lifetime
|
||||
: MAX(1, 0.003 * zif->rtadv.MaxRtrAdvInterval));
|
||||
|
||||
len += sizeof(struct nd_opt_dnssl);
|
||||
|
||||
names_start = len;
|
||||
memcpy(buf + len, dnssl->encoded_name, dnssl->encoded_len);
|
||||
len += dnssl->encoded_len;
|
||||
|
||||
/* Zero-pad to 8-octet boundary */
|
||||
while (len % 8)
|
||||
buf[len++] = '\0';
|
||||
|
||||
opt->nd_opt_dnssl_len += (len - names_start) / 8;
|
||||
}
|
||||
|
||||
msg.msg_name = (void *)&addr;
|
||||
msg.msg_namelen = sizeof(struct sockaddr_in6);
|
||||
msg.msg_iov = &iov;
|
||||
|
@ -1533,6 +1580,308 @@ DEFUN (no_ipv6_nd_mtu,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static struct rtadv_rdnss *rtadv_rdnss_new(void)
|
||||
{
|
||||
return XCALLOC(MTYPE_RTADV_RDNSS, sizeof(struct rtadv_rdnss));
|
||||
}
|
||||
|
||||
static void rtadv_rdnss_free(struct rtadv_rdnss *rdnss)
|
||||
{
|
||||
XFREE(MTYPE_RTADV_RDNSS, rdnss);
|
||||
}
|
||||
|
||||
static struct rtadv_rdnss *rtadv_rdnss_lookup(struct list *list,
|
||||
struct rtadv_rdnss *rdnss)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct rtadv_rdnss *p;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(list, node, p))
|
||||
if (IPV6_ADDR_SAME(&p->addr, &rdnss->addr))
|
||||
return p;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct rtadv_rdnss *rtadv_rdnss_get(struct list *list,
|
||||
struct rtadv_rdnss *rdnss)
|
||||
{
|
||||
struct rtadv_rdnss *p;
|
||||
|
||||
p = rtadv_rdnss_lookup(list, rdnss);
|
||||
if (p)
|
||||
return p;
|
||||
|
||||
p = rtadv_rdnss_new();
|
||||
memcpy(p, rdnss, sizeof(struct rtadv_rdnss));
|
||||
listnode_add(list, p);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static void rtadv_rdnss_set(struct zebra_if *zif, struct rtadv_rdnss *rdnss)
|
||||
{
|
||||
struct rtadv_rdnss *p;
|
||||
|
||||
p = rtadv_rdnss_get(zif->rtadv.AdvRDNSSList, rdnss);
|
||||
p->lifetime = rdnss->lifetime;
|
||||
p->lifetime_set = rdnss->lifetime_set;
|
||||
}
|
||||
|
||||
static int rtadv_rdnss_reset(struct zebra_if *zif, struct rtadv_rdnss *rdnss)
|
||||
{
|
||||
struct rtadv_rdnss *p;
|
||||
|
||||
p = rtadv_rdnss_lookup(zif->rtadv.AdvRDNSSList, rdnss);
|
||||
if (p) {
|
||||
listnode_delete(zif->rtadv.AdvRDNSSList, p);
|
||||
rtadv_rdnss_free(p);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct rtadv_dnssl *rtadv_dnssl_new(void)
|
||||
{
|
||||
return XCALLOC(MTYPE_RTADV_DNSSL, sizeof(struct rtadv_dnssl));
|
||||
}
|
||||
|
||||
static void rtadv_dnssl_free(struct rtadv_dnssl *dnssl)
|
||||
{
|
||||
XFREE(MTYPE_RTADV_DNSSL, dnssl);
|
||||
}
|
||||
|
||||
static struct rtadv_dnssl *rtadv_dnssl_lookup(struct list *list,
|
||||
struct rtadv_dnssl *dnssl)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct rtadv_dnssl *p;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(list, node, p))
|
||||
if (!strcasecmp(p->name, dnssl->name))
|
||||
return p;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct rtadv_dnssl *rtadv_dnssl_get(struct list *list,
|
||||
struct rtadv_dnssl *dnssl)
|
||||
{
|
||||
struct rtadv_dnssl *p;
|
||||
|
||||
p = rtadv_dnssl_lookup(list, dnssl);
|
||||
if (p)
|
||||
return p;
|
||||
|
||||
p = rtadv_dnssl_new();
|
||||
memcpy(p, dnssl, sizeof(struct rtadv_dnssl));
|
||||
listnode_add(list, p);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static void rtadv_dnssl_set(struct zebra_if *zif, struct rtadv_dnssl *dnssl)
|
||||
{
|
||||
struct rtadv_dnssl *p;
|
||||
|
||||
p = rtadv_dnssl_get(zif->rtadv.AdvDNSSLList, dnssl);
|
||||
memcpy(p, dnssl, sizeof(struct rtadv_dnssl));
|
||||
}
|
||||
|
||||
static int rtadv_dnssl_reset(struct zebra_if *zif, struct rtadv_dnssl *dnssl)
|
||||
{
|
||||
struct rtadv_dnssl *p;
|
||||
|
||||
p = rtadv_dnssl_lookup(zif->rtadv.AdvDNSSLList, dnssl);
|
||||
if (p) {
|
||||
listnode_delete(zif->rtadv.AdvDNSSLList, p);
|
||||
rtadv_dnssl_free(p);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert dotted domain name (with or without trailing root zone dot) to
|
||||
* sequence of length-prefixed labels, as described in [RFC1035 3.1]. Write up
|
||||
* to strlen(in) + 2 octets to out.
|
||||
*
|
||||
* Returns the number of octets written to out or -1 if in does not constitute
|
||||
* a valid domain name.
|
||||
*/
|
||||
static int rtadv_dnssl_encode(uint8_t *out, const char *in)
|
||||
{
|
||||
const char *label_start, *label_end;
|
||||
size_t outp;
|
||||
|
||||
outp = 0;
|
||||
label_start = in;
|
||||
|
||||
while (*label_start) {
|
||||
size_t label_len;
|
||||
|
||||
label_end = strchr(label_start, '.');
|
||||
if (label_end == NULL)
|
||||
label_end = label_start + strlen(label_start);
|
||||
|
||||
label_len = label_end - label_start;
|
||||
if (label_len >= 64)
|
||||
return -1; /* labels must be 63 octets or less */
|
||||
|
||||
out[outp++] = (uint8_t)label_len;
|
||||
memcpy(out + outp, label_start, label_len);
|
||||
outp += label_len;
|
||||
label_start += label_len;
|
||||
if (*label_start == '.')
|
||||
label_start++;
|
||||
}
|
||||
|
||||
out[outp++] = '\0';
|
||||
return outp;
|
||||
}
|
||||
|
||||
DEFUN(ipv6_nd_rdnss,
|
||||
ipv6_nd_rdnss_cmd,
|
||||
"ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
|
||||
"Interface IPv6 config commands\n"
|
||||
"Neighbor discovery\n"
|
||||
"Recursive DNS server information\n"
|
||||
"IPv6 address\n"
|
||||
"Valid lifetime in seconds\n"
|
||||
"Infinite valid lifetime\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
struct zebra_if *zif = ifp->info;
|
||||
struct rtadv_rdnss rdnss = {0};
|
||||
|
||||
if (inet_pton(AF_INET6, argv[3]->arg, &rdnss.addr) != 1) {
|
||||
vty_out(vty, "Malformed IPv6 address\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
if (argc > 4) {
|
||||
char *lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
|
||||
: argv[4]->text;
|
||||
rdnss.lifetime = strmatch(lifetime, "infinite")
|
||||
? UINT32_MAX
|
||||
: strtoll(lifetime, NULL, 10);
|
||||
rdnss.lifetime_set = 1;
|
||||
}
|
||||
|
||||
rtadv_rdnss_set(zif, &rdnss);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(no_ipv6_nd_rdnss,
|
||||
no_ipv6_nd_rdnss_cmd,
|
||||
"no ipv6 nd rdnss X:X::X:X [<(0-4294967295)|infinite>]",
|
||||
NO_STR
|
||||
"Interface IPv6 config commands\n"
|
||||
"Neighbor discovery\n"
|
||||
"Recursive DNS server information\n"
|
||||
"IPv6 address\n"
|
||||
"Valid lifetime in seconds\n"
|
||||
"Infinite valid lifetime\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
struct zebra_if *zif = ifp->info;
|
||||
struct rtadv_rdnss rdnss = {0};
|
||||
|
||||
if (inet_pton(AF_INET6, argv[4]->arg, &rdnss.addr) != 1) {
|
||||
vty_out(vty, "Malformed IPv6 address\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
if (rtadv_rdnss_reset(zif, &rdnss) != 1) {
|
||||
vty_out(vty, "Non-existant RDNSS address\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(ipv6_nd_dnssl,
|
||||
ipv6_nd_dnssl_cmd,
|
||||
"ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
|
||||
"Interface IPv6 config commands\n"
|
||||
"Neighbor discovery\n"
|
||||
"DNS search list information\n"
|
||||
"Domain name suffix\n"
|
||||
"Valid lifetime in seconds\n"
|
||||
"Infinite valid lifetime\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
struct zebra_if *zif = ifp->info;
|
||||
struct rtadv_dnssl dnssl = {0};
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = strlcpy(dnssl.name, argv[3]->arg, sizeof(dnssl.name));
|
||||
if (len == 0 || len >= sizeof(dnssl.name)) {
|
||||
vty_out(vty, "Malformed DNS search domain\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
if (dnssl.name[len - 1] == '.') {
|
||||
/*
|
||||
* Allow, but don't require, a trailing dot signifying the root
|
||||
* zone. Canonicalize by cutting it off if present.
|
||||
*/
|
||||
dnssl.name[len - 1] = '\0';
|
||||
len--;
|
||||
}
|
||||
if (argc > 4) {
|
||||
char *lifetime = argv[4]->type == RANGE_TKN ? argv[4]->arg
|
||||
: argv[4]->text;
|
||||
dnssl.lifetime = strmatch(lifetime, "infinite")
|
||||
? UINT32_MAX
|
||||
: strtoll(lifetime, NULL, 10);
|
||||
dnssl.lifetime_set = 1;
|
||||
}
|
||||
|
||||
ret = rtadv_dnssl_encode(dnssl.encoded_name, dnssl.name);
|
||||
if (ret < 0) {
|
||||
vty_out(vty, "Malformed DNS search domain\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
dnssl.encoded_len = ret;
|
||||
rtadv_dnssl_set(zif, &dnssl);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(no_ipv6_nd_dnssl,
|
||||
no_ipv6_nd_dnssl_cmd,
|
||||
"no ipv6 nd dnssl SUFFIX [<(0-4294967295)|infinite>]",
|
||||
NO_STR
|
||||
"Interface IPv6 config commands\n"
|
||||
"Neighbor discovery\n"
|
||||
"DNS search list information\n"
|
||||
"Domain name suffix\n"
|
||||
"Valid lifetime in seconds\n"
|
||||
"Infinite valid lifetime\n")
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
struct zebra_if *zif = ifp->info;
|
||||
struct rtadv_dnssl dnssl = {0};
|
||||
size_t len;
|
||||
|
||||
len = strlcpy(dnssl.name, argv[4]->arg, sizeof(dnssl.name));
|
||||
if (len == 0 || len >= sizeof(dnssl.name)) {
|
||||
vty_out(vty, "Malformed DNS search domain\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
if (dnssl.name[len - 1] == '.') {
|
||||
dnssl.name[len - 1] = '\0';
|
||||
len--;
|
||||
}
|
||||
if (rtadv_dnssl_reset(zif, &dnssl) != 1) {
|
||||
vty_out(vty, "Non-existant DNS search domain\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Dump interface ND information to vty. */
|
||||
static int nd_dump_vty(struct vty *vty, struct interface *ifp)
|
||||
{
|
||||
|
@ -1607,6 +1956,8 @@ static int rtadv_config_write(struct vty *vty, struct interface *ifp)
|
|||
struct zebra_if *zif;
|
||||
struct listnode *node;
|
||||
struct rtadv_prefix *rprefix;
|
||||
struct rtadv_rdnss *rdnss;
|
||||
struct rtadv_dnssl *dnssl;
|
||||
char buf[PREFIX_STRLEN];
|
||||
int interval;
|
||||
|
||||
|
@ -1688,6 +2039,29 @@ static int rtadv_config_write(struct vty *vty, struct interface *ifp)
|
|||
vty_out(vty, " router-address");
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvRDNSSList, node, rdnss)) {
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
|
||||
vty_out(vty, " ipv6 nd rdnss %s",
|
||||
inet_ntop(AF_INET6, &rdnss->addr, buf, sizeof(buf)));
|
||||
if (rdnss->lifetime_set) {
|
||||
if (rdnss->lifetime == UINT32_MAX)
|
||||
vty_out(vty, " infinite");
|
||||
else
|
||||
vty_out(vty, " %u", rdnss->lifetime);
|
||||
}
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
for (ALL_LIST_ELEMENTS_RO(zif->rtadv.AdvDNSSLList, node, dnssl)) {
|
||||
vty_out(vty, " ipv6 nd dnssl %s", dnssl->name);
|
||||
if (dnssl->lifetime_set) {
|
||||
if (dnssl->lifetime == UINT32_MAX)
|
||||
vty_out(vty, " infinite");
|
||||
else
|
||||
vty_out(vty, " %u", dnssl->lifetime);
|
||||
}
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1782,6 +2156,10 @@ void rtadv_cmd_init(void)
|
|||
install_element(INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
|
||||
install_element(INTERFACE_NODE, &ipv6_nd_mtu_cmd);
|
||||
install_element(INTERFACE_NODE, &no_ipv6_nd_mtu_cmd);
|
||||
install_element(INTERFACE_NODE, &ipv6_nd_rdnss_cmd);
|
||||
install_element(INTERFACE_NODE, &no_ipv6_nd_rdnss_cmd);
|
||||
install_element(INTERFACE_NODE, &ipv6_nd_dnssl_cmd);
|
||||
install_element(INTERFACE_NODE, &no_ipv6_nd_dnssl_cmd);
|
||||
}
|
||||
|
||||
static int if_join_all_router(int sock, struct interface *ifp)
|
||||
|
|
|
@ -91,6 +91,37 @@ struct nd_opt_homeagent_info { /* Home Agent info */
|
|||
} __attribute__((__packed__));
|
||||
#endif
|
||||
|
||||
#ifndef ND_OPT_RDNSS
|
||||
#define ND_OPT_RDNSS 25
|
||||
#endif
|
||||
#ifndef ND_OPT_DNSSL
|
||||
#define ND_OPT_DNSSL 31
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRUCT_ND_OPT_RDNSS
|
||||
struct nd_opt_rdnss { /* Recursive DNS server option [RFC8106 5.1] */
|
||||
uint8_t nd_opt_rdnss_type;
|
||||
uint8_t nd_opt_rdnss_len;
|
||||
uint16_t nd_opt_rdnss_reserved;
|
||||
uint32_t nd_opt_rdnss_lifetime;
|
||||
/* Followed by one or more IPv6 addresses */
|
||||
} __attribute__((__packed__));
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRUCT_ND_OPT_DNSSL
|
||||
struct nd_opt_dnssl { /* DNS search list option [RFC8106 5.2] */
|
||||
uint8_t nd_opt_dnssl_type;
|
||||
uint8_t nd_opt_dnssl_len;
|
||||
uint16_t nd_opt_dnssl_reserved;
|
||||
uint32_t nd_opt_dnssl_lifetime;
|
||||
/*
|
||||
* Followed by one or more domain names encoded as in [RFC1035 3.1].
|
||||
* Multiple domain names are concatenated after encoding. In any case,
|
||||
* the result is zero-padded to a multiple of 8 octets.
|
||||
*/
|
||||
} __attribute__((__packed__));
|
||||
#endif
|
||||
|
||||
extern const char *rtadv_pref_strs[];
|
||||
|
||||
#endif /* HAVE_RTADV */
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
DEFINE_MGROUP(ZEBRA, "zebra")
|
||||
DEFINE_MTYPE(ZEBRA, RTADV_PREFIX, "Router Advertisement Prefix")
|
||||
DEFINE_MTYPE(ZEBRA, RTADV_RDNSS, "Router Advertisement RDNSS")
|
||||
DEFINE_MTYPE(ZEBRA, RTADV_DNSSL, "Router Advertisement DNSSL")
|
||||
DEFINE_MTYPE(ZEBRA, ZEBRA_VRF, "ZEBRA VRF")
|
||||
DEFINE_MTYPE(ZEBRA, RE, "Route Entry")
|
||||
DEFINE_MTYPE(ZEBRA, RIB_QUEUE, "RIB process work queue")
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
|
||||
DECLARE_MGROUP(ZEBRA)
|
||||
DECLARE_MTYPE(RTADV_PREFIX)
|
||||
DECLARE_MTYPE(RTADV_RDNSS)
|
||||
DECLARE_MTYPE(RTADV_DNSSL)
|
||||
DECLARE_MTYPE(ZEBRA_NS)
|
||||
DECLARE_MTYPE(ZEBRA_VRF)
|
||||
DECLARE_MTYPE(RE)
|
||||
|
|
Loading…
Reference in a new issue