OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [net/] [common/] [v2_0/] [src/] [getaddrinfo.c] - Blame information for rev 1254

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1254 phoenix
//==========================================================================
2
//
3
//      lib/getaddrinfo.c
4
//
5
//      getaddrinfo(), freeaddrinfo(), gai_strerror(), getnameinfo()
6
//
7
//==========================================================================
8
//####ECOSPDCOPYRIGHTBEGIN####
9
//
10
// Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
11
// All Rights Reserved.
12
//
13
// Permission is granted to use, copy, modify and redistribute this
14
// file.
15
//
16
//####ECOSPDCOPYRIGHTEND####
17
//==========================================================================
18
//#####DESCRIPTIONBEGIN####
19
//
20
// Author(s):    gthomas
21
// Contributors: gthomas
22
// Date:         2002-03-05
23
// Purpose:      
24
// Description:  
25
//              
26
//
27
//####DESCRIPTIONEND####
28
//
29
//==========================================================================
30
 
31
#include <sys/param.h>
32
#include <sys/socket.h>           // PF_xxx
33
#include <netinet/in.h>           // IPPROTO_xx
34
#include <net/netdb.h>
35
#include <errno.h>
36
#include <cyg/infra/cyg_ass.h>
37
 
38
extern int  sprintf(char *, const char *, ...);
39
extern long strtol(const char *, char **, int);
40
extern void *malloc(size_t);
41
extern void *calloc(int, size_t);
42
extern void free(void *);
43
 
44
// This routine is the real meat of the host->address translation
45
static int
46
_getaddr(struct addrinfo *ai, const char *node,
47
         const struct addrinfo *hints, int family, int port)
48
{
49
    switch (family) {
50
    case AF_INET:
51
    {
52
        struct sockaddr_in *sa;
53
        sa = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
54
        ai->ai_addr = (struct sockaddr *)sa;
55
        ai->ai_addrlen = sizeof(*sa);
56
        if (ai->ai_addr == (struct sockaddr *)NULL) {
57
            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);
58
            return EAI_MEMORY;
59
        }
60
        sa->sin_family = AF_INET;
61
        sa->sin_len = sizeof(*sa);
62
        sa->sin_port = htons(port);
63
        if (node == (char *)NULL) {
64
            if (hints->ai_flags & AI_PASSIVE) {
65
                sa->sin_addr.s_addr = htonl(INADDR_ANY);
66
            } else {
67
                sa->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
68
            }
69
        } else {
70
            // For now, only numeric "presentation" addresses supported
71
            if (!inet_pton(AF_INET, (char *)node, (char *)&sa->sin_addr.s_addr)) {
72
            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);
73
                return EAI_FAIL;  // Couldn't resolve name
74
            }
75
        }
76
    }
77
    break;
78
#ifdef CYGPKG_NET_INET6
79
    case AF_INET6:
80
    {
81
        struct sockaddr_in6 *sa;
82
        sa = (struct sockaddr_in6 *)malloc(sizeof(struct sockaddr_in6));
83
        ai->ai_addr = (struct sockaddr *)sa;
84
        ai->ai_addrlen = sizeof(*sa);
85
        if (ai->ai_addr == (struct sockaddr *)NULL) {
86
            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);
87
            return EAI_MEMORY;
88
        }
89
        sa->sin6_family = AF_INET6;
90
        sa->sin6_len = sizeof(*sa);
91
        sa->sin6_port = htons(port);
92
        if (node == (char *)NULL) {
93
            if (hints->ai_flags & AI_PASSIVE) {
94
                sa->sin6_addr = in6addr_any;
95
            } else {
96
                sa->sin6_addr = in6addr_loopback;
97
            }
98
        } else {
99
            // For now, only numeric "presentation" addresses supported
100
            if (!inet_pton(AF_INET6, (char *)node, (char *)&sa->sin6_addr)) {
101
            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);
102
                return EAI_FAIL;  // Couldn't resolve name
103
            }
104
        }
105
    }
106
    break;
107
#endif
108
    }
109
    return EAI_NONE;
110
}
111
 
112
int
113
getaddrinfo(const char *nodename, const char *servname,
114
            const struct addrinfo *hints, struct addrinfo **res)
