mirror of https://github.com/postgres/postgres
When building libpq, ip.c and md5.c were symlinked or copied from src/backend/libpq into src/interfaces/libpq, but now that we have a directory specifically for routines that are shared between the server and client binaries, src/common/, move them there. Some routines in ip.c were only used in the backend. Keep those in src/backend/libpq, but rename to ifaddr.c to avoid confusion with the file that's now in common. Fix the comment in src/common/Makefile to reflect how libpq actually links those files. There are two more files that libpq symlinks directly from src/backend: encnames.c and wchar.c. I don't feel compelled to move those right now, though. Patch by Michael Paquier, with some changes by me. Discussion: <69938195-9c76-8523-0af8-eb718ea5b36e@iki.fi>pull/17/head
parent
9cca11c915
commit
ec136d19b2
@ -0,0 +1,260 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* ip.c |
||||
* IPv6-aware network access. |
||||
* |
||||
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group |
||||
* Portions Copyright (c) 1994, Regents of the University of California |
||||
* |
||||
* |
||||
* IDENTIFICATION |
||||
* src/common/ip.c |
||||
* |
||||
* This file and the IPV6 implementation were initially provided by |
||||
* Nigel Kukard <nkukard@lbsd.net>, Linux Based Systems Design |
||||
* http://www.lbsd.net.
|
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
|
||||
#ifndef FRONTEND |
||||
#include "postgres.h" |
||||
#else |
||||
#include "postgres_fe.h" |
||||
#endif |
||||
|
||||
#include <unistd.h> |
||||
#include <sys/types.h> |
||||
#include <sys/stat.h> |
||||
#include <sys/socket.h> |
||||
#include <netdb.h> |
||||
#include <netinet/in.h> |
||||
#ifdef HAVE_NETINET_TCP_H |
||||
#include <netinet/tcp.h> |
||||
#endif |
||||
#include <arpa/inet.h> |
||||
#include <sys/file.h> |
||||
|
||||
#include "common/ip.h" |
||||
|
||||
|
||||
|
||||
#ifdef HAVE_UNIX_SOCKETS |
||||
static int getaddrinfo_unix(const char *path, |
||||
const struct addrinfo * hintsp, |
||||
struct addrinfo ** result); |
||||
|
||||
static int getnameinfo_unix(const struct sockaddr_un * sa, int salen, |
||||
char *node, int nodelen, |
||||
char *service, int servicelen, |
||||
int flags); |
||||
#endif |
||||
|
||||
|
||||
/*
|
||||
* pg_getaddrinfo_all - get address info for Unix, IPv4 and IPv6 sockets |
||||
*/ |
||||
int |
||||
pg_getaddrinfo_all(const char *hostname, const char *servname, |
||||
const struct addrinfo * hintp, struct addrinfo ** result) |
||||
{ |
||||
int rc; |
||||
|
||||
/* not all versions of getaddrinfo() zero *result on failure */ |
||||
*result = NULL; |
||||
|
||||
#ifdef HAVE_UNIX_SOCKETS |
||||
if (hintp->ai_family == AF_UNIX) |
||||
return getaddrinfo_unix(servname, hintp, result); |
||||
#endif |
||||
|
||||
/* NULL has special meaning to getaddrinfo(). */ |
||||
rc = getaddrinfo((!hostname || hostname[0] == '\0') ? NULL : hostname, |
||||
servname, hintp, result); |
||||
|
||||
return rc; |
||||
} |
||||
|
||||
|
||||
/*
|
||||
* pg_freeaddrinfo_all - free addrinfo structures for IPv4, IPv6, or Unix |
||||
* |
||||
* Note: the ai_family field of the original hint structure must be passed |
||||
* so that we can tell whether the addrinfo struct was built by the system's |
||||
* getaddrinfo() routine or our own getaddrinfo_unix() routine. Some versions |
||||
* of getaddrinfo() might be willing to return AF_UNIX addresses, so it's |
||||
* not safe to look at ai_family in the addrinfo itself. |
||||
*/ |
||||
void |
||||
pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo * ai) |
||||
{ |
||||
#ifdef HAVE_UNIX_SOCKETS |
||||
if (hint_ai_family == AF_UNIX) |
||||
{ |
||||
/* struct was built by getaddrinfo_unix (see pg_getaddrinfo_all) */ |
||||
while (ai != NULL) |
||||
{ |
||||
struct addrinfo *p = ai; |
||||
|
||||
ai = ai->ai_next; |
||||
free(p->ai_addr); |
||||
free(p); |
||||
} |
||||
} |
||||
else |
||||
#endif /* HAVE_UNIX_SOCKETS */ |
||||
{ |
||||
/* struct was built by getaddrinfo() */ |
||||
if (ai != NULL) |
||||
freeaddrinfo(ai); |
||||
} |
||||
} |
||||
|
||||
|
||||
/*
|
||||
* pg_getnameinfo_all - get name info for Unix, IPv4 and IPv6 sockets |
||||
* |
||||
* The API of this routine differs from the standard getnameinfo() definition |
||||
* in two ways: first, the addr parameter is declared as sockaddr_storage |
||||
* rather than struct sockaddr, and second, the node and service fields are |
||||
* guaranteed to be filled with something even on failure return. |
||||
*/ |
||||
int |
||||
pg_getnameinfo_all(const struct sockaddr_storage * addr, int salen, |
||||
char *node, int nodelen, |
||||
char *service, int servicelen, |
||||
int flags) |
||||
{ |
||||
int rc; |
||||
|
||||
#ifdef HAVE_UNIX_SOCKETS |
||||
if (addr && addr->ss_family == AF_UNIX) |
||||
rc = getnameinfo_unix((const struct sockaddr_un *) addr, salen, |
||||
node, nodelen, |
||||
service, servicelen, |
||||
flags); |
||||
else |
||||
#endif |
||||
rc = getnameinfo((const struct sockaddr *) addr, salen, |
||||
node, nodelen, |
||||
service, servicelen, |
||||
flags); |
||||
|
||||
if (rc != 0) |
||||
{ |
||||
if (node) |
||||
strlcpy(node, "???", nodelen); |
||||
if (service) |
||||
strlcpy(service, "???", servicelen); |
||||
} |
||||
|
||||
return rc; |
||||
} |
||||
|
||||
|
||||
#if defined(HAVE_UNIX_SOCKETS) |
||||
|
||||
/* -------
|
||||
* getaddrinfo_unix - get unix socket info using IPv6-compatible API |
||||
* |
||||
* Bugs: only one addrinfo is set even though hintsp is NULL or |
||||
* ai_socktype is 0 |
||||
* AI_CANONNAME is not supported. |
||||
* ------- |
||||
*/ |
||||
static int |
||||
getaddrinfo_unix(const char *path, const struct addrinfo * hintsp, |
||||
struct addrinfo ** result) |
||||
{ |
||||
struct addrinfo hints; |
||||
struct addrinfo *aip; |
||||
struct sockaddr_un *unp; |
||||
|
||||
*result = NULL; |
||||
|
||||
MemSet(&hints, 0, sizeof(hints)); |
||||
|
||||
if (strlen(path) >= sizeof(unp->sun_path)) |
||||
return EAI_FAIL; |
||||
|
||||
if (hintsp == NULL) |
||||
{ |
||||
hints.ai_family = AF_UNIX; |
||||
hints.ai_socktype = SOCK_STREAM; |
||||
} |
||||
else |
||||
memcpy(&hints, hintsp, sizeof(hints)); |
||||
|
||||
if (hints.ai_socktype == 0) |
||||
hints.ai_socktype = SOCK_STREAM; |
||||
|
||||
if (hints.ai_family != AF_UNIX) |
||||
{ |
||||
/* shouldn't have been called */ |
||||
return EAI_FAIL; |
||||
} |
||||
|
||||
aip = calloc(1, sizeof(struct addrinfo)); |
||||
if (aip == NULL) |
||||
return EAI_MEMORY; |
||||
|
||||
unp = calloc(1, sizeof(struct sockaddr_un)); |
||||
if (unp == NULL) |
||||
{ |
||||
free(aip); |
||||
return EAI_MEMORY; |
||||
} |
||||
|
||||
aip->ai_family = AF_UNIX; |
||||
aip->ai_socktype = hints.ai_socktype; |
||||
aip->ai_protocol = hints.ai_protocol; |
||||
aip->ai_next = NULL; |
||||
aip->ai_canonname = NULL; |
||||
*result = aip; |
||||
|
||||
unp->sun_family = AF_UNIX; |
||||
aip->ai_addr = (struct sockaddr *) unp; |
||||
aip->ai_addrlen = sizeof(struct sockaddr_un); |
||||
|
||||
strcpy(unp->sun_path, path); |
||||
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN |
||||
unp->sun_len = sizeof(struct sockaddr_un); |
||||
#endif |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/*
|
||||
* Convert an address to a hostname. |
||||
*/ |
||||
static int |
||||
getnameinfo_unix(const struct sockaddr_un * sa, int salen, |
||||
char *node, int nodelen, |
||||
char *service, int servicelen, |
||||
int flags) |
||||
{ |
||||
int ret = -1; |
||||
|
||||
/* Invalid arguments. */ |
||||
if (sa == NULL || sa->sun_family != AF_UNIX || |
||||
(node == NULL && service == NULL)) |
||||
return EAI_FAIL; |
||||
|
||||
if (node) |
||||
{ |
||||
ret = snprintf(node, nodelen, "%s", "[local]"); |
||||
if (ret == -1 || ret > nodelen) |
||||
return EAI_MEMORY; |
||||
} |
||||
|
||||
if (service) |
||||
{ |
||||
ret = snprintf(service, servicelen, "%s", sa->sun_path); |
||||
if (ret == -1 || ret > servicelen) |
||||
return EAI_MEMORY; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
#endif /* HAVE_UNIX_SOCKETS */ |
@ -0,0 +1,30 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* ifaddr.h |
||||
* IP netmask calculations, and enumerating network interfaces. |
||||
* |
||||
* Copyright (c) 2003-2016, PostgreSQL Global Development Group |
||||
* |
||||
* src/include/libpq/ifaddr.h |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
#ifndef IFADDR_H |
||||
#define IFADDR_H |
||||
|
||||
#include "libpq/pqcomm.h" /* pgrminclude ignore */ |
||||
|
||||
typedef void (*PgIfAddrCallback) (struct sockaddr * addr, |
||||
struct sockaddr * netmask, |
||||
void *cb_data); |
||||
|
||||
extern int pg_range_sockaddr(const struct sockaddr_storage * addr, |
||||
const struct sockaddr_storage * netaddr, |
||||
const struct sockaddr_storage * netmask); |
||||
|
||||
extern int pg_sockaddr_cidr_mask(struct sockaddr_storage * mask, |
||||
char *numbits, int family); |
||||
|
||||
extern int pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data); |
||||
|
||||
#endif /* IFADDR_H */ |
Loading…
Reference in new issue