Mercurial > emacs
comparison src/process.c @ 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 | 8f3c10fea90b |
| children | e213d76ca446 |
comparison
equal
deleted
inserted
replaced
| 68007:0b578812ab24 | 68008:10f0a09ec82e |
|---|---|
| 138 #include "atimer.h" | 138 #include "atimer.h" |
| 139 | 139 |
| 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; |
| 147 Lisp_Object QCsentinel, QClog, QCoptions, QCplist; | 150 Lisp_Object QCsentinel, QClog, QCoptions, QCplist; |
| 148 Lisp_Object QCfilter_multibyte; | 151 Lisp_Object QCfilter_multibyte; |
| 1193 | 1196 |
| 1194 #ifdef HAVE_SOCKETS | 1197 #ifdef HAVE_SOCKETS |
| 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 { |
| 1204 if (NILP (address)) | 1209 if (NILP (address)) |
| 1205 return Qnil; | 1210 return Qnil; |
| 1206 | 1211 |
| 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; |
| 1220 } | 1225 } |
| 1221 else if (p->size == 5) | 1226 else if (p->size == 5) |
| 1222 { | 1227 { |
| 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; |
| 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; | |
| 1225 } | 1240 } |
| 1226 else | 1241 else |
| 1227 return Qnil; | 1242 return Qnil; |
| 1228 | 1243 |
| 1229 for (i = 0; i < nargs; i++) | 1244 for (i = 0; i < nargs; i++) |
| 2210 p = XVECTOR (address); | 2225 p = XVECTOR (address); |
| 2211 p->contents[--len] = make_number (ntohs (sin->sin_port)); | 2226 p->contents[--len] = make_number (ntohs (sin->sin_port)); |
| 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 { |
| 2218 struct sockaddr_un *sockun = (struct sockaddr_un *) sa; | 2247 struct sockaddr_un *sockun = (struct sockaddr_un *) sa; |
| 2219 for (i = 0; i < sizeof (sockun->sun_path); i++) | 2248 for (i = 0; i < sizeof (sockun->sun_path); i++) |
| 2254 if (p->size == 5) | 2283 if (p->size == 5) |
| 2255 { | 2284 { |
| 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)) |
| 2262 { | 2298 { |
| 2263 *familyp = AF_LOCAL; | 2299 *familyp = AF_LOCAL; |
| 2300 len = sizeof (sin->sin_addr) + 1; | 2336 len = sizeof (sin->sin_addr) + 1; |
| 2301 i = XINT (p->contents[--len]); | 2337 i = XINT (p->contents[--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 { |
| 2308 #ifdef HAVE_LOCAL_SOCKETS | 2361 #ifdef HAVE_LOCAL_SOCKETS |
| 2309 if (family == AF_LOCAL) | 2362 if (family == AF_LOCAL) |
| 2593 | 2646 |
| 2594 :type TYPE -- TYPE is the type of connection. The default (nil) is a | 2647 :type TYPE -- TYPE is the type of connection. The default (nil) is a |
| 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 |
| 2605 for a server process, the FAMILY, HOST and SERVICE args are ignored. | 2661 for a server process, the FAMILY, HOST and SERVICE args are ignored. |
| 2606 | 2662 |
| 2713 Lisp_Object proc; | 2769 Lisp_Object proc; |
| 2714 Lisp_Object contact; | 2770 Lisp_Object contact; |
| 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 { |
| 2723 int ai_family; | 2779 int ai_family; |
| 2724 int ai_socktype; | 2780 int ai_socktype; |
| 2853 goto open_socket; | 2909 goto open_socket; |
| 2854 } | 2910 } |
| 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)) |
| 2915 { | |
| 2916 #ifdef HAVE_GETADDRINFO | |
| 2917 family = AF_UNSPEC; | |
| 2918 #else | |
| 2919 family = AF_INET; | |
| 2920 #endif | |
| 2921 } | |
| 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)) | |
| 2859 family = XINT (tem); | 2933 family = XINT (tem); |
| 2860 else | 2934 else |
| 2861 { | |
| 2862 if (NILP (tem)) | |
| 2863 family = AF_INET; | |
| 2864 #ifdef HAVE_LOCAL_SOCKETS | |
| 2865 else if (EQ (tem, Qlocal)) | |
| 2866 family = AF_LOCAL; | |
| 2867 #endif | |
| 2868 } | |
| 2869 if (family < 0) | |
| 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). */ |
| 2874 service = Fplist_get (contact, QCservice); | 2940 service = Fplist_get (contact, QCservice); |
| 2875 | 2941 |
| 2931 | 2997 |
| 2932 immediate_quit = 1; | 2998 immediate_quit = 1; |
| 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); |
| 2940 if (ret) | 3006 if (ret) |
| 2941 #ifdef HAVE_GAI_STRERROR | 3007 #ifdef HAVE_GAI_STRERROR |
| 3520 { IFF_AUTOMEDIA, "automedia" }, | 3586 { IFF_AUTOMEDIA, "automedia" }, |
| 3521 #endif | 3587 #endif |
| 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 |
| 3528 DEFUN ("network-interface-info", Fnetwork_interface_info, Snetwork_interface_info, 1, 1, 0, | 3609 DEFUN ("network-interface-info", Fnetwork_interface_info, Snetwork_interface_info, 1, 1, 0, |
| 3529 doc: /* Return information about network interface named IFNAME. | 3610 doc: /* Return information about network interface named IFNAME. |
| 3814 struct Lisp_Process *p; | 3895 struct Lisp_Process *p; |
| 3815 int s; | 3896 int s; |
| 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 |
| 3822 } saddr; | 3906 } saddr; |
| 3823 int len = sizeof saddr; | 3907 int len = sizeof saddr; |
| 3869 args[1] = host; | 3953 args[1] = host; |
| 3870 args[2] = service; | 3954 args[2] = service; |
| 3871 caller = Fformat (3, args); | 3955 caller = Fformat (3, args); |
| 3872 } | 3956 } |
| 3873 break; | 3957 break; |
| 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 | |
| 3874 | 3978 |
| 3875 #ifdef HAVE_LOCAL_SOCKETS | 3979 #ifdef HAVE_LOCAL_SOCKETS |
| 3876 case AF_LOCAL: | 3980 case AF_LOCAL: |
| 3877 #endif | 3981 #endif |
| 3878 default: | 3982 default: |
| 6722 ADD_SUBFEATURE (QCtype, Qdatagram); | 6826 ADD_SUBFEATURE (QCtype, Qdatagram); |
| 6723 #endif | 6827 #endif |
| 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 |
| 6730 #if !defined(TERM) && (defined(O_NONBLOCK) || defined(O_NDELAY)) | 6838 #if !defined(TERM) && (defined(O_NONBLOCK) || defined(O_NDELAY)) |
| 6731 ADD_SUBFEATURE (QCserver, Qt); | 6839 ADD_SUBFEATURE (QCserver, Qt); |
| 6780 staticpro (&Qfailed); | 6888 staticpro (&Qfailed); |
| 6781 Qlisten = intern ("listen"); | 6889 Qlisten = intern ("listen"); |
| 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 |
| 6788 QCname = intern (":name"); | 6902 QCname = intern (":name"); |
| 6789 staticpro (&QCname); | 6903 staticpro (&QCname); |
