diff options
Diffstat (limited to '3rdparty/openpgm-svn-r1135/pgm/indextoaddr.c')
-rw-r--r-- | 3rdparty/openpgm-svn-r1135/pgm/indextoaddr.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/3rdparty/openpgm-svn-r1135/pgm/indextoaddr.c b/3rdparty/openpgm-svn-r1135/pgm/indextoaddr.c new file mode 100644 index 0000000..479dffd --- /dev/null +++ b/3rdparty/openpgm-svn-r1135/pgm/indextoaddr.c @@ -0,0 +1,98 @@ +/* vim:ts=8:sts=8:sw=4:noai:noexpandtab + * + * portable interface index to socket address function. + * + * Copyright (c) 2006-2010 Miru Limited. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <impl/i18n.h> +#include <impl/framework.h> + + +//#define INDEXTOADDR_DEBUG + + +/* interfaces indexes refer to the link layer, we want to find the internet layer address. + * the big problem is that multiple IPv6 addresses can be bound to one link - called scopes. + * we can just pick the first scope and let IP routing handle the rest. + */ + +bool +pgm_if_indextoaddr ( + const unsigned ifindex, + const sa_family_t iffamily, + const uint32_t ifscope, + struct sockaddr* restrict ifsa, + pgm_error_t** restrict error + ) +{ + pgm_return_val_if_fail (NULL != ifsa, FALSE); + + if (0 == ifindex) /* any interface or address */ + { + ifsa->sa_family = iffamily; + switch (iffamily) { + case AF_INET: + ((struct sockaddr_in*)ifsa)->sin_addr.s_addr = INADDR_ANY; + break; + + case AF_INET6: + ((struct sockaddr_in6*)ifsa)->sin6_addr = in6addr_any; + break; + + default: + pgm_return_val_if_reached (FALSE); + break; + } + return TRUE; + } + + struct pgm_ifaddrs_t *ifap, *ifa; + if (!pgm_getifaddrs (&ifap, error)) { + pgm_prefix_error (error, + _("Enumerating network interfaces: ")); + return FALSE; + } + + for (ifa = ifap; ifa; ifa = ifa->ifa_next) + { + if (NULL == ifa->ifa_addr || + ifa->ifa_addr->sa_family != iffamily) + continue; + + const unsigned i = pgm_if_nametoindex (iffamily, ifa->ifa_name); + pgm_assert (0 != i); + if (i == ifindex) + { + if (ifscope && ifscope != pgm_sockaddr_scope_id (ifa->ifa_addr)) + continue; + memcpy (ifsa, ifa->ifa_addr, pgm_sockaddr_len(ifa->ifa_addr)); + pgm_freeifaddrs (ifap); + return TRUE; + } + } + + pgm_set_error (error, + PGM_ERROR_DOMAIN_IF, + PGM_ERROR_NODEV, + _("No matching network interface index: %i"), + ifindex); + pgm_freeifaddrs (ifap); + return FALSE; +} + +/* eof */ |