From 6ea547962997517629240c4c9d8e5a2592a6a95a Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 5 Jan 2012 13:38:07 +0200 Subject: [PATCH] inet: Get router advertisement prefix option information. --- src/connman.h | 2 ++ src/inet.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/connman.h b/src/connman.h index e42cbe1..e8c6187 100644 --- a/src/connman.h +++ b/src/connman.h @@ -141,6 +141,8 @@ typedef void (*__connman_inet_rs_cb_t) (struct nd_router_advert *reply, int __connman_inet_ipv6_send_rs(int index, int timeout, __connman_inet_rs_cb_t callback, void *user_data); +GSList *__connman_inet_ipv6_get_prefixes(struct nd_router_advert *hdr, + unsigned int length); #include diff --git a/src/inet.c b/src/inet.c index a659ab0..d9e12a9 100644 --- a/src/inet.c +++ b/src/inet.c @@ -1722,3 +1722,53 @@ int __connman_inet_ipv6_send_rs(int index, int timeout, return 0; } + +GSList *__connman_inet_ipv6_get_prefixes(struct nd_router_advert *hdr, + unsigned int length) +{ + GSList *prefixes = NULL; + uint8_t *pos; + int len; + + if (length <= sizeof(struct nd_router_advert)) + return NULL; + + len = length - sizeof(struct nd_router_advert); + pos = (uint8_t *)hdr + sizeof(struct nd_router_advert); + + while (len > 0) { + struct nd_opt_prefix_info *pinfo; + char prefix_str[INET6_ADDRSTRLEN+1], *str; + const char *prefix; + int optlen; + + if (len < 2) + break; + + optlen = pos[1] << 3; + if (optlen == 0 || optlen > len) + break; + + switch (pos[0]) { + case ND_OPT_PREFIX_INFORMATION: + pinfo = (struct nd_opt_prefix_info *)pos; + prefix = inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix, + prefix_str, INET6_ADDRSTRLEN); + if (prefix == NULL) + break; + + str = g_strdup_printf("%s/%d", prefix, + pinfo->nd_opt_pi_prefix_len); + prefixes = g_slist_append(prefixes, str); + + DBG("prefix %s", str); + + break; + } + + len -= optlen; + pos += optlen; + } + + return prefixes; +} -- 2.7.4