diff options
-rw-r--r-- | include/ndp.h | 11 | ||||
-rw-r--r-- | libndp/libndp.c | 79 | ||||
-rw-r--r-- | libndp/ndp_private.h | 10 | ||||
-rw-r--r-- | utils/ndptool.c | 19 |
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) { |