*/
int ip_hton(const char *src, int af, fr_ipaddr_t *dst)
{
- int error;
+ int rcode;
struct addrinfo hints, *ai = NULL, *res = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = af;
- if ((error = getaddrinfo(src, NULL, &hints, &res)) != 0) {
- fr_strerror_printf("ip_hton: %s", gai_strerror(error));
+ if ((rcode = getaddrinfo(src, NULL, &hints, &res)) != 0) {
+ fr_strerror_printf("ip_hton: %s", gai_strerror(rcode));
return -1;
}
return -1;
}
- switch (ai->ai_family) {
- case AF_INET :
- dst->af = AF_INET;
- memcpy(&dst->ipaddr,
- &((struct sockaddr_in*)ai->ai_addr)->sin_addr,
- sizeof(struct in_addr));
- break;
-
-#ifdef HAVE_STRUCT_SOCKADDR_IN6
- case AF_INET6 :
- dst->af = AF_INET6;
- memcpy(&dst->ipaddr,
- &((struct sockaddr_in6*)ai->ai_addr)->sin6_addr,
- sizeof(struct in6_addr));
- break;
-#endif
-
- /* Flow should never reach here */
- case AF_UNSPEC :
- default :
- fr_strerror_printf("ip_hton found unusable information for host %.100s", src);
- freeaddrinfo(ai);
- return -1;
- }
-
+ rcode = fr_sockaddr2ipaddr((struct sockaddr_storage *)ai->ai_addr,
+ ai->ai_addrlen, dst, NULL);
freeaddrinfo(ai);
+ if (!rcode) return -1;
+
return 0;
}
#ifdef HAVE_STRUCT_SOCKADDR_IN6
case AF_INET6:
+ if (a->scope < b->scope) return -1;
+ if (a->scope > b->scope) return +1;
+
return memcmp(&a->ipaddr.ip6addr,
&b->ipaddr.ip6addr,
sizeof(a->ipaddr.ip6addr));
s6.sin6_family = AF_INET6;
s6.sin6_addr = ipaddr->ipaddr.ip6addr;
s6.sin6_port = htons(port);
+ s6.sin6_scope_id = ipaddr->scope;
memset(sa, 0, sizeof(*sa));
memcpy(sa, &s6, sizeof(s6));
#endif
int fr_sockaddr2ipaddr(const struct sockaddr_storage *sa, socklen_t salen,
- fr_ipaddr_t *ipaddr, int * port)
+ fr_ipaddr_t *ipaddr, int *port)
{
- /*
- * FIXME: Check salen against sizeof socket structures.
- */
- salen = salen; /* -Wunused */
-
if (sa->ss_family == AF_INET) {
struct sockaddr_in s4;
+
+ if (salen < sizeof(s4)) {
+ fr_strerror_printf("IPv4 address is too small");
+ return 0;
+ }
memcpy(&s4, sa, sizeof(s4));
ipaddr->af = AF_INET;
} else if (sa->ss_family == AF_INET6) {
struct sockaddr_in6 s6;
+ if (salen < sizeof(s6)) {
+ fr_strerror_printf("IPv6 address is too small");
+ return 0;
+ }
+
memcpy(&s6, sa, sizeof(s6));
ipaddr->af = AF_INET6;
ipaddr->ipaddr.ip6addr = s6.sin6_addr;
if (port) *port = ntohs(s6.sin6_port);
+ ipaddr->scope = s6.sin6_scope_id;
#endif
} else {
+ fr_strerror_printf("Unsupported address famility %d",
+ sa->ss_family);
return 0;
}