summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ndp.h11
-rw-r--r--libndp/libndp.c79
-rw-r--r--libndp/ndp_private.h10
-rw-r--r--utils/ndptool.c19
4 files changed, 119 insertions, 0 deletions
diff --git a/include/ndp.h b/include/ndp.h
index c19e27f..d6603f4 100644
--- a/include/ndp.h
+++ b/include/ndp.h
@@ -107,6 +107,7 @@ enum ndp_msg_opt_type {
NDP_MSG_OPT_MTU, /* MTU */
NDP_MSG_OPT_ROUTE, /* Route Information */
NDP_MSG_OPT_RDNSS, /* Recursive DNS Server */
+ NDP_MSG_OPT_DNSSL, /* DNS Search List */
};
int ndp_msg_next_opt_offset(struct ndp_msg *msg, int offset,
@@ -145,6 +146,16 @@ struct in6_addr *ndp_msg_opt_rdnss_addr(struct ndp_msg *msg, int offset,
addr; \
addr = ndp_msg_opt_rdnss_addr(msg, offset, ++addr_index))
+uint32_t ndp_msg_opt_dnssl_lifetime(struct ndp_msg *msg, int offset);
+char *ndp_msg_opt_dnssl_domain(struct ndp_msg *msg, int offset,
+ int domain_index);
+
+#define ndp_msg_opt_dnssl_for_each_domain(domain, domain_index, msg, offset) \
+ for (domain_index = 0, \
+ domain = ndp_msg_opt_dnssl_domain(msg, offset, domain_index); \
+ domain; \
+ domain = ndp_msg_opt_dnssl_domain(msg, offset, ++domain_index))
+
typedef int (*ndp_msgrcv_handler_func_t)(struct ndp *ndp, struct ndp_msg *msg,
void *priv);
int ndp_msgrcv_handler_register(struct ndp *ndp, ndp_msgrcv_handler_func_t func,
diff --git a/libndp/libndp.c b/libndp/libndp.c
index 44da3e7..88e0e36 100644
--- a/libndp/libndp.c
+++ b/libndp/libndp.c
@@ -1013,6 +1013,10 @@ static struct ndp_msg_opt_type_info ndp_msg_opt_type_info_list[] =
.raw_type = __ND_OPT_RDNSS,
.raw_struct_size = sizeof(struct __nd_opt_rdnss),
},
+ [NDP_MSG_OPT_DNSSL] = {
+ .raw_type = __ND_OPT_DNSSL,
+ .raw_struct_size = sizeof(struct __nd_opt_dnssl),
+ },
};
#define NDP_MSG_OPT_TYPE_LIST_SIZE ARRAY_SIZE(ndp_msg_opt_type_info_list)
@@ -1415,6 +1419,81 @@ struct in6_addr *ndp_msg_opt_rdnss_addr(struct ndp_msg *msg, int offset,
return &addr;
}
+/**
+ * ndp_msg_opt_dnssl_lifetime:
+ * @msg: message structure
+ * @offset: in-message offset
+ *
+ * Get DNS Search List lifetime.
+ * User should use this function only inside ndp_msg_opt_for_each_offset()
+ * macro loop.
+ *
+ * Returns: route lifetime in seconds, (uint32_t) -1 means infinity.
+ **/
+NDP_EXPORT
+uint32_t ndp_msg_opt_dnssl_lifetime(struct ndp_msg *msg, int offset)
+{
+ struct __nd_opt_dnssl *dnssl =
+ ndp_msg_payload_opts_offset(msg, offset);
+
+ return ntohl(dnssl->nd_opt_dnssl_lifetime);
+}
+
+/**
+ * ndp_msg_opt_dnssl_domain:
+ * @msg: message structure
+ * @offset: in-message offset
+ * @domain_index: domain index
+ *
+ * Get DNS Search List domain.
+ * User should use this function only inside ndp_msg_opt_for_each_offset()
+ * macro loop.
+ *
+ * Returns: address.
+ **/
+NDP_EXPORT
+char *ndp_msg_opt_dnssl_domain(struct ndp_msg *msg, int offset,
+ int domain_index)
+{
+ int i;
+ static char buf[256];
+ struct __nd_opt_dnssl *dnssl =
+ ndp_msg_payload_opts_offset(msg, offset);
+ size_t len = dnssl->nd_opt_dnssl_len << 3; /* convert to bytes */
+ char *ptr;
+
+ len -= in_struct_offset(struct __nd_opt_dnssl, nd_opt_dnssl_domains);
+ ptr = dnssl->nd_opt_dnssl_domains;
+
+ i = 0;
+ while (len > 0) {
+ *buf = '\0';
+ while (len > 0) {
+ uint8_t dom_len = *ptr;
+
+ ptr++;
+ len--;
+ if (!dom_len)
+ break;
+
+ if (dom_len > len)
+ return NULL;
+
+ if (strlen(buf))
+ sprintf(buf, "%s.", buf);
+ buf[strlen(buf) + dom_len] = '\0';
+ memcpy(buf + strlen(buf), ptr, dom_len);
+ ptr += dom_len;
+ len -= dom_len;
+ }
+ if (!strlen(buf))
+ break;
+ if (i++ == domain_index)
+ return buf;
+ }
+ return NULL;
+}
+
static int ndp_call_handlers(struct ndp *ndp, struct ndp_msg *msg);
static int ndp_sock_recv(struct ndp *ndp)
diff --git a/libndp/ndp_private.h b/libndp/ndp_private.h
index 7424e8c..49ecad0 100644
--- a/libndp/ndp_private.h
+++ b/libndp/ndp_private.h
@@ -84,6 +84,7 @@ ndp_log_null(struct ndp *ndp, const char *format, ...) {}
#define __ND_OPT_ROUTE_INFO 24 /* rfc4191 */
#define __ND_OPT_RDNSS 25 /* rfc6106 */
+#define __ND_OPT_DNSSL 31 /* rfc6106 */
struct __nd_opt_route_info { /* route information */
uint8_t nd_opt_ri_type;
@@ -102,4 +103,13 @@ struct __nd_opt_rdnss { /* Recursive DNS Server */
char nd_opt_rdnss_addresses[0];
};
+struct __nd_opt_dnssl { /* DNS Search List */
+ uint8_t nd_opt_dnssl_type;
+ uint8_t nd_opt_dnssl_len;
+ uint16_t nd_opt_dnssl_reserved;
+ uint32_t nd_opt_dnssl_lifetime;
+ char nd_opt_dnssl_domains[0];
+};
+
+
#endif /* _NDP_PRIVATE_H_ */
diff --git a/utils/ndptool.c b/utils/ndptool.c
index 283d55b..6d45097 100644
--- a/utils/ndptool.c
+++ b/utils/ndptool.c
@@ -288,6 +288,25 @@ static int msgrcv_handler_func(struct ndp *ndp, struct ndp_msg *msg, void *priv)
pr_out("%us", lifetime);
pr_out("\n");
}
+ ndp_msg_opt_for_each_offset(offset, msg, NDP_MSG_OPT_DNSSL) {
+ char *domain;
+ int domain_index;
+ uint32_t lifetime;
+
+ lifetime = ndp_msg_opt_rdnss_lifetime(msg, offset);
+ pr_out(" DNS Search List: ");
+ ndp_msg_opt_dnssl_for_each_domain(domain, domain_index, msg, offset) {
+ if (domain_index != 0)
+ pr_out(" ");
+ pr_out("%s", domain);
+ }
+ pr_out(", lifetime: ");
+ if (lifetime == (uint32_t) -1)
+ pr_out("infinity");
+ else
+ pr_out("%us", lifetime);
+ pr_out("\n");
+ }
} else if (msg_type == NDP_MSG_NS) {
pr_out(" Type: NS\n");
} else if (msg_type == NDP_MSG_NA) {