~ubuntu-branches/ubuntu/trusty/libssh/trusty

« back to all changes in this revision

Viewing changes to include/wspiapi.h

  • Committer: Bazaar Package Importer
  • Author(s): Laurent Bigonville
  • Date: 2009-12-12 14:29:12 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20091212142912-ha5g2iibt6nfnjq8
Tags: 0.4.0-1
* New upstream release.
  - Bump soname
  - Adjust .symbols file
* Readd static library in -dev package
* Let dh_lintian install override file
* debian/README.Debian: Update file
* debian/rules: Add list-missing rule

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*++
2
 
 
3
 
Copyright (c) 2000, Microsoft Corporation
4
 
 
5
 
Module Name:
6
 
    wspiapi.h
7
 
 
8
 
Abstract:
9
 
    The file contains protocol independent API functions.
10
 
 
11
 
Revision History:
12
 
    Wed Jul 12 10:50:31 2000, Created
13
 
 
14
 
--*/
15
 
 
16
 
#ifndef _WSPIAPI_H_
17
 
#define _WSPIAPI_H_
18
 
 
19
 
#include <stdio.h>              // sprintf()
20
 
#include <stdlib.h>             // calloc(), strtoul()
21
 
#include <malloc.h>             // calloc()
22
 
#include <string.h>             // strlen(), strcmp(), strstr()
23
 
 
24
 
#define WspiapiMalloc(tSize)    calloc(1, (tSize))
25
 
#define WspiapiFree(p)          free(p)
26
 
#define WspiapiSwap(a, b, c)    { (c) = (a); (a) = (b); (b) = (c); }
27
 
#define getaddrinfo             WspiapiGetAddrInfo
28
 
#define getnameinfo             WspiapiGetNameInfo
29
 
#define freeaddrinfo            WspiapiFreeAddrInfo
30
 
 
31
 
typedef int (WINAPI *WSPIAPI_PGETADDRINFO) (
32
 
    IN  const char                      *nodename,
33
 
    IN  const char                      *servname,
34
 
    IN  const struct addrinfo           *hints,
35
 
    OUT struct addrinfo                 **res);
36
 
 
37
 
typedef int (WINAPI *WSPIAPI_PGETNAMEINFO) (
38
 
    IN  const struct sockaddr           *sa,
39
 
    IN  socklen_t                       salen,
40
 
    OUT char                            *host,
41
 
    IN  size_t                          hostlen,
42
 
    OUT char                            *serv,
43
 
    IN  size_t                          servlen,
44
 
    IN  int                             flags);
45
 
 
46
 
typedef void (WINAPI *WSPIAPI_PFREEADDRINFO) (
47
 
    IN  struct addrinfo                 *ai);
48
 
 
49
 
 
50
 
 
51
 
#ifdef __cplusplus
52
 
