/* * Copyright (C) 2012 John Eaglesham * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND JOHN EAGLESHAM * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * JOHN EAGLESHAM BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #define ADDR_BUF_LEN INET6_ADDRSTRLEN #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "dlz_perl_driver.h" #include /* And some XS code. */ MODULE = DLZ_Perl::clientinfo PACKAGE = DLZ_Perl::clientinfo PROTOTYPES: DISABLE void sourceip(opaque) SV *opaque PREINIT: const char *ret; char addr_buf[ADDR_BUF_LEN]; int port; isc_sockaddr_t *src; dlz_perl_clientinfo_opaque *ci; I32 wantarray = GIMME_V; PPCODE: if (!SvTRUE(opaque) || !SvIOK(opaque)) XSRETURN_EMPTY; /* * Safe, because Perl guarantees that an IV (the type we * pass into DLZ functions who pass it here) is able to * hold a pointer. */ ci = (dlz_perl_clientinfo_opaque *) SvIV(opaque); if (wantarray == G_VOID || ci->methods == NULL || ci->methods->version - ci->methods->age < DNS_CLIENTINFOMETHODS_VERSION) XSRETURN_EMPTY; ci->methods->sourceip(ci->clientinfo, &src); switch (src->type.sa.sa_family) { case AF_INET: port = ntohs(src->type.sin.sin_port); ret = inet_ntop(AF_INET, &src->type.sin.sin_addr, addr_buf, ADDR_BUF_LEN); break; case AF_INET6: port = ntohs(src->type.sin6.sin6_port); ret = inet_ntop(AF_INET6, &src->type.sin6.sin6_addr, addr_buf, ADDR_BUF_LEN); break; default: ret = NULL; } if (ret == NULL) XSRETURN_EMPTY; XPUSHs(sv_2mortal(newSVpv(addr_buf, strlen(addr_buf)))); if (wantarray == G_ARRAY) XPUSHs(sv_2mortal(newSViv(port)));