#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <stddef.h>
#ifndef VMS
# ifdef I_SYS_TYPES
# endif
# if !defined(ultrix) /* Avoid double definition. */
# endif
# include <socks.h>
# endif
# ifdef MPE
# define SOCK_RAW 3
# endif
# ifdef I_SYS_UN
# endif
/* XXX Configure test for <netinet/in_systm.h needed XXX */
# include <netinet/in_systm.h>
# endif
# endif
# if defined(I_NETINET_IN) || defined(__ultrix__)
# endif
# ifdef I_NETDB
# if !defined(ultrix) /* Avoid double definition. */
# include <netdb.h>
# endif
# endif
# ifdef I_ARPA_INET
# endif
# ifdef I_NETINET_TCP
# endif
#else
# include "sockadapt.h"
#endif
#ifdef NETWARE
#endif
#ifdef I_SYSUIO
#endif
#ifndef AF_NBS
#endif
#ifndef AF_X25
#endif
#ifndef INADDR_NONE
# define INADDR_NONE 0xffffffff
#endif /* INADDR_NONE */
#ifndef INADDR_BROADCAST
# define INADDR_BROADCAST 0xffffffff
#endif /* INADDR_BROADCAST */
#ifndef INADDR_LOOPBACK
# define INADDR_LOOPBACK 0x7F000001
#endif /* INADDR_LOOPBACK */
#ifndef HAS_INET_ATON
/*
* Check whether "cp" is a valid ascii representation
* of an Internet address and convert to a binary address.
* Returns 1 if the address is valid, 0 if not.
* This replaces inet_addr, the return value from which
* cannot distinguish between failure and a local broadcast address.
*/
static int
{
dTHX;
register int base;
register char c;
int nparts;
const char *s;
unsigned int parts[4];
return 0;
for (;;) {
/*
* Collect number up to ``.''.
* Values are specified as for C:
* 0x=hex, 0=octal, other=decimal.
*/
if (*cp == '0') {
else
base = 8;
}
while ((c = *cp) != '\0') {
if (isDIGIT(c)) {
cp++;
continue;
}
((s - PL_hexdigit) & 15);
cp++;
continue;
}
break;
}
if (*cp == '.') {
/*
* Internet format:
* a.b.c.d
* a.b.c (with c treated as 16-bits)
* a.b (with b treated as 24 bits)
*/
return 0;
} else
break;
}
/*
* Check for trailing characters.
*/
return 0;
/*
* Concoct the address according to
* the number of parts specified.
*/
switch (nparts) {
case 1: /* a -- 32 bits */
break;
case 2: /* a.b -- 8.24 bits */
if (val > 0xffffff)
return 0;
break;
case 3: /* a.b.c -- 8.8.16 bits */
if (val > 0xffff)
return 0;
break;
case 4: /* a.b.c.d -- 8.8.8.8 bits */
if (val > 0xff)
return 0;
break;
}
return 1;
}
#define inet_aton my_inet_aton
#endif /* ! HAS_INET_ATON */
static int
not_here(char *s)
{
croak("Socket::%s not implemented on this architecture", s);
return -1;
}
#define PERL_IN_ADDR_S_ADDR_SIZE 4
/*
* Bad assumptions possible here.
*
* Bad Assumption 1: struct in_addr has no other fields
* than the s_addr (which is the field we care about
* in here, really). However, we can be fed either 4-byte
* addresses (from pack("N", ...), or va.b.c.d, or ...),
* or full struct in_addrs (from e.g. pack_sockaddr_in()),
* which may or may not be 4 bytes in size.
*
* Bad Assumption 2: the s_addr field is a simple type
* (such as an int, u_int32_t). It can be a bit field,
* in which case using & (address-of) on it or taking sizeof()
* wouldn't go over too well. (Those are not attempted
* now but in case someone thinks to change the below code
* to use addr.s_addr instead of addr, you have been warned.)
*
* Bad Assumption 3: the s_addr is the first field in
* an in_addr, or that its bytes are the first bytes in
* an in_addr.
*
* These bad assumptions are wrong in UNICOS which has
* struct in_addr { struct { u_long st_addr:32; } s_da };
* #define s_addr s_da.st_addr
* and u_long is 64 bits.
*
* --jhi */
#include "const-c.inc"
void
char * host
CODE:
{
struct in_addr ip_address;
int ok =
(*host != '\0') &&
ok = 1;
}
ST(0) = sv_newmortal();
if (ok)
}
void
CODE:
{
char * addr_str;
char * ip_address;
croak("Wide character in Socket::inet_ntoa");
else
croak("Bad arg length for %s, length is %d, should be %d",
"Socket::inet_ntoa",
/* We could use inet_ntoa() but that is broken
* in HP-UX + GCC + 64bitint (returns "0.0.0.0"),
* so let's use this sprintf() workaround everywhere.
* This is also more threadsafe than using inet_ntoa(). */
}
void
CODE:
croak("Bad arg length for %s, length is %d, should be at least %d",
"Socket::sockaddr_family", sockaddr_len,
}
void
CODE:
{
#ifdef I_SYS_UN
char * pathname_pv;
# ifdef OS2 /* Name should start with \socket\ and contain backslashes! */
{
int off;
char *s, *e;
croak("Relative UNIX domain socket name '%s' unsupported",
else if (len < 8
off = 7;
else
off = 0; /* Preserve names starting with \socket\ */
e = s + len + 1;
while (++s < e)
if (*s = '/')
*s = '\\';
}
# else /* !( defined OS2 ) */
# endif
if (0) not_here("dummy");
#else
#endif
}
void
CODE:
{
#ifdef I_SYS_UN
struct sockaddr_un addr;
char * e;
# ifndef __linux__
/* On Linux sockaddrlen on sockets returned by accept, recvfrom,
getpeername and getsockname is not equal to sizeof(addr). */
if (sockaddrlen != sizeof(addr)) {
croak("Bad arg length for %s, length is %d, should be %d",
"Socket::unpack_sockaddr_un",
sockaddrlen, sizeof(addr));
}
# endif
croak("Bad address family for %s, got %d, should be %d",
"Socket::unpack_sockaddr_un",
AF_UNIX);
}
/* On Linux, the name of abstract unix domain sockets begins
* with a '\0', so allow this. */
++e;
#else
#endif
}
void
unsigned short port
CODE:
{
struct sockaddr_in sin;
char * ip_address;
croak("Wide character in Socket::pack_sockaddr_in");
else
croak("Bad arg length for %s, length is %d, should be %d",
"Socket::pack_sockaddr_in",
}
void
{
struct sockaddr_in addr;
unsigned short port;
struct in_addr ip_address;
if (sockaddrlen != sizeof(addr)) {
croak("Bad arg length for %s, length is %d, should be %d",
"Socket::unpack_sockaddr_in",
sockaddrlen, sizeof(addr));
}
croak("Bad address family for %s, got %d, should be %d",
"Socket::unpack_sockaddr_in",
AF_INET);
}
}