extern "C" {
53
 
#endif
54
 
 
55
 
////////////////////////////////////////////////////////////
56
 
// v4 only versions of getaddrinfo and friends.
57
 
// NOTE: gai_strerror is inlined in ws2tcpip.h
58
 
////////////////////////////////////////////////////////////
59
 
 
60
 
__inline
61
 
char *
62
 
WINAPI
63
 
WspiapiStrdup (
64
 
        IN  const char *                    pszString)
65
 
/*++
66
 
 
67
 
Routine Description
68
 
    allocates enough storage via calloc() for a copy of the string,
69
 
    copies the string into the new memory, and returns a pointer to it.
70
 
 
71
 
Arguments
72
 
    pszString       string to copy into new memory
73
 
 
74
 
Return Value
75
 
    a pointer to the newly allocated storage with the string in it.
76
 
    NULL if enough memory could not be allocated, or string was NULL.
77
 
 
78
 
--*/
79
 
{
80
 
    char    *pszMemory;
81
 
 
82
 
    if (!pszString)
83
 
        return(NULL);
84
 
 
85
 
    pszMemory = (char *) WspiapiMalloc(strlen(pszString) + 1);
86
 
    if (!pszMemory)
87
 
        return(NULL);
88
 
 
89
 
    return(strcpy(pszMemory, pszString));
90
 
}
91
 
 
92
 
 
93
 
 
94
 
__inline
95
 
BOOL
96
 
WINAPI
97
 
WspiapiParseV4Address (
98
 
    IN  const char *                    pszAddress,
99
 
    OUT PDWORD                          pdwAddress)
100
 
/*++
101
 
 
102
 
Routine Description
103
 
    get the IPv4 address (in network byte order) from its string
104
 
    representation.  the syntax should be a.b.c.d.
105
 
 
106
 
Arguments
107
 
    pszArgument         string representation of the IPv4 address
108
 
    ptAddress           pointer to the resulting IPv4 address
109
 
 
110
 
Return Value
111
 
    Returns FALSE if there is an error, TRUE for success.
112
 
 
113
 
--*/
114
 
{
115
 
    DWORD       dwAddress   = 0;
116
 
    const char  *pcNext     = NULL;
117
 
    int         iCount      = 0;
118
 
 
119
 
    // ensure there are 3 '.' (periods)
120
 
    for (pcNext = pszAddress; *pcNext != '\0'; pcNext++)
121
 
        if (*pcNext == '.')
122
 
            iCount++;
123
 
    if (iCount != 3)
124
 
        return FALSE;
125
 
 
126
 
    // return an error if dwAddress is INADDR_NONE (255.255.255.255)
127
 
    // since this is never a valid argument to getaddrinfo.
128
 
    dwAddress = inet_addr(pszAddress);
129
 
    if (dwAddress == INADDR_NONE)
130
 
        return FALSE;
131
 
 
132
 
    *pdwAddress = dwAddress;
133
 
    return TRUE;
134
 
}
135
 
 
136
 
 
137
 
 
138
 
__inline
139
 
struct addrinfo *
140
 
WINAPI
141
 
WspiapiNewAddrInfo (
142
 
    IN  int                             iSocketType,
143
 
    IN  int                             iProtocol,
144
 
    IN  WORD                            wPort,
145
 
    IN  DWORD                           dwAddress)
146
 
/*++
147
 
 
148
 
Routine Description
149
 
    allocate an addrinfo structure and populate fields.
150
 
    IPv4 specific internal function, not exported.
151
 
 
152
 
Arguments
153
 
    iSocketType         SOCK_*.  can be wildcarded (zero).
154
 
    iProtocol           IPPROTO_*.  can be wildcarded (zero).
155
 
    wPort               port number of service (in network order).
156
 
    dwAddress           IPv4 address (in network order).
157
 
 
158
 
Return Value
159
 
    returns an addrinfo struct, or NULL if out of memory.
160
 
 
161
 
--*/
162
 
{
163
 
    struct addrinfo     *ptNew;
164
 
    struct sockaddr_in  *ptAddress;
165
 
 
166
 
    // allocate a new addrinfo structure.
167
 
    ptNew       =
168
 
        (struct addrinfo *) WspiapiMalloc(sizeof(struct addrinfo));
169
 
    if (!ptNew)
170
 
        return NULL;
171
 
 
172
 
    ptAddress   =
173
 
        (struct sockaddr_in *) WspiapiMalloc(sizeof(struct sockaddr_in));
174
 
    if (!ptAddress)
175
 
    {
176
 
        WspiapiFree(ptNew);
177
 
        return NULL;
178
 
    }
179
 
    ptAddress->sin_family       = AF_INET;
180
 
    ptAddress->sin_port         = wPort;
181
 
    ptAddress->sin_addr.s_addr  = dwAddress;
182
 
 
183
 
    // fill in the fields...
184
 
    ptNew->ai_family            = PF_INET;
185
 
    ptNew->ai_socktype          = iSocketType;
186
 
    ptNew->ai_protocol          = iProtocol;
187
 
    ptNew->ai_addrlen           = sizeof(struct sockaddr_in);
188
 
    ptNew->ai_addr              = (struct sockaddr *) ptAddress;
189
 
 
190
 
    return ptNew;
191
 
}
192
 
 
193
 
 
194
 
 
195
 
__inline
196
 
int
197
 
WINAPI
198
 
WspiapiQueryDNS(
199
 
    IN  const char                      *pszNodeName,
200
 
    IN  int                             iSocketType,
201
 
    IN  int                             iProtocol,
202
 
    IN  WORD                            wPort,
203
 
    OUT char                            *pszAlias,
204
 
    OUT struct addrinfo                 **pptResult)
205
 
/*++
206
 
 
207
 
Routine Description
208
 
    helper routine for WspiapiLookupNode.
209
 
    performs name resolution by querying the DNS for A records.
210
 
    *pptResult would need to be freed if an error is returned.
211
 
 
212
 
Arguments
213
 
    pszNodeName         name of node to resolve.
214
 
    iSocketType         SOCK_*.  can be wildcarded (zero).
215
 
    iProtocol           IPPROTO_*.  can be wildcarded (zero).
216
 
    wPort               port number of service (in network order).
217
 
    pszAlias            where to return the alias.
218
 
    pptResult           where to return the result.
219
 
 
220
 
Return Value
221
 
    Returns 0 on success, an EAI_* style error value otherwise.
222
 
 
223
 
--*/
224
 
{
225
 
    struct addrinfo **pptNext   = pptResult;
226
 
    struct hostent  *ptHost     = NULL;
227
 
    char            **ppAddresses;
228
 
 
229
 
    *pptNext    = NULL;
230
 
    pszAlias[0] = '\0';
231
 
 
232
 
    ptHost = gethostbyname(pszNodeName);
233
 
    if (ptHost)
234
 
    {
235
 
        if ((ptHost->h_addrtype == AF_INET)     &&
236
 
            (ptHost->h_length   == sizeof(struct in_addr)))
237
 
        {
238
 
            for (ppAddresses    = ptHost->h_addr_list;
239
 
                 *ppAddresses   != NULL;
240
 
                 ppAddresses++)
241
 
            {
242
 
                // create an addrinfo structure...
243
 
                *pptNext = WspiapiNewAddrInfo(
244
 
                    iSocketType,
245
 
                    iProtocol,
246
 
                    wPort,
247
 
                    ((struct in_addr *) *ppAddresses)->s_addr);
248
 
                if (!*pptNext)
249
 
                    return EAI_MEMORY;
250
 
 
251
 
                pptNext = &((*pptNext)->ai_next);
252
 
            }
253
 
        }
254
 
 
255
 
        // pick up the canonical name.
256
 
        strcpy(pszAlias, ptHost->h_name);
257
 
        return 0;
258
 
    }
259
 
 
260
 
    switch (WSAGetLastError())
261
 
    {
262
 
        case WSAHOST_NOT_FOUND: return EAI_NONAME;
263
 
        case WSATRY_AGAIN:      return EAI_AGAIN;
264
 
        case WSANO_RECOVERY:    return EAI_FAIL;
265
 
        case WSANO_DATA:        return EAI_NODATA;
266
 
        default:                return EAI_NONAME;
267
 
    }
268
 
}
269
 
 
270
 
 
271
 
 
272
 
__inline
273
 
int
274
 
WINAPI
275
 
WspiapiLookupNode(
276
 
    IN  const char                      *pszNodeName,
277
 
    IN  int                             iSocketType,
278
 
    IN  int                             iProtocol,
279
 
    IN  WORD                            wPort,
280
 
    IN  BOOL                            bAI_CANONNAME,
281
 
    OUT struct addrinfo                 **pptResult)
282
 
/*++
283
 
 
284
 
Routine Description
285
 
    resolve a nodename and return a list of addrinfo structures.
286
 
    IPv4 specific internal function, not exported.
287
 
    *pptResult would need to be freed if an error is returned.
288
 
 
289
 
    NOTE: if bAI_CANONNAME is true, the canonical name should be
290
 
          returned in the first addrinfo structure.
291
 
 
292
 
Arguments
293
 
    pszNodeName         name of node to resolve.
294
 
    iSocketType         SOCK_*.  can be wildcarded (zero).
295
 
    iProtocol           IPPROTO_*.  can be wildcarded (zero).
296
 
    wPort               port number of service (in network order).
297
 
    bAI_CANONNAME       whether the AI_CANONNAME flag is set.
298
 
    pptResult           where to return result.
299
 
 
300
 
Return Value
301
 
    Returns 0 on success, an EAI_* style error value otherwise.
302
 
 
303
 
--*/
304
 
{
305
 
    int     iError              = 0;
306
 
    int     iAliasCount         = 0;
307
 
 
308
 
    char    szFQDN1[NI_MAXHOST] = "";
309
 
    char    szFQDN2[NI_MAXHOST] = "";
310
 
    char    *pszName            = szFQDN1;
311
 
    char    *pszAlias           = szFQDN2;
312
 
    char    *pszScratch         = NULL;
313
 
    strcpy(pszName, pszNodeName);
314
 
 
315
 
    for (;;)
316
 
    {
317
 
        iError = WspiapiQueryDNS(pszNodeName,
318
 
                                 iSocketType,
319
 
                                 iProtocol,
320
 
                                 wPort,
321
 
                                 pszAlias,
322
 
                                 pptResult);
323
 
        if (iError)
324
 
            break;
325
 
 
326
 
        // if we found addresses, then we are done.
327
 
        if (*pptResult)
328
 
            break;
329
 
 
330
 
        // stop infinite loops due to DNS misconfiguration.  there appears
331
 
        // to be no particular recommended limit in RFCs 1034 and 1035.
332
 
        if ((!strlen(pszAlias))             ||
333
 
            (!strcmp(pszName, pszAlias))    ||
334
 
            (++iAliasCount == 16))
335
 
        {
336
 
            iError = EAI_FAIL;
337
 
            break;
338
 
        }
339
 
 
340
 
        // there was a new CNAME, look again.
341
 
        WspiapiSwap(pszName, pszAlias, pszScratch);
342
 
    }
343
 
 
344
 
    if (!iError && bAI_CANONNAME)
345
 
    {
346
 
        (*pptResult)->ai_canonname = WspiapiStrdup(pszAlias);
347
 
        if (!(*pptResult)->ai_canonname)
348
 
            iError = EAI_MEMORY;
349
 
    }
350
 
 
351
 
    return iError;
352
 
}
353
 
 
354
 
 
355
 
 
356
 
__inline
357
 
int
358
 
WINAPI
359
 
WspiapiClone (
360
 
    IN  WORD                            wPort,
361
 
    IN  struct addrinfo                 *ptResult)
362
 
/*++
363
 
 
364
 
Routine Description
365
 
    clone every addrinfo structure in ptResult for the UDP service.
366
 
    ptResult would need to be freed if an error is returned.
367
 
 
368
 
Arguments
369
 
    wPort               port number of UDP service.
370
 
    ptResult            list of addrinfo structures, each
371
 
                        of whose node needs to be cloned.
372
 
 
373
 
Return Value
374
 
    Returns 0 on success, an EAI_MEMORY on allocation failure.
375
 
 
376
 
--*/
377
 
{
378
 
    struct addrinfo *ptNext = NULL;
379
 
    struct addrinfo *ptNew  = NULL;
380
 
 
381
 
    for (ptNext = ptResult; ptNext != NULL; )
382
 
    {
383
 
        // create an addrinfo structure...
384
 
        ptNew = WspiapiNewAddrInfo(
385
 
            SOCK_DGRAM,
386
 
            ptNext->ai_protocol,
387
 
            wPort,
388
 
            ((struct sockaddr_in *) ptNext->ai_addr)->sin_addr.s_addr);
389
 
        if (!ptNew)
390
 
            break;
391
 
 
392
 
        // link the cloned addrinfo
393
 
        ptNew->ai_next  = ptNext->ai_next;
394
 
        ptNext->ai_next = ptNew;
395
 
        ptNext          = ptNew->ai_next;
396
 
    }
397
 
 
398
 
    if (ptNext != NULL)
399
 
        return EAI_MEMORY;
400
 
 
401
 
    return 0;
402
 
}
403
 
 
404
 
 
405
 
 
406
 
__inline
407
 
void
408
 
WINAPI
409
 
WspiapiLegacyFreeAddrInfo (
410
 
    IN  struct addrinfo                 *ptHead)
411
 
/*++
412
 
 
413
 
Routine Description
414
 
    Free an addrinfo structure (or chain of structures).
415
 
    As specified in RFC 2553, Section 6.4.
416
 
 
417
 
Arguments
418
 
    ptHead              structure (chain) to free
419
 
 
420
 
--*/
421
 
{
422
 
    struct addrinfo *ptNext;    // next strcture to free
423
 
 
424
 
    for (ptNext = ptHead; ptNext != NULL; ptNext = ptHead)
425
 
    {
426
 
        if (ptNext->ai_canonname)
427
 
            WspiapiFree(ptNext->ai_canonname);
428
 
 
429
 
        if (ptNext->ai_addr)
430
 
            WspiapiFree(ptNext->ai_addr);
431
 
 
432
 
        ptHead = ptNext->ai_next;
433
 
        WspiapiFree(ptNext);
434
 
    }
435
 
}
436
 
 
437
 
 
438
 
 
439
 
__inline
440
 
int
441
 
WINAPI
442
 
WspiapiLegacyGetAddrInfo(
443
 
    IN const char                       *pszNodeName,
444
 
    IN const char                       *pszServiceName,
445
 
    IN const struct addrinfo            *ptHints,
446
 
    OUT struct addrinfo                 **pptResult)
447
 
/*++
448
 
 
449
 
Routine Description
450
 
    Protocol-independent name-to-address translation.
451
 
    As specified in RFC 2553, Section 6.4.
452
 
    This is the hacked version that only supports IPv4.
453
 
 
454
 
Arguments
455
 
    pszNodeName         node name to lookup.
456
 
    pszServiceName      service name to lookup.
457
 
    ptHints             hints about how to process request.
458
 
    pptResult           where to return result.
459
 
 
460
 
Return Value
461
 
    returns zero if successful, an EAI_* error code if not.
462
 
 
463
 
--*/
464
 
{
465
 
    int                 iError      = 0;
466
 
    int                 iFlags      = 0;
467
 
    int                 iFamily     = PF_UNSPEC;
468
 
    int                 iSocketType = 0;
469
 
    int                 iProtocol   = 0;
470
 
    WORD                wPort       = 0;
471
 
    DWORD               dwAddress   = 0;
472
 
 
473
 
    struct servent      *ptService  = NULL;
474
 
    char                *pc         = NULL;
475
 
    BOOL                bClone      = FALSE;
476
 
    WORD                wTcpPort    = 0;
477
 
    WORD                wUdpPort    = 0;
478
 
 
479
 
 
480
 
    // initialize pptResult with default return value.
481
 
    *pptResult  = NULL;
482
 
 
483
 
 
484
 
    ////////////////////////////////////////
485
 
    // validate arguments...
486
 
    //
487
 
 
488
 
    // both the node name and the service name can't be NULL.
489
 
    if ((!pszNodeName) && (!pszServiceName))
490
 
        return EAI_NONAME;
491
 
 
492
 
    // validate hints.
493
 
    if (ptHints)
494
 
    {
495
 
        // all members other than ai_flags, ai_family, ai_socktype
496
 
        // and ai_protocol must be zero or a null pointer.
497
 
        if ((ptHints->ai_addrlen    != 0)       ||
498
 
            (ptHints->ai_canonname  != NULL)    ||
499
 
            (ptHints->ai_addr       != NULL)    ||
500
 
            (ptHints->ai_next       != NULL))
501
 
        {
502
 
            return EAI_FAIL;
503
 
        }
504
 
 
505
 
        // the spec has the "bad flags" error code, so presumably we
506
 
        // should check something here.  insisting that there aren't
507
 
        // any unspecified flags set would break forward compatibility,
508
 
        // however.  so we just check for non-sensical combinations.
509
 
        //
510
 
        // we cannot come up with a canonical name given a null node name.
511
 
        iFlags      = ptHints->ai_flags;
512
 
        if ((iFlags & AI_CANONNAME) && !pszNodeName)
513
 
            return EAI_BADFLAGS;
514
 
 
515
 
        // we only support a limited number of protocol families.
516
 
        iFamily     = ptHints->ai_family;
517
 
        if ((iFamily != PF_UNSPEC) && (iFamily != PF_INET))
518
 
            return EAI_FAMILY;
519
 
 
520
 
        // we only support only these socket types.
521
 
        iSocketType = ptHints->ai_socktype;
522
 
        if ((iSocketType != 0)                  &&
523
 
            (iSocketType != SOCK_STREAM)        &&
524
 
            (iSocketType != SOCK_DGRAM)         &&
525
 
            (iSocketType != SOCK_RAW))
526
 
            return EAI_SOCKTYPE;
527
 
 
528
 
        // REVIEW: What if ai_socktype and ai_protocol are at odds?
529
 
        iProtocol   = ptHints->ai_protocol;
530
 
    }
531
 
 
532
 
 
533
 
    ////////////////////////////////////////
534
 
    // do service lookup...
535
 
 
536
 
    if (pszServiceName)
537
 
    {
538
 
        wPort = (WORD) strtoul(pszServiceName, &pc, 10);
539
 
        if (*pc == '\0')        // numeric port string
540
 
        {
541
 
            wPort = wTcpPort = wUdpPort = htons(wPort);
542
 
            if (iSocketType == 0)
543
 
            {
544
 
                bClone      = TRUE;
545
 
                iSocketType = SOCK_STREAM;
546
 
            }
547
 
        }
548
 
        else                    // non numeric port string
549
 
        {
550
 
            if ((iSocketType == 0) || (iSocketType == SOCK_DGRAM))
551
 
            {
552
 
                ptService = getservbyname(pszServiceName, "udp");
553
 
                if (ptService)
554
 
                    wPort = wUdpPort = ptService->s_port;
555
 
            }
556
 
 
557
 
            if ((iSocketType == 0) || (iSocketType == SOCK_STREAM))
558
 
            {
559
 
                ptService = getservbyname(pszServiceName, "tcp");
560
 
                if (ptService)
561
 
                    wPort = wTcpPort = ptService->s_port;
562
 
            }
563
 
 
564
 
            // assumes 0 is an invalid service port...
565
 
            if (wPort == 0)     // no service exists
566
 
                return (iSocketType ? EAI_SERVICE : EAI_NONAME);
567
 
 
568
 
            if (iSocketType == 0)
569
 
            {
570
 
                // if both tcp and udp, process tcp now & clone udp later.
571
 
                iSocketType = (wTcpPort) ? SOCK_STREAM : SOCK_DGRAM;
572
 
                bClone      = (wTcpPort && wUdpPort);
573
 
            }
574
 
        }
575
 
    }
576
 
 
577
 
 
578
 
 
579
 
    ////////////////////////////////////////
580
 
    // do node name lookup...
581
 
 
582
 
    // if we weren't given a node name,
583
 
    // return the wildcard or loopback address (depending on AI_PASSIVE).
584
 
    //
585
 
    // if we have a numeric host address string,
586
 
    // return the binary address.
587
 
    //
588
 
    if ((!pszNodeName) || (WspiapiParseV4Address(pszNodeName, &dwAddress)))
589
 
    {
590
 
        if (!pszNodeName)
591
 
        {
592
 
            dwAddress = htonl((iFlags & AI_PASSIVE)
593
 
                              ? INADDR_ANY
594
 
                              : INADDR_LOOPBACK);
595
 
        }
596
 
 
597
 
        // create an addrinfo structure...
598
 
        *pptResult =
599
 
            WspiapiNewAddrInfo(iSocketType, iProtocol, wPort, dwAddress);
600
 
        if (!(*pptResult))
601
 
            iError = EAI_MEMORY;
602
 
 
603
 
        if (!iError && pszNodeName)
604
 
        {
605
 
            // implementation specific behavior: set AI_NUMERICHOST
606
 
            // to indicate that we got a numeric host address string.
607
 
            (*pptResult)->ai_flags |= AI_NUMERICHOST;
608
 
 
609
 
            // return the numeric address string as the canonical name
610
 
            if (iFlags & AI_CANONNAME)
611
 
            {
612
 
                (*pptResult)->ai_canonname =
613
 
                    WspiapiStrdup(inet_ntoa(*((struct in_addr *) &dwAddress)));
614
 
                if (!(*pptResult)->ai_canonname)
615
 
                    iError = EAI_MEMORY;
616
 
            }
617
 
        }
618
 
    }
619
 
 
620
 
 
621
 
    // if we do not have a numeric host address string and
622
 
    // AI_NUMERICHOST flag is set, return an error!
623
 
    else if (iFlags & AI_NUMERICHOST)
624
 
    {
625
 
        iError = EAI_NONAME;
626
 
    }
627
 
 
628
 
 
629
 
    // since we have a non-numeric node name,
630
 
    // we have to do a regular node name lookup.
631
 
    else
632
 
    {
633
 
        iError = WspiapiLookupNode(pszNodeName,
634
 
                                   iSocketType,
635
 
                                   iProtocol,
636
 
                                   wPort,
637
 
                                   (iFlags & AI_CANONNAME),
638
 
                                   pptResult);
639
 
    }
640
 
 
641
 
    if (!iError && bClone)
642
 
    {
643
 
        iError = WspiapiClone(wUdpPort, *pptResult);
644
 
    }
645
 
 
646
 
    if (iError)
647
 
    {
648
 
        WspiapiLegacyFreeAddrInfo(*pptResult);
649
 
        *pptResult  = NULL;
650
 
    }
651
 
 
652
 
    return (iError);
653
 
}
654
 
 
655
 
 
656
 
 
657
 
__inline
658
 
int
659
 
WINAPI
660
 
WspiapiLegacyGetNameInfo(
661
 
    IN  const struct sockaddr           *ptSocketAddress,
662
 
    IN  socklen_t                       tSocketLength,
663
 
    OUT char                            *pszNodeName,
664
 
    IN  size_t                          tNodeLength,
665
 
    OUT char                            *pszServiceName,
666
 
    IN  size_t                          tServiceLength,
667
 
    IN  int                             iFlags)
668
 
/*++
669
 
 
670
 
Routine Description
671
 
    protocol-independent address-to-name translation.
672
 
    as specified in RFC 2553, Section 6.5.
673
 
    this is the hacked version that only supports IPv4.
674
 
 
675
 
Arguments
676
 
    ptSocketAddress     socket address to translate.
677
 
    tSocketLength       length of above socket address.
678
 
    pszNodeName         where to return the node name.
679
 
    tNodeLength         size of above buffer.
680
 
    pszServiceName      where to return the service name.
681
 
    tServiceLength      size of above buffer.
682
 
    iFlags              flags of type NI_*.
683
 
 
684
 
Return Value
685
 
    returns zero if successful, an EAI_* error code if not.
686
 
 
687
 
--*/
688
 
{
689
 
    struct servent  *ptService;
690
 
    WORD            wPort;
691
 
    char            szBuffer[]  = "65535";
692
 
    char            *pszService = szBuffer;
693
 
 
694
 
    struct hostent  *ptHost;
695
 
    struct in_addr  tAddress;
696
 
    char            *pszNode    = NULL;
697
 
    char            *pc         = NULL;
698
 
 
699
 
 
700
 
    // sanity check ptSocketAddress and tSocketLength.
701
 
    if (!ptSocketAddress)
702
 
        return EAI_FAIL;
703
 
 
704
 
    if ((ptSocketAddress->sa_family != AF_INET)     ||
705
 
        (tSocketLength != sizeof(struct sockaddr_in)))
706
 
    {
707
 
        return EAI_FAMILY;
708
 
    }
709
 
 
710
 
    if (!(pszNodeName && tNodeLength) &&
711
 
        !(pszServiceName && tServiceLength))
712
 
    {
713
 
        return EAI_NONAME;
714
 
    }
715
 
 
716
 
    // the draft has the "bad flags" error code, so presumably we
717
 
    // should check something here.  insisting that there aren't
718
 
    // any unspecified flags set would break forward compatibility,
719
 
    // however.  so we just check for non-sensical combinations.
720
 
    if ((iFlags & NI_NUMERICHOST) && (iFlags & NI_NAMEREQD))
721
 
    {
722
 
        return EAI_BADFLAGS;
723
 
    }
724
 
 
725
 
    // translate the port to a service name (if requested).
726
 
    if (pszServiceName && tServiceLength)
727
 
    {
728
 
        wPort = ((struct sockaddr_in *) ptSocketAddress)->sin_port;
729
 
 
730
 
        if (iFlags & NI_NUMERICSERV)
731
 
        {
732
 
            // return numeric form of the address.
733
 
            sprintf(szBuffer, "%u", ntohs(wPort));
734
 
        }
735
 
        else
736
 
        {
737
 
            // return service name corresponding to port.
738
 
            ptService = getservbyport(wPort,
739
 
                                      (iFlags & NI_DGRAM) ? "udp" : NULL);
740
 
            if (ptService && ptService->s_name)
741
 
            {
742
 
                // lookup successful.
743
 
                pszService = ptService->s_name;
744
 
            }
745
 
            else
746
 
            {
747
 
                // DRAFT: return numeric form of the port!
748
 
                sprintf(szBuffer, "%u", ntohs(wPort));
749
 
            }
750
 
        }
751
 
 
752
 
 
753
 
        if (tServiceLength > strlen(pszService))
754
 
            strcpy(pszServiceName, pszService);
755
 
        else
756
 
            return EAI_FAIL;
757
 
    }
758
 
 
759
 
 
760
 
    // translate the address to a node name (if requested).
761
 
    if (pszNodeName && tNodeLength)
762
 
    {
763
 
        // this is the IPv4-only version, so we have an IPv4 address.
764
 
        tAddress = ((struct sockaddr_in *) ptSocketAddress)->sin_addr;
765
 
 
766
 
        if (iFlags & NI_NUMERICHOST)
767
 
        {
768
 
            // return numeric form of the address.
769
 
            pszNode  = inet_ntoa(tAddress);
770
 
        }
771
 
        else
772
 
        {
773
 
            // return node name corresponding to address.
774
 
            ptHost = gethostbyaddr((char *) &tAddress,
775
 
                                   sizeof(struct in_addr),
776
 
                                   AF_INET);
777
 
            if (ptHost && ptHost->h_name)
778
 
            {
779
 
                // DNS lookup successful.
780
 
                // stop copying at a "." if NI_NOFQDN is specified.
781
 
                pszNode = ptHost->h_name;
782
 
                if ((iFlags & NI_NOFQDN) && (pc = strchr(pszNode, '.')))
783
 
                    *pc = '\0';
784
 
            }
785
 
            else
786
 
            {
787
 
                // DNS lookup failed.  return numeric form of the address.
788
 
                if (iFlags & NI_NAMEREQD)
789
 
                {
790
 
                    switch (WSAGetLastError())
791
 
                    {
792
 
                        case WSAHOST_NOT_FOUND: return EAI_NONAME;
793
 
                        case WSATRY_AGAIN:      return EAI_AGAIN;
794
 
                        case WSANO_RECOVERY:    return EAI_FAIL;
795
 
                        default:                return EAI_NONAME;
796
 
                    }
797
 
                }
798
 
                else
799
 
                    pszNode  = inet_ntoa(tAddress);
800
 
            }
801
 
        }
802
 
 
803
 
        if (tNodeLength > strlen(pszNode))
804
 
            strcpy(pszNodeName, pszNode);
805
 
        else
806
 
            return EAI_FAIL;
807
 
    }
808
 
 
809
 
    return 0;
810
 
}
811
 
 
812
 
 
813
 
 
814
 
typedef struct
815
 
{
816
 
    char const          *pszName;
817
 
    FARPROC             pfAddress;
818
 
} WSPIAPI_FUNCTION;
819
 
 
820
 
#define WSPIAPI_FUNCTION_ARRAY                                  \
821
 
{                                                               \
822
 
    "getaddrinfo",      (FARPROC) WspiapiLegacyGetAddrInfo,     \
823
 
    "getnameinfo",      (FARPROC) WspiapiLegacyGetNameInfo,     \
824
 
    "freeaddrinfo",     (FARPROC) WspiapiLegacyFreeAddrInfo,    \
825
 
}
826
 
 
827
 
 
828
 
 
829
 
__inline
830
 
FARPROC
831
 
WINAPI
832
 
WspiapiLoad(
833
 
    IN  WORD                            wFunction)
834
 
/*++
835
 
 
836
 
Routine Description
837
 
    try to locate the address family independent name resolution routines
838
 
    (i.e. getaddrinfo, getnameinfo, freeaddrinfo, gai_strerror).
839
 
 
840
 
Locks
841
 
    this function call is not synchronized.  hence the library containing
842
 
    the routines might be loaded multiple times.  another option is to
843
 
    synchronize through a spin lock using a static local variable and the
844
 
    InterlockedExchange operation.
845
 
 
846
 
 
847
 
Arguments
848
 
    wFunction           ordinal # of the function to get the pointer to
849
 
                        0   getaddrinfo
850
 
                        1   getnameinfo
851
 
                        2   freeaddrinfo
852
 
 
853
 
Return Value
854
 
    address of the library/legacy routine
855
 
 
856
 
--*/
857
 
{
858
 
    HMODULE                 hLibrary        = NULL;
859
 
 
860
 
    // these static variables store state across calls, across threads.
861
 
    static BOOL             bInitialized    = FALSE;
862
 
    static WSPIAPI_FUNCTION rgtGlobal[]     = WSPIAPI_FUNCTION_ARRAY;
863
 
    static const int        iNumGlobal      = (sizeof(rgtGlobal) /
864
 
                                               sizeof(WSPIAPI_FUNCTION));
865
 
 
866
 
    // we overwrite rgtGlobal only if all routines exist in library.
867
 
    WSPIAPI_FUNCTION        rgtLocal[]      = WSPIAPI_FUNCTION_ARRAY;
868
 
    FARPROC                 fScratch        = NULL;
869
 
    int                     i               = 0;
870
 
 
871
 
 
872
 
    if (bInitialized)           // WspiapiLoad has already been called once
873
 
        return (rgtGlobal[wFunction].pfAddress);
874
 
 
875
 
    do                          // breakout loop
876
 
    {
877
 
        // in Whistler and beyond...
878
 
        // the routines are present in the WinSock 2 library (ws2_32.dll).
879
 
        // printf("Looking in ws2_32 for getaddrinfo...\n");
880
 
        hLibrary = LoadLibraryA("ws2_32");
881
 
        if (hLibrary != NULL)
882
 
        {
883
 
            fScratch = GetProcAddress(hLibrary, "getaddrinfo");
884
 
            if (fScratch == NULL)
885
 
            {
886
 
                FreeLibrary(hLibrary);
887
 
                hLibrary = NULL;
888
 
            }
889
 
        }
890
 
        if (hLibrary != NULL)
891
 
            break;
892
 
 
893
 
 
894
 
        // in the IPv6 Technology Preview...
895
 
        // the routines are present in the IPv6 WinSock library (wship6.dll).
896
 
        // printf("Looking in wship6 for getaddrinfo...\n");
897
 
        hLibrary = LoadLibraryA("wship6");
898
 
        if (hLibrary != NULL)
899
 
        {
900
 
            fScratch = GetProcAddress(hLibrary, "getaddrinfo");
901
 
            if (fScratch == NULL)
902
 
            {
903
 
                FreeLibrary(hLibrary);
904
 
                hLibrary = NULL;
905
 
            }
906
 
        }
907
 
    } while (FALSE);
908
 
 
909
 
 
910
 
    if (hLibrary != NULL)
911
 
    {
912
 
        // use routines from this library...
913
 
        // since getaddrinfo is here, we expect all routines to be here,
914
 
        // but will fall back to IPv4-only if any of them is missing.
915
 
        for (i = 0; i < iNumGlobal; i++)
916
 
        {
917
 
            rgtLocal[i].pfAddress
918
 
                = GetProcAddress(hLibrary, rgtLocal[i].pszName);
919
 
            if (rgtLocal[i].pfAddress == NULL)
920
 
            {
921
 
                FreeLibrary(hLibrary);
922
 
                hLibrary = NULL;
923
 
                break;
924
 
            }
925
 
        }
926
 
 
927
 
        if (hLibrary != NULL)
928
 
        {
929
 
            // printf("found!\n");
930
 
            for (i = 0; i < iNumGlobal; i++)
931
 
                rgtGlobal[i].pfAddress = rgtLocal[i].pfAddress;
932
 
        }
933
 
    }
934
 
 
935
 
    bInitialized = TRUE;
936
 
    return (rgtGlobal[wFunction].pfAddress);
937
 
}
938
 
 
939
 
 
940
 
 
941
 
__inline
942
 
int
943
 
WINAPI
944
 
WspiapiGetAddrInfo(
945
 
    IN const char                       *nodename,
946
 
    IN const char                       *servname,
947
 
    IN const struct addrinfo            *hints,
948
 
    OUT struct addrinfo                 **res)
949
 
{
950
 
    static WSPIAPI_PGETADDRINFO     pfGetAddrInfo   = NULL;
951
 
 
952
 
    if (!pfGetAddrInfo)
953
 
        pfGetAddrInfo   = (WSPIAPI_PGETADDRINFO) WspiapiLoad(0);
954
 
    return ((*pfGetAddrInfo)
955
 
            (nodename, servname, hints, res));
956
 
}
957
 
 
958
 
 
959
 
 
960
 
__inline
961
 
int
962
 
WINAPI
963
 
WspiapiGetNameInfo (
964
 
    IN  const struct sockaddr           *sa,
965
 
    IN  socklen_t                       salen,
966
 
    OUT char                            *host,
967
 
    IN  size_t                          hostlen,
968
 
    OUT char                            *serv,
969
 
    IN  size_t                          servlen,
970
 
    IN  int                             flags)
971
 
{
972
 
    static WSPIAPI_PGETNAMEINFO     pfGetNameInfo   = NULL;
973
 
 
974
 
    if (!pfGetNameInfo)
975
 
        pfGetNameInfo   = (WSPIAPI_PGETNAMEINFO) WspiapiLoad(1);
976
 
    return ((*pfGetNameInfo)
977
 
            (sa, salen, host, hostlen, serv, servlen, flags));
978
 
}
979
 
 
980
 
 
981
 
 
982
 
__inline
983
 
void
984
 
WINAPI
985
 
WspiapiFreeAddrInfo (
986
 
    IN  struct addrinfo                 *ai)
987
 
{
988
 
    static WSPIAPI_PFREEADDRINFO    pfFreeAddrInfo   = NULL;
989
 
 
990
 
    if (!pfFreeAddrInfo)
991
 
        pfFreeAddrInfo  = (WSPIAPI_PFREEADDRINFO) WspiapiLoad(2);
992
 
    (*pfFreeAddrInfo)(ai);
993
 
}
994
 
 
995
 
#ifdef  __cplusplus
996
 
}
997
 
#endif
998
 
 
999
 
#endif // _WSPIAPI_H_