summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <vinschen@redhat.com>2006-07-06 14:04:32 +0000
committerCorinna Vinschen <vinschen@redhat.com>2006-07-06 14:04:32 +0000
commit6836437f9c15dad5088da4ecfcd8ca44a56e6d63 (patch)
tree0783f22039a6c503fdb9d09e38d885b3d0b73808
parent9ee064b4bd06b7be50fbc976c46172f83557f084 (diff)
downloadgdb-6836437f9c15dad5088da4ecfcd8ca44a56e6d63.tar.gz
* cygwin.din: Export in6addr_any, in6addr_loopback, freeaddrinfo,
gai_strerror, getaddrinfo, getnameinfo. * fhandler_socket.cc: Include cygwin/in6.h. (get_inet_addr): Accomodate AF_INET6 usage. (fhandler_socket::connect): Ditto. (fhandler_socket::listen): Ditto. (fhandler_socket::sendto): Ditto. * net.cc: Include cygwin/in6.h. (in6addr_any): Define. (in6addr_loopback): Define. (cygwin_socket): Accomodate AF_INET6 usage. (socketpair): Bind socketpairs only to loopback for security. (inet_pton4): New static function. (inet_pton6): Ditto. (cygwin_inet_pton): New AF_INET6 aware inet_pton implementation. (inet_ntop4): New static function. (inet_ntop6): Ditto. (cygwin_inet_ntop): New AF_INET6 aware inet_ntop implementation. (ga_aistruct): New static function. (ga_clone): Ditto. (ga_echeck): Ditto. (ga_nsearch): Ditto. (ga_port): Ditto. (ga_serv): Ditto. (ga_unix): Ditto. (gn_ipv46): Ditto. (ipv4_freeaddrinfo): Ditto. (ipv4_getaddrinfo): Ditto. (ipv4_getnameinfo): Ditto. (gai_errmap_t): New structure holding error code - error string mapping. (cygwin_gai_strerror): New function implementing gai_strerror. (w32_to_gai_err): New static function. (get_ipv6_funcs): Ditto. (load_ipv6_funcs): Ditto. (cygwin_freeaddrinfo): New function implementing freeaddrinfo. (cygwin_getaddrinfo): New function implementing getaddrinfo. (cygwin_getnameinfo): New function implementing getnameinfo. * include/netdb.h: Include stdint.h and cygwin/socket.h. Define data types and macros used by getaddrinfo and friends. Declare freeaddrinfo, gai_strerror, getaddrinfo and getnameinfo. * include/cygwin/in.h: Add IPv6 related IPPROTOs. Remove definition of struct sockaddr_in6. Include cygwin/in6.h instead. * include/cygwin/in6.h: New header file defining IPv6 releated data types and macros. * include/cygwin/socket.h: Enable AF_INET6 and PF_INET6. Add IPv6 related socket options. * include/cygwin/version.h: Bump API minor number.
-rw-r--r--winsup/cygwin/ChangeLog50
-rw-r--r--winsup/cygwin/cygwin.din1628
-rw-r--r--winsup/cygwin/fhandler_socket.cc1694
-rw-r--r--winsup/cygwin/include/cygwin/in.h209
-rw-r--r--winsup/cygwin/include/cygwin/in6.h119
-rw-r--r--winsup/cygwin/include/cygwin/socket.h277
-rw-r--r--winsup/cygwin/include/cygwin/version.h367
-rw-r--r--winsup/cygwin/include/netdb.h227
-rw-r--r--winsup/cygwin/net.cc3629
9 files changed, 8200 insertions, 0 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 9ab0c2cb1b7..f4c954db660 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,55 @@
2006-07-06 Corinna Vinschen <corinna@vinschen.de>
+ * cygwin.din: Export in6addr_any, in6addr_loopback, freeaddrinfo,
+ gai_strerror, getaddrinfo, getnameinfo.
+ * fhandler_socket.cc: Include cygwin/in6.h.
+ (get_inet_addr): Accomodate AF_INET6 usage.
+ (fhandler_socket::connect): Ditto.
+ (fhandler_socket::listen): Ditto.
+ (fhandler_socket::sendto): Ditto.
+ * net.cc: Include cygwin/in6.h.
+ (in6addr_any): Define.
+ (in6addr_loopback): Define.
+ (cygwin_socket): Accomodate AF_INET6 usage.
+ (socketpair): Bind socketpairs only to loopback for security.
+ (inet_pton4): New static function.
+ (inet_pton6): Ditto.
+ (cygwin_inet_pton): New AF_INET6 aware inet_pton implementation.
+ (inet_ntop4): New static function.
+ (inet_ntop6): Ditto.
+ (cygwin_inet_ntop): New AF_INET6 aware inet_ntop implementation.
+ (ga_aistruct): New static function.
+ (ga_clone): Ditto.
+ (ga_echeck): Ditto.
+ (ga_nsearch): Ditto.
+ (ga_port): Ditto.
+ (ga_serv): Ditto.
+ (ga_unix): Ditto.
+ (gn_ipv46): Ditto.
+ (ipv4_freeaddrinfo): Ditto.
+ (ipv4_getaddrinfo): Ditto.
+ (ipv4_getnameinfo): Ditto.
+ (gai_errmap_t): New structure holding error code - error string mapping.
+ (cygwin_gai_strerror): New function implementing gai_strerror.
+ (w32_to_gai_err): New static function.
+ (get_ipv6_funcs): Ditto.
+ (load_ipv6_funcs): Ditto.
+ (cygwin_freeaddrinfo): New function implementing freeaddrinfo.
+ (cygwin_getaddrinfo): New function implementing getaddrinfo.
+ (cygwin_getnameinfo): New function implementing getnameinfo.
+ * include/netdb.h: Include stdint.h and cygwin/socket.h. Define
+ data types and macros used by getaddrinfo and friends. Declare
+ freeaddrinfo, gai_strerror, getaddrinfo and getnameinfo.
+ * include/cygwin/in.h: Add IPv6 related IPPROTOs. Remove definition
+ of struct sockaddr_in6. Include cygwin/in6.h instead.
+ * include/cygwin/in6.h: New header file defining IPv6 releated
+ data types and macros.
+ * include/cygwin/socket.h: Enable AF_INET6 and PF_INET6. Add
+ IPv6 related socket options.
+ * include/cygwin/version.h: Bump API minor number.
+
+2006-07-06 Corinna Vinschen <corinna@vinschen.de>
+
* autoload.cc (DsGetDcNameA): Define.
(NetGetAnyDCName): Define.
* security.cc: Include dsgetdc.h.
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
new file mode 100644
index 00000000000..7d00b785b41
--- /dev/null
+++ b/winsup/cygwin/cygwin.din
@@ -0,0 +1,1628 @@
+LIBRARY "cygwin1.dll" BASE=0x61000000
+
+EXPORTS
+__argc DATA
+__argv DATA
+_check_for_executable DATA
+__check_rhosts_file DATA
+_ctype_ DATA
+__cygwin_environ DATA
+__cygwin_user_data DATA
+_daylight DATA
+h_errno DATA
+_impure_ptr DATA
+in6addr_any DATA
+in6addr_loopback DATA
+__mb_cur_max DATA
+optarg DATA
+opterr DATA
+optind DATA
+optopt DATA
+optreset DATA
+__progname DATA
+__rcmd_errstr DATA
+reent_data DATA
+sys_errlist = _sys_errlist DATA
+_sys_errlist DATA
+sys_nerr = _sys_nerr DATA
+_sys_nerr DATA
+_timezone DATA
+_tzname DATA
+a64l NOSIGFE
+abort NOSIGFE
+_abort = abort SIGFE
+abs NOSIGFE
+_abs = abs NOSIGFE
+accept = cygwin_accept SIGFE
+access SIGFE
+_access = access SIGFE
+acl SIGFE
+_acl = acl SIGFE
+_acl32 = acl32 SIGFE
+aclcheck NOSIGFE
+_aclcheck = aclcheck NOSIGFE
+_aclcheck32 = aclcheck32 NOSIGFE
+aclfrommode SIGFE
+_aclfrommode = aclfrommode SIGFE
+_aclfrommode32 = aclfrommode32 SIGFE
+aclfrompbits SIGFE
+_aclfrompbits = aclfrompbits SIGFE
+_aclfrompbits32 = aclfrompbits32 SIGFE
+aclfromtext SIGFE
+_aclfromtext = aclfromtext SIGFE
+_aclfromtext32 = aclfromtext32 SIGFE
+aclsort SIGFE
+_aclsort = aclsort SIGFE
+_aclsort32 = aclsort32 SIGFE
+acltomode SIGFE
+_acltomode = acltomode SIGFE
+_acltomode32 = acltomode32 SIGFE
+acltopbits SIGFE
+_acltopbits = acltopbits SIGFE
+_acltopbits32 = acltopbits32 SIGFE
+acltotext SIGFE
+_acltotext = acltotext SIGFE
+_acltotext32 = acltotext32 SIGFE
+acos NOSIGFE
+_acos = acos NOSIGFE
+acosf NOSIGFE
+_acosf = acosf NOSIGFE
+acosh NOSIGFE
+_acosh = acosh NOSIGFE
+acoshf NOSIGFE
+_acoshf = acoshf NOSIGFE
+alarm SIGFE
+_alarm = alarm SIGFE
+_alloca NOSIGFE
+alphasort NOSIGFE
+_alphasort = alphasort NOSIGFE
+argz_add SIGFE
+__argz_add = argz_add SIGFE
+argz_add_sep SIGFE
+__argz_add_sep = argz_add_sep SIGFE
+argz_append SIGFE
+__argz_append = argz_append SIGFE
+argz_count NOSIGFE
+__argz_count = argz_count NOSIGFE
+argz_create SIGFE
+__argz_create = argz_create SIGFE
+argz_create_sep SIGFE
+__argz_create_sep = argz_create_sep SIGFE
+argz_delete SIGFE
+__argz_delete = argz_delete SIGFE
+argz_extract NOSIGFE
+__argz_extract = argz_extract NOSIGFE
+argz_insert SIGFE
+__argz_insert = argz_insert SIGFE
+argz_next NOSIGFE
+__argz_next = argz_next NOSIGFE
+argz_replace SIGFE
+__argz_replace = argz_replace SIGFE
+argz_stringify NOSIGFE
+__argz_stringify = argz_stringify NOSIGFE
+asctime SIGFE
+_asctime = asctime SIGFE
+asctime_r SIGFE
+_asctime_r = asctime_r SIGFE
+asin NOSIGFE
+_asin = asin NOSIGFE
+asinf NOSIGFE
+_asinf = asinf NOSIGFE
+asinh NOSIGFE
+_asinh = asinh NOSIGFE
+asinhf NOSIGFE
+_asinhf = asinhf NOSIGFE
+asprintf SIGFE
+_asprintf = asprintf SIGFE
+asprintf_r = _asprintf_r SIGFE
+_asprintf_r SIGFE
+__assert SIGFE
+__assertfail SIGFE
+atan NOSIGFE
+_atan = atan NOSIGFE
+atan2 NOSIGFE
+_atan2 = atan2 NOSIGFE
+atan2f NOSIGFE
+_atan2f = atan2f NOSIGFE
+atanf NOSIGFE
+_atanf = atanf NOSIGFE
+atanh NOSIGFE
+_atanh = atanh NOSIGFE
+atanhf NOSIGFE
+_atanhf = atanhf NOSIGFE
+atexit = cygwin_atexit SIGFE
+_atexit = cygwin_atexit SIGFE
+atof SIGFE
+_atof = atof SIGFE
+atoff SIGFE
+_atoff = atoff SIGFE
+atoi NOSIGFE
+_atoi = atoi NOSIGFE
+atol NOSIGFE
+_atol = atol NOSIGFE
+atoll NOSIGFE
+basename NOSIGFE
+bcmp NOSIGFE
+_bcmp = bcmp NOSIGFE
+bcopy NOSIGFE
+_bcopy = bcopy NOSIGFE
+bind = cygwin_bind SIGFE
+bsearch NOSIGFE
+_bsearch = bsearch NOSIGFE
+btowc NOSIGFE
+bzero NOSIGFE
+_bzero = bzero NOSIGFE
+cabs NOSIGFE
+_cabs = cabs NOSIGFE
+cabsf NOSIGFE
+_cabsf = cabsf NOSIGFE
+calloc SIGFE
+_calloc = calloc SIGFE
+cbrt NOSIGFE
+_cbrt = cbrt NOSIGFE
+cbrtf NOSIGFE
+_cbrtf = cbrtf NOSIGFE
+ceil NOSIGFE
+_ceil = ceil NOSIGFE
+ceilf NOSIGFE
+_ceilf = ceilf NOSIGFE
+cfgetispeed NOSIGFE
+cfgetospeed NOSIGFE
+cfsetispeed SIGFE
+cfsetospeed SIGFE
+chdir SIGFE
+_chdir = chdir SIGFE
+chmod SIGFE
+_chmod = chmod SIGFE
+chown SIGFE
+_chown = chown SIGFE
+_chown32 = chown32 SIGFE
+chroot SIGFE
+_chroot = chroot SIGFE
+cleanup_glue NOSIGFE
+clearerr SIGFE
+_clearerr = clearerr SIGFE
+clock SIGFE
+_clock = clock SIGFE
+clock_getres SIGFE
+clock_gettime SIGFE
+clock_setres SIGFE
+close SIGFE
+_close = close SIGFE
+closedir SIGFE
+_closedir = closedir SIGFE
+closelog SIGFE
+connect = cygwin_connect SIGFE
+copysign NOSIGFE
+_copysign = copysign NOSIGFE
+copysignf NOSIGFE
+_copysignf = copysignf NOSIGFE
+cos NOSIGFE
+_cos = cos NOSIGFE
+cosf NOSIGFE
+_cosf = cosf NOSIGFE
+cosh NOSIGFE
+_cosh = cosh NOSIGFE
+coshf NOSIGFE
+_coshf = coshf NOSIGFE
+creat SIGFE
+_creat = creat SIGFE
+ctermid SIGFE
+ctime SIGFE
+_ctime = ctime SIGFE
+ctime_r SIGFE
+_ctime_r = ctime_r SIGFE
+cuserid NOSIGFE
+_cuserid = cuserid NOSIGFE
+cwait SIGFE
+_cwait = cwait SIGFE
+cygwin32_attach_handle_to_fd = cygwin_attach_handle_to_fd SIGFE
+cygwin32_conv_to_full_posix_path = cygwin_conv_to_full_posix_path SIGFE
+cygwin32_conv_to_full_win32_path = cygwin_conv_to_full_win32_path SIGFE
+cygwin32_conv_to_posix_path = cygwin_conv_to_posix_path SIGFE
+cygwin32_conv_to_win32_path = cygwin_conv_to_win32_path SIGFE
+cygwin32_detach_dll = cygwin_detach_dll SIGFE_MAYBE
+cygwin32_internal = cygwin_internal SIGFE
+cygwin32_posix_path_list_p = cygwin_posix_path_list_p NOSIGFE
+cygwin32_posix_to_win32_path_list = cygwin_posix_to_win32_path_list SIGFE
+cygwin32_posix_to_win32_path_list_buf_size = cygwin_posix_to_win32_path_list_buf_size SIGFE
+cygwin32_split_path = cygwin_split_path NOSIGFE
+cygwin32_win32_to_posix_path_list = cygwin_win32_to_posix_path_list SIGFE
+cygwin32_win32_to_posix_path_list_buf_size = cygwin_win32_to_posix_path_list_buf_size SIGFE
+cygwin32_winpid_to_pid = cygwin_winpid_to_pid SIGFE
+cygwin_attach_handle_to_fd SIGFE
+cygwin_conv_to_full_posix_path SIGFE
+cygwin_conv_to_full_win32_path SIGFE
+cygwin_conv_to_posix_path SIGFE
+cygwin_conv_to_win32_path SIGFE
+cygwin_detach_dll SIGFE_MAYBE
+cygwin_dll_init NOSIGFE
+cygwin_internal NOSIGFE
+cygwin_logon_user SIGFE
+cygwin_posix_path_list_p NOSIGFE
+cygwin_posix_to_win32_path_list SIGFE
+cygwin_posix_to_win32_path_list_buf_size SIGFE
+cygwin_set_impersonation_token SIGFE
+cygwin_split_path NOSIGFE
+cygwin_stackdump SIGFE
+cygwin_umount SIGFE
+cygwin_win32_to_posix_path_list SIGFE
+cygwin_win32_to_posix_path_list_buf_size SIGFE
+cygwin_winpid_to_pid SIGFE
+daemon SIGFE
+difftime NOSIGFE
+_difftime = difftime NOSIGFE
+dirfd SIGFE
+_dirfd = dirfd SIGFE
+dirname NOSIGFE
+div NOSIGFE
+_div = div NOSIGFE
+dlclose SIGFE
+dlerror NOSIGFE
+dlfork NOSIGFE
+_dll_crt0@0 NOSIGFE
+dll_crt0__FP11per_process NOSIGFE
+dll_dllcrt0 NOSIGFE
+dll_entry@12 NOSIGFE
+dll_noncygwin_dllcrt0 NOSIGFE
+dlopen SIGFE
+dlsym SIGFE
+drand48 NOSIGFE
+_drand48 = drand48 NOSIGFE
+drem NOSIGFE
+_drem = drem NOSIGFE
+dremf NOSIGFE
+_dremf = dremf NOSIGFE
+dup SIGFE
+_dup = dup SIGFE
+dup2 SIGFE
+_dup2 = dup2 SIGFE
+ecvt SIGFE
+_ecvt = ecvt SIGFE
+ecvtbuf SIGFE
+_ecvtbuf = ecvtbuf SIGFE
+ecvtf SIGFE
+_ecvtf = ecvtf SIGFE
+endgrent NOSIGFE
+_endgrent = endgrent NOSIGFE
+endhostent NOSIGFE
+endmntent NOSIGFE
+_endmntent = endmntent NOSIGFE
+endprotoent = cygwin_endprotoent SIGFE
+endpwent NOSIGFE
+_endpwent = endpwent NOSIGFE
+endservent = cygwin_endservent SIGFE
+endusershell SIGFE
+endutent SIGFE
+_endutent = endutent SIGFE
+endutxent SIGFE
+envz_add SIGFE
+__envz_add = envz_add SIGFE
+envz_entry NOSIGFE
+__envz_entry = envz_entry NOSIGFE
+envz_get NOSIGFE
+__envz_get = envz_get NOSIGFE
+envz_merge SIGFE
+__envz_merge = envz_merge SIGFE
+envz_remove SIGFE
+__envz_remove = envz_remove SIGFE
+envz_strip SIGFE
+__envz_strip = envz_strip SIGFE
+__eprintf SIGFE
+erand48 NOSIGFE
+_erand48 = erand48 NOSIGFE
+erf NOSIGFE
+_erf = erf NOSIGFE
+erfc NOSIGFE
+_erfc = erfc NOSIGFE
+erfcf NOSIGFE
+_erfcf = erfcf NOSIGFE
+erff NOSIGFE
+_erff = erff NOSIGFE
+err SIGFE
+__errno NOSIGFE
+errx SIGFE
+execl SIGFE
+_execl = execl SIGFE
+execle SIGFE
+_execle = execle SIGFE
+execlp SIGFE
+_execlp = execlp SIGFE
+execv SIGFE
+_execv = execv SIGFE
+execve SIGFE
+_execve = execve SIGFE
+execvp SIGFE
+_execvp = execvp SIGFE
+exit = cygwin_exit SIGFE
+_exit SIGFE
+exp NOSIGFE
+_exp = exp NOSIGFE
+exp2 NOSIGFE
+exp2f NOSIGFE
+expf NOSIGFE
+_expf = expf NOSIGFE
+expm1 NOSIGFE
+_expm1 = expm1 NOSIGFE
+expm1f NOSIGFE
+_expm1f = expm1f NOSIGFE
+_f_atan2 NOSIGFE
+__f_atan2 = _f_atan2 NOSIGFE
+_f_atan2f NOSIGFE
+__f_atan2f = _f_atan2f NOSIGFE
+_f_exp NOSIGFE
+__f_exp = _f_exp NOSIGFE
+_f_expf NOSIGFE
+__f_expf = _f_expf NOSIGFE
+_f_frexp NOSIGFE
+__f_frexp = _f_frexp NOSIGFE
+_f_frexpf NOSIGFE
+__f_frexpf = _f_frexpf NOSIGFE
+_f_ldexp NOSIGFE
+__f_ldexp = _f_ldexp NOSIGFE
+_f_ldexpf NOSIGFE
+__f_ldexpf = _f_ldexpf NOSIGFE
+_f_log NOSIGFE
+__f_log = _f_log NOSIGFE
+_f_log10 NOSIGFE
+__f_log10 = _f_log10 NOSIGFE
+_f_log10f NOSIGFE
+__f_log10f = _f_log10f NOSIGFE
+_f_logf NOSIGFE
+__f_logf = _f_logf NOSIGFE
+_f_pow NOSIGFE
+__f_pow = _f_pow NOSIGFE
+_f_powf NOSIGFE
+__f_powf = _f_powf NOSIGFE
+_f_tan NOSIGFE
+__f_tan = _f_tan NOSIGFE
+_f_tanf NOSIGFE
+__f_tanf = _f_tanf NOSIGFE
+fabs NOSIGFE
+_fabs = fabs NOSIGFE
+fabsf NOSIGFE
+_fabsf = fabsf NOSIGFE
+facl SIGFE
+_facl = facl SIGFE
+_facl32 = facl32 SIGFE
+fchdir SIGFE
+_fchdir = fchdir SIGFE
+fchmod SIGFE
+_fchmod = fchmod SIGFE
+fchown SIGFE
+_fchown = fchown SIGFE
+_fchown32 = fchown32 SIGFE
+fclose SIGFE
+_fclose = fclose SIGFE
+fcloseall SIGFE
+_fcloseall = fcloseall SIGFE
+fcloseall_r = _fcloseall_r SIGFE
+_fcloseall_r SIGFE
+fcntl SIGFE
+_fcntl = fcntl SIGFE
+_fcntl64 = fcntl64 SIGFE
+fcvt SIGFE
+_fcvt = fcvt SIGFE
+fcvtbuf SIGFE
+_fcvtbuf = fcvtbuf SIGFE
+fcvtf SIGFE
+_fcvtf = fcvtf SIGFE
+fdatasync SIGFE
+fdim NOSIGFE
+fdimf NOSIGFE
+fdopen SIGFE
+_fdopen = fdopen SIGFE
+_fdopen64 = fdopen64 SIGFE
+feof SIGFE
+_feof = feof SIGFE
+ferror SIGFE
+_ferror = ferror SIGFE
+fflush SIGFE
+_fflush = fflush SIGFE
+ffs NOSIGFE
+_ffs = ffs NOSIGFE
+fgetc SIGFE
+_fgetc = fgetc SIGFE
+fgetpos SIGFE
+_fgetpos = fgetpos SIGFE
+_fgetpos64 = fgetpos64 SIGFE
+fgets SIGFE
+_fgets = fgets SIGFE
+fileno SIGFE
+_fileno = fileno SIGFE
+finite NOSIGFE
+_finite = finite NOSIGFE
+finitef NOSIGFE
+_finitef = finitef NOSIGFE
+fiprintf SIGFE
+_fiprintf = fiprintf SIGFE
+flock SIGFE
+flockfile SIGFE
+floor NOSIGFE
+_floor = floor NOSIGFE
+floorf NOSIGFE
+_floorf = floorf NOSIGFE
+fma NOSIGFE
+fmaf NOSIGFE
+fmax NOSIGFE
+fmaxf NOSIGFE
+fmin NOSIGFE
+fminf NOSIGFE
+fmod NOSIGFE
+_fmod = fmod NOSIGFE
+fmodf NOSIGFE
+_fmodf = fmodf NOSIGFE
+fnmatch NOSIGFE
+_fnmatch = fnmatch NOSIGFE
+fopen SIGFE
+_fopen = fopen SIGFE
+_fopen64 = fopen64 SIGFE
+fork SIGFE
+_fork = fork SIGFE
+forkpty SIGFE
+fpathconf SIGFE
+__fpclassifyd NOSIGFE
+__fpclassifyf NOSIGFE
+fprintf SIGFE
+_fprintf = fprintf SIGFE
+fputc SIGFE
+_fputc = fputc SIGFE
+fputs SIGFE
+_fputs = fputs SIGFE
+fread SIGFE
+_fread = fread SIGFE
+free SIGFE
+_free = free SIGFE
+freeaddrinfo = cygwin_freeaddrinfo SIGFE
+freopen SIGFE
+_freopen = freopen SIGFE
+_freopen64 = freopen64 SIGFE
+frexp NOSIGFE
+_frexp = frexp NOSIGFE
+frexpf NOSIGFE
+_frexpf = frexpf NOSIGFE
+fscanf SIGFE
+_fscanf = fscanf SIGFE
+fscanf_r = _fscanf_r SIGFE
+_fscanf_r SIGFE
+fseek SIGFE
+_fseek = fseek SIGFE
+fseeko SIGFE
+_fseeko = fseeko SIGFE
+_fseeko64 = fseeko64 SIGFE
+fsetpos SIGFE
+_fsetpos = fsetpos SIGFE
+_fsetpos64 = fsetpos64 SIGFE
+fstat SIGFE
+_fstat = fstat SIGFE
+_fstat64 = fstat64 SIGFE
+fstatfs SIGFE
+_fstatfs = fstatfs SIGFE
+fstatvfs SIGFE
+fsync SIGFE
+_fsync = fsync SIGFE
+ftell SIGFE
+_ftell = ftell SIGFE
+ftello SIGFE
+_ftello = ftello SIGFE
+_ftello64 = ftello64 SIGFE
+ftime SIGFE
+_ftime = ftime SIGFE
+ftok SIGFE
+_ftok = ftok SIGFE
+ftruncate SIGFE
+_ftruncate = ftruncate SIGFE
+_ftruncate64 = ftruncate64 SIGFE
+ftrylockfile SIGFE
+fts_children SIGFE
+fts_close SIGFE
+fts_get_clientptr NOSIGFE
+fts_get_stream NOSIGFE
+fts_open SIGFE
+fts_read SIGFE
+fts_set NOSIGFE
+fts_set_clientptr NOSIGFE
+ftw SIGFE
+funlockfile SIGFE
+futimes SIGFE
+fwrite SIGFE
+_fwrite = fwrite SIGFE
+gai_strerror = cygwin_gai_strerror NOSIGFE
+gamma NOSIGFE
+_gamma = gamma NOSIGFE
+gamma_r NOSIGFE
+_gamma_r = gamma_r NOSIGFE
+gammaf NOSIGFE
+_gammaf = gammaf NOSIGFE
+gammaf_r NOSIGFE
+_gammaf_r = gammaf_r NOSIGFE
+gcvt SIGFE
+_gcvt = gcvt SIGFE
+gcvtf SIGFE
+_gcvtf = gcvtf SIGFE
+get_osfhandle SIGFE
+_get_osfhandle = get_osfhandle SIGFE
+getaddrinfo = cygwin_getaddrinfo SIGFE
+getc SIGFE
+_getc = getc SIGFE
+getc_unlocked SIGFE
+_getc_unlocked = getc_unlocked SIGFE
+getchar SIGFE
+_getchar = getchar SIGFE
+getchar_unlocked SIGFE
+_getchar_unlocked = getchar_unlocked SIGFE
+getcwd SIGFE
+_getcwd = getcwd SIGFE
+getdelim = __getdelim SIGFE
+__getdelim SIGFE
+getdomainname SIGFE
+_getdomainname = getdomainname SIGFE
+getdtablesize NOSIGFE
+_getdtablesize = getdtablesize NOSIGFE
+getegid NOSIGFE
+_getegid = getegid NOSIGFE
+_getegid32 = getegid32 NOSIGFE
+getenv NOSIGFE
+_getenv = getenv NOSIGFE
+geteuid NOSIGFE
+_geteuid = geteuid NOSIGFE
+_geteuid32 = geteuid32 NOSIGFE
+getgid NOSIGFE
+_getgid = getgid NOSIGFE
+_getgid32 = getgid32 NOSIGFE
+getgrent SIGFE
+_getgrent = getgrent SIGFE
+_getgrent32 = getgrent32 SIGFE
+getgrgid SIGFE
+_getgrgid = getgrgid SIGFE
+_getgrgid32 = getgrgid32 SIGFE
+getgrgid_r SIGFE
+getgrnam SIGFE
+_getgrnam = getgrnam SIGFE
+_getgrnam32 = getgrnam32 SIGFE
+getgrnam_r SIGFE
+getgroups SIGFE
+_getgroups = getgroups SIGFE
+_getgroups32 = getgroups32 SIGFE
+gethostbyaddr = cygwin_gethostbyaddr SIGFE
+gethostbyname = cygwin_gethostbyname SIGFE
+gethostid SIGFE
+gethostname = cygwin_gethostname SIGFE
+_gethostname = cygwin_gethostname SIGFE
+getitimer SIGFE
+getline = __getline SIGFE
+__getline SIGFE
+getlogin NOSIGFE
+_getlogin = getlogin NOSIGFE
+getlogin_r NOSIGFE
+getmntent SIGFE
+_getmntent = getmntent SIGFE
+getmode SIGFE
+_getmode = getmode SIGFE
+getnameinfo = cygwin_getnameinfo SIGFE
+getopt SIGFE
+getopt_long SIGFE
+getopt_long_only SIGFE
+getpagesize SIGFE
+_getpagesize = getpagesize SIGFE
+getpass SIGFE
+_getpass = getpass SIGFE
+getpeereid SIGFE
+getpeername = cygwin_getpeername SIGFE
+getpgid SIGFE
+getpgrp SIGFE
+_getpgrp = getpgrp SIGFE
+getpid NOSIGFE
+_getpid = getpid NOSIGFE
+getppid NOSIGFE
+_getppid = getppid NOSIGFE
+getpriority SIGFE
+getprogname NOSIGFE
+getprotobyname = cygwin_getprotobyname SIGFE
+getprotobynumber = cygwin_getprotobynumber SIGFE
+getprotoent = cygwin_getprotoent SIGFE
+getpwduid NOSIGFE
+_getpwduid = getpwduid NOSIGFE
+getpwent SIGFE
+_getpwent = getpwent SIGFE
+getpwnam SIGFE
+_getpwnam = getpwnam SIGFE
+getpwnam_r SIGFE
+getpwuid SIGFE
+_getpwuid = getpwuid SIGFE
+_getpwuid32 = getpwuid32 SIGFE
+getpwuid_r SIGFE
+_getpwuid_r32 = getpwuid_r32 SIGFE
+__getreent NOSIGFE
+getrlimit SIGFE
+_getrlimit = getrlimit SIGFE
+getrusage SIGFE
+_getrusage = getrusage SIGFE
+gets SIGFE
+_gets = gets SIGFE
+getservbyname = cygwin_getservbyname SIGFE
+getservbyport = cygwin_getservbyport SIGFE
+getservent = cygwin_getservent SIGFE
+getsid SIGFE
+getsockname = cygwin_getsockname SIGFE
+getsockopt = cygwin_getsockopt SIGFE
+getsubopt NOSIGFE
+gettimeofday SIGFE
+_gettimeofday = gettimeofday SIGFE
+getuid NOSIGFE
+_getuid = getuid NOSIGFE
+_getuid32 = getuid32 NOSIGFE
+getusershell SIGFE
+getutent SIGFE
+_getutent = getutent SIGFE
+getutid SIGFE
+_getutid = getutid SIGFE
+getutline SIGFE
+_getutline = getutline SIGFE
+getutxent SIGFE
+getutxid SIGFE
+getutxline SIGFE
+getw SIGFE
+_getw = getw SIGFE
+getwd SIGFE
+_getwd = getwd SIGFE
+glob SIGFE
+_glob = glob SIGFE
+globfree SIGFE
+_globfree = globfree SIGFE
+gmtime SIGFE
+_gmtime = gmtime SIGFE
+gmtime_r SIGFE
+_gmtime_r = gmtime_r SIGFE
+grantpt NOSIGFE
+hcreate SIGFE
+hcreate_r SIGFE
+hdestroy SIGFE
+hdestroy_r SIGFE
+herror = cygwin_herror SIGFE
+hsearch SIGFE
+hsearch_r SIGFE
+hstrerror = cygwin_hstrerror NOSIGFE
+htonl NOSIGFE
+_htonl = htonl NOSIGFE
+htons NOSIGFE
+_htons = htons NOSIGFE
+hypot NOSIGFE
+_hypot = hypot NOSIGFE
+hypotf NOSIGFE
+_hypotf = hypotf NOSIGFE
+ilogb NOSIGFE
+_ilogb = ilogb NOSIGFE
+ilogbf NOSIGFE
+_ilogbf = ilogbf NOSIGFE
+imaxabs = llabs NOSIGFE
+imaxdiv = lldiv NOSIGFE
+index NOSIGFE
+_index = index NOSIGFE
+inet_addr = cygwin_inet_addr SIGFE
+inet_aton = cygwin_inet_aton SIGFE
+inet_makeaddr NOSIGFE
+inet_netof NOSIGFE
+inet_network = cygwin_inet_network SIGFE
+inet_ntoa = cygwin_inet_ntoa SIGFE
+inet_ntop = cygwin_inet_ntop SIGFE
+inet_pton = cygwin_inet_pton SIGFE
+infinity NOSIGFE
+_infinity = infinity NOSIGFE
+__infinity NOSIGFE
+infinityf NOSIGFE
+_infinityf = infinityf NOSIGFE
+initgroups SIGFE
+_initgroups32 = initgroups32 SIGFE
+initstate NOSIGFE
+ioctl SIGFE
+_ioctl = ioctl SIGFE
+iprintf SIGFE
+_iprintf = iprintf SIGFE
+iruserok SIGFE
+isalnum NOSIGFE
+_isalnum = isalnum NOSIGFE
+isalpha NOSIGFE
+_isalpha = isalpha NOSIGFE
+isascii NOSIGFE
+_isascii = isascii NOSIGFE
+isatty SIGFE
+_isatty = isatty SIGFE
+isblank NOSIGFE
+iscntrl NOSIGFE
+_iscntrl = iscntrl NOSIGFE
+isdigit NOSIGFE
+_isdigit = isdigit NOSIGFE
+isgraph NOSIGFE
+_isgraph = isgraph NOSIGFE
+isinf NOSIGFE
+_isinf = isinf NOSIGFE
+__isinfd NOSIGFE
+isinff NOSIGFE
+_isinff = isinff NOSIGFE
+__isinff NOSIGFE
+islower NOSIGFE
+_islower = islower NOSIGFE
+isnan NOSIGFE
+_isnan = isnan NOSIGFE
+__isnand NOSIGFE
+isnanf NOSIGFE
+_isnanf = isnanf NOSIGFE
+__isnanf NOSIGFE
+isprint NOSIGFE
+_isprint = isprint NOSIGFE
+ispunct NOSIGFE
+_ispunct = ispunct NOSIGFE
+isspace NOSIGFE
+_isspace = isspace NOSIGFE
+isupper NOSIGFE
+_isupper = isupper NOSIGFE
+iswalnum NOSIGFE
+iswalpha NOSIGFE
+iswblank NOSIGFE
+iswcntrl NOSIGFE
+iswctype NOSIGFE
+iswdigit NOSIGFE
+iswgraph NOSIGFE
+iswlower NOSIGFE
+iswprint NOSIGFE
+iswpunct NOSIGFE
+iswspace NOSIGFE
+iswupper NOSIGFE
+iswxdigit NOSIGFE
+isxdigit NOSIGFE
+_isxdigit = isxdigit NOSIGFE
+j0 NOSIGFE
+_j0 = j0 NOSIGFE
+j0f NOSIGFE
+_j0f = j0f NOSIGFE
+j1 NOSIGFE
+_j1 = j1 NOSIGFE
+j1f NOSIGFE
+_j1f = j1f NOSIGFE
+jn NOSIGFE
+_jn = jn NOSIGFE
+jnf NOSIGFE
+_jnf = jnf NOSIGFE
+jrand48 NOSIGFE
+_jrand48 = jrand48 NOSIGFE
+kill SIGFE
+_kill = kill SIGFE
+killpg SIGFE
+l64a NOSIGFE
+labs NOSIGFE
+_labs = labs NOSIGFE
+lacl SIGFE
+_lacl = lacl SIGFE
+lchown SIGFE
+_lchown = lchown SIGFE
+_lchown32 = lchown32 SIGFE
+lcong48 NOSIGFE
+_lcong48 = lcong48 NOSIGFE
+ldexp NOSIGFE
+_ldexp = ldexp NOSIGFE
+ldexpf NOSIGFE
+_ldexpf = ldexpf NOSIGFE
+ldiv NOSIGFE
+_ldiv = ldiv NOSIGFE
+lfind NOSIGFE
+lgamma NOSIGFE
+_lgamma = lgamma NOSIGFE
+lgamma_r NOSIGFE
+_lgamma_r = lgamma_r NOSIGFE
+lgammaf NOSIGFE
+_lgammaf = lgammaf NOSIGFE
+lgammaf_r NOSIGFE
+_lgammaf_r = lgammaf_r NOSIGFE
+link SIGFE
+_link = link SIGFE
+listen = cygwin_listen SIGFE
+llabs NOSIGFE
+lldiv NOSIGFE
+localeconv NOSIGFE
+_localeconv = localeconv NOSIGFE
+localtime SIGFE
+_localtime = localtime SIGFE
+localtime_r SIGFE
+_localtime_r = localtime_r SIGFE
+log NOSIGFE
+_log = log NOSIGFE
+log10 NOSIGFE
+_log10 = log10 NOSIGFE
+log10f NOSIGFE
+_log10f = log10f NOSIGFE
+log1p NOSIGFE
+_log1p = log1p NOSIGFE
+log1pf NOSIGFE
+_log1pf = log1pf NOSIGFE
+logb NOSIGFE
+_logb = logb NOSIGFE
+logbf NOSIGFE
+_logbf = logbf NOSIGFE
+logf NOSIGFE
+_logf = logf NOSIGFE
+login SIGFE
+login_tty SIGFE
+logout SIGFE
+logwtmp SIGFE
+longjmp NOSIGFE
+_longjmp = longjmp NOSIGFE
+lrand48 NOSIGFE
+_lrand48 = lrand48 NOSIGFE
+lrint NOSIGFE
+lrintf NOSIGFE
+lround NOSIGFE
+lroundf NOSIGFE
+lsearch NOSIGFE
+lseek SIGFE
+_lseek = lseek SIGFE
+_lseek64 = lseek64 SIGFE
+lstat SIGFE
+_lstat = lstat SIGFE
+_lstat64 = lstat64 SIGFE
+lutimes SIGFE
+__main NOSIGFE
+mallinfo SIGFE
+malloc SIGFE
+_malloc = malloc SIGFE
+malloc_stats SIGFE
+malloc_trim SIGFE
+malloc_usable_size SIGFE
+mallopt SIGFE
+matherr NOSIGFE
+_matherr = matherr NOSIGFE
+mblen NOSIGFE
+_mblen = mblen NOSIGFE
+mbrlen NOSIGFE
+mbrtowc NOSIGFE
+mbsinit NOSIGFE
+mbsrtowcs NOSIGFE
+mbstowcs NOSIGFE
+_mbstowcs = mbstowcs NOSIGFE
+mbtowc NOSIGFE
+_mbtowc = mbtowc NOSIGFE
+memalign SIGFE
+memccpy NOSIGFE
+_memccpy = memccpy NOSIGFE
+memchr NOSIGFE
+_memchr = memchr NOSIGFE
+memcmp NOSIGFE
+_memcmp = memcmp NOSIGFE
+memcpy NOSIGFE
+_memcpy = memcpy NOSIGFE
+memmem NOSIGFE
+memmove NOSIGFE
+_memmove = memmove NOSIGFE
+mempcpy NOSIGFE
+__mempcpy = mempcpy NOSIGFE
+memset NOSIGFE
+_memset = memset NOSIGFE
+mkdir SIGFE
+_mkdir = mkdir SIGFE
+mkdtemp SIGFE
+mkfifo SIGFE
+mknod SIGFE
+_mknod = mknod SIGFE
+_mknod32 = mknod32 SIGFE
+mkstemp SIGFE
+_mkstemp = mkstemp SIGFE
+mktemp SIGFE
+_mktemp = mktemp SIGFE
+mktime SIGFE
+_mktime = mktime SIGFE
+mlock SIGFE
+mmap SIGFE
+_mmap64 = mmap64 SIGFE
+modf NOSIGFE
+_modf = modf NOSIGFE
+modff NOSIGFE
+_modff = modff NOSIGFE
+mount SIGFE
+_mount = mount SIGFE
+mprotect SIGFE
+mrand48 NOSIGFE
+msgctl SIGFE
+msgget SIGFE
+msgrcv SIGFE
+msgsnd SIGFE
+msync SIGFE
+munlock SIGFE
+munmap SIGFE
+nan NOSIGFE
+_nan = nan NOSIGFE
+nanf NOSIGFE
+_nanf = nanf NOSIGFE
+nanosleep SIGFE
+_nanosleep = nanosleep SIGFE
+nearbyint NOSIGFE
+nearbyintf NOSIGFE
+nextafter NOSIGFE
+_nextafter = nextafter NOSIGFE
+nextafterf NOSIGFE
+_nextafterf = nextafterf NOSIGFE
+nftw SIGFE
+nice SIGFE
+_nice = nice SIGFE
+nl_langinfo SIGFE
+_nl_langinfo = nl_langinfo SIGFE
+nrand48 NOSIGFE
+_nrand48 = nrand48 NOSIGFE
+ntohl NOSIGFE
+_ntohl = ntohl NOSIGFE
+ntohs NOSIGFE
+_ntohs = ntohs NOSIGFE
+on_exit SIGFE
+open SIGFE
+_open = open SIGFE
+_open64
+opendir SIGFE
+__opendir_with_d_ino SIGFE
+openlog SIGFE
+_openlog = openlog SIGFE
+openpty SIGFE
+pathconf SIGFE
+_pathconf = pathconf SIGFE
+pause SIGFE
+pclose SIGFE
+_pclose = pclose SIGFE
+perror SIGFE
+_perror = perror SIGFE
+pipe SIGFE
+_pipe SIGFE
+poll SIGFE
+_poll = poll SIGFE
+popen SIGFE
+_popen = popen SIGFE
+posix_regcomp SIGFE
+posix_regerror SIGFE
+posix_regexec SIGFE
+posix_regfree SIGFE
+pow NOSIGFE
+_pow = pow NOSIGFE
+powf NOSIGFE
+_powf = powf NOSIGFE
+pread SIGFE
+printf SIGFE
+_printf = printf SIGFE
+pselect SIGFE
+pthread_atfork SIGFE
+pthread_attr_destroy SIGFE
+pthread_attr_getdetachstate SIGFE
+pthread_attr_getinheritsched SIGFE
+pthread_attr_getschedparam SIGFE
+pthread_attr_getschedpolicy SIGFE
+pthread_attr_getscope SIGFE
+pthread_attr_getstacksize SIGFE
+pthread_attr_init SIGFE
+pthread_attr_setdetachstate SIGFE
+pthread_attr_setinheritsched SIGFE
+pthread_attr_setschedparam SIGFE
+pthread_attr_setschedpolicy SIGFE
+pthread_attr_setscope SIGFE
+pthread_attr_setstacksize SIGFE
+pthread_cancel SIGFE
+_pthread_cleanup_pop SIGFE
+_pthread_cleanup_push SIGFE
+pthread_cond_broadcast SIGFE
+pthread_cond_destroy SIGFE
+pthread_cond_init SIGFE
+pthread_cond_signal SIGFE
+pthread_cond_timedwait SIGFE
+pthread_cond_wait SIGFE
+pthread_condattr_destroy SIGFE
+pthread_condattr_getpshared SIGFE
+pthread_condattr_init SIGFE
+pthread_condattr_setpshared SIGFE
+pthread_continue SIGFE
+pthread_create SIGFE
+pthread_detach SIGFE
+pthread_equal SIGFE
+pthread_exit SIGFE
+pthread_getconcurrency SIGFE
+pthread_getschedparam SIGFE
+pthread_getsequence_np SIGFE
+pthread_getspecific SIGFE
+pthread_join SIGFE
+pthread_key_create SIGFE
+pthread_key_delete SIGFE
+pthread_kill SIGFE
+pthread_mutex_destroy SIGFE
+pthread_mutex_getprioceiling SIGFE
+pthread_mutex_init SIGFE
+pthread_mutex_lock SIGFE
+pthread_mutex_setprioceiling SIGFE
+pthread_mutex_trylock SIGFE
+pthread_mutex_unlock SIGFE
+pthread_mutexattr_destroy SIGFE
+pthread_mutexattr_getprioceiling SIGFE
+pthread_mutexattr_getprotocol SIGFE
+pthread_mutexattr_getpshared SIGFE
+pthread_mutexattr_gettype SIGFE
+pthread_mutexattr_init SIGFE
+pthread_mutexattr_setprioceiling SIGFE
+pthread_mutexattr_setprotocol SIGFE
+pthread_mutexattr_setpshared SIGFE
+pthread_mutexattr_settype SIGFE
+pthread_once SIGFE
+pthread_rwlock_destroy SIGFE
+pthread_rwlock_init SIGFE
+pthread_rwlock_rdlock SIGFE
+pthread_rwlock_tryrdlock SIGFE
+pthread_rwlock_trywrlock SIGFE
+pthread_rwlock_unlock SIGFE
+pthread_rwlock_wrlock SIGFE
+pthread_rwlockattr_destroy SIGFE
+pthread_rwlockattr_getpshared SIGFE
+pthread_rwlockattr_init SIGFE
+pthread_rwlockattr_setpshared SIGFE
+pthread_self SIGFE
+pthread_setcancelstate SIGFE
+pthread_setcanceltype SIGFE
+pthread_setconcurrency SIGFE
+pthread_setschedparam SIGFE
+pthread_setspecific SIGFE
+pthread_sigmask SIGFE
+pthread_suspend SIGFE
+pthread_testcancel SIGFE
+ptsname SIGFE
+putc SIGFE
+_putc = putc SIGFE
+putc_unlocked SIGFE
+_putc_unlocked = putc_unlocked SIGFE
+putchar SIGFE
+_putchar = putchar SIGFE
+putchar_unlocked SIGFE
+_putchar_unlocked = putchar_unlocked SIGFE
+putenv SIGFE
+_putenv = putenv SIGFE
+puts SIGFE
+_puts = puts SIGFE
+pututline SIGFE
+_pututline = pututline SIGFE
+pututxline SIGFE
+putw SIGFE
+_putw = putw SIGFE
+pwrite SIGFE
+qsort NOSIGFE
+_qsort = qsort NOSIGFE
+raise SIGFE
+_raise = raise SIGFE
+rand NOSIGFE
+_rand = rand NOSIGFE
+rand_r NOSIGFE
+random NOSIGFE
+rcmd = cygwin_rcmd SIGFE
+read SIGFE
+_read = read SIGFE
+readdir SIGFE
+_readdir = readdir SIGFE
+readdir_r SIGFE
+readlink SIGFE
+_readlink = readlink SIGFE
+readv SIGFE
+_readv = readv SIGFE
+realloc SIGFE
+_realloc = realloc SIGFE
+realpath SIGFE
+recv = cygwin_recv SIGFE
+recvfrom = cygwin_recvfrom SIGFE
+recvmsg = cygwin_recvmsg SIGFE
+remainder NOSIGFE
+_remainder = remainder NOSIGFE
+remainderf NOSIGFE
+_remainderf = remainderf NOSIGFE
+remove SIGFE
+_remove = remove SIGFE
+remquo NOSIGFE
+remquof NOSIGFE
+rename SIGFE
+_rename = rename SIGFE
+revoke SIGFE
+rewind SIGFE
+_rewind = rewind SIGFE
+rewinddir SIGFE
+_rewinddir = rewinddir SIGFE
+rexec = cygwin_rexec SIGFE
+rindex NOSIGFE
+_rindex = rindex NOSIGFE
+rint NOSIGFE
+_rint = rint NOSIGFE
+rintf NOSIGFE
+_rintf = rintf NOSIGFE
+rmdir SIGFE
+_rmdir = rmdir SIGFE
+round NOSIGFE
+roundf NOSIGFE
+rresvport = cygwin_rresvport SIGFE
+ruserok SIGFE
+sbrk SIGFE
+_sbrk = sbrk SIGFE
+scalb NOSIGFE
+_scalb = scalb NOSIGFE
+scalbf NOSIGFE
+_scalbf = scalbf NOSIGFE
+scalbln NOSIGFE
+scalblnf NOSIGFE
+scalbn NOSIGFE
+_scalbn = scalbn NOSIGFE
+scalbnf NOSIGFE
+_scalbnf = scalbnf NOSIGFE
+scandir SIGFE
+_scandir = scandir SIGFE
+scanf SIGFE
+_scanf = scanf SIGFE
+scanf_r = _scanf_r SIGFE
+_scanf_r SIGFE
+sched_get_priority_max SIGFE
+sched_get_priority_min SIGFE
+sched_getparam SIGFE
+sched_getscheduler NOSIGFE
+sched_rr_get_interval SIGFE
+sched_setparam SIGFE
+sched_setscheduler SIGFE
+sched_yield SIGFE
+seed48 NOSIGFE
+_seed48 = seed48 NOSIGFE
+seekdir SIGFE
+_seekdir = seekdir SIGFE
+_seekdir64 = seekdir64 SIGFE
+select = cygwin_select SIGFE
+_select = cygwin_select SIGFE
+sem_close SIGFE
+sem_destroy SIGFE
+sem_getvalue SIGFE
+sem_init SIGFE
+sem_open SIGFE
+sem_post SIGFE
+sem_timedwait SIGFE
+sem_trywait SIGFE
+sem_wait SIGFE
+semctl SIGFE
+semget SIGFE
+semop SIGFE
+send = cygwin_send SIGFE
+sendmsg = cygwin_sendmsg SIGFE
+sendto = cygwin_sendto SIGFE
+setbuf SIGFE
+_setbuf = setbuf SIGFE
+setbuffer SIGFE
+setdtablesize SIGFE
+_setdtablesize = setdtablesize SIGFE
+setegid SIGFE
+_setegid = setegid SIGFE
+_setegid32 = setegid32 SIGFE
+setenv SIGFE
+_setenv = setenv SIGFE
+seteuid SIGFE
+_seteuid = seteuid SIGFE
+_seteuid32 = seteuid32 SIGFE
+setgid SIGFE
+_setgid = setgid SIGFE
+_setgid32 = setgid32 SIGFE
+setgrent NOSIGFE
+_setgrent = setgrent NOSIGFE
+setgroups SIGFE
+_setgroups = setgroups SIGFE
+_setgroups32 = setgroups32 SIGFE
+sethostent NOSIGFE
+setitimer SIGFE
+setjmp NOSIGFE
+_setjmp = setjmp NOSIGFE
+setlinebuf SIGFE
+setlocale NOSIGFE
+_setlocale = setlocale NOSIGFE
+setlogmask NOSIGFE
+setmntent SIGFE
+_setmntent = setmntent SIGFE
+setmode = cygwin_setmode SIGFE
+_setmode = cygwin_setmode SIGFE
+setpassent NOSIGFE
+_setpassent = setpassent NOSIGFE
+setpgid SIGFE
+_setpgid = setpgid SIGFE
+setpgrp SIGFE
+_setpgrp = setpgrp SIGFE
+setpriority SIGFE
+setprogname NOSIGFE
+setprotoent = cygwin_setprotoent SIGFE
+setpwent NOSIGFE
+_setpwent = setpwent NOSIGFE
+setregid SIGFE
+_setregid = setregid SIGFE
+setregid32 SIGFE
+_setregid32 = setregid32 SIGFE
+setreuid SIGFE
+_setreuid = setreuid SIGFE
+setreuid32 SIGFE
+_setreuid32 = setreuid32 SIGFE
+setrlimit SIGFE
+_setrlimit = setrlimit SIGFE
+setservent = cygwin_setservent SIGFE
+setsid SIGFE
+_setsid = setsid SIGFE
+setsockopt = cygwin_setsockopt SIGFE
+setstate NOSIGFE
+settimeofday SIGFE
+_settimeofday = settimeofday SIGFE
+setuid SIGFE
+_setuid = setuid SIGFE
+_setuid32 = setuid32 SIGFE
+setusershell SIGFE
+setutent SIGFE
+_setutent = setutent SIGFE
+setutxent SIGFE
+setvbuf SIGFE
+_setvbuf = setvbuf SIGFE
+sexecl = sexecve_is_bad SIGFE
+sexecle = sexecve_is_bad SIGFE
+sexeclp = sexecve_is_bad SIGFE
+sexeclpe = sexecve_is_bad SIGFE
+sexecp = sexecve_is_bad SIGFE
+sexecv = sexecve_is_bad SIGFE
+sexecve = sexecve_is_bad SIGFE
+sexecvpe = sexecve_is_bad SIGFE
+shmat SIGFE
+shmctl SIGFE
+shmdt SIGFE
+shmget SIGFE
+shutdown = cygwin_shutdown SIGFE
+sigaction SIGFE
+sigaddset SIGFE
+sigdelset SIGFE
+sigemptyset NOSIGFE
+sigfillset NOSIGFE
+sighold SIGFE
+sigignore SIGFE
+siginterrupt SIGFE
+sigismember SIGFE
+signal SIGFE
+__signbitd NOSIGFE
+__signbitf NOSIGFE
+__signgam NOSIGFE
+significand NOSIGFE
+significandf NOSIGFE
+sigpause SIGFE
+sigpending SIGFE
+sigprocmask SIGFE
+sigqueue SIGFE
+sigrelse SIGFE
+sigset SIGFE
+sigsuspend SIGFE
+sigwait SIGFE
+sigwaitinfo SIGFE
+sin NOSIGFE
+_sin = sin NOSIGFE
+sincos NOSIGFE
+sincosf NOSIGFE
+sinf NOSIGFE
+_sinf = sinf NOSIGFE
+sinh NOSIGFE
+_sinh = sinh NOSIGFE
+sinhf NOSIGFE
+_sinhf = sinhf NOSIGFE
+siprintf SIGFE
+_siprintf = siprintf SIGFE
+sleep SIGFE
+_sleep = sleep SIGFE
+snprintf SIGFE
+_snprintf = snprintf SIGFE
+socket = cygwin_socket SIGFE
+socketpair SIGFE
+spawnl SIGFE
+_spawnl = spawnl SIGFE
+spawnle SIGFE
+_spawnle = spawnle SIGFE
+spawnlp SIGFE
+_spawnlp = spawnlp SIGFE
+spawnlpe SIGFE
+_spawnlpe = spawnlpe SIGFE
+spawnv SIGFE
+_spawnv = spawnv SIGFE
+spawnve SIGFE
+_spawnve = spawnve SIGFE
+spawnvp SIGFE
+_spawnvp = spawnvp SIGFE
+spawnvpe SIGFE
+_spawnvpe = spawnvpe SIGFE
+sprintf SIGFE
+_sprintf = sprintf SIGFE
+sqrt NOSIGFE
+_sqrt = sqrt NOSIGFE
+sqrtf NOSIGFE
+_sqrtf = sqrtf NOSIGFE
+srand NOSIGFE
+_srand = srand NOSIGFE
+srand48 NOSIGFE
+_srand48 = srand48 NOSIGFE
+srandom NOSIGFE
+__srget SIGFE
+__srget_r SIGFE
+sscanf SIGFE
+_sscanf = sscanf SIGFE
+sscanf_r = _sscanf_r SIGFE
+_sscanf_r SIGFE
+stat SIGFE
+_stat = stat SIGFE
+_stat64 = stat64 SIGFE
+statfs SIGFE
+_statfs = statfs SIGFE
+statvfs SIGFE
+strcasecmp NOSIGFE
+_strcasecmp = strcasecmp NOSIGFE
+strcat NOSIGFE
+_strcat = strcat NOSIGFE
+strchr NOSIGFE
+_strchr = strchr NOSIGFE
+strcmp NOSIGFE
+_strcmp = strcmp NOSIGFE
+strcoll NOSIGFE
+_strcoll = strcoll NOSIGFE
+strcpy NOSIGFE
+_strcpy = strcpy NOSIGFE
+strcspn NOSIGFE
+_strcspn = strcspn NOSIGFE
+strdup SIGFE
+_strdup = strdup SIGFE
+strerror SIGFE
+_strerror = strerror SIGFE
+strerror_r SIGFE
+_strerror_r = strerror_r SIGFE
+strftime SIGFE
+_strftime = strftime SIGFE
+strlcat NOSIGFE
+_strlcat = strlcat NOSIGFE
+strlcpy NOSIGFE
+_strlcpy = strlcpy NOSIGFE
+strlen NOSIGFE
+_strlen = strlen NOSIGFE
+strlwr NOSIGFE
+_strlwr = strlwr NOSIGFE
+strncasecmp NOSIGFE
+_strncasecmp = strncasecmp NOSIGFE
+strncat NOSIGFE
+_strncat = strncat NOSIGFE
+strncmp NOSIGFE
+_strncmp = strncmp NOSIGFE
+strncpy NOSIGFE
+_strncpy = strncpy NOSIGFE
+strndup SIGFE
+strnlen NOSIGFE
+strpbrk NOSIGFE
+_strpbrk = strpbrk NOSIGFE
+strptime SIGFE
+_strptime = strptime SIGFE
+strrchr NOSIGFE
+_strrchr = strrchr NOSIGFE
+strsep NOSIGFE
+_strsep = strsep NOSIGFE
+strsignal SIGFE
+strspn NOSIGFE
+_strspn = strspn NOSIGFE
+strstr NOSIGFE
+_strstr = strstr NOSIGFE
+strtod SIGFE
+_strtod = strtod SIGFE
+strtodf = strtof SIGFE
+_strtodf = strtof SIGFE
+strtof SIGFE
+strtoimax = strtoll NOSIGFE
+strtok NOSIGFE
+_strtok = strtok NOSIGFE
+strtok_r NOSIGFE
+_strtok_r = strtok_r NOSIGFE
+strtol NOSIGFE
+_strtol = strtol NOSIGFE
+_strtold SIGFE
+strtoll NOSIGFE
+_strtoll = strtoll NOSIGFE
+strtosigno NOSIGFE
+strtoul NOSIGFE
+_strtoul = strtoul NOSIGFE
+strtoull NOSIGFE
+_strtoull = strtoull NOSIGFE
+strtoumax = strtoull NOSIGFE
+strupr NOSIGFE
+_strupr = strupr NOSIGFE
+strxfrm NOSIGFE
+_strxfrm = strxfrm NOSIGFE
+swab NOSIGFE
+_swab = swab NOSIGFE
+__swbuf SIGFE
+__swbuf_r SIGFE
+symlink SIGFE
+_symlink = symlink SIGFE
+sync SIGFE
+sysconf SIGFE
+_sysconf = sysconf SIGFE
+syslog SIGFE
+_syslog = syslog SIGFE
+system SIGFE
+_system = system SIGFE
+tan NOSIGFE
+_tan = tan NOSIGFE
+tanf NOSIGFE
+_tanf = tanf NOSIGFE
+tanh NOSIGFE
+_tanh = tanh NOSIGFE
+tanhf NOSIGFE
+_tanhf = tanhf NOSIGFE
+tcdrain SIGFE
+_tcdrain = tcdrain SIGFE
+tcflow SIGFE
+_tcflow = tcflow SIGFE
+tcflush SIGFE
+_tcflush = tcflush SIGFE
+tcgetattr SIGFE
+_tcgetattr = tcgetattr SIGFE
+tcgetpgrp SIGFE
+_tcgetpgrp = tcgetpgrp SIGFE
+tcsendbreak SIGFE
+_tcsendbreak = tcsendbreak SIGFE
+tcsetattr SIGFE
+_tcsetattr = tcsetattr SIGFE
+tcsetpgrp SIGFE
+_tcsetpgrp = tcsetpgrp SIGFE
+tdelete SIGFE
+tdestroy NOSIGFE
+telldir SIGFE
+_telldir = telldir SIGFE
+_telldir64 = telldir64 SIGFE
+tempnam SIGFE
+_tempnam = tempnam SIGFE
+tfind NOSIGFE
+tgamma NOSIGFE
+tgammaf NOSIGFE
+time SIGFE
+_time = time SIGFE
+timegm NOSIGFE
+timelocal SIGFE
+timer_create SIGFE
+timer_delete SIGFE
+timer_gettime SIGFE
+timer_settime SIGFE
+times SIGFE
+_times = times SIGFE
+timezone SIGFE
+tmpfile SIGFE
+_tmpfile = tmpfile SIGFE
+_tmpfile64 = tmpfile64 SIGFE
+tmpnam SIGFE
+_tmpnam = tmpnam SIGFE
+toascii NOSIGFE
+_toascii = toascii NOSIGFE
+tolower NOSIGFE
+_tolower = tolower NOSIGFE
+toupper NOSIGFE
+_toupper = toupper NOSIGFE
+towctrans NOSIGFE
+towlower NOSIGFE
+towupper NOSIGFE
+trunc NOSIGFE
+truncate SIGFE
+_truncate = truncate SIGFE
+_truncate64 = truncate64 SIGFE
+truncf NOSIGFE
+tsearch SIGFE
+ttyname SIGFE
+_ttyname = ttyname SIGFE
+ttyname_r SIGFE
+ttyslot NOSIGFE
+twalk NOSIGFE
+tzset SIGFE
+_tzset = tzset SIGFE
+ualarm SIGFE
+_ualarm = ualarm SIGFE
+umask NOSIGFE
+_umask = umask NOSIGFE
+umount SIGFE
+_umount = umount SIGFE
+uname SIGFE
+_uname = uname SIGFE
+ungetc SIGFE
+_ungetc = ungetc SIGFE
+unlink SIGFE
+_unlink = unlink SIGFE
+unlockpt NOSIGFE
+unsetenv SIGFE
+_unsetenv = unsetenv SIGFE
+updwtmp SIGFE
+updwtmpx SIGFE
+usleep SIGFE
+_usleep = usleep SIGFE
+utime SIGFE
+_utime = utime SIGFE
+utimes SIGFE
+_utimes = utimes SIGFE
+utmpname SIGFE
+_utmpname = utmpname SIGFE
+utmpxname SIGFE
+valloc SIGFE
+vasprintf SIGFE
+_vasprintf = vasprintf SIGFE
+vasprintf_r = _vasprintf_r SIGFE
+_vasprintf_r SIGFE
+verr SIGFE
+verrx SIGFE
+vfiprintf SIGFE
+_vfiprintf = vfiprintf SIGFE
+vfork SIGFE
+_vfork = vfork SIGFE
+vfprintf SIGFE
+_vfprintf = vfprintf SIGFE
+vfscanf SIGFE
+_vfscanf = vfscanf SIGFE
+vfscanf_r = _vfscanf_r SIGFE
+_vfscanf_r SIGFE
+vhangup SIGFE
+_vhangup = vhangup SIGFE
+vprintf SIGFE
+_vprintf = vprintf SIGFE
+vscanf SIGFE
+_vscanf = vscanf SIGFE
+vscanf_r = _vscanf_r SIGFE
+_vscanf_r SIGFE
+vsnprintf SIGFE
+_vsnprintf = vsnprintf SIGFE
+vsprintf SIGFE
+_vsprintf = vsprintf SIGFE
+vsscanf SIGFE
+_vsscanf = vsscanf SIGFE
+vsscanf_r = _vsscanf_r SIGFE
+_vsscanf_r SIGFE
+vsyslog SIGFE
+vwarn SIGFE
+vwarnx SIGFE
+wait SIGFE
+_wait = wait SIGFE
+wait3 SIGFE
+wait4 SIGFE
+waitpid SIGFE
+_waitpid = waitpid SIGFE
+warn SIGFE
+warnx SIGFE
+wcrtomb NOSIGFE
+wcscat NOSIGFE
+wcschr NOSIGFE
+wcscmp NOSIGFE
+_wcscmp = wcscmp NOSIGFE
+wcscoll NOSIGFE
+wcscpy NOSIGFE
+wcscspn NOSIGFE
+wcslcat NOSIGFE
+wcslcpy NOSIGFE
+wcslen NOSIGFE
+_wcslen = wcslen NOSIGFE
+wcsncat NOSIGFE
+wcsncmp NOSIGFE
+wcsncpy NOSIGFE
+wcspbrk NOSIGFE
+wcsrchr NOSIGFE
+wcsrtombs NOSIGFE
+wcsspn NOSIGFE
+wcsstr NOSIGFE
+wcstombs NOSIGFE
+_wcstombs = wcstombs NOSIGFE
+wcswidth NOSIGFE
+wctob NOSIGFE
+wctomb NOSIGFE
+_wctomb = wctomb NOSIGFE
+wctrans NOSIGFE
+wctype NOSIGFE
+wcwidth NOSIGFE
+wmemchr NOSIGFE
+wmemcmp NOSIGFE
+wmemcpy NOSIGFE
+wmemmove NOSIGFE
+wmemset NOSIGFE
+wprintf SIGFE
+_wprintf = wprintf SIGFE
+write SIGFE
+_write = write SIGFE
+writev SIGFE
+_writev = writev SIGFE
+y0 NOSIGFE
+y0f NOSIGFE
+y1 NOSIGFE
+y1f NOSIGFE
+yn NOSIGFE
+ynf NOSIGFE
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
new file mode 100644
index 00000000000..51d72fc8f90
--- /dev/null
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -0,0 +1,1694 @@
+/* fhandler_socket.cc. See fhandler.h for a description of the fhandler classes.
+
+ Copyright 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc.
+
+ This file is part of Cygwin.
+
+ This software is a copyrighted work licensed under the terms of the
+ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+ details. */
+
+/* #define DEBUG_NEST_ON 1 */
+
+#define __INSIDE_CYGWIN_NET__
+
+#include "winsup.h"
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/uio.h>
+#include <asm/byteorder.h>
+
+#include <stdlib.h>
+#define USE_SYS_TYPES_FD_SET
+#include <winsock2.h>
+#include <iphlpapi.h>
+#include "cygerrno.h"
+#include "security.h"
+#include "cygwin/version.h"
+#include "perprocess.h"
+#include "path.h"
+#include "fhandler.h"
+#include "dtable.h"
+#include "cygheap.h"
+#include "sigproc.h"
+#include "cygthread.h"
+#include "select.h"
+#include "wininfo.h"
+#include <unistd.h>
+#include <sys/acl.h>
+#include "cygtls.h"
+#include "cygwin/in6.h"
+
+#define ASYNC_MASK (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT)
+
+extern bool fdsock (cygheap_fdmanip& fd, const device *, SOCKET soc);
+extern "C" {
+int sscanf (const char *, const char *, ...);
+} /* End of "C" section */
+
+fhandler_dev_random* entropy_source;
+
+/* cygwin internal: map sockaddr into internet domain address */
+static int
+get_inet_addr (const struct sockaddr *in, int inlen,
+ struct sockaddr_storage *out, int *outlen,
+ int *type = NULL, int *secret = NULL)
+{
+ int secret_buf [4];
+ int* secret_ptr = (secret ? : secret_buf);
+
+ if (in->sa_family == AF_INET || in->sa_family == AF_INET6)
+ {
+ memcpy (out, in, inlen);
+ *outlen = inlen;
+ return 1;
+ }
+ else if (in->sa_family == AF_LOCAL)
+ {
+ path_conv pc (in->sa_data, PC_SYM_FOLLOW);
+ if (pc.error)
+ {
+ set_errno (pc.error);
+ return 0;
+ }
+ if (!pc.exists ())
+ {
+ set_errno (ENOENT);
+ return 0;
+ }
+ if (!pc.issocket ())
+ {
+ set_errno (EBADF);
+ return 0;
+ }
+ HANDLE fh = CreateFile (pc, GENERIC_READ, wincap.shared (), &sec_none,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ if (fh == INVALID_HANDLE_VALUE)
+ {
+ __seterrno ();
+ return 0;
+ }
+ int ret = 0;
+ DWORD len = 0;
+ char buf[128];
+ memset (buf, 0, sizeof buf);
+ if (ReadFile (fh, buf, 128, &len, 0))
+ {
+ struct sockaddr_in sin;
+ char ctype;
+ sin.sin_family = AF_INET;
+ sscanf (buf + strlen (SOCKET_COOKIE), "%hu %c %08x-%08x-%08x-%08x",
+ &sin.sin_port,
+ &ctype,
+ secret_ptr, secret_ptr + 1, secret_ptr + 2, secret_ptr + 3);
+ sin.sin_port = htons (sin.sin_port);
+ sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+ memcpy (out, &sin, sizeof sin);
+ *outlen = sizeof sin;
+ if (type)
+ *type = (ctype == 's' ? SOCK_STREAM :
+ ctype == 'd' ? SOCK_DGRAM
+ : 0);
+ ret = 1;
+ }
+ else
+ __seterrno ();
+ CloseHandle (fh);
+ return ret;
+ }
+ else
+ {
+ set_errno (EAFNOSUPPORT);
+ return 0;
+ }
+}
+
+/**********************************************************************/
+/* fhandler_socket */
+
+fhandler_socket::fhandler_socket () :
+ fhandler_base (),
+ sun_path (NULL),
+ status ()
+{
+ need_fork_fixup (true);
+ prot_info_ptr = (LPWSAPROTOCOL_INFOA) cmalloc (HEAP_BUF,
+ sizeof (WSAPROTOCOL_INFOA));
+#if 0
+ if (pc.is_fs_special ())
+ {
+ fhandler_socket * fhs = (fhandler_socket *) fh;
+ fhs->set_addr_family (AF_LOCAL);
+ fhs->set_sun_path (posix_path);
+ }
+#endif
+}
+
+fhandler_socket::~fhandler_socket ()
+{
+ if (prot_info_ptr)
+ cfree (prot_info_ptr);
+ if (sun_path)
+ cfree (sun_path);
+}
+
+char *
+fhandler_socket::get_proc_fd_name (char *buf)
+{
+ __small_sprintf (buf, "socket:[%d]", get_socket ());
+ return buf;
+}
+
+int
+fhandler_socket::open (int flags, mode_t mode)
+{
+ set_errno (ENXIO);
+ return 0;
+}
+
+void
+fhandler_socket::af_local_set_sockpair_cred ()
+{
+ sec_pid = sec_peer_pid = getpid ();
+ sec_uid = sec_peer_uid = geteuid32 ();
+ sec_gid = sec_peer_gid = getegid32 ();
+}
+
+void
+fhandler_socket::af_local_setblocking (bool &async, bool &nonblocking)
+{
+ async = async_io ();
+ nonblocking = is_nonblocking ();
+ if (async || nonblocking)
+ WSAAsyncSelect (get_socket (), winmsg, 0, 0);
+ unsigned long p = 0;
+ ioctlsocket (get_socket (), FIONBIO, &p);
+ set_nonblocking (false);
+ async_io (false);
+}
+
+void
+fhandler_socket::af_local_unsetblocking (bool async, bool nonblocking)
+{
+ if (nonblocking)
+ {
+ unsigned long p = 1;
+ ioctlsocket (get_socket (), FIONBIO, &p);
+ set_nonblocking (true);
+ }
+ if (async)
+ {
+ WSAAsyncSelect (get_socket (), winmsg, WM_ASYNCIO, ASYNC_MASK);
+ async_io (true);
+ }
+}
+
+bool
+fhandler_socket::af_local_recv_secret ()
+{
+ int out[4] = { 0, 0, 0, 0 };
+ int rest = sizeof out;
+ char *ptr = (char *) out;
+ while (rest > 0)
+ {
+ int ret = recvfrom (ptr, rest, 0, NULL, NULL);
+ if (ret <= 0)
+ break;
+ rest -= ret;
+ ptr += ret;
+ }
+ if (rest == 0)
+ {
+ debug_printf ("Received af_local secret: %08x-%08x-%08x-%08x",
+ out[0], out[1], out[2], out[3]);
+ if (out[0] != connect_secret[0] || out[1] != connect_secret[1]
+ || out[2] != connect_secret[2] || out[3] != connect_secret[3])
+ {
+ debug_printf ("Receiving af_local secret mismatch");
+ return false;
+ }
+ }
+ else
+ debug_printf ("Receiving af_local secret failed");
+ return rest == 0;
+}
+
+bool
+fhandler_socket::af_local_send_secret ()
+{
+ int rest = sizeof connect_secret;
+ char *ptr = (char *) connect_secret;
+ while (rest > 0)
+ {
+ int ret = sendto (ptr, rest, 0, NULL, 0);
+ if (ret <= 0)
+ break;
+ rest -= ret;
+ ptr += ret;
+ }
+ debug_printf ("Sending af_local secret %s", rest == 0 ? "succeeded"
+ : "failed");
+ return rest == 0;
+}
+
+bool
+fhandler_socket::af_local_recv_cred ()
+{
+ struct ucred out = { (pid_t) 0, (__uid32_t) -1, (__gid32_t) -1 };
+ int rest = sizeof out;
+ char *ptr = (char *) &out;
+ while (rest > 0)
+ {
+ int ret = recvfrom (ptr, rest, 0, NULL, NULL);
+ if (ret <= 0)
+ break;
+ rest -= ret;
+ ptr += ret;
+ }
+ if (rest == 0)
+ {
+ debug_printf ("Received eid credentials: pid: %d, uid: %d, gid: %d",
+ out.pid, out.uid, out.gid);
+ sec_peer_pid = out.pid;
+ sec_peer_uid = out.uid;
+ sec_peer_gid = out.gid;
+ }
+ else
+ debug_printf ("Receiving eid credentials failed");
+ return rest == 0;
+}
+
+bool
+fhandler_socket::af_local_send_cred ()
+{
+ struct ucred in = { sec_pid, sec_uid, sec_gid };
+ int rest = sizeof in;
+ char *ptr = (char *) &in;
+ while (rest > 0)
+ {
+ int ret = sendto (ptr, rest, 0, NULL, 0);
+ if (ret <= 0)
+ break;
+ rest -= ret;
+ ptr += ret;
+ }
+ if (rest == 0)
+ debug_printf ("Sending eid credentials succeeded");
+ else
+ debug_printf ("Sending eid credentials failed");
+ return rest == 0;
+}
+
+int
+fhandler_socket::af_local_connect ()
+{
+ /* This keeps the test out of select. */
+ if (get_addr_family () != AF_LOCAL || get_socket_type () != SOCK_STREAM)
+ return 0;
+
+ debug_printf ("af_local_connect called");
+ bool orig_async_io, orig_is_nonblocking;
+ af_local_setblocking (orig_async_io, orig_is_nonblocking);
+ if (!af_local_send_secret () || !af_local_recv_secret ()
+ || !af_local_send_cred () || !af_local_recv_cred ())
+ {
+ debug_printf ("accept from unauthorized server");
+ ::shutdown (get_socket (), SD_BOTH);
+ WSASetLastError (WSAECONNREFUSED);
+ return -1;
+ }
+ af_local_unsetblocking (orig_async_io, orig_is_nonblocking);
+ return 0;
+}
+
+int
+fhandler_socket::af_local_accept ()
+{
+ debug_printf ("af_local_accept called");
+ bool orig_async_io, orig_is_nonblocking;
+ af_local_setblocking (orig_async_io, orig_is_nonblocking);
+ if (!af_local_recv_secret () || !af_local_send_secret ()
+ || !af_local_recv_cred () || !af_local_send_cred ())
+ {
+ debug_printf ("connect from unauthorized client");
+ ::shutdown (get_socket (), SD_BOTH);
+ ::closesocket (get_socket ());
+ WSASetLastError (WSAECONNABORTED);
+ return -1;
+ }
+ af_local_unsetblocking (orig_async_io, orig_is_nonblocking);
+ return 0;
+}
+
+void
+fhandler_socket::af_local_set_cred ()
+{
+ sec_pid = getpid ();
+ sec_uid = geteuid32 ();
+ sec_gid = getegid32 ();
+ sec_peer_pid = (pid_t) 0;
+ sec_peer_uid = (__uid32_t) -1;
+ sec_peer_gid = (__gid32_t) -1;
+}
+
+void
+fhandler_socket::af_local_copy (fhandler_socket *sock)
+{
+ sock->connect_secret[0] = connect_secret[0];
+ sock->connect_secret[1] = connect_secret[1];
+ sock->connect_secret[2] = connect_secret[2];
+ sock->connect_secret[3] = connect_secret[3];
+ sock->sec_pid = sec_pid;
+ sock->sec_uid = sec_uid;
+ sock->sec_gid = sec_gid;
+ sock->sec_peer_pid = sec_peer_pid;
+ sock->sec_peer_uid = sec_peer_uid;
+ sock->sec_peer_gid = sec_peer_gid;
+}
+
+void
+fhandler_socket::af_local_set_secret (char *buf)
+{
+ if (!entropy_source)
+ {
+ void *buf = malloc (sizeof (fhandler_dev_random));
+ entropy_source = new (buf) fhandler_dev_random ();
+ entropy_source->dev () = *urandom_dev;
+ }
+ if (entropy_source &&
+ !entropy_source->open (O_RDONLY))
+ {
+ delete entropy_source;
+ entropy_source = NULL;
+ }
+ if (entropy_source)
+ {
+ size_t len = sizeof (connect_secret);
+ entropy_source->read (connect_secret, len);
+ if (len != sizeof (connect_secret))
+ bzero ((char*) connect_secret, sizeof (connect_secret));
+ }
+ __small_sprintf (buf, "%08x-%08x-%08x-%08x",
+ connect_secret [0], connect_secret [1],
+ connect_secret [2], connect_secret [3]);
+}
+
+void
+fhandler_socket::fixup_before_fork_exec (DWORD win_proc_id)
+{
+ if (!WSADuplicateSocketA (get_socket (), win_proc_id, prot_info_ptr))
+ debug_printf ("WSADuplicateSocket went fine, sock %p, win_proc_id %d, prot_info_ptr %p",
+ get_socket (), win_proc_id, prot_info_ptr);
+ else
+ {
+ debug_printf ("WSADuplicateSocket error, sock %p, win_proc_id %d, prot_info_ptr %p",
+ get_socket (), win_proc_id, prot_info_ptr);
+ set_winsock_errno ();
+ }
+}
+
+void
+fhandler_socket::fixup_after_fork (HANDLE parent)
+{
+ SOCKET new_sock;
+
+ debug_printf ("WSASocket begin, dwServiceFlags1=%d",
+ prot_info_ptr->dwServiceFlags1);
+
+ if ((new_sock = WSASocketA (FROM_PROTOCOL_INFO,
+ FROM_PROTOCOL_INFO,
+ FROM_PROTOCOL_INFO,
+ prot_info_ptr, 0, 0)) == INVALID_SOCKET)
+ {
+ debug_printf ("WSASocket error");
+ set_io_handle ((HANDLE)INVALID_SOCKET);
+ set_winsock_errno ();
+ }
+ else
+ {
+ debug_printf ("WSASocket went fine new_sock %p, old_sock %p", new_sock, get_socket ());
+
+ /* Go figure! Even though the original socket was not inheritable,
+ the duplicated socket is inheritable again. This can lead to all
+ sorts of trouble, apparently. Note that there's no way to prevent
+ this on 9x, not even by trying to reset socket inheritance using
+ DuplicateHandle and closing the original socket. */
+ if (wincap.has_set_handle_information ())
+ SetHandleInformation ((HANDLE) new_sock, HANDLE_FLAG_INHERIT, 0);
+
+ set_io_handle ((HANDLE) new_sock);
+ }
+}
+
+void
+fhandler_socket::fixup_after_exec ()
+{
+ if (!close_on_exec ())
+ fixup_after_fork (NULL);
+}
+
+int
+fhandler_socket::dup (fhandler_base *child)
+{
+ HANDLE nh;
+
+ debug_printf ("here");
+ fhandler_socket *fhs = (fhandler_socket *) child;
+ fhs->addr_family = addr_family;
+ fhs->set_socket_type (get_socket_type ());
+ if (get_addr_family () == AF_LOCAL)
+ {
+ fhs->set_sun_path (get_sun_path ());
+ if (get_socket_type () == SOCK_STREAM)
+ {
+ fhs->sec_pid = sec_pid;
+ fhs->sec_uid = sec_uid;
+ fhs->sec_gid = sec_gid;
+ fhs->sec_peer_pid = sec_peer_pid;
+ fhs->sec_peer_uid = sec_peer_uid;
+ fhs->sec_peer_gid = sec_peer_gid;
+ }
+ }
+ fhs->connect_state (connect_state ());
+
+ /* Since WSADuplicateSocket() fails on NT systems when the process
+ is currently impersonating a non-privileged account, we revert
+ to the original account before calling WSADuplicateSocket() and
+ switch back afterwards as it's also in fork().
+ If WSADuplicateSocket() still fails for some reason, we fall back
+ to DuplicateHandle(). */
+ WSASetLastError (0);
+ cygheap->user.deimpersonate ();
+ fhs->set_io_handle (get_io_handle ());
+ fhs->fixup_before_fork_exec (GetCurrentProcessId ());
+ cygheap->user.reimpersonate ();
+ if (!WSAGetLastError ())
+ {
+ fhs->fixup_after_fork (hMainProc);
+ if (fhs->get_io_handle() != (HANDLE) INVALID_SOCKET)
+ {
+ cygheap->fdtab.inc_need_fixup_before ();
+ return 0;
+ }
+ }
+ debug_printf ("WSADuplicateSocket failed, trying DuplicateHandle");
+
+ /* We don't call fhandler_base::dup here since that requires
+ having winsock called from fhandler_base and it creates only
+ inheritable sockets which is wrong for winsock2. */
+
+ if (!DuplicateHandle (hMainProc, get_io_handle (), hMainProc, &nh, 0,
+ FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ system_printf ("!DuplicateHandle(%x) failed, %E", get_io_handle ());
+ __seterrno ();
+ return -1;
+ }
+ VerifyHandle (nh);
+ fhs->set_io_handle (nh);
+ cygheap->fdtab.inc_need_fixup_before ();
+ return 0;
+}
+
+int __stdcall
+fhandler_socket::fstat (struct __stat64 *buf)
+{
+ int res;
+ if (get_device () == FH_UNIX)
+ {
+ res = fhandler_base::fstat_fs (buf);
+ if (!res)
+ {
+ buf->st_mode = (buf->st_mode & ~S_IFMT) | S_IFSOCK;
+ }
+ }
+ else
+ {
+ res = fhandler_base::fstat (buf);
+ if (!res)
+ {
+ buf->st_dev = 0;
+ buf->st_ino = (__ino64_t) ((DWORD) get_handle ());
+ buf->st_mode = S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO;
+ }
+ }
+ return res;
+}
+
+int
+fhandler_socket::fchmod (mode_t mode)
+{
+ if (get_device () == FH_UNIX)
+ {
+ fhandler_disk_file fh (pc);
+ fh.get_device () = FH_FS;
+ int ret = fh.fchmod (mode);
+ SetFileAttributes (pc, GetFileAttributes (pc) | FILE_ATTRIBUTE_SYSTEM);
+ return ret;
+ }
+ return 0;
+}
+
+int
+fhandler_socket::fchown (__uid32_t uid, __gid32_t gid)
+{
+ if (get_device () == FH_UNIX)
+ {
+ fhandler_disk_file fh (pc);
+ return fh.fchown (uid, gid);
+ }
+ return 0;
+}
+
+int
+fhandler_socket::facl (int cmd, int nentries, __aclent32_t *aclbufp)
+{
+ if (get_device () == FH_UNIX)
+ {
+ fhandler_disk_file fh (pc);
+ return fh.facl (cmd, nentries, aclbufp);
+ }
+ return fhandler_base::facl (cmd, nentries, aclbufp);
+}
+
+int
+fhandler_socket::link (const char *newpath)
+{
+ if (get_device () == FH_UNIX)
+ {
+ fhandler_disk_file fh (pc);
+ return fh.link (newpath);
+ }
+ return fhandler_base::link (newpath);
+}
+
+static inline bool
+address_in_use (struct sockaddr_in *addr)
+{
+ PMIB_TCPTABLE tab;
+ PMIB_TCPROW entry;
+ DWORD size = 0, i;
+
+ if (GetTcpTable (NULL, &size, FALSE) == ERROR_INSUFFICIENT_BUFFER)
+ {
+ tab = (PMIB_TCPTABLE) alloca (size);
+ if (!GetTcpTable (tab, &size, FALSE))
+ {
+ for (i = tab->dwNumEntries, entry = tab->table; i > 0; --i, ++entry)
+ if (entry->dwLocalAddr == addr->sin_addr.s_addr
+ && entry->dwLocalPort == addr->sin_port
+ && entry->dwState >= MIB_TCP_STATE_LISTEN
+ && entry->dwState <= MIB_TCP_STATE_LAST_ACK)
+ return true;
+ }
+ }
+ return false;
+}
+
+int
+fhandler_socket::bind (const struct sockaddr *name, int namelen)
+{
+ int res = -1;
+
+ if (name->sa_family == AF_LOCAL)
+ {
+#define un_addr ((struct sockaddr_un *) name)
+ struct sockaddr_in sin;
+ int len = sizeof sin;
+
+ if (strlen (un_addr->sun_path) >= UNIX_PATH_LEN)
+ {
+ set_errno (ENAMETOOLONG);
+ goto out;
+ }
+ sin.sin_family = AF_INET;
+ sin.sin_port = 0;
+ sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+ if (::bind (get_socket (), (sockaddr *) &sin, len))
+ {
+ syscall_printf ("AF_LOCAL: bind failed %d", get_errno ());
+ set_winsock_errno ();
+ goto out;
+ }
+ if (::getsockname (get_socket (), (sockaddr *) &sin, &len))
+ {
+ syscall_printf ("AF_LOCAL: getsockname failed %d", get_errno ());
+ set_winsock_errno ();
+ goto out;
+ }
+
+ sin.sin_port = ntohs (sin.sin_port);
+ debug_printf ("AF_LOCAL: socket bound to port %u", sin.sin_port);
+
+ path_conv pc (un_addr->sun_path, PC_SYM_FOLLOW);
+ if (pc.error)
+ {
+ set_errno (pc.error);
+ goto out;
+ }
+ if (pc.exists ())
+ {
+ set_errno (EADDRINUSE);
+ goto out;
+ }
+ mode_t mode = (S_IRWXU | S_IRWXG | S_IRWXO) & ~cygheap->umask;
+ DWORD attr = FILE_ATTRIBUTE_SYSTEM;
+ if (!(mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
+ attr |= FILE_ATTRIBUTE_READONLY;
+ SECURITY_ATTRIBUTES sa = sec_none;
+ security_descriptor sd;
+ if (allow_ntsec && pc.has_acls ())
+ set_security_attribute (mode, &sa, sd);
+ HANDLE fh = CreateFile (pc, GENERIC_WRITE, 0, &sa, CREATE_NEW, attr, 0);
+ if (fh == INVALID_HANDLE_VALUE)
+ {
+ if (GetLastError () == ERROR_ALREADY_EXISTS)
+ set_errno (EADDRINUSE);
+ else
+ __seterrno ();
+ }
+
+ char buf[sizeof (SOCKET_COOKIE) + 80];
+ __small_sprintf (buf, "%s%u %c ", SOCKET_COOKIE, sin.sin_port, get_socket_type () == SOCK_STREAM ? 's' : get_socket_type () == SOCK_DGRAM ? 'd' : '-');
+ af_local_set_secret (strchr (buf, '\0'));
+ DWORD blen = strlen (buf) + 1;
+ if (!WriteFile (fh, buf, blen, &blen, 0))
+ {
+ __seterrno ();
+ CloseHandle (fh);
+ DeleteFile (pc);
+ }
+ else
+ {
+ CloseHandle (fh);
+ set_sun_path (un_addr->sun_path);
+ res = 0;
+ }
+#undef un_addr
+ }
+ else
+ {
+ /* If the application didn't explicitely call setsockopt (SO_REUSEADDR),
+ enforce exclusive local address use using the SO_EXCLUSIVEADDRUSE
+ socket option, to emulate POSIX socket behaviour more closely.
+
+ KB 870562: Note that this option is only available since NT4 SP4.
+ Also note that a bug in Win2K SP1-3 and XP up to SP1 only enables
+ this option for users in the local administrators group. */
+ if (wincap.has_exclusiveaddruse ())
+ {
+ if (!saw_reuseaddr ())
+ {
+ int on = 1;
+ int ret = ::setsockopt (get_socket (), SOL_SOCKET,
+ ~(SO_REUSEADDR),
+ (const char *) &on, sizeof on);
+ debug_printf ("%d = setsockopt (SO_EXCLUSIVEADDRUSE), %E", ret);
+ }
+ else
+ {
+ debug_printf ("SO_REUSEADDR set");
+ /* There's a bug in SO_REUSEADDR handling in WinSock.
+ Per standards, we must not be able to reuse a complete
+ duplicate of a local TCP address (same IP, same port),
+ even if SO_REUSEADDR has been set. That's unfortunately
+ possible in WinSock. So we're testing here if the local
+ address is already in use and don't bind, if so. This
+ only works for OSes with IP Helper support. */
+ if (get_socket_type () == SOCK_STREAM
+ && wincap.has_ip_helper_lib ()
+ && address_in_use ((struct sockaddr_in *) name))
+ {
+ debug_printf ("Local address in use, don't bind");
+ set_errno (EADDRINUSE);
+ goto out;
+ }
+ }
+ }
+ if (::bind (get_socket (), name, namelen))
+ set_winsock_errno ();
+ else
+ res = 0;
+ }
+
+out:
+ return res;
+}
+
+int
+fhandler_socket::connect (const struct sockaddr *name, int namelen)
+{
+ int res = -1;
+ bool in_progress = false;
+ struct sockaddr_storage sst;
+ DWORD err;
+ int type;
+
+ if (!get_inet_addr (name, namelen, &sst, &namelen, &type, connect_secret))
+ return -1;
+
+ if (get_addr_family () == AF_LOCAL && get_socket_type () != type)
+ {
+ WSASetLastError (WSAEPROTOTYPE);
+ set_winsock_errno ();
+ return -1;
+ }
+
+ res = ::connect (get_socket (), (struct sockaddr *) &sst, namelen);
+
+ if (!res)
+ err = 0;
+ else
+ {
+ err = WSAGetLastError ();
+ /* Special handling for connect to return the correct error code
+ when called on a non-blocking socket. */
+ if (is_nonblocking ())
+ {
+ if (err == WSAEWOULDBLOCK || err == WSAEALREADY)
+ in_progress = true;
+
+ if (err == WSAEWOULDBLOCK)
+ WSASetLastError (err = WSAEINPROGRESS);
+ }
+ if (err == WSAEINVAL)
+ WSASetLastError (err = WSAEISCONN);
+ set_winsock_errno ();
+ }
+
+ if (get_addr_family () == AF_LOCAL && (!res || in_progress))
+ set_sun_path (name->sa_data);
+
+ if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM)
+ {
+ af_local_set_cred (); /* Don't move into af_local_connect since
+ af_local_connect is called from select,
+ possibly running under another identity. */
+ if (!res && af_local_connect ())
+ {
+ set_winsock_errno ();
+ return -1;
+ }
+ }
+
+ if (err == WSAEINPROGRESS || err == WSAEALREADY)
+ connect_state (connect_pending);
+ else if (err)
+ connect_state (connect_failed);
+ else
+ connect_state (connected);
+
+ return res;
+}
+
+int
+fhandler_socket::listen (int backlog)
+{
+ int res = ::listen (get_socket (), backlog);
+ if (res && WSAGetLastError () == WSAEINVAL)
+ {
+ /* It's perfectly valid to call listen on an unbound INET socket.
+ In this case the socket is automatically bound to an unused
+ port number, listening on all interfaces. On Winsock, listen
+ fails with WSAEINVAL when it's called on an unbound socket.
+ So we have to bind manually here to have POSIX semantics. */
+ if (get_addr_family () == AF_INET)
+ {
+ struct sockaddr_in sin;
+ sin.sin_family = AF_INET;
+ sin.sin_port = 0;
+ sin.sin_addr.s_addr = INADDR_ANY;
+ if (!::bind (get_socket (), (struct sockaddr *) &sin, sizeof sin))
+ res = ::listen (get_socket (), backlog);
+ }
+ else if (get_addr_family () == AF_INET6)
+ {
+ struct sockaddr_in6 sin6 =
+ {
+ sin6_family: AF_INET6,
+ sin6_port: 0,
+ sin6_flowinfo: 0,
+ sin6_addr: IN6ADDR_ANY_INIT,
+ sin6_scope_id: 0
+ };
+ if (!::bind (get_socket (), (struct sockaddr *) &sin6, sizeof sin6))
+ res = ::listen (get_socket (), backlog);
+ }
+ }
+ if (!res)
+ {
+ if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM)
+ af_local_set_cred ();
+ connect_state (connected);
+ }
+ else
+ set_winsock_errno ();
+ return res;
+}
+
+int
+fhandler_socket::accept (struct sockaddr *peer, int *len)
+{
+ int res = -1;
+
+ /* Allows NULL peer and len parameters. */
+ struct sockaddr_in peer_dummy;
+ int len_dummy;
+ if (!peer)
+ peer = (struct sockaddr *) &peer_dummy;
+ if (!len)
+ {
+ len_dummy = sizeof (struct sockaddr_in);
+ len = &len_dummy;
+ }
+
+ /* accept on NT fails if len < sizeof (sockaddr_in)
+ * some programs set len to
+ * sizeof (name.sun_family) + strlen (name.sun_path) for UNIX domain
+ */
+ if (len && ((unsigned) *len < sizeof (struct sockaddr_in)))
+ *len = sizeof (struct sockaddr_in);
+
+ res = ::accept (get_socket (), peer, len);
+
+ if (res == (int) INVALID_SOCKET)
+ set_winsock_errno ();
+ else
+ {
+ cygheap_fdnew res_fd;
+ if (res_fd >= 0 && fdsock (res_fd, &dev (), res))
+ {
+ fhandler_socket *sock = (fhandler_socket *) res_fd;
+ sock->set_addr_family (get_addr_family ());
+ sock->set_socket_type (get_socket_type ());
+ sock->async_io (async_io ());
+ sock->set_nonblocking (is_nonblocking ());
+ if (get_addr_family () == AF_LOCAL)
+ {
+ sock->set_sun_path (get_sun_path ());
+ if (get_socket_type () == SOCK_STREAM)
+ {
+ /* Don't forget to copy credentials from accepting
+ socket to accepted socket and start transaction
+ on accepted socket! */
+ af_local_copy (sock);
+ res = sock->af_local_accept ();
+ if (res == -1)
+ {
+ res_fd.release ();
+ set_winsock_errno ();
+ goto out;
+ }
+ }
+ }
+ sock->connect_state (connected);
+ res = res_fd;
+ }
+ else
+ {
+ closesocket (res);
+ res = -1;
+ }
+ }
+
+out:
+ debug_printf ("res %d", res);
+ return res;
+}
+
+int
+fhandler_socket::getsockname (struct sockaddr *name, int *namelen)
+{
+ int res = -1;
+
+ if (get_addr_family () == AF_LOCAL)
+ {
+ struct sockaddr_un *sun = (struct sockaddr_un *) name;
+ memset (sun, 0, *namelen);
+ sun->sun_family = AF_LOCAL;
+
+ if (!get_sun_path ())
+ sun->sun_path[0] = '\0';
+ else
+ /* According to SUSv2 "If the actual length of the address is
+ greater than the length of the supplied sockaddr structure, the
+ stored address will be truncated." We play it save here so
+ that the path always has a trailing 0 even if it's truncated. */
+ strncpy (sun->sun_path, get_sun_path (),
+ *namelen - sizeof *sun + sizeof sun->sun_path - 1);
+
+ *namelen = sizeof *sun - sizeof sun->sun_path
+ + strlen (sun->sun_path) + 1;
+ res = 0;
+ }
+ else
+ {
+ res = ::getsockname (get_socket (), name, namelen);
+ if (res)
+ set_winsock_errno ();
+ }
+
+ return res;
+}
+
+int
+fhandler_socket::getpeername (struct sockaddr *name, int *namelen)
+{
+ int res = ::getpeername (get_socket (), name, namelen);
+ if (res)
+ set_winsock_errno ();
+
+ return res;
+}
+
+bool
+fhandler_socket::prepare (HANDLE &event, long event_mask)
+{
+ WSASetLastError (0);
+ closed (false);
+ if ((event = WSACreateEvent ()) == WSA_INVALID_EVENT)
+ {
+ debug_printf ("WSACreateEvent, %E");
+ return false;
+ }
+ if (WSAEventSelect (get_socket (), event, event_mask) == SOCKET_ERROR)
+ {
+ debug_printf ("WSAEventSelect(evt), %d", WSAGetLastError ());
+ return false;
+ }
+ return true;
+}
+
+int
+fhandler_socket::wait (HANDLE event, int flags, DWORD timeout)
+{
+ int ret = SOCKET_ERROR;
+ int wsa_err = 0;
+ WSAEVENT ev[2] = { event, signal_arrived };
+ WSANETWORKEVENTS evts;
+
+/* If WSAWaitForMultipleEvents is interrupted by a signal, and the signal
+ has the SA_RESTART flag set, return to this label and... restart. */
+sa_restart:
+
+ switch (WSAWaitForMultipleEvents (2, ev, FALSE, timeout, FALSE))
+ {
+ case WSA_WAIT_TIMEOUT:
+ ret = 0;
+ break;
+ case WSA_WAIT_EVENT_0:
+ if (!WSAEnumNetworkEvents (get_socket (), event, &evts))
+ {
+ if (!evts.lNetworkEvents)
+ {
+ ret = 0;
+ break;
+ }
+ if (evts.lNetworkEvents & FD_OOB)
+ {
+ if (evts.iErrorCode[FD_OOB_BIT])
+ wsa_err = evts.iErrorCode[FD_OOB_BIT];
+ else if (flags & MSG_OOB)
+ ret = 0;
+ else
+ {
+ raise (SIGURG);
+ WSASetLastError (WSAEINTR);
+ break;
+ }
+ }
+ if (evts.lNetworkEvents & FD_ACCEPT)
+ {
+ if (evts.iErrorCode[FD_ACCEPT_BIT])
+ wsa_err = evts.iErrorCode[FD_ACCEPT_BIT];
+ else
+ ret = 0;
+ }
+ if (evts.lNetworkEvents & FD_CONNECT)
+ {
+ if (evts.iErrorCode[FD_CONNECT_BIT])
+ wsa_err = evts.iErrorCode[FD_CONNECT_BIT];
+ else
+ ret = 0;
+ }
+ else if (evts.lNetworkEvents & FD_READ)
+ {
+ if (evts.iErrorCode[FD_READ_BIT])
+ wsa_err = evts.iErrorCode[FD_READ_BIT];
+ else
+ ret = 0;
+ }
+ else if (evts.lNetworkEvents & FD_WRITE)
+ {
+ if (evts.iErrorCode[FD_WRITE_BIT])
+ wsa_err = evts.iErrorCode[FD_WRITE_BIT];
+ else
+ ret = 0;
+ }
+ if (evts.lNetworkEvents & FD_CLOSE)
+ {
+ closed (true);
+ if (!wsa_err)
+ {
+ if (evts.iErrorCode[FD_CLOSE_BIT])
+ wsa_err = evts.iErrorCode[FD_CLOSE_BIT];
+ else
+ ret = 0;
+ }
+ }
+ if (wsa_err)
+ WSASetLastError (wsa_err);
+ }
+ break;
+ case WSA_WAIT_EVENT_0 + 1:
+ if (_my_tls.call_signal_handler ())
+ {
+ sig_dispatch_pending ();
+ goto sa_restart;
+ }
+ WSASetLastError (WSAEINTR);
+ break;
+ default:
+ WSASetLastError (WSAEFAULT);
+ break;
+ }
+ return ret;
+}
+
+void
+fhandler_socket::release (HANDLE event)
+{
+ int last_err = WSAGetLastError ();
+ /* KB 168349: NT4 fails if the event parameter is not NULL. */
+ if (WSAEventSelect (get_socket (), NULL, 0) == SOCKET_ERROR)
+ debug_printf ("WSAEventSelect(NULL), %d", WSAGetLastError ());
+ WSACloseEvent (event);
+ unsigned long non_block = 0;
+ if (ioctlsocket (get_socket (), FIONBIO, &non_block))
+ debug_printf ("return to blocking failed: %d", WSAGetLastError ());
+ else
+ WSASetLastError (last_err);
+}
+
+int
+fhandler_socket::readv (const struct iovec *const iov, const int iovcnt,
+ ssize_t tot)
+{
+ struct msghdr msg =
+ {
+ msg_name: NULL,
+ msg_namelen: 0,
+ msg_iov: (struct iovec *) iov, // const_cast
+ msg_iovlen: iovcnt,
+ msg_control: NULL,
+ msg_controllen: 0,
+ msg_flags: 0
+ };
+
+ return recvmsg (&msg, 0, tot);
+}
+
+int
+fhandler_socket::recvfrom (void *ptr, size_t len, int flags,
+ struct sockaddr *from, int *fromlen)
+{
+ int res = SOCKET_ERROR;
+ DWORD ret = 0;
+
+ WSABUF wsabuf = { len, (char *) ptr };
+
+ if (is_nonblocking () || closed () || async_io ())
+ {
+ DWORD lflags = (DWORD) (flags & MSG_WINMASK);
+ res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret,
+ &lflags, from, fromlen, NULL, NULL);
+ }
+ else
+ {
+ HANDLE evt;
+ if (prepare (evt, FD_CLOSE | FD_READ | (owner () ? FD_OOB : 0)))
+ {
+ do
+ {
+ DWORD lflags = (DWORD) (flags & MSG_WINMASK);
+ res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, &lflags,
+ from, fromlen, NULL, NULL);
+ }
+ while (res == SOCKET_ERROR
+ && WSAGetLastError () == WSAEWOULDBLOCK
+ && !closed ()
+ && !(res = wait (evt, flags)));
+ release (evt);
+ }
+ }
+
+ if (res == SOCKET_ERROR)
+ {
+ /* According to SUSv3, errno isn't set in that case and no error
+ condition is returned. */
+ if (WSAGetLastError () == WSAEMSGSIZE)
+ return len;
+
+ /* ESHUTDOWN isn't defined for recv in SUSv3. Simply EOF is returned
+ in this case. */
+ if (WSAGetLastError () == WSAESHUTDOWN)
+ return 0;
+
+ set_winsock_errno ();
+ }
+ else
+ res = ret;
+
+ return res;
+}
+
+int
+fhandler_socket::recvmsg (struct msghdr *msg, int flags, ssize_t tot)
+{
+ if (CYGWIN_VERSION_CHECK_FOR_USING_ANCIENT_MSGHDR)
+ ((struct OLD_msghdr *) msg)->msg_accrightslen = 0;
+ else
+ {
+ msg->msg_controllen = 0;
+ msg->msg_flags = 0;
+ }
+ if (get_addr_family () == AF_LOCAL)
+ {
+ /* On AF_LOCAL sockets the (fixed-size) name of the shared memory
+ area used for descriptor passing is transmitted first.
+ If this string is empty, no descriptors are passed and we can
+ go ahead recv'ing the normal data blocks. Otherwise start
+ special handling for descriptor passing. */
+ /*TODO*/
+ }
+
+ struct iovec *const iov = msg->msg_iov;
+ const int iovcnt = msg->msg_iovlen;
+
+ struct sockaddr *from = (struct sockaddr *) msg->msg_name;
+ int *fromlen = from ? &msg->msg_namelen : NULL;
+
+ int res = SOCKET_ERROR;
+
+ WSABUF wsabuf[iovcnt];
+ unsigned long len = 0L;
+
+ const struct iovec *iovptr = iov + iovcnt;
+ WSABUF *wsaptr = wsabuf + iovcnt;
+ do
+ {
+ iovptr -= 1;
+ wsaptr -= 1;
+ len += wsaptr->len = iovptr->iov_len;
+ wsaptr->buf = (char *) iovptr->iov_base;
+ }
+ while (wsaptr != wsabuf);
+
+ DWORD ret = 0;
+
+ if (is_nonblocking () || closed () || async_io ())
+ {
+ DWORD lflags = (DWORD) (flags & MSG_WINMASK);
+ res = WSARecvFrom (get_socket (), wsabuf, iovcnt, &ret,
+ &lflags, from, fromlen, NULL, NULL);
+ }
+ else
+ {
+ HANDLE evt;
+ if (prepare (evt, FD_CLOSE | FD_READ | (owner () ? FD_OOB : 0)))
+ {
+ do
+ {
+ DWORD lflags = (DWORD) (flags & MSG_WINMASK);
+ res = WSARecvFrom (get_socket (), wsabuf, iovcnt, &ret,
+ &lflags, from, fromlen, NULL, NULL);
+ }
+ while (res == SOCKET_ERROR
+ && WSAGetLastError () == WSAEWOULDBLOCK
+ && !closed ()
+ && !(res = wait (evt, flags)));
+ release (evt);
+ }
+ }
+
+ if (res == SOCKET_ERROR)
+ {
+ /* According to SUSv3, errno isn't set in that case and no error
+ condition is returned. */
+ if (WSAGetLastError () == WSAEMSGSIZE)
+ return len;
+
+ /* ESHUTDOWN isn't defined for recv in SUSv3. Simply EOF is returned
+ in this case. */
+ if (WSAGetLastError () == WSAESHUTDOWN)
+ return 0;
+
+ set_winsock_errno ();
+ }
+ else
+ res = ret;
+
+ return res;
+}
+
+int
+fhandler_socket::writev (const struct iovec *const iov, const int iovcnt,
+ ssize_t tot)
+{
+ struct msghdr msg =
+ {
+ msg_name: NULL,
+ msg_namelen: 0,
+ msg_iov: (struct iovec *) iov, // const_cast
+ msg_iovlen: iovcnt,
+ msg_control: NULL,
+ msg_controllen: 0,
+ msg_flags: 0
+ };
+
+ return sendmsg (&msg, 0, tot);
+}
+
+int
+fhandler_socket::sendto (const void *ptr, size_t len, int flags,
+ const struct sockaddr *to, int tolen)
+{
+ struct sockaddr_storage sst;
+
+ if (to && !get_inet_addr (to, tolen, &sst, &tolen))
+ return SOCKET_ERROR;
+
+ int res = SOCKET_ERROR;
+ DWORD ret = 0;
+
+ WSABUF wsabuf = { len, (char *) ptr };
+
+ if (is_nonblocking () || closed () || async_io ())
+ res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
+ flags & MSG_WINMASK,
+ (to ? (const struct sockaddr *) &sst : NULL), tolen,
+ NULL, NULL);
+ else
+ {
+ HANDLE evt;
+ if (prepare (evt, FD_CLOSE | FD_WRITE | (owner () ? FD_OOB : 0)))
+ {
+ do
+ {
+ res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
+ flags & MSG_WINMASK,
+ (to ? (const struct sockaddr *) &sst : NULL),
+ tolen, NULL, NULL);
+ }
+ while (res == SOCKET_ERROR
+ && WSAGetLastError () == WSAEWOULDBLOCK
+ && !(res = wait (evt, 0))
+ && !closed ());
+ release (evt);
+ }
+ }
+
+ if (res == SOCKET_ERROR)
+ set_winsock_errno ();
+ else
+ res = ret;
+
+ /* Special handling for EPIPE and SIGPIPE.
+
+ EPIPE is generated if the local end has been shut down on a connection
+ oriented socket. In this case the process will also receive a SIGPIPE
+ unless MSG_NOSIGNAL is set. */
+ if (res == SOCKET_ERROR && get_errno () == ESHUTDOWN
+ && get_socket_type () == SOCK_STREAM)
+ {
+ set_errno (EPIPE);
+ if (! (flags & MSG_NOSIGNAL))
+ raise (SIGPIPE);
+ }
+
+ return res;
+}
+
+int
+fhandler_socket::sendmsg (const struct msghdr *msg, int flags, ssize_t tot)
+{
+ if (get_addr_family () == AF_LOCAL)
+ {
+ /* For AF_LOCAL/AF_UNIX sockets, if descriptors are given, start
+ the special handling for descriptor passing. Otherwise just
+ transmit an empty string to tell the receiver that no
+ descriptor passing is done. */
+ /*TODO*/
+ }
+
+ struct iovec *const iov = msg->msg_iov;
+ const int iovcnt = msg->msg_iovlen;
+
+ int res = SOCKET_ERROR;
+
+ WSABUF wsabuf[iovcnt];
+
+ const struct iovec *iovptr = iov + iovcnt;
+ WSABUF *wsaptr = wsabuf + iovcnt;
+ do
+ {
+ iovptr -= 1;
+ wsaptr -= 1;
+ wsaptr->len = iovptr->iov_len;
+ wsaptr->buf = (char *) iovptr->iov_base;
+ }
+ while (wsaptr != wsabuf);
+
+ DWORD ret = 0;
+
+ if (is_nonblocking () || closed () || async_io ())
+ res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret,
+ flags & MSG_WINMASK, (struct sockaddr *) msg->msg_name,
+ msg->msg_namelen, NULL, NULL);
+ else
+ {
+ HANDLE evt;
+ if (prepare (evt, FD_CLOSE | FD_WRITE | (owner () ? FD_OOB : 0)))
+ {
+ do
+ {
+ res = WSASendTo (get_socket (), wsabuf, iovcnt,
+ &ret, flags & MSG_WINMASK,
+ (struct sockaddr *) msg->msg_name,
+ msg->msg_namelen, NULL, NULL);
+ }
+ while (res == SOCKET_ERROR
+ && WSAGetLastError () == WSAEWOULDBLOCK
+ && !(res = wait (evt, 0))
+ && !closed ());
+ release (evt);
+ }
+ }
+
+ if (res == SOCKET_ERROR)
+ set_winsock_errno ();
+ else
+ res = ret;
+
+ /* Special handling for EPIPE and SIGPIPE.
+
+ EPIPE is generated if the local end has been shut down on a connection
+ oriented socket. In this case the process will also receive a SIGPIPE
+ unless MSG_NOSIGNAL is set. */
+ if (res == SOCKET_ERROR && get_errno () == ESHUTDOWN
+ && get_socket_type () == SOCK_STREAM)
+ {
+ set_errno (EPIPE);
+ if (! (flags & MSG_NOSIGNAL))
+ raise (SIGPIPE);
+ }
+
+ return res;
+}
+
+int
+fhandler_socket::shutdown (int how)
+{
+ int res = ::shutdown (get_socket (), how);
+
+ if (res)
+ set_winsock_errno ();
+ else
+ switch (how)
+ {
+ case SHUT_RD:
+ saw_shutdown_read (true);
+ break;
+ case SHUT_WR:
+ saw_shutdown_write (true);
+ break;
+ case SHUT_RDWR:
+ saw_shutdown_read (true);
+ saw_shutdown_write (true);
+ break;
+ }
+ return res;
+}
+
+int
+fhandler_socket::close ()
+{
+ int res = 0;
+
+ /* HACK to allow a graceful shutdown even if shutdown() hasn't been
+ called by the application. Note that this isn't the ultimate
+ solution but it helps in many cases. */
+ struct linger linger;
+ linger.l_onoff = 1;
+ linger.l_linger = 240; /* secs. default 2MSL value according to MSDN. */
+ setsockopt (get_socket (), SOL_SOCKET, SO_LINGER,
+ (const char *)&linger, sizeof linger);
+
+ while ((res = closesocket (get_socket ())) != 0)
+ {
+ if (WSAGetLastError () != WSAEWOULDBLOCK)
+ {
+ set_winsock_errno ();
+ res = -1;
+ break;
+ }
+ if (WaitForSingleObject (signal_arrived, 10) == WAIT_OBJECT_0)
+ {
+ set_errno (EINTR);
+ res = -1;
+ break;
+ }
+ WSASetLastError (0);
+ }
+
+ debug_printf ("%d = fhandler_socket::close()", res);
+ return res;
+}
+
+int
+fhandler_socket::ioctl (unsigned int cmd, void *p)
+{
+ extern int get_ifconf (struct ifconf *ifc, int what); /* net.cc */
+ int res;
+ struct ifconf ifc, *ifcp;
+ struct ifreq *ifr, *ifrp;
+
+ switch (cmd)
+ {
+ case SIOCGIFCONF:
+ ifcp = (struct ifconf *) p;
+ if (!ifcp)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ res = get_ifconf (ifcp, cmd);
+ if (res)
+ debug_printf ("error in get_ifconf");
+ break;
+ case SIOCGIFFLAGS:
+ ifr = (struct ifreq *) p;
+ if (ifr == 0)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ ifr->ifr_flags = IFF_NOTRAILERS | IFF_UP | IFF_RUNNING;
+ if (!strncmp(ifr->ifr_name, "lo", 2)
+ || ntohl (((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr)
+ == INADDR_LOOPBACK)
+ ifr->ifr_flags |= IFF_LOOPBACK;
+ else
+ ifr->ifr_flags |= IFF_BROADCAST;
+ res = 0;
+ break;
+ case SIOCGIFBRDADDR:
+ case SIOCGIFNETMASK:
+ case SIOCGIFADDR:
+ case SIOCGIFHWADDR:
+ case SIOCGIFMETRIC:
+ case SIOCGIFMTU:
+ {
+ ifc.ifc_len = 2048;
+ ifc.ifc_buf = (char *) alloca (2048);
+
+ ifr = (struct ifreq *) p;
+ if (ifr == 0)
+ {
+ debug_printf ("ifr == NULL");
+ set_errno (EINVAL);
+ return -1;
+ }
+
+ res = get_ifconf (&ifc, cmd);
+ if (res)
+ {
+ debug_printf ("error in get_ifconf");
+ break;
+ }
+
+ debug_printf (" name: %s", ifr->ifr_name);
+ for (ifrp = ifc.ifc_req;
+ (caddr_t) ifrp < ifc.ifc_buf + ifc.ifc_len;
+ ++ifrp)
+ {
+ debug_printf ("testname: %s", ifrp->ifr_name);
+ if (! strcmp (ifrp->ifr_name, ifr->ifr_name))
+ {
+ switch (cmd)
+ {
+ case SIOCGIFADDR:
+ ifr->ifr_addr = ifrp->ifr_addr;
+ break;
+ case SIOCGIFBRDADDR:
+ ifr->ifr_broadaddr = ifrp->ifr_broadaddr;
+ break;
+ case SIOCGIFNETMASK:
+ ifr->ifr_netmask = ifrp->ifr_netmask;
+ break;
+ case SIOCGIFHWADDR:
+ ifr->ifr_hwaddr = ifrp->ifr_hwaddr;
+ break;
+ case SIOCGIFMETRIC:
+ ifr->ifr_metric = ifrp->ifr_metric;
+ break;
+ case SIOCGIFMTU:
+ ifr->ifr_mtu = ifrp->ifr_mtu;
+ break;
+ }
+ break;
+ }
+ }
+ if ((caddr_t) ifrp >= ifc.ifc_buf + ifc.ifc_len)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ break;
+ }
+ case FIOASYNC:
+ res = WSAAsyncSelect (get_socket (), winmsg, WM_ASYNCIO,
+ *(int *) p ? ASYNC_MASK : 0);
+ syscall_printf ("Async I/O on socket %s",
+ *(int *) p ? "started" : "cancelled");
+ async_io (*(int *) p != 0);
+ break;
+ case FIONREAD:
+ res = ioctlsocket (get_socket (), FIONREAD, (unsigned long *) p);
+ if (res == SOCKET_ERROR)
+ set_winsock_errno ();
+ break;
+ default:
+ /* We must cancel WSAAsyncSelect (if any) before setting socket to
+ * blocking mode
+ */
+ if (cmd == FIONBIO && *(int *) p == 0)
+ {
+ if (async_io ())
+ WSAAsyncSelect (get_socket (), winmsg, 0, 0);
+ if (WSAEventSelect (get_socket (), NULL, 0) == SOCKET_ERROR)
+ debug_printf ("WSAEventSelect(NULL), %d", WSAGetLastError ());
+ }
+ res = ioctlsocket (get_socket (), cmd, (unsigned long *) p);
+ if (res == SOCKET_ERROR)
+ set_winsock_errno ();
+ if (cmd == FIONBIO)
+ {
+ if (!res)
+ {
+ syscall_printf ("socket is now %sblocking",
+ *(int *) p ? "non" : "");
+ set_nonblocking (*(int *) p);
+ }
+ /* Start AsyncSelect if async socket unblocked */
+ if (*(int *) p && async_io ())
+ WSAAsyncSelect (get_socket (), winmsg, WM_ASYNCIO, ASYNC_MASK);
+ }
+ break;
+ }
+ syscall_printf ("%d = ioctl_socket (%x, %x)", res, cmd, p);
+ return res;
+}
+
+int
+fhandler_socket::fcntl (int cmd, void *arg)
+{
+ int res = 0;
+ int request, current;
+
+ switch (cmd)
+ {
+ case F_SETOWN:
+ {
+ /* Urgh! Bad hack! */
+ pid_t pid = (pid_t) arg;
+ owner (pid == getpid ());
+ debug_printf ("owner set to %d", owner ());
+ }
+ break;
+ case F_SETFL:
+ {
+ /* Carefully test for the O_NONBLOCK or deprecated OLD_O_NDELAY flag.
+ Set only the flag that has been passed in. If both are set, just
+ record O_NONBLOCK. */
+ int new_flags = (int) arg & O_NONBLOCK_MASK;
+ if ((new_flags & OLD_O_NDELAY) && (new_flags & O_NONBLOCK))
+ new_flags = O_NONBLOCK;
+ current = get_flags () & O_NONBLOCK_MASK;
+ request = new_flags ? 1 : 0;
+ if (!!current != !!new_flags && (res = ioctl (FIONBIO, &request)))
+ break;
+ set_flags ((get_flags () & ~O_NONBLOCK_MASK) | new_flags);
+ break;
+ }
+ default:
+ res = fhandler_base::fcntl (cmd, arg);
+ break;
+ }
+ return res;
+}
+
+void
+fhandler_socket::set_close_on_exec (bool val)
+{
+ close_on_exec (val);
+ debug_printf ("set close_on_exec for %s to %d", get_name (), val);
+}
+
+void
+fhandler_socket::set_sun_path (const char *path)
+{
+ sun_path = path ? cstrdup (path) : NULL;
+}
+
+int
+fhandler_socket::getpeereid (pid_t *pid, __uid32_t *euid, __gid32_t *egid)
+{
+ if (get_addr_family () != AF_LOCAL || get_socket_type () != SOCK_STREAM)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ if (connect_state () != connected)
+ {
+ set_errno (ENOTCONN);
+ return -1;
+ }
+ if (sec_peer_pid == (pid_t) 0)
+ {
+ set_errno (ENOTCONN); /* Usually when calling getpeereid on
+ accepting (instead of accepted) socket. */
+ return -1;
+ }
+
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return -1;
+ if (pid)
+ *pid = sec_peer_pid;
+ if (euid)
+ *euid = sec_peer_uid;
+ if (egid)
+ *egid = sec_peer_gid;
+ return 0;
+}
diff --git a/winsup/cygwin/include/cygwin/in.h b/winsup/cygwin/include/cygwin/in.h
new file mode 100644
index 00000000000..619d47a30d4
--- /dev/null
+++ b/winsup/cygwin/include/cygwin/in.h
@@ -0,0 +1,209 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions of the Internet Protocol.
+ *
+ * Version: @(#)in.h 1.0.1 04/21/93
+ *
+ * Authors: Original taken from the GNU Project <netinet/in.h> file.
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _CYGWIN_IN_H
+#define _CYGWIN_IN_H
+
+#include <cygwin/socket.h>
+
+typedef uint16_t in_port_t;
+typedef uint32_t in_addr_t;
+
+/* Standard well-defined IP protocols. If you ever add one here, don't
+ forget to define it below. */
+enum
+{
+ IPPROTO_IP = 0, /* Dummy protocol for TCP */
+ IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options */
+ IPPROTO_ICMP = 1, /* Internet Control Message Protocol */
+ IPPROTO_IGMP = 2, /* Internet Gateway Management Protocol */
+ IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94) */
+ IPPROTO_TCP = 6, /* Transmission Control Protocol */
+ IPPROTO_EGP = 8, /* Exterior Gateway Protocol */
+ IPPROTO_PUP = 12, /* PUP protocol */
+ IPPROTO_UDP = 17, /* User Datagram Protocol */
+ IPPROTO_IDP = 22, /* XNS IDP protocol */
+ IPPROTO_IPV6 = 41, /* IPv6 header */
+ IPPROTO_ROUTING = 43, /* IPv6 Routing header */
+ IPPROTO_FRAGMENT = 44, /* IPv6 fragmentation header */
+ IPPROTO_ESP = 50, /* encapsulating security payload */
+ IPPROTO_AH = 51, /* authentication header */
+ IPPROTO_ICMPV6 = 58, /* ICMPv6 */
+ IPPROTO_NONE = 59, /* IPv6 no next header */
+ IPPROTO_DSTOPTS = 60, /* IPv6 Destination options */
+ IPPROTO_RAW = 255, /* Raw IP packets */
+ IPPROTO_MAX
+};
+
+/* Define IPPROTO_xxx values to accomodate SUSv3 */
+#define IPPROTO_IP IPPROTO_IP
+#define IPPROTO_HOPOPTS IPPROTO_HOPOPTS
+#define IPPROTO_ICMP IPPROTO_ICMP
+#define IPPROTO_IGMP IPPROTO_IGMP
+#define IPPROTO_IPIP IPPROTO_IPIP
+#define IPPROTO_TCP IPPROTO_TCP
+#define IPPROTO_EGP IPPROTO_EGP
+#define IPPROTO_PUP IPPROTO_PUP
+#define IPPROTO_UDP IPPROTO_UDP
+#define IPPROTO_IDP IPPROTO_IDP
+#define IPPROTO_RAW IPPROTO_RAW
+#define IPPROTO_IPV6 IPPROTO_IPV6
+#define IPPROTO_ROUTING IPPROTO_ROUTING
+#define IPPROTO_FRAGMENT IPPROTO_FRAGMENT
+#define IPPROTO_ESP IPPROTO_ESP
+#define IPPROTO_AH IPPROTO_AH
+#define IPPROTO_ICMPV6 IPPROTO_ICMPV6
+#define IPPROTO_NONE IPPROTO_NONE
+#define IPPROTO_DSTOPTS IPPROTO_DSTOPTS
+
+/* Standard well-known ports. *//* from winsup/include/netinet/in.h */
+enum
+{
+ IPPORT_ECHO = 7, /* Echo service. */
+ IPPORT_DISCARD = 9, /* Discard transmissions service. */
+ IPPORT_SYSTAT = 11, /* System status service. */
+ IPPORT_DAYTIME = 13, /* Time of day service. */
+ IPPORT_NETSTAT = 15, /* Network status service. */
+ IPPORT_FTP = 21, /* File Transfer Protocol. */
+ IPPORT_TELNET = 23, /* Telnet protocol. */
+ IPPORT_SMTP = 25, /* Simple Mail Transfer Protocol. */
+ IPPORT_TIMESERVER = 37, /* Timeserver service. */
+ IPPORT_NAMESERVER = 42, /* Domain Name Service. */
+ IPPORT_WHOIS = 43, /* Internet Whois service. */
+ IPPORT_MTP = 57,
+
+ IPPORT_TFTP = 69, /* Trivial File Transfer Protocol. */
+ IPPORT_RJE = 77,
+ IPPORT_FINGER = 79, /* Finger service. */
+ IPPORT_TTYLINK = 87,
+ IPPORT_SUPDUP = 95, /* SUPDUP protocol. */
+
+
+ IPPORT_EXECSERVER = 512, /* execd service. */
+ IPPORT_LOGINSERVER = 513, /* rlogind service. */
+ IPPORT_CMDSERVER = 514,
+ IPPORT_EFSSERVER = 520,
+
+ /* UDP ports. */
+ IPPORT_BIFFUDP = 512,
+ IPPORT_WHOSERVER = 513,
+ IPPORT_ROUTESERVER = 520,
+
+ /* Ports less than this value are reserved for privileged processes. */
+ IPPORT_RESERVED = 1024,
+
+ /* Ports greater this value are reserved for (non-privileged) servers. */
+ IPPORT_USERRESERVED = 5000
+};
+
+/* Internet address. */
+struct in_addr
+{
+ in_addr_t s_addr;
+};
+
+/* Request struct for multicast socket ops */
+
+struct ip_mreq
+{
+ struct in_addr imr_multiaddr; /* IP multicast address of group */
+ struct in_addr imr_interface; /* local IP address of interface */
+};
+
+
+/* Structure describing an Internet (IP) socket address. */
+#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */
+struct sockaddr_in
+{
+ sa_family_t sin_family; /* Address family */
+ in_port_t sin_port; /* Port number */
+ struct in_addr sin_addr; /* Internet address */
+
+ /* Pad to size of `struct sockaddr'. */
+ unsigned char __pad[__SOCK_SIZE__ - sizeof(short int)
+ - sizeof(unsigned short int) - sizeof(struct in_addr)];
+};
+#define sin_zero __pad /* for BSD UNIX comp. -FvK */
+
+/*
+ * Definitions of the bits in an Internet address integer.
+ * On subnets, host and network parts are found according
+ * to the subnet mask, not these masks.
+ */
+#define IN_CLASSA(a) ((((long int) (a)) & 0x80000000) == 0)
+#define IN_CLASSA_NET 0xff000000
+#define IN_CLASSA_NSHIFT 24
+#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET)
+#define IN_CLASSA_MAX 128
+
+#define IN_CLASSB(a) ((((long int) (a)) & 0xc0000000) == 0x80000000)
+#define IN_CLASSB_NET 0xffff0000
+#define IN_CLASSB_NSHIFT 16
+#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET)
+#define IN_CLASSB_MAX 65536
+
+#define IN_CLASSC(a) ((((long int) (a)) & 0xe0000000) == 0xc0000000)
+#define IN_CLASSC_NET 0xffffff00
+#define IN_CLASSC_NSHIFT 8
+#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET)
+
+#define IN_CLASSD(a) ((((long int) (a)) & 0xf0000000) == 0xe0000000)
+#define IN_MULTICAST(a) IN_CLASSD(a)
+#define IN_MULTICAST_NET 0xF0000000
+
+#define IN_EXPERIMENTAL(a) ((((long int) (a)) & 0xe0000000) == 0xe0000000)
+#define IN_BADCLASS(a) ((((long int) (a)) & 0xf0000000) == 0xf0000000)
+
+/* Address to accept any incoming messages. */
+#define INADDR_ANY ((unsigned long int) 0x00000000)
+
+/* Address to send to all hosts. */
+#define INADDR_BROADCAST ((unsigned long int) 0xffffffff)
+
+/* Address indicating an error return. */
+#define INADDR_NONE 0xffffffff
+
+/* Network number for local host loopback. */
+#define IN_LOOPBACKNET 127
+
+/* Address to loopback in software to local host. */
+#define INADDR_LOOPBACK 0x7f000001 /* 127.0.0.1 */
+#define IN_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000)
+
+/* Defines for Multicast INADDR */
+#define INADDR_UNSPEC_GROUP 0xe0000000 /* 224.0.0.0 */
+#define INADDR_ALLHOSTS_GROUP 0xe0000001 /* 224.0.0.1 */
+#define INADDR_MAX_LOCAL_GROUP 0xe00000ff /* 224.0.0.255 */
+
+#define INET_ADDRSTRLEN 16
+
+/* <asm/byteorder.h> contains the htonl type stuff.. */
+
+#include <asm/byteorder.h>
+
+/* Some random defines to make it easier in the kernel.. */
+#ifdef __KERNEL__
+
+#define LOOPBACK(x) (((x) & htonl(0xff000000)) == htonl(0x7f000000))
+#define MULTICAST(x) (((x) & htonl(0xf0000000)) == htonl(0xe0000000))
+
+#endif
+
+#ifdef AF_INET6
+#include <cygwin/in6.h>
+#endif
+#endif /* _CYGWIN_IN_H */
diff --git a/winsup/cygwin/include/cygwin/in6.h b/winsup/cygwin/include/cygwin/in6.h
new file mode 100644
index 00000000000..ef73588f49c
--- /dev/null
+++ b/winsup/cygwin/include/cygwin/in6.h
@@ -0,0 +1,119 @@
+/* cygwin/in6.h
+
+ Copyright 2006 Red Hat, Inc.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+/* NOTE: This file is NOT for direct inclusion. Use netinet/in.h. */
+
+#ifndef _CYGWIN_IN6_H
+#define _CYGWIN_IN6_H
+
+#define INET6_ADDRSTRLEN 46
+
+#define IN6_ARE_ADDR_EQUAL(a, b) \
+ (((const uint32_t *)(a))[0] == ((const uint32_t *)(b))[0] \
+ && ((const uint32_t *)(a))[1] == ((const uint32_t *)(b))[1] \
+ && ((const uint32_t *)(a))[2] == ((const uint32_t *)(b))[2] \
+ && ((const uint32_t *)(a))[3] == ((const uint32_t *)(b))[3])
+
+#define IN6_IS_ADDR_UNSPECIFIED(addr) \
+ (((const uint32_t *)(addr))[0] == 0 \
+ && ((const uint32_t *)(addr))[1] == 0 \
+ && ((const uint32_t *)(addr))[2] == 0 \
+ && ((const uint32_t *)(addr))[3] == 0)
+
+#define IN6_IS_ADDR_LOOPBACK(addr) \
+ (((const uint32_t *)(addr))[0] == 0 \
+ && ((const uint32_t *)(addr))[1] == 0 \
+ && ((const uint32_t *)(addr))[2] == 0 \
+ && ((const uint32_t *)(addr))[3] == htonl (1))
+
+#define IN6_IS_ADDR_MULTICAST(addr) (((const uint8_t *) (addr))[0] == 0xff)
+
+#define IN6_IS_ADDR_LINKLOCAL(addr) \
+ ((((const uint16_t *)(addr))[0] & htons (0xffc0)) == htons (0xfe80))
+
+#define IN6_IS_ADDR_SITELOCAL(addr) \
+ ((((const uint16_t *)(addr))[0] & htons (0xffc0)) == htons (0xfec0))
+
+#define IN6_IS_ADDR_V4MAPPED(addr) \
+ (((const uint32_t *)(addr))[0] == 0 \
+ && ((const uint32_t *)(addr))[1] == 0 \
+ && ((const uint32_t *)(addr))[2] == htonl (0xffff))
+
+#define IN6_IS_ADDR_V4COMPAT(addr) \
+ (((const uint32_t *)(addr))[0] == 0 \
+ && ((const uint32_t *)(addr))[1] == 0 \
+ && ((const uint32_t *)(addr))[2] == 0 \
+ && ntohl (((const uint32_t *)(addr))[3]) > 1)
+
+#define IN6_IS_ADDR_MC_NODELOCAL(addr) \
+ (IN6_IS_ADDR_MULTICAST(addr) \
+ && (((const uint8_t *)(addr))[1] & 0xf) == 0x1)
+
+#define IN6_IS_ADDR_MC_LINKLOCAL(addr) \
+ (IN6_IS_ADDR_MULTICAST (addr) \
+ && (((const uint8_t *)(addr))[1] & 0xf) == 0x2)
+
+#define IN6_IS_ADDR_MC_SITELOCAL(addr) \
+ (IN6_IS_ADDR_MULTICAST(addr) \
+ && (((const uint8_t *)(addr))[1] & 0xf) == 0x5)
+
+#define IN6_IS_ADDR_MC_ORGLOCAL(addr) \
+ (IN6_IS_ADDR_MULTICAST(addr) \
+ && (((const uint8_t *)(addr))[1] & 0xf) == 0x8)
+
+#define IN6_IS_ADDR_MC_GLOBAL(addr) \
+ (IN6_IS_ADDR_MULTICAST(addr) \
+ && (((const uint8_t *)(addr))[1] & 0xf) == 0xe)
+
+struct in6_addr
+{
+ union
+ {
+ uint8_t __s6_addr_u[16];
+ uint16_t __s6_addr16[8];
+ uint32_t __s6_addr32[4];
+ } __u6;
+#define s6_addr __u6.__s6_addr
+#define s6_addr16 __u6.__s6_addr16
+#define s6_addr32 __u6.__s6_addr32
+};
+
+struct ipv6_mreq
+{
+ struct in6_addr ipv6mr_multiaddr;
+ unsigned int ipv6mr_interface;
+};
+
+struct in6_pktinfo
+{
+ struct in6_addr ipi6_addr;
+ unsigned int ipi6_ifindex;
+};
+
+#ifdef __INSIDE_CYGWIN__
+typedef uint16_t in_port_t;
+#endif
+
+struct sockaddr_in6
+{
+ sa_family_t sin6_family; /* AF_INET6 */
+ in_port_t sin6_port; /* Port number. */
+ uint32_t sin6_flowinfo; /* Traffic class and flow inf. */
+ struct in6_addr sin6_addr; /* IPv6 address. */
+ uint32_t sin6_scope_id; /* Set of interfaces for a scope. */
+};
+
+#define IN6ADDR_ANY_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+#define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }
+
+extern const struct in6_addr in6addr_any;
+extern const struct in6_addr in6addr_loopback;
+
+#endif /* _CYGWIN_IN6_H */
diff --git a/winsup/cygwin/include/cygwin/socket.h b/winsup/cygwin/include/cygwin/socket.h
new file mode 100644
index 00000000000..33aec8c6306
--- /dev/null
+++ b/winsup/cygwin/include/cygwin/socket.h
@@ -0,0 +1,277 @@
+/* cygwin/socket.h
+
+ Copyright 1999, 2000, 2001, 2005 Red Hat, Inc.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#ifndef _CYGWIN_SOCKET_H
+#define _CYGWIN_SOCKET_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <stdint.h>
+
+/* Not unsigned for backward compatibility. Keep #define for backward
+ compatibility. */
+#ifndef socklen_t
+typedef int socklen_t;
+#define socklen_t socklen_t
+#endif
+
+typedef uint16_t sa_family_t;
+
+struct sockaddr {
+ sa_family_t sa_family; /* address family, AF_xxx */
+ char sa_data[14]; /* 14 bytes of protocol address */
+};
+
+/* Definition of sockaddr_storage according to SUSv3. */
+#define _SS_MAXSIZE 128 /* Maximum size. */
+#define _SS_ALIGNSIZE (sizeof (int64_t))/* Desired alignment. */
+#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof (sa_family_t))
+#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (sa_family_t) \
+ + _SS_PAD1SIZE + _SS_ALIGNSIZE))
+
+struct sockaddr_storage {
+ sa_family_t ss_family;
+ char _ss_pad1[_SS_PAD1SIZE];
+ int64_t __ss_align;
+ char _ss_pad2[_SS_PAD2SIZE];
+};
+
+#include <asm/socket.h> /* arch-dependent defines */
+#include <cygwin/sockios.h> /* the SIOCxxx I/O controls */
+#include <cygwin/uio.h> /* iovec support */
+#include <sys/types.h>
+
+struct ucred {
+ pid_t pid;
+ __uid32_t uid;
+ __gid32_t gid;
+};
+
+struct linger {
+ unsigned short l_onoff; /* Linger active */
+ unsigned short l_linger; /* How long to linger for */
+};
+
+struct msghdr
+{
+ void * msg_name; /* Socket name */
+ socklen_t msg_namelen; /* Length of name */
+ struct iovec * msg_iov; /* Data blocks */
+ int msg_iovlen; /* Number of blocks */
+ void * msg_control; /* Ancillary data */
+ socklen_t msg_controllen; /* Ancillary data buffer length */
+ int msg_flags; /* Received flags on recvmsg */
+};
+
+struct cmsghdr
+{
+ socklen_t cmsg_len; /* Length of cmsghdr + data */
+ int cmsg_level; /* Protocol */
+ int cmsg_type; /* Protocol type */
+};
+
+#define CMSG_ALIGN(len) \
+ (((len) + sizeof (size_t) - 1) & ~(sizeof (size_t) - 1))
+#define CMSG_LEN(len) \
+ (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
+#define CMSG_SPACE(len) \
+ (CMSG_ALIGN (sizeof (struct cmsghdr)) + CMSG_ALIGN(len))
+#define CMSG_FIRSTHDR(mhdr) \
+ ({ \
+ struct msghdr *_m = (struct msghdr *) mhdr; \
+ (unsigned) (_m)->msg_controllen >= sizeof (struct cmsghdr) \
+ ? (struct cmsghdr *) (_m)->msg_control \
+ : (struct cmsghdr *) NULL; \
+ })
+#define CMSG_NXTHDR(mhdr,cmsg) \
+ ({ \
+ struct msghdr *_m = (struct msghdr *) mhdr; \
+ struct cmsghdr *_c = (struct cmsghdr *) cmsg; \
+ ((char *) _c + CMSG_SPACE (_c->cmsg_len) \
+ > (char *) _m->msg_control + _m->msg_controllen) \
+ ? (struct cmsghdr *) NULL \
+ : (struct cmsghdr *) ((char *) _c + CMSG_ALIGN (_c->cmsg_len)); \
+ })
+#define CMSG_DATA(cmsg) \
+ ((unsigned char *) ((struct cmsghdr *)(cmsg) + 1))
+
+/* "Socket"-level control message types: */
+#define SCM_RIGHTS 0x01 /* access rights (array of int) */
+
+#ifdef __INSIDE_CYGWIN__
+/* Definition of struct msghdr up to release 1.5.18 */
+struct OLD_msghdr
+{
+ void * msg_name; /* Socket name */
+ int msg_namelen; /* Length of name */
+ struct iovec * msg_iov; /* Data blocks */
+ int msg_iovlen; /* Number of blocks */
+ void * msg_accrights; /* Per protocol magic */
+ /* (eg BSD descriptor passing) */
+ int msg_accrightslen; /* Length of rights list */
+};
+#endif
+
+/* Socket types. */
+#define SOCK_STREAM 1 /* stream (connection) socket */
+#define SOCK_DGRAM 2 /* datagram (conn.less) socket */
+#define SOCK_RAW 3 /* raw socket */
+#define SOCK_RDM 4 /* reliably-delivered message */
+#define SOCK_SEQPACKET 5 /* sequential packet socket */
+
+/* Supported address families. */
+/*
+ * Address families.
+ */
+#define AF_UNSPEC 0 /* unspecified */
+#define AF_UNIX 1 /* local to host (pipes, portals) */
+#define AF_LOCAL 1 /* POSIX name for AF_UNIX */
+#define AF_INET 2 /* internetwork: UDP, TCP, etc. */
+#define AF_IMPLINK 3 /* arpanet imp addresses */
+#define AF_PUP 4 /* pup protocols: e.g. BSP */
+#define AF_CHAOS 5 /* mit CHAOS protocols */
+#define AF_NS 6 /* XEROX NS protocols */
+#define AF_ISO 7 /* ISO protocols */
+#define AF_OSI AF_ISO /* OSI is ISO */
+#define AF_ECMA 8 /* european computer manufacturers */
+#define AF_DATAKIT 9 /* datakit protocols */
+#define AF_CCITT 10 /* CCITT protocols, X.25 etc */
+#define AF_SNA 11 /* IBM SNA */
+#define AF_DECnet 12 /* DECnet */
+#define AF_DLI 13 /* Direct data link interface */
+#define AF_LAT 14 /* LAT */
+#define AF_HYLINK 15 /* NSC Hyperchannel */
+#define AF_APPLETALK 16 /* AppleTalk */
+#define AF_NETBIOS 17 /* NetBios-style addresses */
+#define AF_INET6 23 /* IP version 6 */
+
+#define AF_MAX 32
+/*
+ * Protocol families, same as address families for now.
+ */
+#define PF_UNSPEC AF_UNSPEC
+#define PF_UNIX AF_UNIX
+#define PF_LOCAL AF_LOCAL
+#define PF_INET AF_INET
+#define PF_IMPLINK AF_IMPLINK
+#define PF_PUP AF_PUP
+#define PF_CHAOS AF_CHAOS
+#define PF_NS AF_NS
+#define PF_ISO AF_ISO
+#define PF_OSI AF_OSI
+#define PF_ECMA AF_ECMA
+#define PF_DATAKIT AF_DATAKIT
+#define PF_CCITT AF_CCITT
+#define PF_SNA AF_SNA
+#define PF_DECnet AF_DECnet
+#define PF_DLI AF_DLI
+#define PF_LAT AF_LAT
+#define PF_HYLINK AF_HYLINK
+#define PF_APPLETALK AF_APPLETALK
+#define PF_NETBIOS AF_NETBIOS
+#define PF_INET6 AF_INET6
+
+#define PF_MAX AF_MAX
+
+/* Maximum queue length specificable by listen. */
+#define SOMAXCONN 0x7fffffff
+
+/* Flags we can use with send/ and recv. */
+#define MSG_OOB 0x1 /* process out-of-band data */
+#define MSG_PEEK 0x2 /* peek at incoming message */
+#define MSG_DONTROUTE 0x4 /* send without using routing tables */
+#define MSG_WINMASK 0x7 /* flags understood by WinSock calls */
+#define MSG_NOSIGNAL 0x20 /* Don't raise SIGPIPE */
+#define MSG_TRUNC 0x0100 /* Normal data truncated */
+#define MSG_CTRUNC 0x0200 /* Control data truncated */
+
+/* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx */
+#define SOL_IP 0
+#define SOL_IPX 256
+#define SOL_AX25 257
+#define SOL_ATALK 258
+#define SOL_NETROM 259
+#define SOL_TCP 6
+#define SOL_UDP 17
+
+/* IP options */
+#ifndef IPTOS_LOWDELAY
+#define IPTOS_LOWDELAY 0x10
+#define IPTOS_THROUGHPUT 0x08
+#define IPTOS_RELIABILITY 0x04
+#endif
+
+/* These need to appear somewhere around here */
+#define IP_DEFAULT_MULTICAST_TTL 1
+#define IP_DEFAULT_MULTICAST_LOOP 1
+#define IP_MAX_MEMBERSHIPS 20
+
+/* IP options for use with getsockopt/setsockopt */
+#define IP_OPTIONS 1
+#define IP_HDRINCL 2
+#define IP_TOS 3
+#define IP_TTL 4
+#define IP_MULTICAST_IF 9
+#define IP_MULTICAST_TTL 10
+#define IP_MULTICAST_LOOP 11
+#define IP_ADD_MEMBERSHIP 12
+#define IP_DROP_MEMBERSHIP 13
+#define IP_DONTFRAGMENT 14
+#define IP_ADD_SOURCE_MEMBERSHIP 15
+#define IP_DROP_SOURCE_MEMBERSHIP 16
+#define IP_BLOCK_SOURCE 17
+#define IP_UNBLOCK_SOURCE 18
+#define IP_PKTINFO 19
+
+/* IPv6 options for use with getsockopt/setsockopt */
+#define IPV6_UNICAST_HOPS 4
+#define IPV6_MULTICAST_IF 9
+#define IPV6_MULTICAST_HOPS 10
+#define IPV6_MULTICAST_LOOP 11
+#define IPV6_ADD_MEMBERSHIP 12
+#define IPV6_DROP_MEMBERSHIP 13
+#define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
+#define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
+#define IPV6_PKTINFO 19
+
+/* Old WinSock1 values, needed internally */
+#ifdef __INSIDE_CYGWIN__
+#define _WS1_IP_OPTIONS 1
+#define _WS1_IP_MULTICAST_IF 2
+#define _WS1_IP_MULTICAST_TTL 3
+#define _WS1_IP_MULTICAST_LOOP 4
+#define _WS1_IP_ADD_MEMBERSHIP 5
+#define _WS1_IP_DROP_MEMBERSHIP 6
+#define _WS1_IP_TTL 7
+#define _WS1_IP_TOS 8
+#define _WS1_IP_DONTFRAGMENT 9
+#endif
+
+/* IPX options */
+#define IPX_TYPE 1
+
+/* TCP options - this way around because someone left a set in the c library includes */
+#ifndef TCP_NODELAY
+#define TCP_NODELAY 0x0001
+#define TCP_MAXSEG 2
+#endif
+
+/* The various priorities. */
+#define SOPRI_INTERACTIVE 0
+#define SOPRI_NORMAL 1
+#define SOPRI_BACKGROUND 2
+
+#ifdef __cplusplus
+};
+#endif /* __cplusplus */
+
+#endif /* _CYGWIN_SOCKET_H */
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
new file mode 100644
index 00000000000..ab2de7af3dd
--- /dev/null
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -0,0 +1,367 @@
+/* version.h -- Cygwin version numbers and accompanying documentation.
+
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005, 2006 Red Hat, Inc.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+/* Cygwin versioning is relatively complicated because of its status
+ as a shared library. Let's start with how versioning used to be done.
+
+ Historical versioning in Cygwin 16.0 to 19.5:
+
+ In the olden days of Cygwin, we had a dll major and minor version
+ and a registry version. The major number started at 16 because the
+ "b15" GNU-Win32 release of the compiler tools was out when this
+ scheme was started. We incremented the DLL name frequently (for
+ every official release) and towards the end of this period every
+ release used a different shared memory area to prevent DLLs from
+ interfering with each other (embedding a build timestamp into the
+ name of the shared memory area). This turned out to be a Bad Idea
+ (tm) because people needed to mingle separate releases and have
+ them work together more than we thought they would. This was
+ especially problematic when tty info needed to be retained when an
+ old Cygwin executable executed a newer one.
+
+ In the old scheme, we incremented the major number whenever a
+ change to the dll invalidated existing executables. This can
+ happen for a number of reasons, including when functions are
+ removed from the export list of the dll. The minor number was
+ incremented when a change was made that we wanted to record, but
+ that didn't invalidate existing executables. Both numbers were
+ recorded in the executable and in the dll.
+
+ In October 1998 (starting with Cygwin 19.6), we started a new method
+ of Cygwin versioning: */
+
+ /* The DLL major and minor numbers correspond to the "version of
+ the Cygwin shared library". This version is used to track important
+ changes to the DLL and is mainly informative in nature. */
+
+#define CYGWIN_VERSION_DLL_MAJOR 1005
+#define CYGWIN_VERSION_DLL_MINOR 21
+
+ /* Major numbers before CYGWIN_VERSION_DLL_EPOCH are
+ incompatible. */
+
+#define CYGWIN_VERSION_DLL_EPOCH 19
+
+ /* CYGWIN_VERSION_DLL_COMBINED gives us a single number
+ representing the combined DLL major and minor numbers. */
+
+ /* WATCH OUT FOR OCTAL! Don't use, say, "00020" for 0.20 */
+
+#define CYGWIN_VERSION_DLL_MAKE_COMBINED(maj, min) (((maj) * 1000) + min)
+#define CYGWIN_VERSION_DLL_COMBINED \
+ CYGWIN_VERSION_DLL_MAKE_COMBINED (CYGWIN_VERSION_DLL_MAJOR, CYGWIN_VERSION_DLL_MINOR)
+
+ /* Every version of cygwin <= this uses an old, incorrect method
+ to determine signal masks. */
+
+#define CYGWIN_VERSION_DLL_BAD_SIGNAL_MASK 19005
+
+#define CYGWIN_VERSION_USER_API_VERSION_COMBINED \
+ CYGWIN_VERSION_DLL_MAKE_COMBINED (user_data->api_major, user_data->api_minor)
+
+ /* API versions <= this had a termios structure whose members were
+ too small to accomodate modern settings. */
+#define CYGWIN_VERSION_DLL_OLD_TERMIOS 5
+#define CYGWIN_VERSION_DLL_IS_OLD_TERMIOS \
+ (CYGWIN_VERSION_USER_API_VERSION_COMBINED <= CYGWIN_VERSION_DLL_OLD_TERMIOS)
+
+#define CYGWIN_VERSION_DLL_MALLOC_ENV 28
+ /* Old APIs had getc/putc macros that conflict with new CR/LF
+ handling in the stdio buffers */
+#define CYGWIN_VERSION_OLD_STDIO_CRLF_HANDLING \
+ (CYGWIN_VERSION_USER_API_VERSION_COMBINED <= 20)
+
+#define CYGWIN_VERSION_CHECK_FOR_S_IEXEC \
+ (CYGWIN_VERSION_USER_API_VERSION_COMBINED >= 36)
+
+#define CYGWIN_VERSION_CHECK_FOR_OLD_O_NONBLOCK \
+ (CYGWIN_VERSION_USER_API_VERSION_COMBINED <= 28)
+
+#define CYGWIN_VERSION_CHECK_FOR_USING_BIG_TYPES \
+ (CYGWIN_VERSION_USER_API_VERSION_COMBINED >= 79)
+
+#define CYGWIN_VERSION_CHECK_FOR_USING_ANCIENT_MSGHDR \
+ (CYGWIN_VERSION_USER_API_VERSION_COMBINED <= 138)
+
+#define CYGWIN_VERSION_CHECK_FOR_USING_WINSOCK1_VALUES \
+ (CYGWIN_VERSION_USER_API_VERSION_COMBINED <= 138)
+
+ /* API_MAJOR 0.0: Initial version. API_MINOR changes:
+ 1: Export cygwin32_ calls as cygwin_ as well.
+ 2: Export j1, jn, y1, yn.
+ 3: Export dll_noncygwin_dllcrt0.
+ 4: New socket ioctls, revamped ifconf support.
+ 5: Thread support/exports.
+ 6: Change in termios handling.
+ 7: Export scandir and alphasort.
+ 8: Export _ctype_, _sys_errlist, _sys_nerr.
+ 9: Mount-related changes, new cygwin_umount export.
+ Raw device support (tape, floppies).
+ 10: Fast math routine support added.
+ 11: Export seekdir, telldir.
+ 12: Export pthread_join, pthread_detach.
+ 13: Export math funcs gamma and friends, also _j0, _j1, etc.
+ 14: Export snprintf and vnsprintf.
+ 15: Export glob
+ 16: Export cygwin_stackdump
+ 17: Export fast math stuff
+ 18: Stop exporting _strace_wm
+ 19: Export fchown, lchown, lacl
+ 20: regsub, inet_network
+ 21: incompatible change to stdio cr/lf and buffering
+ 22: Export cygwin_logon_user, cygwin_set_impersonation_token.
+ geteuid, getegid return effective uid/gid.
+ getuid, getgid return real uid/gid.
+ seteuid, setegid set only effective uid/gid.
+ setuid, setgid set effective and real uid/gid.
+ 23: Export new dll_crt0 interface and cygwin_user_data for use
+ with crt0 startup code.
+ 24: Export poll and _poll.
+ 25: Export getmode and _getmode.
+ 26: CW_GET_CYGDRIVE_PREFIXES addition to external.cc
+ 27: CW_GETPINFO_FULL addition to external.cc
+ 28: Accidentally bumped by cgf
+ 29: Export hstrerror
+ 30: CW_GET_CYGDRIVE_INFO addition to external.cc
+ 31: Export inet_aton
+ 32: Export getrlimit/setrlimit
+ 33: Export setlogmask
+ 34: Separated out mount table
+ 35: Export drand48, erand48, jrand48, lcong48, lrand48,
+ mrand48, nrand48, seed48, and srand48.
+ 36: Added _cygwin_S_IEXEC, et al
+ 37: [f]pathconv support _PC_POSIX_PERMISSIONS and _PC_POSIX_SECURITY
+ 38: vscanf, vscanf_r, and random pthread functions
+ 39: asctime_r, ctime_r, gmtime_r, localtime_r
+ 40: fchdir
+ 41: __signgam
+ 42: sys_errlist, sys_nerr
+ 43: sigsetjmp, siglongjmp fixed
+ 44: Export dirfd
+ 45: perprocess change, gamma_r, gammaf_r, lgamma_r, lgammaf_r
+ 46: Remove cygwin_getshared
+ 47: Report EOTWarningZoneSize in struct mtget.
+ 48: Export "posix" regex functions
+ 49: Export setutent, endutent, utmpname, getutent, getutid, getutline.
+ 50: Export fnmatch.
+ 51: Export recvmsg, sendmsg.
+ 52: Export strptime
+ 53: Export strlcat, strlcpy.
+ 54: Export __fpclassifyd, __fpclassifyf, __signbitd, __signbitf.
+ 55: Export fcloseall, fcloseall_r.
+ 56: Make ntsec on by default.
+ 57: Export setgroups.
+ 58: Export memalign, valloc, malloc_trim, malloc_usable_size, mallopt,
+ malloc_stats
+ 59: getsid
+ 60: MSG_NOSIGNAL
+ 61: Export getc_unlocked, getchar_unlocked, putc_unlocked,
+ putchar_unlocked
+ 62: Erroneously bumped
+ 63: Export pututline
+ 64: Export fseeko, ftello
+ 65: Export siginterrupt
+ 66: Export nl_langinfo
+ 67: Export pthread_getsequence_np
+ 68: Export netdb stuff
+ 69: Export strtof
+ 70: Export asprintf, _asprintf_r, vasprintf, _vasprintf_r
+ 71: Export strerror_r
+ 72: Export nanosleep
+ 73: Export setreuid32, setreuid, setregid32, setregid
+ 74: Export _strtold a64l hcreate hcreate_r hdestroy hdestroy_r hsearch
+ hsearch_r isblank iswalnum iswalpha iswblank iswcntrl iswctype
+ iswdigit iswgraph iswlower iswprint iswpunct iswspace iswupper
+ iswxdigit l64a mbrlen mbrtowc mbsinit mbsrtowcs mempcpy
+ on_exit setbuffer setlinebuf strndup strnlen tdelete tdestroy
+ tfind towctrans towlower towupper tsearch twalk wcrtomb wcscat
+ wcschr wcscpy wcscspn wcslcat wcslcpy wcsncat wcsncmp wcsncpy
+ wcspbrk wcsrchr wcsrtombs wcsspn wcsstr wctob wctob wctrans
+ wctype wmemchr wmemcmp wmemcpy wmemmove wmemset
+ 75: Export exp2 exp2f fdim fdimf fma fmaf fmax fmaxf fmin fminf lrint
+ lrintf lround lroundf nearbyint nearbyintf remquo remquof
+ round roundf scalbln scalblnf sincos sincosf tgamma tgammaf
+ truncf
+ 76: mallinfo
+ 77: thread-safe exit/at_exit
+ 78: Use stat and fstat rather than _stat, and _fstat.
+ Export btowc and trunc.
+ 79: Export acl32 aclcheck32 aclfrommode32 aclfrompbits32 aclfromtext32
+ aclsort32 acltomode32 acltopbits32 acltotext32 facl32
+ fgetpos64 fopen64 freopen64 fseeko64 fsetpos64 ftello64
+ _open64 _lseek64 _fstat64 _stat64 mknod32
+ 80: Export pthread_rwlock stuff
+ 81: CW_CHECK_NTSEC addition to external.cc
+ 82: Export wcscoll wcswidth wcwidth
+ 83: Export gethostid
+ 84: Pty open allocates invisible console. 64 bit interface
+ 85: Export new 32/64 functions from API 0.79 only with leading
+ underscore. No problems with backward compatibility since no
+ official release has been made so far. This change removes
+ exported symbols like fopen64, which might confuse configure.
+ 86: Export ftok
+ 87: Export vsyslog
+ 88: Export _getreent
+ 89: Export __mempcpy
+ 90: Export _fopen64
+ 91: Export argz_add argz_add_sep argz_append argz_count argz_create
+ argz_create_sep argz_delete argz_extract argz_insert
+ argz_next argz_replace argz_stringify envz_add envz_entry
+ envz_get envz_merge envz_remove envz_strip
+ 92: Export getusershell, setusershell, endusershell
+ 93: Export daemon, forkpty, openpty, iruserok, ruserok, login_tty,
+ openpty, forkpty, revoke, logwtmp, updwtmp
+ 94: Export getopt, getopt_long, optarg, opterr, optind, optopt,
+ optreset, __check_rhosts_file, __rcmd_errstr.
+ 95: Export shmat, shmctl, shmdt, shmget.
+ 96: CW_GET_ERRNO_FROM_WINERROR addition to external.cc
+ 97: Export sem_open, sem_close, sem_timedwait, sem_getvalue.
+ 98: Export _tmpfile64.
+ 99: CW_GET_POSIX_SECURITY_ATTRIBUTE addition to external.cc.
+ 100: CW_GET_SHMLBA addition to external.cc.
+ 101: Export err, errx, verr, verrx, warn, warnx, vwarn, vwarnx.
+ 102: CW_GET_UID_FROM_SID and CW_GET_GID_FROM_SID addition to external.cc.
+ 103: Export getprogname, setprogname.
+ 104: Export msgctl, msgget, msgrcv, msgsnd, semctl, semget, semop.
+ 105: Export sigwait.
+ 106: Export flock.
+ 107: Export fcntl64.
+ 108: Remove unused (hopefully) reent_data export.
+ 109: Oh well. Someone uses reent_data.
+ 110: Export clock_gettime, sigwaitinfo, timer_create, timer_delete,
+ timer_settime
+ 111: Export sigqueue, sighold.
+ 112: Redefine some mtget fields.
+ 113: Again redefine some mtget fields. Use mt_fileno and mt_blkno as
+ on Linux.
+ 114: Export rand_r, ttyname_r.
+ 115: Export flockfile, ftrylockfile, funlockfile, getgrgid_r, getgrnam_r,
+ getlogin_r.
+ 116: Export atoll.
+ 117: Export utmpx functions, Return utmp * from pututent.
+ 118: Export getpriority, setpriority.
+ 119: Export fdatasync.
+ 120: Export basename, dirname.
+ 122: Export statvfs, fstatvfs.
+ 123: Export utmpxname.
+ 124: Add MAP_AUTOGROW flag to mmap.
+ 125: LD_PRELOAD/CW_HOOK available.
+ 126: Export lsearch, lfind, timer_gettime.
+ 127: Export sigrelese.
+ 128: Export pselect.
+ 129: Export mkdtemp.
+ 130: Export strtoimax, strtoumax, llabs, imaxabs, lldiv, imaxdiv.
+ 131: Export inet_ntop, inet_pton.
+ 132: Add GLOB_LIMIT flag to glob.
+ 133: Export __getline, __getdelim.
+ 134: Export getline, getdelim.
+ 135: Export pread, pwrite
+ 136: Add TIOCMBIS/TIOCMBIC ioctl codes.
+ 137: fts_children, fts_close, fts_get_clientptr, fts_get_stream,
+ fts_open, fts_read, fts_set, fts_set_clientptr, ftw, nftw.
+ 138: Export readdir_r.
+ 139: Start using POSIX definition of struct msghdr and WinSock2
+ IPPROTO_IP values.
+ 140: Export mlock, munlock.
+ 141: Export futimes, lutimes.
+ 142: Export memmem
+ 143: Export clock_getres, clock_setres
+ 144: Export timelocal, timegm.
+ 145: Add MAP_NORESERVE flag to mmap.
+ 146: Change SI_USER definition. FIXME: Need to develop compatibility
+ macro for this?
+ 147: Eliminate problematic d_ino from dirent structure. unsetenv now
+ returns int, as per linux.
+ 148: Add open(2) flags O_SYNC, O_RSYNC, O_DSYNC and O_DIRECT.
+ 149: Add open(2) flag O_NOFOLLOW.
+ 150: Export getsubopt.
+ 151: Export __opendir_with_d_ino
+ 152: Revert to having d_ino in dirent unconditionally.
+ 153: Export updwtmpx, Implement CW_SETUP_WINENV.
+ 154: Export sigset, sigignore.
+ 155: Export __isinff, __isinfd, __isnanf, __isnand.
+ 156: Export __srbuf_r, __swget_r.
+ 157: Export gai_strerror, getaddrinfo, getnameinfo, freeaddrinfo,
+ in6addr_any, in6addr_loopback.
+ */
+
+ /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
+
+#define CYGWIN_VERSION_API_MAJOR 0
+#define CYGWIN_VERSION_API_MINOR 157
+
+ /* There is also a compatibity version number associated with the
+ shared memory regions. It is incremented when incompatible
+ changes are made to the shared memory region *or* to any named
+ shared mutexes, semaphores, etc. The arbitrary starting
+ version was 0 (cygwin release 98r2).
+ Bump to 4 since this hasn't been rigorously updated in a
+ while. */
+
+#define CYGWIN_VERSION_SHARED_DATA 4
+
+ /* An identifier used in the names used to create shared objects.
+ The full names include the CYGWIN_VERSION_SHARED_DATA version
+ as well as this identifier. */
+
+#define CYGWIN_VERSION_DLL_IDENTIFIER "cygwin1"
+
+ /* The Cygwin mount table interface in the Win32 registry also
+ has a version number associated with it in case that is
+ changed in a non-backwards compatible fashion. Increment this
+ version number whenever incompatible changes in mount table
+ registry usage are made.
+
+ 1: Original number version.
+ 2: New mount registry layout, system-wide mount accessibility.
+ */
+
+#define CYGWIN_VERSION_MOUNT_REGISTRY 2
+
+ /* Identifiers used in the Win32 registry. */
+
+#define CYGWIN_INFO_CYGNUS_REGISTRY_NAME "Cygnus Solutions"
+#define CYGWIN_INFO_CYGWIN_REGISTRY_NAME "Cygwin"
+#define CYGWIN_INFO_PROGRAM_OPTIONS_NAME "Program Options"
+#define CYGWIN_INFO_CYGWIN_MOUNT_REGISTRY_NAME "mounts v2"
+#define CYGWIN_INFO_CYGDRIVE_FLAGS "cygdrive flags"
+#define CYGWIN_INFO_CYGDRIVE_PREFIX "cygdrive prefix"
+#define CYGWIN_INFO_CYGDRIVE_DEFAULT_PREFIX "/cygdrive"
+
+ /* In addition to the above version number strings, the build
+ process adds some strings that may be useful in
+ debugging/identifying a particular Cygwin DLL:
+
+ The mkvers.sh script at the top level produces a .cc file
+ which initializes a cygwin_version structure based on the
+ above version information and creates a string table for
+ grepping via "fgrep '%%%' cygwinwhatever.dll" if you are
+ using GNU grep. Otherwise you may want to do a
+ "strings cygwinwhatever.dll | fgrep '%%%'" instead.
+
+ This will produce output such as:
+
+ %%% Cygwin dll_identifier: cygwin
+ %%% Cygwin api_major: 0
+ %%% Cygwin api_minor: 0
+ %%% Cygwin dll_major: 19
+ %%% Cygwin dll_minor: 6
+ %%% Cygwin shared_data: 1
+ %%% Cygwin registry: b15
+ %%% Cygwin build date: Wed Oct 14 16:26:51 EDT 1998
+ %%% Cygwin shared id: cygwinS1
+
+ This information can also be obtained through a call to
+ cygwin_internal (CW_GETVERSIONINFO).
+ */
+
+#define CYGWIN_VERSION_MAGIC(a, b) ((unsigned) ((((unsigned short) a) << 16) | (unsigned short) b))
+#define CYGWIN_VERSION_MAGIC_VERSION(a) ((unsigned) ((unsigned)a & 0xffff))
diff --git a/winsup/cygwin/include/netdb.h b/winsup/cygwin/include/netdb.h
new file mode 100644
index 00000000000..89bb1e7c26e
--- /dev/null
+++ b/winsup/cygwin/include/netdb.h
@@ -0,0 +1,227 @@
+/* Original linux netdb.h merged with winsock.h types */
+
+/*-
+ * Copyright (c) 1980, 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)netdb.h 8.1 (Berkeley) 6/2/93
+ * netdb.h,v 1.1.1.1 1995/02/18 05:34:07 hjl Exp
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#ifndef _NETDB_H_
+#define _NETDB_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <cygwin/socket.h>
+
+/*
+ * Structures returned by network data base library. All addresses are
+ * supplied in host order, and returned in network order (suitable for
+ * use in system calls).
+ */
+
+ /* Different from the linux versions - note the shorts.. */
+struct hostent {
+ const char *h_name; /* official name of host */
+ char **h_aliases; /* alias list */
+ short h_addrtype; /* host address type */
+ short h_length; /* length of address */
+ char **h_addr_list; /* list of addresses from name server */
+#define h_addr h_addr_list[0] /* address, for backward compatiblity */
+};
+
+/*
+ * Assumption here is that a network number
+ * fits in an unsigned long -- probably a poor one.
+ */
+
+struct netent {
+ char *n_name; /* official name of net */
+ char **n_aliases; /* alias list */
+ short n_addrtype; /* net address type */
+ uint32_t n_net; /* network # */
+};
+
+struct servent {
+ char *s_name; /* official service name */
+ char **s_aliases; /* alias list */
+ short s_port; /* port # */
+ char *s_proto; /* protocol to use */
+};
+
+struct protoent
+{
+ char *p_name; /* official protocol name */
+ char **p_aliases; /* alias list */
+ short p_proto; /* protocol # */
+};
+
+struct rpcent {
+ char *r_name; /* name of server for this rpc program */
+ char **r_aliases; /* alias list */
+ int r_number; /* rpc program number */
+};
+
+struct addrinfo {
+ int ai_flags; /* input flags */
+ int ai_family; /* address family of socket */
+ int ai_socktype; /* socket type */
+ int ai_protocol; /* ai_protocol */
+ socklen_t ai_addrlen; /* length of socket address */
+ char *ai_canonname; /* canonical name of service location */
+ struct sockaddr *ai_addr; /* socket address of socket */
+ struct addrinfo *ai_next; /* pointer to next in list */
+};
+
+/*
+ * Error return codes from gethostbyname() and gethostbyaddr()
+ * (left in extern int h_errno).
+ */
+
+#ifdef __INSIDE_CYGWIN_NET__
+extern int h_errno;
+#else
+extern __declspec(dllimport) int h_errno;
+#endif
+
+#define NETDB_INTERNAL -1 /* see errno */
+#define NETDB_SUCCESS 0 /* no problem */
+#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */
+#define TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */
+#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
+#define NO_DATA 4 /* Valid name, no data record of requested type */
+#define NO_ADDRESS NO_DATA /* no address, look for MX record */
+
+#define AI_PASSIVE 1
+#define AI_CANONNAME 2
+#define AI_NUMERICHOST 4
+/*
+ * These are not available in the WinSock implementation. It wouldn't make
+ * sense to support them in the ipv4 only case, so we drop them entirely.
+ * We can define them if we run into problems but they are non-functional, so...
+ */
+#if 0
+#define AI_V4MAPPED 16
+#define AI_ALL 32
+#define AI_ADDRCONFIG 64
+#endif
+
+#define NI_NOFQDN 1
+#define NI_NUMERICHOST 2
+#define NI_NAMEREQD 4
+#define NI_NUMERICSERV 8
+#define NI_DGRAM 16
+
+#define NI_MAXHOST 1025
+#define NI_MAXSERV 32
+
+#define EAI_ADDRFAMILY 1
+#define EAI_AGAIN 2
+#define EAI_BADFLAGS 3
+#define EAI_FAIL 4
+#define EAI_FAMILY 5
+#define EAI_MEMORY 6
+#define EAI_NODATA 7
+#define EAI_NONAME 8
+#define EAI_SERVICE 9
+#define EAI_SOCKTYPE 10
+#define EAI_SYSTEM 11
+#define EAI_BADHINTS 12
+#define EAI_PROTOCOL 13
+
+#define EAI_MAX 14
+
+#ifndef __INSIDE_CYGWIN_NET__
+void endhostent (void);
+void endnetent (void);
+void endprotoent (void);
+void endservent (void);
+void endrpcent (void);
+struct hostent *gethostbyaddr (const char *, int, int);
+struct hostent *gethostbyname (const char *);
+struct hostent *gethostent (void);
+struct netent *getnetbyaddr (long, int); /* u_long? */
+struct netent *getnetbyname (const char *);
+struct netent *getnetent (void);
+struct protoent *getprotobyname (const char *);
+struct protoent *getprotobynumber (int);
+struct protoent *getprotoent (void);
+struct servent *getservbyname (const char *, const char *);
+struct servent *getservbyport (int, const char *);
+struct servent *getservent (void);
+struct rpcent *getrpcent (void);
+struct rpcent *getrpcbyname (const char *);
+struct rpcent *getrpcbynumber (int);
+const char *hstrerror (int);
+void herror (const char *);
+void sethostent (int);
+void setnetent (int);
+void setprotoent (int);
+void setservent (int);
+void setrpcent (int);
+void freeaddrinfo (struct addrinfo *);
+const char *gai_strerror (int);
+int getaddrinfo (const char *, const char *,
+ const struct addrinfo *, struct addrinfo **);
+int getnameinfo (const struct sockaddr *, socklen_t, char *,
+ socklen_t, char *, socklen_t, int);
+#endif
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* !_NETDB_H_ */
+
diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc
new file mode 100644
index 00000000000..6391aee8500
--- /dev/null
+++ b/winsup/cygwin/net.cc
@@ -0,0 +1,3629 @@
+/* net.cc: network-related routines.
+
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005, 2006 Red Hat, Inc.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+/* #define DEBUG_NEST_ON 1 */
+
+#define __INSIDE_CYGWIN_NET__
+
+#include "winsup.h"
+#include <ctype.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <syslog.h>
+
+#include <stdlib.h>
+#define gethostname cygwin_gethostname
+#include <unistd.h>
+#undef gethostname
+#include <netdb.h>
+#define USE_SYS_TYPES_FD_SET
+#include <winsock2.h>
+#include <iphlpapi.h>
+#include <assert.h>
+#include "cygerrno.h"
+#include "security.h"
+#include "cygwin/version.h"
+#include "perprocess.h"
+#include "path.h"
+#include "fhandler.h"
+#include "dtable.h"
+#include "cygheap.h"
+#include "sigproc.h"
+#include "pinfo.h"
+#include "registry.h"
+#include "cygtls.h"
+#include "cygwin/in6.h"
+
+extern "C"
+{
+ int h_errno;
+
+ int __stdcall rcmd (char **ahost, unsigned short inport, char *locuser,
+ char *remuser, char *cmd, SOCKET * fd2p);
+ int sscanf (const char *, const char *, ...);
+} /* End of "C" section */
+
+const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
+
+static fhandler_socket *
+get (const int fd)
+{
+ cygheap_fdget cfd (fd);
+
+ if (cfd < 0)
+ return 0;
+
+ fhandler_socket *const fh = cfd->is_socket ();
+
+ if (!fh)
+ set_errno (ENOTSOCK);
+
+ return fh;
+}
+
+/* htonl: standards? */
+extern "C" unsigned long int
+htonl (unsigned long int x)
+{
+ return ((((x & 0x000000ffU) << 24) |
+ ((x & 0x0000ff00U) << 8) |
+ ((x & 0x00ff0000U) >> 8) |
+ ((x & 0xff000000U) >> 24)));
+}
+
+/* ntohl: standards? */
+extern "C" unsigned long int
+ntohl (unsigned long int x)
+{
+ return htonl (x);
+}
+
+/* htons: standards? */
+extern "C" unsigned short
+htons (unsigned short x)
+{
+ return ((((x & 0x000000ffU) << 8) |
+ ((x & 0x0000ff00U) >> 8)));
+}
+
+/* ntohs: standards? */
+extern "C" unsigned short
+ntohs (unsigned short x)
+{
+ return htons (x);
+}
+
+/* exported as inet_ntoa: BSD 4.3 */
+extern "C" char *
+cygwin_inet_ntoa (struct in_addr in)
+{
+ char *res = inet_ntoa (in);
+
+ if (_my_tls.locals.ntoa_buf)
+ {
+ free (_my_tls.locals.ntoa_buf);
+ _my_tls.locals.ntoa_buf = NULL;
+ }
+ if (res)
+ _my_tls.locals.ntoa_buf = strdup (res);
+ return _my_tls.locals.ntoa_buf;
+}
+
+/* exported as inet_addr: BSD 4.3 */
+extern "C" unsigned long
+cygwin_inet_addr (const char *cp)
+{
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return INADDR_NONE;
+ unsigned long res = inet_addr (cp);
+
+ return res;
+}
+
+/* exported as inet_aton: BSD 4.3
+ inet_aton is not exported by wsock32 and ws2_32,
+ so it has to be implemented here. */
+extern "C" int
+cygwin_inet_aton (const char *cp, struct in_addr *inp)
+{
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return 0;
+
+ unsigned long res = inet_addr (cp);
+
+ if (res == INADDR_NONE && strcmp (cp, "255.255.255.255"))
+ return 0;
+ if (inp)
+ inp->s_addr = res;
+ return 1;
+}
+
+extern "C" unsigned int
+cygwin_inet_network (const char *cp)
+{
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return INADDR_NONE;
+ return ntohl (inet_addr (cp));
+}
+
+/* inet_netof is in the standard BSD sockets library. It is useless
+ for modern networks, since it assumes network values which are no
+ longer meaningful, but some existing code calls it. */
+
+extern "C" unsigned long
+inet_netof (struct in_addr in)
+{
+ unsigned long i, res;
+
+ i = ntohl (in.s_addr);
+ if (IN_CLASSA (i))
+ res = (i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT;
+ else if (IN_CLASSB (i))
+ res = (i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT;
+ else
+ res = (i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT;
+
+
+ return res;
+}
+
+/* inet_makeaddr is in the standard BSD sockets library. It is
+ useless for modern networks, since it assumes network values which
+ are no longer meaningful, but some existing code calls it. */
+
+extern "C" struct in_addr
+inet_makeaddr (int net, int lna)
+{
+ unsigned long i;
+ struct in_addr in;
+
+ if (net < IN_CLASSA_MAX)
+ i = (net << IN_CLASSA_NSHIFT) | (lna & IN_CLASSA_HOST);
+ else if (net < IN_CLASSB_MAX)
+ i = (net << IN_CLASSB_NSHIFT) | (lna & IN_CLASSB_HOST);
+ else if (net < 0x1000000)
+ i = (net << IN_CLASSC_NSHIFT) | (lna & IN_CLASSC_HOST);
+ else
+ i = net | lna;
+
+ in.s_addr = htonl (i);
+
+
+ return in;
+}
+
+struct tl
+{
+ int w;
+ const char *s;
+ int e;
+};
+
+static NO_COPY struct tl errmap[] = {
+ {WSAEINTR, "WSAEINTR", EINTR},
+ {WSAEWOULDBLOCK, "WSAEWOULDBLOCK", EWOULDBLOCK},
+ {WSAEINPROGRESS, "WSAEINPROGRESS", EINPROGRESS},
+ {WSAEALREADY, "WSAEALREADY", EALREADY},
+ {WSAENOTSOCK, "WSAENOTSOCK", ENOTSOCK},
+ {WSAEDESTADDRREQ, "WSAEDESTADDRREQ", EDESTADDRREQ},
+ {WSAEMSGSIZE, "WSAEMSGSIZE", EMSGSIZE},
+ {WSAEPROTOTYPE, "WSAEPROTOTYPE", EPROTOTYPE},
+ {WSAENOPROTOOPT, "WSAENOPROTOOPT", ENOPROTOOPT},
+ {WSAEPROTONOSUPPORT, "WSAEPROTONOSUPPORT", EPROTONOSUPPORT},
+ {WSAESOCKTNOSUPPORT, "WSAESOCKTNOSUPPORT", ESOCKTNOSUPPORT},
+ {WSAEOPNOTSUPP, "WSAEOPNOTSUPP", EOPNOTSUPP},
+ {WSAEPFNOSUPPORT, "WSAEPFNOSUPPORT", EPFNOSUPPORT},
+ {WSAEAFNOSUPPORT, "WSAEAFNOSUPPORT", EAFNOSUPPORT},
+ {WSAEADDRINUSE, "WSAEADDRINUSE", EADDRINUSE},
+ {WSAEADDRNOTAVAIL, "WSAEADDRNOTAVAIL", EADDRNOTAVAIL},
+ {WSAENETDOWN, "WSAENETDOWN", ENETDOWN},
+ {WSAENETUNREACH, "WSAENETUNREACH", ENETUNREACH},
+ {WSAENETRESET, "WSAENETRESET", ENETRESET},
+ {WSAECONNABORTED, "WSAECONNABORTED", ECONNABORTED},
+ {WSAECONNRESET, "WSAECONNRESET", ECONNRESET},
+ {WSAENOBUFS, "WSAENOBUFS", ENOBUFS},
+ {WSAEISCONN, "WSAEISCONN", EISCONN},
+ {WSAENOTCONN, "WSAENOTCONN", ENOTCONN},
+ {WSAESHUTDOWN, "WSAESHUTDOWN", ESHUTDOWN},
+ {WSAETOOMANYREFS, "WSAETOOMANYREFS", ETOOMANYREFS},
+ {WSAETIMEDOUT, "WSAETIMEDOUT", ETIMEDOUT},
+ {WSAECONNREFUSED, "WSAECONNREFUSED", ECONNREFUSED},
+ {WSAELOOP, "WSAELOOP", ELOOP},
+ {WSAENAMETOOLONG, "WSAENAMETOOLONG", ENAMETOOLONG},
+ {WSAEHOSTDOWN, "WSAEHOSTDOWN", EHOSTDOWN},
+ {WSAEHOSTUNREACH, "WSAEHOSTUNREACH", EHOSTUNREACH},
+ {WSAENOTEMPTY, "WSAENOTEMPTY", ENOTEMPTY},
+ {WSAEPROCLIM, "WSAEPROCLIM", EPROCLIM},
+ {WSAEUSERS, "WSAEUSERS", EUSERS},
+ {WSAEDQUOT, "WSAEDQUOT", EDQUOT},
+ {WSAESTALE, "WSAESTALE", ESTALE},
+ {WSAEREMOTE, "WSAEREMOTE", EREMOTE},
+ {WSAEINVAL, "WSAEINVAL", EINVAL},
+ {WSAEFAULT, "WSAEFAULT", EFAULT},
+ {0, "NOERROR", 0},
+ {0, NULL, 0}
+};
+
+static int
+find_winsock_errno (int why)
+{
+ for (int i = 0; errmap[i].s != NULL; ++i)
+ if (why == errmap[i].w)
+ return errmap[i].e;
+
+ return EPERM;
+}
+
+void
+__set_winsock_errno (const char *fn, int ln)
+{
+ DWORD werr = WSAGetLastError ();
+ int err = find_winsock_errno (werr);
+
+ set_errno (err);
+ syscall_printf ("%s:%d - winsock error %d -> errno %d", fn, ln, werr, err);
+}
+
+/*
+ * Since the member `s' isn't used for debug output we can use it
+ * for the error text returned by herror and hstrerror.
+ */
+static NO_COPY struct tl host_errmap[] = {
+ {WSAHOST_NOT_FOUND, "Unknown host", HOST_NOT_FOUND},
+ {WSATRY_AGAIN, "Host name lookup failure", TRY_AGAIN},
+ {WSANO_RECOVERY, "Unknown server error", NO_RECOVERY},
+ {WSANO_DATA, "No address associated with name", NO_DATA},
+ {0, NULL, 0}
+};
+
+static void
+set_host_errno ()
+{
+ int i;
+
+ int why = WSAGetLastError ();
+
+ for (i = 0; host_errmap[i].w != 0; ++i)
+ if (why == host_errmap[i].w)
+ break;
+
+ if (host_errmap[i].w != 0)
+ h_errno = host_errmap[i].e;
+ else
+ h_errno = NETDB_INTERNAL;
+}
+
+inline int
+DWORD_round (int n)
+{
+ return sizeof (DWORD) * (((n + sizeof (DWORD) - 1)) / sizeof (DWORD));
+}
+
+inline int
+strlen_round (const char *s)
+{
+ if (!s)
+ return 0;
+ return DWORD_round (strlen (s) + 1);
+}
+
+#pragma pack(push,2)
+struct pservent
+{
+ char *s_name;
+ char **s_aliases;
+ short s_port;
+ char *s_proto;
+};
+#pragma pack(pop)
+
+struct unionent
+{
+ char *name;
+ char **list;
+ short port_proto_addrtype;
+ short h_len;
+ union
+ {
+ char *s_proto;
+ char **h_addr_list;
+ };
+};
+
+enum struct_type
+{
+ t_hostent, t_protoent, t_servent
+};
+
+static const char *entnames[] = {"host", "proto", "serv"};
+
+/* Generic "dup a {host,proto,serv}ent structure" function.
+ This is complicated because we need to be able to free the
+ structure at any point and we can't rely on the pointer contents
+ being untouched by callers. So, we allocate a chunk of memory
+ large enough to hold the structure and all of the stuff it points
+ to then we copy the source into this new block of memory.
+ The 'unionent' struct is a union of all of the currently used
+ *ent structure. */
+
+#define dup_ent(old, src, type) __dup_ent ((unionent *&) (_my_tls.locals.old), (unionent *) (src), type)
+#ifdef DEBUGGING
+static void *
+#else
+static inline void *
+#endif
+__dup_ent (unionent *&dst, unionent *src, struct_type type)
+{
+ if (dst)
+ debug_printf ("old %sent structure \"%s\" %p\n", entnames[type],
+ ((unionent *) dst)->name, dst);
+
+ if (!src)
+ {
+ set_winsock_errno ();
+ return NULL;
+ }
+
+ debug_printf ("duping %sent \"%s\", %p", entnames[type], src->name, src);
+
+ /* Find the size of the raw structure minus any character strings, etc. */
+ int sz, struct_sz;
+ switch (type)
+ {
+ case t_protoent:
+ struct_sz = sizeof (protoent);
+ break;
+ case t_servent:
+ struct_sz = sizeof (servent);
+ break;
+ case t_hostent:
+ struct_sz = sizeof (hostent);
+ break;
+ default:
+ api_fatal ("called with invalid value %d", type);
+ break;
+ }
+
+ /* Every *ent begins with a name. Calculate it's length. */
+ int namelen = strlen_round (src->name);
+ sz = struct_sz + namelen;
+
+ char **av;
+ /* The next field in every *ent is an argv list of "something".
+ Calculate the number of components and how much space the
+ character strings will take. */
+ int list_len = 0;
+ for (av = src->list; av && *av; av++)
+ {
+ list_len++;
+ sz += sizeof (char **) + strlen_round (*av);
+ }
+
+ /* NULL terminate if there actually was a list */
+ if (av)
+ {
+ sz += sizeof (char **);
+ list_len++;
+ }
+
+ /* Do servent/hostent specific processing */
+ int protolen = 0;
+ int addr_list_len = 0;
+ char *s_proto = NULL;
+ if (type == t_servent)
+ {
+ if (src->s_proto)
+ {
+ /* Windows 95 idiocy. Structure is misaligned on Windows 95.
+ Kludge around this by trying a different pointer alignment. */
+ if (!IsBadStringPtr (src->s_proto, INT32_MAX))
+ s_proto = src->s_proto;
+ else if (!IsBadStringPtr (((pservent *) src)->s_proto, INT32_MAX))
+ s_proto = ((pservent *) src)->s_proto;
+ sz += (protolen = strlen_round (s_proto));
+ }
+ }
+ else if (type == t_hostent)
+ {
+ /* Calculate the length and storage used for h_addr_list */
+ for (av = src->h_addr_list; av && *av; av++)
+ {
+ addr_list_len++;
+ sz += sizeof (char **) + DWORD_round (src->h_len);
+ }
+ if (av)
+ {
+ sz += sizeof (char **);
+ addr_list_len++;
+ }
+ }
+
+ /* Allocate the storage needed. Allocate a rounded size to attempt to force
+ reuse of this buffer so that a poorly-written caller will not be using
+ a freed buffer. */
+ unsigned rsz = 256 * ((sz + 255) / 256);
+ dst = (unionent *) realloc (dst, rsz);
+
+ /* Hopefully, this worked. */
+ if (dst)
+ {
+ memset (dst, 0, sz);
+ /* This field is common to all *ent structures but named differently
+ in each, of course. */
+ dst->port_proto_addrtype = src->port_proto_addrtype;
+
+ char *dp = ((char *) dst) + struct_sz;
+ if (namelen)
+ {
+ /* Copy the name field to dst, using space just beyond the end of
+ the dst structure. */
+ strcpy (dst->name = dp, src->name);
+ dp += namelen;
+ }
+
+ /* Copy the 'list' type to dst, using space beyond end of structure
+ + storage for name. */
+ if (src->list)
+ {
+ char **dav = dst->list = (char **) dp;
+ dp += sizeof (char **) * list_len;
+ for (av = src->list; av && *av; av++)
+ {
+ int len = strlen (*av) + 1;
+ memcpy (*dav++ = dp, *av, len);
+ dp += DWORD_round (len);
+ }
+ }
+
+ /* Do servent/protoent/hostent specific processing. */
+ if (type == t_protoent)
+ debug_printf ("protoent %s %x %x", dst->name, dst->list, dst->port_proto_addrtype);
+ else if (type == t_servent)
+ {
+ if (s_proto)
+ {
+ strcpy (dst->s_proto = dp, s_proto);
+ dp += protolen;
+ }
+ }
+ else if (type == t_hostent)
+ {
+ /* Transfer h_len and duplicate contents of h_addr_list, using
+ memory after 'list' allocation. */
+ dst->h_len = src->h_len;
+ char **dav = dst->h_addr_list = (char **) dp;
+ dp += sizeof (char **) * addr_list_len;
+ for (av = src->h_addr_list; av && *av; av++)
+ {
+ memcpy (*dav++ = dp, *av, src->h_len);
+ dp += DWORD_round (src->h_len);
+ }
+ }
+ /* Sanity check that we did our bookkeeping correctly. */
+ assert ((dp - (char *) dst) == sz);
+ }
+ debug_printf ("duped %sent \"%s\", %p", entnames[type], dst ? dst->name : "<null!>", dst);
+ return dst;
+}
+
+/* exported as getprotobyname: standards? */
+extern "C" struct protoent *
+cygwin_getprotobyname (const char *p)
+{
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return NULL;
+ return (protoent *) dup_ent (protoent_buf, getprotobyname (p), t_protoent);
+}
+
+/* exported as getprotobynumber: standards? */
+extern "C" struct protoent *
+cygwin_getprotobynumber (int number)
+{
+ return (protoent *) dup_ent (protoent_buf, getprotobynumber (number), t_protoent);
+}
+
+bool
+fdsock (cygheap_fdmanip& fd, const device *dev, SOCKET soc)
+{
+ if (wincap.has_set_handle_information ())
+ {
+ /* NT systems apparently set sockets to inheritable by default */
+ SetHandleInformation ((HANDLE) soc, HANDLE_FLAG_INHERIT, 0);
+ debug_printf ("reset socket inheritance");
+ }
+ else
+ debug_printf ("not setting socket inheritance");
+ fd = build_fh_dev (*dev);
+ if (!fd.isopen ())
+ return false;
+ fd->set_io_handle ((HANDLE) soc);
+ fd->set_flags (O_RDWR | O_BINARY);
+ fd->uninterruptible_io (true);
+ cygheap->fdtab.inc_need_fixup_before ();
+ debug_printf ("fd %d, name '%s', soc %p", (int) fd, dev->name, soc);
+#if 0
+ /* Same default buffer sizes as on Linux (instead of WinSock default 8K).
+
+ NOT. If the SO_RCVBUF size exceeds 65535(*), and if the socket is
+ connected to a remote machine, then duplicating the socket on
+ fork/exec fails with WinSock error 10022, WSAEINVAL. Given that,
+ there's not any good reason to set the buffer sizes at all. So we
+ stick with the defaults. However, an explanation for this weird
+ behaviour would be nice. I keep this stuff in the code for later
+ generations. Archeological programmers might find it useful.
+
+ (*) Maximum normal TCP window size. Coincidence? */
+
+ int rmem = dev == tcp_dev ? 87380 : 120832;
+ int wmem = dev == tcp_dev ? 16384 : 120832;
+ if (::setsockopt (soc, SOL_SOCKET, SO_RCVBUF, (char *) &rmem, sizeof (int)))
+ debug_printf ("setsockopt(SO_RCVBUF) failed, %lu", WSAGetLastError ());
+ if (::setsockopt (soc, SOL_SOCKET, SO_SNDBUF, (char *) &wmem, sizeof (int)))
+ debug_printf ("setsockopt(SO_SNDBUF) failed, %lu", WSAGetLastError ());
+#endif
+ return true;
+}
+
+/* exported as socket: standards? */
+extern "C" int
+cygwin_socket (int af, int type, int protocol)
+{
+ int res = -1;
+ SOCKET soc = 0;
+
+ debug_printf ("socket (%d, %d, %d)", af, type, protocol);
+
+ soc = socket (af == AF_LOCAL ? AF_INET : af, type,
+ af == AF_LOCAL ? 0 : protocol);
+
+ if (soc == INVALID_SOCKET)
+ {
+ set_winsock_errno ();
+ goto done;
+ }
+
+ const device *dev;
+
+ if (af == AF_LOCAL)
+ dev = type == SOCK_STREAM ? stream_dev : dgram_dev;
+ else
+ dev = type == SOCK_STREAM ? tcp_dev : udp_dev;
+
+ {
+ cygheap_fdnew fd;
+ if (fd < 0 || !fdsock (fd, dev, soc))
+ closesocket (soc);
+ else
+ {
+ ((fhandler_socket *) fd)->set_addr_family (af);
+ ((fhandler_socket *) fd)->set_socket_type (type);
+ res = fd;
+ }
+ }
+
+done:
+ syscall_printf ("%d = socket (%d, %d, %d)", res, af, type, protocol);
+ return res;
+}
+
+/* exported as sendto: standards? */
+extern "C" int
+cygwin_sendto (int fd, const void *buf, size_t len, int flags,
+ const struct sockaddr *to, socklen_t tolen)
+{
+ int res;
+ sig_dispatch_pending ();
+
+ fhandler_socket *fh = get (fd);
+
+ myfault efault;
+ if (efault.faulted (EFAULT) || !fh)
+ res = -1;
+ else
+ res = fh->sendto (buf, len, flags, to, tolen);
+
+ syscall_printf ("%d = sendto (%d, %p, %d, %x, %p, %d)",
+ res, fd, buf, len, flags, to, tolen);
+
+ return res;
+}
+
+/* exported as recvfrom: standards? */
+extern "C" int
+cygwin_recvfrom (int fd, void *buf, size_t len, int flags,
+ struct sockaddr *from, socklen_t *fromlen)
+{
+ int res;
+ sig_dispatch_pending ();
+
+ fhandler_socket *fh = get (fd);
+
+ myfault efault;
+ if (efault.faulted (EFAULT) || !fh)
+ res = -1;
+ else if ((res = len) != 0)
+ res = fh->recvfrom (buf, len, flags, from, fromlen);
+
+ syscall_printf ("%d = recvfrom (%d, %p, %d, %x, %p, %p)",
+ res, fd, buf, len, flags, from, fromlen);
+
+ return res;
+}
+
+static int
+convert_ws1_ip_optname (int optname)
+{
+ static int ws2_optname[] =
+ {
+ 0,
+ IP_OPTIONS,
+ IP_MULTICAST_IF,
+ IP_MULTICAST_TTL,
+ IP_MULTICAST_LOOP,
+ IP_ADD_MEMBERSHIP,
+ IP_DROP_MEMBERSHIP,
+ IP_TTL,
+ IP_TOS,
+ IP_DONTFRAGMENT
+ };
+ return (optname < 1 || optname > _WS1_IP_DONTFRAGMENT)
+ ? optname
+ : ws2_optname[optname];
+}
+
+/* exported as setsockopt: standards? */
+extern "C" int
+cygwin_setsockopt (int fd, int level, int optname, const void *optval,
+ socklen_t optlen)
+{
+ int res;
+ fhandler_socket *fh = get (fd);
+
+ myfault efault;
+ if (efault.faulted (EFAULT) || !fh)
+ res = -1;
+ else
+ {
+ /* Old applications still use the old Winsock1 IPPROTO_IP values. */
+ if (level == IPPROTO_IP && CYGWIN_VERSION_CHECK_FOR_USING_WINSOCK1_VALUES)
+ optname = convert_ws1_ip_optname (optname);
+
+ res = setsockopt (fh->get_socket (), level, optname,
+ (const char *) optval, optlen);
+
+ if (optlen == 4)
+ syscall_printf ("setsockopt optval=%x", *(long *) optval);
+
+ if (res)
+ {
+ /* KB 248611:
+
+ Windows 2000 and above don't support setting the IP_TOS field
+ with setsockopt. Additionally, TOS was always (also under 9x
+ and NT) only implemented for UDP and ICMP, never for TCP.
+
+ The difference is that beginning with Windows 2000 the
+ setsockopt call returns WinSock error 10022, WSAEINVAL when
+ trying to set the IP_TOS field, instead of just ignoring the
+ call. This is *not* explained in KB 248611, but only in KB
+ 258978.
+
+ Either case, the official workaround is to add a new registry
+ DWORD value HKLM/System/CurrentControlSet/Services/Tcpip/...
+ ... Parameters/DisableUserTOSSetting, set to 0, and reboot.
+
+ Sidenote: The reasoning for dropping ToS in Win2K is that ToS
+ per RFC 1349 is incompatible with DiffServ per RFC 2474/2475.
+
+ We just ignore the return value of setting IP_TOS under Windows
+ 2000 and above entirely. */
+ if (level == IPPROTO_IP && optname == IP_TOS
+ && WSAGetLastError () == WSAEINVAL
+ && wincap.has_disabled_user_tos_setting ())
+ {
+ debug_printf ("Faked IP_TOS success");
+ res = 0;
+ }
+ else
+ set_winsock_errno ();
+ }
+ else if (level == SOL_SOCKET && optname == SO_REUSEADDR)
+ fh->saw_reuseaddr (*(int *) optval);
+ }
+
+ syscall_printf ("%d = setsockopt (%d, %d, %x, %p, %d)",
+ res, fd, level, optname, optval, optlen);
+ return res;
+}
+
+/* exported as getsockopt: standards? */
+extern "C" int
+cygwin_getsockopt (int fd, int level, int optname, void *optval,
+ socklen_t *optlen)
+{
+ int res;
+ fhandler_socket *fh = get (fd);
+
+ myfault efault;
+ if (efault.faulted (EFAULT) || !fh)
+ res = -1;
+ else if (optname == SO_PEERCRED)
+ {
+ struct ucred *cred = (struct ucred *) optval;
+ res = fh->getpeereid (&cred->pid, &cred->uid, &cred->gid);
+ }
+ else
+ {
+ /* Old applications still use the old Winsock1 IPPROTO_IP values. */
+ if (level == IPPROTO_IP && CYGWIN_VERSION_CHECK_FOR_USING_WINSOCK1_VALUES)
+ optname = convert_ws1_ip_optname (optname);
+ res = getsockopt (fh->get_socket (), level, optname, (char *) optval,
+ (int *) optlen);
+
+ if (optname == SO_ERROR)
+ {
+ int *e = (int *) optval;
+
+ debug_printf ("WinSock SO_ERROR = %d", *e);
+ *e = find_winsock_errno (*e);
+ }
+
+ if (res)
+ set_winsock_errno ();
+ }
+
+ syscall_printf ("%d = getsockopt (%d, %d, 0x%x, %p, %p)",
+ res, fd, level, optname, optval, optlen);
+ return res;
+}
+
+extern "C" int
+getpeereid (int fd, __uid32_t *euid, __gid32_t *egid)
+{
+ sig_dispatch_pending ();
+ fhandler_socket *fh = get (fd);
+ if (fh)
+ return fh->getpeereid (NULL, euid, egid);
+ return -1;
+}
+
+/* exported as connect: standards? */
+extern "C" int
+cygwin_connect (int fd, const struct sockaddr *name, socklen_t namelen)
+{
+ int res;
+ sig_dispatch_pending ();
+
+ fhandler_socket *fh = get (fd);
+
+ myfault efault;
+ if (efault.faulted (EFAULT) || !fh)
+ res = -1;
+ else
+ {
+ bool was_blocking = false;
+ if (!fh->is_nonblocking ())
+ {
+ int nonblocking = 1;
+ fh->ioctl (FIONBIO, &nonblocking);
+ was_blocking = true;
+ }
+ res = fh->connect (name, namelen);
+ if (was_blocking)
+ {
+ if (res == -1 && get_errno () == EINPROGRESS)
+ {
+ size_t fds_size = howmany (fd + 1, NFDBITS) * sizeof (fd_mask);
+ fd_set *write_fds = (fd_set *) alloca (fds_size);
+ fd_set *except_fds = (fd_set *) alloca (fds_size);
+ memset (write_fds, 0, fds_size);
+ memset (except_fds, 0, fds_size);
+ FD_SET (fd, write_fds);
+ FD_SET (fd, except_fds);
+ res = cygwin_select (fd + 1, NULL, write_fds, except_fds, NULL);
+ if (res > 0 && FD_ISSET (fd, except_fds))
+ {
+ res = -1;
+ for (;;)
+ {
+ int err;
+ int len = sizeof err;
+ cygwin_getsockopt (fd, SOL_SOCKET, SO_ERROR,
+ (void *) &err, &len);
+ if (err)
+ {
+ set_errno (err);
+ break;
+ }
+ low_priority_sleep (0);
+ }
+ }
+ else if (res > 0)
+ res = 0;
+ else
+ {
+ WSASetLastError (WSAEINPROGRESS);
+ set_winsock_errno ();
+ }
+ }
+ int nonblocking = 0;
+ fh->ioctl (FIONBIO, &nonblocking);
+ }
+ }
+
+ syscall_printf ("%d = connect (%d, %p, %d)", res, fd, name, namelen);
+
+ return res;
+}
+
+/* exported as getservbyname: standards? */
+extern "C" struct servent *
+cygwin_getservbyname (const char *name, const char *proto)
+{
+ sig_dispatch_pending ();
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return NULL;
+
+ servent *res = (servent *) dup_ent (servent_buf, getservbyname (name, proto), t_servent);
+ syscall_printf ("%p = getservbyname (%s, %s)", res, name, proto);
+ return res;
+}
+
+/* exported as getservbyport: standards? */
+extern "C" struct servent *
+cygwin_getservbyport (int port, const char *proto)
+{
+ sig_dispatch_pending ();
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return NULL;
+
+ servent *res = (servent *) dup_ent (servent_buf, getservbyport (port, proto), t_servent);
+ syscall_printf ("%p = getservbyport (%d, %s)", _my_tls.locals.servent_buf, port, proto);
+ return res;
+}
+
+extern "C" int
+cygwin_gethostname (char *name, size_t len)
+{
+ sig_dispatch_pending ();
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return -1;
+
+ if (gethostname (name, len))
+ {
+ DWORD local_len = len;
+
+ if (!GetComputerNameA (name, &local_len))
+ {
+ set_winsock_errno ();
+ return -1;
+ }
+ }
+ debug_printf ("name %s", name);
+ return 0;
+}
+
+/* exported as gethostbyname: standards? */
+extern "C" struct hostent *
+cygwin_gethostbyname (const char *name)
+{
+ sig_dispatch_pending ();
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return NULL;
+
+ unsigned char tmp_addr[4];
+ struct hostent tmp, *h;
+ char *tmp_aliases[1] = {0};
+ char *tmp_addr_list[2] = {0,0};
+ unsigned int a, b, c, d;
+ char dummy;
+
+ if (sscanf (name, "%u.%u.%u.%u%c", &a, &b, &c, &d, &dummy) != 4
+ || a >= 256 || b >= 256 || c >= 256 || d >= 256)
+ h = gethostbyname (name);
+ else
+ {
+ /* In case you don't have DNS, at least x.x.x.x still works */
+ memset (&tmp, 0, sizeof (tmp));
+ tmp_addr[0] = a;
+ tmp_addr[1] = b;
+ tmp_addr[2] = c;
+ tmp_addr[3] = d;
+ tmp_addr_list[0] = (char *) tmp_addr;
+ tmp.h_name = name;
+ tmp.h_aliases = tmp_aliases;
+ tmp.h_addrtype = 2;
+ tmp.h_length = 4;
+ tmp.h_addr_list = tmp_addr_list;
+ h = &tmp;
+ }
+
+ hostent *res = (hostent *) dup_ent (hostent_buf, h, t_hostent);
+ if (res)
+ debug_printf ("h_name %s", res->h_name);
+ else
+ {
+ debug_printf ("dup_ent returned NULL for name %s, h %p", name, h);
+ set_host_errno ();
+ }
+ return res;
+}
+
+/* exported as gethostbyaddr: standards? */
+extern "C" struct hostent *
+cygwin_gethostbyaddr (const char *addr, int len, int type)
+{
+ sig_dispatch_pending ();
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return NULL;
+
+ hostent *res = (hostent *) dup_ent (hostent_buf, gethostbyaddr (addr, len, type), t_hostent);
+ if (res)
+ debug_printf ("h_name %s", _my_tls.locals.hostent_buf->h_name);
+ else
+ set_host_errno ();
+ return res;
+}
+
+/* exported as accept: standards? */
+extern "C" int
+cygwin_accept (int fd, struct sockaddr *peer, socklen_t *len)
+{
+ int res;
+ sig_dispatch_pending ();
+
+ fhandler_socket *fh = get (fd);
+
+ myfault efault;
+ if (efault.faulted (EFAULT) || !fh)
+ res = -1;
+ else
+ {
+ if (!fh->is_nonblocking ())
+ {
+ size_t fds_size = howmany (fd + 1, NFDBITS) * sizeof (fd_mask);
+ fd_set *read_fds = (fd_set *) alloca (fds_size);
+ memset (read_fds, 0, fds_size);
+ FD_SET (fd, read_fds);
+ res = cygwin_select (fd + 1, read_fds, NULL, NULL, NULL);
+ if (res == -1)
+ return -1;
+ }
+ res = fh->accept (peer, len);
+ }
+
+ syscall_printf ("%d = accept (%d, %p, %p)", res, fd, peer, len);
+ return res;
+}
+
+/* exported as bind: standards? */
+extern "C" int
+cygwin_bind (int fd, const struct sockaddr *my_addr, socklen_t addrlen)
+{
+ int res;
+ sig_dispatch_pending ();
+ fhandler_socket *fh = get (fd);
+
+ myfault efault;
+ if (efault.faulted (EFAULT) || !fh)
+ res = -1;
+ else
+ res = fh->bind (my_addr, addrlen);
+
+ syscall_printf ("%d = bind (%d, %p, %d)", res, fd, my_addr, addrlen);
+ return res;
+}
+
+/* exported as getsockname: standards? */
+extern "C" int
+cygwin_getsockname (int fd, struct sockaddr *addr, socklen_t *namelen)
+{
+ int res;
+ sig_dispatch_pending ();
+
+ fhandler_socket *fh = get (fd);
+
+ myfault efault;
+ if (efault.faulted (EFAULT) || !fh)
+ res = -1;
+ else
+ res = fh->getsockname (addr, namelen);
+
+ syscall_printf ("%d = getsockname (%d, %p, %p)", res, fd, addr, namelen);
+ return res;
+}
+
+/* exported as listen: standards? */
+extern "C" int
+cygwin_listen (int fd, int backlog)
+{
+ int res;
+ sig_dispatch_pending ();
+ fhandler_socket *fh = get (fd);
+
+ if (!fh)
+ res = -1;
+ else
+ res = fh->listen (backlog);
+
+ syscall_printf ("%d = listen (%d, %d)", res, fd, backlog);
+ return res;
+}
+
+/* exported as shutdown: standards? */
+extern "C" int
+cygwin_shutdown (int fd, int how)
+{
+ int res;
+ sig_dispatch_pending ();
+
+ fhandler_socket *fh = get (fd);
+
+ if (!fh)
+ res = -1;
+ else
+ res = fh->shutdown (how);
+
+ syscall_printf ("%d = shutdown (%d, %d)", res, fd, how);
+ return res;
+}
+
+/* exported as hstrerror: BSD 4.3 */
+extern "C" const char *
+cygwin_hstrerror (int err)
+{
+ int i;
+
+ for (i = 0; host_errmap[i].e != 0; ++i)
+ if (err == host_errmap[i].e)
+ break;
+
+ return host_errmap[i].s;
+}
+
+/* exported as herror: BSD 4.3 */
+extern "C" void
+cygwin_herror (const char *s)
+{
+ myfault efault;
+ if (efault.faulted ())
+ return;
+ if (cygheap->fdtab.not_open (2))
+ return;
+
+ if (s)
+ {
+ write (2, s, strlen (s));
+ write (2, ": ", 2);
+ }
+
+ const char *h_errstr = cygwin_hstrerror (h_errno);
+
+ if (!h_errstr)
+ switch (h_errno)
+ {
+ case NETDB_INTERNAL:
+ h_errstr = "Resolver internal error";
+ break;
+ case NETDB_SUCCESS:
+ h_errstr = "Resolver error 0 (no error)";
+ break;
+ default:
+ h_errstr = "Unknown resolver error";
+ break;
+ }
+ write (2, h_errstr, strlen (h_errstr));
+ write (2, "\n", 1);
+}
+
+/* exported as getpeername: standards? */
+extern "C" int
+cygwin_getpeername (int fd, struct sockaddr *name, socklen_t *len)
+{
+ int res;
+ sig_dispatch_pending ();
+
+ fhandler_socket *fh = get (fd);
+
+ myfault efault;
+ if (efault.faulted (EFAULT) || !fh)
+ res = -1;
+ else
+ res = fh->getpeername (name, len);
+
+ syscall_printf ("%d = getpeername (%d) %d", res, fd, (fh ? fh->get_socket () : -1));
+ return res;
+}
+
+/* exported as recv: standards? */
+extern "C" int
+cygwin_recv (int fd, void *buf, size_t len, int flags)
+{
+ return cygwin_recvfrom (fd, buf, len, flags, NULL, NULL);
+}
+
+/* exported as send: standards? */
+extern "C" int
+cygwin_send (int fd, const void *buf, size_t len, int flags)
+{
+ return cygwin_sendto (fd, buf, len, flags, NULL, 0);
+}
+
+/* getdomainname: standards? */
+extern "C" int
+getdomainname (char *domain, size_t len)
+{
+ /*
+ * This works for Win95 only if the machine is configured to use MS-TCP.
+ * If a third-party TCP is being used this will fail.
+ * FIXME: On Win95, is there a way to portably check the TCP stack
+ * in use and include paths for the Domain name in each ?
+ * Punt for now and assume MS-TCP on Win95.
+ */
+ sig_dispatch_pending ();
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return -1;
+
+ PFIXED_INFO info = NULL;
+ ULONG size = 0;
+
+ if (GetNetworkParams(info, &size) == ERROR_BUFFER_OVERFLOW
+ && (info = (PFIXED_INFO) alloca(size))
+ && GetNetworkParams(info, &size) == ERROR_SUCCESS)
+ {
+ strncpy(domain, info->DomainName, len);
+ return 0;
+ }
+
+ /* This is only used by Win95 and NT <= 4.0.
+ The registry names are language independent.
+ FIXME: Handle DHCP on Win95. The DhcpDomain(s) may be available
+ in ..VxD\DHCP\DhcpInfoXX\OptionInfo, RFC 1533 format */
+
+ reg_key r (HKEY_LOCAL_MACHINE, KEY_READ,
+ (!wincap.is_winnt ()) ? "System" : "SYSTEM",
+ "CurrentControlSet", "Services",
+ (!wincap.is_winnt ()) ? "VxD" : "Tcpip",
+ (!wincap.is_winnt ()) ? "MSTCP" : "Parameters", NULL);
+
+ if (!r.error ())
+ {
+ int res1, res2 = 0; /* Suppress compiler warning */
+ res1 = r.get_string ("Domain", domain, len, "");
+ if (res1 != ERROR_SUCCESS || !domain[0])
+ res2 = r.get_string ("DhcpDomain", domain, len, "");
+ if (res1 == ERROR_SUCCESS || res2 == ERROR_SUCCESS)
+ return 0;
+ }
+ __seterrno ();
+ return -1;
+}
+
+/* Fill out an ifconf struct. */
+
+/*
+ * IFCONF 98/ME, NTSP4, W2K:
+ * Use IP Helper Library
+ */
+static void
+get_2k_ifconf (struct ifconf *ifc, int what)
+{
+ int cnt = 0;
+ int ethId = 0, pppId = 0, slpId = 0, tokId = 0;
+
+ /* Union maps buffer to correct struct */
+ struct ifreq *ifr = ifc->ifc_req;
+
+ DWORD ip_cnt, lip, lnp;
+ DWORD siz_ip_table = 0;
+ PMIB_IPADDRTABLE ipt;
+ PMIB_IFROW ifrow;
+ struct sockaddr_in *sa = NULL;
+ struct sockaddr *so = NULL;
+
+ typedef struct ifcount_t
+ {
+ DWORD ifIndex;
+ size_t count;
+ unsigned int enumerated; // for eth0:1
+ unsigned int classId; // for eth0, tok0 ...
+
+ };
+ ifcount_t *iflist, *ifEntry;
+
+ if (GetIpAddrTable (NULL, &siz_ip_table, TRUE) == ERROR_INSUFFICIENT_BUFFER
+ && (ifrow = (PMIB_IFROW) alloca (sizeof (MIB_IFROW)))
+ && (ipt = (PMIB_IPADDRTABLE) alloca (siz_ip_table))
+ && !GetIpAddrTable (ipt, &siz_ip_table, TRUE))
+ {
+ iflist =
+ (ifcount_t *) alloca (sizeof (ifcount_t) * (ipt->dwNumEntries + 1));
+ memset (iflist, 0, sizeof (ifcount_t) * (ipt->dwNumEntries + 1));
+ for (ip_cnt = 0; ip_cnt < ipt->dwNumEntries; ++ip_cnt)
+ {
+ ifEntry = iflist;
+ /* search for matching entry (and stop at first free entry) */
+ while (ifEntry->count != 0)
+ {
+ if (ifEntry->ifIndex == ipt->table[ip_cnt].dwIndex)
+ break;
+ ifEntry++;
+ }
+ if (ifEntry->count == 0)
+ {
+ ifEntry->count = 1;
+ ifEntry->ifIndex = ipt->table[ip_cnt].dwIndex;
+ }
+ else
+ {
+ ifEntry->count++;
+ }
+ }
+ // reset the last element. This is just the stopper for the loop.
+ iflist[ipt->dwNumEntries].count = 0;
+
+ /* Iterate over all configured IP-addresses */
+ for (ip_cnt = 0; ip_cnt < ipt->dwNumEntries; ++ip_cnt)
+ {
+ memset (ifrow, 0, sizeof (MIB_IFROW));
+ ifrow->dwIndex = ipt->table[ip_cnt].dwIndex;
+ if (GetIfEntry (ifrow) != NO_ERROR)
+ continue;
+
+ ifcount_t *ifEntry = iflist;
+
+ /* search for matching entry (and stop at first free entry) */
+ while (ifEntry->count != 0)
+ {
+ if (ifEntry->ifIndex == ipt->table[ip_cnt].dwIndex)
+ break;
+ ifEntry++;
+ }
+
+ /* Setup the interface name */
+ switch (ifrow->dwType)
+ {
+ case MIB_IF_TYPE_TOKENRING:
+ if (ifEntry->enumerated == 0)
+ {
+ ifEntry->classId = tokId++;
+ __small_sprintf (ifr->ifr_name, "tok%u",
+ ifEntry->classId);
+ }
+ else
+ {
+ __small_sprintf (ifr->ifr_name, "tok%u:%u",
+ ifEntry->classId,
+ ifEntry->enumerated - 1);
+ }
+ ifEntry->enumerated++;
+ break;
+ case MIB_IF_TYPE_ETHERNET:
+ if (ifEntry->enumerated == 0)
+ {
+ ifEntry->classId = ethId++;
+ __small_sprintf (ifr->ifr_name, "eth%u",
+ ifEntry->classId);
+ }
+ else
+ {
+ __small_sprintf (ifr->ifr_name, "eth%u:%u",
+ ifEntry->classId,
+ ifEntry->enumerated - 1);
+ }
+ ifEntry->enumerated++;
+ break;
+ case MIB_IF_TYPE_PPP:
+ if (ifEntry->enumerated == 0)
+ {
+ ifEntry->classId = pppId++;
+ __small_sprintf (ifr->ifr_name, "ppp%u",
+ ifEntry->classId);
+ }
+ else
+ {
+ __small_sprintf (ifr->ifr_name, "ppp%u:%u",
+ ifEntry->classId,
+ ifEntry->enumerated - 1);
+ }
+ ifEntry->enumerated++;
+ break;
+ case MIB_IF_TYPE_SLIP:
+ if (ifEntry->enumerated == 0)
+ {
+ ifEntry->classId = slpId++;
+ __small_sprintf (ifr->ifr_name, "slp%u",
+ ifEntry->classId);
+ }
+ else
+ {
+ __small_sprintf (ifr->ifr_name, "slp%u:%u",
+ ifEntry->classId,
+ ifEntry->enumerated - 1);
+ }
+ ifEntry->enumerated++;
+ break;
+ case MIB_IF_TYPE_LOOPBACK:
+ strcpy (ifr->ifr_name, "lo");
+ break;
+ default:
+ continue;
+ }
+ /* setup sockaddr struct */
+ switch (what)
+ {
+ case SIOCGIFCONF:
+ case SIOCGIFADDR:
+ sa = (struct sockaddr_in *) &ifr->ifr_addr;
+ sa->sin_addr.s_addr = ipt->table[ip_cnt].dwAddr;
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
+ break;
+ case SIOCGIFBRDADDR:
+ sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
+#if 0
+ /* Unfortunately, the field returns only crap. */
+ sa->sin_addr.s_addr = ipt->table[ip_cnt].dwBCastAddr;
+#else
+ lip = ipt->table[ip_cnt].dwAddr;
+ lnp = ipt->table[ip_cnt].dwMask;
+ sa->sin_addr.s_addr = lip & lnp | ~lnp;
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
+#endif
+ break;
+ case SIOCGIFNETMASK:
+ sa = (struct sockaddr_in *) &ifr->ifr_netmask;
+ sa->sin_addr.s_addr = ipt->table[ip_cnt].dwMask;
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
+ break;
+ case SIOCGIFHWADDR:
+ so = &ifr->ifr_hwaddr;
+ for (UINT i = 0; i < IFHWADDRLEN; ++i)
+ if (i >= ifrow->dwPhysAddrLen)
+ so->sa_data[i] = '\0';
+ else
+ so->sa_data[i] = ifrow->bPhysAddr[i];
+ so->sa_family = AF_INET;
+ break;
+ case SIOCGIFMETRIC:
+ ifr->ifr_metric = 1;
+ break;
+ case SIOCGIFMTU:
+ ifr->ifr_mtu = ifrow->dwMtu;
+ break;
+ }
+ ++cnt;
+ if ((caddr_t)++ ifr >
+ ifc->ifc_buf + ifc->ifc_len - sizeof (struct ifreq))
+ goto done;
+ }
+ }
+
+done:
+ /* Set the correct length */
+ ifc->ifc_len = cnt * sizeof (struct ifreq);
+}
+
+/*
+ * IFCONF Windows NT < SP4:
+ * Look at the Bind value in
+ * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Linkage\
+ * This is a REG_MULTI_SZ with strings of the form:
+ * \Device\<Netcard>, where netcard is the name of the net device.
+ * Then look under:
+ * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\<NetCard>\
+ * Parameters\Tcpip
+ * at the IPAddress, Subnetmask and DefaultGateway values for the
+ * required values.
+ */
+static void
+get_nt_ifconf (struct ifconf *ifc, int what)
+{
+ HKEY key;
+ unsigned long lip, lnp;
+ struct sockaddr_in *sa = NULL;
+ struct sockaddr *so = NULL;
+ DWORD size;
+ int cnt = 1;
+ char *binding = (char *) 0;
+
+ /* Union maps buffer to correct struct */
+ struct ifreq *ifr = ifc->ifc_req;
+
+ if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
+ "SYSTEM\\"
+ "CurrentControlSet\\"
+ "Services\\"
+ "Tcpip\\" "Linkage",
+ 0, KEY_READ, &key) == ERROR_SUCCESS)
+ {
+ if (RegQueryValueEx (key, "Bind",
+ NULL, NULL,
+ NULL, &size) == ERROR_SUCCESS)
+ {
+ binding = (char *) alloca (size);
+ if (RegQueryValueEx (key, "Bind",
+ NULL, NULL,
+ (unsigned char *) binding,
+ &size) != ERROR_SUCCESS)
+ {
+ binding = NULL;
+ }
+ }
+ RegCloseKey (key);
+ }
+
+ if (binding)
+ {
+ char *bp, eth[2] = "/";
+ char cardkey[256], ipaddress[256], netmask[256];
+
+ for (bp = binding; *bp; bp += strlen (bp) + 1)
+ {
+ bp += strlen ("\\Device\\");
+ strcpy (cardkey, "SYSTEM\\CurrentControlSet\\Services\\");
+ strcat (cardkey, bp);
+ strcat (cardkey, "\\Parameters\\Tcpip");
+
+ if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, cardkey,
+ 0, KEY_READ, &key) != ERROR_SUCCESS)
+ continue;
+
+ if (RegQueryValueEx (key, "IPAddress",
+ NULL, NULL,
+ (unsigned char *) ipaddress,
+ (size = 256, &size)) == ERROR_SUCCESS
+ && RegQueryValueEx (key, "SubnetMask",
+ NULL, NULL,
+ (unsigned char *) netmask,
+ (size = 256, &size)) == ERROR_SUCCESS)
+ {
+ char *ip, *np;
+ char dhcpaddress[256], dhcpnetmask[256];
+
+ for (ip = ipaddress, np = netmask;
+ *ip && *np;
+ ip += strlen (ip) + 1, np += strlen (np) + 1)
+ {
+ if ((caddr_t)++ ifr > ifc->ifc_buf
+ + ifc->ifc_len - sizeof (struct ifreq))
+ break;
+
+ if (!strncmp (bp, "NdisWan", 7))
+ {
+ strcpy (ifr->ifr_name, "ppp");
+ strcat (ifr->ifr_name, bp + 7);
+ }
+ else
+ {
+ ++*eth;
+ strcpy (ifr->ifr_name, "eth");
+ strcat (ifr->ifr_name, eth);
+ }
+ memset (&ifr->ifr_addr, '\0', sizeof ifr->ifr_addr);
+ if (cygwin_inet_addr (ip) == 0L
+ && RegQueryValueEx (key, "DhcpIPAddress",
+ NULL, NULL,
+ (unsigned char *) dhcpaddress,
+ (size = 256, &size))
+ == ERROR_SUCCESS
+ && RegQueryValueEx (key, "DhcpSubnetMask",
+ NULL, NULL,
+ (unsigned char *) dhcpnetmask,
+ (size = 256, &size))
+ == ERROR_SUCCESS)
+ {
+ switch (what)
+ {
+ case SIOCGIFCONF:
+ case SIOCGIFADDR:
+ sa = (struct sockaddr_in *) &ifr->ifr_addr;
+ sa->sin_addr.s_addr =
+ cygwin_inet_addr (dhcpaddress);
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
+ break;
+ case SIOCGIFBRDADDR:
+ lip = cygwin_inet_addr (dhcpaddress);
+ lnp = cygwin_inet_addr (dhcpnetmask);
+ sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
+ sa->sin_addr.s_addr = lip & lnp | ~lnp;
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
+ break;
+ case SIOCGIFNETMASK:
+ sa = (struct sockaddr_in *) &ifr->ifr_netmask;
+ sa->sin_addr.s_addr =
+ cygwin_inet_addr (dhcpnetmask);
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
+ break;
+ case SIOCGIFHWADDR:
+ so = &ifr->ifr_hwaddr;
+ memset (so->sa_data, 0, IFHWADDRLEN);
+ so->sa_family = AF_INET;
+ break;
+ case SIOCGIFMETRIC:
+ ifr->ifr_metric = 1;
+ break;
+ case SIOCGIFMTU:
+ ifr->ifr_mtu = 1500;
+ break;
+ }
+ }
+ else
+ {
+ switch (what)
+ {
+ case SIOCGIFCONF:
+ case SIOCGIFADDR:
+ sa = (struct sockaddr_in *) &ifr->ifr_addr;
+ sa->sin_addr.s_addr = cygwin_inet_addr (ip);
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
+ break;
+ case SIOCGIFBRDADDR:
+ lip = cygwin_inet_addr (ip);
+ lnp = cygwin_inet_addr (np);
+ sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
+ sa->sin_addr.s_addr = lip & lnp | ~lnp;
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
+ break;
+ case SIOCGIFNETMASK:
+ sa = (struct sockaddr_in *) &ifr->ifr_netmask;
+ sa->sin_addr.s_addr = cygwin_inet_addr (np);
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
+ break;
+ case SIOCGIFHWADDR:
+ so = &ifr->ifr_hwaddr;
+ memset (so->sa_data, 0, IFHWADDRLEN);
+ so->sa_family = AF_INET;
+ break;
+ case SIOCGIFMETRIC:
+ ifr->ifr_metric = 1;
+ break;
+ case SIOCGIFMTU:
+ ifr->ifr_mtu = 1500;
+ break;
+ }
+ }
+ ++cnt;
+ }
+ }
+ RegCloseKey (key);
+ }
+ }
+
+ /* Set the correct length */
+ ifc->ifc_len = cnt * sizeof (struct ifreq);
+}
+
+/*
+ * IFCONF Windows 95:
+ * HKLM/Enum/Network/MSTCP/"*"
+ * -> Value "Driver" enthält Subkey relativ zu
+ * HKLM/System/CurrentControlSet/Class/
+ * -> In Subkey "Bindings" die Values aufzählen
+ * -> Enthält Subkeys der Form "VREDIR\*"
+ * Das * ist ein Subkey relativ zu
+ * HKLM/System/CurrentControlSet/Class/Net/
+ * HKLM/System/CurrentControlSet/Class/"Driver"
+ * -> Value "IPAddress"
+ * -> Value "IPMask"
+ * HKLM/System/CurrentControlSet/Class/Net/"*"(aus "VREDIR\*")
+ * -> Wenn Value "AdapterName" == "MS$PPP" -> ppp interface
+ * -> Value "DriverDesc" enthält den Namen
+ *
+ */
+static void
+get_95_ifconf (struct ifconf *ifc, int what)
+{
+ HKEY key;
+ unsigned long lip, lnp;
+ struct sockaddr_in *sa = NULL;
+ struct sockaddr *so = NULL;
+ FILETIME update;
+ LONG res;
+ DWORD size;
+ int cnt = 1;
+ char ifname[256];
+ char eth[2] = "/";
+ char ppp[2] = "/";
+
+ /* Union maps buffer to correct struct */
+ struct ifreq *ifr = ifc->ifc_req;
+
+ if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Enum\\Network\\MSTCP",
+ 0, KEY_READ, &key) != ERROR_SUCCESS)
+ {
+ /* Set the correct length */
+ ifc->ifc_len = cnt * sizeof (struct ifreq);
+ return;
+ }
+
+ for (int i = 0;
+ (res = RegEnumKeyEx (key, i, ifname,
+ (size = sizeof ifname, &size),
+ 0, 0, 0, &update)) != ERROR_NO_MORE_ITEMS;
+ ++i)
+ {
+ HKEY ifkey, subkey;
+ char driver[256], classname[256], netname[256];
+ char adapter[256], ip[256], np[256];
+
+ if (res != ERROR_SUCCESS
+ || RegOpenKeyEx (key, ifname, 0, KEY_READ, &ifkey) != ERROR_SUCCESS)
+ continue;
+
+ if (RegQueryValueEx (ifkey, "Driver", 0,
+ NULL, (unsigned char *) driver,
+ (size = sizeof driver, &size)) != ERROR_SUCCESS)
+ {
+ RegCloseKey (ifkey);
+ continue;
+ }
+
+ strcpy (classname, "System\\CurrentControlSet\\Services\\Class\\");
+ strcat (classname, driver);
+ if ((res = RegOpenKeyEx (HKEY_LOCAL_MACHINE, classname,
+ 0, KEY_READ, &subkey)) != ERROR_SUCCESS)
+ {
+ RegCloseKey (ifkey);
+ continue;
+ }
+
+ if (RegQueryValueEx (subkey, "IPAddress", 0,
+ NULL, (unsigned char *) ip,
+ (size = sizeof ip, &size)) == ERROR_SUCCESS
+ && RegQueryValueEx (subkey, "IPMask", 0,
+ NULL, (unsigned char *) np,
+ (size = sizeof np, &size)) == ERROR_SUCCESS)
+ {
+ if ((caddr_t)++ ifr > ifc->ifc_buf
+ + ifc->ifc_len - sizeof (struct ifreq))
+ goto out;
+
+ switch (what)
+ {
+ case SIOCGIFCONF:
+ case SIOCGIFADDR:
+ sa = (struct sockaddr_in *) &ifr->ifr_addr;
+ sa->sin_addr.s_addr = cygwin_inet_addr (ip);
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
+ break;
+ case SIOCGIFBRDADDR:
+ lip = cygwin_inet_addr (ip);
+ lnp = cygwin_inet_addr (np);
+ sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
+ sa->sin_addr.s_addr = lip & lnp | ~lnp;
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
+ break;
+ case SIOCGIFNETMASK:
+ sa = (struct sockaddr_in *) &ifr->ifr_netmask;
+ sa->sin_addr.s_addr = cygwin_inet_addr (np);
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
+ break;
+ case SIOCGIFHWADDR:
+ so = &ifr->ifr_hwaddr;
+ memset (so->sa_data, 0, IFHWADDRLEN);
+ so->sa_family = AF_INET;
+ break;
+ case SIOCGIFMETRIC:
+ ifr->ifr_metric = 1;
+ break;
+ case SIOCGIFMTU:
+ ifr->ifr_mtu = 1500;
+ break;
+ }
+ }
+
+ RegCloseKey (subkey);
+
+ strcpy (netname, "System\\CurrentControlSet\\Services\\Class\\Net\\");
+ strcat (netname, ifname);
+
+ if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, netname,
+ 0, KEY_READ, &subkey) != ERROR_SUCCESS)
+ {
+ RegCloseKey (ifkey);
+ --ifr;
+ continue;
+ }
+
+ if (RegQueryValueEx (subkey, "AdapterName", 0,
+ NULL, (unsigned char *) adapter,
+ (size = sizeof adapter, &size)) == ERROR_SUCCESS
+ && strcasematch (adapter, "MS$PPP"))
+ {
+ ++*ppp;
+ strcpy (ifr->ifr_name, "ppp");
+ strcat (ifr->ifr_name, ppp);
+ }
+ else
+ {
+ ++*eth;
+ strcpy (ifr->ifr_name, "eth");
+ strcat (ifr->ifr_name, eth);
+ }
+
+ RegCloseKey (subkey);
+ RegCloseKey (ifkey);
+
+ ++cnt;
+ }
+
+out:
+
+ RegCloseKey (key);
+
+ /* Set the correct length */
+ ifc->ifc_len = cnt * sizeof (struct ifreq);
+}
+
+int
+get_ifconf (struct ifconf *ifc, int what)
+{
+ unsigned long lip, lnp;
+ struct sockaddr_in *sa;
+
+ sig_dispatch_pending ();
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return -1;
+
+ /* Union maps buffer to correct struct */
+ struct ifreq *ifr = ifc->ifc_req;
+
+ /* Ensure we have space for two struct ifreqs, fail if not. */
+ if (ifc->ifc_len < (int) (2 * sizeof (struct ifreq)))
+ {
+ set_errno (EFAULT);
+ return -1;
+ }
+
+ /* Set up interface lo0 first */
+ strcpy (ifr->ifr_name, "lo");
+ memset (&ifr->ifr_addr, '\0', sizeof (ifr->ifr_addr));
+ switch (what)
+ {
+ case SIOCGIFCONF:
+ case SIOCGIFADDR:
+ sa = (struct sockaddr_in *) &ifr->ifr_addr;
+ sa->sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
+ break;
+ case SIOCGIFBRDADDR:
+ lip = htonl (INADDR_LOOPBACK);
+ lnp = cygwin_inet_addr ("255.0.0.0");
+ sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
+ sa->sin_addr.s_addr = lip & lnp | ~lnp;
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
+ break;
+ case SIOCGIFNETMASK:
+ sa = (struct sockaddr_in *) &ifr->ifr_netmask;
+ sa->sin_addr.s_addr = cygwin_inet_addr ("255.0.0.0");
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
+ break;
+ case SIOCGIFHWADDR:
+ ifr->ifr_hwaddr.sa_family = AF_INET;
+ memset (ifr->ifr_hwaddr.sa_data, 0, IFHWADDRLEN);
+ break;
+ case SIOCGIFMETRIC:
+ ifr->ifr_metric = 1;
+ break;
+ case SIOCGIFMTU:
+ /* This funny value is returned by `ifconfig lo' on Linux 2.2 kernel. */
+ ifr->ifr_mtu = 3924;
+ break;
+ default:
+ set_errno (EINVAL);
+ return -1;
+ }
+
+ if (wincap.has_ip_helper_lib ())
+ get_2k_ifconf (ifc, what);
+ else if (wincap.is_winnt ())
+ get_nt_ifconf (ifc, what);
+ else
+ get_95_ifconf (ifc, what);
+ return 0;
+}
+
+/* exported as rcmd: standards? */
+extern "C" int
+cygwin_rcmd (char **ahost, unsigned short inport, char *locuser,
+ char *remuser, char *cmd, int *fd2p)
+{
+ int res = -1;
+ SOCKET fd2s;
+
+ sig_dispatch_pending ();
+
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return (int) INVALID_SOCKET;
+ if (!*locuser)
+ {
+ set_errno (EINVAL);
+ return (int) INVALID_SOCKET;
+ }
+
+ res = rcmd (ahost, inport, locuser, remuser, cmd, fd2p ? &fd2s : NULL);
+ if (res != (int) INVALID_SOCKET)
+ {
+ cygheap_fdnew res_fd;
+
+ if (res_fd >= 0 && fdsock (res_fd, tcp_dev, res))
+ {
+ ((fhandler_socket *) res_fd)->connect_state (connected);
+ res = res_fd;
+ }
+ else
+ {
+ closesocket (res);
+ res = -1;
+ }
+
+ if (res >= 0 && fd2p)
+ {
+ cygheap_fdnew newfd (res_fd, false);
+ cygheap_fdget fd (*fd2p);
+
+ if (newfd >= 0 && fdsock (newfd, tcp_dev, fd2s))
+ {
+ *fd2p = newfd;
+ ((fhandler_socket *) fd2p)->connect_state (connected);
+ }
+ else
+ {
+ closesocket (res);
+ closesocket (fd2s);
+ res = -1;
+ }
+ }
+ }
+
+ syscall_printf ("%d = rcmd (...)", res);
+ return res;
+}
+
+/* The below implementation of rresvport looks pretty ugly, but there's
+ a problem in Winsock. The bind(2) call does not fail if a local
+ address is still in TIME_WAIT state, and there's no way to get this
+ behaviour. Unfortunately the first time when this is detected is when
+ the calling application tries to connect.
+
+ One (also not really foolproof) way around this problem would be to use
+ the iphlpapi function GetTcpTable and to check if the port in question is
+ in TIME_WAIT state and if so, choose another port number. But this method
+ is as prone to races as the below one, or any other method using random
+ port numbers, etc. The below method at least tries to avoid races between
+ multiple applications using rrecvport.
+
+ As for the question "why don't you just use the Winsock rresvport?"...
+ For some reason I do NOT understand, the call to WinSocks rresvport
+ corrupts the stack when Cygwin is built using -fomit-frame-pointers.
+ And then again, the Winsock rresvport function has the exact same
+ problem with reusing ports in the TIME_WAIT state as the socket/bind
+ method has. So there's no gain in using that function. */
+
+#define PORT_LOW (IPPORT_EFSSERVER + 1)
+#define PORT_HIGH (IPPORT_RESERVED - 1)
+#define NUM_PORTS (PORT_HIGH - PORT_LOW + 1)
+
+LONG last_used_rrecvport __attribute__((section (".cygwin_dll_common"), shared)) = IPPORT_RESERVED;
+
+/* exported as rresvport: standards? */
+extern "C" int
+cygwin_rresvport (int *port)
+{
+ int res;
+ sig_dispatch_pending ();
+
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return -1;
+
+ res = socket (AF_INET, SOCK_STREAM, 0);
+ if (res != (int) INVALID_SOCKET)
+ {
+ LONG myport;
+ int ret = SOCKET_ERROR;
+ struct sockaddr_in sin;
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = INADDR_ANY;
+
+ for (int i = 0; i < NUM_PORTS; i++)
+ {
+ while ((myport = InterlockedExchange (&last_used_rrecvport, 0)) == 0)
+ low_priority_sleep (0);
+ if (--myport < PORT_LOW)
+ myport = PORT_HIGH;
+ InterlockedExchange (&last_used_rrecvport, myport);
+
+ sin.sin_port = htons (myport);
+ if (!(ret = bind (res, (struct sockaddr *) &sin, sizeof sin)))
+ break;
+ int err = WSAGetLastError ();
+ if (err != WSAEADDRINUSE && err != WSAEINVAL)
+ break;
+ }
+ if (ret == SOCKET_ERROR)
+ {
+ closesocket (res);
+ res = (int) INVALID_SOCKET;
+ }
+ else if (port)
+ *port = myport;
+ }
+
+ if (res != (int) INVALID_SOCKET)
+ {
+ cygheap_fdnew res_fd;
+
+ if (res_fd >= 0 && fdsock (res_fd, tcp_dev, res))
+ res = res_fd;
+ else
+ res = -1;
+ }
+
+ syscall_printf ("%d = rresvport (%d)", res, port ? *port : 0);
+ return res;
+}
+
+/* socketpair: standards? */
+/* Win32 supports AF_INET only, so ignore domain and protocol arguments */
+extern "C" int
+socketpair (int family, int type, int protocol, int *sb)
+{
+ int res = -1;
+ SOCKET insock, outsock, newsock;
+ struct sockaddr_in sock_in, sock_out;
+ int len;
+
+ sig_dispatch_pending ();
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return -1;
+
+ if (family != AF_LOCAL && family != AF_INET)
+ {
+ set_errno (EAFNOSUPPORT);
+ goto done;
+ }
+ if (type != SOCK_STREAM && type != SOCK_DGRAM)
+ {
+ set_errno (EPROTOTYPE);
+ goto done;
+ }
+ if ((family == AF_LOCAL && protocol != PF_UNSPEC && protocol != PF_LOCAL)
+ || (family == AF_INET && protocol != PF_UNSPEC && protocol != PF_INET))
+ {
+ set_errno (EPROTONOSUPPORT);
+ goto done;
+ }
+
+ /* create the first socket */
+ newsock = socket (AF_INET, type, 0);
+ if (newsock == INVALID_SOCKET)
+ {
+ debug_printf ("first socket call failed");
+ set_winsock_errno ();
+ goto done;
+ }
+
+ /* bind the socket to any unused port */
+ sock_in.sin_family = AF_INET;
+ sock_in.sin_port = 0;
+ sock_in.sin_addr.s_addr = INADDR_ANY;
+ if (bind (newsock, (struct sockaddr *) &sock_in, sizeof (sock_in)) < 0)
+ {
+ debug_printf ("bind failed");
+ set_winsock_errno ();
+ closesocket (newsock);
+ goto done;
+ }
+ len = sizeof (sock_in);
+ if (getsockname (newsock, (struct sockaddr *) &sock_in, &len) < 0)
+ {
+ debug_printf ("getsockname error");
+ set_winsock_errno ();
+ closesocket (newsock);
+ goto done;
+ }
+
+ /* For stream sockets, create a listener */
+ if (type == SOCK_STREAM)
+ listen (newsock, 2);
+
+ /* create a connecting socket */
+ outsock = socket (AF_INET, type, 0);
+ if (outsock == INVALID_SOCKET)
+ {
+ debug_printf ("second socket call failed");
+ set_winsock_errno ();
+ closesocket (newsock);
+ goto done;
+ }
+
+ /* For datagram sockets, bind the 2nd socket to an unused address, too */
+ if (type == SOCK_DGRAM)
+ {
+ sock_out.sin_family = AF_INET;
+ sock_out.sin_port = 0;
+ sock_out.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+ if (bind (outsock, (struct sockaddr *) &sock_out, sizeof (sock_out)) < 0)
+ {
+ debug_printf ("bind failed");
+ set_winsock_errno ();
+ closesocket (newsock);
+ closesocket (outsock);
+ goto done;
+ }
+ len = sizeof (sock_out);
+ if (getsockname (outsock, (struct sockaddr *) &sock_out, &len) < 0)
+ {
+ debug_printf ("getsockname error");
+ set_winsock_errno ();
+ closesocket (newsock);
+ closesocket (outsock);
+ goto done;
+ }
+ }
+
+ /* Force IP address to loopback */
+ sock_in.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+ if (type == SOCK_DGRAM)
+ sock_out.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+
+ /* Do a connect */
+ if (connect (outsock, (struct sockaddr *) &sock_in, sizeof (sock_in)) < 0)
+ {
+ debug_printf ("connect error");
+ set_winsock_errno ();
+ closesocket (newsock);
+ closesocket (outsock);
+ goto done;
+ }
+
+ if (type == SOCK_STREAM)
+ {
+ /* For stream sockets, accept the connection and close the listener */
+ len = sizeof (sock_in);
+ insock = accept (newsock, (struct sockaddr *) &sock_in, &len);
+ if (insock == INVALID_SOCKET)
+ {
+ debug_printf ("accept error");
+ set_winsock_errno ();
+ closesocket (newsock);
+ closesocket (outsock);
+ goto done;
+ }
+ closesocket (newsock);
+ }
+ else
+ {
+ /* For datagram sockets, connect the 2nd socket */
+ if (connect (newsock, (struct sockaddr *) &sock_out,
+ sizeof (sock_out)) < 0)
+ {
+ debug_printf ("connect error");
+ set_winsock_errno ();
+ closesocket (newsock);
+ closesocket (outsock);
+ goto done;
+ }
+ insock = newsock;
+ }
+
+ {
+ cygheap_fdnew sb0;
+ const device *dev;
+
+ if (family == AF_INET)
+ dev = (type == SOCK_STREAM ? tcp_dev : udp_dev);
+ else
+ dev = (type == SOCK_STREAM ? stream_dev : dgram_dev);
+
+ if (sb0 >= 0 && fdsock (sb0, dev, insock))
+ {
+ ((fhandler_socket *) sb0)->set_sun_path ("");
+ ((fhandler_socket *) sb0)->set_addr_family (family);
+ ((fhandler_socket *) sb0)->set_socket_type (type);
+ ((fhandler_socket *) sb0)->connect_state (connected);
+ if (family == AF_LOCAL && type == SOCK_STREAM)
+ ((fhandler_socket *) sb0)->af_local_set_sockpair_cred ();
+
+ cygheap_fdnew sb1 (sb0, false);
+
+ if (sb1 >= 0 && fdsock (sb1, dev, outsock))
+ {
+ ((fhandler_socket *) sb1)->set_sun_path ("");
+ ((fhandler_socket *) sb1)->set_addr_family (family);
+ ((fhandler_socket *) sb1)->set_socket_type (type);
+ ((fhandler_socket *) sb1)->connect_state (connected);
+ if (family == AF_LOCAL && type == SOCK_STREAM)
+ ((fhandler_socket *) sb1)->af_local_set_sockpair_cred ();
+
+ sb[0] = sb0;
+ sb[1] = sb1;
+ res = 0;
+ }
+ }
+
+ if (res == -1)
+ {
+ closesocket (insock);
+ closesocket (outsock);
+ }
+ }
+
+done:
+ syscall_printf ("%d = socketpair (...)", res);
+ return res;
+}
+
+/* sethostent: standards? */
+extern "C" void
+sethostent (int)
+{
+}
+
+/* endhostent: standards? */
+extern "C" void
+endhostent (void)
+{
+}
+
+/* exported as recvmsg: standards? */
+extern "C" int
+cygwin_recvmsg (int fd, struct msghdr *msg, int flags)
+{
+ int res;
+ sig_dispatch_pending ();
+
+ fhandler_socket *fh = get (fd);
+
+ myfault efault;
+ if (efault.faulted (EFAULT) || !fh)
+ res = -1;
+ else
+ {
+ res = check_iovec_for_read (msg->msg_iov, msg->msg_iovlen);
+ if (res > 0)
+ res = fh->recvmsg (msg, flags, res); // res == iovec tot
+ }
+
+ syscall_printf ("%d = recvmsg (%d, %p, %x)", res, fd, msg, flags);
+ return res;
+}
+
+/* exported as sendmsg: standards? */
+extern "C" int
+cygwin_sendmsg (int fd, const struct msghdr *msg, int flags)
+{
+ int res;
+ sig_dispatch_pending ();
+
+ fhandler_socket *fh = get (fd);
+
+ myfault efault;
+ if (efault.faulted (EFAULT) || !fh)
+ res = -1;
+ else
+ {
+ res = check_iovec_for_write (msg->msg_iov, msg->msg_iovlen);
+ res = fh->sendmsg (msg, flags, res); // res == iovec tot
+ }
+
+ syscall_printf ("%d = sendmsg (%d, %p, %x)", res, fd, msg, flags);
+ return res;
+}
+
+/* This is from the BIND 4.9.4 release, modified to compile by itself */
+
+/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#define IN6ADDRSZ 16
+#define INADDRSZ 4
+#define INT16SZ 2
+
+/* int
+ * inet_pton4(src, dst)
+ * like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ * 1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ * does not touch `dst' unless it's returning 1.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton4 (const char *src, u_char *dst)
+{
+ static const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ u_char tmp[INADDRSZ], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ *(tp = tmp) = 0;
+ while ((ch = *src++) != '\0')
+ {
+ const char *pch;
+
+ if ((pch = strchr(digits, ch)) != NULL)
+ {
+ u_int ret = *tp * 10 + (pch - digits);
+
+ if (ret > 255)
+ return (0);
+ *tp = ret;
+ if (! saw_digit)
+ {
+ if (++octets > 4)
+ return (0);
+ saw_digit = 1;
+ }
+ }
+ else if (ch == '.' && saw_digit)
+ {
+ if (octets == 4)
+ return (0);
+ *++tp = 0;
+ saw_digit = 0;
+ }
+ else
+ return (0);
+ }
+ if (octets < 4)
+ return (0);
+
+ memcpy(dst, tmp, INADDRSZ);
+ return (1);
+}
+
+/* int
+ * inet_pton6(src, dst)
+ * convert presentation level address to network order binary form.
+ * return:
+ * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ * (1) does not touch `dst' unless it's returning 1.
+ * (2) :: in a full address is silently ignored.
+ * credit:
+ * inspired by Mark Andrews.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton6 (const char *src, u_char *dst)
+{
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit;
+ u_int val;
+
+ memset((tp = tmp), 0, IN6ADDRSZ);
+ endp = tp + IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ return (0);
+ curtok = src;
+ saw_xdigit = 0;
+ val = 0;
+ while ((ch = *src++) != '\0')
+ {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL)
+ {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (val > 0xffff)
+ return (0);
+ saw_xdigit = 1;
+ continue;
+ }
+ if (ch == ':')
+ {
+ curtok = src;
+ if (!saw_xdigit)
+ {
+ if (colonp)
+ return (0);
+ colonp = tp;
+ continue;
+ }
+ if (tp + INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ saw_xdigit = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0)
+ {
+ tp += INADDRSZ;
+ saw_xdigit = 0;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ return (0);
+ }
+ if (saw_xdigit)
+ {
+ if (tp + INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ }
+ if (colonp != NULL)
+ {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ for (i = 1; i <= n; i++)
+ {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if (tp != endp)
+ return (0);
+
+ memcpy(dst, tmp, IN6ADDRSZ);
+ return (1);
+}
+
+/* int
+ * inet_pton(af, src, dst)
+ * convert from presentation format (which usually means ASCII printable)
+ * to network format (which is usually some kind of binary format).
+ * return:
+ * 1 if the address was valid for the specified address family
+ * 0 if the address wasn't valid (`dst' is untouched in this case)
+ * -1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ * Paul Vixie, 1996.
+ */
+extern "C" int
+cygwin_inet_pton (int af, const char *src, void *dst)
+{
+ switch (af)
+ {
+ case AF_INET:
+ return (inet_pton4(src, (u_char *) dst));
+ case AF_INET6:
+ return (inet_pton6(src, (u_char *) dst));
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+ /* NOTREACHED */
+}
+
+/* const char *
+ * inet_ntop4(src, dst, size)
+ * format an IPv4 address, more or less like inet_ntoa()
+ * return:
+ * `dst' (as a const)
+ * notes:
+ * (1) uses no statics
+ * (2) takes a u_char* not an in_addr as input
+ * author:
+ * Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop4 (const u_char *src, char *dst, size_t size)
+{
+ static const char fmt[] = "%u.%u.%u.%u";
+ char tmp[sizeof "255.255.255.255"];
+
+ __small_sprintf(tmp, fmt, src[0], src[1], src[2], src[3]);
+ if (strlen(tmp) > size)
+ {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return (dst);
+}
+
+/* const char *
+ * inet_ntop6(src, dst, size)
+ * convert IPv6 binary address into presentation (printable) format
+ * author:
+ * Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop6 (const u_char *src, char *dst, size_t size)
+{
+ /*
+ * Note that int32_t and int16_t need only be "at least" large enough
+ * to contain a value of the specified size. On some systems, like
+ * Crays, there is no such thing as an integer variable with 16 bits.
+ * Keep this in mind if you think this function should have been coded
+ * to use pointer overlays. All the world's not a VAX.
+ */
+ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
+ struct { int base, len; } best, cur;
+ u_int words[IN6ADDRSZ / INT16SZ];
+ int i;
+
+ /*
+ * Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, 0, sizeof words);
+ for (i = 0; i < IN6ADDRSZ; i++)
+ words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+ best.base = -1;
+ cur.base = -1;
+ for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
+ {
+ if (words[i] == 0)
+ {
+ if (cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ }
+ else
+ {
+ if (cur.base != -1)
+ {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if (cur.base != -1)
+ {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ }
+ if (best.base != -1 && best.len < 2)
+ best.base = -1;
+
+ /*
+ * Format the result.
+ */
+ tp = tmp;
+ for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
+ {
+ /* Are we inside the best run of 0x00's? */
+ if (best.base != -1 && i >= best.base && i < (best.base + best.len))
+ {
+ if (i == best.base)
+ *tp++ = ':';
+ continue;
+ }
+ /* Are we following an initial run of 0x00s or any real hex? */
+ if (i != 0)
+ *tp++ = ':';
+ /* Is this address an encapsulated IPv4? */
+ if (i == 6 && best.base == 0 &&
+ (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
+ {
+ if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
+ return (NULL);
+ tp += strlen(tp);
+ break;
+ }
+ __small_sprintf(tp, "%x", words[i]);
+ tp += strlen(tp);
+ }
+ /* Was it a trailing run of 0x00's? */
+ if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
+ *tp++ = ':';
+ *tp++ = '\0';
+
+ /*
+ * Check for overflow, copy, and we're done.
+ */
+ if ((size_t) (tp - tmp) > size)
+ {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return (dst);
+}
+
+/* char *
+ * inet_ntop(af, src, dst, size)
+ * convert a network format address to presentation format.
+ * return:
+ * pointer to presentation format address (`dst'), or NULL (see errno).
+ * author:
+ * Paul Vixie, 1996.
+ */
+extern "C" const char *
+cygwin_inet_ntop (int af, const void *src, char *dst, size_t size)
+{
+ switch (af)
+ {
+ case AF_INET:
+ return (inet_ntop4((const u_char *) src, dst, size));
+ case AF_INET6:
+ return (inet_ntop6((const u_char *) src, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+ /* NOTREACHED */
+}
+
+/* W. Richard STEVENS libgai implementation, slightly tweaked for inclusion
+ into Cygwin as pure IPv4 replacement. Please note that the code is
+ kept intact as much as possible. Especially the IPv6 and AF_UNIX code
+ is kept in, even though we can support neither of them. Please don't
+ activate them, they won't work correctly. */
+
+#define IPv4
+#undef IPv6
+#undef UNIXdomain
+
+#undef HAVE_SOCKADDR_SA_LEN
+#define gethostbyname2(host,family) cygwin_gethostbyname((host))
+
+#define AI_CLONE 0x8000 /* Avoid collision with AI_ values in netdb.h */
+
+/*
+ * Create and fill in an addrinfo{}.
+ */
+
+/* include ga_aistruct1 */
+static int
+ga_aistruct (struct addrinfo ***paipnext, const struct addrinfo *hintsp,
+ const void *addr, int family)
+{
+ struct addrinfo *ai;
+
+ if ((ai = (struct addrinfo *) calloc (1, sizeof (struct addrinfo))) == NULL)
+ return (EAI_MEMORY);
+ ai->ai_next = NULL;
+ ai->ai_canonname = NULL;
+ **paipnext = ai;
+ *paipnext = &ai->ai_next;
+
+ if ((ai->ai_socktype = hintsp->ai_socktype) == 0)
+ ai->ai_flags |= AI_CLONE;
+
+ ai->ai_protocol = hintsp->ai_protocol;
+/* end ga_aistruct1 */
+
+/* include ga_aistruct2 */
+ switch ((ai->ai_family = family))
+ {
+#ifdef IPv4
+ case AF_INET:
+ {
+ struct sockaddr_in *sinptr;
+
+ /* 4allocate sockaddr_in{} and fill in all but port */
+ if ((sinptr = (struct sockaddr_in *)
+ calloc (1, sizeof (struct sockaddr_in))) == NULL)
+ return (EAI_MEMORY);
+#ifdef HAVE_SOCKADDR_SA_LEN
+ sinptr->sin_len = sizeof (struct sockaddr_in);
+#endif
+ sinptr->sin_family = AF_INET;
+ memcpy (&sinptr->sin_addr, addr, sizeof (struct in_addr));
+ ai->ai_addr = (struct sockaddr *) sinptr;
+ ai->ai_addrlen = sizeof (struct sockaddr_in);
+ break;
+ }
+#endif /* IPV4 */
+#ifdef IPv6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6ptr;
+
+ /* 4allocate sockaddr_in6{} and fill in all but port */
+ if ((sin6ptr = calloc (1, sizeof (struct sockaddr_in6))) == NULL)
+ return (EAI_MEMORY);
+#ifdef HAVE_SOCKADDR_SA_LEN
+ sin6ptr->sin6_len = sizeof (struct sockaddr_in6);
+#endif
+ sin6ptr->sin6_family = AF_INET6;
+ memcpy (&sin6ptr->sin6_addr, addr, sizeof (struct in6_addr));
+ ai->ai_addr = (struct sockaddr *) sin6ptr;
+ ai->ai_addrlen = sizeof (struct sockaddr_in6);
+ break;
+ }
+#endif /* IPV6 */
+#ifdef UNIXdomain
+ case AF_LOCAL:
+ {
+ struct sockaddr_un *unp;
+
+ /* 4allocate sockaddr_un{} and fill in */
+/* *INDENT-OFF* */
+ if (strlen(addr) >= sizeof(unp->sun_path))
+ return(EAI_SERVICE);
+ if ( (unp = calloc(1, sizeof(struct sockaddr_un))) == NULL)
+ return(EAI_MEMORY);
+/* *INDENT-ON* */
+ unp->sun_family = AF_LOCAL;
+ strcpy (unp->sun_path, addr);
+#ifdef HAVE_SOCKADDR_SA_LEN
+ unp->sun_len = SUN_LEN (unp);
+#endif
+ ai->ai_addr = (struct sockaddr *) unp;
+ ai->ai_addrlen = sizeof (struct sockaddr_un);
+ if (hintsp->ai_flags & AI_PASSIVE)
+ unlink (unp->sun_path); /* OK if this fails */
+ break;
+ }
+#endif /* UNIXDOMAIN */
+ }
+ return (0);
+}
+
+/* end ga_aistruct2 */
+
+/*
+ * Clone a new addrinfo structure from an existing one.
+ */
+
+/* include ga_clone */
+static struct addrinfo *
+ga_clone (struct addrinfo *ai)
+{
+ struct addrinfo *nai;
+
+ if ((nai = (struct addrinfo *) calloc (1, sizeof (struct addrinfo))) == NULL)
+ return (NULL);
+
+ nai->ai_next = ai->ai_next;
+ ai->ai_next = nai;
+
+ nai->ai_flags = 0; /* make sure AI_CLONE is off */
+ nai->ai_family = ai->ai_family;
+ nai->ai_socktype = ai->ai_socktype;
+ nai->ai_protocol = ai->ai_protocol;
+ nai->ai_canonname = NULL;
+ nai->ai_addrlen = ai->ai_addrlen;
+ if ((nai->ai_addr = (struct sockaddr *) malloc (ai->ai_addrlen)) == NULL)
+ return (NULL);
+ memcpy (nai->ai_addr, ai->ai_addr, ai->ai_addrlen);
+
+ return (nai);
+}
+
+/* end ga_clone */
+
+/*
+ * Basic error checking of flags, family, socket type, and protocol.
+ */
+
+/* include ga_echeck */
+static int
+ga_echeck (const char *hostname, const char *servname,
+ int flags, int family, int socktype, int protocol)
+{
+ if (flags & ~(AI_PASSIVE | AI_CANONNAME))
+ return (EAI_BADFLAGS); /* unknown flag bits */
+
+ if (hostname == NULL || hostname[0] == '\0')
+ {
+ if (servname == NULL || servname[0] == '\0')
+ return (EAI_NONAME); /* host or service must be specified */
+ }
+
+ switch (family)
+ {
+ case AF_UNSPEC:
+ break;
+#ifdef IPv4
+ case AF_INET:
+ if (socktype != 0 &&
+ (socktype != SOCK_STREAM &&
+ socktype != SOCK_DGRAM && socktype != SOCK_RAW))
+ return (EAI_SOCKTYPE); /* invalid socket type */
+ break;
+#endif
+#ifdef IPv6
+ case AF_INET6:
+ if (socktype != 0 &&
+ (socktype != SOCK_STREAM &&
+ socktype != SOCK_DGRAM && socktype != SOCK_RAW))
+ return (EAI_SOCKTYPE); /* invalid socket type */
+ break;
+#endif
+#ifdef UNIXdomain
+ case AF_LOCAL:
+ if (socktype != 0 &&
+ (socktype != SOCK_STREAM && socktype != SOCK_DGRAM))
+ return (EAI_SOCKTYPE); /* invalid socket type */
+ break;
+#endif
+ default:
+ return (EAI_FAMILY); /* unknown protocol family */
+ }
+ return (0);
+}
+
+/* end ga_echeck */
+
+struct search {
+ const char *host; /* hostname or address string */
+ int family; /* AF_xxx */
+};
+
+/*
+ * Set up the search[] array with the hostnames and address families
+ * that we are to look up.
+ */
+
+/* include ga_nsearch1 */
+static int
+ga_nsearch (const char *hostname, const struct addrinfo *hintsp,
+ struct search *search)
+{
+ int nsearch = 0;
+
+ if (hostname == NULL || hostname[0] == '\0')
+ {
+ if (hintsp->ai_flags & AI_PASSIVE)
+ {
+ /* 4no hostname and AI_PASSIVE: implies wildcard bind */
+ switch (hintsp->ai_family)
+ {
+#ifdef IPv4
+ case AF_INET:
+ search[nsearch].host = "0.0.0.0";
+ search[nsearch].family = AF_INET;
+ nsearch++;
+ break;
+#endif
+#ifdef IPv6
+ case AF_INET6:
+ search[nsearch].host = "0::0";
+ search[nsearch].family = AF_INET6;
+ nsearch++;
+ break;
+#endif
+ case AF_UNSPEC:
+#ifdef IPv6
+ search[nsearch].host = "0::0"; /* IPv6 first, then IPv4 */
+ search[nsearch].family = AF_INET6;
+ nsearch++;
+#endif
+#ifdef IPv4
+ search[nsearch].host = "0.0.0.0";
+ search[nsearch].family = AF_INET;
+ nsearch++;
+#endif
+ break;
+ }
+/* end ga_nsearch1 */
+/* include ga_nsearch2 */
+ }
+ else
+ {
+ /* 4no host and not AI_PASSIVE: connect to local host */
+ switch (hintsp->ai_family)
+ {
+#ifdef IPv4
+ case AF_INET:
+ search[nsearch].host = "localhost"; /* 127.0.0.1 */
+ search[nsearch].family = AF_INET;
+ nsearch++;
+ break;
+#endif
+#ifdef IPv6
+ case AF_INET6:
+ search[nsearch].host = "0::1";
+ search[nsearch].family = AF_INET6;
+ nsearch++;
+ break;
+#endif
+ case AF_UNSPEC:
+#ifdef IPv6
+ search[nsearch].host = "0::1"; /* IPv6 first, then IPv4 */
+ search[nsearch].family = AF_INET6;
+ nsearch++;
+#endif
+#ifdef IPv4
+ search[nsearch].host = "localhost";
+ search[nsearch].family = AF_INET;
+ nsearch++;
+#endif
+ break;
+ }
+ }
+/* end ga_nsearch2 */
+/* include ga_nsearch3 */
+ }
+ else
+ { /* host is specified */
+ switch (hintsp->ai_family)
+ {
+#ifdef IPv4
+ case AF_INET:
+ search[nsearch].host = hostname;
+ search[nsearch].family = AF_INET;
+ nsearch++;
+ break;
+#endif
+#ifdef IPv6
+ case AF_INET6:
+ search[nsearch].host = hostname;
+ search[nsearch].family = AF_INET6;
+ nsearch++;
+ break;
+#endif
+ case AF_UNSPEC:
+#ifdef IPv6
+ search[nsearch].host = hostname;
+ search[nsearch].family = AF_INET6; /* IPv6 first */
+ nsearch++;
+#endif
+#ifdef IPv4
+ search[nsearch].host = hostname;
+ search[nsearch].family = AF_INET; /* then IPv4 */
+ nsearch++;
+#endif
+ break;
+ }
+ }
+ if (nsearch < 1 || nsearch > 2)
+ return -1;
+ return (nsearch);
+}
+
+/* end ga_nsearch3 */
+
+/*
+ * Go through all the addrinfo structures, checking for a match of the
+ * socket type and filling in the socket type, and then the port number
+ * in the corresponding socket address structures.
+ *
+ * The AI_CLONE flag works as follows. Consider a multihomed host with
+ * two IP addresses and no socket type specified by the caller. After
+ * the "host" search there are two addrinfo structures, one per IP address.
+ * Assuming a service supported by both TCP and UDP (say the daytime
+ * service) we need to return *four* addrinfo structures:
+ * IP#1, SOCK_STREAM, TCP port,
+ * IP#1, SOCK_DGRAM, UDP port,
+ * IP#2, SOCK_STREAM, TCP port,
+ * IP#2, SOCK_DGRAM, UDP port.
+ * To do this, when the "host" loop creates an addrinfo structure, if the
+ * caller has not specified a socket type (hintsp->ai_socktype == 0), the
+ * AI_CLONE flag is set. When the following function finds an entry like
+ * this it is handled as follows: If the entry's ai_socktype is still 0,
+ * this is the first use of the structure, and the ai_socktype field is set.
+ * But, if the entry's ai_socktype is nonzero, then we clone a new addrinfo
+ * structure and set it's ai_socktype to the new value. Although we only
+ * need two socket types today (SOCK_STREAM and SOCK_DGRAM) this algorithm
+ * will handle any number. Also notice that Posix.1g requires all socket
+ * types to be nonzero.
+ */
+
+/* include ga_port */
+static int
+ga_port (struct addrinfo *aihead, int port, int socktype)
+ /* port must be in network byte order */
+{
+ int nfound = 0;
+ struct addrinfo *ai;
+
+ for (ai = aihead; ai != NULL; ai = ai->ai_next)
+ {
+ if (ai->ai_flags & AI_CLONE)
+ {
+ if (ai->ai_socktype != 0)
+ {
+ if ((ai = ga_clone (ai)) == NULL)
+ return (-1); /* memory allocation error */
+ /* ai points to newly cloned entry, which is what we want */
+ }
+ }
+ else if (ai->ai_socktype != socktype)
+ continue; /* ignore if mismatch on socket type */
+
+ ai->ai_socktype = socktype;
+
+ switch (ai->ai_family)
+ {
+#ifdef IPv4
+ case AF_INET:
+ ((struct sockaddr_in *) ai->ai_addr)->sin_port = port;
+ nfound++;
+ break;
+#endif
+#ifdef IPv6
+ case AF_INET6:
+ ((struct sockaddr_in6 *) ai->ai_addr)->sin6_port = port;
+ nfound++;
+ break;
+#endif
+ }
+ }
+ return (nfound);
+}
+
+/* end ga_port */
+
+/*
+ * This function handles the service string.
+ */
+
+/* include ga_serv */
+static int
+ga_serv (struct addrinfo *aihead, const struct addrinfo *hintsp,
+ const char *serv)
+{
+ int port, rc, nfound;
+ struct servent *sptr;
+
+ nfound = 0;
+ if (isdigit (serv[0]))
+ { /* check for port number string first */
+ port = htons (atoi (serv));
+ if (hintsp->ai_socktype)
+ {
+ /* 4caller specifies socket type */
+ if ((rc = ga_port (aihead, port, hintsp->ai_socktype)) < 0)
+ return (EAI_MEMORY);
+ nfound += rc;
+ }
+ else
+ {
+ /* 4caller does not specify socket type */
+ if ((rc = ga_port (aihead, port, SOCK_STREAM)) < 0)
+ return (EAI_MEMORY);
+ nfound += rc;
+ if ((rc = ga_port (aihead, port, SOCK_DGRAM)) < 0)
+ return (EAI_MEMORY);
+ nfound += rc;
+ }
+ }
+ else
+ {
+ /* 4try service name, TCP then UDP */
+ if (hintsp->ai_socktype == 0 || hintsp->ai_socktype == SOCK_STREAM)
+ {
+ if ((sptr = cygwin_getservbyname (serv, "tcp")) != NULL)
+ {
+ if ((rc = ga_port (aihead, sptr->s_port, SOCK_STREAM)) < 0)
+ return (EAI_MEMORY);
+ nfound += rc;
+ }
+ }
+ if (hintsp->ai_socktype == 0 || hintsp->ai_socktype == SOCK_DGRAM)
+ {
+ if ((sptr = cygwin_getservbyname (serv, "udp")) != NULL)
+ {
+ if ((rc = ga_port (aihead, sptr->s_port, SOCK_DGRAM)) < 0)
+ return (EAI_MEMORY);
+ nfound += rc;
+ }
+ }
+ }
+
+ if (nfound == 0)
+ {
+ if (hintsp->ai_socktype == 0)
+ return (EAI_NONAME); /* all calls to getservbyname() failed */
+ else
+ return (EAI_SERVICE); /* service not supported for socket type */
+ }
+ return (0);
+}
+
+/* end ga_serv */
+
+#ifdef UNIXdomain
+/* include ga_unix */
+static int
+ga_unix (const char *path, struct addrinfo *hintsp, struct addrinfo **result)
+{
+ int rc;
+ struct addrinfo *aihead, **aipnext;
+
+ aihead = NULL;
+ aipnext = &aihead;
+
+ if (hintsp->ai_family != AF_UNSPEC && hintsp->ai_family != AF_LOCAL)
+ return (EAI_ADDRFAMILY);
+
+ if (hintsp->ai_socktype == 0)
+ {
+ /* 4no socket type specified: return stream then dgram */
+ hintsp->ai_socktype = SOCK_STREAM;
+ if ((rc = ga_aistruct (&aipnext, hintsp, path, AF_LOCAL)) != 0)
+ return (rc);
+ hintsp->ai_socktype = SOCK_DGRAM;
+ }
+
+ if ((rc = ga_aistruct (&aipnext, hintsp, path, AF_LOCAL)) != 0)
+ return (rc);
+
+ if (hintsp->ai_flags & AI_CANONNAME)
+ {
+ struct utsname myname;
+
+ if (uname (&myname) < 0)
+ return (EAI_SYSTEM);
+ if ((aihead->ai_canonname = strdup (myname.nodename)) == NULL)
+ return (EAI_MEMORY);
+ }
+
+ *result = aihead; /* pointer to first structure in linked list */
+ return (0);
+}
+
+/* end ga_unix */
+#endif /* UNIXdomain */
+
+/* include gn_ipv46 */
+static int
+gn_ipv46 (char *host, size_t hostlen, char *serv, size_t servlen,
+ void *aptr, size_t alen, int family, int port, int flags)
+{
+ char *ptr;
+ struct hostent *hptr;
+ struct servent *sptr;
+
+ if (host && hostlen > 0)
+ {
+ if (flags & NI_NUMERICHOST)
+ {
+ if (cygwin_inet_ntop (family, aptr, host, hostlen) == NULL)
+ return (1);
+ }
+ else
+ {
+ hptr = cygwin_gethostbyaddr ((const char *) aptr, alen, family);
+ if (hptr != NULL && hptr->h_name != NULL)
+ {
+ if (flags & NI_NOFQDN)
+ {
+ if ((ptr = strchr (hptr->h_name, '.')) != NULL)
+ *ptr = 0; /* overwrite first dot */
+ }
+ //snprintf (host, hostlen, "%s", hptr->h_name);
+ *host = '\0';
+ strncat (host, hptr->h_name, hostlen - 1);
+ }
+ else
+ {
+ if (flags & NI_NAMEREQD)
+ return (1);
+ if (cygwin_inet_ntop (family, aptr, host, hostlen) == NULL)
+ return (1);
+ }
+ }
+ }
+
+ if (serv && servlen > 0)
+ {
+ if (flags & NI_NUMERICSERV)
+ {
+ //snprintf (serv, servlen, "%d", ntohs (port));
+ char buf[32];
+ __small_sprintf (buf, "%d", ntohs (port));
+ *serv = '\0';
+ strncat (serv, buf, servlen - 1);
+ }
+ else
+ {
+ sptr = cygwin_getservbyport (port, (flags & NI_DGRAM) ? "udp" : NULL);
+ if (sptr != NULL && sptr->s_name != NULL)
+ {
+ //snprintf (serv, servlen, "%s", sptr->s_name);
+ *serv = '\0';
+ strncat (serv, sptr->s_name, servlen - 1);
+ }
+ else
+ {
+ //snprintf (serv, servlen, "%d", ntohs (port));
+ char buf[32];
+ __small_sprintf (buf, "%d", ntohs (port));
+ *serv = '\0';
+ strncat (serv, buf, servlen - 1);
+ }
+ }
+ }
+ return (0);
+}
+
+/* end gn_ipv46 */
+
+/* include freeaddrinfo */
+void
+ipv4_freeaddrinfo (struct addrinfo *aihead)
+{
+ struct addrinfo *ai, *ainext;
+
+ for (ai = aihead; ai != NULL; ai = ainext)
+ {
+ if (ai->ai_addr != NULL)
+ free (ai->ai_addr); /* socket address structure */
+
+ if (ai->ai_canonname != NULL)
+ free (ai->ai_canonname);
+
+ ainext = ai->ai_next; /* can't fetch ai_next after free() */
+ free (ai); /* the addrinfo{} itself */
+ }
+}
+
+/* end freeaddrinfo */
+
+/* include ga1 */
+
+int
+ipv4_getaddrinfo (const char *hostname, const char *servname,
+ const struct addrinfo *hintsp, struct addrinfo **result)
+{
+ int rc, error, nsearch;
+ char **ap, *canon;
+ struct hostent *hptr;
+ struct search search[3], *sptr;
+ struct addrinfo hints, *aihead, **aipnext;
+
+ /*
+ * If we encounter an error we want to free() any dynamic memory
+ * that we've allocated. This is our hack to simplify the code.
+ */
+#define error(e) { error = (e); goto bad; }
+
+ aihead = NULL; /* initialize automatic variables */
+ aipnext = &aihead;
+ canon = NULL;
+
+ if (hintsp == NULL)
+ {
+ bzero (&hints, sizeof (hints));
+ hints.ai_family = AF_UNSPEC;
+ }
+ else
+ hints = *hintsp; /* struct copy */
+
+ /* 4first some basic error checking */
+ if ((rc = ga_echeck (hostname, servname, hints.ai_flags, hints.ai_family,
+ hints.ai_socktype, hints.ai_protocol)) != 0)
+ error (rc);
+
+#ifdef UNIXdomain
+ /* 4special case Unix domain first */
+ if (hostname != NULL &&
+ (strcmp (hostname, "/local") == 0 || strcmp (hostname, "/unix") == 0) &&
+ (servname != NULL && servname[0] == '/'))
+ return (ga_unix (servname, &hints, result));
+#endif
+/* end ga1 */
+
+/* include ga3 */
+ /* 4remainder of function for IPv4/IPv6 */
+ nsearch = ga_nsearch (hostname, &hints, &search[0]);
+ if (nsearch == -1)
+ error (EAI_FAMILY);
+ for (sptr = &search[0]; sptr < &search[nsearch]; sptr++)
+ {
+#ifdef IPv4
+ /* 4check for an IPv4 dotted-decimal string */
+ if (isdigit (sptr->host[0]))
+ {
+ struct in_addr inaddr;
+
+ if (inet_pton4 (sptr->host, (u_char *) &inaddr) == 1)
+ {
+ if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET)
+ error (EAI_ADDRFAMILY);
+ if (sptr->family != AF_INET)
+ continue; /* ignore */
+ rc = ga_aistruct (&aipnext, &hints, &inaddr, AF_INET);
+ if (rc != 0)
+ error (rc);
+ continue;
+ }
+ }
+#endif
+
+#ifdef IPv6
+ /* 4check for an IPv6 hex string */
+ if ((isxdigit (sptr->host[0]) || sptr->host[0] == ':') &&
+ (strchr (sptr->host, ':') != NULL))
+ {
+ struct in6_addr in6addr;
+
+ if (inet_pton6 (sptr->host, &in6addr) == 1)
+ {
+ if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET6)
+ error (EAI_ADDRFAMILY);
+ if (sptr->family != AF_INET6)
+ continue; /* ignore */
+ rc = ga_aistruct (&aipnext, &hints, &in6addr, AF_INET6);
+ if (rc != 0)
+ error (rc);
+ continue;
+ }
+ }
+#endif
+/* end ga3 */
+/* include ga4 */
+#ifdef IPv6
+ /* 4remainder of for() to look up hostname */
+ if ((_res.options & RES_INIT) == 0)
+ res_init (); /* need this to set _res.options */
+#endif
+
+ if (nsearch == 2)
+ {
+#ifdef IPv6
+ _res.options &= ~RES_USE_INET6;
+#endif
+ hptr = gethostbyname2 (sptr->host, sptr->family);
+ }
+ else
+ {
+#ifdef IPv6
+ if (sptr->family == AF_INET6)
+ _res.options |= RES_USE_INET6;
+ else
+ _res.options &= ~RES_USE_INET6;
+#endif
+ hptr = gethostbyname (sptr->host);
+ }
+ if (hptr == NULL)
+ {
+ if (nsearch == 2)
+ continue; /* failure OK if multiple searches */
+
+ switch (h_errno)
+ {
+ case HOST_NOT_FOUND:
+ error (EAI_NONAME);
+ case TRY_AGAIN:
+ error (EAI_AGAIN);
+ case NO_RECOVERY:
+ error (EAI_FAIL);
+ case NO_DATA:
+ error (EAI_NODATA);
+ default:
+ error (EAI_NONAME);
+ }
+ }
+
+ /* 4check for address family mismatch if one specified */
+ if (hints.ai_family != AF_UNSPEC && hints.ai_family != hptr->h_addrtype)
+ error (EAI_ADDRFAMILY);
+
+ /* 4save canonical name first time */
+ if (hostname != NULL && hostname[0] != '\0' &&
+ (hints.ai_flags & AI_CANONNAME) && canon == NULL)
+ {
+ if ((canon = strdup (hptr->h_name)) == NULL)
+ error (EAI_MEMORY);
+ }
+
+ /* 4create one addrinfo{} for each returned address */
+ for (ap = hptr->h_addr_list; *ap != NULL; ap++)
+ {
+ rc = ga_aistruct (&aipnext, &hints, *ap, hptr->h_addrtype);
+ if (rc != 0)
+ error (rc);
+ }
+ }
+ if (aihead == NULL)
+ error (EAI_NONAME); /* nothing found */
+/* end ga4 */
+
+/* include ga5 */
+ /* 4return canonical name */
+ if (hostname != NULL && hostname[0] != '\0' &&
+ hints.ai_flags & AI_CANONNAME)
+ {
+ if (canon != NULL)
+ aihead->ai_canonname = canon; /* strdup'ed earlier */
+ else
+ {
+ if ((aihead->ai_canonname = strdup (search[0].host)) == NULL)
+ error (EAI_MEMORY);
+ }
+ }
+
+ /* 4now process the service name */
+ if (servname != NULL && servname[0] != '\0')
+ {
+ if ((rc = ga_serv (aihead, &hints, servname)) != 0)
+ error (rc);
+ }
+
+ *result = aihead; /* pointer to first structure in linked list */
+ return (0);
+
+bad:
+ ipv4_freeaddrinfo (aihead); /* free any alloc'ed memory */
+ return (error);
+}
+
+/* end ga5 */
+
+/* include getnameinfo */
+int
+ipv4_getnameinfo (const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen, int flags)
+{
+
+ switch (sa->sa_family)
+ {
+#ifdef IPv4
+ case AF_INET:
+ {
+ struct sockaddr_in *sain = (struct sockaddr_in *) sa;
+
+ return (gn_ipv46 (host, hostlen, serv, servlen,
+ &sain->sin_addr, sizeof (struct in_addr),
+ AF_INET, sain->sin_port, flags));
+ }
+#endif
+
+#ifdef IPv6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sain = (struct sockaddr_in6 *) sa;
+
+ return (gn_ipv46 (host, hostlen, serv, servlen,
+ &sain->sin6_addr, sizeof (struct in6_addr),
+ AF_INET6, sain->sin6_port, flags));
+ }
+#endif
+
+#ifdef UNIXdomain
+ case AF_LOCAL:
+ {
+ struct sockaddr_un *un = (struct sockaddr_un *) sa;
+
+ if (hostlen > 0)
+ snprintf (host, hostlen, "%s", "/local");
+ if (servlen > 0)
+ snprintf (serv, servlen, "%s", un->sun_path);
+ return (0);
+ }
+#endif
+
+ default:
+ return (1);
+ }
+}
+
+/* end getnameinfo */
+
+/* Start of cygwin specific wrappers around the gai functions. */
+
+struct gai_errmap_t
+{
+ int w32_errval;
+ const char *errtxt;
+};
+
+static gai_errmap_t gai_errmap[] =
+{
+ {0, "Success"},
+ {0, "Address family for hostname not supported"},
+ {WSATRY_AGAIN, "Temporary failure in name resolution"},
+ {WSAEINVAL, "Invalid value for ai_flags"},
+ {WSANO_RECOVERY, "Non-recoverable failure in name resolution"},
+ {WSAEAFNOSUPPORT, "ai_family not supported"},
+ {WSA_NOT_ENOUGH_MEMORY, "Memory allocation failure"},
+ {WSANO_DATA, "No address associated with hostname"},
+ {WSAHOST_NOT_FOUND, "hostname nor servname provided, or not known"},
+ {WSATYPE_NOT_FOUND, "servname not supported for ai_socktype"},
+ {WSAESOCKTNOSUPPORT, "ai_socktype not supported"},
+ {0, "System error returned in errno"},
+ {0, "Invalid value for hints"},
+ {0, "Resolved protocol is unknown"}
+};
+
+extern "C" const char *
+cygwin_gai_strerror (int err)
+{
+ if (err >= 0 && err < EAI_MAX)
+ return gai_errmap[err].errtxt;
+ return "Unknown error";
+}
+
+static int
+w32_to_gai_err (int w32_err)
+{
+ if (w32_err >= WSABASEERR)
+ for (int i = 0; i < EAI_MAX; ++i)
+ if (gai_errmap[i].w32_errval == w32_err)
+ return i;
+ return w32_err;
+}
+
+/* We can't use autoload here because we don't know where the functions
+ are loaded from. On Win2K, the functions are available in the
+ ipv6 technology preview lib called wship6.dll, in XP and above they
+ are implemented in ws2_32.dll. For older systems we use the ipv4-only
+ version above. */
+
+static void (WINAPI *freeaddrinfo)(const struct addrinfo *);
+static int (WINAPI *getaddrinfo)(const char *, const char *,
+ const struct addrinfo *,
+ struct addrinfo **);
+static int (WINAPI *getnameinfo)(const struct sockaddr *, socklen_t,
+ char *, size_t, char *, size_t, int);
+static bool
+get_ipv6_funcs (HMODULE lib)
+{
+ return ((freeaddrinfo = (void (WINAPI *)(const struct addrinfo *))
+ GetProcAddress(lib, "freeaddrinfo"))
+ && (getaddrinfo = (int (WINAPI *)(const char *, const char *,
+ const struct addrinfo *,
+ struct addrinfo **))
+ GetProcAddress(lib, "getaddrinfo"))
+ && (getnameinfo = (int (WINAPI *)(const struct sockaddr *,
+ socklen_t, char *, size_t,
+ char *, size_t, int))
+ GetProcAddress(lib, "getnameinfo")));
+}
+
+static NO_COPY muto load_ipv6_guard;
+static bool ipv6_inited = false;
+#define load_ipv6() if (!ipv6_inited) load_ipv6_funcs ();
+
+static void
+load_ipv6_funcs ()
+{
+
+ char lib_name[CYG_MAX_PATH];
+ size_t len;
+ HMODULE lib;
+
+ load_ipv6_guard.init ("klog_guard")->acquire ();
+ if (ipv6_inited)
+ goto out;
+ WSAGetLastError (); /* Kludge. Enforce WSAStartup call. */
+ if (GetSystemDirectory (lib_name, CYG_MAX_PATH))
+ {
+ len = strlen (lib_name);
+ strcpy (lib_name + len, "\\ws2_32.dll");
+ if ((lib = LoadLibrary (lib_name)))
+ {
+ if (get_ipv6_funcs (lib))
+ goto out;
+ FreeLibrary (lib);
+ }
+ strcpy (lib_name + len, "\\wship6.dll");
+ if ((lib = LoadLibrary (lib_name)))
+ {
+ if (get_ipv6_funcs (lib))
+ goto out;
+ FreeLibrary (lib);
+ }
+ freeaddrinfo = NULL;
+ getaddrinfo = NULL;
+ getnameinfo = NULL;
+ }
+out:
+ ipv6_inited = true;
+ load_ipv6_guard.release ();
+}
+
+extern "C" void
+cygwin_freeaddrinfo (struct addrinfo *addr)
+{
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return;
+ load_ipv6 ();
+ if (freeaddrinfo)
+ freeaddrinfo (addr);
+ else
+ ipv4_freeaddrinfo (addr);
+}
+
+extern "C" int
+cygwin_getaddrinfo (const char *hostname, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res)
+{
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return EAI_SYSTEM;
+ load_ipv6 ();
+ if (getaddrinfo)
+ return w32_to_gai_err (getaddrinfo (hostname, servname, hints, res));
+ return ipv4_getaddrinfo (hostname, servname, hints, res);
+}
+
+extern "C" int
+cygwin_getnameinfo (const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen, char *serv,
+ size_t servlen, int flags)
+{
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return EAI_SYSTEM;
+ load_ipv6 ();
+ if (getnameinfo)
+ {
+ /* When the incoming port number is set to 0, Winsock's getnameinfo
+ returns with error WSAENO_DATA instead of simply ignoring the port.
+ To avoid this strange behaviour, we check manually, if the port number
+ is 0. If so, set the NI_NUMERICSERV flag to avoid this problem. */
+ switch (sa->sa_family)
+ {
+ case AF_INET:
+ if (((struct sockaddr_in *) sa)->sin_port == 0)
+ flags |= NI_NUMERICSERV;
+ break;
+ case AF_INET6:
+ if (((struct sockaddr_in6 *) sa)->sin6_port == 0)
+ flags |= NI_NUMERICSERV;
+ break;
+ }
+ int ret = w32_to_gai_err (getnameinfo (sa, salen, host, hostlen, serv,
+ servlen, flags));
+ if (ret)
+ set_winsock_errno ();
+ return ret;
+ }
+ return ipv4_getnameinfo (sa, salen, host, hostlen, serv, servlen, flags);
+}
+