xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/ext/Socket/Socket.xs (revision 0:68f95e015346)
1*0Sstevel@tonic-gate #define PERL_NO_GET_CONTEXT
2*0Sstevel@tonic-gate #include "EXTERN.h"
3*0Sstevel@tonic-gate #include "perl.h"
4*0Sstevel@tonic-gate #include "XSUB.h"
5*0Sstevel@tonic-gate 
6*0Sstevel@tonic-gate #include <stddef.h>
7*0Sstevel@tonic-gate 
8*0Sstevel@tonic-gate #ifndef VMS
9*0Sstevel@tonic-gate # ifdef I_SYS_TYPES
10*0Sstevel@tonic-gate #  include <sys/types.h>
11*0Sstevel@tonic-gate # endif
12*0Sstevel@tonic-gate # if !defined(ultrix) /* Avoid double definition. */
13*0Sstevel@tonic-gate #   include <sys/socket.h>
14*0Sstevel@tonic-gate # endif
15*0Sstevel@tonic-gate # if defined(USE_SOCKS) && defined(I_SOCKS)
16*0Sstevel@tonic-gate #   include <socks.h>
17*0Sstevel@tonic-gate # endif
18*0Sstevel@tonic-gate # ifdef MPE
19*0Sstevel@tonic-gate #  define PF_INET AF_INET
20*0Sstevel@tonic-gate #  define PF_UNIX AF_UNIX
21*0Sstevel@tonic-gate #  define SOCK_RAW 3
22*0Sstevel@tonic-gate # endif
23*0Sstevel@tonic-gate # ifdef I_SYS_UN
24*0Sstevel@tonic-gate #  include <sys/un.h>
25*0Sstevel@tonic-gate # endif
26*0Sstevel@tonic-gate /* XXX Configure test for <netinet/in_systm.h needed XXX */
27*0Sstevel@tonic-gate # if defined(NeXT) || defined(__NeXT__)
28*0Sstevel@tonic-gate #  include <netinet/in_systm.h>
29*0Sstevel@tonic-gate # endif
30*0Sstevel@tonic-gate # if defined(__sgi) && !defined(AF_LINK) && defined(PF_LINK) && PF_LINK == AF_LNK
31*0Sstevel@tonic-gate #  undef PF_LINK
32*0Sstevel@tonic-gate # endif
33*0Sstevel@tonic-gate # if defined(I_NETINET_IN) || defined(__ultrix__)
34*0Sstevel@tonic-gate #  include <netinet/in.h>
35*0Sstevel@tonic-gate # endif
36*0Sstevel@tonic-gate # ifdef I_NETDB
37*0Sstevel@tonic-gate #  if !defined(ultrix)  /* Avoid double definition. */
38*0Sstevel@tonic-gate #   include <netdb.h>
39*0Sstevel@tonic-gate #  endif
40*0Sstevel@tonic-gate # endif
41*0Sstevel@tonic-gate # ifdef I_ARPA_INET
42*0Sstevel@tonic-gate #  include <arpa/inet.h>
43*0Sstevel@tonic-gate # endif
44*0Sstevel@tonic-gate # ifdef I_NETINET_TCP
45*0Sstevel@tonic-gate #  include <netinet/tcp.h>
46*0Sstevel@tonic-gate # endif
47*0Sstevel@tonic-gate #else
48*0Sstevel@tonic-gate # include "sockadapt.h"
49*0Sstevel@tonic-gate #endif
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate #ifdef NETWARE
52*0Sstevel@tonic-gate NETDB_DEFINE_CONTEXT
53*0Sstevel@tonic-gate NETINET_DEFINE_CONTEXT
54*0Sstevel@tonic-gate #endif
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate #ifdef I_SYSUIO
57*0Sstevel@tonic-gate # include <sys/uio.h>
58*0Sstevel@tonic-gate #endif
59*0Sstevel@tonic-gate 
60*0Sstevel@tonic-gate #ifndef AF_NBS
61*0Sstevel@tonic-gate # undef PF_NBS
62*0Sstevel@tonic-gate #endif
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate #ifndef AF_X25
65*0Sstevel@tonic-gate # undef PF_X25
66*0Sstevel@tonic-gate #endif
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate #ifndef INADDR_NONE
69*0Sstevel@tonic-gate # define INADDR_NONE	0xffffffff
70*0Sstevel@tonic-gate #endif /* INADDR_NONE */
71*0Sstevel@tonic-gate #ifndef INADDR_BROADCAST
72*0Sstevel@tonic-gate # define INADDR_BROADCAST	0xffffffff
73*0Sstevel@tonic-gate #endif /* INADDR_BROADCAST */
74*0Sstevel@tonic-gate #ifndef INADDR_LOOPBACK
75*0Sstevel@tonic-gate # define INADDR_LOOPBACK         0x7F000001
76*0Sstevel@tonic-gate #endif /* INADDR_LOOPBACK */
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate #ifndef HAS_INET_ATON
79*0Sstevel@tonic-gate 
80*0Sstevel@tonic-gate /*
81*0Sstevel@tonic-gate  * Check whether "cp" is a valid ascii representation
82*0Sstevel@tonic-gate  * of an Internet address and convert to a binary address.
83*0Sstevel@tonic-gate  * Returns 1 if the address is valid, 0 if not.
84*0Sstevel@tonic-gate  * This replaces inet_addr, the return value from which
85*0Sstevel@tonic-gate  * cannot distinguish between failure and a local broadcast address.
86*0Sstevel@tonic-gate  */
87*0Sstevel@tonic-gate static int
my_inet_aton(register const char * cp,struct in_addr * addr)88*0Sstevel@tonic-gate my_inet_aton(register const char *cp, struct in_addr *addr)
89*0Sstevel@tonic-gate {
90*0Sstevel@tonic-gate 	dTHX;
91*0Sstevel@tonic-gate 	register U32 val;
92*0Sstevel@tonic-gate 	register int base;
93*0Sstevel@tonic-gate 	register char c;
94*0Sstevel@tonic-gate 	int nparts;
95*0Sstevel@tonic-gate 	const char *s;
96*0Sstevel@tonic-gate 	unsigned int parts[4];
97*0Sstevel@tonic-gate 	register unsigned int *pp = parts;
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate        if (!cp || !*cp)
100*0Sstevel@tonic-gate 		return 0;
101*0Sstevel@tonic-gate 	for (;;) {
102*0Sstevel@tonic-gate 		/*
103*0Sstevel@tonic-gate 		 * Collect number up to ``.''.
104*0Sstevel@tonic-gate 		 * Values are specified as for C:
105*0Sstevel@tonic-gate 		 * 0x=hex, 0=octal, other=decimal.
106*0Sstevel@tonic-gate 		 */
107*0Sstevel@tonic-gate 		val = 0; base = 10;
108*0Sstevel@tonic-gate 		if (*cp == '0') {
109*0Sstevel@tonic-gate 			if (*++cp == 'x' || *cp == 'X')
110*0Sstevel@tonic-gate 				base = 16, cp++;
111*0Sstevel@tonic-gate 			else
112*0Sstevel@tonic-gate 				base = 8;
113*0Sstevel@tonic-gate 		}
114*0Sstevel@tonic-gate 		while ((c = *cp) != '\0') {
115*0Sstevel@tonic-gate 			if (isDIGIT(c)) {
116*0Sstevel@tonic-gate 				val = (val * base) + (c - '0');
117*0Sstevel@tonic-gate 				cp++;
118*0Sstevel@tonic-gate 				continue;
119*0Sstevel@tonic-gate 			}
120*0Sstevel@tonic-gate 			if (base == 16 && (s=strchr(PL_hexdigit,c))) {
121*0Sstevel@tonic-gate 				val = (val << 4) +
122*0Sstevel@tonic-gate 					((s - PL_hexdigit) & 15);
123*0Sstevel@tonic-gate 				cp++;
124*0Sstevel@tonic-gate 				continue;
125*0Sstevel@tonic-gate 			}
126*0Sstevel@tonic-gate 			break;
127*0Sstevel@tonic-gate 		}
128*0Sstevel@tonic-gate 		if (*cp == '.') {
129*0Sstevel@tonic-gate 			/*
130*0Sstevel@tonic-gate 			 * Internet format:
131*0Sstevel@tonic-gate 			 *	a.b.c.d
132*0Sstevel@tonic-gate 			 *	a.b.c	(with c treated as 16-bits)
133*0Sstevel@tonic-gate 			 *	a.b	(with b treated as 24 bits)
134*0Sstevel@tonic-gate 			 */
135*0Sstevel@tonic-gate 			if (pp >= parts + 3 || val > 0xff)
136*0Sstevel@tonic-gate 				return 0;
137*0Sstevel@tonic-gate 			*pp++ = val, cp++;
138*0Sstevel@tonic-gate 		} else
139*0Sstevel@tonic-gate 			break;
140*0Sstevel@tonic-gate 	}
141*0Sstevel@tonic-gate 	/*
142*0Sstevel@tonic-gate 	 * Check for trailing characters.
143*0Sstevel@tonic-gate 	 */
144*0Sstevel@tonic-gate 	if (*cp && !isSPACE(*cp))
145*0Sstevel@tonic-gate 		return 0;
146*0Sstevel@tonic-gate 	/*
147*0Sstevel@tonic-gate 	 * Concoct the address according to
148*0Sstevel@tonic-gate 	 * the number of parts specified.
149*0Sstevel@tonic-gate 	 */
150*0Sstevel@tonic-gate 	nparts = pp - parts + 1;	/* force to an int for switch() */
151*0Sstevel@tonic-gate 	switch (nparts) {
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate 	case 1:				/* a -- 32 bits */
154*0Sstevel@tonic-gate 		break;
155*0Sstevel@tonic-gate 
156*0Sstevel@tonic-gate 	case 2:				/* a.b -- 8.24 bits */
157*0Sstevel@tonic-gate 		if (val > 0xffffff)
158*0Sstevel@tonic-gate 			return 0;
159*0Sstevel@tonic-gate 		val |= parts[0] << 24;
160*0Sstevel@tonic-gate 		break;
161*0Sstevel@tonic-gate 
162*0Sstevel@tonic-gate 	case 3:				/* a.b.c -- 8.8.16 bits */
163*0Sstevel@tonic-gate 		if (val > 0xffff)
164*0Sstevel@tonic-gate 			return 0;
165*0Sstevel@tonic-gate 		val |= (parts[0] << 24) | (parts[1] << 16);
166*0Sstevel@tonic-gate 		break;
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate 	case 4:				/* a.b.c.d -- 8.8.8.8 bits */
169*0Sstevel@tonic-gate 		if (val > 0xff)
170*0Sstevel@tonic-gate 			return 0;
171*0Sstevel@tonic-gate 		val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
172*0Sstevel@tonic-gate 		break;
173*0Sstevel@tonic-gate 	}
174*0Sstevel@tonic-gate 	addr->s_addr = htonl(val);
175*0Sstevel@tonic-gate 	return 1;
176*0Sstevel@tonic-gate }
177*0Sstevel@tonic-gate 
178*0Sstevel@tonic-gate #undef inet_aton
179*0Sstevel@tonic-gate #define inet_aton my_inet_aton
180*0Sstevel@tonic-gate 
181*0Sstevel@tonic-gate #endif /* ! HAS_INET_ATON */
182*0Sstevel@tonic-gate 
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate static int
not_here(char * s)185*0Sstevel@tonic-gate not_here(char *s)
186*0Sstevel@tonic-gate {
187*0Sstevel@tonic-gate     croak("Socket::%s not implemented on this architecture", s);
188*0Sstevel@tonic-gate     return -1;
189*0Sstevel@tonic-gate }
190*0Sstevel@tonic-gate 
191*0Sstevel@tonic-gate #define PERL_IN_ADDR_S_ADDR_SIZE 4
192*0Sstevel@tonic-gate 
193*0Sstevel@tonic-gate /*
194*0Sstevel@tonic-gate * Bad assumptions possible here.
195*0Sstevel@tonic-gate *
196*0Sstevel@tonic-gate * Bad Assumption 1: struct in_addr has no other fields
197*0Sstevel@tonic-gate * than the s_addr (which is the field we care about
198*0Sstevel@tonic-gate * in here, really). However, we can be fed either 4-byte
199*0Sstevel@tonic-gate * addresses (from pack("N", ...), or va.b.c.d, or ...),
200*0Sstevel@tonic-gate * or full struct in_addrs (from e.g. pack_sockaddr_in()),
201*0Sstevel@tonic-gate * which may or may not be 4 bytes in size.
202*0Sstevel@tonic-gate *
203*0Sstevel@tonic-gate * Bad Assumption 2: the s_addr field is a simple type
204*0Sstevel@tonic-gate * (such as an int, u_int32_t).  It can be a bit field,
205*0Sstevel@tonic-gate * in which case using & (address-of) on it or taking sizeof()
206*0Sstevel@tonic-gate * wouldn't go over too well.  (Those are not attempted
207*0Sstevel@tonic-gate * now but in case someone thinks to change the below code
208*0Sstevel@tonic-gate * to use addr.s_addr instead of addr, you have been warned.)
209*0Sstevel@tonic-gate *
210*0Sstevel@tonic-gate * Bad Assumption 3: the s_addr is the first field in
211*0Sstevel@tonic-gate * an in_addr, or that its bytes are the first bytes in
212*0Sstevel@tonic-gate * an in_addr.
213*0Sstevel@tonic-gate *
214*0Sstevel@tonic-gate * These bad assumptions are wrong in UNICOS which has
215*0Sstevel@tonic-gate * struct in_addr { struct { u_long  st_addr:32; } s_da };
216*0Sstevel@tonic-gate * #define s_addr s_da.st_addr
217*0Sstevel@tonic-gate * and u_long is 64 bits.
218*0Sstevel@tonic-gate *
219*0Sstevel@tonic-gate * --jhi */
220*0Sstevel@tonic-gate 
221*0Sstevel@tonic-gate #include "const-c.inc"
222*0Sstevel@tonic-gate 
223*0Sstevel@tonic-gate MODULE = Socket		PACKAGE = Socket
224*0Sstevel@tonic-gate 
225*0Sstevel@tonic-gate INCLUDE: const-xs.inc
226*0Sstevel@tonic-gate 
227*0Sstevel@tonic-gate void
228*0Sstevel@tonic-gate inet_aton(host)
229*0Sstevel@tonic-gate 	char *	host
230*0Sstevel@tonic-gate 	CODE:
231*0Sstevel@tonic-gate 	{
232*0Sstevel@tonic-gate 	struct in_addr ip_address;
233*0Sstevel@tonic-gate 	struct hostent * phe;
234*0Sstevel@tonic-gate 	int ok =
235*0Sstevel@tonic-gate 		(host != NULL) &&
236*0Sstevel@tonic-gate 		(*host != '\0') &&
237*0Sstevel@tonic-gate 		inet_aton(host, &ip_address);
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate 	if (!ok && (phe = gethostbyname(host))) {
240*0Sstevel@tonic-gate 		Copy( phe->h_addr, &ip_address, phe->h_length, char );
241*0Sstevel@tonic-gate 		ok = 1;
242*0Sstevel@tonic-gate 	}
243*0Sstevel@tonic-gate 
244*0Sstevel@tonic-gate 	ST(0) = sv_newmortal();
245*0Sstevel@tonic-gate 	if (ok)
246*0Sstevel@tonic-gate 		sv_setpvn( ST(0), (char *)&ip_address, sizeof ip_address );
247*0Sstevel@tonic-gate 	}
248*0Sstevel@tonic-gate 
249*0Sstevel@tonic-gate void
inet_ntoa(ip_address_sv)250*0Sstevel@tonic-gate inet_ntoa(ip_address_sv)
251*0Sstevel@tonic-gate 	SV *	ip_address_sv
252*0Sstevel@tonic-gate 	CODE:
253*0Sstevel@tonic-gate 	{
254*0Sstevel@tonic-gate 	STRLEN addrlen;
255*0Sstevel@tonic-gate 	struct in_addr addr;
256*0Sstevel@tonic-gate 	char * addr_str;
257*0Sstevel@tonic-gate 	char * ip_address;
258*0Sstevel@tonic-gate 	if (DO_UTF8(ip_address_sv) && !sv_utf8_downgrade(ip_address_sv, 1))
259*0Sstevel@tonic-gate 	     croak("Wide character in Socket::inet_ntoa");
260*0Sstevel@tonic-gate 	ip_address = SvPVbyte(ip_address_sv, addrlen);
261*0Sstevel@tonic-gate 	if (addrlen == sizeof(addr) || addrlen == 4)
262*0Sstevel@tonic-gate 	        addr.s_addr =
263*0Sstevel@tonic-gate 		    (ip_address[0] & 0xFF) << 24 |
264*0Sstevel@tonic-gate 		    (ip_address[1] & 0xFF) << 16 |
265*0Sstevel@tonic-gate 		    (ip_address[2] & 0xFF) <<  8 |
266*0Sstevel@tonic-gate 		    (ip_address[3] & 0xFF);
267*0Sstevel@tonic-gate 	else
268*0Sstevel@tonic-gate 	        croak("Bad arg length for %s, length is %d, should be %d",
269*0Sstevel@tonic-gate 		      "Socket::inet_ntoa",
270*0Sstevel@tonic-gate 		      addrlen, sizeof(addr));
271*0Sstevel@tonic-gate 	/* We could use inet_ntoa() but that is broken
272*0Sstevel@tonic-gate 	 * in HP-UX + GCC + 64bitint (returns "0.0.0.0"),
273*0Sstevel@tonic-gate 	 * so let's use this sprintf() workaround everywhere.
274*0Sstevel@tonic-gate 	 * This is also more threadsafe than using inet_ntoa(). */
275*0Sstevel@tonic-gate 	New(1138, addr_str, 4 * 3 + 3 + 1, char); /* IPv6? */
276*0Sstevel@tonic-gate 	sprintf(addr_str, "%d.%d.%d.%d",
277*0Sstevel@tonic-gate 		((addr.s_addr >> 24) & 0xFF),
278*0Sstevel@tonic-gate 		((addr.s_addr >> 16) & 0xFF),
279*0Sstevel@tonic-gate 		((addr.s_addr >>  8) & 0xFF),
280*0Sstevel@tonic-gate 		( addr.s_addr        & 0xFF));
281*0Sstevel@tonic-gate 	ST(0) = sv_2mortal(newSVpvn(addr_str, strlen(addr_str)));
282*0Sstevel@tonic-gate 	Safefree(addr_str);
283*0Sstevel@tonic-gate 	}
284*0Sstevel@tonic-gate 
285*0Sstevel@tonic-gate void
286*0Sstevel@tonic-gate sockaddr_family(sockaddr)
287*0Sstevel@tonic-gate 	SV *	sockaddr
288*0Sstevel@tonic-gate 	PREINIT:
289*0Sstevel@tonic-gate 	STRLEN sockaddr_len;
290*0Sstevel@tonic-gate 	char *sockaddr_pv = SvPVbyte(sockaddr, sockaddr_len);
291*0Sstevel@tonic-gate 	CODE:
292*0Sstevel@tonic-gate 	if (sockaddr_len < offsetof(struct sockaddr, sa_data)) {
293*0Sstevel@tonic-gate 	    croak("Bad arg length for %s, length is %d, should be at least %d",
294*0Sstevel@tonic-gate 	          "Socket::sockaddr_family", sockaddr_len,
295*0Sstevel@tonic-gate 		  offsetof(struct sockaddr, sa_data));
296*0Sstevel@tonic-gate 	}
297*0Sstevel@tonic-gate 	ST(0) = sv_2mortal(newSViv(((struct sockaddr*)sockaddr_pv)->sa_family));
298*0Sstevel@tonic-gate 
299*0Sstevel@tonic-gate void
pack_sockaddr_un(pathname)300*0Sstevel@tonic-gate pack_sockaddr_un(pathname)
301*0Sstevel@tonic-gate 	SV *	pathname
302*0Sstevel@tonic-gate 	CODE:
303*0Sstevel@tonic-gate 	{
304*0Sstevel@tonic-gate #ifdef I_SYS_UN
305*0Sstevel@tonic-gate 	struct sockaddr_un sun_ad; /* fear using sun */
306*0Sstevel@tonic-gate 	STRLEN len;
307*0Sstevel@tonic-gate 	char * pathname_pv;
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate 	Zero( &sun_ad, sizeof sun_ad, char );
310*0Sstevel@tonic-gate 	sun_ad.sun_family = AF_UNIX;
311*0Sstevel@tonic-gate 	pathname_pv = SvPV(pathname,len);
312*0Sstevel@tonic-gate 	if (len > sizeof(sun_ad.sun_path))
313*0Sstevel@tonic-gate 	    len = sizeof(sun_ad.sun_path);
314*0Sstevel@tonic-gate #  ifdef OS2	/* Name should start with \socket\ and contain backslashes! */
315*0Sstevel@tonic-gate 	{
316*0Sstevel@tonic-gate 	    int off;
317*0Sstevel@tonic-gate 	    char *s, *e;
318*0Sstevel@tonic-gate 
319*0Sstevel@tonic-gate 	    if (pathname_pv[0] != '/' && pathname_pv[0] != '\\')
320*0Sstevel@tonic-gate 		croak("Relative UNIX domain socket name '%s' unsupported",
321*0Sstevel@tonic-gate 			pathname_pv);
322*0Sstevel@tonic-gate 	    else if (len < 8
323*0Sstevel@tonic-gate 		     || pathname_pv[7] != '/' && pathname_pv[7] != '\\'
324*0Sstevel@tonic-gate 		     || !strnicmp(pathname_pv + 1, "socket", 6))
325*0Sstevel@tonic-gate 		off = 7;
326*0Sstevel@tonic-gate 	    else
327*0Sstevel@tonic-gate 		off = 0;		/* Preserve names starting with \socket\ */
328*0Sstevel@tonic-gate 	    Copy( "\\socket", sun_ad.sun_path, off, char);
329*0Sstevel@tonic-gate 	    Copy( pathname_pv, sun_ad.sun_path + off, len, char );
330*0Sstevel@tonic-gate 
331*0Sstevel@tonic-gate 	    s = sun_ad.sun_path + off - 1;
332*0Sstevel@tonic-gate 	    e = s + len + 1;
333*0Sstevel@tonic-gate 	    while (++s < e)
334*0Sstevel@tonic-gate 		if (*s = '/')
335*0Sstevel@tonic-gate 		    *s = '\\';
336*0Sstevel@tonic-gate 	}
337*0Sstevel@tonic-gate #  else	/* !( defined OS2 ) */
338*0Sstevel@tonic-gate 	Copy( pathname_pv, sun_ad.sun_path, len, char );
339*0Sstevel@tonic-gate #  endif
340*0Sstevel@tonic-gate 	if (0) not_here("dummy");
341*0Sstevel@tonic-gate 	ST(0) = sv_2mortal(newSVpvn((char *)&sun_ad, sizeof sun_ad));
342*0Sstevel@tonic-gate #else
343*0Sstevel@tonic-gate 	ST(0) = (SV *) not_here("pack_sockaddr_un");
344*0Sstevel@tonic-gate #endif
345*0Sstevel@tonic-gate 
346*0Sstevel@tonic-gate 	}
347*0Sstevel@tonic-gate 
348*0Sstevel@tonic-gate void
unpack_sockaddr_un(sun_sv)349*0Sstevel@tonic-gate unpack_sockaddr_un(sun_sv)
350*0Sstevel@tonic-gate 	SV *	sun_sv
351*0Sstevel@tonic-gate 	CODE:
352*0Sstevel@tonic-gate 	{
353*0Sstevel@tonic-gate #ifdef I_SYS_UN
354*0Sstevel@tonic-gate 	struct sockaddr_un addr;
355*0Sstevel@tonic-gate 	STRLEN sockaddrlen;
356*0Sstevel@tonic-gate 	char * sun_ad = SvPVbyte(sun_sv,sockaddrlen);
357*0Sstevel@tonic-gate 	char * e;
358*0Sstevel@tonic-gate #   ifndef __linux__
359*0Sstevel@tonic-gate 	/* On Linux sockaddrlen on sockets returned by accept, recvfrom,
360*0Sstevel@tonic-gate 	   getpeername and getsockname is not equal to sizeof(addr). */
361*0Sstevel@tonic-gate 	if (sockaddrlen != sizeof(addr)) {
362*0Sstevel@tonic-gate 	    croak("Bad arg length for %s, length is %d, should be %d",
363*0Sstevel@tonic-gate 			"Socket::unpack_sockaddr_un",
364*0Sstevel@tonic-gate 			sockaddrlen, sizeof(addr));
365*0Sstevel@tonic-gate 	}
366*0Sstevel@tonic-gate #   endif
367*0Sstevel@tonic-gate 
368*0Sstevel@tonic-gate 	Copy( sun_ad, &addr, sizeof addr, char );
369*0Sstevel@tonic-gate 
370*0Sstevel@tonic-gate 	if ( addr.sun_family != AF_UNIX ) {
371*0Sstevel@tonic-gate 	    croak("Bad address family for %s, got %d, should be %d",
372*0Sstevel@tonic-gate 			"Socket::unpack_sockaddr_un",
373*0Sstevel@tonic-gate 			addr.sun_family,
374*0Sstevel@tonic-gate 			AF_UNIX);
375*0Sstevel@tonic-gate 	}
376*0Sstevel@tonic-gate 	e = (char*)addr.sun_path;
377*0Sstevel@tonic-gate 	/* On Linux, the name of abstract unix domain sockets begins
378*0Sstevel@tonic-gate 	 * with a '\0', so allow this. */
379*0Sstevel@tonic-gate 	while ((*e || (e == addr.sun_path && e[1] && sockaddrlen > 1))
380*0Sstevel@tonic-gate 		&& e < (char*)addr.sun_path + sizeof addr.sun_path)
381*0Sstevel@tonic-gate 	    ++e;
382*0Sstevel@tonic-gate 	ST(0) = sv_2mortal(newSVpvn(addr.sun_path, e - (char*)addr.sun_path));
383*0Sstevel@tonic-gate #else
384*0Sstevel@tonic-gate 	ST(0) = (SV *) not_here("unpack_sockaddr_un");
385*0Sstevel@tonic-gate #endif
386*0Sstevel@tonic-gate 	}
387*0Sstevel@tonic-gate 
388*0Sstevel@tonic-gate void
pack_sockaddr_in(port,ip_address_sv)389*0Sstevel@tonic-gate pack_sockaddr_in(port, ip_address_sv)
390*0Sstevel@tonic-gate 	unsigned short	port
391*0Sstevel@tonic-gate 	SV *	ip_address_sv
392*0Sstevel@tonic-gate 	CODE:
393*0Sstevel@tonic-gate 	{
394*0Sstevel@tonic-gate 	struct sockaddr_in sin;
395*0Sstevel@tonic-gate 	struct in_addr addr;
396*0Sstevel@tonic-gate 	STRLEN addrlen;
397*0Sstevel@tonic-gate 	char * ip_address;
398*0Sstevel@tonic-gate 	if (DO_UTF8(ip_address_sv) && !sv_utf8_downgrade(ip_address_sv, 1))
399*0Sstevel@tonic-gate 	     croak("Wide character in Socket::pack_sockaddr_in");
400*0Sstevel@tonic-gate 	ip_address = SvPVbyte(ip_address_sv, addrlen);
401*0Sstevel@tonic-gate 	if (addrlen == sizeof(addr) || addrlen == 4)
402*0Sstevel@tonic-gate 	        addr.s_addr =
403*0Sstevel@tonic-gate 		    (ip_address[0] & 0xFF) << 24 |
404*0Sstevel@tonic-gate 		    (ip_address[1] & 0xFF) << 16 |
405*0Sstevel@tonic-gate 		    (ip_address[2] & 0xFF) <<  8 |
406*0Sstevel@tonic-gate 		    (ip_address[3] & 0xFF);
407*0Sstevel@tonic-gate 	else
408*0Sstevel@tonic-gate 	        croak("Bad arg length for %s, length is %d, should be %d",
409*0Sstevel@tonic-gate 		      "Socket::pack_sockaddr_in",
410*0Sstevel@tonic-gate 		      addrlen, sizeof(addr));
411*0Sstevel@tonic-gate 	Zero( &sin, sizeof sin, char );
412*0Sstevel@tonic-gate 	sin.sin_family = AF_INET;
413*0Sstevel@tonic-gate 	sin.sin_port = htons(port);
414*0Sstevel@tonic-gate 	sin.sin_addr.s_addr = htonl(addr.s_addr);
415*0Sstevel@tonic-gate 	ST(0) = sv_2mortal(newSVpvn((char *)&sin, sizeof sin));
416*0Sstevel@tonic-gate 	}
417*0Sstevel@tonic-gate 
418*0Sstevel@tonic-gate void
unpack_sockaddr_in(sin_sv)419*0Sstevel@tonic-gate unpack_sockaddr_in(sin_sv)
420*0Sstevel@tonic-gate 	SV *	sin_sv
421*0Sstevel@tonic-gate 	PPCODE:
422*0Sstevel@tonic-gate 	{
423*0Sstevel@tonic-gate 	STRLEN sockaddrlen;
424*0Sstevel@tonic-gate 	struct sockaddr_in addr;
425*0Sstevel@tonic-gate 	unsigned short	port;
426*0Sstevel@tonic-gate 	struct in_addr  ip_address;
427*0Sstevel@tonic-gate 	char *	sin = SvPVbyte(sin_sv,sockaddrlen);
428*0Sstevel@tonic-gate 	if (sockaddrlen != sizeof(addr)) {
429*0Sstevel@tonic-gate 	    croak("Bad arg length for %s, length is %d, should be %d",
430*0Sstevel@tonic-gate 			"Socket::unpack_sockaddr_in",
431*0Sstevel@tonic-gate 			sockaddrlen, sizeof(addr));
432*0Sstevel@tonic-gate 	}
433*0Sstevel@tonic-gate 	Copy( sin, &addr,sizeof addr, char );
434*0Sstevel@tonic-gate 	if ( addr.sin_family != AF_INET ) {
435*0Sstevel@tonic-gate 	    croak("Bad address family for %s, got %d, should be %d",
436*0Sstevel@tonic-gate 			"Socket::unpack_sockaddr_in",
437*0Sstevel@tonic-gate 			addr.sin_family,
438*0Sstevel@tonic-gate 			AF_INET);
439*0Sstevel@tonic-gate 	}
440*0Sstevel@tonic-gate 	port = ntohs(addr.sin_port);
441*0Sstevel@tonic-gate 	ip_address = addr.sin_addr;
442*0Sstevel@tonic-gate 
443*0Sstevel@tonic-gate 	EXTEND(SP, 2);
444*0Sstevel@tonic-gate 	PUSHs(sv_2mortal(newSViv((IV) port)));
445*0Sstevel@tonic-gate 	PUSHs(sv_2mortal(newSVpvn((char *)&ip_address, sizeof ip_address)));
446*0Sstevel@tonic-gate 	}
447