PageRenderTime 55ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/win32/win32compat/sfds.c

https://gitlab.com/adam.lukaitis/Win32-OpenSSH
C | 459 lines | 253 code | 94 blank | 112 comment | 39 complexity | c041647df8c528113fef81decc929749 MD5 | raw file
  1. /*
  2. * Author: NoMachine <developers@nomachine.com>
  3. *
  4. * Copyright (c) 2009, 2012 NoMachine
  5. * All rights reserved
  6. *
  7. * Support functions and system calls' replacements needed to let the
  8. * software run on Win32 based operating systems.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. *
  14. * 1. Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. * 2. Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in the
  18. * documentation and/or other materials provided with the distribution.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  21. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  22. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  23. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  25. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  29. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #include <winsock2.h>
  32. #include <io.h>
  33. #include "sfds.h"
  34. #ifndef __MINGW32__
  35. #include <Crtdbg.h>
  36. #endif
  37. extern void debug(const char *fmt,...);
  38. extern void debug2(const char *fmt,...);
  39. extern void debug3(const char *fmt,...);
  40. extern void error(const char *fmt,...);
  41. extern void fatal(const char *fmt,...);
  42. /*
  43. * structure to store real file descriptor and type for sfd
  44. */
  45. static struct
  46. {
  47. int fd;
  48. HANDLE handle;
  49. sfd_type type;
  50. } sfd_map[SFD_MAP_SIZE];
  51. static int sfd_map_init = 0;
  52. static int sfd_count = 0;
  53. int sfd_start = 0;
  54. #ifndef __MINGW32__
  55. void myInvalidParameterHandler(const wchar_t* expression,
  56. const wchar_t* function,
  57. const wchar_t* file,
  58. unsigned int line,
  59. uintptr_t pReserved)
  60. {
  61. return;
  62. }
  63. #endif
  64. /*
  65. * store real fd in map, detect fd type and return sfd number.
  66. */
  67. int allocate_sfd(int fd_or_handle)
  68. {
  69. int slot = SFD_FD_INVALID;
  70. int i;
  71. int real_fd;
  72. HANDLE real_handle;
  73. DWORD handle_type;
  74. /*
  75. * Init the map once
  76. */
  77. if (!sfd_map_init)
  78. {
  79. sfd_map_init = 1;
  80. for (i = 0; i < SFD_MAP_SIZE; ++i)
  81. {
  82. sfd_map[i].fd = SFD_FD_INVALID;
  83. sfd_map[i].type = SFD_TYPE_NONE;
  84. }
  85. }
  86. /*
  87. * Find an open slot
  88. */
  89. for (i = sfd_start; i < SFD_MAP_SIZE; ++i)
  90. {
  91. /*
  92. * Is this slot open?
  93. */
  94. if (sfd_map[i].fd == SFD_FD_INVALID)
  95. {
  96. slot = i;
  97. break;
  98. }
  99. }
  100. /*
  101. * Bail if no slot found
  102. */
  103. if (slot == SFD_FD_INVALID)
  104. {
  105. error("ERROR: Too many connections.");
  106. return -1;
  107. }
  108. #if 0
  109. /*
  110. * Detect and save real fd and real handle
  111. */
  112. int optVal;
  113. int optLen = sizeof(int);
  114. BOOL bIsSocket = TRUE;
  115. HRESULT hr = S_OK;
  116. int ret = getsockopt(fd_or_handle,
  117. SOL_SOCKET,
  118. SO_DEBUG,
  119. (char*)&optVal,
  120. &optLen);
  121. if (ret == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK)
  122. {
  123. bIsSocket = FALSE;
  124. }
  125. // if (!bIsSocket && fd_or_handle > 600)
  126. // bIsSocket = TRUE;
  127. if (bIsSocket == TRUE)
  128. real_handle = (HANDLE)fd_or_handle;
  129. else
  130. #endif
  131. #ifndef __MINGW32__
  132. _invalid_parameter_handler oldHandler, newHandler;
  133. newHandler = myInvalidParameterHandler;
  134. oldHandler = _set_invalid_parameter_handler(newHandler);
  135. int iPrev = _CrtSetReportMode(_CRT_ASSERT, 0);
  136. #endif
  137. real_handle = (HANDLE)_get_osfhandle(fd_or_handle);
  138. #ifndef __MINGW32__
  139. _set_invalid_parameter_handler(oldHandler);
  140. _CrtSetReportMode(_CRT_ASSERT, iPrev);
  141. #endif
  142. if (real_handle == INVALID_HANDLE_VALUE)
  143. {
  144. /*
  145. * fd_or_handle was a handle, we can try to create a fd for it
  146. */
  147. real_handle = (HANDLE) fd_or_handle;
  148. real_fd = _open_osfhandle((long) real_handle, 0);
  149. }
  150. else
  151. {
  152. /*
  153. * fd_or_handle was a fd
  154. */
  155. real_fd = fd_or_handle;
  156. }
  157. debug3("_get_osfhandle() for real_fd [%d] returned [%d]", real_fd, real_handle);
  158. /*
  159. * Detect and save type
  160. */
  161. handle_type = GetFileType(real_handle);
  162. debug3("GetFileType() for handle [%d] returned [%d]", real_handle, handle_type);
  163. switch (handle_type)
  164. {
  165. case FILE_TYPE_CHAR:
  166. {
  167. sfd_map[slot].type = SFD_TYPE_CONSOLE;
  168. break;
  169. }
  170. case FILE_TYPE_PIPE:
  171. {
  172. int optVal = 0;
  173. int optLen = sizeof(optVal);
  174. if (getsockopt((SOCKET) real_handle, SOL_SOCKET,
  175. SO_ACCEPTCONN, (char *) &optVal, &optLen))
  176. {
  177. sfd_map[slot].type = SFD_TYPE_PIPE;
  178. }
  179. else
  180. {
  181. sfd_map[slot].type = SFD_TYPE_SOCKET;
  182. }
  183. break;
  184. }
  185. case FILE_TYPE_DISK:
  186. {
  187. sfd_map[slot].type = SFD_TYPE_FD;
  188. break;
  189. }
  190. case FILE_TYPE_UNKNOWN:
  191. {
  192. error("unknown type for handle [%d]", real_handle);
  193. return SFD_FD_INVALID;
  194. break;
  195. }
  196. default:
  197. {
  198. error("cannot detect a type for handle [%d]", real_handle);
  199. return SFD_FD_INVALID;
  200. break;
  201. }
  202. }
  203. /*
  204. * Save the fd and handle
  205. */
  206. sfd_map[slot].fd = (int) real_fd;
  207. sfd_map[slot].handle = (HANDLE) real_handle;
  208. debug("allocating new sfd, sfd [%i] fd [%i] handle [%d] type [%i]",
  209. slot, real_fd, real_handle, sfd_map[slot].type);
  210. sfd_count++;
  211. /*
  212. * Return the slot as the sfd
  213. */
  214. return (slot);
  215. }
  216. /*
  217. * For a real fd, get our sfd
  218. */
  219. int fd_to_sfd(int real_fd)
  220. {
  221. int i;
  222. int sfds;
  223. /*
  224. * Walk the list.
  225. */
  226. for (i = 0, sfds = 0; i < SFD_MAP_SIZE && sfds < sfd_count; i++)
  227. {
  228. /*
  229. * Increment the count of sfds that we have encountered in our walk,
  230. */
  231. if (sfd_map[i].fd != SFD_FD_INVALID)
  232. {
  233. sfds++;
  234. }
  235. if (sfd_map[i].fd == real_fd)
  236. {
  237. return i;
  238. }
  239. }
  240. fatal("cannot convert fd to sfd");
  241. return SFD_FD_INVALID;
  242. }
  243. /*
  244. * For an sfd, get the real descriptor behind it.
  245. */
  246. int sfd_to_fd(int sfd)
  247. {
  248. return sfd_map[sfd].fd;
  249. }
  250. // set the sfd type to console. GetFileType() in Windows seem to return wrong type for a console returning PIPE (3) in place of CHARTYPE (2)
  251. void sfd_set_to_console(int sfd)
  252. {
  253. sfd_map[sfd].type = SFD_TYPE_CONSOLE;
  254. }
  255. /*
  256. * For an sfd, get the real handle behind it
  257. */
  258. HANDLE sfd_to_handle(int sfd)
  259. {
  260. return sfd_map[sfd].handle;
  261. }
  262. void sfd_replace(int sfd, HANDLE handle, int type)
  263. {
  264. //_close(sfd_map[sfd].handle);
  265. sfd_map[sfd].handle = handle;
  266. sfd_map[sfd].type = type;
  267. }
  268. /*
  269. * For an sfd, get the type
  270. */
  271. int get_sfd_type(int sfd)
  272. {
  273. if(sfd < sizeof(sfd_map) / sizeof(sfd_map[0]))
  274. {
  275. return sfd_map[sfd].type;
  276. }
  277. else
  278. {
  279. return -1;
  280. }
  281. }
  282. /*
  283. * Free an sfd from the map.
  284. */
  285. void free_sfd(int sfd)
  286. {
  287. if (sfd_map[sfd].type != SFD_TYPE_NONE
  288. && sfd < sizeof(sfd_map) / sizeof(sfd_map[0]))
  289. {
  290. /*
  291. * Blank the slot
  292. */
  293. sfd_map[sfd].fd = SFD_FD_INVALID;
  294. sfd_map[sfd].handle = (HANDLE) SFD_HANDLE_INVALID;
  295. sfd_map[sfd].type = SFD_TYPE_NONE;
  296. sfd_count--;
  297. }
  298. }
  299. /*
  300. * Check if sfd is file.
  301. */
  302. int
  303. sfd_is_fd(int sfd)
  304. {
  305. if (sfd_map[sfd].type == SFD_TYPE_FD)
  306. {
  307. return 1;
  308. }
  309. return 0;
  310. }
  311. /*
  312. * Check if sfd is socket.
  313. */
  314. int sfd_is_socket(int sfd)
  315. {
  316. if (sfd_map[sfd].type == SFD_TYPE_SOCKET)
  317. {
  318. return 1;
  319. }
  320. return 0;
  321. }
  322. /*
  323. * Check if sfd is pipe.
  324. */
  325. int sfd_is_pipe(int sfd)
  326. {
  327. if (sfd_map[sfd].type == SFD_TYPE_PIPE)
  328. {
  329. return 1;
  330. }
  331. return 0;
  332. }
  333. /*
  334. * Check if sfd is console.
  335. */
  336. int sfd_is_console(int sfd)
  337. {
  338. if (sfd_map[sfd].type == SFD_TYPE_CONSOLE)
  339. {
  340. return 1;
  341. }
  342. return 0;
  343. }
  344. /*
  345. * Check if sfd is file or console.
  346. */
  347. int sfd_is_fd_or_console(int sfd)
  348. {
  349. if (sfd_is_fd(sfd) || sfd_is_console(sfd))
  350. {
  351. return 1;
  352. }
  353. return 0;
  354. }
  355. /*
  356. * Check if sfd is socket or pipe.
  357. */
  358. int sfd_is_socket_or_pipe(int sfd)
  359. {
  360. if (sfd_is_socket(sfd) || sfd_is_pipe(sfd))
  361. {
  362. return 1;
  363. }
  364. return 0;
  365. }