115
{
116
    struct addrinfo dflt_hints;
117
    struct protoent *proto = (struct protoent *)NULL;
118
    struct addrinfo *ai;
119
    char *protoname;
120
    int port = 0;
121
    int family;
122
    int err;
123
 
124
    if (hints == (struct addrinfo *)NULL) {
125
        dflt_hints.ai_flags = 0;  // No special flags
126
        dflt_hints.ai_family = PF_UNSPEC;
127
        dflt_hints.ai_socktype = 0;
128
        dflt_hints.ai_protocol = 0;
129
        hints = &dflt_hints;
130
    }
131
    // Prevalidate parameters
132
    if ((nodename == (char *)NULL) && (servname == (char *)NULL)) {
133
            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);
134
        return EAI_NONAME;
135
    }
136
    switch (hints->ai_family) {
137
    case PF_UNSPEC:
138
    case PF_INET:
139
        family = AF_INET;
140
        break;
141
#ifdef CYGPKG_NET_INET6
142
    case PF_INET6:
143
        family = AF_INET6;
144
        break;
145
#endif
146
    default:
147
            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);
148
        return EAI_FAMILY;
149
    }
150
    // Allocate the first/primary result
151
    *res = ai = (struct addrinfo *)calloc(1, sizeof(struct addrinfo));
152
    if (ai == (struct addrinfo *)NULL) {
153
            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);
154
        return EAI_MEMORY;
155
    }
156
    // Handle request
157
    if (hints->ai_protocol != 0) {
158
        proto = getprotobynumber(hints->ai_protocol);
159
    }
160
    ai->ai_family = family;
161
    if (servname != (char *)NULL) {
162
        switch (hints->ai_socktype) {
163
        case 0:
164
        case SOCK_STREAM:
165
            protoname = "tcp";
166
            ai->ai_socktype = SOCK_STREAM;
167
            break;
168
        case SOCK_DGRAM:
169
            protoname = "udp";
170
            ai->ai_socktype = SOCK_DGRAM;
171
            break;
172
        default:
173
            freeaddrinfo(ai);
174
            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);
175
            return EAI_SOCKTYPE;
176
        }
177
        // See if this is just a port #
178
        if ((port = strtol(servname, 0, 0)) > 0) {
179
            ai->ai_socktype = hints->ai_socktype;
180
            if (hints->ai_socktype == 0) {
181
                // Need to have complete binding type/port
182
                freeaddrinfo(ai);
183
            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);
184
                return EAI_SERVICE;
185
            }
186
        } else {
187
            struct servent *serv = (struct servent *)NULL;
188
 
189
            serv = getservbyname(servname, protoname);
190
            if (serv == (struct servent *)NULL) {
191
                if (hints->ai_socktype == 0) {
192
                    protoname = "udp";
193
                    serv = getservbyname(servname, protoname);
194
                }
195
            }
196
            if (serv == (struct servent *)NULL) {
197
                freeaddrinfo(ai);
198
            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);
199
                return EAI_SERVICE;
200
            }
201
            port = ntohs(serv->s_port);
202
        }
203
        proto = getprotobyname(protoname);
204
        if (hints->ai_protocol && (hints->ai_protocol != proto->p_proto)) {
205
            freeaddrinfo(ai);
206
            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);
207
            return EAI_SOCKTYPE;
208
        }
209
        ai->ai_protocol = proto->p_proto;
210
    }
211
    // Iterate through address types and create addresses
212
    // Note: this does not handle the case where a given service can be
213
    // handled via multiple protocols, e.g. http/tcp & http/udp
214
    err = _getaddr(ai, nodename, hints, family, port);
215
    if (err != EAI_NONE) {
216
        freeaddrinfo(ai);
217
        return err;
218
    }
219
#ifdef CYGPKG_NET_INET6
220
    if (hints->ai_family == PF_UNSPEC) {
221
        // Add IPv6 address as well
222
        struct addrinfo *nai = (struct addrinfo *)calloc(1, sizeof(struct addrinfo));
223
        if (nai == (struct addrinfo *)NULL) {
224
            freeaddrinfo(ai);
225
            diag_printf("Error at %s.%d\n", __FUNCTION__, __LINE__);
226
            return EAI_MEMORY;
227
        }
228
        ai->ai_next = nai;
229
        nai->ai_family = PF_INET6;
230
        nai->ai_socktype = ai->ai_socktype;
231
        nai->ai_protocol = ai->ai_protocol;
232
        err = _getaddr(nai, nodename, hints, AF_INET6, port);
233
        if (err != EAI_NONE) {
234
            freeaddrinfo(*res);
235
            return err;
236
        }
237
    }
