resolver.c 5.15 KB
Newer Older
Jack Moffitt's avatar
Jack Moffitt committed
1
/*
2 3
 * resolver.c - name resolver library
 *
4 5 6 7 8
 * Copyright (C) 2014 Michael Smith <msmith@icecast.org>,
 *                    Brendan Cully <brendan@xiph.org>,
 *                    Karl Heyes <karl@xiph.org>,
 *                    Jack Moffitt <jack@icecast.org>,
 *                    Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
9
 *
10 11 12 13
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
14
 *
15 16 17 18 19 20 21 22 23
 * 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA  02110-1301, USA.
24 25
 *
 */
26 27 28
#ifdef HAVE_CONFIG_H
 #include <config.h>
#endif
Jack Moffitt's avatar
Jack Moffitt committed
29 30 31 32 33 34 35

#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>

#ifndef _WIN32
36
#include <netdb.h>
37 38 39 40
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#else
41
#include <winsock2.h>
Jack Moffitt's avatar
Jack Moffitt committed
42 43
#endif

44
#ifndef NO_THREAD
45
#include <thread/thread.h>
46
#else
47 48 49 50
#define thread_mutex_create(x) do{}while(0)
#define thread_mutex_destroy(x) do{}while(0)
#define thread_mutex_lock(x) do{}while(0)
#define thread_mutex_unlock(x) do{}while(0)
51 52
#endif

Jack Moffitt's avatar
Jack Moffitt committed
53 54 55 56 57 58 59 60 61
#include "resolver.h"
#include "sock.h"

/* internal function */

static int _isip(const char *what);

/* internal data */

62
#ifndef NO_THREAD
Jack Moffitt's avatar
Jack Moffitt committed
63
static mutex_t _resolver_mutex;
64
#endif
Jack Moffitt's avatar
Jack Moffitt committed
65 66
static int _initialized = 0;

67 68
#ifdef HAVE_INET_PTON
static int _isip(const char *what)
Jack Moffitt's avatar
Jack Moffitt committed
69
{
70 71 72 73 74 75 76
    union {
        struct in_addr v4addr;
        struct in6_addr v6addr;
    } addr_u;

    if (inet_pton(AF_INET, what, &addr_u.v4addr) <= 0)
        return inet_pton(AF_INET6, what, &addr_u.v6addr) > 0 ? 1 : 0;
Jack Moffitt's avatar
Jack Moffitt committed
77

78
    return 1;
Jack Moffitt's avatar
Jack Moffitt committed
79 80
}

81 82
#else
static int _isip(const char *what)
Jack Moffitt's avatar
Jack Moffitt committed
83
{
84
    struct in_addr inp;
Jack Moffitt's avatar
Jack Moffitt committed
85

86
    return inet_aton(what, &inp);
Jack Moffitt's avatar
Jack Moffitt committed
87
}
88
#endif
Jack Moffitt's avatar
Jack Moffitt committed
89

90 91 92

#if defined (HAVE_GETNAMEINFO) && defined (HAVE_GETADDRINFO)
char *resolver_getname(const char *ip, char *buff, int len)
Jack Moffitt's avatar
Jack Moffitt committed
93
{
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
    struct addrinfo *head = NULL, hints;
    char *ret = NULL;

    if (!_isip(ip)) {
        strncpy(buff, ip, len);
        buff [len-1] = '\0';
        return buff;
    }

    memset (&hints, 0, sizeof (hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_CANONNAME;
    if (getaddrinfo (ip, NULL, &hints, &head))
        return NULL;

    if (head)
    {
        if (getnameinfo(head->ai_addr, head->ai_addrlen, buff, len, NULL, 
                    0, NI_NAMEREQD) == 0)
            ret = buff;

        freeaddrinfo (head);
    }

    return ret;
}
Jack Moffitt's avatar
Jack Moffitt committed
121 122


123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
char *resolver_getip(const char *name, char *buff, int len)
{
    struct addrinfo *head, hints;
    char *ret = NULL;

    if (_isip(name)) {
        strncpy(buff, name, len);
        buff [len-1] = '\0';
        return buff;
    }

    memset (&hints, 0, sizeof (hints));
    hints . ai_family = AF_UNSPEC;
    hints . ai_socktype = SOCK_STREAM;
    if (getaddrinfo (name, NULL, &hints, &head))
        return NULL;

    if (head)
    {
        if (getnameinfo(head->ai_addr, head->ai_addrlen, buff, len, NULL, 
                    0, NI_NUMERICHOST) == 0)
            ret = buff;
        freeaddrinfo (head);
    }

    return ret;
}

Jack Moffitt's avatar
Jack Moffitt committed
151 152
#else

153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
char *resolver_getname(const char *ip, char *buff, int len)
{
    struct hostent *host;
    char *ret = NULL;
    struct in_addr addr;

    if (! _isip(ip))
    {
        strncpy(buff, ip, len);
        buff [len-1] = '\0';
        return buff;
    }

    thread_mutex_lock(&_resolver_mutex);
    if (inet_aton (ip, &addr)) {
168 169
        /* casting &addr to const char* as it is recommended on win* */
        if ((host=gethostbyaddr ((const char *)&addr, sizeof (struct in_addr), AF_INET)))
170 171 172 173 174 175 176 177
        {
            ret = strncpy (buff, host->h_name, len);
            buff [len-1] = '\0';
        }
    }

    thread_mutex_unlock(&_resolver_mutex);
    return ret;
Jack Moffitt's avatar
Jack Moffitt committed
178 179
}

180
char *resolver_getip(const char *name, char *buff, int len)
Jack Moffitt's avatar
Jack Moffitt committed
181
{
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
    struct hostent *host;
    char *ret = NULL;

    if (_isip(name))
    {
        strncpy(buff, name, len);
        buff [len-1] = '\0';
        return buff;
    }
    thread_mutex_lock(&_resolver_mutex);
    host = gethostbyname(name);
    if (host)
    {
        char * temp = inet_ntoa(*(struct in_addr *)host->h_addr);
        ret = strncpy(buff, temp, len);
        buff [len-1] = '\0';
    }
    thread_mutex_unlock(&_resolver_mutex);

    return ret;
}
Jack Moffitt's avatar
Jack Moffitt committed
203 204 205 206 207
#endif


void resolver_initialize()
{
208
    /* initialize the lib if we havne't done so already */
Jack Moffitt's avatar
Jack Moffitt committed
209

210 211 212 213
    if (!_initialized)
    {
        _initialized = 1;
        thread_mutex_create (&_resolver_mutex);
Jack Moffitt's avatar
Jack Moffitt committed
214

215 216 217
        /* keep dns connects (TCP) open */
#ifdef HAVE_SETHOSTENT
        sethostent(1);
Jack Moffitt's avatar
Jack Moffitt committed
218
#endif
219
    }
Jack Moffitt's avatar
Jack Moffitt committed
220 221
}

222
void resolver_shutdown(void)
Jack Moffitt's avatar
Jack Moffitt committed
223
{
224 225 226 227 228 229
    if (_initialized)
    {
        thread_mutex_destroy(&_resolver_mutex);
        _initialized = 0;
#ifdef HAVE_ENDHOSTENT
        endhostent();
Jack Moffitt's avatar
Jack Moffitt committed
230
#endif
231
    }
Jack Moffitt's avatar
Jack Moffitt committed
232 233
}