Lisp_Object Qprocessp;
Lisp_Object Qrun, Qstop, Qsignal;
Lisp_Object Qopen, Qclosed, Qconnect, Qfailed, Qlisten;
-Lisp_Object Qlocal, Qdatagram;
+Lisp_Object Qlocal, Qipv4, Qdatagram;
+#ifdef AF_INET6
+Lisp_Object Qipv6;
+#endif
Lisp_Object QCname, QCbuffer, QChost, QCservice, QCtype;
Lisp_Object QClocal, QCremote, QCcoding;
Lisp_Object QCserver, QCnowait, QCnoquery, QCstop;
DEFUN ("format-network-address", Fformat_network_address, Sformat_network_address,
1, 2, 0,
doc: /* Convert network ADDRESS from internal format to a string.
+A 4 or 5 element vector represents an IPv4 address (with port number).
+An 8 or 9 element vector represents an IPv6 address (with port number).
If optional second argument OMIT-PORT is non-nil, don't include a port
-number in the string; in this case, interpret a 4 element vector as an
-IP address. Returns nil if format of ADDRESS is invalid. */)
+number in the string, even when present in ADDRESS.
+Returns nil if format of ADDRESS is invalid. */)
(address, omit_port)
Lisp_Object address, omit_port;
{
if (STRINGP (address)) /* AF_LOCAL */
return address;
- if (VECTORP (address)) /* AF_INET */
+ if (VECTORP (address)) /* AF_INET or AF_INET6 */
{
register struct Lisp_Vector *p = XVECTOR (address);
Lisp_Object args[6];
int nargs, i;
- if (!NILP (omit_port) && (p->size == 4 || p->size == 5))
+ if (p->size == 4 || (p->size == 5 && !NILP (omit_port)))
{
args[0] = build_string ("%d.%d.%d.%d");
nargs = 4;
args[0] = build_string ("%d.%d.%d.%d:%d");
nargs = 5;
}
+ else if (p->size == 8 || (p->size == 9 && !NILP (omit_port)))
+ {
+ args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x");
+ nargs = 8;
+ }
+ else if (p->size == 9)
+ {
+ args[0] = build_string ("[%x:%x:%x:%x:%x:%x:%x:%x]:%d");
+ nargs = 9;
+ }
else
return Qnil;
cp = (unsigned char *)&sin->sin_addr;
break;
}
+#ifdef AF_INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
+ uint16_t *ip6 = (uint16_t *)&sin6->sin6_addr;
+ len = sizeof (sin6->sin6_addr)/2 + 1;
+ address = Fmake_vector (make_number (len), Qnil);
+ p = XVECTOR (address);
+ p->contents[--len] = make_number (ntohs (sin6->sin6_port));
+ for (i = 0; i < len; i++)
+ p->contents[i] = make_number (ntohs (ip6[i]));
+ return address;
+ }
+#endif
#ifdef HAVE_LOCAL_SOCKETS
case AF_LOCAL:
{
*familyp = AF_INET;
return sizeof (struct sockaddr_in);
}
+#ifdef AF_INET6
+ else if (p->size == 9)
+ {
+ *familyp = AF_INET6;
+ return sizeof (struct sockaddr_in6);
+ }
+#endif
}
#ifdef HAVE_LOCAL_SOCKETS
else if (STRINGP (address))
sin->sin_port = htons (i);
cp = (unsigned char *)&sin->sin_addr;
}
+#ifdef AF_INET6
+ else if (family == AF_INET6)
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
+ uint16_t *ip6 = (uint16_t *)&sin6->sin6_addr;
+ len = sizeof (sin6->sin6_addr) + 1;
+ i = XINT (p->contents[--len]);
+ sin6->sin6_port = htons (i);
+ for (i = 0; i < len; i++)
+ if (INTEGERP (p->contents[i]))
+ {
+ int j = XFASTINT (p->contents[i]) & 0xffff;
+ ip6[i] = ntohs (j);
+ }
+ return;
+ }
+#endif
}
else if (STRINGP (address))
{
stream type connection, `datagram' creates a datagram type connection.
:family FAMILY -- FAMILY is the address (and protocol) family for the
-service specified by HOST and SERVICE. The default address family is
-Inet (or IPv4) for the host and port number specified by HOST and
-SERVICE. Other address families supported are:
+service specified by HOST and SERVICE. The default (nil) is to use
+whatever address family (IPv4 or IPv6) that is defined for the host
+and port number specified by HOST and SERVICE. Other address families
+supported are:
local -- for a local (i.e. UNIX) address specified by SERVICE.
+ ipv4 -- use IPv4 address family only.
+ ipv6 -- use IPv6 address family only.
:local ADDRESS -- ADDRESS is the local address used for the connection.
This parameter is ignored when opening a client process. When specified
struct Lisp_Process *p;
#ifdef HAVE_GETADDRINFO
struct addrinfo ai, *res, *lres;
- struct addrinfo hints;
- char *portstring, portbuf[128];
+ struct addrinfo hints;
+ char *portstring, portbuf[128];
#else /* HAVE_GETADDRINFO */
struct _emacs_addrinfo
{
/* :family FAMILY -- nil (for Inet), local, or integer. */
tem = Fplist_get (contact, QCfamily);
- if (INTEGERP (tem))
- family = XINT (tem);
- else
+ if (NILP (tem))
{
- if (NILP (tem))
- family = AF_INET;
-#ifdef HAVE_LOCAL_SOCKETS
- else if (EQ (tem, Qlocal))
- family = AF_LOCAL;
+#ifdef HAVE_GETADDRINFO
+ family = AF_UNSPEC;
+#else
+ family = AF_INET;
#endif
}
- if (family < 0)
+#ifdef HAVE_LOCAL_SOCKETS
+ else if (EQ (tem, Qlocal))
+ family = AF_LOCAL;
+#endif
+#ifdef AF_INET6
+ else if (EQ (tem, Qipv6))
+ family = AF_INET6;
+#endif
+ else if (EQ (tem, Qipv4))
+ family = AF_INET;
+ else if (INTEGERP (tem))
+ family = XINT (tem);
+ else
error ("Unknown address family");
+
ai.ai_family = family;
/* :service SERVICE -- string, integer (port number), or t (random port). */
QUIT;
memset (&hints, 0, sizeof (hints));
hints.ai_flags = 0;
- hints.ai_family = NILP (Fplist_member (contact, QCfamily)) ? AF_UNSPEC : family;
+ hints.ai_family = family;
hints.ai_socktype = socktype;
hints.ai_protocol = 0;
ret = getaddrinfo (SDATA (host), portstring, &hints, &res);
#endif
#ifdef IFF_DYNAMIC
{ IFF_DYNAMIC, "dynamic" },
+#endif
+#ifdef IFF_OACTIV
+ { IFF_OACTIV, "oactiv" }, /* OpenBSD: transmission in progress */
+#endif
+#ifdef IFF_SIMPLEX
+ { IFF_SIMPLEX, "simplex" }, /* OpenBSD: can't hear own transmissions */
+#endif
+#ifdef IFF_LINK0
+ { IFF_LINK0, "link0" }, /* OpenBSD: per link layer defined bit */
+#endif
+#ifdef IFF_LINK1
+ { IFF_LINK1, "link1" }, /* OpenBSD: per link layer defined bit */
+#endif
+#ifdef IFF_LINK2
+ { IFF_LINK2, "link2" }, /* OpenBSD: per link layer defined bit */
#endif
{ 0, 0 }
};
union u_sockaddr {
struct sockaddr sa;
struct sockaddr_in in;
+#ifdef AF_INET6
+ struct sockaddr_in6 in6;
+#endif
#ifdef HAVE_LOCAL_SOCKETS
struct sockaddr_un un;
#endif
}
break;
+#ifdef AF_INET6
+ case AF_INET6:
+ {
+ Lisp_Object args[9];
+ uint16_t *ip6 = (uint16_t *)&saddr.in6.sin6_addr;
+ int i;
+ args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x");
+ for (i = 0; i < 8; i++)
+ args[i+1] = make_number (ntohs(ip6[i]));
+ host = Fformat (9, args);
+ service = make_number (ntohs (saddr.in.sin_port));
+
+ args[0] = build_string (" <[%s]:%d>");
+ args[1] = host;
+ args[2] = service;
+ caller = Fformat (3, args);
+ }
+ break;
+#endif
+
#ifdef HAVE_LOCAL_SOCKETS
case AF_LOCAL:
#endif
#endif
#ifdef HAVE_LOCAL_SOCKETS
ADD_SUBFEATURE (QCfamily, Qlocal);
+#endif
+ ADD_SUBFEATURE (QCfamily, Qipv4);
+#ifdef AF_INET6
+ ADD_SUBFEATURE (QCfamily, Qipv6);
#endif
#ifdef HAVE_GETSOCKNAME
ADD_SUBFEATURE (QCservice, Qt);
staticpro (&Qlisten);
Qlocal = intern ("local");
staticpro (&Qlocal);
+ Qipv4 = intern ("ipv4");
+ staticpro (&Qipv4);
+#ifdef AF_INET6
+ Qipv6 = intern ("ipv6");
+ staticpro (&Qipv6);
+#endif
Qdatagram = intern ("datagram");
staticpro (&Qdatagram);