238
#endif
239
    // Note: null nodename is the same as 'localhost'
240
    if (nodename == (char *)NULL) {
241
        nodename = (const char *)"localhost";
242
    }
243
    if (hints->ai_flags & AI_CANONNAME) {
244
        // Hack - until host name handling is more complete
245
        ai = *res;  // Canonical name is only in primary record
246
        ai->ai_canonname = malloc(strlen(nodename)+1);
247
        if (ai->ai_canonname) {
248
            strcpy(ai->ai_canonname, nodename);
249
        }
250
    }
251
    if (hints->ai_flags & AI_PASSIVE) {
252
        // Incomplete addressing - used for bind/listen
253
    } else {
254
        // Complete addressing - used for connect/send/...
255
    }
256
    return EAI_NONE;  // No errors
257
}
258
 
259
void
260
freeaddrinfo(struct addrinfo *ai)
261
{
262
    struct addrinfo *next = ai;
263
 
264
    while ((ai = next) != (struct addrinfo *)NULL) {
265
        if (ai->ai_canonname) free(ai->ai_canonname);
266
        if (ai->ai_addr) free(ai->ai_addr);
267
        next = ai->ai_next;
268
        free(ai);
269
    }
270
}
271
 
272
char
273
*gai_strerror(int err)
274
{
275
    switch (err) {
276
    case EAI_NONE:
277
        return "EAI - no error";
278
    case EAI_AGAIN:
279
        return "EAI - temporary failure in name resolution";
280
    case EAI_BADFLAGS:
281
        return "EAI - invalid flags";
282
    case EAI_FAIL:
283
        return "EAI - non-recoverable failure in name resolution";
284
    case EAI_FAMILY:
285
        return "EAI - family not supported";
286
    case EAI_MEMORY:
287
        return "EAI - memory allocation failure";
288
    case EAI_NONAME:
289
        return "EAI - hostname nor servname provided, or not known";
290
    case EAI_SERVICE:
291
        return "EAI - servname not supported for socket type";
292
    case EAI_SOCKTYPE:
293
        return "EAI - socket type not supported";
294
    case EAI_SYSTEM:
295
        return "EAI - system error";
296
    case EAI_BADHINTS:
297
        return "EAI - inconsistent hints";
298
    case EAI_PROTOCOL:
299
        return "EAI - bad protocol";
300
    default:
301
        return "EAI - unknown error";
302
    }
303
}
304
 
305
// Set of flags implemented
306
#define NI_MASK (NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|NI_DGRAM)
307
 
308
int
309
getnameinfo (const struct sockaddr *sa, socklen_t salen,
310
             char *host, socklen_t hostlen,
311
             char *serv, socklen_t servlen,
312
             unsigned int flags)
313
{
314
    int port;
315
    char *s;
316
    struct servent *se;
317
 
318
    if ((flags & ~NI_MASK) != 0) {
319
        return EAI_BADFLAGS;
320
    }
321
    switch (sa->sa_family) {
322
    case PF_INET:
323
#ifdef CYGPKG_NET_INET6
324
    case PF_INET6:
325
#endif
326
        if (host != (char *)NULL) {
327
            s = _inet_ntop((struct sockaddr *)sa, host, hostlen);
328
            if (!s) {
329
                return EAI_FAIL;
330
            }
331
        }
332
        if (serv != (char *)NULL) {
333
            port = _inet_port((struct sockaddr *)sa);
334
            if (!port) {
335
                return EAI_FAIL;
336
            }
337
            se = (struct servent *)NULL;
338
            if ((flags & NI_NUMERICSERV) == 0) {
339
                if ((flags & NI_DGRAM) == 0) {
340
                    se = getservbyport(port, "tcp");
341
                }
342
                if (se == (struct servent *)NULL) {
343
                    se = getservbyport(port, "ucp");
344
                }
345
            }
346
            if (se != (struct servent *)NULL) {
347
                sprintf(serv, "%s/%s", se->s_name, se->s_proto);
348
            } else {
349
                sprintf(serv, "%d", port);
350
            }
351
        }
352
        break;
353
    default:
354
        return EAI_FAMILY;
355
    }
356
    return EAI_NONE;
357
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.