xref: /minix3/external/bsd/bind/dist/contrib/dlz/modules/perl/dlz_perl_callback_clientinfo.xs (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
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