Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
liblongpath-rsync
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
liblongpath
liblongpath-rsync
Commits
9f802c72
Commit
9f802c72
authored
Nov 02, 2007
by
Wayne Davison
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
A new version of the getaddrinfo code from the samba source.
parent
6e1fa33f
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
675 additions
and
0 deletions
+675
-0
addrinfo.h
lib/addrinfo.h
+174
-0
getaddrinfo.c
lib/getaddrinfo.c
+501
-0
No files found.
lib/addrinfo.h
0 → 100644
View file @
9f802c72
/*
PostgreSQL Database Management System
(formerly known as Postgres, then as Postgres95)
Portions Copyright (c) 1996-2005, The PostgreSQL Global Development Group
Portions Copyright (c) 1994, The Regents of the University of California
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose, without fee, and without a written agreement
is hereby granted, provided that the above copyright notice and this paragraph
and the following two paragraphs appear in all copies.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS
TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/*-------------------------------------------------------------------------
*
* getaddrinfo.h
* Support getaddrinfo() on platforms that don't have it.
*
* Note: we use our own routines on platforms that don't HAVE_STRUCT_ADDRINFO,
* whether or not the library routine getaddrinfo() can be found. This
* policy is needed because on some platforms a manually installed libbind.a
* may provide getaddrinfo(), yet the system headers may not provide the
* struct definitions needed to call it. To avoid conflict with the libbind
* definition in such cases, we rename our routines to pg_xxx() via macros.
*
* This code will also work on platforms where struct addrinfo is defined
* in the system headers but no getaddrinfo() can be located.
*
* Copyright (c) 2003-2007, PostgreSQL Global Development Group
*
*-------------------------------------------------------------------------
*/
#ifndef ADDRINFO_H
#define ADDRINFO_H
/* Various macros that ought to be in <netdb.h>, but might not be */
#ifndef EAI_FAIL
#define EAI_BADFLAGS (-1)
#define EAI_NONAME (-2)
#define EAI_AGAIN (-3)
#define EAI_FAIL (-4)
#define EAI_FAMILY (-6)
#define EAI_SOCKTYPE (-7)
#define EAI_SERVICE (-8)
#define EAI_MEMORY (-10)
#define EAI_SYSTEM (-11)
#endif
/* !EAI_FAIL */
#ifndef AI_PASSIVE
#define AI_PASSIVE 0x0001
#endif
#ifndef AI_NUMERICHOST
/*
* some platforms don't support AI_NUMERICHOST; define as zero if using
* the system version of getaddrinfo...
*/
#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO)
#define AI_NUMERICHOST 0
#else
#define AI_NUMERICHOST 0x0004
#endif
#endif
#ifndef AI_CANONNAME
#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO)
#define AI_CANONNAME 0
#else
#define AI_CANONNAME 0x0008
#endif
#endif
#ifndef AI_NUMERICSERV
#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO)
#define AI_NUMERICSERV 0
#else
#define AI_NUMERICSERV 0x0010
#endif
#endif
#ifndef NI_NUMERICHOST
#define NI_NUMERICHOST 1
#endif
#ifndef NI_NUMERICSERV
#define NI_NUMERICSERV 2
#endif
#ifndef NI_NOFQDN
#define NI_NOFQDN 4
#endif
#ifndef NI_NAMEREQD
#define NI_NAMEREQD 8
#endif
#ifndef NI_DGRAM
#define NI_DGRAM 16
#endif
#ifndef NI_MAXHOST
#define NI_MAXHOST 1025
#endif
#ifndef NI_MAXSERV
#define NI_MAXSERV 32
#endif
#ifndef HAVE_STRUCT_ADDRINFO
struct
addrinfo
{
int
ai_flags
;
int
ai_family
;
int
ai_socktype
;
int
ai_protocol
;
size_t
ai_addrlen
;
struct
sockaddr
*
ai_addr
;
char
*
ai_canonname
;
struct
addrinfo
*
ai_next
;
};
#endif
/* HAVE_STRUCT_ADDRINFO */
#ifndef HAVE_GETADDRINFO
/* Rename private copies per comments above */
#ifdef getaddrinfo
#undef getaddrinfo
#endif
#define getaddrinfo pg_getaddrinfo
#ifdef freeaddrinfo
#undef freeaddrinfo
#endif
#define freeaddrinfo pg_freeaddrinfo
#ifdef gai_strerror
#undef gai_strerror
#endif
#define gai_strerror pg_gai_strerror
#ifdef getnameinfo
#undef getnameinfo
#endif
#define getnameinfo pg_getnameinfo
extern
int
getaddrinfo
(
const
char
*
node
,
const
char
*
service
,
const
struct
addrinfo
*
hints
,
struct
addrinfo
**
res
);
extern
void
freeaddrinfo
(
struct
addrinfo
*
res
);
extern
const
char
*
gai_strerror
(
int
errcode
);
extern
int
getnameinfo
(
const
struct
sockaddr
*
sa
,
socklen_t
salen
,
char
*
node
,
size_t
nodelen
,
char
*
service
,
size_t
servicelen
,
int
flags
);
#endif
/* HAVE_GETADDRINFO */
#endif
/* ADDRINFO_H */
lib/getaddrinfo.c
0 → 100644
View file @
9f802c72
/*
PostgreSQL Database Management System
(formerly known as Postgres, then as Postgres95)
Portions Copyright (c) 1996-2005, The PostgreSQL Global Development Group
Portions Copyright (c) 1994, The Regents of the University of California
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose, without fee, and without a written agreement
is hereby granted, provided that the above copyright notice and this paragraph
and the following two paragraphs appear in all copies.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS
TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/*-------------------------------------------------------------------------
*
* getaddrinfo.c
* Support getaddrinfo() on platforms that don't have it.
*
* We also supply getnameinfo() here, assuming that the platform will have
* it if and only if it has getaddrinfo(). If this proves false on some
* platform, we'll need to split this file and provide a separate configure
* test for getnameinfo().
*
* Copyright (c) 2003-2007, PostgreSQL Global Development Group
*
* Copyright (C) 2007 Jeremy Allison.
* Modified to return multiple IPv4 addresses for Samba.
*
*-------------------------------------------------------------------------
*/
#include "rsync.h"
#ifndef SMB_MALLOC
#define SMB_MALLOC(s) malloc(s)
#endif
#ifndef SMB_STRDUP
#define SMB_STRDUP(s) strdup(s)
#endif
static
int
check_hostent_err
(
struct
hostent
*
hp
)
{
if
(
!
hp
)
{
switch
(
h_errno
)
{
case
HOST_NOT_FOUND
:
case
NO_DATA
:
return
EAI_NONAME
;
case
TRY_AGAIN
:
return
EAI_AGAIN
;
case
NO_RECOVERY
:
default:
return
EAI_FAIL
;
}
}
if
(
!
hp
->
h_name
||
hp
->
h_addrtype
!=
AF_INET
)
{
return
EAI_FAIL
;
}
return
0
;
}
static
char
*
canon_name_from_hostent
(
struct
hostent
*
hp
,
int
*
perr
)
{
char
*
ret
=
NULL
;
*
perr
=
check_hostent_err
(
hp
);
if
(
*
perr
)
{
return
NULL
;
}
ret
=
SMB_STRDUP
(
hp
->
h_name
);
if
(
!
ret
)
{
*
perr
=
EAI_MEMORY
;
}
return
ret
;
}
static
char
*
get_my_canon_name
(
int
*
perr
)
{
char
name
[
HOST_NAME_MAX
+
1
];
if
(
gethostname
(
name
,
HOST_NAME_MAX
)
==
-
1
)
{
*
perr
=
EAI_FAIL
;
return
NULL
;
}
/* Ensure null termination. */
name
[
HOST_NAME_MAX
]
=
'\0'
;
return
canon_name_from_hostent
(
gethostbyname
(
name
),
perr
);
}
static
char
*
get_canon_name_from_addr
(
struct
in_addr
ip
,
int
*
perr
)
{
return
canon_name_from_hostent
(
gethostbyaddr
(
&
ip
,
sizeof
(
ip
),
AF_INET
),
perr
);
}
static
struct
addrinfo
*
alloc_entry
(
const
struct
addrinfo
*
hints
,
struct
in_addr
ip
,
unsigned
short
port
)
{
struct
sockaddr_in
*
psin
=
NULL
;
struct
addrinfo
*
ai
=
SMB_MALLOC
(
sizeof
(
*
ai
));
if
(
!
ai
)
{
return
NULL
;
}
memset
(
ai
,
'\0'
,
sizeof
(
*
ai
));
psin
=
SMB_MALLOC
(
sizeof
(
*
psin
));
if
(
!
psin
)
{
free
(
ai
);
return
NULL
;
}
memset
(
psin
,
'\0'
,
sizeof
(
*
psin
));
psin
->
sin_family
=
AF_INET
;
psin
->
sin_port
=
htons
(
port
);
psin
->
sin_addr
=
ip
;
ai
->
ai_flags
=
0
;
ai
->
ai_family
=
AF_INET
;
ai
->
ai_socktype
=
hints
->
ai_socktype
;
ai
->
ai_protocol
=
hints
->
ai_protocol
;
ai
->
ai_addrlen
=
sizeof
(
*
psin
);
ai
->
ai_addr
=
(
struct
sockaddr
*
)
psin
;
ai
->
ai_canonname
=
NULL
;
ai
->
ai_next
=
NULL
;
return
ai
;
}
/*
* get address info for a single ipv4 address.
*
* Bugs: - servname can only be a number, not text.
*/
static
int
getaddr_info_single_addr
(
const
char
*
service
,
uint32_t
addr
,
const
struct
addrinfo
*
hints
,
struct
addrinfo
**
res
)
{
struct
addrinfo
*
ai
=
NULL
;
struct
in_addr
ip
;
unsigned
short
port
=
0
;
if
(
service
)
{
port
=
(
unsigned
short
)
atoi
(
service
);
}
ip
.
s_addr
=
htonl
(
addr
);
ai
=
alloc_entry
(
hints
,
ip
,
port
);
if
(
!
ai
)
{
return
EAI_MEMORY
;
}
/* If we're asked for the canonical name,
* make sure it returns correctly. */
if
(
!
(
hints
->
ai_flags
&
AI_NUMERICSERV
)
&&
hints
->
ai_flags
&
AI_CANONNAME
)
{
int
err
;
if
(
addr
==
INADDR_LOOPBACK
||
addr
==
INADDR_ANY
)
{
ai
->
ai_canonname
=
get_my_canon_name
(
&
err
);
}
else
{
ai
->
ai_canonname
=
get_canon_name_from_addr
(
ip
,
&
err
);
}
if
(
ai
->
ai_canonname
==
NULL
)
{
freeaddrinfo
(
ai
);
return
err
;
}
}
*
res
=
ai
;
return
0
;
}
/*
* get address info for multiple ipv4 addresses.
*
* Bugs: - servname can only be a number, not text.
*/
static
int
getaddr_info_name
(
const
char
*
node
,
const
char
*
service
,
const
struct
addrinfo
*
hints
,
struct
addrinfo
**
res
)
{
struct
addrinfo
*
listp
=
NULL
,
*
prevp
=
NULL
;
char
**
pptr
=
NULL
;
int
err
;
struct
hostent
*
hp
=
NULL
;
unsigned
short
port
=
0
;
if
(
service
)
{
port
=
(
unsigned
short
)
atoi
(
service
);
}
hp
=
gethostbyname
(
node
);
err
=
check_hostent_err
(
hp
);
if
(
err
)
{
return
err
;
}
for
(
pptr
=
hp
->
h_addr_list
;
*
pptr
;
pptr
++
)
{
struct
in_addr
ip
=
*
(
struct
in_addr
*
)
*
pptr
;
struct
addrinfo
*
ai
=
alloc_entry
(
hints
,
ip
,
port
);
if
(
!
ai
)
{
freeaddrinfo
(
listp
);
return
EAI_MEMORY
;
}
if
(
!
listp
)
{
listp
=
ai
;
prevp
=
ai
;
ai
->
ai_canonname
=
SMB_STRDUP
(
hp
->
h_name
);
if
(
!
ai
->
ai_canonname
)
{
freeaddrinfo
(
listp
);
return
EAI_MEMORY
;
}
}
else
{
prevp
->
ai_next
=
ai
;
prevp
=
ai
;
}
}
*
res
=
listp
;
return
0
;
}
/*
* get address info for ipv4 sockets.
*
* Bugs: - servname can only be a number, not text.
*/
int
getaddrinfo
(
const
char
*
node
,
const
char
*
service
,
const
struct
addrinfo
*
hintp
,
struct
addrinfo
**
res
)
{
struct
addrinfo
hints
;
/* Setup the hints struct. */
if
(
hintp
==
NULL
)
{
memset
(
&
hints
,
0
,
sizeof
(
hints
));
hints
.
ai_family
=
AF_INET
;
hints
.
ai_socktype
=
SOCK_STREAM
;
}
else
{
memcpy
(
&
hints
,
hintp
,
sizeof
(
hints
));
}
if
(
hints
.
ai_family
!=
AF_INET
&&
hints
.
ai_family
!=
AF_UNSPEC
)
{
return
EAI_FAMILY
;
}
if
(
hints
.
ai_socktype
==
0
)
{
hints
.
ai_socktype
=
SOCK_STREAM
;
}
if
(
!
node
&&
!
service
)
{
return
EAI_NONAME
;
}
if
(
node
)
{
if
(
node
[
0
]
==
'\0'
)
{
return
getaddr_info_single_addr
(
service
,
INADDR_ANY
,
&
hints
,
res
);
}
else
if
(
hints
.
ai_flags
&
AI_NUMERICHOST
)
{
struct
in_addr
ip
;
if
(
!
inet_aton
(
node
,
&
ip
))
{
return
EAI_FAIL
;
}
return
getaddr_info_single_addr
(
service
,
ntohl
(
ip
.
s_addr
),
&
hints
,
res
);
}
else
{
return
getaddr_info_name
(
node
,
service
,
&
hints
,
res
);
}
}
else
if
(
hints
.
ai_flags
&
AI_PASSIVE
)
{
return
getaddr_info_single_addr
(
service
,
INADDR_ANY
,
&
hints
,
res
);
}
return
getaddr_info_single_addr
(
service
,
INADDR_LOOPBACK
,
&
hints
,
res
);
}
void
freeaddrinfo
(
struct
addrinfo
*
res
)
{
struct
addrinfo
*
next
=
NULL
;
for
(;
res
;
res
=
next
)
{
next
=
res
->
ai_next
;
if
(
res
->
ai_canonname
)
{
free
(
res
->
ai_canonname
);
}
if
(
res
->
ai_addr
)
{
free
(
res
->
ai_addr
);
}
free
(
res
);
}
}
const
char
*
gai_strerror
(
int
errcode
)
{
#ifdef HAVE_HSTRERROR
int
hcode
;
switch
(
errcode
)
{
case
EAI_NONAME
:
hcode
=
HOST_NOT_FOUND
;
break
;
case
EAI_AGAIN
:
hcode
=
TRY_AGAIN
;
break
;
case
EAI_FAIL
:
default:
hcode
=
NO_RECOVERY
;
break
;
}
return
hstrerror
(
hcode
);
#else
/* !HAVE_HSTRERROR */
switch
(
errcode
)
{
case
EAI_NONAME
:
return
"Unknown host"
;
case
EAI_AGAIN
:
return
"Host name lookup failure"
;
#ifdef EAI_BADFLAGS
case
EAI_BADFLAGS
:
return
"Invalid argument"
;
#endif
#ifdef EAI_FAMILY
case
EAI_FAMILY
:
return
"Address family not supported"
;
#endif
#ifdef EAI_MEMORY
case
EAI_MEMORY
:
return
"Not enough memory"
;
#endif
#ifdef EAI_NODATA
case
EAI_NODATA
:
return
"No host data of that type was found"
;
#endif
#ifdef EAI_SERVICE
case
EAI_SERVICE
:
return
"Class type not found"
;
#endif
#ifdef EAI_SOCKTYPE
case
EAI_SOCKTYPE
:
return
"Socket type not supported"
;
#endif
default:
return
"Unknown server error"
;
}
#endif
/* HAVE_HSTRERROR */
}
static
int
gethostnameinfo
(
const
struct
sockaddr
*
sa
,
char
*
node
,
size_t
nodelen
,
int
flags
)
{
int
ret
=
-
1
;
char
*
p
=
NULL
;
if
(
!
(
flags
&
NI_NUMERICHOST
))
{
struct
hostent
*
hp
=
gethostbyaddr
(
&
((
struct
sockaddr_in
*
)
sa
)
->
sin_addr
,
sizeof
(
struct
in_addr
),
sa
->
sa_family
);
ret
=
check_hostent_err
(
hp
);
if
(
ret
==
0
)
{
/* Name looked up successfully. */
ret
=
snprintf
(
node
,
nodelen
,
"%s"
,
hp
->
h_name
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
nodelen
)
{
return
EAI_MEMORY
;
}
if
(
flags
&
NI_NOFQDN
)
{
p
=
strchr
(
node
,
'.'
);
if
(
p
)
{
*
p
=
'\0'
;
}
}
return
0
;
}
if
(
flags
&
NI_NAMEREQD
)
{
/* If we require a name and didn't get one,
* automatically fail. */
return
ret
;
}
/* Otherwise just fall into the numeric host code... */
}
p
=
inet_ntoa
(((
struct
sockaddr_in
*
)
sa
)
->
sin_addr
);
ret
=
snprintf
(
node
,
nodelen
,
"%s"
,
p
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
nodelen
)
{
return
EAI_MEMORY
;
}
return
0
;
}
static
int
getservicenameinfo
(
const
struct
sockaddr
*
sa
,
char
*
service
,
size_t
servicelen
,
int
flags
)
{
int
ret
=
-
1
;
int
port
=
ntohs
(((
struct
sockaddr_in
*
)
sa
)
->
sin_port
);
if
(
!
(
flags
&
NI_NUMERICSERV
))
{
struct
servent
*
se
=
getservbyport
(
port
,
(
flags
&
NI_DGRAM
)
?
"udp"
:
"tcp"
);
if
(
se
&&
se
->
s_name
)
{
/* Service name looked up successfully. */
ret
=
snprintf
(
service
,
servicelen
,
"%s"
,
se
->
s_name
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
servicelen
)
{
return
EAI_MEMORY
;
}
return
0
;
}
/* Otherwise just fall into the numeric service code... */
}
ret
=
snprintf
(
service
,
servicelen
,
"%d"
,
port
);
if
(
ret
<
0
||
(
size_t
)
ret
>=
servicelen
)
{
return
EAI_MEMORY
;
}
return
0
;
}
/*
* Convert an ipv4 address to a hostname.
*
* Bugs: - No IPv6 support.
*/
int
getnameinfo
(
const
struct
sockaddr
*
sa
,
socklen_t
salen
,
char
*
node
,
size_t
nodelen
,
char
*
service
,
size_t
servicelen
,
int
flags
)
{
/* Invalid arguments. */
if
(
sa
==
NULL
||
(
node
==
NULL
&&
service
==
NULL
))
{
return
EAI_FAIL
;
}
if
(
sa
->
sa_family
!=
AF_INET
)
{
return
EAI_FAIL
;
}
if
(
salen
<
sizeof
(
struct
sockaddr_in
))
{
return
EAI_FAIL
;
}
/* We don't support those. */
if
((
node
&&
!
(
flags
&
NI_NUMERICHOST
))
||
(
service
&&
!
(
flags
&
NI_NUMERICSERV
)))
return
EAI_FAIL
;
if
(
node
)
{
return
gethostnameinfo
(
sa
,
node
,
nodelen
,
flags
);
}
if
(
service
)
{
return
getservicenameinfo
(
sa
,
service
,
servicelen
,
flags
);
}
return
0
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment