AF_LAST AF_LAT AF_LINK AF_MAX AF_NBS AF_NIT AF_NS
AF_OSI AF_OSINET AF_PUP AF_ROUTE AF_SNA
AF_UNIX AF_UNSPEC AF_USER AF_WAN AF_X25
+ AI_CANONNAME AI_NUMERICHOST AI_NUMERICSERV AI_PASSIVE
+ EAI_ADDRFAMILY EAI_AGAIN EAI_BADFLAGS EAI_FAIL EAI_FAMILY
+ EAI_NODATA EAI_NONAME EAI_SERVICE EAI_SOCKTYPE
IOV_MAX IP_OPTIONS IP_HDRINCL IP_TOS IP_TTL IP_RECVOPTS
IP_RECVRETOPTS IP_RETOPTS
MSG_BCAST MSG_BTAG MSG_CTLFLAGS MSG_CTLIGNORE MSG_DONTWAIT
MSG_EOF MSG_EOR MSG_ERRQUEUE MSG_ETAG MSG_FIN
MSG_MAXIOVLEN MSG_MCAST MSG_NOSIGNAL MSG_RST MSG_SYN
MSG_TRUNC MSG_URG MSG_WAITALL MSG_WIRE
+ NI_DGRAM NI_NAMEREQD NI_NUMERICHOST NI_NUMERICSERV
PF_802 PF_AAL PF_APPLETALK PF_CCITT PF_CHAOS PF_CTF
PF_DATAKIT PF_DECnet PF_DLI PF_ECMA PF_GOSIP PF_HYLINK
PF_IMPLINK PF_INET PF_INET6 PF_ISO PF_KEY
#include "const-c.inc"
+#ifdef HAS_GETADDRINFO
+static SV *err_to_SV(pTHX_ int err)
+{
+ SV *ret = sv_newmortal();
+ SvUPGRADE(ret, SVt_PVNV);
+
+ if(err) {
+ const char *error = gai_strerror(err);
+ sv_setpv(ret, error);
+ }
+ else {
+ sv_setpv(ret, "");
+ }
+
+ SvIV_set(ret, err); SvIOK_on(ret);
+
+ return ret;
+}
+
+static void xs_getaddrinfo(pTHX_ CV *cv)
+{
+ dVAR;
+ dXSARGS;
+
+ SV *host;
+ SV *service;
+ SV *hints;
+
+ char *hostname = NULL;
+ char *servicename = NULL;
+ STRLEN len;
+ struct addrinfo hints_s = {};
+ struct addrinfo *res;
+ struct addrinfo *res_iter;
+ int err;
+ int n_res;
+
+ if(items > 3)
+ croak_xs_usage(cv, "host, service, hints");
+
+ SP -= items;
+
+ if(items < 1)
+ host = &PL_sv_undef;
+ else
+ host = ST(0);
+
+ if(items < 2)
+ service = &PL_sv_undef;
+ else
+ service = ST(1);
+
+ if(items < 3)
+ hints = NULL;
+ else
+ hints = ST(2);
+
+ SvGETMAGIC(host);
+ if(SvOK(host)) {
+ hostname = SvPV_nomg(host, len);
+ if (!len)
+ hostname = NULL;
+ }
+
+ SvGETMAGIC(service);
+ if(SvOK(service)) {
+ servicename = SvPV_nomg(service, len);
+ if (!len)
+ servicename = NULL;
+ }
+
+ if(hints && SvOK(hints)) {
+ HV *hintshash;
+ SV **valp;
+
+ if(!SvROK(hints) || SvTYPE(SvRV(hints)) != SVt_PVHV)
+ croak("hints is not a HASH reference");
+
+ hintshash = (HV*)SvRV(hints);
+
+ if((valp = hv_fetch(hintshash, "flags", 5, 0)) != NULL)
+ hints_s.ai_flags = SvIV(*valp);
+ if((valp = hv_fetch(hintshash, "family", 6, 0)) != NULL)
+ hints_s.ai_family = SvIV(*valp);
+ if((valp = hv_fetch(hintshash, "socktype", 8, 0)) != NULL)
+ hints_s.ai_socktype = SvIV(*valp);
+ if((valp = hv_fetch(hintshash, "protocol", 8, 0)) != NULL)
+ hints_s.ai_protocol = SvIV(*valp);
+ }
+
+ err = getaddrinfo(hostname, servicename, &hints_s, &res);
+
+ XPUSHs(err_to_SV(aTHX_ err));
+
+ if(err)
+ XSRETURN(1);
+
+ n_res = 0;
+ for(res_iter = res; res_iter; res_iter = res_iter->ai_next) {
+ HV *res_hv = newHV();
+
+ (void)hv_stores(res_hv, "family", newSViv(res_iter->ai_family));
+ (void)hv_stores(res_hv, "socktype", newSViv(res_iter->ai_socktype));
+ (void)hv_stores(res_hv, "protocol", newSViv(res_iter->ai_protocol));
+
+ (void)hv_stores(res_hv, "addr", newSVpvn((char*)res_iter->ai_addr, res_iter->ai_addrlen));
+
+ if(res_iter->ai_canonname)
+ (void)hv_stores(res_hv, "canonname", newSVpv(res_iter->ai_canonname, 0));
+ else
+ (void)hv_stores(res_hv, "canonname", newSV(0));
+
+ XPUSHs(sv_2mortal(newRV_noinc((SV*)res_hv)));
+ n_res++;
+ }
+
+ freeaddrinfo(res);
+
+ XSRETURN(1 + n_res);
+}
+#endif
+
+#ifdef HAS_GETNAMEINFO
+static void xs_getnameinfo(pTHX_ CV *cv)
+{
+ dVAR;
+ dXSARGS;
+
+ SV *addr;
+ int flags;
+
+ char host[1024];
+ char serv[256];
+ char *sa; /* we'll cast to struct sockaddr * when necessary */
+ STRLEN addr_len;
+ int err;
+
+ if(items < 1 || items > 2)
+ croak_xs_usage(cv, "addr, flags=0");
+
+ SP -= items;
+
+ addr = ST(0);
+
+ if(items < 2)
+ flags = 0;
+ else
+ flags = SvIV(ST(1));
+
+ if(!SvPOK(addr))
+ croak("addr is not a string");
+
+ addr_len = SvCUR(addr);
+
+ /* We need to ensure the sockaddr is aligned, because a random SvPV might
+ * not be due to SvOOK */
+ Newx(sa, addr_len, char);
+ Copy(SvPV_nolen(addr), sa, addr_len, char);
+#ifdef HAS_SOCKADDR_SA_LEN
+ ((struct sockaddr *)sa)->sa_len = addr_len;
+#endif
+
+ err = getnameinfo((struct sockaddr *)sa, addr_len,
+ host, sizeof(host),
+ serv, sizeof(serv),
+ flags);
+
+ Safefree(sa);
+
+ XPUSHs(err_to_SV(aTHX_ err));
+
+ if(err)
+ XSRETURN(1);
+
+ XPUSHs(sv_2mortal(newSVpv(host, 0)));
+ XPUSHs(sv_2mortal(newSVpv(serv, 0)));
+
+ XSRETURN(3);
+}
+#endif
+
MODULE = Socket PACKAGE = Socket
INCLUDE: const-xs.inc
+BOOT:
+#ifdef HAS_GETADDRINFO
+ newXS("Socket::getaddrinfo", xs_getaddrinfo, __FILE__);
+#endif
+#ifdef HAS_GETNAMEINFO
+ newXS("Socket::getnameinfo", xs_getnameinfo, __FILE__);
+#endif
+
void
inet_aton(host)
char * host