/* ** L2 - OSSP Logging Library ** Copyright (c) 2001 The OSSP Project (http://www.ossp.org/) ** Copyright (c) 2001 Cable & Wireless Deutschland (http://www.cw.com/de/) ** ** This file is part of OSSP L2, a flexible logging library which ** can be found at http://www.ossp.org/pkg/l2/. ** ** Permission to use, copy, modify, and distribute this software for ** any purpose with or without fee is hereby granted, provided that ** the above copyright notice and this permission notice appear in all ** copies. ** ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. ** ** l2_ut_sa.c: utility library for socket address handling */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "l2_config.h" #include "l2_ut_sa.h" #if !defined(AF_LOCAL) && defined(AF_UNIX) #define AF_LOCAL AF_UNIX #endif #ifndef HAVE_INET_PTON #ifdef HAVE_INET_ATON static int inet_pton(int family, const char *strptr, void *addrptr) { struct in_addr in_val; if (family == AF_INET) { if (inet_aton(strptr, &in_val)) { memcpy(addrptr, &in_val, sizeof(struct in_addr)); return 1; } return 0; } errno = EAFNOSUPPORT; return -1; } #else #error "neither inet_pton nor inet_aton available" #endif #endif #ifndef NUL #define NUL '\0' #endif l2_util_sa_t *l2_util_sa_create(int sa_type, ...) { va_list ap; l2_util_sa_t *rc; int nPort; socklen_t sl; struct sockaddr *sa; struct sockaddr_in sa4; #ifdef AF_INET6 struct sockaddr_in6 sa6; #endif struct sockaddr_un sau; struct hostent *he; struct servent *se; struct protoent *pe; int bNumeric; int i; char *cpPath; int nPath; char *cpProto; int nProto; char *cpHost; char *cpPort; va_start(ap, sa_type); sa = NULL; sl = 0; if (sa_type == SA_UNIX) { #if defined(AF_LOCAL) if ((cpPath = va_arg(ap, char *)) == NULL) return NULL; if ((nPath = strlen(cpPath)) >= (sizeof(sau.sun_path)-1)) return NULL; nProto = 0; sau.sun_family = AF_LOCAL; memcpy(sau.sun_path, cpPath, nPath + 1); sa = (struct sockaddr *)&sau; sl = sizeof(sau); #else return NULL; #endif } else if (sa_type == SA_IP) { if ((cpProto = va_arg(ap, char *)) == NULL) return NULL; if ((cpHost = va_arg(ap, char *)) == NULL) return NULL; if ((cpPort = va_arg(ap, char *)) == NULL) return NULL; /* resolve protocol */ if ((pe = getprotobyname(cpProto)) == NULL) return NULL; nProto = pe->p_proto; /* resolve port */ bNumeric = 1; for (i = 0; cpPort[i] != NUL; i++) { if (!isdigit((int)cpPort[i])) { bNumeric = 0; break; } } if (bNumeric) nPort = atoi(cpPort); else { if ((se = getservbyname(cpPort, cpProto)) == NULL) return NULL; nPort = ntohs(se->s_port); } /* resolve host */ if (inet_pton(AF_INET, cpHost, &sa4.sin_addr.s_addr) == 1) { sa4.sin_family = AF_INET; sa4.sin_port = htons(nPort); sa = (struct sockaddr *)&sa4; sl = sizeof(sa4); } #ifdef AF_INET6 else if (inet_pton(AF_INET6, cpHost, &sa6.sin6_addr.s6_addr) == 1) { sa6.sin6_family = AF_INET6; sa6.sin6_port = htons(nPort); sa = (struct sockaddr *)&sa6; sl = sizeof(sa6); } #endif else if ((he = gethostbyname(cpHost)) != NULL) { if (he->h_addrtype == AF_INET) { sa4.sin_family = AF_INET; sa4.sin_port = htons(nPort); memcpy(&sa4.sin_addr.s_addr, he->h_addr_list[0], sizeof(sa4.sin_addr.s_addr)); sa = (struct sockaddr *)&sa4; sl = sizeof(sa4); } #ifdef AF_INET6 else if (he->h_addrtype == AF_INET6) { sa6.sin6_family = AF_INET6; sa6.sin6_port = htons(nPort); memcpy(&sa6.sin6_addr.s6_addr, he->h_addr_list[0], sizeof(sa6.sin6_addr.s6_addr)); sa = (struct sockaddr *)&sa6; sl = sizeof(sa6); } #endif } } else return NULL; va_end(ap); if (sa == NULL) return NULL; if ((rc = (l2_util_sa_t *)malloc(sizeof(l2_util_sa_t))) == NULL) return NULL; if ((rc->sa_buf = (struct sockaddr *)malloc(sl)) == NULL) { free(rc); return NULL; } memcpy(rc->sa_buf, sa, sl); rc->sa_len = sl; rc->sa_proto = nProto; return rc; } void l2_ut_sa_destroy(l2_util_sa_t *sa) { if (sa == NULL) return; if (sa->sa_buf != NULL) free(sa->sa_buf); free(sa); return; }