socket.c 59 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465
  1. /*++
  2. Copyright (c) 2013 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. socket.c
  5. Abstract:
  6. This module implements kernel support for sockets.
  7. Author:
  8. Evan Green 4-Apr-2013
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <minoca/kernel/kernel.h>
  16. #include "iop.h"
  17. #include "unsocket.h"
  18. //
  19. // ---------------------------------------------------------------- Definitions
  20. //
  21. //
  22. // ------------------------------------------------------ Data Type Definitions
  23. //
  24. //
  25. // ----------------------------------------------- Internal Function Prototypes
  26. //
  27. VOID
  28. IopDestroySocket (
  29. PSOCKET Socket
  30. );
  31. //
  32. // -------------------------------------------------------------------- Globals
  33. //
  34. //
  35. // Store a pointer to the core networking interface.
  36. //
  37. NET_INTERFACE IoNetInterface;
  38. BOOL IoNetInterfaceInitialized = FALSE;
  39. //
  40. // ------------------------------------------------------------------ Functions
  41. //
  42. KERNEL_API
  43. VOID
  44. IoInitializeCoreNetworking (
  45. PNET_INTERFACE Interface
  46. )
  47. /*++
  48. Routine Description:
  49. This routine initializes the interface between the kernel and the core
  50. networking library. This routine should not be called by random drivers.
  51. Arguments:
  52. Interface - Supplies a pointer to the core networking library interface.
  53. Return Value:
  54. None.
  55. --*/
  56. {
  57. ASSERT((Interface->CreateSocket != NULL) &&
  58. (Interface->DestroySocket != NULL) &&
  59. (Interface->BindToAddress != NULL) &&
  60. (Interface->Listen != NULL) &&
  61. (Interface->Accept != NULL) &&
  62. (Interface->Connect != NULL) &&
  63. (Interface->CloseSocket != NULL) &&
  64. (Interface->Send != NULL) &&
  65. (Interface->Receive != NULL) &&
  66. (Interface->GetSetSocketInformation != NULL) &&
  67. (Interface->Shutdown != NULL) &&
  68. (Interface->UserControl != NULL));
  69. if (IoNetInterfaceInitialized != FALSE) {
  70. ASSERT(FALSE);
  71. return;
  72. }
  73. RtlCopyMemory(&IoNetInterface, Interface, sizeof(NET_INTERFACE));
  74. IoNetInterfaceInitialized = TRUE;
  75. return;
  76. }
  77. KERNEL_API
  78. ULONG
  79. IoSocketAddReference (
  80. PSOCKET Socket
  81. )
  82. /*++
  83. Routine Description:
  84. This routine increases the reference count on a socket.
  85. Arguments:
  86. Socket - Supplies a pointer to the socket whose reference count should be
  87. incremented.
  88. Return Value:
  89. Returns the old reference count.
  90. --*/
  91. {
  92. ULONG OldReferenceCount;
  93. OldReferenceCount = RtlAtomicAdd32(&(Socket->ReferenceCount), 1);
  94. ASSERT((OldReferenceCount != 0) & (OldReferenceCount < 0x20000000));
  95. return OldReferenceCount;
  96. }
  97. KERNEL_API
  98. ULONG
  99. IoSocketReleaseReference (
  100. PSOCKET Socket
  101. )
  102. /*++
  103. Routine Description:
  104. This routine decreases the reference count of a socket, and destroys the
  105. socket if in this call the reference count drops to zero.
  106. Arguments:
  107. Socket - Supplies a pointer to the socket whose reference count should be
  108. decremented.
  109. Return Value:
  110. Returns the old reference count.
  111. --*/
  112. {
  113. ULONG OldReferenceCount;
  114. OldReferenceCount = RtlAtomicAdd32(&(Socket->ReferenceCount), -1);
  115. ASSERT((OldReferenceCount != 0) & (OldReferenceCount < 0x20000000));
  116. if (OldReferenceCount == 1) {
  117. IopDestroySocket(Socket);
  118. }
  119. return OldReferenceCount;
  120. }
  121. KERNEL_API
  122. KSTATUS
  123. IoSocketCreatePair (
  124. NET_DOMAIN_TYPE Domain,
  125. NET_SOCKET_TYPE Type,
  126. ULONG Protocol,
  127. ULONG OpenFlags,
  128. PIO_HANDLE IoHandles[2]
  129. )
  130. /*++
  131. Routine Description:
  132. This routine creates a pair of sockets that are connected to each other.
  133. Arguments:
  134. Domain - Supplies the network domain to use on the socket.
  135. Type - Supplies the socket connection type.
  136. Protocol - Supplies the raw protocol value used on the network.
  137. OpenFlags - Supplies a bitfield of open flags governing the new handles.
  138. See OPEN_FLAG_* definitions.
  139. IoHandles - Supplies an array where the two I/O handles to the connected
  140. sockets will be returned on success.
  141. Return Value:
  142. Status code.
  143. --*/
  144. {
  145. KSTATUS Status;
  146. if (Domain == NetDomainLocal) {
  147. Status = IopCreateUnixSocketPair(Type, Protocol, OpenFlags, IoHandles);
  148. } else {
  149. Status = STATUS_DOMAIN_NOT_SUPPORTED;
  150. }
  151. return Status;
  152. }
  153. KERNEL_API
  154. KSTATUS
  155. IoSocketCreate (
  156. NET_DOMAIN_TYPE Domain,
  157. NET_SOCKET_TYPE Type,
  158. ULONG Protocol,
  159. ULONG OpenFlags,
  160. PIO_HANDLE *IoHandle
  161. )
  162. /*++
  163. Routine Description:
  164. This routine allocates resources associated with a new socket.
  165. Arguments:
  166. Domain - Supplies the network domain to use on the socket.
  167. Type - Supplies the socket connection type.
  168. Protocol - Supplies the raw protocol value used on the network.
  169. OpenFlags - Supplies the open flags for the socket. See OPEN_FLAG_*
  170. definitions.
  171. IoHandle - Supplies a pointer where a pointer to the new socket's I/O
  172. handle will be returned.
  173. Return Value:
  174. Status code.
  175. --*/
  176. {
  177. SOCKET_CREATION_PARAMETERS Parameters;
  178. FILE_PERMISSIONS Permissions;
  179. PKPROCESS Process;
  180. PSOCKET Socket;
  181. KSTATUS Status;
  182. Process = PsGetCurrentProcess();
  183. Parameters.Domain = Domain;
  184. Parameters.Type = Type;
  185. Parameters.Protocol = Protocol;
  186. Parameters.ExistingSocket = NULL;
  187. Permissions = FILE_PERMISSION_ALL & ~(Process->Umask);
  188. Status = IopOpen(FALSE,
  189. NULL,
  190. NULL,
  191. 0,
  192. IO_ACCESS_READ | IO_ACCESS_WRITE,
  193. OpenFlags,
  194. IoObjectSocket,
  195. &Parameters,
  196. Permissions,
  197. IoHandle);
  198. if (KSUCCESS(Status)) {
  199. Socket = NULL;
  200. Status = IoGetSocketFromHandle(*IoHandle, &Socket);
  201. ASSERT(KSUCCESS(Status));
  202. ASSERT(Socket != NULL);
  203. Socket->IoHandle = *IoHandle;
  204. }
  205. return Status;
  206. }
  207. KERNEL_API
  208. KSTATUS
  209. IoSocketBindToAddress (
  210. BOOL FromKernelMode,
  211. PIO_HANDLE Handle,
  212. PVOID Link,
  213. PNETWORK_ADDRESS Address,
  214. PSTR Path,
  215. UINTN PathSize
  216. )
  217. /*++
  218. Routine Description:
  219. This routine binds the socket to the given address and starts listening for
  220. client requests.
  221. Arguments:
  222. FromKernelMode - Supplies a boolean indicating if the request is coming
  223. from kernel mode or user mode. This value affects the root path node
  224. to traverse for local domain sockets.
  225. Handle - Supplies a pointer to the socket handle to bind.
  226. Link - Supplies an optional pointer to a link to bind to.
  227. Address - Supplies a pointer to the address to bind the socket to.
  228. Path - Supplies an optional pointer to a path, required if the network
  229. address is a local socket.
  230. PathSize - Supplies the size of the path in bytes including the null
  231. terminator.
  232. Return Value:
  233. Status code.
  234. --*/
  235. {
  236. PSOCKET Socket;
  237. KSTATUS Status;
  238. Status = IoGetSocketFromHandle(Handle, &Socket);
  239. if (!KSUCCESS(Status)) {
  240. goto SocketBindToAddressEnd;
  241. }
  242. //
  243. // If it's a local domain socket and there's an address, bind it into the
  244. // file system.
  245. //
  246. if (Socket->Domain == NetDomainLocal) {
  247. Status = IopUnixSocketBindToAddress(FromKernelMode,
  248. Handle,
  249. Address,
  250. Path,
  251. PathSize);
  252. } else {
  253. if (IoNetInterfaceInitialized == FALSE) {
  254. Status = STATUS_NOT_IMPLEMENTED;
  255. } else {
  256. Status = IoNetInterface.BindToAddress(Socket, Link, Address);
  257. }
  258. }
  259. if (!KSUCCESS(Status)) {
  260. goto SocketBindToAddressEnd;
  261. }
  262. SocketBindToAddressEnd:
  263. return Status;
  264. }
  265. KERNEL_API
  266. KSTATUS
  267. IoSocketListen (
  268. PIO_HANDLE Handle,
  269. ULONG BacklogCount
  270. )
  271. /*++
  272. Routine Description:
  273. This routine adds a bound socket to the list of listening sockets,
  274. officially allowing sockets to attempt to connect to it.
  275. Arguments:
  276. Handle - Supplies a pointer to the socket to mark as listening.
  277. BacklogCount - Supplies the number of attempted connections that can be
  278. queued before additional connections are refused.
  279. Return Value:
  280. Status code.
  281. --*/
  282. {
  283. PSOCKET Socket;
  284. KSTATUS Status;
  285. Status = IoGetSocketFromHandle(Handle, &Socket);
  286. if (!KSUCCESS(Status)) {
  287. goto SocketListenEnd;
  288. }
  289. if (Socket->Domain == NetDomainLocal) {
  290. Status = IopUnixSocketListen(Socket, BacklogCount);
  291. } else {
  292. if (IoNetInterfaceInitialized == FALSE) {
  293. Status = STATUS_NOT_IMPLEMENTED;
  294. } else {
  295. Status = IoNetInterface.Listen(Socket, BacklogCount);
  296. }
  297. }
  298. SocketListenEnd:
  299. return Status;
  300. }
  301. KERNEL_API
  302. KSTATUS
  303. IoSocketAccept (
  304. PIO_HANDLE Handle,
  305. PIO_HANDLE *NewConnectionSocket,
  306. PNETWORK_ADDRESS RemoteAddress,
  307. PSTR *RemotePath,
  308. PUINTN RemotePathSize
  309. )
  310. /*++
  311. Routine Description:
  312. This routine accepts an incoming connection on a listening connection-based
  313. socket.
  314. Arguments:
  315. Handle - Supplies a pointer to the socket to accept a connection from.
  316. NewConnectionSocket - Supplies a pointer where a new socket will be
  317. returned that represents the accepted connection with the remote
  318. host.
  319. RemoteAddress - Supplies a pointer where the address of the connected
  320. remote host will be returned.
  321. RemotePath - Supplies a pointer where a string containing the remote path
  322. will be returned on success. The caller does not own this string, it is
  323. connected with the new socket coming out. This only applies to local
  324. sockets.
  325. RemotePathSize - Supplies a pointer where the size of the remote path in
  326. bytes will be returned on success.
  327. Return Value:
  328. Status code.
  329. --*/
  330. {
  331. PSOCKET Socket;
  332. KSTATUS Status;
  333. *RemotePath = NULL;
  334. *RemotePathSize = 0;
  335. Status = IoGetSocketFromHandle(Handle, &Socket);
  336. if (!KSUCCESS(Status)) {
  337. goto SocketAcceptEnd;
  338. }
  339. if (Socket->Domain == NetDomainLocal) {
  340. Status = IopUnixSocketAccept(Socket,
  341. NewConnectionSocket,
  342. RemoteAddress,
  343. RemotePath,
  344. RemotePathSize);
  345. } else {
  346. if (IoNetInterfaceInitialized == FALSE) {
  347. Status = STATUS_NOT_IMPLEMENTED;
  348. } else {
  349. Status = IoNetInterface.Accept(Socket,
  350. NewConnectionSocket,
  351. RemoteAddress);
  352. }
  353. }
  354. SocketAcceptEnd:
  355. return Status;
  356. }
  357. KERNEL_API
  358. KSTATUS
  359. IoSocketConnect (
  360. BOOL FromKernelMode,
  361. PIO_HANDLE Handle,
  362. PNETWORK_ADDRESS Address,
  363. PSTR RemotePath,
  364. UINTN RemotePathSize
  365. )
  366. /*++
  367. Routine Description:
  368. This routine attempts to make an outgoing connection to a server.
  369. Arguments:
  370. FromKernelMode - Supplies a boolean indicating if the request is coming
  371. from kernel mode or user mode.
  372. Handle - Supplies a pointer to the socket to use for the connection.
  373. Address - Supplies a pointer to the address to connect to.
  374. RemotePath - Supplies a pointer to the path to connect to, if this is a
  375. local socket.
  376. RemotePathSize - Supplies the size of the remote path buffer in bytes,
  377. including the null terminator.
  378. Return Value:
  379. Status code.
  380. --*/
  381. {
  382. PSOCKET Socket;
  383. KSTATUS Status;
  384. Status = IoGetSocketFromHandle(Handle, &Socket);
  385. if (!KSUCCESS(Status)) {
  386. goto SocketConnectEnd;
  387. }
  388. if (Socket->Domain == NetDomainLocal) {
  389. Status = IopUnixSocketConnect(FromKernelMode,
  390. Socket,
  391. Address,
  392. RemotePath,
  393. RemotePathSize);
  394. } else {
  395. if (RemotePathSize != 0) {
  396. Status = STATUS_INVALID_PARAMETER;
  397. goto SocketConnectEnd;
  398. }
  399. if (IoNetInterfaceInitialized == FALSE) {
  400. Status = STATUS_NOT_IMPLEMENTED;
  401. } else {
  402. Status = IoNetInterface.Connect(Socket, Address);
  403. }
  404. }
  405. SocketConnectEnd:
  406. return Status;
  407. }
  408. KERNEL_API
  409. KSTATUS
  410. IoSocketSendData (
  411. BOOL FromKernelMode,
  412. PIO_HANDLE Handle,
  413. PSOCKET_IO_PARAMETERS Parameters,
  414. PIO_BUFFER IoBuffer
  415. )
  416. /*++
  417. Routine Description:
  418. This routine sends the given data buffer through the network.
  419. Arguments:
  420. FromKernelMode - Supplies a boolean indicating if the request is coming
  421. from kernel mode or user mode. This value affects the root path node
  422. to traverse for local domain sockets.
  423. Handle - Supplies a pointer to the socket to send the data to.
  424. Parameters - Supplies a pointer to the socket I/O parameters.
  425. IoBuffer - Supplies a pointer to the I/O buffer containing the data to
  426. send.
  427. Return Value:
  428. Status code.
  429. --*/
  430. {
  431. PSOCKET Socket;
  432. KSTATUS Status;
  433. Socket = NULL;
  434. Status = IoGetSocketFromHandle(Handle, &Socket);
  435. if (!KSUCCESS(Status)) {
  436. goto SocketSendData;
  437. }
  438. if ((Parameters->SocketIoFlags & SOCKET_IO_NON_BLOCKING) != 0) {
  439. Parameters->TimeoutInMilliseconds = 0;
  440. }
  441. if (Socket->Domain == NetDomainLocal) {
  442. Status = IopUnixSocketSendData(FromKernelMode,
  443. Socket,
  444. Parameters,
  445. IoBuffer);
  446. } else {
  447. if (IoNetInterfaceInitialized == FALSE) {
  448. Status = STATUS_NOT_IMPLEMENTED;
  449. } else {
  450. Status = IoNetInterface.Send(FromKernelMode,
  451. Socket,
  452. Parameters,
  453. IoBuffer);
  454. }
  455. }
  456. SocketSendData:
  457. return Status;
  458. }
  459. KERNEL_API
  460. KSTATUS
  461. IoSocketReceiveData (
  462. BOOL FromKernelMode,
  463. PIO_HANDLE Handle,
  464. PSOCKET_IO_PARAMETERS Parameters,
  465. PIO_BUFFER IoBuffer
  466. )
  467. /*++
  468. Routine Description:
  469. This routine is called by the user to receive data from the socket.
  470. Arguments:
  471. FromKernelMode - Supplies a boolean indicating if the request is coming
  472. from kernel mode or user mode. This value affects the root path node
  473. to traverse for local domain sockets.
  474. Handle - Supplies a pointer to the socket to receive data from.
  475. Parameters - Supplies a pointer to the socket I/O parameters.
  476. IoBuffer - Supplies a pointer to the I/O buffer where the received data
  477. will be returned.
  478. Return Value:
  479. STATUS_SUCCESS if any bytes were read.
  480. STATUS_TIMEOUT if the request timed out.
  481. STATUS_BUFFER_TOO_SMALL if the incoming datagram was too large for the
  482. buffer. The remainder of the datagram is discarded in this case.
  483. Other error codes on other failures.
  484. --*/
  485. {
  486. PSOCKET Socket;
  487. KSTATUS Status;
  488. Socket = NULL;
  489. Status = IoGetSocketFromHandle(Handle, &Socket);
  490. if (!KSUCCESS(Status)) {
  491. goto SocketReceiveDataEnd;
  492. }
  493. if ((Parameters->SocketIoFlags & SOCKET_IO_NON_BLOCKING) != 0) {
  494. Parameters->TimeoutInMilliseconds = 0;
  495. }
  496. if (Socket->Domain == NetDomainLocal) {
  497. Status = IopUnixSocketReceiveData(FromKernelMode,
  498. Socket,
  499. Parameters,
  500. IoBuffer);
  501. } else {
  502. if (IoNetInterfaceInitialized == FALSE) {
  503. Status = STATUS_NOT_IMPLEMENTED;
  504. } else {
  505. Status = IoNetInterface.Receive(FromKernelMode,
  506. Socket,
  507. Parameters,
  508. IoBuffer);
  509. }
  510. }
  511. SocketReceiveDataEnd:
  512. return Status;
  513. }
  514. KERNEL_API
  515. KSTATUS
  516. IoSocketGetSetInformation (
  517. PIO_HANDLE IoHandle,
  518. SOCKET_INFORMATION_TYPE InformationType,
  519. UINTN SocketOption,
  520. PVOID Data,
  521. PUINTN DataSize,
  522. BOOL Set
  523. )
  524. /*++
  525. Routine Description:
  526. This routine gets or sets information about the given socket.
  527. Arguments:
  528. IoHandle - Supplies a pointer to the I/O handle of the socket.
  529. InformationType - Supplies the socket information type category to which
  530. specified option belongs.
  531. SocketOption - Supplies the option to get or set, which is specific to the
  532. information type. The type of this value is generally
  533. SOCKET_<information_type>_OPTION.
  534. Data - Supplies a pointer to the data buffer where the data is either
  535. returned for a get operation or given for a set operation. If the
  536. data buffer is too small on a get operation, the truncated information
  537. will be copied to the data buffer and the routine will return
  538. STATUS_BUFFER_TOO_SMALL.
  539. DataSize - Supplies a pointer that on input constains the size of the data
  540. buffer. On output, this contains the required size of the data buffer.
  541. Set - Supplies a boolean indicating if this is a get operation (FALSE) or
  542. a set operation (TRUE).
  543. Return Value:
  544. STATUS_SUCCESS on success.
  545. STATUS_INVALID_PARAMETER if the data is not appropriate for the socket
  546. option.
  547. STATUS_BUFFER_TOO_SMALL if the socket option information does not fit in
  548. the supplied buffer. On a get request, the data buffer will be filled
  549. with the truncated socket information.
  550. STATUS_NOT_SUPPORTED_BY_PROTOCOL if the socket option or information type
  551. is not supported by the socket.
  552. STATUS_NOT_A_SOCKET if the given handle wasn't a socket.
  553. --*/
  554. {
  555. PSOCKET Socket;
  556. KSTATUS Status;
  557. ASSERT((Data == NULL) || (Data >= KERNEL_VA_START));
  558. Status = IoGetSocketFromHandle(IoHandle, &Socket);
  559. if (!KSUCCESS(Status)) {
  560. goto SocketGetSetInformationEnd;
  561. }
  562. if (Socket->Domain == NetDomainLocal) {
  563. Status = IopUnixSocketGetSetSocketInformation(Socket,
  564. InformationType,
  565. SocketOption,
  566. Data,
  567. DataSize,
  568. Set);
  569. } else {
  570. if (IoNetInterfaceInitialized == FALSE) {
  571. Status = STATUS_NOT_IMPLEMENTED;
  572. } else {
  573. Status = IoNetInterface.GetSetSocketInformation(Socket,
  574. InformationType,
  575. SocketOption,
  576. Data,
  577. DataSize,
  578. Set);
  579. }
  580. }
  581. SocketGetSetInformationEnd:
  582. return Status;
  583. }
  584. KERNEL_API
  585. KSTATUS
  586. IoSocketShutdown (
  587. PIO_HANDLE IoHandle,
  588. ULONG ShutdownType
  589. )
  590. /*++
  591. Routine Description:
  592. This routine shuts down communication with a given socket.
  593. Arguments:
  594. IoHandle - Supplies a pointer to the I/O handle of the socket.
  595. ShutdownType - Supplies the shutdown type to perform. See the
  596. SOCKET_SHUTDOWN_* definitions.
  597. Return Value:
  598. STATUS_SUCCESS on success.
  599. STATUS_NOT_A_SOCKET if the given handle wasn't a socket.
  600. Other error codes on failure.
  601. --*/
  602. {
  603. PSOCKET Socket;
  604. KSTATUS Status;
  605. Status = IoGetSocketFromHandle(IoHandle, &Socket);
  606. if (!KSUCCESS(Status)) {
  607. goto SocketShutdownEnd;
  608. }
  609. if (Socket->Domain == NetDomainLocal) {
  610. Status = IopUnixSocketShutdown(Socket, ShutdownType);
  611. } else {
  612. if (IoNetInterfaceInitialized == FALSE) {
  613. Status = STATUS_NOT_IMPLEMENTED;
  614. } else {
  615. Status = IoNetInterface.Shutdown(Socket, ShutdownType);
  616. }
  617. }
  618. SocketShutdownEnd:
  619. return Status;
  620. }
  621. KERNEL_API
  622. KSTATUS
  623. IoSocketUserControl (
  624. PIO_HANDLE Handle,
  625. ULONG CodeNumber,
  626. BOOL FromKernelMode,
  627. PVOID ContextBuffer,
  628. UINTN ContextBufferSize
  629. )
  630. /*++
  631. Routine Description:
  632. This routine handles user control requests destined for a socket.
  633. Arguments:
  634. Handle - Supplies the open file handle.
  635. CodeNumber - Supplies the minor code of the request.
  636. FromKernelMode - Supplies a boolean indicating whether or not this request
  637. (and the buffer associated with it) originates from user mode (FALSE)
  638. or kernel mode (TRUE).
  639. ContextBuffer - Supplies a pointer to the context buffer allocated by the
  640. caller for the request.
  641. ContextBufferSize - Supplies the size of the supplied context buffer.
  642. Return Value:
  643. Status code.
  644. --*/
  645. {
  646. PSOCKET Socket;
  647. KSTATUS Status;
  648. Status = IoGetSocketFromHandle(Handle, &Socket);
  649. if (!KSUCCESS(Status)) {
  650. goto SocketUserControlEnd;
  651. }
  652. if (Socket->Domain == NetDomainLocal) {
  653. Status = STATUS_NOT_SUPPORTED;
  654. } else {
  655. if (IoNetInterfaceInitialized == FALSE) {
  656. Status = STATUS_NOT_IMPLEMENTED;
  657. } else {
  658. Status = IoNetInterface.UserControl(Socket,
  659. CodeNumber,
  660. FromKernelMode,
  661. ContextBuffer,
  662. ContextBufferSize);
  663. }
  664. }
  665. SocketUserControlEnd:
  666. return Status;
  667. }
  668. KERNEL_API
  669. KSTATUS
  670. IoGetSocketFromHandle (
  671. PIO_HANDLE IoHandle,
  672. PSOCKET *Socket
  673. )
  674. /*++
  675. Routine Description:
  676. This routine returns the socket structure from inside an I/O handle. This
  677. routine is usually only used by networking protocol to get their own
  678. structures for the socket they create in the "accept" function.
  679. Arguments:
  680. IoHandle - Supplies a pointer to the I/O handle whose corresponding socket
  681. is desired.
  682. Socket - Supplies a pointer where a pointer to the socket corresponding to
  683. the given handle will be returned on success.
  684. Return Value:
  685. STATUS_SUCCESS on success.
  686. STATUS_NOT_A_SOCKET if the given handle wasn't a socket.
  687. --*/
  688. {
  689. PFILE_OBJECT FileObject;
  690. FileObject = IoHandle->FileObject;
  691. if (FileObject->Properties.Type != IoObjectSocket) {
  692. return STATUS_NOT_A_SOCKET;
  693. }
  694. *Socket = FileObject->SpecialIo;
  695. return STATUS_SUCCESS;
  696. }
  697. VOID
  698. IoSysSocketCreatePair (
  699. ULONG SystemCallNumber,
  700. PVOID SystemCallParameter,
  701. PTRAP_FRAME TrapFrame,
  702. PULONG ResultSize
  703. )
  704. /*++
  705. Routine Description:
  706. This routine handles the system call that creates a pair of connected
  707. sockets.
  708. Arguments:
  709. SystemCallNumber - Supplies the system call number that was requested.
  710. SystemCallParameter - Supplies a pointer to the parameters supplied with
  711. the system call. This structure will be a stack-local copy of the
  712. actual parameters passed from user-mode.
  713. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  714. from user mode to kernel mode.
  715. ResultSize - Supplies a pointer where the system call routine returns the
  716. size of the parameter structure to be copied back to user mode. The
  717. value returned here must be no larger than the original parameter
  718. structure size. The default is the original size of the parameters.
  719. Return Value:
  720. None.
  721. --*/
  722. {
  723. ULONG HandleFlags;
  724. ULONG OpenFlags;
  725. PSYSTEM_CALL_SOCKET_CREATE_PAIR Parameters;
  726. PKPROCESS Process;
  727. PIO_HANDLE Sockets[2];
  728. KSTATUS Status;
  729. ASSERT(SystemCallNumber == SystemCallSocketCreatePair);
  730. Parameters = (PSYSTEM_CALL_SOCKET_CREATE_PAIR)SystemCallParameter;
  731. Parameters->Socket1 = INVALID_HANDLE;
  732. Parameters->Socket2 = INVALID_HANDLE;
  733. Process = PsGetCurrentProcess();
  734. Sockets[0] = NULL;
  735. Sockets[1] = NULL;
  736. HandleFlags = 0;
  737. if ((Parameters->OpenFlags & SYS_OPEN_FLAG_CLOSE_ON_EXECUTE) != 0) {
  738. HandleFlags |= FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
  739. }
  740. OpenFlags = Parameters->OpenFlags & OPEN_FLAG_NON_BLOCKING;
  741. Status = IoSocketCreatePair(Parameters->Domain,
  742. Parameters->Type,
  743. Parameters->Protocol,
  744. OpenFlags,
  745. Sockets);
  746. if (!KSUCCESS(Status)) {
  747. goto CreateSocketPairEnd;
  748. }
  749. //
  750. // Create the handles for the sockets.
  751. //
  752. Status = ObCreateHandle(Process->HandleTable,
  753. Sockets[0],
  754. HandleFlags,
  755. &(Parameters->Socket1));
  756. if (!KSUCCESS(Status)) {
  757. goto CreateSocketPairEnd;
  758. }
  759. Status = ObCreateHandle(Process->HandleTable,
  760. Sockets[1],
  761. HandleFlags,
  762. &(Parameters->Socket2));
  763. if (!KSUCCESS(Status)) {
  764. //
  765. // Destory the first handle manually.
  766. //
  767. ObDestroyHandle(Process->HandleTable, Parameters->Socket1);
  768. Parameters->Socket1 = INVALID_HANDLE;
  769. goto CreateSocketPairEnd;
  770. }
  771. Status = STATUS_SUCCESS;
  772. CreateSocketPairEnd:
  773. if (!KSUCCESS(Status)) {
  774. ASSERT((Parameters->Socket1 == INVALID_HANDLE) &&
  775. (Parameters->Socket2 == INVALID_HANDLE));
  776. if (Sockets[0] != NULL) {
  777. IoClose(Sockets[0]);
  778. Sockets[0] = NULL;
  779. }
  780. if (Sockets[1] != NULL) {
  781. IoClose(Sockets[1]);
  782. Sockets[1] = NULL;
  783. }
  784. }
  785. Parameters->Status = Status;
  786. return;
  787. }
  788. VOID
  789. IoSysSocketCreate (
  790. ULONG SystemCallNumber,
  791. PVOID SystemCallParameter,
  792. PTRAP_FRAME TrapFrame,
  793. PULONG ResultSize
  794. )
  795. /*++
  796. Routine Description:
  797. This routine handles the system call that creates a new socket.
  798. Arguments:
  799. SystemCallNumber - Supplies the system call number that was requested.
  800. SystemCallParameter - Supplies a pointer to the parameters supplied with
  801. the system call. This structure will be a stack-local copy of the
  802. actual parameters passed from user-mode.
  803. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  804. from user mode to kernel mode.
  805. ResultSize - Supplies a pointer where the system call routine returns the
  806. size of the parameter structure to be copied back to user mode. The
  807. value returned here must be no larger than the original parameter
  808. structure size. The default is the original size of the parameters.
  809. Return Value:
  810. None.
  811. --*/
  812. {
  813. ULONG HandleFlags;
  814. PIO_HANDLE IoHandle;
  815. ULONG OpenFlags;
  816. PSYSTEM_CALL_SOCKET_CREATE Parameters;
  817. PKPROCESS Process;
  818. KSTATUS Status;
  819. ASSERT(SystemCallNumber == SystemCallSocketCreate);
  820. Parameters = (PSYSTEM_CALL_SOCKET_CREATE)SystemCallParameter;
  821. Parameters->Socket = INVALID_HANDLE;
  822. Process = PsGetCurrentProcess();
  823. ASSERT(Process != PsGetKernelProcess());
  824. HandleFlags = 0;
  825. if ((Parameters->OpenFlags & SYS_OPEN_FLAG_CLOSE_ON_EXECUTE) != 0) {
  826. HandleFlags |= FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
  827. }
  828. OpenFlags = Parameters->OpenFlags & SYS_OPEN_FLAG_NON_BLOCKING;
  829. IoHandle = NULL;
  830. Status = IoSocketCreate(Parameters->Domain,
  831. Parameters->Type,
  832. Parameters->Protocol,
  833. OpenFlags,
  834. &IoHandle);
  835. if (!KSUCCESS(Status)) {
  836. goto CreateSocketEnd;
  837. }
  838. //
  839. // Create a handle table entry for this socket.
  840. //
  841. Status = ObCreateHandle(Process->HandleTable,
  842. IoHandle,
  843. HandleFlags,
  844. &(Parameters->Socket));
  845. if (!KSUCCESS(Status)) {
  846. goto CreateSocketEnd;
  847. }
  848. CreateSocketEnd:
  849. if (!KSUCCESS(Status)) {
  850. if (IoHandle != NULL) {
  851. IoIoHandleReleaseReference(IoHandle);
  852. }
  853. Parameters->Socket = INVALID_HANDLE;
  854. }
  855. Parameters->Status = Status;
  856. return;
  857. }
  858. VOID
  859. IoSysSocketBind (
  860. ULONG SystemCallNumber,
  861. PVOID SystemCallParameter,
  862. PTRAP_FRAME TrapFrame,
  863. PULONG ResultSize
  864. )
  865. /*++
  866. Routine Description:
  867. This routine attempts to bind a socket to a local address.
  868. Arguments:
  869. SystemCallNumber - Supplies the system call number that was requested.
  870. SystemCallParameter - Supplies a pointer to the parameters supplied with
  871. the system call. This structure will be a stack-local copy of the
  872. actual parameters passed from user-mode.
  873. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  874. from user mode to kernel mode.
  875. ResultSize - Supplies a pointer where the system call routine returns the
  876. size of the parameter structure to be copied back to user mode. The
  877. value returned here must be no larger than the original parameter
  878. structure size. The default is the original size of the parameters.
  879. Return Value:
  880. None.
  881. --*/
  882. {
  883. PIO_HANDLE IoHandle;
  884. PSYSTEM_CALL_SOCKET_BIND Parameters;
  885. PKPROCESS Process;
  886. KSTATUS Status;
  887. ASSERT(SystemCallNumber == SystemCallSocketBind);
  888. Parameters = (PSYSTEM_CALL_SOCKET_BIND)SystemCallParameter;
  889. Process = PsGetCurrentProcess();
  890. //
  891. // Get the I/O handle.
  892. //
  893. IoHandle = ObGetHandleValue(Process->HandleTable, Parameters->Socket, NULL);
  894. if (IoHandle == NULL) {
  895. Status = STATUS_INVALID_HANDLE;
  896. goto SysSocketBindEnd;
  897. }
  898. Status = IoSocketBindToAddress(FALSE,
  899. IoHandle,
  900. NULL,
  901. &(Parameters->Address),
  902. Parameters->Path,
  903. Parameters->PathSize);
  904. if (!KSUCCESS(Status)) {
  905. goto SysSocketBindEnd;
  906. }
  907. SysSocketBindEnd:
  908. //
  909. // Release the reference that was added when the handle was looked up.
  910. //
  911. if (IoHandle != NULL) {
  912. IoIoHandleReleaseReference(IoHandle);
  913. }
  914. Parameters->Status = Status;
  915. return;
  916. }
  917. VOID
  918. IoSysSocketListen (
  919. ULONG SystemCallNumber,
  920. PVOID SystemCallParameter,
  921. PTRAP_FRAME TrapFrame,
  922. PULONG ResultSize
  923. )
  924. /*++
  925. Routine Description:
  926. This routine handles the system call that makes a socket listen and become
  927. eligible to accept new incoming connections.
  928. Arguments:
  929. SystemCallNumber - Supplies the system call number that was requested.
  930. SystemCallParameter - Supplies a pointer to the parameters supplied with
  931. the system call. This structure will be a stack-local copy of the
  932. actual parameters passed from user-mode.
  933. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  934. from user mode to kernel mode.
  935. ResultSize - Supplies a pointer where the system call routine returns the
  936. size of the parameter structure to be copied back to user mode. The
  937. value returned here must be no larger than the original parameter
  938. structure size. The default is the original size of the parameters.
  939. Return Value:
  940. None.
  941. --*/
  942. {
  943. PIO_HANDLE IoHandle;
  944. PSYSTEM_CALL_SOCKET_LISTEN Parameters;
  945. PKPROCESS Process;
  946. KSTATUS Status;
  947. ASSERT(SystemCallNumber == SystemCallSocketListen);
  948. Parameters = (PSYSTEM_CALL_SOCKET_LISTEN)SystemCallParameter;
  949. Process = PsGetCurrentProcess();
  950. IoHandle = ObGetHandleValue(Process->HandleTable, Parameters->Socket, NULL);
  951. if (IoHandle == NULL) {
  952. Status = STATUS_INVALID_HANDLE;
  953. goto SysSocketListenEnd;
  954. }
  955. Status = IoSocketListen(IoHandle, Parameters->BacklogCount);
  956. if (!KSUCCESS(Status)) {
  957. goto SysSocketListenEnd;
  958. }
  959. SysSocketListenEnd:
  960. //
  961. // Release the reference that was added when the handle was looked up.
  962. //
  963. if (IoHandle != NULL) {
  964. IoIoHandleReleaseReference(IoHandle);
  965. }
  966. Parameters->Status = Status;
  967. return;
  968. }
  969. VOID
  970. IoSysSocketAccept (
  971. ULONG SystemCallNumber,
  972. PVOID SystemCallParameter,
  973. PTRAP_FRAME TrapFrame,
  974. PULONG ResultSize
  975. )
  976. /*++
  977. Routine Description:
  978. This routine handles the system call that accepts a new incoming
  979. connection on a socket and spins it off into another socket.
  980. Arguments:
  981. SystemCallNumber - Supplies the system call number that was requested.
  982. SystemCallParameter - Supplies a pointer to the parameters supplied with
  983. the system call. This structure will be a stack-local copy of the
  984. actual parameters passed from user-mode.
  985. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  986. from user mode to kernel mode.
  987. ResultSize - Supplies a pointer where the system call routine returns the
  988. size of the parameter structure to be copied back to user mode. The
  989. value returned here must be no larger than the original parameter
  990. structure size. The default is the original size of the parameters.
  991. Return Value:
  992. None.
  993. --*/
  994. {
  995. UINTN CopySize;
  996. ULONG HandleFlags;
  997. PIO_HANDLE IoHandle;
  998. PIO_HANDLE NewHandle;
  999. PSYSTEM_CALL_SOCKET_ACCEPT Parameters;
  1000. PKPROCESS Process;
  1001. PSTR RemotePath;
  1002. UINTN RemotePathSize;
  1003. KSTATUS Status;
  1004. ASSERT(SystemCallNumber == SystemCallSocketAccept);
  1005. NewHandle = NULL;
  1006. Parameters = (PSYSTEM_CALL_SOCKET_ACCEPT)SystemCallParameter;
  1007. Parameters->NewSocket = INVALID_HANDLE;
  1008. Process = PsGetCurrentProcess();
  1009. IoHandle = ObGetHandleValue(Process->HandleTable, Parameters->Socket, NULL);
  1010. if (IoHandle == NULL) {
  1011. Status = STATUS_INVALID_HANDLE;
  1012. goto SysSocketAcceptEnd;
  1013. }
  1014. //
  1015. // Run the actual accept function, which will pop out a new socket that is
  1016. // unconnected to an I/O handle.
  1017. //
  1018. RemotePath = NULL;
  1019. RemotePathSize = 0;
  1020. Status = IoSocketAccept(IoHandle,
  1021. &NewHandle,
  1022. &(Parameters->Address),
  1023. &RemotePath,
  1024. &RemotePathSize);
  1025. if (!KSUCCESS(Status)) {
  1026. goto SysSocketAcceptEnd;
  1027. }
  1028. if ((Parameters->OpenFlags & SYS_OPEN_FLAG_NON_BLOCKING) != 0) {
  1029. NewHandle->OpenFlags |= OPEN_FLAG_NON_BLOCKING;
  1030. }
  1031. HandleFlags = 0;
  1032. if ((Parameters->OpenFlags & SYS_OPEN_FLAG_CLOSE_ON_EXECUTE) != 0) {
  1033. HandleFlags |= FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
  1034. }
  1035. //
  1036. // Finally, create a user mode handle for this socket.
  1037. //
  1038. Status = ObCreateHandle(Process->HandleTable,
  1039. NewHandle,
  1040. HandleFlags,
  1041. &(Parameters->NewSocket));
  1042. if (!KSUCCESS(Status)) {
  1043. goto SysSocketAcceptEnd;
  1044. }
  1045. //
  1046. // Copy the remote path over.
  1047. //
  1048. if (RemotePath != NULL) {
  1049. CopySize = RemotePathSize;
  1050. if (CopySize > Parameters->RemotePathSize) {
  1051. CopySize = Parameters->RemotePathSize;
  1052. }
  1053. if (CopySize != 0) {
  1054. Status = MmCopyToUserMode(Parameters->RemotePath,
  1055. RemotePath,
  1056. CopySize);
  1057. }
  1058. Parameters->RemotePathSize = RemotePathSize;
  1059. if (!KSUCCESS(Status)) {
  1060. goto SysSocketAcceptEnd;
  1061. }
  1062. }
  1063. SysSocketAcceptEnd:
  1064. if (!KSUCCESS(Status)) {
  1065. if (NewHandle != NULL) {
  1066. IoIoHandleReleaseReference(NewHandle);
  1067. }
  1068. }
  1069. //
  1070. // Release the reference that was added when the handle was looked up.
  1071. //
  1072. if (IoHandle != NULL) {
  1073. IoIoHandleReleaseReference(IoHandle);
  1074. }
  1075. Parameters->Status = Status;
  1076. return;
  1077. }
  1078. VOID
  1079. IoSysSocketConnect (
  1080. ULONG SystemCallNumber,
  1081. PVOID SystemCallParameter,
  1082. PTRAP_FRAME TrapFrame,
  1083. PULONG ResultSize
  1084. )
  1085. /*++
  1086. Routine Description:
  1087. This routine handles the system call that reaches and and attempts to
  1088. connect with another socket.
  1089. Arguments:
  1090. SystemCallNumber - Supplies the system call number that was requested.
  1091. SystemCallParameter - Supplies a pointer to the parameters supplied with
  1092. the system call. This structure will be a stack-local copy of the
  1093. actual parameters passed from user-mode.
  1094. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  1095. from user mode to kernel mode.
  1096. ResultSize - Supplies a pointer where the system call routine returns the
  1097. size of the parameter structure to be copied back to user mode. The
  1098. value returned here must be no larger than the original parameter
  1099. structure size. The default is the original size of the parameters.
  1100. Return Value:
  1101. None.
  1102. --*/
  1103. {
  1104. PIO_HANDLE IoHandle;
  1105. PSYSTEM_CALL_SOCKET_CONNECT Parameters;
  1106. PSTR PathCopy;
  1107. PKPROCESS Process;
  1108. KSTATUS Status;
  1109. ASSERT(SystemCallNumber == SystemCallSocketConnect);
  1110. Parameters = (PSYSTEM_CALL_SOCKET_CONNECT)SystemCallParameter;
  1111. PathCopy = NULL;
  1112. Process = PsGetCurrentProcess();
  1113. IoHandle = ObGetHandleValue(Process->HandleTable, Parameters->Socket, NULL);
  1114. if (IoHandle == NULL) {
  1115. Status = STATUS_INVALID_HANDLE;
  1116. goto SysSocketConnectEnd;
  1117. }
  1118. if (Parameters->RemotePathSize != 0) {
  1119. Status = MmCreateCopyOfUserModeString(Parameters->RemotePath,
  1120. Parameters->RemotePathSize,
  1121. UNIX_SOCKET_ALLOCATION_TAG,
  1122. &PathCopy);
  1123. if (!KSUCCESS(Status)) {
  1124. goto SysSocketConnectEnd;
  1125. }
  1126. }
  1127. Status = IoSocketConnect(FALSE,
  1128. IoHandle,
  1129. &(Parameters->Address),
  1130. PathCopy,
  1131. Parameters->RemotePathSize);
  1132. if (!KSUCCESS(Status)) {
  1133. goto SysSocketConnectEnd;
  1134. }
  1135. SysSocketConnectEnd:
  1136. if (PathCopy != NULL) {
  1137. MmFreePagedPool(PathCopy);
  1138. }
  1139. //
  1140. // Release the reference that was added when the handle was looked up.
  1141. //
  1142. if (IoHandle != NULL) {
  1143. IoIoHandleReleaseReference(IoHandle);
  1144. }
  1145. Parameters->Status = Status;
  1146. return;
  1147. }
  1148. VOID
  1149. IoSysSocketPerformIo (
  1150. ULONG SystemCallNumber,
  1151. PVOID SystemCallParameter,
  1152. PTRAP_FRAME TrapFrame,
  1153. PULONG ResultSize
  1154. )
  1155. /*++
  1156. Routine Description:
  1157. This routine handles the system call that sends a packet to a specific
  1158. destination or receives data from a destination. Sockets may also use the
  1159. generic perform I/O operations if the identity of the remote address is
  1160. either already known or not needed.
  1161. Arguments:
  1162. SystemCallNumber - Supplies the system call number that was requested.
  1163. SystemCallParameter - Supplies a pointer to the parameters supplied with
  1164. the system call. This structure will be a stack-local copy of the
  1165. actual parameters passed from user-mode.
  1166. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  1167. from user mode to kernel mode.
  1168. ResultSize - Supplies a pointer where the system call routine returns the
  1169. size of the parameter structure to be copied back to user mode. The
  1170. value returned here must be no larger than the original parameter
  1171. structure size. The default is the original size of the parameters.
  1172. Return Value:
  1173. None.
  1174. --*/
  1175. {
  1176. IO_BUFFER IoBuffer;
  1177. PIO_HANDLE IoHandle;
  1178. SOCKET_IO_PARAMETERS IoParameters;
  1179. PSYSTEM_CALL_SOCKET_PERFORM_IO Parameters;
  1180. PKPROCESS Process;
  1181. KSTATUS Status;
  1182. ASSERT(SystemCallNumber == SystemCallSocketPerformIo);
  1183. Parameters = (PSYSTEM_CALL_SOCKET_PERFORM_IO)SystemCallParameter;
  1184. Process = PsGetCurrentProcess();
  1185. ASSERT(SYS_WAIT_TIME_INDEFINITE == WAIT_TIME_INDEFINITE);
  1186. IoHandle = ObGetHandleValue(Process->HandleTable, Parameters->Socket, NULL);
  1187. if (IoHandle == NULL) {
  1188. Status = STATUS_INVALID_HANDLE;
  1189. goto SysSocketPerformIoEnd;
  1190. }
  1191. Status = MmCopyFromUserMode(&IoParameters,
  1192. Parameters->Parameters,
  1193. sizeof(SOCKET_IO_PARAMETERS));
  1194. if (!KSUCCESS(Status)) {
  1195. goto SysSocketPerformIoEnd;
  1196. }
  1197. IoParameters.IoFlags &= SYS_IO_FLAG_MASK;
  1198. Status = MmInitializeIoBuffer(&IoBuffer,
  1199. Parameters->Buffer,
  1200. INVALID_PHYSICAL_ADDRESS,
  1201. IoParameters.Size,
  1202. 0);
  1203. if (!KSUCCESS(Status)) {
  1204. goto SysSocketPerformIoEnd;
  1205. }
  1206. //
  1207. // Non-blocking handles always have a timeout of zero.
  1208. //
  1209. if ((IoHandle->OpenFlags & OPEN_FLAG_NON_BLOCKING) != 0) {
  1210. IoParameters.TimeoutInMilliseconds = 0;
  1211. }
  1212. if ((IoParameters.IoFlags & SYS_IO_FLAG_WRITE) != 0) {
  1213. Status = IoSocketSendData(FALSE, IoHandle, &IoParameters, &IoBuffer);
  1214. //
  1215. // Send a pipe signal if the returning status was "broken pipe".
  1216. //
  1217. if (Status == STATUS_BROKEN_PIPE) {
  1218. ASSERT(Process != PsGetKernelProcess());
  1219. PsSignalProcess(Process, SIGNAL_BROKEN_PIPE, NULL);
  1220. }
  1221. } else {
  1222. Status = IoSocketReceiveData(FALSE, IoHandle, &IoParameters, &IoBuffer);
  1223. }
  1224. if (!KSUCCESS(Status)) {
  1225. goto SysSocketPerformIoEnd;
  1226. }
  1227. SysSocketPerformIoEnd:
  1228. MmCopyToUserMode(Parameters->Parameters,
  1229. &IoParameters,
  1230. sizeof(SOCKET_IO_PARAMETERS));
  1231. //
  1232. // Release the reference that was added when the handle was looked up.
  1233. //
  1234. if (IoHandle != NULL) {
  1235. IoIoHandleReleaseReference(IoHandle);
  1236. }
  1237. Parameters->Status = Status;
  1238. return;
  1239. }
  1240. VOID
  1241. IoSysSocketPerformVectoredIo (
  1242. ULONG SystemCallNumber,
  1243. PVOID SystemCallParameter,
  1244. PTRAP_FRAME TrapFrame,
  1245. PULONG ResultSize
  1246. )
  1247. /*++
  1248. Routine Description:
  1249. This routine handles the system call that performs socket I/O using I/O
  1250. vectors.
  1251. Arguments:
  1252. SystemCallNumber - Supplies the system call number that was requested.
  1253. SystemCallParameter - Supplies a pointer to the parameters supplied with
  1254. the system call. This structure will be a stack-local copy of the
  1255. actual parameters passed from user-mode.
  1256. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  1257. from user mode to kernel mode.
  1258. ResultSize - Supplies a pointer where the system call routine returns the
  1259. size of the parameter structure to be copied back to user mode. The
  1260. value returned here must be no larger than the original parameter
  1261. structure size. The default is the original size of the parameters.
  1262. Return Value:
  1263. None.
  1264. --*/
  1265. {
  1266. PIO_BUFFER IoBuffer;
  1267. PIO_HANDLE IoHandle;
  1268. SOCKET_IO_PARAMETERS IoParameters;
  1269. PSYSTEM_CALL_SOCKET_PERFORM_VECTORED_IO Parameters;
  1270. PKPROCESS Process;
  1271. KSTATUS Status;
  1272. ASSERT(SystemCallNumber == SystemCallSocketPerformVectoredIo);
  1273. IoBuffer = NULL;
  1274. Parameters = (PSYSTEM_CALL_SOCKET_PERFORM_VECTORED_IO)SystemCallParameter;
  1275. Process = PsGetCurrentProcess();
  1276. ASSERT(SYS_WAIT_TIME_INDEFINITE == WAIT_TIME_INDEFINITE);
  1277. IoHandle = ObGetHandleValue(Process->HandleTable, Parameters->Socket, NULL);
  1278. if (IoHandle == NULL) {
  1279. Status = STATUS_INVALID_HANDLE;
  1280. goto SysSocketPerformVectoredIoEnd;
  1281. }
  1282. Status = MmCopyFromUserMode(&IoParameters,
  1283. Parameters->Parameters,
  1284. sizeof(SOCKET_IO_PARAMETERS));
  1285. if (!KSUCCESS(Status)) {
  1286. goto SysSocketPerformVectoredIoEnd;
  1287. }
  1288. IoParameters.IoFlags &= SYS_IO_FLAG_MASK;
  1289. Status = MmCreateIoBufferFromVector(Parameters->VectorArray,
  1290. FALSE,
  1291. Parameters->VectorCount,
  1292. &IoBuffer);
  1293. if (!KSUCCESS(Status)) {
  1294. goto SysSocketPerformVectoredIoEnd;
  1295. }
  1296. //
  1297. // Non-blocking handles always have a timeout of zero.
  1298. //
  1299. if ((IoHandle->OpenFlags & OPEN_FLAG_NON_BLOCKING) != 0) {
  1300. IoParameters.TimeoutInMilliseconds = 0;
  1301. }
  1302. if ((IoParameters.IoFlags & SYS_IO_FLAG_WRITE) != 0) {
  1303. Status = IoSocketSendData(FALSE, IoHandle, &IoParameters, IoBuffer);
  1304. //
  1305. // Send a pipe signal if the returning status was "broken pipe".
  1306. //
  1307. if (Status == STATUS_BROKEN_PIPE) {
  1308. ASSERT(Process != PsGetKernelProcess());
  1309. PsSignalProcess(Process, SIGNAL_BROKEN_PIPE, NULL);
  1310. }
  1311. } else {
  1312. Status = IoSocketReceiveData(FALSE, IoHandle, &IoParameters, IoBuffer);
  1313. }
  1314. if (!KSUCCESS(Status)) {
  1315. goto SysSocketPerformVectoredIoEnd;
  1316. }
  1317. SysSocketPerformVectoredIoEnd:
  1318. if (IoBuffer != NULL) {
  1319. MmFreeIoBuffer(IoBuffer);
  1320. }
  1321. MmCopyToUserMode(Parameters->Parameters,
  1322. &IoParameters,
  1323. sizeof(SOCKET_IO_PARAMETERS));
  1324. //
  1325. // Release the reference that was added when the handle was looked up.
  1326. //
  1327. if (IoHandle != NULL) {
  1328. IoIoHandleReleaseReference(IoHandle);
  1329. }
  1330. Parameters->Status = Status;
  1331. return;
  1332. }
  1333. VOID
  1334. IoSysSocketGetSetInformation (
  1335. ULONG SystemCallNumber,
  1336. PVOID SystemCallParameter,
  1337. PTRAP_FRAME TrapFrame,
  1338. PULONG ResultSize
  1339. )
  1340. /*++
  1341. Routine Description:
  1342. This routine implements the system call for getting or setting socket
  1343. information.
  1344. Arguments:
  1345. SystemCallNumber - Supplies the system call number that was requested.
  1346. SystemCallParameter - Supplies a pointer to the parameters supplied with
  1347. the system call. This structure will be a stack-local copy of the
  1348. actual parameters passed from user-mode.
  1349. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  1350. from user mode to kernel mode.
  1351. ResultSize - Supplies a pointer where the system call routine returns the
  1352. size of the parameter structure to be copied back to user mode. The
  1353. value returned here must be no larger than the original parameter
  1354. structure size. The default is the original size of the parameters.
  1355. Return Value:
  1356. None.
  1357. --*/
  1358. {
  1359. PVOID Buffer;
  1360. UINTN CopySize;
  1361. KSTATUS CopyStatus;
  1362. PIO_HANDLE IoHandle;
  1363. PSYSTEM_CALL_SOCKET_GET_SET_INFORMATION Parameters;
  1364. PKPROCESS Process;
  1365. KSTATUS Status;
  1366. ASSERT(SystemCallNumber == SystemCallSocketGetSetInformation);
  1367. Buffer = NULL;
  1368. Parameters = (PSYSTEM_CALL_SOCKET_GET_SET_INFORMATION)SystemCallParameter;
  1369. Process = PsGetCurrentProcess();
  1370. IoHandle = ObGetHandleValue(Process->HandleTable, Parameters->Socket, NULL);
  1371. if (IoHandle == NULL) {
  1372. Status = STATUS_INVALID_HANDLE;
  1373. goto SysSocketGetSetInformationEnd;
  1374. }
  1375. //
  1376. // Create a paged pool buffer to hold the data.
  1377. //
  1378. CopySize = 0;
  1379. if (Parameters->DataSize != 0) {
  1380. Buffer = MmAllocatePagedPool(Parameters->DataSize,
  1381. SOCKET_INFORMATION_ALLOCATION_TAG);
  1382. if (Buffer == NULL) {
  1383. Status = STATUS_INSUFFICIENT_RESOURCES;
  1384. goto SysSocketGetSetInformationEnd;
  1385. }
  1386. CopySize = Parameters->DataSize;
  1387. //
  1388. // Copy the data into the kernel mode buffer.
  1389. //
  1390. Status = MmCopyFromUserMode(Buffer,
  1391. Parameters->Data,
  1392. Parameters->DataSize);
  1393. if (!KSUCCESS(Status)) {
  1394. goto SysSocketGetSetInformationEnd;
  1395. }
  1396. }
  1397. Status = IoSocketGetSetInformation(IoHandle,
  1398. Parameters->InformationType,
  1399. Parameters->Option,
  1400. Buffer,
  1401. &(Parameters->DataSize),
  1402. Parameters->Set);
  1403. //
  1404. // Copy the data back into user mode, even on set operations.
  1405. //
  1406. if (CopySize > Parameters->DataSize) {
  1407. CopySize = Parameters->DataSize;
  1408. }
  1409. if (CopySize != 0) {
  1410. CopyStatus = MmCopyToUserMode(Parameters->Data, Buffer, CopySize);
  1411. if ((KSUCCESS(Status)) && (!KSUCCESS(CopyStatus))) {
  1412. Status = CopyStatus;
  1413. }
  1414. }
  1415. SysSocketGetSetInformationEnd:
  1416. if (Buffer != NULL) {
  1417. MmFreePagedPool(Buffer);
  1418. }
  1419. if (IoHandle != NULL) {
  1420. IoIoHandleReleaseReference(IoHandle);
  1421. }
  1422. Parameters->Status = Status;
  1423. return;
  1424. }
  1425. VOID
  1426. IoSysSocketShutdown (
  1427. ULONG SystemCallNumber,
  1428. PVOID SystemCallParameter,
  1429. PTRAP_FRAME TrapFrame,
  1430. PULONG ResultSize
  1431. )
  1432. /*++
  1433. Routine Description:
  1434. This routine implements the system call for shutting down communication to
  1435. a socket.
  1436. Arguments:
  1437. SystemCallNumber - Supplies the system call number that was requested.
  1438. SystemCallParameter - Supplies a pointer to the parameters supplied with
  1439. the system call. This structure will be a stack-local copy of the
  1440. actual parameters passed from user-mode.
  1441. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  1442. from user mode to kernel mode.
  1443. ResultSize - Supplies a pointer where the system call routine returns the
  1444. size of the parameter structure to be copied back to user mode. The
  1445. value returned here must be no larger than the original parameter
  1446. structure size. The default is the original size of the parameters.
  1447. Return Value:
  1448. None.
  1449. --*/
  1450. {
  1451. PIO_HANDLE IoHandle;
  1452. PSYSTEM_CALL_SOCKET_SHUTDOWN Parameters;
  1453. PKPROCESS Process;
  1454. KSTATUS Status;
  1455. ASSERT(SystemCallNumber == SystemCallSocketShutdown);
  1456. Parameters = (PSYSTEM_CALL_SOCKET_SHUTDOWN)SystemCallParameter;
  1457. Process = PsGetCurrentProcess();
  1458. IoHandle = ObGetHandleValue(Process->HandleTable, Parameters->Socket, NULL);
  1459. if (IoHandle == NULL) {
  1460. Status = STATUS_INVALID_HANDLE;
  1461. goto SysSocketShutdownEnd;
  1462. }
  1463. Status = IoSocketShutdown(IoHandle, Parameters->ShutdownType);
  1464. SysSocketShutdownEnd:
  1465. //
  1466. // Release the reference that was added when the handle was looked up.
  1467. //
  1468. if (IoHandle != NULL) {
  1469. IoIoHandleReleaseReference(IoHandle);
  1470. }
  1471. Parameters->Status = Status;
  1472. return;
  1473. }
  1474. KSTATUS
  1475. IopCreateSocket (
  1476. PVOID Parameter,
  1477. FILE_PERMISSIONS CreatePermissions,
  1478. PFILE_OBJECT *FileObject
  1479. )
  1480. /*++
  1481. Routine Description:
  1482. This routine allocates resources associated with a new socket.
  1483. Arguments:
  1484. Parameter - Supplies the parameters the socket was created with.
  1485. CreatePermissions - Supplies the permissions to create the file with.
  1486. FileObject - Supplies a pointer where the new file object representing the
  1487. socket will be returned on success.
  1488. Return Value:
  1489. Status code.
  1490. --*/
  1491. {
  1492. BOOL Created;
  1493. NETWORK_ADDRESS LocalAddress;
  1494. PFILE_OBJECT NewFileObject;
  1495. PSOCKET_CREATION_PARAMETERS Parameters;
  1496. FILE_PROPERTIES Properties;
  1497. PVOID RootObject;
  1498. PSOCKET Socket;
  1499. KSTATUS Status;
  1500. PKTHREAD Thread;
  1501. Created = FALSE;
  1502. NewFileObject = NULL;
  1503. Parameters = (PSOCKET_CREATION_PARAMETERS)Parameter;
  1504. //
  1505. // If there are no parameters, then this file object is being created from
  1506. // a leftover file system entry. Just succeed, but it will never be able to
  1507. // be opened. The common case for this is a request for the file properties.
  1508. //
  1509. if (Parameters == NULL) {
  1510. ASSERT(*FileObject != NULL);
  1511. Status = STATUS_SUCCESS;
  1512. goto CreateSocketEnd;
  1513. }
  1514. Socket = NULL;
  1515. //
  1516. // In cases where a Unix socket is trying to bind to a new path entry,
  1517. // there's already a socket that's been created. Use that one.
  1518. //
  1519. if (Parameters->ExistingSocket != NULL) {
  1520. Socket = Parameters->ExistingSocket;
  1521. ASSERT(Socket->IoState != NULL);
  1522. IoSocketAddReference(Socket);
  1523. //
  1524. // Most of the time, a socket needs to be created.
  1525. //
  1526. } else {
  1527. if (Parameters->Domain == NetDomainLocal) {
  1528. Status = IopCreateUnixSocket(Parameters->Domain,
  1529. Parameters->Type,
  1530. Parameters->Protocol,
  1531. &Socket);
  1532. } else {
  1533. if (IoNetInterfaceInitialized == FALSE) {
  1534. Status = STATUS_NOT_IMPLEMENTED;
  1535. goto CreateSocketEnd;
  1536. }
  1537. Status = IoNetInterface.CreateSocket(Parameters->Domain,
  1538. Parameters->Type,
  1539. Parameters->Protocol,
  1540. &Socket);
  1541. }
  1542. if (!KSUCCESS(Status)) {
  1543. goto CreateSocketEnd;
  1544. }
  1545. IoSocketAddReference(Socket);
  1546. //
  1547. // Fill in the standard parts of the socket structure.
  1548. //
  1549. Socket->Domain = Parameters->Domain;
  1550. Socket->Type = Parameters->Type;
  1551. if (Socket->IoState == NULL) {
  1552. Socket->IoState = IoCreateIoObjectState(FALSE);
  1553. if (Socket->IoState == NULL) {
  1554. Status = STATUS_INSUFFICIENT_RESOURCES;
  1555. goto CreateSocketEnd;
  1556. }
  1557. }
  1558. }
  1559. //
  1560. // Create or look up a file object for the socket if needed.
  1561. //
  1562. if (*FileObject == NULL) {
  1563. Thread = KeGetCurrentThread();
  1564. RtlZeroMemory(&Properties, sizeof(FILE_PROPERTIES));
  1565. RootObject = ObGetRootObject();
  1566. Properties.DeviceId = OBJECT_MANAGER_DEVICE_ID;
  1567. Properties.FileId = (UINTN)Socket;
  1568. Properties.Type = IoObjectSocket;
  1569. Properties.UserId = Thread->Identity.EffectiveUserId;
  1570. Properties.GroupId = Thread->Identity.EffectiveGroupId;
  1571. Properties.HardLinkCount = 1;
  1572. Properties.Permissions = CreatePermissions;
  1573. KeGetSystemTime(&(Properties.StatusChangeTime));
  1574. RtlCopyMemory(&(Properties.ModifiedTime),
  1575. &(Properties.StatusChangeTime),
  1576. sizeof(SYSTEM_TIME));
  1577. RtlCopyMemory(&(Properties.AccessTime),
  1578. &(Properties.StatusChangeTime),
  1579. sizeof(SYSTEM_TIME));
  1580. Status = IopCreateOrLookupFileObject(&Properties,
  1581. RootObject,
  1582. FILE_OBJECT_FLAG_EXTERNAL_IO_STATE,
  1583. &NewFileObject,
  1584. &Created);
  1585. if (!KSUCCESS(Status)) {
  1586. goto CreateSocketEnd;
  1587. }
  1588. ASSERT((Created != FALSE) || (Socket == Parameters->ExistingSocket));
  1589. *FileObject = NewFileObject;
  1590. }
  1591. ASSERT(((*FileObject)->IoState == NULL) &&
  1592. (((*FileObject)->Flags & FILE_OBJECT_FLAG_EXTERNAL_IO_STATE) != 0));
  1593. (*FileObject)->IoState = Socket->IoState;
  1594. (*FileObject)->SpecialIo = Socket;
  1595. //
  1596. // The socket is finally ready to go. If it is a raw socket it needs to get
  1597. // bound to the any address.
  1598. //
  1599. if ((Socket->Type == NetSocketRaw) &&
  1600. (Socket->Domain != NetDomainLocal)) {
  1601. ASSERT(Parameters->ExistingSocket == NULL);
  1602. RtlZeroMemory(&LocalAddress, sizeof(NETWORK_ADDRESS));
  1603. LocalAddress.Domain = Socket->Domain;
  1604. Status = IoNetInterface.BindToAddress(Socket, NULL, &LocalAddress);
  1605. if (!KSUCCESS(Status)) {
  1606. goto CreateSocketEnd;
  1607. }
  1608. }
  1609. Status = STATUS_SUCCESS;
  1610. CreateSocketEnd:
  1611. //
  1612. // On both success and failure, the file object's ready event needs to be
  1613. // signaled. Other threads may be waiting on the event.
  1614. //
  1615. if (*FileObject != NULL) {
  1616. ASSERT((KeGetEventState((*FileObject)->ReadyEvent) == NotSignaled) ||
  1617. (KeGetEventState((*FileObject)->ReadyEvent) ==
  1618. NotSignaledWithWaiters));
  1619. KeSignalEvent((*FileObject)->ReadyEvent, SignalOptionSignalAll);
  1620. }
  1621. if (!KSUCCESS(Status)) {
  1622. if ((Socket != NULL) && ((*FileObject)->SpecialIo != Socket)) {
  1623. IoSocketReleaseReference(Socket);
  1624. }
  1625. if (NewFileObject != NULL) {
  1626. IopFileObjectReleaseReference(NewFileObject);
  1627. *FileObject = NULL;
  1628. }
  1629. }
  1630. return Status;
  1631. }
  1632. KSTATUS
  1633. IopPerformSocketIoOperation (
  1634. PIO_HANDLE Handle,
  1635. PIO_CONTEXT IoContext
  1636. )
  1637. /*++
  1638. Routine Description:
  1639. This routine reads from or writes to a socket.
  1640. Arguments:
  1641. Handle - Supplies a pointer to the socket I/O handle.
  1642. IoContext - Supplies a pointer to the I/O context.
  1643. Return Value:
  1644. Status code. A failing status code does not necessarily mean no I/O made it
  1645. in or out. Check the bytes completed value in the I/O context to find out
  1646. how much occurred.
  1647. --*/
  1648. {
  1649. SOCKET_IO_PARAMETERS IoParameters;
  1650. KSTATUS Status;
  1651. ASSERT(IoContext->IoBuffer != NULL);
  1652. RtlZeroMemory(&IoParameters, sizeof(SOCKET_IO_PARAMETERS));
  1653. IoParameters.Size = IoContext->SizeInBytes;
  1654. IoParameters.TimeoutInMilliseconds = IoContext->TimeoutInMilliseconds;
  1655. if (IoContext->Write != FALSE) {
  1656. Status = IoSocketSendData(FALSE,
  1657. Handle,
  1658. &IoParameters,
  1659. IoContext->IoBuffer);
  1660. } else {
  1661. Status = IoSocketReceiveData(FALSE,
  1662. Handle,
  1663. &IoParameters,
  1664. IoContext->IoBuffer);
  1665. }
  1666. IoContext->BytesCompleted = IoParameters.Size;
  1667. return Status;
  1668. }
  1669. KSTATUS
  1670. IopOpenSocket (
  1671. PIO_HANDLE IoHandle
  1672. )
  1673. /*++
  1674. Routine Description:
  1675. This routine opens a socket connection.
  1676. Arguments:
  1677. IoHandle - Supplies a pointer to the I/O handle for the socket being opened.
  1678. Return Value:
  1679. Status code.
  1680. --*/
  1681. {
  1682. PFILE_OBJECT FileObject;
  1683. PSOCKET Socket;
  1684. FileObject = IoHandle->FileObject;
  1685. ASSERT(FileObject->Properties.Type == IoObjectSocket);
  1686. if (IoHandle->Access == 0) {
  1687. return STATUS_SUCCESS;
  1688. }
  1689. Socket = FileObject->SpecialIo;
  1690. if (Socket == NULL) {
  1691. return STATUS_NOT_READY;
  1692. }
  1693. return STATUS_SUCCESS;
  1694. }
  1695. KSTATUS
  1696. IopCloseSocket (
  1697. PIO_HANDLE IoHandle
  1698. )
  1699. /*++
  1700. Routine Description:
  1701. This routine closes a socket connection.
  1702. Arguments:
  1703. IoHandle - Supplies a pointer to the socket handle to close.
  1704. Return Value:
  1705. Status code.
  1706. --*/
  1707. {
  1708. PFILE_OBJECT FileObject;
  1709. PSOCKET Socket;
  1710. KSTATUS Status;
  1711. FileObject = IoHandle->FileObject;
  1712. if (FileObject->Properties.Type != IoObjectSocket) {
  1713. Status = STATUS_NOT_A_SOCKET;
  1714. goto CloseSocketEnd;
  1715. }
  1716. if (IoHandle->Access == 0) {
  1717. return STATUS_SUCCESS;
  1718. }
  1719. Socket = FileObject->SpecialIo;
  1720. if (Socket->Domain == NetDomainLocal) {
  1721. Status = IopUnixSocketClose(Socket);
  1722. } else {
  1723. if (IoNetInterfaceInitialized == FALSE) {
  1724. Status = STATUS_NOT_IMPLEMENTED;
  1725. } else {
  1726. Status = IoNetInterface.CloseSocket(Socket);
  1727. if (!KSUCCESS(Status)) {
  1728. goto CloseSocketEnd;
  1729. }
  1730. }
  1731. }
  1732. CloseSocketEnd:
  1733. return Status;
  1734. }
  1735. //
  1736. // --------------------------------------------------------- Internal Functions
  1737. //
  1738. VOID
  1739. IopDestroySocket (
  1740. PSOCKET Socket
  1741. )
  1742. /*++
  1743. Routine Description:
  1744. This routine destroys a socket object.
  1745. Arguments:
  1746. Socket - Supplies a pointer to the socket to close.
  1747. Return Value:
  1748. Status code.
  1749. --*/
  1750. {
  1751. ASSERT(Socket->ReferenceCount == 0);
  1752. ASSERT(Socket->IoState != NULL);
  1753. IoDestroyIoObjectState(Socket->IoState);
  1754. Socket->IoState = NULL;
  1755. if (Socket->Domain == NetDomainLocal) {
  1756. IopDestroyUnixSocket(Socket);
  1757. } else {
  1758. IoNetInterface.DestroySocket(Socket);
  1759. }
  1760. return;
  1761. }