Mercurial > emacs
changeset 68008:10f0a09ec82e
Add IPv6 support.
(Qipv4, Qipv6): New vars.
(syms_of_process): Intern and staticpro them.
(Fformat_network_address): Handle 9 or 8 element vector as IPv6 address
with or without port number. Handle 4 element vector as IPv4 address
without port number.
(conv_sockaddr_to_lisp, get_lisp_to_sockaddr_size)
(conv_lisp_to_sockaddr): Handle IPv6 addresses.
(Fmake_network_process): Use :family 'ipv4 and 'ipv6 to explicitly
request that address family only. :family nil or omitted means to
determine address family from the specified :host and :service.
(server_accept_connection): Handle IPv6 addresses.
(init_process): Add (:family ipv4) and (:family ipv6) sub-features.
(ifflag_table): Add missing OpenBSD IFF_ flags.
author | Kim F. Storm <storm@cua.dk> |
---|---|
date | Wed, 04 Jan 2006 00:16:54 +0000 |
parents | 0b578812ab24 |
children | dd865bff7357 |
files | src/process.c |
diffstat | 1 files changed, 135 insertions(+), 21 deletions(-) [+] |
line wrap: on
line diff
--- a/src/process.c Tue Jan 03 23:35:20 2006 +0000 +++ b/src/process.c Wed Jan 04 00:16:54 2006 +0000 @@ -140,7 +140,10 @@ 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; @@ -1195,9 +1198,11 @@ 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; { @@ -1207,13 +1212,13 @@ 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; @@ -1223,6 +1228,16 @@ 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; @@ -2212,6 +2227,20 @@ 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: { @@ -2256,6 +2285,13 @@ *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)) @@ -2302,6 +2338,23 @@ 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)) { @@ -2595,10 +2648,13 @@ 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 @@ -2715,8 +2771,8 @@ 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 { @@ -2855,19 +2911,29 @@ /* :family FAMILY -- nil (for Inet), local, or integer. */ tem = Fplist_get (contact, QCfamily); - if (INTEGERP (tem)) + if (NILP (tem)) + { +#ifdef HAVE_GETADDRINFO + family = AF_UNSPEC; +#else + family = AF_INET; +#endif + } +#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 - { - if (NILP (tem)) - family = AF_INET; -#ifdef HAVE_LOCAL_SOCKETS - else if (EQ (tem, Qlocal)) - family = AF_LOCAL; -#endif - } - if (family < 0) error ("Unknown address family"); + ai.ai_family = family; /* :service SERVICE -- string, integer (port number), or t (random port). */ @@ -2933,7 +2999,7 @@ 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); @@ -3522,6 +3588,21 @@ #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 } }; @@ -3816,6 +3897,9 @@ 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 @@ -3872,6 +3956,26 @@ } 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 @@ -6724,6 +6828,10 @@ #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); #endif @@ -6782,6 +6890,12 @@ 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);