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