address to the four-dotted numeric format). Will croak if the
structure does not have AF_INET in the right place.
+=item pack_sockaddr_in6 PORT, IP6_ADDRESS, [ SCOPE_ID, [ FLOWINFO ] ]
+
+Takes two to four arguments, a port number, an opaque string (as returned by
+inet_pton()), optionally a scope ID number, and optionally a flow label
+number. Returns the sockaddr_in6 structure with those arguments packed in
+with AF_INET6 filled in. IPv6 equivalent of pack_sockaddr_in().
+
+=item unpack_sockaddr_in6 SOCKADDR_IN6
+
+Takes a sockaddr_in6 structure (as returned by pack_sockaddr_in6()) and
+returns an array of four elements: the port number, an opaque string
+representing the IPv6 address, the scope ID, and the flow label. (You can
+use inet_ntop() to convert the address to the usual string format). Will
+croak if the structure does not have AF_INET6 in the right place.
+
=item sockaddr_un PATHNAME
=item sockaddr_un SOCKADDR_UN
sockaddr_family
pack_sockaddr_in unpack_sockaddr_in
pack_sockaddr_un unpack_sockaddr_un
+ pack_sockaddr_in6 unpack_sockaddr_in6
sockaddr_in sockaddr_un
INADDR_ANY INADDR_BROADCAST INADDR_LOOPBACK INADDR_NONE
AF_802
}
void
+pack_sockaddr_in6(port, sin6_addr, scope_id=0, flowinfo=0)
+ unsigned short port
+ SV * sin6_addr
+ unsigned long scope_id
+ unsigned long flowinfo
+ CODE:
+ {
+#ifdef AF_INET6
+ struct sockaddr_in6 sin6;
+ char * addrbytes;
+ STRLEN addrlen;
+ if (DO_UTF8(sin6_addr) && !sv_utf8_downgrade(sin6_addr, 1))
+ croak("Wide character in %s", "Socket::pack_sockaddr_in6");
+ addrbytes = SvPVbyte(sin6_addr, addrlen);
+ if(addrlen != sizeof(sin6.sin6_addr))
+ croak("Bad arg length %s, length is %d, should be %d",
+ "Socket::pack_sockaddr_in6", addrlen, sizeof(sin6.sin6_addr));
+ Zero(&sin6, sizeof(sin6), char);
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_port = htons(port);
+ sin6.sin6_flowinfo = htonl(flowinfo);
+ Copy(addrbytes, &sin6.sin6_addr, sizeof(sin6.sin6_addr), char);
+ sin6.sin6_scope_id = scope_id;
+ ST(0) = newSVpvn_flags((char *)&sin6, sizeof(sin6), SVs_TEMP);
+#else
+ ST(0) = (SV*)not_here("pack_sockaddr_in6");
+#endif
+ }
+
+void
+unpack_sockaddr_in6(sin6_sv)
+ SV * sin6_sv
+ PPCODE:
+ {
+#ifdef AF_INET6
+ STRLEN addrlen;
+ struct sockaddr_in6 sin6;
+ char * addrbytes = SvPVbyte(sin6_sv, addrlen);
+ if (addrlen != sizeof(sin6))
+ croak("Bad arg length for %s, length is %d, should be %d",
+ "Socket::unpack_sockaddr_in6",
+ addrlen, sizeof(sin6));
+ Copy(addrbytes, &sin6, sizeof(sin6), char);
+ if(sin6.sin6_family != AF_INET6)
+ croak("Bad address family for %s, got %d, should be %d",
+ "Socket::unpack_sockaddr_in6",
+ sin6.sin6_family, AF_INET6);
+ EXTEND(SP, 4);
+ mPUSHi(ntohs(sin6.sin6_port));
+ mPUSHp((char *)&sin6.sin6_addr, sizeof(sin6.sin6_addr));
+ mPUSHi(sin6.sin6_scope_id);
+ mPUSHi(ntohl(sin6.sin6_flowinfo));
+#else
+ ST(0) = (SV*)not_here("pack_sockaddr_in6");
+#endif
+ }
+
+void
inet_ntop(af, ip_address_sv)
int af
SV * ip_address_sv
use Socket qw(:all);
-print "1..21\n";
+print "1..26\n";
$has_echo = $^O ne 'MSWin32';
$alarmed = 0;
# no IPv6
print "ok $_ - skipped on this platform\n" for 19 .. 21;
}
+
+if(defined eval { AF_INET6() } ) {
+ my $sin6 = pack_sockaddr_in6(0x1234, "0123456789abcdef", 567, 89);
+
+ print "not " unless sockaddr_family($sin6) == AF_INET6;
+ print "ok 22\n";
+
+ print "not " unless (unpack_sockaddr_in6($sin6))[0] == 0x1234;
+ print "ok 23\n";
+
+ print "not " unless (unpack_sockaddr_in6($sin6))[1] == "0123456789abcdef";
+ print "ok 24\n";
+
+ print "not " unless (unpack_sockaddr_in6($sin6))[2] == 567;
+ print "ok 25\n";
+
+ print "not " unless (unpack_sockaddr_in6($sin6))[3] == 89;
+ print "ok 26\n";
+}
+else {
+ print "ok $_ - skipped - no AF_INET6\n" for 22 .. 26;
+}