diff options
| author | Kim F. Storm | 2006-01-04 00:16:54 +0000 |
|---|---|---|
| committer | Kim F. Storm | 2006-01-04 00:16:54 +0000 |
| commit | e1652a86127e201a0e867a62545ec53de7376f3b (patch) | |
| tree | 14908a76b3ad2d3f491382ae9f330091942b9c24 /src/process.c | |
| parent | dd878ee14851f3d201266f451f5801195932d57f (diff) | |
| download | emacs-e1652a86127e201a0e867a62545ec53de7376f3b.tar.gz emacs-e1652a86127e201a0e867a62545ec53de7376f3b.zip | |
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.
Diffstat (limited to 'src/process.c')
| -rw-r--r-- | src/process.c | 154 |
1 files changed, 134 insertions, 20 deletions
diff --git a/src/process.c b/src/process.c index b88617a2c0f..c842b798c43 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -140,7 +140,10 @@ Boston, MA 02110-1301, USA. */ | |||
| 140 | Lisp_Object Qprocessp; | 140 | Lisp_Object Qprocessp; |
| 141 | Lisp_Object Qrun, Qstop, Qsignal; | 141 | Lisp_Object Qrun, Qstop, Qsignal; |
| 142 | Lisp_Object Qopen, Qclosed, Qconnect, Qfailed, Qlisten; | 142 | Lisp_Object Qopen, Qclosed, Qconnect, Qfailed, Qlisten; |
| 143 | Lisp_Object Qlocal, Qdatagram; | 143 | Lisp_Object Qlocal, Qipv4, Qdatagram; |
| 144 | #ifdef AF_INET6 | ||
| 145 | Lisp_Object Qipv6; | ||
| 146 | #endif | ||
| 144 | Lisp_Object QCname, QCbuffer, QChost, QCservice, QCtype; | 147 | Lisp_Object QCname, QCbuffer, QChost, QCservice, QCtype; |
| 145 | Lisp_Object QClocal, QCremote, QCcoding; | 148 | Lisp_Object QClocal, QCremote, QCcoding; |
| 146 | Lisp_Object QCserver, QCnowait, QCnoquery, QCstop; | 149 | Lisp_Object QCserver, QCnowait, QCnoquery, QCstop; |
| @@ -1195,9 +1198,11 @@ a socket connection. */) | |||
| 1195 | DEFUN ("format-network-address", Fformat_network_address, Sformat_network_address, | 1198 | DEFUN ("format-network-address", Fformat_network_address, Sformat_network_address, |
| 1196 | 1, 2, 0, | 1199 | 1, 2, 0, |
| 1197 | doc: /* Convert network ADDRESS from internal format to a string. | 1200 | doc: /* Convert network ADDRESS from internal format to a string. |
| 1201 | A 4 or 5 element vector represents an IPv4 address (with port number). | ||
| 1202 | An 8 or 9 element vector represents an IPv6 address (with port number). | ||
| 1198 | If optional second argument OMIT-PORT is non-nil, don't include a port | 1203 | If optional second argument OMIT-PORT is non-nil, don't include a port |
| 1199 | number in the string; in this case, interpret a 4 element vector as an | 1204 | number in the string, even when present in ADDRESS. |
| 1200 | IP address. Returns nil if format of ADDRESS is invalid. */) | 1205 | Returns nil if format of ADDRESS is invalid. */) |
| 1201 | (address, omit_port) | 1206 | (address, omit_port) |
| 1202 | Lisp_Object address, omit_port; | 1207 | Lisp_Object address, omit_port; |
| 1203 | { | 1208 | { |
| @@ -1207,13 +1212,13 @@ IP address. Returns nil if format of ADDRESS is invalid. */) | |||
| 1207 | if (STRINGP (address)) /* AF_LOCAL */ | 1212 | if (STRINGP (address)) /* AF_LOCAL */ |
| 1208 | return address; | 1213 | return address; |
| 1209 | 1214 | ||
| 1210 | if (VECTORP (address)) /* AF_INET */ | 1215 | if (VECTORP (address)) /* AF_INET or AF_INET6 */ |
| 1211 | { | 1216 | { |
| 1212 | register struct Lisp_Vector *p = XVECTOR (address); | 1217 | register struct Lisp_Vector *p = XVECTOR (address); |
| 1213 | Lisp_Object args[6]; | 1218 | Lisp_Object args[6]; |
| 1214 | int nargs, i; | 1219 | int nargs, i; |
| 1215 | 1220 | ||
| 1216 | if (!NILP (omit_port) && (p->size == 4 || p->size == 5)) | 1221 | if (p->size == 4 || (p->size == 5 && !NILP (omit_port))) |
| 1217 | { | 1222 | { |
| 1218 | args[0] = build_string ("%d.%d.%d.%d"); | 1223 | args[0] = build_string ("%d.%d.%d.%d"); |
| 1219 | nargs = 4; | 1224 | nargs = 4; |
| @@ -1223,6 +1228,16 @@ IP address. Returns nil if format of ADDRESS is invalid. */) | |||
| 1223 | args[0] = build_string ("%d.%d.%d.%d:%d"); | 1228 | args[0] = build_string ("%d.%d.%d.%d:%d"); |
| 1224 | nargs = 5; | 1229 | nargs = 5; |
| 1225 | } | 1230 | } |
| 1231 | else if (p->size == 8 || (p->size == 9 && !NILP (omit_port))) | ||
| 1232 | { | ||
| 1233 | args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x"); | ||
| 1234 | nargs = 8; | ||
| 1235 | } | ||
| 1236 | else if (p->size == 9) | ||
| 1237 | { | ||
| 1238 | args[0] = build_string ("[%x:%x:%x:%x:%x:%x:%x:%x]:%d"); | ||
| 1239 | nargs = 9; | ||
| 1240 | } | ||
| 1226 | else | 1241 | else |
| 1227 | return Qnil; | 1242 | return Qnil; |
| 1228 | 1243 | ||
| @@ -2212,6 +2227,20 @@ conv_sockaddr_to_lisp (sa, len) | |||
| 2212 | cp = (unsigned char *)&sin->sin_addr; | 2227 | cp = (unsigned char *)&sin->sin_addr; |
| 2213 | break; | 2228 | break; |
| 2214 | } | 2229 | } |
| 2230 | #ifdef AF_INET6 | ||
| 2231 | case AF_INET6: | ||
| 2232 | { | ||
| 2233 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; | ||
| 2234 | uint16_t *ip6 = (uint16_t *)&sin6->sin6_addr; | ||
| 2235 | len = sizeof (sin6->sin6_addr)/2 + 1; | ||
| 2236 | address = Fmake_vector (make_number (len), Qnil); | ||
| 2237 | p = XVECTOR (address); | ||
| 2238 | p->contents[--len] = make_number (ntohs (sin6->sin6_port)); | ||
| 2239 | for (i = 0; i < len; i++) | ||
| 2240 | p->contents[i] = make_number (ntohs (ip6[i])); | ||
| 2241 | return address; | ||
| 2242 | } | ||
| 2243 | #endif | ||
| 2215 | #ifdef HAVE_LOCAL_SOCKETS | 2244 | #ifdef HAVE_LOCAL_SOCKETS |
| 2216 | case AF_LOCAL: | 2245 | case AF_LOCAL: |
| 2217 | { | 2246 | { |
| @@ -2256,6 +2285,13 @@ get_lisp_to_sockaddr_size (address, familyp) | |||
| 2256 | *familyp = AF_INET; | 2285 | *familyp = AF_INET; |
| 2257 | return sizeof (struct sockaddr_in); | 2286 | return sizeof (struct sockaddr_in); |
| 2258 | } | 2287 | } |
| 2288 | #ifdef AF_INET6 | ||
| 2289 | else if (p->size == 9) | ||
| 2290 | { | ||
| 2291 | *familyp = AF_INET6; | ||
| 2292 | return sizeof (struct sockaddr_in6); | ||
| 2293 | } | ||
| 2294 | #endif | ||
| 2259 | } | 2295 | } |
| 2260 | #ifdef HAVE_LOCAL_SOCKETS | 2296 | #ifdef HAVE_LOCAL_SOCKETS |
| 2261 | else if (STRINGP (address)) | 2297 | else if (STRINGP (address)) |
| @@ -2302,6 +2338,23 @@ conv_lisp_to_sockaddr (family, address, sa, len) | |||
| 2302 | sin->sin_port = htons (i); | 2338 | sin->sin_port = htons (i); |
| 2303 | cp = (unsigned char *)&sin->sin_addr; | 2339 | cp = (unsigned char *)&sin->sin_addr; |
| 2304 | } | 2340 | } |
| 2341 | #ifdef AF_INET6 | ||
| 2342 | else if (family == AF_INET6) | ||
| 2343 | { | ||
| 2344 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; | ||
| 2345 | uint16_t *ip6 = (uint16_t *)&sin6->sin6_addr; | ||
| 2346 | len = sizeof (sin6->sin6_addr) + 1; | ||
| 2347 | i = XINT (p->contents[--len]); | ||
| 2348 | sin6->sin6_port = htons (i); | ||
| 2349 | for (i = 0; i < len; i++) | ||
| 2350 | if (INTEGERP (p->contents[i])) | ||
| 2351 | { | ||
| 2352 | int j = XFASTINT (p->contents[i]) & 0xffff; | ||
| 2353 | ip6[i] = ntohs (j); | ||
| 2354 | } | ||
| 2355 | return; | ||
| 2356 | } | ||
| 2357 | #endif | ||
| 2305 | } | 2358 | } |
| 2306 | else if (STRINGP (address)) | 2359 | else if (STRINGP (address)) |
| 2307 | { | 2360 | { |
| @@ -2595,10 +2648,13 @@ a random port number is selected for the server. | |||
| 2595 | stream type connection, `datagram' creates a datagram type connection. | 2648 | stream type connection, `datagram' creates a datagram type connection. |
| 2596 | 2649 | ||
| 2597 | :family FAMILY -- FAMILY is the address (and protocol) family for the | 2650 | :family FAMILY -- FAMILY is the address (and protocol) family for the |
| 2598 | service specified by HOST and SERVICE. The default address family is | 2651 | service specified by HOST and SERVICE. The default (nil) is to use |
| 2599 | Inet (or IPv4) for the host and port number specified by HOST and | 2652 | whatever address family (IPv4 or IPv6) that is defined for the host |
| 2600 | SERVICE. Other address families supported are: | 2653 | and port number specified by HOST and SERVICE. Other address families |
| 2654 | supported are: | ||
| 2601 | local -- for a local (i.e. UNIX) address specified by SERVICE. | 2655 | local -- for a local (i.e. UNIX) address specified by SERVICE. |
| 2656 | ipv4 -- use IPv4 address family only. | ||
| 2657 | ipv6 -- use IPv6 address family only. | ||
| 2602 | 2658 | ||
| 2603 | :local ADDRESS -- ADDRESS is the local address used for the connection. | 2659 | :local ADDRESS -- ADDRESS is the local address used for the connection. |
| 2604 | This parameter is ignored when opening a client process. When specified | 2660 | This parameter is ignored when opening a client process. When specified |
| @@ -2715,8 +2771,8 @@ usage: (make-network-process &rest ARGS) */) | |||
| 2715 | struct Lisp_Process *p; | 2771 | struct Lisp_Process *p; |
| 2716 | #ifdef HAVE_GETADDRINFO | 2772 | #ifdef HAVE_GETADDRINFO |
| 2717 | struct addrinfo ai, *res, *lres; | 2773 | struct addrinfo ai, *res, *lres; |
| 2718 | struct addrinfo hints; | 2774 | struct addrinfo hints; |
| 2719 | char *portstring, portbuf[128]; | 2775 | char *portstring, portbuf[128]; |
| 2720 | #else /* HAVE_GETADDRINFO */ | 2776 | #else /* HAVE_GETADDRINFO */ |
| 2721 | struct _emacs_addrinfo | 2777 | struct _emacs_addrinfo |
| 2722 | { | 2778 | { |
| @@ -2855,19 +2911,29 @@ usage: (make-network-process &rest ARGS) */) | |||
| 2855 | 2911 | ||
| 2856 | /* :family FAMILY -- nil (for Inet), local, or integer. */ | 2912 | /* :family FAMILY -- nil (for Inet), local, or integer. */ |
| 2857 | tem = Fplist_get (contact, QCfamily); | 2913 | tem = Fplist_get (contact, QCfamily); |
| 2858 | if (INTEGERP (tem)) | 2914 | if (NILP (tem)) |
| 2859 | family = XINT (tem); | ||
| 2860 | else | ||
| 2861 | { | 2915 | { |
| 2862 | if (NILP (tem)) | 2916 | #ifdef HAVE_GETADDRINFO |
| 2863 | family = AF_INET; | 2917 | family = AF_UNSPEC; |
| 2864 | #ifdef HAVE_LOCAL_SOCKETS | 2918 | #else |
| 2865 | else if (EQ (tem, Qlocal)) | 2919 | family = AF_INET; |
| 2866 | family = AF_LOCAL; | ||
| 2867 | #endif | 2920 | #endif |
| 2868 | } | 2921 | } |
| 2869 | if (family < 0) | 2922 | #ifdef HAVE_LOCAL_SOCKETS |
| 2923 | else if (EQ (tem, Qlocal)) | ||
| 2924 | family = AF_LOCAL; | ||
| 2925 | #endif | ||
| 2926 | #ifdef AF_INET6 | ||
| 2927 | else if (EQ (tem, Qipv6)) | ||
| 2928 | family = AF_INET6; | ||
| 2929 | #endif | ||
| 2930 | else if (EQ (tem, Qipv4)) | ||
| 2931 | family = AF_INET; | ||
| 2932 | else if (INTEGERP (tem)) | ||
| 2933 | family = XINT (tem); | ||
| 2934 | else | ||
| 2870 | error ("Unknown address family"); | 2935 | error ("Unknown address family"); |
| 2936 | |||
| 2871 | ai.ai_family = family; | 2937 | ai.ai_family = family; |
| 2872 | 2938 | ||
| 2873 | /* :service SERVICE -- string, integer (port number), or t (random port). */ | 2939 | /* :service SERVICE -- string, integer (port number), or t (random port). */ |
| @@ -2933,7 +2999,7 @@ usage: (make-network-process &rest ARGS) */) | |||
| 2933 | QUIT; | 2999 | QUIT; |
| 2934 | memset (&hints, 0, sizeof (hints)); | 3000 | memset (&hints, 0, sizeof (hints)); |
| 2935 | hints.ai_flags = 0; | 3001 | hints.ai_flags = 0; |
| 2936 | hints.ai_family = NILP (Fplist_member (contact, QCfamily)) ? AF_UNSPEC : family; | 3002 | hints.ai_family = family; |
| 2937 | hints.ai_socktype = socktype; | 3003 | hints.ai_socktype = socktype; |
| 2938 | hints.ai_protocol = 0; | 3004 | hints.ai_protocol = 0; |
| 2939 | ret = getaddrinfo (SDATA (host), portstring, &hints, &res); | 3005 | ret = getaddrinfo (SDATA (host), portstring, &hints, &res); |
| @@ -3522,6 +3588,21 @@ static struct ifflag_def ifflag_table[] = { | |||
| 3522 | #ifdef IFF_DYNAMIC | 3588 | #ifdef IFF_DYNAMIC |
| 3523 | { IFF_DYNAMIC, "dynamic" }, | 3589 | { IFF_DYNAMIC, "dynamic" }, |
| 3524 | #endif | 3590 | #endif |
| 3591 | #ifdef IFF_OACTIV | ||
| 3592 | { IFF_OACTIV, "oactiv" }, /* OpenBSD: transmission in progress */ | ||
| 3593 | #endif | ||
| 3594 | #ifdef IFF_SIMPLEX | ||
| 3595 | { IFF_SIMPLEX, "simplex" }, /* OpenBSD: can't hear own transmissions */ | ||
| 3596 | #endif | ||
| 3597 | #ifdef IFF_LINK0 | ||
| 3598 | { IFF_LINK0, "link0" }, /* OpenBSD: per link layer defined bit */ | ||
| 3599 | #endif | ||
| 3600 | #ifdef IFF_LINK1 | ||
| 3601 | { IFF_LINK1, "link1" }, /* OpenBSD: per link layer defined bit */ | ||
| 3602 | #endif | ||
| 3603 | #ifdef IFF_LINK2 | ||
| 3604 | { IFF_LINK2, "link2" }, /* OpenBSD: per link layer defined bit */ | ||
| 3605 | #endif | ||
| 3525 | { 0, 0 } | 3606 | { 0, 0 } |
| 3526 | }; | 3607 | }; |
| 3527 | 3608 | ||
| @@ -3816,6 +3897,9 @@ server_accept_connection (server, channel) | |||
| 3816 | union u_sockaddr { | 3897 | union u_sockaddr { |
| 3817 | struct sockaddr sa; | 3898 | struct sockaddr sa; |
| 3818 | struct sockaddr_in in; | 3899 | struct sockaddr_in in; |
| 3900 | #ifdef AF_INET6 | ||
| 3901 | struct sockaddr_in6 in6; | ||
| 3902 | #endif | ||
| 3819 | #ifdef HAVE_LOCAL_SOCKETS | 3903 | #ifdef HAVE_LOCAL_SOCKETS |
| 3820 | struct sockaddr_un un; | 3904 | struct sockaddr_un un; |
| 3821 | #endif | 3905 | #endif |
| @@ -3872,6 +3956,26 @@ server_accept_connection (server, channel) | |||
| 3872 | } | 3956 | } |
| 3873 | break; | 3957 | break; |
| 3874 | 3958 | ||
| 3959 | #ifdef AF_INET6 | ||
| 3960 | case AF_INET6: | ||
| 3961 | { | ||
| 3962 | Lisp_Object args[9]; | ||
| 3963 | uint16_t *ip6 = (uint16_t *)&saddr.in6.sin6_addr; | ||
| 3964 | int i; | ||
| 3965 | args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x"); | ||
| 3966 | for (i = 0; i < 8; i++) | ||
| 3967 | args[i+1] = make_number (ntohs(ip6[i])); | ||
| 3968 | host = Fformat (9, args); | ||
| 3969 | service = make_number (ntohs (saddr.in.sin_port)); | ||
| 3970 | |||
| 3971 | args[0] = build_string (" <[%s]:%d>"); | ||
| 3972 | args[1] = host; | ||
| 3973 | args[2] = service; | ||
| 3974 | caller = Fformat (3, args); | ||
| 3975 | } | ||
| 3976 | break; | ||
| 3977 | #endif | ||
| 3978 | |||
| 3875 | #ifdef HAVE_LOCAL_SOCKETS | 3979 | #ifdef HAVE_LOCAL_SOCKETS |
| 3876 | case AF_LOCAL: | 3980 | case AF_LOCAL: |
| 3877 | #endif | 3981 | #endif |
| @@ -6724,6 +6828,10 @@ init_process () | |||
| 6724 | #ifdef HAVE_LOCAL_SOCKETS | 6828 | #ifdef HAVE_LOCAL_SOCKETS |
| 6725 | ADD_SUBFEATURE (QCfamily, Qlocal); | 6829 | ADD_SUBFEATURE (QCfamily, Qlocal); |
| 6726 | #endif | 6830 | #endif |
| 6831 | ADD_SUBFEATURE (QCfamily, Qipv4); | ||
| 6832 | #ifdef AF_INET6 | ||
| 6833 | ADD_SUBFEATURE (QCfamily, Qipv6); | ||
| 6834 | #endif | ||
| 6727 | #ifdef HAVE_GETSOCKNAME | 6835 | #ifdef HAVE_GETSOCKNAME |
| 6728 | ADD_SUBFEATURE (QCservice, Qt); | 6836 | ADD_SUBFEATURE (QCservice, Qt); |
| 6729 | #endif | 6837 | #endif |
| @@ -6782,6 +6890,12 @@ syms_of_process () | |||
| 6782 | staticpro (&Qlisten); | 6890 | staticpro (&Qlisten); |
| 6783 | Qlocal = intern ("local"); | 6891 | Qlocal = intern ("local"); |
| 6784 | staticpro (&Qlocal); | 6892 | staticpro (&Qlocal); |
| 6893 | Qipv4 = intern ("ipv4"); | ||
| 6894 | staticpro (&Qipv4); | ||
| 6895 | #ifdef AF_INET6 | ||
| 6896 | Qipv6 = intern ("ipv6"); | ||
| 6897 | staticpro (&Qipv6); | ||
| 6898 | #endif | ||
| 6785 | Qdatagram = intern ("datagram"); | 6899 | Qdatagram = intern ("datagram"); |
| 6786 | staticpro (&Qdatagram); | 6900 | staticpro (&Qdatagram); |
| 6787 | 6901 | ||