xref: /openbsd/gnu/usr.bin/perl/cpan/Socket/Socket.xs (revision 3cab2bb3)
1 #define PERL_NO_GET_CONTEXT
2 #include "EXTERN.h"
3 #include "perl.h"
4 #include "XSUB.h"
5 
6 #include <stddef.h>
7 
8 #ifdef I_SYS_TYPES
9 #  include <sys/types.h>
10 #endif
11 #if !defined(ultrix) /* Avoid double definition. */
12 #   include <sys/socket.h>
13 #endif
14 #if defined(USE_SOCKS) && defined(I_SOCKS)
15 #   include <socks.h>
16 #endif
17 #ifdef MPE
18 #  define PF_INET AF_INET
19 #  define PF_UNIX AF_UNIX
20 #  define SOCK_RAW 3
21 #endif
22 #ifdef I_SYS_UN
23 #  include <sys/un.h>
24 #endif
25 /* XXX Configure test for <netinet/in_systm.h needed XXX */
26 #if defined(NeXT) || defined(__NeXT__)
27 #  include <netinet/in_systm.h>
28 #endif
29 #if defined(__sgi) && !defined(AF_LINK) && defined(PF_LINK) && PF_LINK == AF_LNK
30 #  undef PF_LINK
31 #endif
32 #if defined(I_NETINET_IN) || defined(__ultrix__)
33 #  include <netinet/in.h>
34 #endif
35 #if defined(I_NETINET_IP)
36 #  include <netinet/ip.h>
37 #endif
38 #ifdef I_NETDB
39 #  if !defined(ultrix)	/* Avoid double definition. */
40 #   include <netdb.h>
41 #  endif
42 #endif
43 #ifdef I_ARPA_INET
44 #  include <arpa/inet.h>
45 #endif
46 #ifdef I_NETINET_TCP
47 #  include <netinet/tcp.h>
48 #endif
49 
50 #if defined(WIN32) && !defined(UNDER_CE)
51 # include <ws2tcpip.h>
52 #endif
53 
54 #ifdef WIN32
55 
56 /* VC 6 with its original headers doesn't know about sockaddr_storage, VC 2003 does*/
57 #ifndef _SS_MAXSIZE
58 
59 #  define _SS_MAXSIZE 128
60 #  define _SS_ALIGNSIZE (sizeof(__int64))
61 
62 #  define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof (short))
63 #  define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (short) + _SS_PAD1SIZE \
64                                                     + _SS_ALIGNSIZE))
65 
66 struct sockaddr_storage {
67     short ss_family;
68     char __ss_pad1[_SS_PAD1SIZE];
69     __int64 __ss_align;
70     char __ss_pad2[_SS_PAD2SIZE];
71 };
72 
73 typedef int socklen_t;
74 
75 #define in6_addr in_addr6
76 
77 #define INET_ADDRSTRLEN  22
78 #define INET6_ADDRSTRLEN 65
79 
80 #endif
81 
82 static int inet_pton(int af, const char *src, void *dst)
83 {
84   struct sockaddr_storage ss;
85   int size = sizeof(ss);
86   ss.ss_family = af; /* per MSDN */
87 
88   if (WSAStringToAddress((char*)src, af, NULL, (struct sockaddr *)&ss, &size) != 0)
89     return 0;
90 
91   switch(af) {
92     case AF_INET:
93       *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;
94       return 1;
95     case AF_INET6:
96       *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
97       return 1;
98     default:
99       WSASetLastError(WSAEAFNOSUPPORT);
100       return -1;
101   }
102 }
103 
104 static const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)
105 {
106   struct sockaddr_storage ss;
107   unsigned long s = size;
108 
109   ZeroMemory(&ss, sizeof(ss));
110   ss.ss_family = af;
111 
112   switch(af) {
113     case AF_INET:
114       ((struct sockaddr_in *)&ss)->sin_addr = *(struct in_addr *)src;
115       break;
116     case AF_INET6:
117       ((struct sockaddr_in6 *)&ss)->sin6_addr = *(struct in6_addr *)src;
118       break;
119     default:
120       return NULL;
121   }
122 
123   /* cannot directly use &size because of strict aliasing rules */
124   if (WSAAddressToString((struct sockaddr *)&ss, sizeof(ss), NULL, dst, &s) != 0)
125     return NULL;
126   else
127     return dst;
128 }
129 
130 #define HAS_INETPTON
131 #define HAS_INETNTOP
132 #endif
133 
134 #ifdef NETWARE
135 NETDB_DEFINE_CONTEXT
136 NETINET_DEFINE_CONTEXT
137 #endif
138 
139 #ifdef I_SYSUIO
140 # include <sys/uio.h>
141 #endif
142 
143 #ifndef AF_NBS
144 # undef PF_NBS
145 #endif
146 
147 #ifndef AF_X25
148 # undef PF_X25
149 #endif
150 
151 #ifndef INADDR_NONE
152 # define INADDR_NONE	0xffffffff
153 #endif /* INADDR_NONE */
154 #ifndef INADDR_BROADCAST
155 # define INADDR_BROADCAST	0xffffffff
156 #endif /* INADDR_BROADCAST */
157 #ifndef INADDR_LOOPBACK
158 # define INADDR_LOOPBACK	 0x7F000001
159 #endif /* INADDR_LOOPBACK */
160 
161 #ifndef INET_ADDRSTRLEN
162 #define INET_ADDRSTRLEN 16
163 #endif
164 
165 #ifndef C_ARRAY_LENGTH
166 #define C_ARRAY_LENGTH(arr) (sizeof(arr) / sizeof(*(arr)))
167 #endif /* !C_ARRAY_LENGTH */
168 
169 #ifndef PERL_UNUSED_VAR
170 # define PERL_UNUSED_VAR(x) ((void)x)
171 #endif /* !PERL_UNUSED_VAR */
172 
173 #ifndef PERL_UNUSED_ARG
174 # define PERL_UNUSED_ARG(x) PERL_UNUSED_VAR(x)
175 #endif /* !PERL_UNUSED_ARG */
176 
177 #ifndef Newx
178 # define Newx(v,n,t) New(0,v,n,t)
179 #endif /* !Newx */
180 
181 #ifndef SvPVx_nolen
182 #if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
183 #  define SvPVx_nolen(sv) ({SV *_sv = (sv); SvPV_nolen(_sv); })
184 #else /* __GNUC__ */
185 #  define SvPVx_nolen(sv) ((PL_Sv = (sv)), SvPV_nolen(PL_Sv))
186 #endif /* __GNU__ */
187 #endif /* !SvPVx_nolen */
188 
189 #ifndef croak_sv
190 # define croak_sv(sv)	croak("%s", SvPVx_nolen(sv))
191 #endif
192 
193 #ifndef hv_stores
194 # define hv_stores(hv, keystr, val) \
195 	hv_store(hv, ""keystr"", sizeof(keystr)-1, val, 0)
196 #endif /* !hv_stores */
197 
198 #ifndef newSVpvn_flags
199 # define newSVpvn_flags(s,len,flags) my_newSVpvn_flags(aTHX_ s,len,flags)
200 static SV *my_newSVpvn_flags(pTHX_ const char *s, STRLEN len, U32 flags)
201 {
202   SV *sv = newSVpvn(s, len);
203   SvFLAGS(sv) |= (flags & SVf_UTF8);
204   return (flags & SVs_TEMP) ? sv_2mortal(sv) : sv;
205 }
206 #endif /* !newSVpvn_flags */
207 
208 #ifndef SvRV_set
209 # define SvRV_set(sv, val) (SvRV(sv) = (val))
210 #endif /* !SvRV_set */
211 
212 #ifndef SvPV_nomg
213 # define SvPV_nomg SvPV
214 #endif /* !SvPV_nomg */
215 
216 #ifndef HEK_FLAGS
217 # define HEK_FLAGS(hek) 0
218 # define HVhek_UTF8 1
219 #endif /* !HEK_FLAGS */
220 
221 #ifndef hv_common
222 /* These magic numbers are arbitrarily chosen (copied from perl core in fact)
223  * and only have to match between this definition and the code that uses them
224  */
225 # define HV_FETCH_ISSTORE 0x04
226 # define HV_FETCH_LVALUE  0x10
227 # define hv_common(hv, keysv, key, klen, flags, act, val, hash) \
228 	my_hv_common(aTHX_ hv, keysv, key, klen, flags, act, val, hash)
229 static void *my_hv_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
230 	int flags, int act, SV *val, U32 hash)
231 {
232 	/*
233 	 * This only handles the usage actually made by the code
234 	 * generated by ExtUtils::Constant.  EU:C really ought to arrange
235 	 * portability of its generated code itself.
236 	 */
237 	if (!keysv) {
238 		keysv = sv_2mortal(newSVpvn(key, klen));
239 		if (flags & HVhek_UTF8)
240 			SvUTF8_on(keysv);
241 	}
242 	if (act == HV_FETCH_LVALUE) {
243 		return (void*)hv_fetch_ent(hv, keysv, 1, hash);
244 	} else if (act == HV_FETCH_ISSTORE) {
245 		return (void*)hv_store_ent(hv, keysv, val, hash);
246 	} else {
247 		croak("panic: my_hv_common: act=0x%x", act);
248 	}
249 }
250 #endif /* !hv_common */
251 
252 #ifndef hv_common_key_len
253 # define hv_common_key_len(hv, key, kl, act, val, hash) \
254 	my_hv_common_key_len(aTHX_ hv, key, kl, act, val, hash)
255 static void *my_hv_common_key_len(pTHX_ HV *hv, const char *key, I32 kl,
256 	int act, SV *val, U32 hash)
257 {
258 	STRLEN klen;
259 	int flags;
260 	if (kl < 0) {
261 		klen = -kl;
262 		flags = HVhek_UTF8;
263 	} else {
264 		klen = kl;
265 		flags = 0;
266 	}
267 	return hv_common(hv, NULL, key, klen, flags, act, val, hash);
268 }
269 #endif /* !hv_common_key_len */
270 
271 #ifndef mPUSHi
272 # define mPUSHi(i) sv_setiv_mg(PUSHs(sv_newmortal()), (IV)(i))
273 #endif /* !mPUSHi */
274 #ifndef mPUSHp
275 # define mPUSHp(p,l) sv_setpvn_mg(PUSHs(sv_newmortal()), (p), (l))
276 #endif /* !mPUSHp */
277 #ifndef mPUSHs
278 # define mPUSHs(s) PUSHs(sv_2mortal(s))
279 #endif /* !mPUSHs */
280 
281 #ifndef CvCONST_on
282 # undef newCONSTSUB
283 # define newCONSTSUB(stash, name, val) my_newCONSTSUB(aTHX_ stash, name, val)
284 static CV *my_newCONSTSUB(pTHX_ HV *stash, char *name, SV *val)
285 {
286 	/*
287 	 * This has to satisfy code generated by ExtUtils::Constant.
288 	 * It depends on the 5.8+ layout of constant subs.  It has
289 	 * two calls to newCONSTSUB(): one for real constants, and one
290 	 * for undefined constants.  In the latter case, it turns the
291 	 * initially-generated constant subs into something else, and
292 	 * it needs the return value from newCONSTSUB() which Perl 5.6
293 	 * doesn't provide.
294 	 */
295 	GV *gv;
296 	CV *cv;
297 	Perl_newCONSTSUB(aTHX_ stash, name, val);
298 	ENTER;
299 	SAVESPTR(PL_curstash);
300 	PL_curstash = stash;
301 	gv = gv_fetchpv(name, 0, SVt_PVCV);
302 	cv = GvCV(gv);
303 	LEAVE;
304 	CvXSUBANY(cv).any_ptr = &PL_sv_undef;
305 	return cv;
306 }
307 # define CvCONST_off(cv) my_CvCONST_off(aTHX_ cv)
308 static void my_CvCONST_off(pTHX_ CV *cv)
309 {
310 	op_free(CvROOT(cv));
311 	CvROOT(cv) = NULL;
312 	CvSTART(cv) = NULL;
313 }
314 #endif /* !CvCONST_on */
315 
316 #ifndef HAS_INET_ATON
317 
318 /*
319  * Check whether "cp" is a valid ascii representation
320  * of an Internet address and convert to a binary address.
321  * Returns 1 if the address is valid, 0 if not.
322  * This replaces inet_addr, the return value from which
323  * cannot distinguish between failure and a local broadcast address.
324  */
325 static int
326 my_inet_aton(register const char *cp, struct in_addr *addr)
327 {
328 	dTHX;
329 	register U32 val;
330 	register int base;
331 	register char c;
332 	int nparts;
333 	const char *s;
334 	unsigned int parts[4];
335 	register unsigned int *pp = parts;
336 
337 	if (!cp || !*cp)
338 		return 0;
339 	for (;;) {
340 		/*
341 		 * Collect number up to ".".
342 		 * Values are specified as for C:
343 		 * 0x=hex, 0=octal, other=decimal.
344 		 */
345 		val = 0; base = 10;
346 		if (*cp == '0') {
347 			if (*++cp == 'x' || *cp == 'X')
348 				base = 16, cp++;
349 			else
350 				base = 8;
351 		}
352 		while ((c = *cp) != '\0') {
353 			if (isDIGIT(c)) {
354 				val = (val * base) + (c - '0');
355 				cp++;
356 				continue;
357 			}
358 			if (base == 16 && (s=strchr(PL_hexdigit,c))) {
359 				val = (val << 4) +
360 					((s - PL_hexdigit) & 15);
361 				cp++;
362 				continue;
363 			}
364 			break;
365 		}
366 		if (*cp == '.') {
367 			/*
368 			 * Internet format:
369 			 *	a.b.c.d
370 			 *	a.b.c	(with c treated as 16-bits)
371 			 *	a.b	(with b treated as 24 bits)
372 			 */
373 			if (pp >= parts + 3 || val > 0xff)
374 				return 0;
375 			*pp++ = val, cp++;
376 		} else
377 			break;
378 	}
379 	/*
380 	 * Check for trailing characters.
381 	 */
382 	if (*cp && !isSPACE(*cp))
383 		return 0;
384 	/*
385 	 * Concoct the address according to
386 	 * the number of parts specified.
387 	 */
388 	nparts = pp - parts + 1;	/* force to an int for switch() */
389 	switch (nparts) {
390 
391 	case 1:				/* a -- 32 bits */
392 		break;
393 
394 	case 2:				/* a.b -- 8.24 bits */
395 		if (val > 0xffffff)
396 			return 0;
397 		val |= parts[0] << 24;
398 		break;
399 
400 	case 3:				/* a.b.c -- 8.8.16 bits */
401 		if (val > 0xffff)
402 			return 0;
403 		val |= (parts[0] << 24) | (parts[1] << 16);
404 		break;
405 
406 	case 4:				/* a.b.c.d -- 8.8.8.8 bits */
407 		if (val > 0xff)
408 			return 0;
409 		val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
410 		break;
411 	}
412 	addr->s_addr = htonl(val);
413 	return 1;
414 }
415 
416 #undef inet_aton
417 #define inet_aton my_inet_aton
418 
419 #endif /* ! HAS_INET_ATON */
420 
421 /* These are not gni() constants; they're extensions for the perl API */
422 /* The definitions in Socket.pm and Socket.xs must match */
423 #define NIx_NOHOST   (1 << 0)
424 #define NIx_NOSERV   (1 << 1)
425 
426 /* On Windows, ole2.h defines a macro called "interface". We don't need that,
427  * and it will complicate the variables in pack_ip_mreq() etc. (RT87389)
428  */
429 #undef interface
430 
431 /* STRUCT_OFFSET should have come from from perl.h, but if not,
432  * roll our own (not using offsetof() since that is C99). */
433 #ifndef STRUCT_OFFSET
434 #  define STRUCT_OFFSET(s,m)  (Size_t)(&(((s *)0)->m))
435 #endif
436 
437 static int
438 not_here(const char *s)
439 {
440     croak("Socket::%s not implemented on this architecture", s);
441     return -1;
442 }
443 
444 #define PERL_IN_ADDR_S_ADDR_SIZE 4
445 
446 /*
447 * Bad assumptions possible here.
448 *
449 * Bad Assumption 1: struct in_addr has no other fields
450 * than the s_addr (which is the field we care about
451 * in here, really). However, we can be fed either 4-byte
452 * addresses (from pack("N", ...), or va.b.c.d, or ...),
453 * or full struct in_addrs (from e.g. pack_sockaddr_in()),
454 * which may or may not be 4 bytes in size.
455 *
456 * Bad Assumption 2: the s_addr field is a simple type
457 * (such as an int, u_int32_t).	It can be a bit field,
458 * in which case using & (address-of) on it or taking sizeof()
459 * wouldn't go over too well.  (Those are not attempted
460 * now but in case someone thinks to change the below code
461 * to use addr.s_addr instead of addr, you have been warned.)
462 *
463 * Bad Assumption 3: the s_addr is the first field in
464 * an in_addr, or that its bytes are the first bytes in
465 * an in_addr.
466 *
467 * These bad assumptions are wrong in UNICOS which has
468 * struct in_addr { struct { u_long  st_addr:32; } s_da };
469 * #define s_addr s_da.st_addr
470 * and u_long is 64 bits.
471 *
472 * --jhi */
473 
474 #include "const-c.inc"
475 
476 #if defined(HAS_GETADDRINFO) && !defined(HAS_GAI_STRERROR)
477 static const char *gai_strerror(int err)
478 {
479   switch (err)
480   {
481 #ifdef EAI_ADDRFAMILY
482   case EAI_ADDRFAMILY:
483     return "Address family for hostname is not supported.";
484 #endif
485 #ifdef EAI_AGAIN
486   case EAI_AGAIN:
487     return "The name could not be resolved at this time.";
488 #endif
489 #ifdef EAI_BADFLAGS
490   case EAI_BADFLAGS:
491     return "The flags parameter has an invalid value.";
492 #endif
493 #ifdef EAI_FAIL
494   case EAI_FAIL:
495     return "A non-recoverable error occurred while resolving the name.";
496 #endif
497 #ifdef EAI_FAMILY
498   case EAI_FAMILY:
499     return "The address family was not recognized or length is invalid.";
500 #endif
501 #ifdef EAI_MEMORY
502   case EAI_MEMORY:
503     return "A memory allocation failure occurred.";
504 #endif
505 #ifdef EAI_NODATA
506   case EAI_NODATA:
507     return "No address is associated with the hostname.";
508 #endif
509 #ifdef EAI_NONAME
510   case EAI_NONAME:
511     return "The name does not resolve for the supplied parameters.";
512 #endif
513 #ifdef EAI_OVERFLOW
514   case EAI_OVERFLOW:
515     return "An argument buffer overflowed.";
516 #endif
517 #ifdef EAI_SERVICE
518   case EAI_SERVICE:
519     return "The service parameter was not recognized for the specified socket type.";
520 #endif
521 #ifdef EAI_SOCKTYPE
522   case EAI_SOCKTYPE:
523     return "The specified socket type was not recognized.";
524 #endif
525 #ifdef EAI_SYSTEM
526   case EAI_SYSTEM:
527     return "A system error occurred - see errno.";
528 #endif
529   default:
530     return "Unknown error in getaddrinfo().";
531   }
532 }
533 #endif
534 
535 #ifdef HAS_GETADDRINFO
536 static SV *err_to_SV(pTHX_ int err)
537 {
538 	SV *ret = sv_newmortal();
539 	(void) SvUPGRADE(ret, SVt_PVNV);
540 
541 	if(err) {
542 		const char *error = gai_strerror(err);
543 		sv_setpv(ret, error);
544 	}
545 	else {
546 		sv_setpv(ret, "");
547 	}
548 
549 	SvIV_set(ret, err); SvIOK_on(ret);
550 
551 	return ret;
552 }
553 
554 static void xs_getaddrinfo(pTHX_ CV *cv)
555 {
556 	dXSARGS;
557 
558 	SV   *host;
559 	SV   *service;
560 	SV   *hints;
561 
562 	char *hostname = NULL;
563 	char *servicename = NULL;
564 	STRLEN len;
565 	struct addrinfo hints_s;
566 	struct addrinfo *res;
567 	struct addrinfo *res_iter;
568 	int err;
569 	int n_res;
570 
571 	PERL_UNUSED_ARG(cv);
572 	if(items > 3)
573 		croak("Usage: Socket::getaddrinfo(host, service, hints)");
574 
575 	SP -= items;
576 
577 	if(items < 1)
578 		host = &PL_sv_undef;
579 	else
580 		host = ST(0);
581 
582 	if(items < 2)
583 		service = &PL_sv_undef;
584 	else
585 		service = ST(1);
586 
587 	if(items < 3)
588 		hints = NULL;
589 	else
590 		hints = ST(2);
591 
592 	SvGETMAGIC(host);
593 	if(SvOK(host)) {
594 		hostname = SvPV_nomg(host, len);
595 		if (!len)
596 			hostname = NULL;
597 	}
598 
599 	SvGETMAGIC(service);
600 	if(SvOK(service)) {
601 		servicename = SvPV_nomg(service, len);
602 		if (!len)
603 			servicename = NULL;
604 	}
605 
606 	Zero(&hints_s, sizeof(hints_s), char);
607 	hints_s.ai_family = PF_UNSPEC;
608 
609 	if(hints && SvOK(hints)) {
610 		HV *hintshash;
611 		SV **valp;
612 
613 		if(!SvROK(hints) || SvTYPE(SvRV(hints)) != SVt_PVHV)
614 			croak("hints is not a HASH reference");
615 
616 		hintshash = (HV*)SvRV(hints);
617 
618 		if((valp = hv_fetch(hintshash, "flags", 5, 0)) != NULL && SvOK(*valp))
619 			hints_s.ai_flags = SvIV(*valp);
620 		if((valp = hv_fetch(hintshash, "family", 6, 0)) != NULL && SvOK(*valp))
621 			hints_s.ai_family = SvIV(*valp);
622 		if((valp = hv_fetch(hintshash, "socktype", 8, 0)) != NULL && SvOK(*valp))
623 			hints_s.ai_socktype = SvIV(*valp);
624 		if((valp = hv_fetch(hintshash, "protocol", 8, 0)) != NULL && SvOK(*valp))
625 			hints_s.ai_protocol = SvIV(*valp);
626 	}
627 
628 	err = getaddrinfo(hostname, servicename, &hints_s, &res);
629 
630 	XPUSHs(err_to_SV(aTHX_ err));
631 
632 	if(err)
633 		XSRETURN(1);
634 
635 	n_res = 0;
636 	for(res_iter = res; res_iter; res_iter = res_iter->ai_next) {
637 		HV *res_hv = newHV();
638 
639 		(void)hv_stores(res_hv, "family",   newSViv(res_iter->ai_family));
640 		(void)hv_stores(res_hv, "socktype", newSViv(res_iter->ai_socktype));
641 		(void)hv_stores(res_hv, "protocol", newSViv(res_iter->ai_protocol));
642 
643 		(void)hv_stores(res_hv, "addr",     newSVpvn((char*)res_iter->ai_addr, res_iter->ai_addrlen));
644 
645 		if(res_iter->ai_canonname)
646 			(void)hv_stores(res_hv, "canonname", newSVpv(res_iter->ai_canonname, 0));
647 		else
648 			(void)hv_stores(res_hv, "canonname", newSV(0));
649 
650 		XPUSHs(sv_2mortal(newRV_noinc((SV*)res_hv)));
651 		n_res++;
652 	}
653 
654 	freeaddrinfo(res);
655 
656 	XSRETURN(1 + n_res);
657 }
658 #endif
659 
660 #ifdef HAS_GETNAMEINFO
661 static void xs_getnameinfo(pTHX_ CV *cv)
662 {
663 	dXSARGS;
664 
665 	SV  *addr;
666 	int  flags;
667 	int  xflags;
668 
669 	char host[1024];
670 	char serv[256];
671 	char *sa; /* we'll cast to struct sockaddr * when necessary */
672 	STRLEN addr_len;
673 	int err;
674 
675 	int want_host, want_serv;
676 
677 	PERL_UNUSED_ARG(cv);
678 	if(items < 1 || items > 3)
679 		croak("Usage: Socket::getnameinfo(addr, flags=0, xflags=0)");
680 
681 	SP -= items;
682 
683 	addr = ST(0);
684 	SvGETMAGIC(addr);
685 
686 	if(items < 2)
687 		flags = 0;
688 	else
689 		flags = SvIV(ST(1));
690 
691 	if(items < 3)
692 		xflags = 0;
693 	else
694 		xflags = SvIV(ST(2));
695 
696 	want_host = !(xflags & NIx_NOHOST);
697 	want_serv = !(xflags & NIx_NOSERV);
698 
699 	if(!SvPOKp(addr))
700 		croak("addr is not a string");
701 
702 	addr_len = SvCUR(addr);
703 
704 	/* We need to ensure the sockaddr is aligned, because a random SvPV might
705 	 * not be due to SvOOK */
706 	Newx(sa, addr_len, char);
707 	Copy(SvPV_nolen(addr), sa, addr_len, char);
708 #ifdef HAS_SOCKADDR_SA_LEN
709 	((struct sockaddr *)sa)->sa_len = addr_len;
710 #endif
711 
712 	err = getnameinfo((struct sockaddr *)sa, addr_len,
713 			want_host ? host : NULL, want_host ? sizeof(host) : 0,
714 			want_serv ? serv : NULL, want_serv ? sizeof(serv) : 0,
715 			flags);
716 
717 	Safefree(sa);
718 
719 	XPUSHs(err_to_SV(aTHX_ err));
720 
721 	if(err)
722 		XSRETURN(1);
723 
724 	XPUSHs(want_host ? sv_2mortal(newSVpv(host, 0)) : &PL_sv_undef);
725 	XPUSHs(want_serv ? sv_2mortal(newSVpv(serv, 0)) : &PL_sv_undef);
726 
727 	XSRETURN(3);
728 }
729 #endif
730 
731 MODULE = Socket		PACKAGE = Socket
732 
733 INCLUDE: const-xs.inc
734 
735 BOOT:
736 #ifdef HAS_GETADDRINFO
737 	newXS("Socket::getaddrinfo", xs_getaddrinfo, __FILE__);
738 #endif
739 #ifdef HAS_GETNAMEINFO
740 	newXS("Socket::getnameinfo", xs_getnameinfo, __FILE__);
741 #endif
742 
743 void
744 inet_aton(host)
745 	char *	host
746 	CODE:
747 	{
748 	struct in_addr ip_address;
749 	struct hostent * phe;
750 
751 	if ((*host != '\0') && inet_aton(host, &ip_address)) {
752 		ST(0) = sv_2mortal(newSVpvn((char *)&ip_address, sizeof(ip_address)));
753 		XSRETURN(1);
754 	}
755 #ifdef HAS_GETHOSTBYNAME
756 	phe = gethostbyname(host);
757 	if (phe && phe->h_addrtype == AF_INET && phe->h_length == 4) {
758 		ST(0) = sv_2mortal(newSVpvn((char *)phe->h_addr, phe->h_length));
759 		XSRETURN(1);
760 	}
761 #endif
762 	XSRETURN_UNDEF;
763 	}
764 
765 void
766 inet_ntoa(ip_address_sv)
767 	SV *	ip_address_sv
768 	CODE:
769 	{
770 	STRLEN addrlen;
771 	struct in_addr addr;
772 	char * ip_address;
773 	if (DO_UTF8(ip_address_sv) && !sv_utf8_downgrade(ip_address_sv, 1))
774 		croak("Wide character in %s", "Socket::inet_ntoa");
775 	ip_address = SvPVbyte(ip_address_sv, addrlen);
776 	if (addrlen == sizeof(addr) || addrlen == 4)
777 		addr.s_addr =
778 		    (ip_address[0] & 0xFF) << 24 |
779 		    (ip_address[1] & 0xFF) << 16 |
780 		    (ip_address[2] & 0xFF) <<  8 |
781 		    (ip_address[3] & 0xFF);
782 	else
783 		croak("Bad arg length for %s, length is %" UVuf
784                       ", should be %" UVuf,
785 		      "Socket::inet_ntoa", (UV)addrlen, (UV)sizeof(addr));
786 	/* We could use inet_ntoa() but that is broken
787 	 * in HP-UX + GCC + 64bitint (returns "0.0.0.0"),
788 	 * so let's use this sprintf() workaround everywhere.
789 	 * This is also more threadsafe than using inet_ntoa(). */
790 	ST(0) = sv_2mortal(Perl_newSVpvf(aTHX_ "%d.%d.%d.%d", /* IPv6? */
791 					 (int)((addr.s_addr >> 24) & 0xFF),
792 					 (int)((addr.s_addr >> 16) & 0xFF),
793 					 (int)((addr.s_addr >>  8) & 0xFF),
794 					 (int)( addr.s_addr        & 0xFF)));
795 	}
796 
797 void
798 sockaddr_family(sockaddr)
799 	SV *	sockaddr
800 	PREINIT:
801 	STRLEN sockaddr_len;
802 	char *sockaddr_pv = SvPVbyte(sockaddr, sockaddr_len);
803 	CODE:
804 	if (sockaddr_len < STRUCT_OFFSET(struct sockaddr, sa_data))
805 		croak("Bad arg length for %s, length is %" UVuf
806                       ", should be at least %" UVuf,
807 		      "Socket::sockaddr_family", (UV)sockaddr_len,
808 		      (UV)STRUCT_OFFSET(struct sockaddr, sa_data));
809 	ST(0) = sv_2mortal(newSViv(((struct sockaddr*)sockaddr_pv)->sa_family));
810 
811 void
812 pack_sockaddr_un(pathname)
813 	SV *	pathname
814 	CODE:
815 	{
816 #ifdef I_SYS_UN
817 	struct sockaddr_un sun_ad; /* fear using sun */
818 	STRLEN len;
819 	char * pathname_pv;
820 	int addr_len;
821 
822 	if (!SvOK(pathname))
823 	    croak("Undefined path for %s", "Socket::pack_sockaddr_un");
824 
825 	Zero(&sun_ad, sizeof(sun_ad), char);
826 	sun_ad.sun_family = AF_UNIX;
827 	pathname_pv = SvPV(pathname,len);
828 	if (len > sizeof(sun_ad.sun_path)) {
829 	    warn("Path length (%" UVuf ") is longer than maximum supported length"
830 	         " (%" UVuf ") and will be truncated",
831 	         (UV)len, (UV)sizeof(sun_ad.sun_path));
832 	    len = sizeof(sun_ad.sun_path);
833 	}
834 #  ifdef OS2	/* Name should start with \socket\ and contain backslashes! */
835 	{
836 		int off;
837 		char *s, *e;
838 
839 		if (pathname_pv[0] != '/' && pathname_pv[0] != '\\')
840 			croak("Relative UNIX domain socket name '%s' unsupported",
841 			      pathname_pv);
842 		else if (len < 8
843 			 || pathname_pv[7] != '/' && pathname_pv[7] != '\\'
844 			 || !strnicmp(pathname_pv + 1, "socket", 6))
845 			off = 7;
846 		else
847 			off = 0;	/* Preserve names starting with \socket\ */
848 		Copy("\\socket", sun_ad.sun_path, off, char);
849 		Copy(pathname_pv, sun_ad.sun_path + off, len, char);
850 
851 		s = sun_ad.sun_path + off - 1;
852 		e = s + len + 1;
853 		while (++s < e)
854 			if (*s = '/')
855 				*s = '\\';
856 	}
857 #  else	/* !( defined OS2 ) */
858 	Copy(pathname_pv, sun_ad.sun_path, len, char);
859 #  endif
860 	if (0) not_here("dummy");
861 	if (len > 1 && sun_ad.sun_path[0] == '\0') {
862 		/* Linux-style abstract-namespace socket.
863 		 * The name is not a file name, but an array of arbitrary
864 		 * character, starting with \0 and possibly including \0s,
865 		 * therefore the length of the structure must denote the
866 		 * end of that character array */
867 		addr_len = (char *)&(sun_ad.sun_path) - (char *)&sun_ad + len;
868 	} else {
869 		addr_len = sizeof(sun_ad);
870 	}
871 #  ifdef HAS_SOCKADDR_SA_LEN
872 	sun_ad.sun_len = addr_len;
873 #  endif
874 	ST(0) = sv_2mortal(newSVpvn((char *)&sun_ad, addr_len));
875 #else
876 	ST(0) = (SV*)not_here("pack_sockaddr_un");
877 #endif
878 
879 	}
880 
881 void
882 unpack_sockaddr_un(sun_sv)
883 	SV *	sun_sv
884 	CODE:
885 	{
886 #ifdef I_SYS_UN
887 	struct sockaddr_un addr;
888 	STRLEN sockaddrlen;
889 	char * sun_ad;
890 	int addr_len = 0;
891 	if (!SvOK(sun_sv))
892 	    croak("Undefined address for %s", "Socket::unpack_sockaddr_un");
893 	sun_ad = SvPVbyte(sun_sv,sockaddrlen);
894 #   if defined(__linux__) || defined(HAS_SOCKADDR_SA_LEN)
895 	/* On Linux or *BSD sockaddrlen on sockets returned by accept, recvfrom,
896 	   getpeername and getsockname is not equal to sizeof(addr). */
897 	if (sockaddrlen < sizeof(addr)) {
898 	  Copy(sun_ad, &addr, sockaddrlen, char);
899 	  Zero(((char*)&addr) + sockaddrlen, sizeof(addr) - sockaddrlen, char);
900 	} else {
901 	  Copy(sun_ad, &addr, sizeof(addr), char);
902 	}
903 #     ifdef HAS_SOCKADDR_SA_LEN
904 	/* In this case, sun_len must be checked */
905 	if (sockaddrlen != addr.sun_len)
906 		croak("Invalid arg sun_len field for %s, length is %" UVuf
907                       ", but sun_len is %" UVuf,
908 		      "Socket::unpack_sockaddr_un", (UV)sockaddrlen, (UV)addr.sun_len);
909 #     endif
910 #   else
911 	if (sockaddrlen != sizeof(addr))
912 		croak("Bad arg length for %s, length is %" UVuf
913                       ", should be %" UVuf,
914 		      "Socket::unpack_sockaddr_un", (UV)sockaddrlen, (UV)sizeof(addr));
915 	Copy(sun_ad, &addr, sizeof(addr), char);
916 #   endif
917 
918 	if (addr.sun_family != AF_UNIX)
919 		croak("Bad address family for %s, got %d, should be %d",
920 		      "Socket::unpack_sockaddr_un", addr.sun_family, AF_UNIX);
921 #   ifdef __linux__
922 	if (addr.sun_path[0] == '\0') {
923 		/* Linux-style abstract socket address begins with a nul
924 		 * and can contain nuls. */
925 		addr_len = (char *)&addr - (char *)&(addr.sun_path) + sockaddrlen;
926 	} else
927 #   endif
928 	{
929 #   if defined(HAS_SOCKADDR_SA_LEN)
930 		/* On *BSD sun_path not always ends with a '\0' */
931 		int maxlen = addr.sun_len - 2; /* should use STRUCT_OFFSET(struct sockaddr_un, sun_path) instead of 2 */
932 		if (maxlen > (int)sizeof(addr.sun_path))
933 		  maxlen = (int)sizeof(addr.sun_path);
934 #   else
935 		const int maxlen = (int)sizeof(addr.sun_path);
936 #   endif
937 		while (addr_len < maxlen && addr.sun_path[addr_len])
938 		     addr_len++;
939 	}
940 
941 	ST(0) = sv_2mortal(newSVpvn(addr.sun_path, addr_len));
942 #else
943 	ST(0) = (SV*)not_here("unpack_sockaddr_un");
944 #endif
945 	}
946 
947 void
948 pack_sockaddr_in(port_sv, ip_address_sv)
949 	SV *	port_sv
950 	SV *	ip_address_sv
951 	CODE:
952 	{
953 	struct sockaddr_in sin;
954 	struct in_addr addr;
955 	STRLEN addrlen;
956 	unsigned short port = 0;
957 	char * ip_address;
958 	if (SvOK(port_sv))
959 		port = SvUV(port_sv);
960 	if (!SvOK(ip_address_sv))
961 		croak("Undefined address for %s", "Socket::pack_sockaddr_in");
962 	if (DO_UTF8(ip_address_sv) && !sv_utf8_downgrade(ip_address_sv, 1))
963 		croak("Wide character in %s", "Socket::pack_sockaddr_in");
964 	ip_address = SvPVbyte(ip_address_sv, addrlen);
965 	if (addrlen == sizeof(addr) || addrlen == 4)
966 		addr.s_addr =
967 		    (unsigned int)(ip_address[0] & 0xFF) << 24 |
968 		    (unsigned int)(ip_address[1] & 0xFF) << 16 |
969 		    (unsigned int)(ip_address[2] & 0xFF) <<  8 |
970 		    (unsigned int)(ip_address[3] & 0xFF);
971 	else
972 		croak("Bad arg length for %s, length is %" UVuf
973                       ", should be %" UVuf,
974 		      "Socket::pack_sockaddr_in",
975 		      (UV)addrlen, (UV)sizeof(addr));
976 	Zero(&sin, sizeof(sin), char);
977 	sin.sin_family = AF_INET;
978 	sin.sin_port = htons(port);
979 	sin.sin_addr.s_addr = htonl(addr.s_addr);
980 #  ifdef HAS_SOCKADDR_SA_LEN
981 	sin.sin_len = sizeof(sin);
982 #  endif
983 	ST(0) = sv_2mortal(newSVpvn((char *)&sin, sizeof(sin)));
984 	}
985 
986 void
987 unpack_sockaddr_in(sin_sv)
988 	SV *	sin_sv
989 	PPCODE:
990 	{
991 	STRLEN sockaddrlen;
992 	struct sockaddr_in addr;
993 	SV *ip_address_sv;
994 	char * sin;
995 	if (!SvOK(sin_sv))
996 	    croak("Undefined address for %s", "Socket::unpack_sockaddr_in");
997 	sin = SvPVbyte(sin_sv,sockaddrlen);
998 	if (sockaddrlen != sizeof(addr)) {
999 	    croak("Bad arg length for %s, length is %" UVuf
1000                   ", should be %" UVuf,
1001 		  "Socket::unpack_sockaddr_in", (UV)sockaddrlen, (UV)sizeof(addr));
1002 	}
1003 	Copy(sin, &addr, sizeof(addr), char);
1004 	if (addr.sin_family != AF_INET) {
1005 	    croak("Bad address family for %s, got %d, should be %d",
1006 		  "Socket::unpack_sockaddr_in", addr.sin_family, AF_INET);
1007 	}
1008 	ip_address_sv = newSVpvn((char *)&addr.sin_addr, sizeof(addr.sin_addr));
1009 
1010 	if(GIMME_V == G_ARRAY) {
1011 	    EXTEND(SP, 2);
1012 	    mPUSHi(ntohs(addr.sin_port));
1013 	    mPUSHs(ip_address_sv);
1014 	}
1015 	else {
1016 	    mPUSHs(ip_address_sv);
1017 	}
1018 	}
1019 
1020 void
1021 pack_sockaddr_in6(port_sv, sin6_addr, scope_id=0, flowinfo=0)
1022 	SV *	port_sv
1023 	SV *	sin6_addr
1024 	unsigned long	scope_id
1025 	unsigned long	flowinfo
1026 	CODE:
1027 	{
1028 #ifdef HAS_SOCKADDR_IN6
1029 	unsigned short port = 0;
1030 	struct sockaddr_in6 sin6;
1031 	char * addrbytes;
1032 	STRLEN addrlen;
1033 	if (SvOK(port_sv))
1034 		port = SvUV(port_sv);
1035 	if (!SvOK(sin6_addr))
1036 		croak("Undefined address for %s", "Socket::pack_sockaddr_in6");
1037 	if (DO_UTF8(sin6_addr) && !sv_utf8_downgrade(sin6_addr, 1))
1038 		croak("Wide character in %s", "Socket::pack_sockaddr_in6");
1039 	addrbytes = SvPVbyte(sin6_addr, addrlen);
1040 	if (addrlen != sizeof(sin6.sin6_addr))
1041 		croak("Bad arg length %s, length is %" UVuf
1042                       ", should be %" UVuf,
1043 		      "Socket::pack_sockaddr_in6", (UV)addrlen, (UV)sizeof(sin6.sin6_addr));
1044 	Zero(&sin6, sizeof(sin6), char);
1045 	sin6.sin6_family = AF_INET6;
1046 	sin6.sin6_port = htons(port);
1047 	sin6.sin6_flowinfo = htonl(flowinfo);
1048 	Copy(addrbytes, &sin6.sin6_addr, sizeof(sin6.sin6_addr), char);
1049 #  ifdef HAS_SIN6_SCOPE_ID
1050 	sin6.sin6_scope_id = scope_id;
1051 #  else
1052 	if (scope_id != 0)
1053 	    warn("%s cannot represent non-zero scope_id %d",
1054 		 "Socket::pack_sockaddr_in6", scope_id);
1055 #  endif
1056 #  ifdef HAS_SOCKADDR_SA_LEN
1057 	sin6.sin6_len = sizeof(sin6);
1058 #  endif
1059 	ST(0) = sv_2mortal(newSVpvn((char *)&sin6, sizeof(sin6)));
1060 #else
1061 	PERL_UNUSED_VAR(port_sv);
1062 	PERL_UNUSED_VAR(sin6_addr);
1063 	ST(0) = (SV*)not_here("pack_sockaddr_in6");
1064 #endif
1065 	}
1066 
1067 void
1068 unpack_sockaddr_in6(sin6_sv)
1069 	SV *	sin6_sv
1070 	PPCODE:
1071 	{
1072 #ifdef HAS_SOCKADDR_IN6
1073 	STRLEN addrlen;
1074 	struct sockaddr_in6 sin6;
1075 	char * addrbytes;
1076 	SV *ip_address_sv;
1077 	if (!SvOK(sin6_sv))
1078 		croak("Undefined address for %s", "Socket::unpack_sockaddr_in6");
1079 	addrbytes = SvPVbyte(sin6_sv, addrlen);
1080 	if (addrlen != sizeof(sin6))
1081 		croak("Bad arg length for %s, length is %" UVuf
1082                       ", should be %" UVuf,
1083 		      "Socket::unpack_sockaddr_in6", (UV)addrlen, (UV)sizeof(sin6));
1084 	Copy(addrbytes, &sin6, sizeof(sin6), char);
1085 	if (sin6.sin6_family != AF_INET6)
1086 		croak("Bad address family for %s, got %d, should be %d",
1087 		      "Socket::unpack_sockaddr_in6", sin6.sin6_family, AF_INET6);
1088 	ip_address_sv = newSVpvn((char *)&sin6.sin6_addr, sizeof(sin6.sin6_addr));
1089 
1090 	if(GIMME_V == G_ARRAY) {
1091 	    EXTEND(SP, 4);
1092 	    mPUSHi(ntohs(sin6.sin6_port));
1093 	    mPUSHs(ip_address_sv);
1094 #  ifdef HAS_SIN6_SCOPE_ID
1095 	    mPUSHi(sin6.sin6_scope_id);
1096 #  else
1097 	    mPUSHi(0);
1098 #  endif
1099 	    mPUSHi(ntohl(sin6.sin6_flowinfo));
1100 	}
1101 	else {
1102 	    mPUSHs(ip_address_sv);
1103 	}
1104 #else
1105 	PERL_UNUSED_VAR(sin6_sv);
1106 	ST(0) = (SV*)not_here("pack_sockaddr_in6");
1107 #endif
1108 	}
1109 
1110 void
1111 inet_ntop(af, ip_address_sv)
1112 	int	af
1113 	SV *	ip_address_sv
1114 	CODE:
1115 #ifdef HAS_INETNTOP
1116 	STRLEN addrlen;
1117 #ifdef AF_INET6
1118 	struct in6_addr addr;
1119 	char str[INET6_ADDRSTRLEN];
1120 #else
1121 	struct in_addr addr;
1122 	char str[INET_ADDRSTRLEN];
1123 #endif
1124 	char *ip_address;
1125 
1126 	if (DO_UTF8(ip_address_sv) && !sv_utf8_downgrade(ip_address_sv, 1))
1127 		croak("Wide character in %s", "Socket::inet_ntop");
1128 
1129 	ip_address = SvPV(ip_address_sv, addrlen);
1130 
1131 	switch(af) {
1132 	  case AF_INET:
1133 	    if(addrlen != 4)
1134 		croak("Bad address length for Socket::inet_ntop on AF_INET;"
1135 		      " got %" UVuf ", should be 4", (UV)addrlen);
1136 	    break;
1137 #ifdef AF_INET6
1138 	  case AF_INET6:
1139 	    if(addrlen != 16)
1140 		croak("Bad address length for Socket::inet_ntop on AF_INET6;"
1141 		      " got %" UVuf ", should be 16", (UV)addrlen);
1142 	    break;
1143 #endif
1144 	  default:
1145 		croak("Bad address family for %s, got %d, should be"
1146 #ifdef AF_INET6
1147 		      " either AF_INET or AF_INET6",
1148 #else
1149 		      " AF_INET",
1150 #endif
1151 		      "Socket::inet_ntop", af);
1152 	}
1153 
1154 	if(addrlen < sizeof(addr)) {
1155 	    Copy(ip_address, &addr, addrlen, char);
1156 	    Zero(((char*)&addr) + addrlen, sizeof(addr) - addrlen, char);
1157 	}
1158 	else {
1159 	    Copy(ip_address, &addr, sizeof addr, char);
1160 	}
1161 	inet_ntop(af, &addr, str, sizeof str);
1162 
1163 	ST(0) = sv_2mortal(newSVpvn(str, strlen(str)));
1164 #else
1165 	PERL_UNUSED_VAR(af);
1166 	PERL_UNUSED_VAR(ip_address_sv);
1167 	ST(0) = (SV*)not_here("inet_ntop");
1168 #endif
1169 
1170 void
1171 inet_pton(af, host)
1172 	int	      af
1173 	const char *  host
1174 	CODE:
1175 #ifdef HAS_INETPTON
1176 	int ok;
1177 	int addrlen = 0;
1178 #ifdef AF_INET6
1179 	struct in6_addr ip_address;
1180 #else
1181 	struct in_addr ip_address;
1182 #endif
1183 
1184 	switch(af) {
1185 	  case AF_INET:
1186 	    addrlen = 4;
1187 	    break;
1188 #ifdef AF_INET6
1189 	  case AF_INET6:
1190 	    addrlen = 16;
1191 	    break;
1192 #endif
1193 	  default:
1194 		croak("Bad address family for %s, got %d, should be"
1195 #ifdef AF_INET6
1196 		      " either AF_INET or AF_INET6",
1197 #else
1198 		      " AF_INET",
1199 #endif
1200 		      "Socket::inet_pton", af);
1201 	}
1202 	ok = (*host != '\0') && inet_pton(af, host, &ip_address);
1203 
1204 	ST(0) = sv_newmortal();
1205 	if (ok) {
1206 		sv_setpvn( ST(0), (char *)&ip_address, addrlen);
1207 	}
1208 #else
1209 	PERL_UNUSED_VAR(af);
1210 	PERL_UNUSED_VAR(host);
1211 	ST(0) = (SV*)not_here("inet_pton");
1212 #endif
1213 
1214 void
1215 pack_ip_mreq(multiaddr, interface=&PL_sv_undef)
1216 	SV *	multiaddr
1217 	SV *	interface
1218 	CODE:
1219 	{
1220 #ifdef HAS_IP_MREQ
1221 	struct ip_mreq mreq;
1222 	char * multiaddrbytes;
1223 	char * interfacebytes;
1224 	STRLEN len;
1225 	if (DO_UTF8(multiaddr) && !sv_utf8_downgrade(multiaddr, 1))
1226 		croak("Wide character in %s", "Socket::pack_ip_mreq");
1227 	multiaddrbytes = SvPVbyte(multiaddr, len);
1228 	if (len != sizeof(mreq.imr_multiaddr))
1229 		croak("Bad arg length %s, length is %" UVuf
1230                       ", should be %" UVuf,
1231 		      "Socket::pack_ip_mreq", (UV)len, (UV)sizeof(mreq.imr_multiaddr));
1232 	Zero(&mreq, sizeof(mreq), char);
1233 	Copy(multiaddrbytes, &mreq.imr_multiaddr, sizeof(mreq.imr_multiaddr), char);
1234 	if(SvOK(interface)) {
1235 		if (DO_UTF8(interface) && !sv_utf8_downgrade(interface, 1))
1236 			croak("Wide character in %s", "Socket::pack_ip_mreq");
1237 		interfacebytes = SvPVbyte(interface, len);
1238 		if (len != sizeof(mreq.imr_interface))
1239 			croak("Bad arg length %s, length is %" UVuf
1240                               ", should be %" UVuf,
1241 			      "Socket::pack_ip_mreq", (UV)len, (UV)sizeof(mreq.imr_interface));
1242 		Copy(interfacebytes, &mreq.imr_interface, sizeof(mreq.imr_interface), char);
1243 	}
1244 	else
1245 		mreq.imr_interface.s_addr = INADDR_ANY;
1246 	ST(0) = sv_2mortal(newSVpvn((char *)&mreq, sizeof(mreq)));
1247 #else
1248 	not_here("pack_ip_mreq");
1249 #endif
1250 	}
1251 
1252 void
1253 unpack_ip_mreq(mreq_sv)
1254 	SV * mreq_sv
1255 	PPCODE:
1256 	{
1257 #ifdef HAS_IP_MREQ
1258 	struct ip_mreq mreq;
1259 	STRLEN mreqlen;
1260 	char * mreqbytes = SvPVbyte(mreq_sv, mreqlen);
1261 	if (mreqlen != sizeof(mreq))
1262 		croak("Bad arg length for %s, length is %" UVuf
1263                       ", should be %" UVuf,
1264 		      "Socket::unpack_ip_mreq", (UV)mreqlen, (UV)sizeof(mreq));
1265 	Copy(mreqbytes, &mreq, sizeof(mreq), char);
1266 	EXTEND(SP, 2);
1267 	mPUSHp((char *)&mreq.imr_multiaddr, sizeof(mreq.imr_multiaddr));
1268 	mPUSHp((char *)&mreq.imr_interface, sizeof(mreq.imr_interface));
1269 #else
1270 	not_here("unpack_ip_mreq");
1271 #endif
1272 	}
1273 
1274 void
1275 pack_ip_mreq_source(multiaddr, source, interface=&PL_sv_undef)
1276 	SV *	multiaddr
1277 	SV *	source
1278 	SV *	interface
1279 	CODE:
1280 	{
1281 #if defined(HAS_IP_MREQ_SOURCE) && defined (IP_ADD_SOURCE_MEMBERSHIP)
1282 	struct ip_mreq_source mreq;
1283 	char * multiaddrbytes;
1284 	char * sourcebytes;
1285 	char * interfacebytes;
1286 	STRLEN len;
1287 	if (DO_UTF8(multiaddr) && !sv_utf8_downgrade(multiaddr, 1))
1288 		croak("Wide character in %s", "Socket::pack_ip_mreq_source");
1289 	multiaddrbytes = SvPVbyte(multiaddr, len);
1290 	if (len != sizeof(mreq.imr_multiaddr))
1291 		croak("Bad arg length %s, length is %" UVuf
1292                       ", should be %" UVuf,
1293 		      "Socket::pack_ip_mreq", (UV)len, (UV)sizeof(mreq.imr_multiaddr));
1294 	if (DO_UTF8(source) && !sv_utf8_downgrade(source, 1))
1295 		croak("Wide character in %s", "Socket::pack_ip_mreq_source");
1296 	if (len != sizeof(mreq.imr_sourceaddr))
1297 		croak("Bad arg length %s, length is %" UVuf
1298                       ", should be %" UVuf,
1299 		      "Socket::pack_ip_mreq", (UV)len, (UV)sizeof(mreq.imr_sourceaddr));
1300 	sourcebytes = SvPVbyte(source, len);
1301 	Zero(&mreq, sizeof(mreq), char);
1302 	Copy(multiaddrbytes, &mreq.imr_multiaddr, sizeof(mreq.imr_multiaddr), char);
1303 	Copy(sourcebytes, &mreq.imr_sourceaddr, sizeof(mreq.imr_sourceaddr), char);
1304 	if(SvOK(interface)) {
1305 		if (DO_UTF8(interface) && !sv_utf8_downgrade(interface, 1))
1306 			croak("Wide character in %s", "Socket::pack_ip_mreq");
1307 		interfacebytes = SvPVbyte(interface, len);
1308 		if (len != sizeof(mreq.imr_interface))
1309 			croak("Bad arg length %s, length is %" UVuf
1310                               ", should be %" UVuf,
1311 			      "Socket::pack_ip_mreq", (UV)len, (UV)sizeof(mreq.imr_interface));
1312 		Copy(interfacebytes, &mreq.imr_interface, sizeof(mreq.imr_interface), char);
1313 	}
1314 	else
1315 		mreq.imr_interface.s_addr = INADDR_ANY;
1316 	ST(0) = sv_2mortal(newSVpvn((char *)&mreq, sizeof(mreq)));
1317 #else
1318 	PERL_UNUSED_VAR(multiaddr);
1319 	PERL_UNUSED_VAR(source);
1320 	not_here("pack_ip_mreq_source");
1321 #endif
1322 	}
1323 
1324 void
1325 unpack_ip_mreq_source(mreq_sv)
1326 	SV * mreq_sv
1327 	PPCODE:
1328 	{
1329 #if defined(HAS_IP_MREQ_SOURCE) && defined (IP_ADD_SOURCE_MEMBERSHIP)
1330 	struct ip_mreq_source mreq;
1331 	STRLEN mreqlen;
1332 	char * mreqbytes = SvPVbyte(mreq_sv, mreqlen);
1333 	if (mreqlen != sizeof(mreq))
1334 		croak("Bad arg length for %s, length is %" UVuf
1335                       ", should be %" UVuf,
1336 		      "Socket::unpack_ip_mreq_source", (UV)mreqlen, (UV)sizeof(mreq));
1337 	Copy(mreqbytes, &mreq, sizeof(mreq), char);
1338 	EXTEND(SP, 3);
1339 	mPUSHp((char *)&mreq.imr_multiaddr, sizeof(mreq.imr_multiaddr));
1340 	mPUSHp((char *)&mreq.imr_sourceaddr, sizeof(mreq.imr_sourceaddr));
1341 	mPUSHp((char *)&mreq.imr_interface, sizeof(mreq.imr_interface));
1342 #else
1343 	PERL_UNUSED_VAR(mreq_sv);
1344 	not_here("unpack_ip_mreq_source");
1345 #endif
1346 	}
1347 
1348 void
1349 pack_ipv6_mreq(multiaddr, ifindex)
1350 	SV *	multiaddr
1351 	unsigned int	ifindex
1352 	CODE:
1353 	{
1354 #ifdef HAS_IPV6_MREQ
1355 	struct ipv6_mreq mreq;
1356 	char * multiaddrbytes;
1357 	STRLEN len;
1358 	if (DO_UTF8(multiaddr) && !sv_utf8_downgrade(multiaddr, 1))
1359 		croak("Wide character in %s", "Socket::pack_ipv6_mreq");
1360 	multiaddrbytes = SvPVbyte(multiaddr, len);
1361 	if (len != sizeof(mreq.ipv6mr_multiaddr))
1362 		croak("Bad arg length %s, length is %" UVuf
1363                       ", should be %" UVuf,
1364 		      "Socket::pack_ipv6_mreq", (UV)len, (UV)sizeof(mreq.ipv6mr_multiaddr));
1365 	Zero(&mreq, sizeof(mreq), char);
1366 	Copy(multiaddrbytes, &mreq.ipv6mr_multiaddr, sizeof(mreq.ipv6mr_multiaddr), char);
1367 	mreq.ipv6mr_interface = ifindex;
1368 	ST(0) = sv_2mortal(newSVpvn((char *)&mreq, sizeof(mreq)));
1369 #else
1370 	PERL_UNUSED_VAR(multiaddr);
1371 	PERL_UNUSED_VAR(ifindex);
1372 	not_here("pack_ipv6_mreq");
1373 #endif
1374 	}
1375 
1376 void
1377 unpack_ipv6_mreq(mreq_sv)
1378 	SV * mreq_sv
1379 	PPCODE:
1380 	{
1381 #ifdef HAS_IPV6_MREQ
1382 	struct ipv6_mreq mreq;
1383 	STRLEN mreqlen;
1384 	char * mreqbytes = SvPVbyte(mreq_sv, mreqlen);
1385 	if (mreqlen != sizeof(mreq))
1386 		croak("Bad arg length for %s, length is %" UVuf
1387                       ", should be %" UVuf,
1388 		      "Socket::unpack_ipv6_mreq", (UV)mreqlen, (UV)sizeof(mreq));
1389 	Copy(mreqbytes, &mreq, sizeof(mreq), char);
1390 	EXTEND(SP, 2);
1391 	mPUSHp((char *)&mreq.ipv6mr_multiaddr, sizeof(mreq.ipv6mr_multiaddr));
1392 	mPUSHi(mreq.ipv6mr_interface);
1393 #else
1394 	PERL_UNUSED_VAR(mreq_sv);
1395 	not_here("unpack_ipv6_mreq");
1396 #endif
1397 	}
1398