X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=ext%2FSocket%2FSocket.xs;h=48f30d902d72b186470f9902398b79d9b3831b98;hb=b56fc9ec2d9f24dd7719ac8ba4c094aaa486bd0e;hp=336e6c451ac82ac8582d1dc4cb7f28f4c31cc893;hpb=202975e60ee076fd8796877b28774137051a97c4;p=p5sagit%2Fp5-mst-13.2.git diff --git a/ext/Socket/Socket.xs b/ext/Socket/Socket.xs index 336e6c4..48f30d9 100644 --- a/ext/Socket/Socket.xs +++ b/ext/Socket/Socket.xs @@ -1,12 +1,20 @@ +#define PERL_NO_GET_CONTEXT #include "EXTERN.h" #include "perl.h" #include "XSUB.h" +#include + #ifndef VMS # ifdef I_SYS_TYPES # include # endif -# include +# if !defined(ultrix) /* Avoid double definition. */ +# include +# endif +# if defined(USE_SOCKS) && defined(I_SOCKS) +# include +# endif # ifdef MPE # define PF_INET AF_INET # define PF_UNIX AF_UNIX @@ -15,10 +23,21 @@ # ifdef I_SYS_UN # include # endif -# ifdef I_NETINET_IN +/* XXX Configure test for +# endif +# if defined(__sgi) && !defined(AF_LINK) && defined(PF_LINK) && PF_LINK == AF_LNK +# undef PF_LINK +# endif +# if defined(I_NETINET_IN) || defined(__ultrix__) # include # endif -# include +# ifdef I_NETDB +# if !defined(ultrix) /* Avoid double definition. */ +# include +# endif +# endif # ifdef I_ARPA_INET # include # endif @@ -29,6 +48,11 @@ # include "sockadapt.h" #endif +#ifdef NETWARE +NETDB_DEFINE_CONTEXT +NETINET_DEFINE_CONTEXT +#endif + #ifdef I_SYSUIO # include #endif @@ -53,7 +77,7 @@ #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. @@ -63,6 +87,7 @@ static int my_inet_aton(register const char *cp, struct in_addr *addr) { + dTHX; register U32 val; register int base; register char c; @@ -71,7 +96,7 @@ my_inet_aton(register const char *cp, struct in_addr *addr) unsigned int parts[4]; register unsigned int *pp = parts; - if (!cp) + if (!cp || !*cp) return 0; for (;;) { /* @@ -93,7 +118,7 @@ my_inet_aton(register const char *cp, struct in_addr *addr) continue; } if (base == 16 && (s=strchr(PL_hexdigit,c))) { - val = (val << 4) + + val = (val << 4) + ((s - PL_hexdigit) & 15); cp++; continue; @@ -163,722 +188,41 @@ not_here(char *s) return -1; } -static double -constant(char *name, int arg) -{ - errno = 0; - switch (*name) { - case 'A': - if (strEQ(name, "AF_802")) -#ifdef AF_802 - return AF_802; -#else - goto not_there; -#endif - if (strEQ(name, "AF_APPLETALK")) -#ifdef AF_APPLETALK - return AF_APPLETALK; -#else - goto not_there; -#endif - if (strEQ(name, "AF_CCITT")) -#ifdef AF_CCITT - return AF_CCITT; -#else - goto not_there; -#endif - if (strEQ(name, "AF_CHAOS")) -#ifdef AF_CHAOS - return AF_CHAOS; -#else - goto not_there; -#endif - if (strEQ(name, "AF_DATAKIT")) -#ifdef AF_DATAKIT - return AF_DATAKIT; -#else - goto not_there; -#endif - if (strEQ(name, "AF_DECnet")) -#ifdef AF_DECnet - return AF_DECnet; -#else - goto not_there; -#endif - if (strEQ(name, "AF_DLI")) -#ifdef AF_DLI - return AF_DLI; -#else - goto not_there; -#endif - if (strEQ(name, "AF_ECMA")) -#ifdef AF_ECMA - return AF_ECMA; -#else - goto not_there; -#endif - if (strEQ(name, "AF_GOSIP")) -#ifdef AF_GOSIP - return AF_GOSIP; -#else - goto not_there; -#endif - if (strEQ(name, "AF_HYLINK")) -#ifdef AF_HYLINK - return AF_HYLINK; -#else - goto not_there; -#endif - if (strEQ(name, "AF_IMPLINK")) -#ifdef AF_IMPLINK - return AF_IMPLINK; -#else - goto not_there; -#endif - if (strEQ(name, "AF_INET")) -#ifdef AF_INET - return AF_INET; -#else - goto not_there; -#endif - if (strEQ(name, "AF_LAT")) -#ifdef AF_LAT - return AF_LAT; -#else - goto not_there; -#endif - if (strEQ(name, "AF_MAX")) -#ifdef AF_MAX - return AF_MAX; -#else - goto not_there; -#endif - if (strEQ(name, "AF_NBS")) -#ifdef AF_NBS - return AF_NBS; -#else - goto not_there; -#endif - if (strEQ(name, "AF_NIT")) -#ifdef AF_NIT - return AF_NIT; -#else - goto not_there; -#endif - if (strEQ(name, "AF_NS")) -#ifdef AF_NS - return AF_NS; -#else - goto not_there; -#endif - if (strEQ(name, "AF_OSI")) -#ifdef AF_OSI - return AF_OSI; -#else - goto not_there; -#endif - if (strEQ(name, "AF_OSINET")) -#ifdef AF_OSINET - return AF_OSINET; -#else - goto not_there; -#endif - if (strEQ(name, "AF_PUP")) -#ifdef AF_PUP - return AF_PUP; -#else - goto not_there; -#endif - if (strEQ(name, "AF_SNA")) -#ifdef AF_SNA - return AF_SNA; -#else - goto not_there; -#endif - if (strEQ(name, "AF_UNIX")) -#ifdef AF_UNIX - return AF_UNIX; -#else - goto not_there; -#endif - if (strEQ(name, "AF_UNSPEC")) -#ifdef AF_UNSPEC - return AF_UNSPEC; -#else - goto not_there; -#endif - if (strEQ(name, "AF_X25")) -#ifdef AF_X25 - return AF_X25; -#else - goto not_there; -#endif - break; - case 'B': - break; - case 'C': - break; - case 'D': - break; - case 'E': - break; - case 'F': - break; - case 'G': - break; - case 'H': - break; - case 'I': - if (strEQ(name, "IOV_MAX")) -#ifdef IOV_MAX - return IOV_MAX; -#else - goto not_there; -#endif - if (strEQ(name, "IPPROTO_TCP")) -#ifdef IPPROTO_TCP - return IPPROTO_TCP; -#else - goto not_there; -#endif - break; - case 'J': - break; - case 'K': - break; - case 'L': - break; - case 'M': - if (strEQ(name, "MSG_BCAST")) -#ifdef MSG_BCAST - return MSG_BCAST; -#else - goto not_there; -#endif - if (strEQ(name, "MSG_CTLFLAGS")) -#ifdef MSG_CTLFLAGS - return MSG_CTLFLAGS; -#else - goto not_there; -#endif - if (strEQ(name, "MSG_CTLIGNORE")) -#ifdef MSG_CTLIGNORE - return MSG_CTLIGNORE; -#else - goto not_there; -#endif - if (strEQ(name, "MSG_CTRUNC")) -#if defined(MSG_TRUNC) || defined(HAS_MSG_CTRUNC) /* might be an enum */ - return MSG_CTRUNC; -#else - goto not_there; -#endif - if (strEQ(name, "MSG_DONTROUTE")) -#if defined(MSG_DONTROUTE) || defined(HAS_MSG_DONTROUTE) /* might be an enum */ - return MSG_DONTROUTE; -#else - goto not_there; -#endif - if (strEQ(name, "MSG_DONTWAIT")) -#ifdef MSG_DONTWAIT - return MSG_DONTWAIT; -#else - goto not_there; -#endif - if (strEQ(name, "MSG_EOF")) -#ifdef MSG_EOF - return MSG_EOF; -#else - goto not_there; -#endif - if (strEQ(name, "MSG_EOR")) -#ifdef MSG_EOR - return MSG_EOR; -#else - goto not_there; -#endif - if (strEQ(name, "MSG_ERRQUEUE")) -#ifdef MSG_ERRQUEUE - return MSG_ERRQUEUE; -#else - goto not_there; -#endif - if (strEQ(name, "MSG_FIN")) -#ifdef MSG_FIN - return MSG_FIN; -#else - goto not_there; -#endif - if (strEQ(name, "MSG_MAXIOVLEN")) -#ifdef MSG_MAXIOVLEN - return MSG_MAXIOVLEN; -#else - goto not_there; -#endif - if (strEQ(name, "MSG_MCAST")) -#ifdef MSG_MCAST - return MSG_MCAST; -#else - goto not_there; -#endif - if (strEQ(name, "MSG_NOSIGNAL")) -#ifdef MSG_NOSIGNAL - return MSG_NOSIGNAL; -#else - goto not_there; -#endif - if (strEQ(name, "MSG_OOB")) -#if defined(MSG_OOB) || defined(HAS_MSG_OOB) /* might be an enum */ - return MSG_OOB; -#else - goto not_there; -#endif - if (strEQ(name, "MSG_PEEK")) -#if defined(MSG_PEEK) || defined(HAS_MSG_PEEK) /* might be an enum */ - return MSG_PEEK; -#else - goto not_there; -#endif - if (strEQ(name, "MSG_PROXY")) -#if defined(MSG_PROXY) || defined(HAS_MSG_PROXY) /* might be an enum */ - return MSG_PROXY; -#else - goto not_there; -#endif - if (strEQ(name, "MSG_RST")) -#ifdef MSG_RST - return MSG_RST; -#else - goto not_there; -#endif - if (strEQ(name, "MSG_SYN")) -#ifdef MSG_SYN - return MSG_SYN; -#else - goto not_there; -#endif - if (strEQ(name, "MSG_TRUNC")) -#ifdef MSG_TRUNC - return MSG_TRUNC; -#else - goto not_there; -#endif - if (strEQ(name, "MSG_WAITALL")) -#ifdef MSG_WAITALL - return MSG_WAITALL; -#else - goto not_there; -#endif - break; - case 'N': - break; - case 'O': - break; - case 'P': - if (strEQ(name, "PF_802")) -#ifdef PF_802 - return PF_802; -#else - goto not_there; -#endif - if (strEQ(name, "PF_APPLETALK")) -#ifdef PF_APPLETALK - return PF_APPLETALK; -#else - goto not_there; -#endif - if (strEQ(name, "PF_CCITT")) -#ifdef PF_CCITT - return PF_CCITT; -#else - goto not_there; -#endif - if (strEQ(name, "PF_CHAOS")) -#ifdef PF_CHAOS - return PF_CHAOS; -#else - goto not_there; -#endif - if (strEQ(name, "PF_DATAKIT")) -#ifdef PF_DATAKIT - return PF_DATAKIT; -#else - goto not_there; -#endif - if (strEQ(name, "PF_DECnet")) -#ifdef PF_DECnet - return PF_DECnet; -#else - goto not_there; -#endif - if (strEQ(name, "PF_DLI")) -#ifdef PF_DLI - return PF_DLI; -#else - goto not_there; -#endif - if (strEQ(name, "PF_ECMA")) -#ifdef PF_ECMA - return PF_ECMA; -#else - goto not_there; -#endif - if (strEQ(name, "PF_GOSIP")) -#ifdef PF_GOSIP - return PF_GOSIP; -#else - goto not_there; -#endif - if (strEQ(name, "PF_HYLINK")) -#ifdef PF_HYLINK - return PF_HYLINK; -#else - goto not_there; -#endif - if (strEQ(name, "PF_IMPLINK")) -#ifdef PF_IMPLINK - return PF_IMPLINK; -#else - goto not_there; -#endif - if (strEQ(name, "PF_INET")) -#ifdef PF_INET - return PF_INET; -#else - goto not_there; -#endif - if (strEQ(name, "PF_LAT")) -#ifdef PF_LAT - return PF_LAT; -#else - goto not_there; -#endif - if (strEQ(name, "PF_MAX")) -#ifdef PF_MAX - return PF_MAX; -#else - goto not_there; -#endif - if (strEQ(name, "PF_NBS")) -#ifdef PF_NBS - return PF_NBS; -#else - goto not_there; -#endif - if (strEQ(name, "PF_NIT")) -#ifdef PF_NIT - return PF_NIT; -#else - goto not_there; -#endif - if (strEQ(name, "PF_NS")) -#ifdef PF_NS - return PF_NS; -#else - goto not_there; -#endif - if (strEQ(name, "PF_OSI")) -#ifdef PF_OSI - return PF_OSI; -#else - goto not_there; -#endif - if (strEQ(name, "PF_OSINET")) -#ifdef PF_OSINET - return PF_OSINET; -#else - goto not_there; -#endif - if (strEQ(name, "PF_PUP")) -#ifdef PF_PUP - return PF_PUP; -#else - goto not_there; -#endif - if (strEQ(name, "PF_SNA")) -#ifdef PF_SNA - return PF_SNA; -#else - goto not_there; -#endif - if (strEQ(name, "PF_UNIX")) -#ifdef PF_UNIX - return PF_UNIX; -#else - goto not_there; -#endif - if (strEQ(name, "PF_UNSPEC")) -#ifdef PF_UNSPEC - return PF_UNSPEC; -#else - goto not_there; -#endif - if (strEQ(name, "PF_X25")) -#ifdef PF_X25 - return PF_X25; -#else - goto not_there; -#endif - break; - case 'Q': - break; - case 'R': - break; - case 'S': - if (strEQ(name, "SCM_CONNECT")) -#ifdef SCM_CONNECT - return SCM_CONNECT; -#else - goto not_there; -#endif - if (strEQ(name, "SCM_CREDENTIALS")) -#ifdef SCM_CREDENTIALS - return SCM_CREDENTIALS; -#else - goto not_there; -#endif - if (strEQ(name, "SCM_CREDS")) -#ifdef SCM_CREDS - return SCM_CREDS; -#else - goto not_there; -#endif - if (strEQ(name, "SCM_RIGHTS")) -#if defined(SCM_RIGHTS) || defined(HAS_SCM_RIGHTS) /* might be an enum */ - return SCM_RIGHTS; -#else - goto not_there; -#endif - if (strEQ(name, "SCM_TIMESTAMP")) -#ifdef SCM_TIMESTAMP - return SCM_TIMESTAMP; -#else - goto not_there; -#endif - if (strEQ(name, "SOCK_DGRAM")) -#ifdef SOCK_DGRAM - return SOCK_DGRAM; -#else - goto not_there; -#endif - if (strEQ(name, "SOCK_RAW")) -#ifdef SOCK_RAW - return SOCK_RAW; -#else - goto not_there; -#endif - if (strEQ(name, "SOCK_RDM")) -#ifdef SOCK_RDM - return SOCK_RDM; -#else - goto not_there; -#endif - if (strEQ(name, "SOCK_SEQPACKET")) -#ifdef SOCK_SEQPACKET - return SOCK_SEQPACKET; -#else - goto not_there; -#endif - if (strEQ(name, "SOCK_STREAM")) -#ifdef SOCK_STREAM - return SOCK_STREAM; -#else - goto not_there; -#endif - if (strEQ(name, "SOL_SOCKET")) -#ifdef SOL_SOCKET - return SOL_SOCKET; -#else - goto not_there; -#endif - if (strEQ(name, "SOMAXCONN")) -#ifdef SOMAXCONN - return SOMAXCONN; -#else - goto not_there; -#endif - if (strEQ(name, "SO_ACCEPTCONN")) -#ifdef SO_ACCEPTCONN - return SO_ACCEPTCONN; -#else - goto not_there; -#endif - if (strEQ(name, "SO_BROADCAST")) -#ifdef SO_BROADCAST - return SO_BROADCAST; -#else - goto not_there; -#endif - if (strEQ(name, "SO_DEBUG")) -#ifdef SO_DEBUG - return SO_DEBUG; -#else - goto not_there; -#endif - if (strEQ(name, "SO_DONTLINGER")) -#ifdef SO_DONTLINGER - return SO_DONTLINGER; -#else - goto not_there; -#endif - if (strEQ(name, "SO_DONTROUTE")) -#ifdef SO_DONTROUTE - return SO_DONTROUTE; -#else - goto not_there; -#endif - if (strEQ(name, "SO_ERROR")) -#ifdef SO_ERROR - return SO_ERROR; -#else - goto not_there; -#endif - if (strEQ(name, "SO_KEEPALIVE")) -#ifdef SO_KEEPALIVE - return SO_KEEPALIVE; -#else - goto not_there; -#endif - if (strEQ(name, "SO_LINGER")) -#ifdef SO_LINGER - return SO_LINGER; -#else - goto not_there; -#endif - if (strEQ(name, "SO_OOBINLINE")) -#ifdef SO_OOBINLINE - return SO_OOBINLINE; -#else - goto not_there; -#endif - if (strEQ(name, "SO_RCVBUF")) -#ifdef SO_RCVBUF - return SO_RCVBUF; -#else - goto not_there; -#endif - if (strEQ(name, "SO_RCVLOWAT")) -#ifdef SO_RCVLOWAT - return SO_RCVLOWAT; -#else - goto not_there; -#endif - if (strEQ(name, "SO_RCVTIMEO")) -#ifdef SO_RCVTIMEO - return SO_RCVTIMEO; -#else - goto not_there; -#endif - if (strEQ(name, "SO_REUSEADDR")) -#ifdef SO_REUSEADDR - return SO_REUSEADDR; -#else - goto not_there; -#endif - if (strEQ(name, "SO_REUSEPORT")) -#ifdef SO_REUSEPORT - return SO_REUSEPORT; -#else - goto not_there; -#endif - if (strEQ(name, "SO_SNDBUF")) -#ifdef SO_SNDBUF - return SO_SNDBUF; -#else - goto not_there; -#endif - if (strEQ(name, "SO_SNDLOWAT")) -#ifdef SO_SNDLOWAT - return SO_SNDLOWAT; -#else - goto not_there; -#endif - if (strEQ(name, "SO_SNDTIMEO")) -#ifdef SO_SNDTIMEO - return SO_SNDTIMEO; -#else - goto not_there; -#endif - if (strEQ(name, "SO_TYPE")) -#ifdef SO_TYPE - return SO_TYPE; -#else - goto not_there; -#endif - if (strEQ(name, "SO_USELOOPBACK")) -#ifdef SO_USELOOPBACK - return SO_USELOOPBACK; -#else - goto not_there; -#endif - break; - case 'T': - if (strEQ(name, "TCP_KEEPALIVE")) -#ifdef TCP_KEEPALIVE - return TCP_KEEPALIVE; -#else - goto not_there; -#endif - if (strEQ(name, "TCP_MAXRT")) -#ifdef TCP_MAXRT - return TCP_MAXRT; -#else - goto not_there; -#endif - if (strEQ(name, "TCP_MAXSEG")) -#ifdef TCP_MAXSEG - return TCP_MAXSEG; -#else - goto not_there; -#endif - if (strEQ(name, "TCP_NODELAY")) -#ifdef TCP_NODELAY - return TCP_NODELAY; -#else - goto not_there; -#endif - if (strEQ(name, "TCP_STDURG")) -#ifdef TCP_STDURG - return TCP_STDURG; -#else - goto not_there; -#endif - break; - case 'U': - if (strEQ(name, "UIO_MAXIOV")) -#ifdef UIO_MAXIOV - return UIO_MAXIOV; -#else - goto not_there; -#endif - break; - case 'V': - break; - case 'W': - break; - case 'X': - break; - case 'Y': - break; - case 'Z': - break; - } - errno = EINVAL; - return 0; - -not_there: - errno = ENOENT; - return 0; -} - +#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" MODULE = Socket PACKAGE = Socket -double -constant(name,arg) - char * name - int arg - +INCLUDE: const-xs.inc void inet_aton(host) @@ -887,7 +231,7 @@ inet_aton(host) { struct in_addr ip_address; struct hostent * phe; - int ok = inet_aton(host, &ip_address); + int ok = (*host != '\0') && inet_aton(host, &ip_address); if (!ok && (phe = gethostbyname(host))) { Copy( phe->h_addr, &ip_address, phe->h_length, char ); @@ -895,10 +239,9 @@ inet_aton(host) } ST(0) = sv_newmortal(); - if (ok) { + if (ok) sv_setpvn( ST(0), (char *)&ip_address, sizeof ip_address ); } - } void inet_ntoa(ip_address_sv) @@ -908,31 +251,61 @@ inet_ntoa(ip_address_sv) STRLEN addrlen; struct in_addr addr; char * addr_str; - char * ip_address = SvPV(ip_address_sv,addrlen); - if (addrlen != sizeof(addr)) { - croak("Bad arg length for %s, length is %d, should be %d", - "Socket::inet_ntoa", - addrlen, sizeof(addr)); + char * ip_address; + if (DO_UTF8(ip_address_sv) && !sv_utf8_downgrade(ip_address_sv, 1)) + croak("Wide character in Socket::inet_ntoa"); + ip_address = SvPVbyte(ip_address_sv, addrlen); + if (addrlen == sizeof(addr) || addrlen == 4) + addr.s_addr = + (ip_address[0] & 0xFF) << 24 | + (ip_address[1] & 0xFF) << 16 | + (ip_address[2] & 0xFF) << 8 | + (ip_address[3] & 0xFF); + else + croak("Bad arg length for %s, length is %d, should be %d", + "Socket::inet_ntoa", + addrlen, sizeof(addr)); + /* 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(). */ + Newx(addr_str, 4 * 3 + 3 + 1, char); /* IPv6? */ + sprintf(addr_str, "%d.%d.%d.%d", + ((addr.s_addr >> 24) & 0xFF), + ((addr.s_addr >> 16) & 0xFF), + ((addr.s_addr >> 8) & 0xFF), + ( addr.s_addr & 0xFF)); + ST(0) = sv_2mortal(newSVpvn(addr_str, strlen(addr_str))); + Safefree(addr_str); } - Copy( ip_address, &addr, sizeof addr, char ); - addr_str = inet_ntoa(addr); - - ST(0) = sv_2mortal(newSVpvn(addr_str, strlen(addr_str))); +void +sockaddr_family(sockaddr) + SV * sockaddr + PREINIT: + STRLEN sockaddr_len; + char *sockaddr_pv = SvPVbyte(sockaddr, sockaddr_len); + CODE: + if (sockaddr_len < offsetof(struct sockaddr, sa_data)) { + croak("Bad arg length for %s, length is %d, should be at least %d", + "Socket::sockaddr_family", sockaddr_len, + offsetof(struct sockaddr, sa_data)); } + ST(0) = sv_2mortal(newSViv(((struct sockaddr*)sockaddr_pv)->sa_family)); void pack_sockaddr_un(pathname) - char * pathname + SV * pathname CODE: { #ifdef I_SYS_UN struct sockaddr_un sun_ad; /* fear using sun */ STRLEN len; + char * pathname_pv; Zero( &sun_ad, sizeof sun_ad, char ); sun_ad.sun_family = AF_UNIX; - len = strlen(pathname); + pathname_pv = SvPV(pathname,len); if (len > sizeof(sun_ad.sun_path)) len = sizeof(sun_ad.sun_path); # ifdef OS2 /* Name should start with \socket\ and contain backslashes! */ @@ -940,16 +313,17 @@ pack_sockaddr_un(pathname) int off; char *s, *e; - if (pathname[0] != '/' && pathname[0] != '\\') - croak("Relative UNIX domain socket name '%s' unsupported", pathname); - else if (len < 8 - || pathname[7] != '/' && pathname[7] != '\\' - || !strnicmp(pathname + 1, "socket", 6)) + if (pathname_pv[0] != '/' && pathname_pv[0] != '\\') + croak("Relative UNIX domain socket name '%s' unsupported", + pathname_pv); + else if (len < 8 + || pathname_pv[7] != '/' && pathname_pv[7] != '\\' + || !strnicmp(pathname_pv + 1, "socket", 6)) off = 7; else off = 0; /* Preserve names starting with \socket\ */ Copy( "\\socket", sun_ad.sun_path, off, char); - Copy( pathname, sun_ad.sun_path + off, len, char ); + Copy( pathname_pv, sun_ad.sun_path + off, len, char ); s = sun_ad.sun_path + off - 1; e = s + len + 1; @@ -957,9 +331,10 @@ pack_sockaddr_un(pathname) if (*s = '/') *s = '\\'; } -# else /* !( defined OS2 ) */ - Copy( pathname, sun_ad.sun_path, len, char ); +# else /* !( defined OS2 ) */ + Copy( pathname_pv, sun_ad.sun_path, len, char ); # endif + if (0) not_here("dummy"); ST(0) = sv_2mortal(newSVpvn((char *)&sun_ad, sizeof sun_ad)); #else ST(0) = (SV *) not_here("pack_sockaddr_un"); @@ -975,14 +350,17 @@ unpack_sockaddr_un(sun_sv) #ifdef I_SYS_UN struct sockaddr_un addr; STRLEN sockaddrlen; - char * sun_ad = SvPV(sun_sv,sockaddrlen); + char * sun_ad = SvPVbyte(sun_sv,sockaddrlen); 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 Copy( sun_ad, &addr, sizeof addr, char ); @@ -992,28 +370,45 @@ unpack_sockaddr_un(sun_sv) addr.sun_family, AF_UNIX); } - e = addr.sun_path; - while (*e && e < addr.sun_path + sizeof addr.sun_path) + e = (char*)addr.sun_path; + /* On Linux, the name of abstract unix domain sockets begins + * with a '\0', so allow this. */ + while ((*e || (e == addr.sun_path && e[1] && sockaddrlen > 1)) + && e < (char*)addr.sun_path + sizeof addr.sun_path) ++e; - ST(0) = sv_2mortal(newSVpvn(addr.sun_path, e - addr.sun_path)); + ST(0) = sv_2mortal(newSVpvn(addr.sun_path, e - (char*)addr.sun_path)); #else ST(0) = (SV *) not_here("unpack_sockaddr_un"); #endif } void -pack_sockaddr_in(port,ip_address) +pack_sockaddr_in(port, ip_address_sv) unsigned short port - char * ip_address + SV * ip_address_sv CODE: { struct sockaddr_in sin; - + struct in_addr addr; + STRLEN addrlen; + char * ip_address; + if (DO_UTF8(ip_address_sv) && !sv_utf8_downgrade(ip_address_sv, 1)) + croak("Wide character in Socket::pack_sockaddr_in"); + ip_address = SvPVbyte(ip_address_sv, addrlen); + if (addrlen == sizeof(addr) || addrlen == 4) + addr.s_addr = + (ip_address[0] & 0xFF) << 24 | + (ip_address[1] & 0xFF) << 16 | + (ip_address[2] & 0xFF) << 8 | + (ip_address[3] & 0xFF); + else + croak("Bad arg length for %s, length is %d, should be %d", + "Socket::pack_sockaddr_in", + addrlen, sizeof(addr)); Zero( &sin, sizeof sin, char ); sin.sin_family = AF_INET; sin.sin_port = htons(port); - Copy( ip_address, &sin.sin_addr, sizeof sin.sin_addr, char ); - + sin.sin_addr.s_addr = htonl(addr.s_addr); ST(0) = sv_2mortal(newSVpvn((char *)&sin, sizeof sin)); } @@ -1025,8 +420,8 @@ unpack_sockaddr_in(sin_sv) STRLEN sockaddrlen; struct sockaddr_in addr; unsigned short port; - struct in_addr ip_address; - char * sin = SvPV(sin_sv,sockaddrlen); + struct in_addr ip_address; + char * sin = SvPVbyte(sin_sv,sockaddrlen); if (sockaddrlen != sizeof(addr)) { croak("Bad arg length for %s, length is %d, should be %d", "Socket::unpack_sockaddr_in", @@ -1038,47 +433,11 @@ unpack_sockaddr_in(sin_sv) "Socket::unpack_sockaddr_in", addr.sin_family, AF_INET); - } + } port = ntohs(addr.sin_port); ip_address = addr.sin_addr; EXTEND(SP, 2); PUSHs(sv_2mortal(newSViv((IV) port))); - PUSHs(sv_2mortal(newSVpvn((char *)&ip_address,sizeof ip_address))); - } - -void -INADDR_ANY() - CODE: - { - struct in_addr ip_address; - ip_address.s_addr = htonl(INADDR_ANY); - ST(0) = sv_2mortal(newSVpvn((char *)&ip_address,sizeof ip_address )); - } - -void -INADDR_LOOPBACK() - CODE: - { - struct in_addr ip_address; - ip_address.s_addr = htonl(INADDR_LOOPBACK); - ST(0) = sv_2mortal(newSVpvn((char *)&ip_address,sizeof ip_address)); - } - -void -INADDR_NONE() - CODE: - { - struct in_addr ip_address; - ip_address.s_addr = htonl(INADDR_NONE); - ST(0) = sv_2mortal(newSVpvn((char *)&ip_address,sizeof ip_address)); - } - -void -INADDR_BROADCAST() - CODE: - { - struct in_addr ip_address; - ip_address.s_addr = htonl(INADDR_BROADCAST); - ST(0) = sv_2mortal(newSVpvn((char *)&ip_address,sizeof ip_address)); + PUSHs(sv_2mortal(newSVpvn((char *)&ip_address, sizeof ip_address))); }