92 lines
2.3 KiB
C

#include "postgres.h"
#include "fmgr.h"
#include "utils/builtins.h"
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/types.h>
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(rdns_lookup);
Datum rdns_lookup(PG_FUNCTION_ARGS) {
struct in_addr iaddr;
char host[512];
struct sockaddr_in sa;
int r;
char* ip = text_to_cstring(PG_GETARG_TEXT_PP(0));
memset(&iaddr, 0, sizeof(struct in_addr));
memset(&sa, 0, sizeof(struct sockaddr_in));
memset(host, 0, 512);
inet_aton(ip, &iaddr);
sa.sin_family = AF_INET;
sa.sin_addr = iaddr;
r = getnameinfo((struct sockaddr*)(&sa), sizeof(struct sockaddr_in), host, 512, 0, 0, NI_NAMEREQD);
if (r == EAI_NONAME)
PG_RETURN_NULL();
if (r) {
ereport(ERROR, (errcode(ERRCODE_SYSTEM_ERROR), errmsg("getnameinfo failed! %s", gai_strerror(r))));
}
PG_RETURN_TEXT_P(cstring_to_text(host));
}
PG_FUNCTION_INFO_V1(circular_rdns_lookup);
Datum circular_rdns_lookup(PG_FUNCTION_ARGS) {
struct in_addr iaddr;
char host[512];
struct sockaddr_in sa;
int r;
struct addrinfo hint;
struct addrinfo* results;
char* ip = text_to_cstring(PG_GETARG_TEXT_PP(0));
struct addrinfo* c;
memset(&iaddr, 0, sizeof(struct in_addr));
memset(&sa, 0, sizeof(struct sockaddr_in));
memset(host, 0, 512);
memset(&hint, 0, sizeof(struct addrinfo));
inet_aton(ip, &iaddr);
sa.sin_family = AF_INET;
sa.sin_addr = iaddr;
r = getnameinfo((struct sockaddr*)(&sa), sizeof(struct sockaddr_in), host, 512, 0, 0, NI_NAMEREQD);
if (r == EAI_NONAME)
PG_RETURN_NULL();
if (r) {
ereport(NOTICE, (errcode(ERRCODE_SYSTEM_ERROR), errmsg("getnameinfo failed for IP `%s`, %s", ip, gai_strerror(r))));
PG_RETURN_NULL();
}
hint.ai_family = AF_INET;
r = getaddrinfo(host, 0, &hint, &results);
if (r) {
ereport(NOTICE, (errcode(ERRCODE_SYSTEM_ERROR), errmsg("getaddrinfo failed for host `%s`, %s", host, gai_strerror(r))));
PG_RETURN_NULL();
}
c = results;
while (c) {
struct addrinfo* current = c;
c = current->ai_next;
if (current->ai_family != AF_INET)
continue;
if (((struct sockaddr_in*)current->ai_addr)->sin_addr.s_addr == iaddr.s_addr) {
freeaddrinfo(results);
PG_RETURN_TEXT_P(cstring_to_text(host));
}
}
freeaddrinfo(results);
PG_RETURN_NULL();
}