File Coverage

Socket6.xs
Criterion Covered Total %
statement 51 233 21.8
branch 23 164 14.0
condition n/a
subroutine n/a
pod n/a
total 74 397 18.6


line stmt bran cond sub pod time code
1             /*
2             * Socket6.xs
3             * $Id: Socket6.xs 688 2018-09-30 04:22:53Z ume $
4             *
5             * Copyright (C) 2000-2018 Hajimu UMEMOTO .
6             * All rights reserved.
7             *
8             * This moduled is besed on perl5.005_55-v6-19990721 written by KAME
9             * Project.
10             *
11             * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
12             * All rights reserved.
13             *
14             * Redistribution and use in source and binary forms, with or without
15             * modification, are permitted provided that the following conditions
16             * are met:
17             * 1. Redistributions of source code must retain the above copyright
18             * notice, this list of conditions and the following disclaimer.
19             * 2. Redistributions in binary form must reproduce the above copyright
20             * notice, this list of conditions and the following disclaimer in the
21             * documentation and/or other materials provided with the distribution.
22             * 3. Neither the name of the project nor the names of its contributors
23             * may be used to endorse or promote products derived from this software
24             * without specific prior written permission.
25             *
26             * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
27             * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28             * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29             * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
30             * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31             * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32             * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33             * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34             * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35             * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36             * SUCH DAMAGE.
37             */
38              
39             #ifdef WIN32
40              
41             #define WINVER 0x0501
42             #include
43             #include
44             #ifndef NI_NUMERICSERV
45             #error Microsoft Platform SDK (Aug. 2001) or later required.
46             #endif
47             const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
48             const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
49             #define WSA_DECLARE \
50             WSADATA wsaData; \
51             int wsa = 0
52             #define WSA_STARTUP() \
53             wsa = WSAStartup(MAKEWORD(2,2), &wsaData)
54             #define WSA_CLEANUP() \
55             if (!wsa) WSACleanup()
56              
57             #else /* WIN32 */
58              
59             #include
60             #include
61             #include
62             #ifdef __KAME__
63             # include
64             # include
65             # if (defined(__FreeBSD__) && __FreeBSD_version >= 700048) || \
66             (defined(__NetBSD__) && __NetBSD_Version__ >= 899002500)
67             # include
68             # elif !defined(__OpenBSD__) && !defined(__DragonFly__)
69             # include
70             # endif
71             #endif
72             #include
73             #define WSA_DECLARE
74             #define WSA_STARTUP()
75             #define WSA_CLEANUP()
76              
77             #endif /* WIN32 */
78              
79             #include "EXTERN.h"
80             #include "perl.h"
81             #include "XSUB.h"
82              
83             #include "config.h"
84              
85             #if defined(HAVE_INET_NTOP) && !defined(CAN_INET_NTOP)
86             #undef HAVE_INET_NTOP
87             #endif
88              
89             #ifndef HAVE_GETADDRINFO
90             #include "getaddrinfo.c"
91             #define NI_MAXHOST 1025
92             #define NI_MAXSERV 32
93             #define HAVE_GETADDRINFO 1
94             #endif
95             #ifndef HAVE_GETNAMEINFO
96             #include "getnameinfo.c"
97             #define HAVE_GETNAMEINFO 1
98             #endif
99              
100             #ifndef HAVE_INET_NTOP
101             #include "inet_ntop.c"
102             #define HAVE_INET_NTOP 1
103             #endif
104             #ifndef HAVE_INET_PTON
105             #include "inet_pton.c"
106             #define HAVE_INET_PTON 1
107             #endif
108              
109             #ifndef HAVE_PL_SV_UNDEF
110             #define PL_sv_undef sv_undef
111             #endif
112              
113             static int
114 0           not_here(char *s)
115             {
116 0           croak("Socket6::%s not implemented on this architecture", s);
117             return -1;
118             }
119              
120             static double
121 2           constant(char *name, int arg)
122             {
123 2           errno = 0;
124 2           switch (*name) {
125             case 'A':
126 0 0         if (strEQ(name, "AF_INET6"))
127             #ifdef AF_INET6
128 0           return AF_INET6;
129             #else
130             goto not_there;
131             #endif
132 0 0         if (strEQ(name, "AI_ADDRCONFIG"))
133             #ifdef AI_ADDRCONFIG
134 0           return AI_ADDRCONFIG;
135             #else
136             goto not_there;
137             #endif
138 0 0         if (strEQ(name, "AI_ALL"))
139             #ifdef AI_ALL
140 0           return AI_ALL;
141             #else
142             goto not_there;
143             #endif
144 0 0         if (strEQ(name, "AI_CANONNAME"))
145             #ifdef AI_CANONNAME
146 0           return AI_CANONNAME;
147             #else
148             goto not_there;
149             #endif
150 0 0         if (strEQ(name, "AI_NUMERICHOST"))
151             #ifdef AI_NUMERICHOST
152 0           return AI_NUMERICHOST;
153             #else
154             goto not_there;
155             #endif
156 0 0         if (strEQ(name, "AI_NUMERICSERV"))
157             #ifdef AI_NUMERICSERV
158 0           return AI_NUMERICSERV;
159             #else
160             goto not_there;
161             #endif
162 0 0         if (strEQ(name, "AI_DEFAULT"))
163             #ifdef AI_DEFAULT
164             return AI_DEFAULT;
165             #else
166 0           goto not_there;
167             #endif
168 0 0         if (strEQ(name, "AI_MASK"))
169             #ifdef AI_MASK
170             return AI_MASK;
171             #else
172 0           goto not_there;
173             #endif
174 0 0         if (strEQ(name, "AI_PASSIVE"))
175             #ifdef AI_PASSIVE
176 0           return AI_PASSIVE;
177             #else
178             goto not_there;
179             #endif
180 0 0         if (strEQ(name, "AI_V4MAPPED"))
181             #ifdef AI_V4MAPPED
182 0           return AI_V4MAPPED;
183             #else
184             goto not_there;
185             #endif
186 0 0         if (strEQ(name, "AI_V4MAPPED_CFG"))
187             #ifdef AI_V4MAPPED_CFG
188             return AI_V4MAPPED_CFG;
189             #else
190 0           goto not_there;
191             #endif
192 0           break;
193             case 'E':
194 0 0         if (strEQ(name, "EAI_ADDRFAMILY"))
195             #ifdef EAI_ADDRFAMILY
196             return EAI_ADDRFAMILY;
197             #else
198 0           goto not_there;
199             #endif
200 0 0         if (strEQ(name, "EAI_AGAIN"))
201             #ifdef EAI_AGAIN
202 0           return EAI_AGAIN;
203             #else
204             goto not_there;
205             #endif
206 0 0         if (strEQ(name, "EAI_BADFLAGS"))
207             #ifdef EAI_BADFLAGS
208 0           return EAI_BADFLAGS;
209             #else
210             goto not_there;
211             #endif
212 0 0         if (strEQ(name, "EAI_FAIL"))
213             #ifdef EAI_FAIL
214 0           return EAI_FAIL;
215             #else
216             goto not_there;
217             #endif
218 0 0         if (strEQ(name, "EAI_FAMILY"))
219             #ifdef EAI_FAMILY
220 0           return EAI_FAMILY;
221             #else
222             goto not_there;
223             #endif
224 0 0         if (strEQ(name, "EAI_MEMORY"))
225             #ifdef EAI_MEMORY
226 0           return EAI_MEMORY;
227             #else
228             goto not_there;
229             #endif
230 0 0         if (strEQ(name, "EAI_NODATA"))
231             #ifdef EAI_NODATA
232             return EAI_NODATA;
233             #else
234 0           goto not_there;
235             #endif
236 0 0         if (strEQ(name, "EAI_NONAME"))
237             #ifdef EAI_NONAME
238 0           return EAI_NONAME;
239             #else
240             goto not_there;
241             #endif
242 0 0         if (strEQ(name, "EAI_SERVICE"))
243             #ifdef EAI_SERVICE
244 0           return EAI_SERVICE;
245             #else
246             goto not_there;
247             #endif
248 0 0         if (strEQ(name, "EAI_SOCKTYPE"))
249             #ifdef EAI_SOCKTYPE
250 0           return EAI_SOCKTYPE;
251             #else
252             goto not_there;
253             #endif
254 0 0         if (strEQ(name, "EAI_SYSTEM"))
255             #ifdef EAI_SYSTEM
256 0           return EAI_SYSTEM;
257             #else
258             goto not_there;
259             #endif
260 0 0         if (strEQ(name, "EAI_BADHINTS"))
261             #ifdef EAI_BADHINTS
262             return EAI_BADHINTS;
263             #else
264 0           goto not_there;
265             #endif
266 0 0         if (strEQ(name, "EAI_PROTOCOL"))
267             #ifdef EAI_PROTOCOL
268             return EAI_PROTOCOL;
269             #else
270 0           goto not_there;
271             #endif
272 0           break;
273             case 'I':
274 0 0         if (strEQ(name, "IP_AUTH_TRANS_LEVEL"))
275             #ifdef IP_AUTH_TRANS_LEVEL
276             return IP_AUTH_TRANS_LEVEL;
277             #else
278 0           goto not_there;
279             #endif
280 0 0         if (strEQ(name, "IP_AUTH_NETWORK_LEVEL"))
281             #ifdef IP_AUTH_NETWORK_LEVEL
282             return IP_AUTH_NETWORK_LEVEL;
283             #else
284 0           goto not_there;
285             #endif
286 0 0         if (strEQ(name, "IP_ESP_TRANS_LEVEL"))
287             #ifdef IP_ESP_TRANS_LEVEL
288             return IP_ESP_TRANS_LEVEL;
289             #else
290 0           goto not_there;
291             #endif
292 0 0         if (strEQ(name, "IP_EPS_NETWORK_LEVEL"))
293             #ifdef IP_EPS_NETWORK_LEVEL
294             return IP_EPS_NETWORK_LEVEL;
295             #else
296 0           goto not_there;
297             #endif
298 0 0         if (strEQ(name, "IPPROTO_IP"))
299             #ifdef IPPROTO_IP
300 0           return IPPROTO_IP;
301             #else
302             goto not_there;
303             #endif
304 0 0         if (strEQ(name, "IPPROTO_IPV6"))
305             #ifdef IPPROTO_IPV6
306 0           return IPPROTO_IPV6;
307             #else
308             goto not_there;
309             #endif
310 0 0         if (strEQ(name, "IPSEC_LEVEL_AVAIL"))
311             #ifdef IPSEC_LEVEL_AVAIL
312             return IPSEC_LEVEL_AVAIL;
313             #else
314 0           goto not_there;
315             #endif
316 0 0         if (strEQ(name, "IPSEC_LEVEL_BYPASS"))
317             #ifdef IPSEC_LEVEL_BYPASS
318             return IPSEC_LEVEL_BYPASS;
319             #else
320 0           goto not_there;
321             #endif
322 0 0         if (strEQ(name, "IPSEC_LEVEL_DEFAULT"))
323             #ifdef IPSEC_LEVEL_DEFAULT
324             return IPSEC_LEVEL_DEFAULT;
325             #else
326 0           goto not_there;
327             #endif
328 0 0         if (strEQ(name, "IPSEC_LEVEL_NONE"))
329             #ifdef IPSEC_LEVEL_NONE
330             return IPSEC_LEVEL_NONE;
331             #else
332 0           goto not_there;
333             #endif
334 0 0         if (strEQ(name, "IPSEC_LEVEL_REQUIRE"))
335             #ifdef IPSEC_LEVEL_REQUIRE
336             return IPSEC_LEVEL_REQUIRE;
337             #else
338 0           goto not_there;
339             #endif
340 0 0         if (strEQ(name, "IPSEC_LEVEL_UNIQUE"))
341             #ifdef IPSEC_LEVEL_UNIQUE
342             return IPSEC_LEVEL_UNIQUE;
343             #else
344 0           goto not_there;
345             #endif
346 0 0         if (strEQ(name, "IPSEC_LEVEL_USE"))
347             #ifdef IPSEC_LEVEL_USE
348             return IPSEC_LEVEL_USE;
349             #else
350 0           goto not_there;
351             #endif
352 0 0         if (strEQ(name, "IPV6_AUTH_TRANS_LEVEL"))
353             #ifdef IPV6_AUTH_TRANS_LEVEL
354             return IPV6_AUTH_TRANS_LEVEL;
355             #else
356 0           goto not_there;
357             #endif
358 0 0         if (strEQ(name, "IPV6_AUTH_NETWORK_LEVEL"))
359             #ifdef IPV6_AUTH_NETWORK_LEVEL
360             return IPV6_AUTH_NETWORK_LEVEL;
361             #else
362 0           goto not_there;
363             #endif
364 0 0         if (strEQ(name, "IPV6_ESP_TRANS_LEVEL"))
365             #ifdef IPV6_ESP_TRANS_LEVEL
366             return IPV6_ESP_TRANS_LEVEL;
367             #else
368 0           goto not_there;
369             #endif
370 0 0         if (strEQ(name, "IPV6_EPS_NETWORK_LEVEL"))
371             #ifdef IPV6_EPS_NETWORK_LEVEL
372             return IPV6_EPS_NETWORK_LEVEL;
373             #else
374 0           goto not_there;
375             #endif
376 0           break;
377             case 'N':
378 2 50         if (strEQ(name, "NI_NOFQDN"))
379             #ifdef NI_NOFQDN
380 0           return NI_NOFQDN;
381             #else
382             goto not_there;
383             #endif
384 2 100         if (strEQ(name, "NI_NUMERICHOST"))
385             #ifdef NI_NUMERICHOST
386 1           return NI_NUMERICHOST;
387             #else
388             goto not_there;
389             #endif
390 1 50         if (strEQ(name, "NI_NAMEREQD"))
391             #ifdef NI_NAMEREQD
392 0           return NI_NAMEREQD;
393             #else
394             goto not_there;
395             #endif
396 1 50         if (strEQ(name, "NI_NUMERICSERV"))
397             #ifdef NI_NUMERICSERV
398 1           return NI_NUMERICSERV;
399             #else
400             goto not_there;
401             #endif
402 0 0         if (strEQ(name, "NI_DGRAM"))
403             #ifdef NI_DGRAM
404 0           return NI_DGRAM;
405             #else
406             goto not_there;
407             #endif
408 0 0         if (strEQ(name, "NI_WITHSCOPEID"))
409             #ifdef NI_WITHSCOPEID
410             return NI_WITHSCOPEID;
411             #else
412 0           goto not_there;
413             #endif
414 0           break;
415             case 'P':
416 0 0         if (strEQ(name, "PF_INET6"))
417             #ifdef PF_INET6
418 0           return PF_INET6;
419             #else
420             goto not_there;
421             #endif
422 0           break;
423             }
424 0           errno = EINVAL;
425 0           return 0;
426              
427             not_there:
428 0           errno = ENOENT;
429 0           return 0;
430             }
431              
432              
433             MODULE = Socket6 PACKAGE = Socket6
434              
435             double
436             constant(name,arg)
437             char * name
438             int arg
439              
440             void
441             gethostbyname2(host, af)
442             char * host;
443             int af;
444             PPCODE:
445             {
446             #ifdef HAVE_GETHOSTBYNAME2
447             struct hostent *phe;
448             int count, i;
449              
450 0 0         if ((phe = gethostbyname2(host, af)) != NULL) {
451 0 0         for (count = 0; phe->h_addr_list[count]; ++count);
452 0 0         EXTEND(sp, 4 + count);
    0          
453 0           PUSHs(sv_2mortal(newSVpv((char *) phe->h_name,
454             strlen(phe->h_name))));
455 0           PUSHs(sv_2mortal(newSVpv((char *) phe->h_aliases,
456             sizeof(char *))));
457 0           PUSHs(sv_2mortal(newSViv((IV) phe->h_addrtype)));
458 0           PUSHs(sv_2mortal(newSViv((IV) phe->h_length)));
459 0 0         for (i = 0; i < count; ++i) {
460 0           PUSHs(sv_2mortal(newSVpv((char *)phe->h_addr_list[i],
461             phe->h_length)));
462             }
463             }
464             #else
465             ST(0) = (SV *) not_here("gethostbyname2");
466             #endif
467             }
468              
469             void
470             inet_pton(af, host)
471             int af
472             char * host
473             CODE:
474             {
475             #ifdef HAVE_INET_PTON
476             union {
477             #ifdef INET6_ADDRSTRLEN
478             struct in6_addr addr6;
479             #endif
480             struct in_addr addr4;
481             } ip_address;
482             int len;
483             int ok;
484              
485 6           switch (af) {
486             #ifdef INET6_ADDRSTRLEN
487             case AF_INET6:
488 6           len = sizeof(struct in6_addr);
489 6           break;
490             #endif
491             case AF_INET:
492 0           len = sizeof(struct in_addr);
493 0           break;
494             default:
495 0           croak("Bad address family for %s, got %d",
496             "Socket6::inet_pton", af);
497             break;
498             }
499 6           ok = inet_pton(af, host, &ip_address);
500              
501 6           ST(0) = sv_newmortal();
502 6 50         if (ok == 1) {
503 6           sv_setpvn( ST(0), (char *)&ip_address, len );
504             }
505             #else
506             ST(0) = (SV *) not_here("inet_pton");
507             #endif
508             }
509              
510             void
511             inet_ntop(af, address_sv)
512             int af
513             SV * address_sv
514             CODE:
515             {
516             #ifdef HAVE_INET_NTOP
517             STRLEN addrlen, alen;
518             #ifdef INET6_ADDRSTRLEN
519             struct in6_addr addr;
520             char addr_str[INET6_ADDRSTRLEN];
521             #else
522             struct in_addr addr;
523             char addr_str[16];
524             #endif
525 6 50         char * address = SvPV(address_sv,addrlen);
526              
527 6           switch (af) {
528             case AF_INET:
529 0           alen = sizeof(struct in_addr);
530 0           break;
531             #ifdef INET6_ADDRSTRLEN
532             case AF_INET6:
533 6           alen = sizeof(struct in6_addr);
534 6           break;
535             #endif
536             default:
537 0           croak("Unsupported address family for %s, af is %d",
538             "Socket6::inet_ntop", af);
539             }
540              
541             /* with sanity check, just in case */
542 6 50         if (alen > sizeof(addr) || alen != addrlen) {
    50          
543 0           croak("Bad arg length for %s, length is %d, should be %d",
544             "Socket6::inet_ntop",
545             addrlen, alen);
546             }
547              
548 6           Copy( address, &addr, alen, char );
549 6           addr_str[0] = 0;
550 6           inet_ntop(af, &addr, addr_str, sizeof addr_str);
551              
552 6           ST(0) = sv_2mortal(newSVpv(addr_str, strlen(addr_str)));
553             #else
554             ST(0) = (SV *) not_here("inet_ntop");
555             #endif
556             }
557              
558             void
559             pack_sockaddr_in6(port,ip6_address)
560             unsigned short port
561             char * ip6_address
562             CODE:
563             {
564             #ifdef INET6_ADDRSTRLEN
565             struct sockaddr_in6 sin;
566              
567 0           Zero( &sin, sizeof sin, char );
568             #ifdef SIN6_LEN
569             sin.sin6_len = sizeof sin;
570             #endif
571 0           sin.sin6_family = AF_INET6;
572 0           sin.sin6_port = htons(port);
573 0           Copy( ip6_address, &sin.sin6_addr, sizeof sin.sin6_addr, char );
574              
575 0           ST(0) = sv_2mortal(newSVpv((char *)&sin, sizeof sin));
576             #else
577             ST(0) = (SV *) not_here("pack_sockaddr_in6");
578             #endif
579             }
580              
581             void
582             pack_sockaddr_in6_all(port,flowinfo,ip6_address,scope_id)
583             unsigned short port
584             unsigned long flowinfo
585             char * ip6_address
586             unsigned long scope_id
587             CODE:
588             {
589             #ifdef INET6_ADDRSTRLEN
590             struct sockaddr_in6 sin;
591              
592 0           Zero( &sin, sizeof sin, char );
593             #ifdef SIN6_LEN
594             sin.sin6_len = sizeof sin;
595             #endif
596 0           sin.sin6_family = AF_INET6;
597 0           sin.sin6_port = htons(port);
598 0           sin.sin6_flowinfo = htonl(flowinfo);
599 0           Copy( ip6_address, &sin.sin6_addr, sizeof sin.sin6_addr, char );
600             #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
601 0           sin.sin6_scope_id = scope_id;
602             #endif
603              
604 0           ST(0) = sv_2mortal(newSVpv((char *)&sin, sizeof sin));
605             #else
606             ST(0) = (SV *) not_here("pack_sockaddr_in6_all");
607             #endif
608             }
609              
610             void
611             unpack_sockaddr_in6(sin_sv)
612             SV * sin_sv
613             PPCODE:
614             {
615             #ifdef INET6_ADDRSTRLEN
616             STRLEN sockaddrlen;
617             struct sockaddr_in6 addr;
618             unsigned short port;
619             struct in6_addr ip6_address;
620 0 0         char * sin = SvPV(sin_sv,sockaddrlen);
621 0 0         if (sockaddrlen != sizeof(addr)) {
622 0           croak("Bad arg length for %s, length is %d, should be %d",
623             "Socket6::unpack_sockaddr_in6",
624             sockaddrlen, sizeof(addr));
625             }
626 0           Copy( sin, &addr,sizeof addr, char );
627 0 0         if ( addr.sin6_family != AF_INET6 ) {
628 0           croak("Bad address family for %s, got %d, should be %d",
629             "Socket6::unpack_sockaddr_in6",
630 0           addr.sin6_family,
631             AF_INET6);
632             }
633 0           port = ntohs(addr.sin6_port);
634 0           ip6_address = addr.sin6_addr;
635              
636 0 0         EXTEND(sp, 2);
637 0           PUSHs(sv_2mortal(newSViv((IV) port)));
638 0           PUSHs(sv_2mortal(newSVpv((char *)&ip6_address,sizeof ip6_address)));
639             #else
640             ST(0) = (SV *) not_here("unpack_sockaddr_in6");
641             #endif
642             }
643              
644             void
645             unpack_sockaddr_in6_all(sin_sv)
646             SV * sin_sv
647             PPCODE:
648             {
649             #ifdef INET6_ADDRSTRLEN
650             STRLEN sockaddrlen;
651             struct sockaddr_in6 addr;
652             unsigned short port;
653             unsigned long flowinfo;
654             struct in6_addr ip6_address;
655             unsigned long scope_id;
656 0 0         char * sin = SvPV(sin_sv,sockaddrlen);
657 0 0         if (sockaddrlen != sizeof(addr)) {
658 0           croak("Bad arg length for %s, length is %d, should be %d",
659             "Socket6::unpack_sockaddr_in6",
660             sockaddrlen, sizeof(addr));
661             }
662 0           Copy( sin, &addr,sizeof addr, char );
663 0 0         if ( addr.sin6_family != AF_INET6 ) {
664 0           croak("Bad address family for %s, got %d, should be %d",
665             "Socket6::unpack_sockaddr_in6",
666 0           addr.sin6_family,
667             AF_INET6);
668             }
669 0           port = ntohs(addr.sin6_port);
670 0           flowinfo = ntohl(addr.sin6_flowinfo);
671 0           ip6_address = addr.sin6_addr;
672             #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
673 0           scope_id = addr.sin6_scope_id;
674             #else
675             scope_id = 0;
676             #endif
677              
678 0 0         EXTEND(sp, 5);
679 0           PUSHs(sv_2mortal(newSViv((IV) port)));
680 0           PUSHs(sv_2mortal(newSViv((IV) flowinfo)));
681 0           PUSHs(sv_2mortal(newSVpv((char *)&ip6_address,sizeof ip6_address)));
682 0           PUSHs(sv_2mortal(newSViv((IV) scope_id)));
683             #else
684             ST(0) = (SV *) not_here("unpack_sockaddr_in6_all");
685             #endif
686             }
687              
688             void
689             in6addr_any()
690             CODE:
691             {
692             #ifdef INET6_ADDRSTRLEN
693 0           ST(0) = sv_2mortal(newSVpv((char *)&in6addr_any, sizeof in6addr_any));
694             #else
695             ST(0) = (SV *) not_here("in6addr_any");
696             #endif
697             }
698              
699             void
700             in6addr_loopback()
701             CODE:
702             {
703             #ifdef INET6_ADDRSTRLEN
704 0           ST(0) = sv_2mortal(newSVpv((char *)&in6addr_loopback,
705             sizeof in6addr_loopback));
706             #else
707             ST(0) = (SV *) not_here("in6addr_loopback");
708             #endif
709             }
710              
711             void
712             getaddrinfo(host,port,family=0,socktype=0,protocol=0,flags=0)
713             char * host
714             char * port
715             int family
716             int socktype
717             int protocol
718             int flags
719             PPCODE:
720             {
721             #ifdef HAVE_GETADDRINFO
722             struct addrinfo hints, * res;
723             int err;
724             int count;
725             const char *error;
726             WSA_DECLARE;
727              
728 1           Zero( &hints, sizeof hints, char );
729 1           hints.ai_flags = flags;
730 1           hints.ai_family = family;
731 1           hints.ai_socktype = socktype;
732 1           hints.ai_protocol = protocol;
733             WSA_STARTUP();
734 1 50         err = getaddrinfo(*host ? host : 0, *port ? port : 0, &hints, &res);
    50          
735             WSA_CLEANUP();
736              
737 1 50         if (err == 0) {
738             struct addrinfo * p;
739 1           count = 0;
740 3 100         for (p = res; p; p = p->ai_next)
741 2           ++count;
742 1 50         EXTEND(sp, 5 * count);
    50          
743 3 100         for (p = res; p; p = p->ai_next) {
744 2           PUSHs(sv_2mortal(newSViv((IV) p->ai_family)));
745 2           PUSHs(sv_2mortal(newSViv((IV) p->ai_socktype)));
746 2           PUSHs(sv_2mortal(newSViv((IV) p->ai_protocol)));
747 2           PUSHs(sv_2mortal(newSVpv((char *)p->ai_addr,
748             p->ai_addrlen)));
749 2 50         if (p->ai_canonname)
750 0           PUSHs(sv_2mortal(newSVpv((char *)p->ai_canonname,
751             strlen(p->ai_canonname))));
752             else
753 2           PUSHs(&PL_sv_undef);
754             }
755 1           freeaddrinfo(res);
756             } else {
757 0           SV *error_sv = sv_newmortal();
758 0 0         SvUPGRADE(error_sv, SVt_PVNV);
759 0           error = gai_strerror(err);
760 0           sv_setpv(error_sv, error);
761 0           SvIV_set(error_sv, err); SvIOK_on(error_sv);
762 0           PUSHs(error_sv);
763             }
764             #else
765             ST(0) = (SV *) not_here("getaddrinfo");
766             #endif
767             }
768              
769             void
770             getnameinfo(sin_sv, flags = 0)
771             SV * sin_sv
772             int flags;
773             PPCODE:
774             {
775             #ifdef HAVE_GETNAMEINFO
776             STRLEN sockaddrlen;
777 1 50         struct sockaddr * sin = (struct sockaddr *)SvPV(sin_sv,sockaddrlen);
778             char host[NI_MAXHOST];
779             char port[NI_MAXSERV];
780             int err;
781             const char *error;
782             WSA_DECLARE;
783              
784             WSA_STARTUP();
785 1 50         if (items < 2) {
786 0           err = getnameinfo(sin, sockaddrlen, host, sizeof host,
787             port, sizeof port, 0);
788 0 0         if (err)
789 0           err = getnameinfo(sin, sockaddrlen, host, sizeof host,
790             port, sizeof port, NI_NUMERICSERV);
791 0 0         if (err)
792 0           err = getnameinfo(sin, sockaddrlen, host, sizeof host,
793             port, sizeof port, NI_NUMERICHOST);
794 0 0         if (err)
795 0           err = getnameinfo(sin, sockaddrlen, host, sizeof host,
796             port, sizeof port,
797             NI_NUMERICHOST|NI_NUMERICSERV);
798             } else {
799 1           err = getnameinfo(sin, sockaddrlen, host, sizeof host,
800             port, sizeof port, flags);
801             }
802             WSA_CLEANUP();
803              
804 1 50         if (err == 0) {
805 1 50         EXTEND(sp, 2);
806 1           PUSHs(sv_2mortal(newSVpv(host, strlen(host))));
807 1           PUSHs(sv_2mortal(newSVpv(port, strlen(port))));
808             } else {
809 0           SV *error_sv = sv_newmortal();
810 0 0         SvUPGRADE(error_sv, SVt_PVNV);
811 0           error = gai_strerror(err);
812 0           sv_setpv(error_sv, error);
813 0           SvIV_set(error_sv, err); SvIOK_on(error_sv);
814 0           PUSHs(error_sv);
815             }
816             #else
817             ST(0) = (SV *) not_here("getnameinfo");
818             #endif
819             }
820              
821             char *
822             gai_strerror(errcode = 0)
823             int errcode;
824             CODE:
825 0           RETVAL = (char *)gai_strerror(errcode);
826             OUTPUT:
827             RETVAL
828              
829             void
830             getipnodebyname(hostname, family=0, flags=0)
831             char * hostname
832             int family
833             int flags
834             PREINIT:
835             #ifdef HAVE_GETIPNODEBYNAME
836             struct hostent *he;
837             int err;
838             char **p;
839             SV *temp, *address_ref, *alias_ref;
840             AV *address_list, *alias_list;
841             #endif
842             PPCODE:
843             {
844             #ifdef HAVE_GETIPNODEBYNAME
845             he = getipnodebyname(hostname, family, flags, &err);
846              
847             if (err == 0) {
848             XPUSHs(sv_2mortal(newSVpv(he->h_name, strlen(he->h_name))));
849             XPUSHs(sv_2mortal(newSViv(he->h_addrtype)));
850             XPUSHs(sv_2mortal(newSViv(he->h_length)));
851              
852             address_list = newAV();
853             for(p = he->h_addr_list; *p != NULL; p++) {
854             temp = newSVpv(*p, he->h_length);
855             av_push(address_list, temp);
856             }
857             address_ref = newRV_noinc((SV*) address_list);
858             XPUSHs(address_ref);
859              
860             alias_list = newAV();
861             for(p = he->h_aliases; *p != NULL; p++) {
862             temp = newSVpv(*p, strlen(*p));
863             av_push(alias_list, temp);
864             }
865             alias_ref = newRV_noinc((SV*) alias_list);
866             XPUSHs(alias_ref);
867             freehostent(he);
868             } else {
869             XPUSHs(sv_2mortal(newSViv(err)));
870             }
871             #else
872 0           ST(0) = (SV *) not_here("getipnodebyname");
873             #endif
874             }
875              
876             void
877             getipnodebyaddr(family, address_sv)
878             int family
879             SV * address_sv
880             PREINIT:
881             #ifdef HAVE_GETIPNODEBYADDR
882             STRLEN addrlen;
883             struct hostent *he;
884             int err, alen;
885             char **p;
886             SV *temp, *address_ref, *alias_ref;
887             AV *address_list, *alias_list;
888             struct in6_addr addr;
889             char *addr_buffer;
890             #endif
891             PPCODE:
892             {
893             #ifdef HAVE_GETIPNODEBYADDR
894             addr_buffer = SvPV(address_sv, addrlen);
895              
896             switch(family) {
897              
898             case AF_INET:
899             alen = sizeof(struct in_addr);
900             break;
901             case AF_INET6:
902             alen = sizeof(struct in6_addr);
903             break;
904             default:
905             croak("Unsupported address family for %s, af is %d",
906             "Socket6::getipnodebyaddr", family);
907             }
908              
909             if (alen > sizeof(addr) || alen != addrlen) {
910             croak("Arg length mismatch in %s, length is %d, should be %d\n",
911             "Socket6::getipnodebyaddr", addrlen, alen);
912             }
913              
914             Copy(addr_buffer, &addr, sizeof(addr), char);
915              
916             he = getipnodebyaddr(addr_buffer, alen, family, &err);
917              
918             if (err == 0) {
919             XPUSHs(sv_2mortal(newSVpv(he->h_name, strlen(he->h_name))));
920             XPUSHs(sv_2mortal(newSViv(he->h_addrtype)));
921             XPUSHs(sv_2mortal(newSViv(he->h_length)));
922              
923             address_list = newAV();
924             for(p = he->h_addr_list; *p != NULL; p++) {
925             temp = newSVpv(*p, he->h_length);
926             av_push(address_list, temp);
927             }
928             address_ref = newRV_noinc((SV*) address_list);
929             XPUSHs(address_ref);
930              
931             alias_list = newAV();
932             for(p = he->h_aliases; *p != NULL; p++) {
933             temp = newSVpv(*p, strlen(*p));
934             av_push(alias_list, temp);
935             }
936             alias_ref = newRV_noinc((SV*) alias_list);
937             XPUSHs(alias_ref);
938             freehostent(he);
939             } else {
940             XPUSHs(sv_2mortal(newSViv(err)));
941             }
942             #else
943 0           ST(0) = (SV *) not_here("getipnodebyaddr");
944             #endif
945             }