1 /* 2 * Copyright (C) 2012 John Eaglesham 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND JOHN EAGLESHAM 9 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 10 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 11 * JOHN EAGLESHAM BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING 13 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 14 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 15 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #define ADDR_BUF_LEN INET6_ADDRSTRLEN 19 20 #include "EXTERN.h" 21 #include "perl.h" 22 #include "XSUB.h" 23 #include "dlz_perl_driver.h" 24 25 #include <dlz_minimal.h> 26 27 /* And some XS code. */ 28 MODULE = DLZ_Perl::clientinfo PACKAGE = DLZ_Perl::clientinfo 29 30 PROTOTYPES: DISABLE 31 32 void 33 sourceip(opaque) 34 SV *opaque 35 36 PREINIT: 37 const char *ret; 38 char addr_buf[ADDR_BUF_LEN]; 39 int port; 40 isc_sockaddr_t *src; 41 dlz_perl_clientinfo_opaque *ci; 42 I32 wantarray = GIMME_V; 43 44 PPCODE: 45 if (!SvTRUE(opaque) || !SvIOK(opaque)) XSRETURN_EMPTY; 46 47 /* 48 * Safe, because Perl guarantees that an IV (the type we 49 * pass into DLZ functions who pass it here) is able to 50 * hold a pointer. 51 */ 52 ci = (dlz_perl_clientinfo_opaque *) SvIV(opaque); 53 if (wantarray == G_VOID || ci->methods == NULL || 54 ci->methods->version - ci->methods->age < 55 DNS_CLIENTINFOMETHODS_VERSION) 56 XSRETURN_EMPTY; 57 58 ci->methods->sourceip(ci->clientinfo, &src); 59 60 switch (src->type.sa.sa_family) { 61 case AF_INET: 62 port = ntohs(src->type.sin.sin_port); 63 ret = inet_ntop(AF_INET, 64 &src->type.sin.sin_addr, 65 addr_buf, ADDR_BUF_LEN); 66 break; 67 case AF_INET6: 68 port = ntohs(src->type.sin6.sin6_port); 69 ret = inet_ntop(AF_INET6, 70 &src->type.sin6.sin6_addr, 71 addr_buf, ADDR_BUF_LEN); 72 break; 73 default: 74 ret = NULL; 75 } 76 77 if (ret == NULL) XSRETURN_EMPTY; 78 79 XPUSHs(sv_2mortal(newSVpv(addr_buf, strlen(addr_buf)))); 80 if (wantarray == G_ARRAY) XPUSHs(sv_2mortal(newSViv(port))); 81 82