1 /*
2 * Socket6.xs
3 * $Id: Socket6.xs 688 2018-09-30 04:22:53Z ume $
4 *
5 * Copyright (C) 2000-2018 Hajimu UMEMOTO <ume@mahoroba.org>.
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 <winsock2.h>
43 #include <ws2tcpip.h>
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 <sys/types.h>
60 #include <sys/socket.h>
61 #include <netinet/in.h>
62 #ifdef __KAME__
63 # include <sys/param.h>
64 # include <net/route.h>
65 # if (defined(__FreeBSD__) && __FreeBSD_version >= 700048) || \
66 (defined(__NetBSD__) && __NetBSD_Version__ >= 899002500)
67 # include <netipsec/ipsec.h>
68 # elif !defined(__OpenBSD__) && !defined(__DragonFly__)
69 # include <netinet6/ipsec.h>
70 # endif
71 #endif
72 #include <netdb.h>
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
not_here(char * s)114 not_here(char *s)
115 {
116 croak("Socket6::%s not implemented on this architecture", s);
117 return -1;
118 }
119
120 static double
constant(char * name,int arg)121 constant(char *name, int arg)
122 {
123 errno = 0;
124 switch (*name) {
125 case 'A':
126 if (strEQ(name, "AF_INET6"))
127 #ifdef AF_INET6
128 return AF_INET6;
129 #else
130 goto not_there;
131 #endif
132 if (strEQ(name, "AI_ADDRCONFIG"))
133 #ifdef AI_ADDRCONFIG
134 return AI_ADDRCONFIG;
135 #else
136 goto not_there;
137 #endif
138 if (strEQ(name, "AI_ALL"))
139 #ifdef AI_ALL
140 return AI_ALL;
141 #else
142 goto not_there;
143 #endif
144 if (strEQ(name, "AI_CANONNAME"))
145 #ifdef AI_CANONNAME
146 return AI_CANONNAME;
147 #else
148 goto not_there;
149 #endif
150 if (strEQ(name, "AI_NUMERICHOST"))
151 #ifdef AI_NUMERICHOST
152 return AI_NUMERICHOST;
153 #else
154 goto not_there;
155 #endif
156 if (strEQ(name, "AI_NUMERICSERV"))
157 #ifdef AI_NUMERICSERV
158 return AI_NUMERICSERV;
159 #else
160 goto not_there;
161 #endif
162 if (strEQ(name, "AI_DEFAULT"))
163 #ifdef AI_DEFAULT
164 return AI_DEFAULT;
165 #else
166 goto not_there;
167 #endif
168 if (strEQ(name, "AI_MASK"))
169 #ifdef AI_MASK
170 return AI_MASK;
171 #else
172 goto not_there;
173 #endif
174 if (strEQ(name, "AI_PASSIVE"))
175 #ifdef AI_PASSIVE
176 return AI_PASSIVE;
177 #else
178 goto not_there;
179 #endif
180 if (strEQ(name, "AI_V4MAPPED"))
181 #ifdef AI_V4MAPPED
182 return AI_V4MAPPED;
183 #else
184 goto not_there;
185 #endif
186 if (strEQ(name, "AI_V4MAPPED_CFG"))
187 #ifdef AI_V4MAPPED_CFG
188 return AI_V4MAPPED_CFG;
189 #else
190 goto not_there;
191 #endif
192 break;
193 case 'E':
194 if (strEQ(name, "EAI_ADDRFAMILY"))
195 #ifdef EAI_ADDRFAMILY
196 return EAI_ADDRFAMILY;
197 #else
198 goto not_there;
199 #endif
200 if (strEQ(name, "EAI_AGAIN"))
201 #ifdef EAI_AGAIN
202 return EAI_AGAIN;
203 #else
204 goto not_there;
205 #endif
206 if (strEQ(name, "EAI_BADFLAGS"))
207 #ifdef EAI_BADFLAGS
208 return EAI_BADFLAGS;
209 #else
210 goto not_there;
211 #endif
212 if (strEQ(name, "EAI_FAIL"))
213 #ifdef EAI_FAIL
214 return EAI_FAIL;
215 #else
216 goto not_there;
217 #endif
218 if (strEQ(name, "EAI_FAMILY"))
219 #ifdef EAI_FAMILY
220 return EAI_FAMILY;
221 #else
222 goto not_there;
223 #endif
224 if (strEQ(name, "EAI_MEMORY"))
225 #ifdef EAI_MEMORY
226 return EAI_MEMORY;
227 #else
228 goto not_there;
229 #endif
230 if (strEQ(name, "EAI_NODATA"))
231 #ifdef EAI_NODATA
232 return EAI_NODATA;
233 #else
234 goto not_there;
235 #endif
236 if (strEQ(name, "EAI_NONAME"))
237 #ifdef EAI_NONAME
238 return EAI_NONAME;
239 #else
240 goto not_there;
241 #endif
242 if (strEQ(name, "EAI_SERVICE"))
243 #ifdef EAI_SERVICE
244 return EAI_SERVICE;
245 #else
246 goto not_there;
247 #endif
248 if (strEQ(name, "EAI_SOCKTYPE"))
249 #ifdef EAI_SOCKTYPE
250 return EAI_SOCKTYPE;
251 #else
252 goto not_there;
253 #endif
254 if (strEQ(name, "EAI_SYSTEM"))
255 #ifdef EAI_SYSTEM
256 return EAI_SYSTEM;
257 #else
258 goto not_there;
259 #endif
260 if (strEQ(name, "EAI_BADHINTS"))
261 #ifdef EAI_BADHINTS
262 return EAI_BADHINTS;
263 #else
264 goto not_there;
265 #endif
266 if (strEQ(name, "EAI_PROTOCOL"))
267 #ifdef EAI_PROTOCOL
268 return EAI_PROTOCOL;
269 #else
270 goto not_there;
271 #endif
272 break;
273 case 'I':
274 if (strEQ(name, "IP_AUTH_TRANS_LEVEL"))
275 #ifdef IP_AUTH_TRANS_LEVEL
276 return IP_AUTH_TRANS_LEVEL;
277 #else
278 goto not_there;
279 #endif
280 if (strEQ(name, "IP_AUTH_NETWORK_LEVEL"))
281 #ifdef IP_AUTH_NETWORK_LEVEL
282 return IP_AUTH_NETWORK_LEVEL;
283 #else
284 goto not_there;
285 #endif
286 if (strEQ(name, "IP_ESP_TRANS_LEVEL"))
287 #ifdef IP_ESP_TRANS_LEVEL
288 return IP_ESP_TRANS_LEVEL;
289 #else
290 goto not_there;
291 #endif
292 if (strEQ(name, "IP_EPS_NETWORK_LEVEL"))
293 #ifdef IP_EPS_NETWORK_LEVEL
294 return IP_EPS_NETWORK_LEVEL;
295 #else
296 goto not_there;
297 #endif
298 if (strEQ(name, "IPPROTO_IP"))
299 #ifdef IPPROTO_IP
300 return IPPROTO_IP;
301 #else
302 goto not_there;
303 #endif
304 if (strEQ(name, "IPPROTO_IPV6"))
305 #ifdef IPPROTO_IPV6
306 return IPPROTO_IPV6;
307 #else
308 goto not_there;
309 #endif
310 if (strEQ(name, "IPSEC_LEVEL_AVAIL"))
311 #ifdef IPSEC_LEVEL_AVAIL
312 return IPSEC_LEVEL_AVAIL;
313 #else
314 goto not_there;
315 #endif
316 if (strEQ(name, "IPSEC_LEVEL_BYPASS"))
317 #ifdef IPSEC_LEVEL_BYPASS
318 return IPSEC_LEVEL_BYPASS;
319 #else
320 goto not_there;
321 #endif
322 if (strEQ(name, "IPSEC_LEVEL_DEFAULT"))
323 #ifdef IPSEC_LEVEL_DEFAULT
324 return IPSEC_LEVEL_DEFAULT;
325 #else
326 goto not_there;
327 #endif
328 if (strEQ(name, "IPSEC_LEVEL_NONE"))
329 #ifdef IPSEC_LEVEL_NONE
330 return IPSEC_LEVEL_NONE;
331 #else
332 goto not_there;
333 #endif
334 if (strEQ(name, "IPSEC_LEVEL_REQUIRE"))
335 #ifdef IPSEC_LEVEL_REQUIRE
336 return IPSEC_LEVEL_REQUIRE;
337 #else
338 goto not_there;
339 #endif
340 if (strEQ(name, "IPSEC_LEVEL_UNIQUE"))
341 #ifdef IPSEC_LEVEL_UNIQUE
342 return IPSEC_LEVEL_UNIQUE;
343 #else
344 goto not_there;
345 #endif
346 if (strEQ(name, "IPSEC_LEVEL_USE"))
347 #ifdef IPSEC_LEVEL_USE
348 return IPSEC_LEVEL_USE;
349 #else
350 goto not_there;
351 #endif
352 if (strEQ(name, "IPV6_AUTH_TRANS_LEVEL"))
353 #ifdef IPV6_AUTH_TRANS_LEVEL
354 return IPV6_AUTH_TRANS_LEVEL;
355 #else
356 goto not_there;
357 #endif
358 if (strEQ(name, "IPV6_AUTH_NETWORK_LEVEL"))
359 #ifdef IPV6_AUTH_NETWORK_LEVEL
360 return IPV6_AUTH_NETWORK_LEVEL;
361 #else
362 goto not_there;
363 #endif
364 if (strEQ(name, "IPV6_ESP_TRANS_LEVEL"))
365 #ifdef IPV6_ESP_TRANS_LEVEL
366 return IPV6_ESP_TRANS_LEVEL;
367 #else
368 goto not_there;
369 #endif
370 if (strEQ(name, "IPV6_EPS_NETWORK_LEVEL"))
371 #ifdef IPV6_EPS_NETWORK_LEVEL
372 return IPV6_EPS_NETWORK_LEVEL;
373 #else
374 goto not_there;
375 #endif
376 break;
377 case 'N':
378 if (strEQ(name, "NI_NOFQDN"))
379 #ifdef NI_NOFQDN
380 return NI_NOFQDN;
381 #else
382 goto not_there;
383 #endif
384 if (strEQ(name, "NI_NUMERICHOST"))
385 #ifdef NI_NUMERICHOST
386 return NI_NUMERICHOST;
387 #else
388 goto not_there;
389 #endif
390 if (strEQ(name, "NI_NAMEREQD"))
391 #ifdef NI_NAMEREQD
392 return NI_NAMEREQD;
393 #else
394 goto not_there;
395 #endif
396 if (strEQ(name, "NI_NUMERICSERV"))
397 #ifdef NI_NUMERICSERV
398 return NI_NUMERICSERV;
399 #else
400 goto not_there;
401 #endif
402 if (strEQ(name, "NI_DGRAM"))
403 #ifdef NI_DGRAM
404 return NI_DGRAM;
405 #else
406 goto not_there;
407 #endif
408 if (strEQ(name, "NI_WITHSCOPEID"))
409 #ifdef NI_WITHSCOPEID
410 return NI_WITHSCOPEID;
411 #else
412 goto not_there;
413 #endif
414 break;
415 case 'P':
416 if (strEQ(name, "PF_INET6"))
417 #ifdef PF_INET6
418 return PF_INET6;
419 #else
420 goto not_there;
421 #endif
422 break;
423 }
424 errno = EINVAL;
425 return 0;
426
427 not_there:
428 errno = ENOENT;
429 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 if ((phe = gethostbyname2(host, af)) != NULL) {
451 for (count = 0; phe->h_addr_list[count]; ++count);
452 EXTEND(sp, 4 + count);
453 PUSHs(sv_2mortal(newSVpv((char *) phe->h_name,
454 strlen(phe->h_name))));
455 PUSHs(sv_2mortal(newSVpv((char *) phe->h_aliases,
456 sizeof(char *))));
457 PUSHs(sv_2mortal(newSViv((IV) phe->h_addrtype)));
458 PUSHs(sv_2mortal(newSViv((IV) phe->h_length)));
459 for (i = 0; i < count; ++i) {
460 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
inet_pton(af,host)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 switch (af) {
486 #ifdef INET6_ADDRSTRLEN
487 case AF_INET6:
488 len = sizeof(struct in6_addr);
489 break;
490 #endif
491 case AF_INET:
492 len = sizeof(struct in_addr);
493 break;
494 default:
495 croak("Bad address family for %s, got %d",
496 "Socket6::inet_pton", af);
497 break;
498 }
499 ok = inet_pton(af, host, &ip_address);
500
501 ST(0) = sv_newmortal();
502 if (ok == 1) {
503 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
inet_ntop(af,address_sv)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 char * address = SvPV(address_sv,addrlen);
526
527 switch (af) {
528 case AF_INET:
529 alen = sizeof(struct in_addr);
530 break;
531 #ifdef INET6_ADDRSTRLEN
532 case AF_INET6:
533 alen = sizeof(struct in6_addr);
534 break;
535 #endif
536 default:
537 croak("Unsupported address family for %s, af is %d",
538 "Socket6::inet_ntop", af);
539 }
540
541 /* with sanity check, just in case */
542 if (alen > sizeof(addr) || alen != addrlen) {
543 croak("Bad arg length for %s, length is %d, should be %d",
544 "Socket6::inet_ntop",
545 addrlen, alen);
546 }
547
548 Copy( address, &addr, alen, char );
549 addr_str[0] = 0;
550 inet_ntop(af, &addr, addr_str, sizeof addr_str);
551
552 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
pack_sockaddr_in6(port,ip6_address)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 Zero( &sin, sizeof sin, char );
568 #ifdef SIN6_LEN
569 sin.sin6_len = sizeof sin;
570 #endif
571 sin.sin6_family = AF_INET6;
572 sin.sin6_port = htons(port);
573 Copy( ip6_address, &sin.sin6_addr, sizeof sin.sin6_addr, char );
574
575 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
pack_sockaddr_in6_all(port,flowinfo,ip6_address,scope_id)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 Zero( &sin, sizeof sin, char );
593 #ifdef SIN6_LEN
594 sin.sin6_len = sizeof sin;
595 #endif
596 sin.sin6_family = AF_INET6;
597 sin.sin6_port = htons(port);
598 sin.sin6_flowinfo = htonl(flowinfo);
599 Copy( ip6_address, &sin.sin6_addr, sizeof sin.sin6_addr, char );
600 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
601 sin.sin6_scope_id = scope_id;
602 #endif
603
604 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
unpack_sockaddr_in6(sin_sv)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 char * sin = SvPV(sin_sv,sockaddrlen);
621 if (sockaddrlen != sizeof(addr)) {
622 croak("Bad arg length for %s, length is %d, should be %d",
623 "Socket6::unpack_sockaddr_in6",
624 sockaddrlen, sizeof(addr));
625 }
626 Copy( sin, &addr,sizeof addr, char );
627 if ( addr.sin6_family != AF_INET6 ) {
628 croak("Bad address family for %s, got %d, should be %d",
629 "Socket6::unpack_sockaddr_in6",
630 addr.sin6_family,
631 AF_INET6);
632 }
633 port = ntohs(addr.sin6_port);
634 ip6_address = addr.sin6_addr;
635
636 EXTEND(sp, 2);
637 PUSHs(sv_2mortal(newSViv((IV) port)));
638 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
unpack_sockaddr_in6_all(sin_sv)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 char * sin = SvPV(sin_sv,sockaddrlen);
657 if (sockaddrlen != sizeof(addr)) {
658 croak("Bad arg length for %s, length is %d, should be %d",
659 "Socket6::unpack_sockaddr_in6",
660 sockaddrlen, sizeof(addr));
661 }
662 Copy( sin, &addr,sizeof addr, char );
663 if ( addr.sin6_family != AF_INET6 ) {
664 croak("Bad address family for %s, got %d, should be %d",
665 "Socket6::unpack_sockaddr_in6",
666 addr.sin6_family,
667 AF_INET6);
668 }
669 port = ntohs(addr.sin6_port);
670 flowinfo = ntohl(addr.sin6_flowinfo);
671 ip6_address = addr.sin6_addr;
672 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
673 scope_id = addr.sin6_scope_id;
674 #else
675 scope_id = 0;
676 #endif
677
678 EXTEND(sp, 5);
679 PUSHs(sv_2mortal(newSViv((IV) port)));
680 PUSHs(sv_2mortal(newSViv((IV) flowinfo)));
681 PUSHs(sv_2mortal(newSVpv((char *)&ip6_address,sizeof ip6_address)));
682 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
in6addr_any()689 in6addr_any()
690 CODE:
691 {
692 #ifdef INET6_ADDRSTRLEN
693 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
in6addr_loopback()700 in6addr_loopback()
701 CODE:
702 {
703 #ifdef INET6_ADDRSTRLEN
704 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 Zero( &hints, sizeof hints, char );
729 hints.ai_flags = flags;
730 hints.ai_family = family;
731 hints.ai_socktype = socktype;
732 hints.ai_protocol = protocol;
733 WSA_STARTUP();
734 err = getaddrinfo(*host ? host : 0, *port ? port : 0, &hints, &res);
735 WSA_CLEANUP();
736
737 if (err == 0) {
738 struct addrinfo * p;
739 count = 0;
740 for (p = res; p; p = p->ai_next)
741 ++count;
742 EXTEND(sp, 5 * count);
743 for (p = res; p; p = p->ai_next) {
744 PUSHs(sv_2mortal(newSViv((IV) p->ai_family)));
745 PUSHs(sv_2mortal(newSViv((IV) p->ai_socktype)));
746 PUSHs(sv_2mortal(newSViv((IV) p->ai_protocol)));
747 PUSHs(sv_2mortal(newSVpv((char *)p->ai_addr,
748 p->ai_addrlen)));
749 if (p->ai_canonname)
750 PUSHs(sv_2mortal(newSVpv((char *)p->ai_canonname,
751 strlen(p->ai_canonname))));
752 else
753 PUSHs(&PL_sv_undef);
754 }
755 freeaddrinfo(res);
756 } else {
757 SV *error_sv = sv_newmortal();
758 SvUPGRADE(error_sv, SVt_PVNV);
759 error = gai_strerror(err);
760 sv_setpv(error_sv, error);
761 SvIV_set(error_sv, err); SvIOK_on(error_sv);
762 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 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 if (items < 2) {
786 err = getnameinfo(sin, sockaddrlen, host, sizeof host,
787 port, sizeof port, 0);
788 if (err)
789 err = getnameinfo(sin, sockaddrlen, host, sizeof host,
790 port, sizeof port, NI_NUMERICSERV);
791 if (err)
792 err = getnameinfo(sin, sockaddrlen, host, sizeof host,
793 port, sizeof port, NI_NUMERICHOST);
794 if (err)
795 err = getnameinfo(sin, sockaddrlen, host, sizeof host,
796 port, sizeof port,
797 NI_NUMERICHOST|NI_NUMERICSERV);
798 } else {
799 err = getnameinfo(sin, sockaddrlen, host, sizeof host,
800 port, sizeof port, flags);
801 }
802 WSA_CLEANUP();
803
804 if (err == 0) {
805 EXTEND(sp, 2);
806 PUSHs(sv_2mortal(newSVpv(host, strlen(host))));
807 PUSHs(sv_2mortal(newSVpv(port, strlen(port))));
808 } else {
809 SV *error_sv = sv_newmortal();
810 SvUPGRADE(error_sv, SVt_PVNV);
811 error = gai_strerror(err);
812 sv_setpv(error_sv, error);
813 SvIV_set(error_sv, err); SvIOK_on(error_sv);
814 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 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 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 ST(0) = (SV *) not_here("getipnodebyaddr");
944 #endif
945 }
946