X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/e83d0967d4c0965eb8036248acc20d1bf12ad1d8..0590cedca75c01811972b2f694f60f24028ee973:/lib/addr.c diff --git a/lib/addr.c b/lib/addr.c index 16cd610..ec245c6 100644 --- a/lib/addr.c +++ b/lib/addr.c @@ -1,6 +1,6 @@ /* * This file is part of DisOrder. - * Copyright (C) 2004 Richard Kettlewell + * Copyright (C) 2004, 2007 Richard Kettlewell * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,6 +17,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ +/** @file lib/addr.c + * @brief Socket address support */ #include #include "types.h" @@ -27,12 +29,33 @@ #include #include #include +#include +#include #include "log.h" #include "printf.h" #include "configuration.h" #include "addr.h" +#include "mem.h" +/** @brief Convert a pair of strings to an address + * @param a Pointer to string list + * @param pref Hints structure for getaddrinfo, or NULL + * @param namep Where to store address description, or NULL + * @return Address info structure or NULL on error + * + * This converts one or two strings into an address specification suitable + * for passing to socket(), bind() etc. + * + * If there is only one string then it is assumed to be the service + * name (port number). If there are two then the first is the host + * name and the second the service name. + * + * @p namep is used to return a description of the address suitable + * for use in log messages. + * + * If an error occurs a message is logged and a null pointer returned. + */ struct addrinfo *get_address(const struct stringlist *a, const struct addrinfo *pref, char **namep) { @@ -70,6 +93,10 @@ struct addrinfo *get_address(const struct stringlist *a, return res; } +/** @brief Comparison function for address information + * + * Suitable for qsort(). + */ int addrinfocmp(const struct addrinfo *a, const struct addrinfo *b) { const struct sockaddr_in *ina, *inb; @@ -97,7 +124,83 @@ int addrinfocmp(const struct addrinfo *a, return memcmp(a->ai_addr, b->ai_addr, a->ai_addrlen); /* kludge */ } } - + +/** @brief Return nonzero if @p sin4 is an IPv4 multicast address */ +static inline int multicast4(const struct sockaddr_in *sin4) { + return IN_MULTICAST(ntohl(sin4->sin_addr.s_addr)); +} + +/** @brief Return nonzero if @p sin6 is an IPv6 multicast address */ +static inline int multicast6(const struct sockaddr_in6 *sin6) { + return IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr); +} + +/** @brief Return true if @p sa represents a multicast address */ +int multicast(const struct sockaddr *sa) { + switch(sa->sa_family) { + case AF_INET: + return multicast4((const struct sockaddr_in *)sa); + case AF_INET6: + return multicast6((const struct sockaddr_in6 *)sa); + default: + return 0; + } +} + +/** @brief Format an IPv4 address */ +static inline char *format_sockaddr4(const struct sockaddr_in *sin4) { + char buffer[1024], *r; + + if(sin4->sin_port) + byte_xasprintf(&r, "%s port %u", + inet_ntop(sin4->sin_family, &sin4->sin_addr, + buffer, sizeof buffer), + ntohs(sin4->sin_port)); + else + byte_xasprintf(&r, "%s", + inet_ntop(sin4->sin_family, &sin4->sin_addr, + buffer, sizeof buffer)); + return r; +} + +/** @brief Format an IPv6 address */ +static inline char *format_sockaddr6(const struct sockaddr_in6 *sin6) { + char buffer[1024], *r; + + if(sin6->sin6_port) + byte_xasprintf(&r, "%s port %u", + inet_ntop(sin6->sin6_family, &sin6->sin6_addr, + buffer, sizeof buffer), + ntohs(sin6->sin6_port)); + else + byte_xasprintf(&r, "%s", + inet_ntop(sin6->sin6_family, &sin6->sin6_addr, + buffer, sizeof buffer)); + return r; +} + +/** @brief Format a UNIX socket address */ +static inline char *format_sockaddrun(const struct sockaddr_un *sun) { + return xstrdup(sun->sun_path); +} + +/** @brief Construct a text description a sockaddr + * @param sa Socket address + * @return Human-readable form of address + */ +char *format_sockaddr(const struct sockaddr *sa) { + switch(sa->sa_family) { + case AF_INET: + return format_sockaddr4((const struct sockaddr_in *)sa); + case AF_INET6: + return format_sockaddr6((const struct sockaddr_in6 *)sa); + case AF_UNIX: + return format_sockaddrun((const struct sockaddr_un *)sa); + default: + return 0; + } +} + /* Local Variables: c-basic-offset:2