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