netlink.c 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077
  1. /*++
  2. Copyright (c) 2016 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. netlink.c
  5. Abstract:
  6. This module implements support for netlink sockets.
  7. Author:
  8. Chris Stevens 9-Feb-2016
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. //
  16. // Network layer drivers are supposed to be able to stand on their own (i.e. be
  17. // able to be implemented outside the core net library). For the builtin ones,
  18. // avoid including netcore.h, but still redefine those functions that would
  19. // otherwise generate imports.
  20. //
  21. #define NET_API __DLLEXPORT
  22. #include <minoca/kernel/driver.h>
  23. #include <minoca/net/netdrv.h>
  24. #include <minoca/net/netlink.h>
  25. //
  26. // ---------------------------------------------------------------- Definitions
  27. //
  28. #define NETLINK_ALLOCATION_TAG 0x694C654E // 'iLeN'
  29. //
  30. // Define the maximum size of an netlink address string, including the null
  31. // terminator. The longest string would look something like
  32. // "FFFFFFFF:FFFFFFFF"
  33. //
  34. #define NETLINK_MAX_ADDRESS_STRING 18
  35. //
  36. // ------------------------------------------------------ Data Type Definitions
  37. //
  38. //
  39. // ----------------------------------------------- Internal Function Prototypes
  40. //
  41. KSTATUS
  42. NetlinkpInitializeLink (
  43. PNET_LINK Link
  44. );
  45. VOID
  46. NetlinkpDestroyLink (
  47. PNET_LINK Link
  48. );
  49. KSTATUS
  50. NetlinkpInitializeSocket (
  51. PNET_PROTOCOL_ENTRY ProtocolEntry,
  52. PNET_NETWORK_ENTRY NetworkEntry,
  53. ULONG NetworkProtocol,
  54. PNET_SOCKET NewSocket
  55. );
  56. KSTATUS
  57. NetlinkpBindToAddress (
  58. PNET_SOCKET Socket,
  59. PNET_LINK Link,
  60. PNETWORK_ADDRESS Address
  61. );
  62. KSTATUS
  63. NetlinkpListen (
  64. PNET_SOCKET Socket
  65. );
  66. KSTATUS
  67. NetlinkpConnect (
  68. PNET_SOCKET Socket,
  69. PNETWORK_ADDRESS Address
  70. );
  71. KSTATUS
  72. NetlinkpDisconnect (
  73. PNET_SOCKET Socket
  74. );
  75. KSTATUS
  76. NetlinkpClose (
  77. PNET_SOCKET Socket
  78. );
  79. KSTATUS
  80. NetlinkpSend (
  81. PNET_SOCKET Socket,
  82. PNETWORK_ADDRESS Destination,
  83. PNET_SOCKET_LINK_OVERRIDE LinkOverride,
  84. PNET_PACKET_LIST PacketList
  85. );
  86. VOID
  87. NetlinkpProcessReceivedData (
  88. PNET_LINK Link,
  89. PNET_PACKET_BUFFER Packet
  90. );
  91. ULONG
  92. NetlinkpPrintAddress (
  93. PNETWORK_ADDRESS Address,
  94. PSTR Buffer,
  95. ULONG BufferLength
  96. );
  97. KSTATUS
  98. NetlinkpGetSetInformation (
  99. PNET_SOCKET Socket,
  100. SOCKET_INFORMATION_TYPE InformationType,
  101. UINTN SocketOption,
  102. PVOID Data,
  103. PUINTN DataSize,
  104. BOOL Set
  105. );
  106. VOID
  107. NetlinkpProcessReceivedPackets (
  108. PNET_LINK Link,
  109. PNETWORK_ADDRESS SourceAddress,
  110. PNETWORK_ADDRESS DestinationAddress,
  111. PNET_PACKET_LIST PacketList,
  112. PNET_PROTOCOL_ENTRY Protocol
  113. );
  114. VOID
  115. NetlinkpProcessReceivedSocketData (
  116. PNET_LINK Link,
  117. PNET_SOCKET Socket,
  118. PNET_PACKET_BUFFER Packet,
  119. PNETWORK_ADDRESS SourceAddress,
  120. PNETWORK_ADDRESS DestinationAddress
  121. );
  122. VOID
  123. NetlinkpProcessReceivedKernelData (
  124. PNET_LINK Link,
  125. PNET_SOCKET Socket,
  126. PNET_PACKET_BUFFER Packet,
  127. PNETWORK_ADDRESS SourceAddress,
  128. PNETWORK_ADDRESS DestinationAddress
  129. );
  130. VOID
  131. NetlinkpSendAck (
  132. PNET_SOCKET Socket,
  133. PNET_PACKET_BUFFER Packet,
  134. PNETWORK_ADDRESS DestinationAddress,
  135. KSTATUS PacketStatus
  136. );
  137. VOID
  138. NetlinkpLeaveMulticastGroup (
  139. PNET_SOCKET Socket,
  140. ULONG GroupId,
  141. BOOL LockHeld
  142. );
  143. //
  144. // -------------------------------------------------------------------- Globals
  145. //
  146. LIST_ENTRY NetlinkMulticastSocketList;
  147. PSHARED_EXCLUSIVE_LOCK NetlinkMulticastLock;
  148. //
  149. // ------------------------------------------------------------------ Functions
  150. //
  151. VOID
  152. NetpNetlinkInitialize (
  153. VOID
  154. )
  155. /*++
  156. Routine Description:
  157. This routine initializes support for netlink packets.
  158. Arguments:
  159. None.
  160. Return Value:
  161. None.
  162. --*/
  163. {
  164. NET_NETWORK_ENTRY NetworkEntry;
  165. KSTATUS Status;
  166. INITIALIZE_LIST_HEAD(&NetlinkMulticastSocketList);
  167. NetlinkMulticastLock = KeCreateSharedExclusiveLock();
  168. if (NetlinkMulticastLock == NULL) {
  169. ASSERT(FALSE);
  170. }
  171. //
  172. // Register the netlink handlers with the core networking library.
  173. //
  174. NetworkEntry.Domain = NetDomainNetlink;
  175. NetworkEntry.ParentProtocolNumber = 0;
  176. NetworkEntry.Interface.InitializeLink = NetlinkpInitializeLink;
  177. NetworkEntry.Interface.DestroyLink = NetlinkpDestroyLink;
  178. NetworkEntry.Interface.InitializeSocket = NetlinkpInitializeSocket;
  179. NetworkEntry.Interface.BindToAddress = NetlinkpBindToAddress;
  180. NetworkEntry.Interface.Listen = NetlinkpListen;
  181. NetworkEntry.Interface.Connect = NetlinkpConnect;
  182. NetworkEntry.Interface.Disconnect = NetlinkpDisconnect;
  183. NetworkEntry.Interface.Close = NetlinkpClose;
  184. NetworkEntry.Interface.Send = NetlinkpSend;
  185. NetworkEntry.Interface.ProcessReceivedData = NetlinkpProcessReceivedData;
  186. NetworkEntry.Interface.PrintAddress = NetlinkpPrintAddress;
  187. NetworkEntry.Interface.GetSetInformation = NetlinkpGetSetInformation;
  188. Status = NetRegisterNetworkLayer(&NetworkEntry, NULL);
  189. if (!KSUCCESS(Status)) {
  190. ASSERT(FALSE);
  191. }
  192. return;
  193. }
  194. KSTATUS
  195. NetlinkpInitializeLink (
  196. PNET_LINK Link
  197. )
  198. /*++
  199. Routine Description:
  200. This routine initializes any pieces of information needed by the network
  201. layer for a new link.
  202. Arguments:
  203. Link - Supplies a pointer to the new link.
  204. Return Value:
  205. Status code.
  206. --*/
  207. {
  208. return STATUS_SUCCESS;
  209. }
  210. VOID
  211. NetlinkpDestroyLink (
  212. PNET_LINK Link
  213. )
  214. /*++
  215. Routine Description:
  216. This routine allows the network layer to tear down any state before a link
  217. is destroyed.
  218. Arguments:
  219. Link - Supplies a pointer to the dying link.
  220. Return Value:
  221. None.
  222. --*/
  223. {
  224. return;
  225. }
  226. KSTATUS
  227. NetlinkpInitializeSocket (
  228. PNET_PROTOCOL_ENTRY ProtocolEntry,
  229. PNET_NETWORK_ENTRY NetworkEntry,
  230. ULONG NetworkProtocol,
  231. PNET_SOCKET NewSocket
  232. )
  233. /*++
  234. Routine Description:
  235. This routine initializes any pieces of information needed by the network
  236. layer for the socket. The core networking library will fill in the common
  237. header when this routine returns.
  238. Arguments:
  239. ProtocolEntry - Supplies a pointer to the protocol information.
  240. NetworkEntry - Supplies a pointer to the network information.
  241. NetworkProtocol - Supplies the raw protocol value for this socket used on
  242. the network. This value is network specific.
  243. NewSocket - Supplies a pointer to the new socket. The network layer should
  244. at the very least add any needed header size.
  245. Return Value:
  246. Status code.
  247. --*/
  248. {
  249. ULONG MaxPacketSize;
  250. PNETLINK_SOCKET NetlinkSocket;
  251. //
  252. // The protocol interface must supply a few routines.
  253. //
  254. NetlinkSocket = (PNETLINK_SOCKET)NewSocket;
  255. if (NetlinkSocket->ProtocolInterface.JoinMulticastGroup == NULL) {
  256. return STATUS_INVALID_PARAMETER;
  257. }
  258. //
  259. // Assume the header is always included on a netlink socket. It is
  260. // essentially a raw network.
  261. //
  262. RtlAtomicOr32(&(NewSocket->Flags), NET_SOCKET_FLAG_NETWORK_HEADER_INCLUDED);
  263. //
  264. // Determine if the maximum IPv4 packet size plus all existing headers and
  265. // footers is less than the current maximum packet size. If so, truncate
  266. // the maximum packet size. Note that the IPv4 maximum packet size includes
  267. // the size of the header.
  268. //
  269. MaxPacketSize = NewSocket->PacketSizeInformation.HeaderSize +
  270. NETLINK_MAX_PACKET_SIZE +
  271. NewSocket->PacketSizeInformation.FooterSize;
  272. if (NewSocket->PacketSizeInformation.MaxPacketSize > MaxPacketSize) {
  273. NewSocket->PacketSizeInformation.MaxPacketSize = MaxPacketSize;
  274. }
  275. NewSocket->PacketSizeInformation.HeaderSize += NETLINK_HEADER_LENGTH;
  276. return STATUS_SUCCESS;
  277. }
  278. KSTATUS
  279. NetlinkpBindToAddress (
  280. PNET_SOCKET Socket,
  281. PNET_LINK Link,
  282. PNETWORK_ADDRESS Address
  283. )
  284. /*++
  285. Routine Description:
  286. This routine binds the given socket to the specified network address.
  287. Arguments:
  288. Socket - Supplies a pointer to the socket to bind.
  289. Link - Supplies an optional pointer to a link to bind to.
  290. Address - Supplies a pointer to the address to bind the socket to.
  291. Return Value:
  292. Status code.
  293. --*/
  294. {
  295. ULONG BindingFlags;
  296. PNETWORK_ADDRESS LocalAddress;
  297. NET_LINK_LOCAL_ADDRESS LocalInformation;
  298. PNETLINK_ADDRESS LocalNetlinkAddress;
  299. PNETLINK_ADDRESS NetlinkAddress;
  300. PNETLINK_SOCKET NetlinkSocket;
  301. KSTATUS Status;
  302. ASSERT(Link == NULL);
  303. LocalInformation.Link = NULL;
  304. LocalInformation.LinkAddress = NULL;
  305. if (Address->Domain != NetDomainNetlink) {
  306. Status = STATUS_NOT_SUPPORTED;
  307. goto BindToAddressEnd;
  308. }
  309. //
  310. // If the socket is not locally or fully bound, then make an attempt at
  311. // locally binding it.
  312. //
  313. NetlinkAddress = (PNETLINK_ADDRESS)Address;
  314. if ((Socket->BindingType != SocketLocallyBound) &&
  315. (Socket->BindingType != SocketFullyBound)) {
  316. //
  317. // If this is a kernel socket, then the only port to which it can be
  318. // bound is port zero. Fail if this is not the case.
  319. //
  320. BindingFlags = 0;
  321. if ((Socket->Flags & NET_SOCKET_FLAG_KERNEL) != 0) {
  322. if (NetlinkAddress->Port != 0) {
  323. Status = STATUS_INVALID_PARAMETER;
  324. goto BindToAddressEnd;
  325. }
  326. //
  327. // Make sure the binding code does not assign an ephemeral port.
  328. //
  329. BindingFlags |= NET_SOCKET_BINDING_FLAG_NO_PORT_ASSIGNMENT;
  330. }
  331. LocalAddress = &(LocalInformation.LocalAddress);
  332. RtlCopyMemory(LocalAddress, Address, sizeof(NETWORK_ADDRESS));
  333. //
  334. // Do not allow netcore to bind to a group. This would prevent
  335. // non-multicast packets from ever reaching this socket. Group bindings
  336. // are handled separately below.
  337. //
  338. LocalNetlinkAddress = (PNETLINK_ADDRESS)LocalAddress;
  339. LocalNetlinkAddress->Group = 0;
  340. //
  341. // There are no "unbound" netlink sockets. The Port ID is either filled
  342. // in or it is zero and an ephemeral port will be assigned. Note that
  343. // kernel netlink sockets always have a port of zero and the binding
  344. // flags dictate that a port should not be assigned.
  345. //
  346. Status = NetBindSocket(Socket,
  347. SocketLocallyBound,
  348. &LocalInformation,
  349. NULL,
  350. BindingFlags);
  351. if (!KSUCCESS(Status)) {
  352. goto BindToAddressEnd;
  353. }
  354. //
  355. // Otherwise this must just be an attempt to join a multicast group. The
  356. // address port must match the socket's local address's port.
  357. //
  358. } else {
  359. if (Socket->LocalAddress.Port != Address->Port) {
  360. Status = STATUS_INVALID_PARAMETER;
  361. goto BindToAddressEnd;
  362. }
  363. }
  364. //
  365. // If the request includes being bound to a group, then add this socket to
  366. // the multicast group.
  367. //
  368. if (NetlinkAddress->Group != 0) {
  369. NetlinkSocket = (PNETLINK_SOCKET)Socket;
  370. Status = NetlinkSocket->ProtocolInterface.JoinMulticastGroup(
  371. Socket,
  372. NetlinkAddress->Group);
  373. if (!KSUCCESS(Status)) {
  374. goto BindToAddressEnd;
  375. }
  376. }
  377. BindToAddressEnd:
  378. return Status;
  379. }
  380. KSTATUS
  381. NetlinkpListen (
  382. PNET_SOCKET Socket
  383. )
  384. /*++
  385. Routine Description:
  386. This routine adds a bound socket to the list of listening sockets,
  387. officially allowing clients to attempt to connect to it.
  388. Arguments:
  389. Socket - Supplies a pointer to the socket to mark as listning.
  390. Return Value:
  391. Status code.
  392. --*/
  393. {
  394. NETWORK_ADDRESS LocalAddress;
  395. KSTATUS Status;
  396. RtlZeroMemory(&(Socket->RemoteAddress), sizeof(NETWORK_ADDRESS));
  397. if (Socket->BindingType == SocketBindingInvalid) {
  398. RtlZeroMemory(&LocalAddress, sizeof(NETWORK_ADDRESS));
  399. LocalAddress.Domain = NetDomainNetlink;
  400. Status = NetlinkpBindToAddress(Socket, NULL, &LocalAddress);
  401. if (!KSUCCESS(Status)) {
  402. goto ListenEnd;
  403. }
  404. }
  405. Status = NetActivateSocket(Socket);
  406. if (!KSUCCESS(Status)) {
  407. goto ListenEnd;
  408. }
  409. ListenEnd:
  410. return Status;
  411. }
  412. KSTATUS
  413. NetlinkpConnect (
  414. PNET_SOCKET Socket,
  415. PNETWORK_ADDRESS Address
  416. )
  417. /*++
  418. Routine Description:
  419. This routine connects the given socket to a specific remote address. It
  420. will implicitly bind the socket if it is not yet locally bound.
  421. Arguments:
  422. Socket - Supplies a pointer to the socket to use for the connection.
  423. Address - Supplies a pointer to the remote address to bind this socket to.
  424. Return Value:
  425. Status code.
  426. --*/
  427. {
  428. ULONG Flags;
  429. NET_LINK_LOCAL_ADDRESS LocalInformation;
  430. KSTATUS Status;
  431. if (Address->Domain != NetDomainNetlink) {
  432. Status = STATUS_NOT_SUPPORTED;
  433. goto ConnectEnd;
  434. }
  435. //
  436. // Zero the local information. If the socket is already locally bound, it
  437. // will not be used. If it is not locally bound, then this will trigger a
  438. // ephemeral port assignment.
  439. //
  440. RtlZeroMemory(&LocalInformation, sizeof(NET_LINK_LOCAL_ADDRESS));
  441. //
  442. // If this is a kernel socket, then the only port to which it can be
  443. // locally bound is port zero. Make sure a local ephemeral port is not
  444. // assigned.
  445. //
  446. Flags = NET_SOCKET_BINDING_FLAG_ACTIVATE;
  447. if ((Socket->Flags & NET_SOCKET_FLAG_KERNEL) != 0) {
  448. Flags |= NET_SOCKET_BINDING_FLAG_NO_PORT_ASSIGNMENT;
  449. }
  450. //
  451. // Fully bind the socket and activate it. It's ready to receive.
  452. //
  453. Status = NetBindSocket(Socket,
  454. SocketFullyBound,
  455. &LocalInformation,
  456. Address,
  457. Flags);
  458. if (!KSUCCESS(Status)) {
  459. goto ConnectEnd;
  460. }
  461. Status = STATUS_SUCCESS;
  462. ConnectEnd:
  463. return Status;
  464. }
  465. KSTATUS
  466. NetlinkpDisconnect (
  467. PNET_SOCKET Socket
  468. )
  469. /*++
  470. Routine Description:
  471. This routine will disconnect the given socket from its remote address.
  472. Arguments:
  473. Socket - Supplies a pointer to the socket to disconnect.
  474. Return Value:
  475. Status code.
  476. --*/
  477. {
  478. ASSERT(FALSE);
  479. return STATUS_NOT_SUPPORTED;
  480. }
  481. KSTATUS
  482. NetlinkpClose (
  483. PNET_SOCKET Socket
  484. )
  485. /*++
  486. Routine Description:
  487. This routine closes a socket connection.
  488. Arguments:
  489. Socket - Supplies a pointer to the socket to shut down.
  490. Return Value:
  491. Status code.
  492. --*/
  493. {
  494. PNETLINK_SOCKET NetlinkSocket;
  495. //
  496. // Deactivate the socket. This will most likely release a reference. There
  497. // should be at least one more sitting around.
  498. //
  499. ASSERT(Socket->KernelSocket.ReferenceCount > 1);
  500. //
  501. // If the socket is a member of any multicast groups, just remove it from
  502. // the list of sockets responding to multicast messages.
  503. //
  504. NetlinkSocket = (PNETLINK_SOCKET)Socket;
  505. if (NetlinkSocket->MulticastListEntry.Next != NULL) {
  506. KeAcquireSharedExclusiveLockExclusive(NetlinkMulticastLock);
  507. LIST_REMOVE(&(NetlinkSocket->MulticastListEntry));
  508. NetlinkSocket->MulticastListEntry.Next = NULL;
  509. KeReleaseSharedExclusiveLockExclusive(NetlinkMulticastLock);
  510. }
  511. NetDeactivateSocket(Socket);
  512. return STATUS_SUCCESS;
  513. }
  514. KSTATUS
  515. NetlinkpSend (
  516. PNET_SOCKET Socket,
  517. PNETWORK_ADDRESS Destination,
  518. PNET_SOCKET_LINK_OVERRIDE LinkOverride,
  519. PNET_PACKET_LIST PacketList
  520. )
  521. /*++
  522. Routine Description:
  523. This routine sends data through the network.
  524. Arguments:
  525. Socket - Supplies a pointer to the socket to send the data to.
  526. Destination - Supplies a pointer to the network address to send to.
  527. LinkOverride - Supplies an optional pointer to a structure that contains
  528. all the necessary information to send data out a link on behalf
  529. of the given socket.
  530. PacketList - Supplies a pointer to a list of network packets to send. Data
  531. in these packets may be modified by this routine, but must not be used
  532. once this routine returns.
  533. Return Value:
  534. Status code. It is assumed that either all packets are submitted (if
  535. success is returned) or none of the packets were submitted (if a failing
  536. status is returned).
  537. --*/
  538. {
  539. NetlinkpProcessReceivedPackets(Socket->Link,
  540. &Socket->LocalAddress,
  541. Destination,
  542. PacketList,
  543. Socket->Protocol);
  544. return STATUS_SUCCESS;
  545. }
  546. VOID
  547. NetlinkpProcessReceivedData (
  548. PNET_LINK Link,
  549. PNET_PACKET_BUFFER Packet
  550. )
  551. /*++
  552. Routine Description:
  553. This routine is called to process a received packet.
  554. Arguments:
  555. Link - Supplies a pointer to the link that received the packet.
  556. Packet - Supplies a pointer to a structure describing the incoming packet.
  557. This structure may be used as a scratch space while this routine
  558. executes and the packet travels up the stack, but will not be accessed
  559. after this routine returns.
  560. Return Value:
  561. None. When the function returns, the memory associated with the packet may
  562. be reclaimed and reused.
  563. --*/
  564. {
  565. //
  566. // A netlink packet header does not contain the protocol number. As a
  567. // result this routine cannot be used to process netlink packets.
  568. //
  569. ASSERT(FALSE);
  570. return;
  571. }
  572. ULONG
  573. NetlinkpPrintAddress (
  574. PNETWORK_ADDRESS Address,
  575. PSTR Buffer,
  576. ULONG BufferLength
  577. )
  578. /*++
  579. Routine Description:
  580. This routine is called to convert a network address into a string, or
  581. determine the length of the buffer needed to convert an address into a
  582. string.
  583. Arguments:
  584. Address - Supplies an optional pointer to a network address to convert to
  585. a string.
  586. Buffer - Supplies an optional pointer where the string representation of
  587. the address will be returned.
  588. BufferLength - Supplies the length of the supplied buffer, in bytes.
  589. Return Value:
  590. Returns the maximum length of any address if no network address is
  591. supplied.
  592. Returns the actual length of the network address string if a network address
  593. was supplied, including the null terminator.
  594. --*/
  595. {
  596. ULONG Length;
  597. PNETLINK_ADDRESS NetlinkAddress;
  598. if (Address == NULL) {
  599. return NETLINK_MAX_ADDRESS_STRING;
  600. }
  601. ASSERT(Address->Domain == NetDomainNetlink);
  602. NetlinkAddress = (PNETLINK_ADDRESS)Address;
  603. //
  604. // If the group is present, print that bad boy out.
  605. //
  606. if (NetlinkAddress->Group != 0) {
  607. Length = RtlPrintToString(Buffer,
  608. BufferLength,
  609. CharacterEncodingDefault,
  610. "%08x:%08x",
  611. NetlinkAddress->Port,
  612. NetlinkAddress->Group);
  613. } else {
  614. Length = RtlPrintToString(Buffer,
  615. BufferLength,
  616. CharacterEncodingDefault,
  617. "%08x",
  618. NetlinkAddress->Port);
  619. }
  620. return Length;
  621. }
  622. KSTATUS
  623. NetlinkpGetSetInformation (
  624. PNET_SOCKET Socket,
  625. SOCKET_INFORMATION_TYPE InformationType,
  626. UINTN Option,
  627. PVOID Data,
  628. PUINTN DataSize,
  629. BOOL Set
  630. )
  631. /*++
  632. Routine Description:
  633. This routine gets or sets properties of the given socket.
  634. Arguments:
  635. Socket - Supplies a pointer to the socket to get or set information for.
  636. InformationType - Supplies the socket information type category to which
  637. specified option belongs.
  638. Option - Supplies the option to get or set, which is specific to the
  639. information type. The type of this value is generally
  640. SOCKET_<information_type>_OPTION.
  641. Data - Supplies a pointer to the data buffer where the data is either
  642. returned for a get operation or given for a set operation.
  643. DataSize - Supplies a pointer that on input constains the size of the data
  644. buffer. On output, this contains the required size of the data buffer.
  645. Set - Supplies a boolean indicating if this is a get operation (FALSE) or
  646. a set operation (TRUE).
  647. Return Value:
  648. STATUS_SUCCESS on success.
  649. STATUS_INVALID_PARAMETER if the information type is incorrect.
  650. STATUS_BUFFER_TOO_SMALL if the data buffer is too small to receive the
  651. requested option.
  652. STATUS_NOT_SUPPORTED_BY_PROTOCOL if the socket option is not supported by
  653. the socket.
  654. --*/
  655. {
  656. ULONG GroupId;
  657. NETLINK_SOCKET_OPTION NetlinkOption;
  658. PNETLINK_SOCKET NetlinkSocket;
  659. UINTN RequiredSize;
  660. PVOID Source;
  661. KSTATUS Status;
  662. NetlinkSocket = (PNETLINK_SOCKET)Socket;
  663. if (InformationType != SocketInformationNetlink) {
  664. Status = STATUS_INVALID_PARAMETER;
  665. goto GetSetInformationEnd;
  666. }
  667. RequiredSize = 0;
  668. Source = NULL;
  669. Status = STATUS_SUCCESS;
  670. NetlinkOption = (NETLINK_SOCKET_OPTION)Option;
  671. switch (NetlinkOption) {
  672. case NetlinkSocketOptionJoinMulticastGroup:
  673. case NetlinkSocketOptionLeaveMulticastGroup:
  674. RequiredSize = sizeof(ULONG);
  675. if (Set == FALSE) {
  676. Status = STATUS_NOT_SUPPORTED_BY_PROTOCOL;
  677. break;
  678. }
  679. if (*DataSize < RequiredSize) {
  680. *DataSize = RequiredSize;
  681. Status = STATUS_BUFFER_TOO_SMALL;
  682. break;
  683. }
  684. GroupId = *((PULONG)Data);
  685. if ((GroupId > SOCKET_OPTION_MAX_ULONG) || (GroupId == 0)) {
  686. Status = STATUS_INVALID_PARAMETER;
  687. break;
  688. }
  689. //
  690. // Adding a socket to a multicast group is a bit tricky, as it needs to
  691. // validate the group ID with the protocol layer. So perform a re-bind.
  692. //
  693. if (NetlinkOption == NetlinkSocketOptionJoinMulticastGroup) {
  694. Status = NetlinkSocket->ProtocolInterface.JoinMulticastGroup(
  695. Socket,
  696. GroupId);
  697. if (!KSUCCESS(Status)) {
  698. break;
  699. }
  700. //
  701. // Dropping membership is easy, as the socket's propertie can validate
  702. // if the group ID is valid and silently fail if it is not.
  703. //
  704. } else {
  705. NetlinkpLeaveMulticastGroup(Socket, GroupId, FALSE);
  706. }
  707. break;
  708. default:
  709. Status = STATUS_NOT_SUPPORTED_BY_PROTOCOL;
  710. break;
  711. }
  712. if (!KSUCCESS(Status)) {
  713. goto GetSetInformationEnd;
  714. }
  715. //
  716. // Truncate all copies for get requests down to the required size and
  717. // always return the required size on set requests.
  718. //
  719. if (*DataSize > RequiredSize) {
  720. *DataSize = RequiredSize;
  721. }
  722. //
  723. // For get requests, copy the gathered information to the supplied data
  724. // buffer.
  725. //
  726. if (Set == FALSE) {
  727. ASSERT(Source != NULL);
  728. RtlCopyMemory(Data, Source, *DataSize);
  729. //
  730. // If the copy truncated the data, report that the given buffer was too
  731. // small. The caller can choose to ignore this if the truncated data is
  732. // enough.
  733. //
  734. if (*DataSize < RequiredSize) {
  735. *DataSize = RequiredSize;
  736. Status = STATUS_BUFFER_TOO_SMALL;
  737. goto GetSetInformationEnd;
  738. }
  739. }
  740. GetSetInformationEnd:
  741. return Status;
  742. }
  743. NETLINK_API
  744. KSTATUS
  745. NetlinkSendMessage (
  746. PNET_SOCKET Socket,
  747. PNET_PACKET_BUFFER Packet,
  748. PNETWORK_ADDRESS DestinationAddress
  749. )
  750. /*++
  751. Routine Description:
  752. This routine sends a netlink message to the given destination address. The
  753. caller should have already filled the buffer with the netlink header.
  754. Arguments:
  755. Socket - Supplies a pointer to the netlink socket over which to send the
  756. message.
  757. Packet - Supplies a pointer to the network packet to be sent.
  758. DestinationAddress - Supplies a pointer to the destination address to which
  759. the message will be sent.
  760. Return Value:
  761. Status code.
  762. --*/
  763. {
  764. SOCKET_IO_PARAMETERS IoParameters;
  765. KSTATUS Status;
  766. //
  767. // The packet should be filled up. Set the data offset back to zero to send
  768. // all the data in the packet.
  769. //
  770. ASSERT(Packet->DataOffset == Packet->FooterOffset);
  771. Packet->DataOffset = 0;
  772. //
  773. // Send the packet using the I/O API.
  774. //
  775. RtlZeroMemory(&IoParameters, sizeof(SOCKET_IO_PARAMETERS));
  776. IoParameters.TimeoutInMilliseconds = WAIT_TIME_INDEFINITE;
  777. IoParameters.NetworkAddress = DestinationAddress;
  778. IoParameters.Size = Packet->FooterOffset - Packet->DataOffset;
  779. MmSetIoBufferCurrentOffset(Packet->IoBuffer, Packet->DataOffset);
  780. Status = IoSocketSendData(TRUE,
  781. Socket->KernelSocket.IoHandle,
  782. &IoParameters,
  783. Packet->IoBuffer);
  784. return Status;
  785. }
  786. NETLINK_API
  787. KSTATUS
  788. NetlinkSendMultipartMessage (
  789. PNET_SOCKET Socket,
  790. PNET_PACKET_BUFFER Packet,
  791. PNETWORK_ADDRESS DestinationAddress,
  792. ULONG SequenceNumber
  793. )
  794. /*++
  795. Routine Description:
  796. This routine sends a multipart message packet. It will append the final
  797. DONE message, which the packet must have space for, reset the packet's data
  798. offset to the beginning and then send the entire packet off to the
  799. destination address.
  800. Arguments:
  801. Socket - Supplies a pointer to the network socket from which the packet
  802. will be sent.
  803. Packet - Supplies a pointer to the network packet to send.
  804. DestinationAddress - Supplies a pointer to the network address to which the
  805. packet will be sent.
  806. SequenceNumber - Supplies the sequence number to set in the header of the
  807. DONE message that is appended to the packet.
  808. Return Value:
  809. Status code.
  810. --*/
  811. {
  812. KSTATUS Status;
  813. //
  814. // Add the done message. It is simply just a netlink header with the type
  815. // set to DONE and the multi-part message flag set.
  816. //
  817. Status = NetlinkAppendHeader(Socket,
  818. Packet,
  819. 0,
  820. SequenceNumber,
  821. NETLINK_MESSAGE_TYPE_DONE,
  822. NETLINK_HEADER_FLAG_MULTIPART);
  823. if (!KSUCCESS(Status)) {
  824. goto SendMultipartMessageEnd;
  825. }
  826. //
  827. // Send the entire multipart packet to the destination as one "message".
  828. //
  829. Status = NetlinkSendMessage(Socket, Packet, DestinationAddress);
  830. if (!KSUCCESS(Status)) {
  831. goto SendMultipartMessageEnd;
  832. }
  833. SendMultipartMessageEnd:
  834. return Status;
  835. }
  836. NETLINK_API
  837. KSTATUS
  838. NetlinkAppendHeader (
  839. PNET_SOCKET Socket,
  840. PNET_PACKET_BUFFER Packet,
  841. ULONG Length,
  842. ULONG SequenceNumber,
  843. USHORT Type,
  844. USHORT Flags
  845. )
  846. /*++
  847. Routine Description:
  848. This routine appends a base netlink header to the given network packet. It
  849. validates if there is enough space remaining in the packet and moves the
  850. data offset forwards to the first byte after the header on success.
  851. Arguments:
  852. Socket - Supplies a pointer to the socket that will send the packet. The
  853. header's port ID is taken from the socket's local address.
  854. Packet - Supplies a pointer to the network packet to which a base netlink
  855. header will be added.
  856. Length - Supplies the length of the netlink message, not including the
  857. header.
  858. SequenceNumber - Supplies the desired sequence number for the netlink
  859. message.
  860. Type - Supplies the message type to be set in the header.
  861. Flags - Supplies a bitmask of netlink message flags to be set. See
  862. NETLINK_HEADER_FLAG_* for definitions.
  863. Return Value:
  864. Status code.
  865. --*/
  866. {
  867. PNETLINK_HEADER Header;
  868. ULONG PacketLength;
  869. PNETLINK_ADDRESS SourceAddress;
  870. KSTATUS Status;
  871. Length += NETLINK_HEADER_LENGTH;
  872. PacketLength = Packet->FooterOffset - Packet->DataOffset;
  873. if (PacketLength < Length) {
  874. Status = STATUS_BUFFER_TOO_SMALL;
  875. goto AppendHeaderEnd;
  876. }
  877. SourceAddress = (PNETLINK_ADDRESS)&(Socket->LocalAddress);
  878. Header = Packet->Buffer + Packet->DataOffset;
  879. Header->Length = Length;
  880. Header->Type = Type;
  881. Header->Flags = Flags;
  882. Header->SequenceNumber = SequenceNumber;
  883. Header->PortId = SourceAddress->Port;
  884. Packet->DataOffset += NETLINK_HEADER_LENGTH;
  885. Status = STATUS_SUCCESS;
  886. AppendHeaderEnd:
  887. return Status;
  888. }
  889. NETLINK_API
  890. KSTATUS
  891. NetlinkAppendAttribute (
  892. PNET_PACKET_BUFFER Packet,
  893. USHORT Type,
  894. PVOID Data,
  895. USHORT DataLength
  896. )
  897. /*++
  898. Routine Description:
  899. This routine appends a netlink attribute to the given network packet. It
  900. validates that there is enough space for the attribute and moves the
  901. packet's data offset to the first byte after the attribute. The exception
  902. to this rule is if a NULL data buffer is supplied; the packet's data offset
  903. is only moved to the first byte after the attribute header.
  904. Arguments:
  905. Packet - Supplies a pointer to the network packet to which the attribute
  906. will be added.
  907. Type - Supplies the netlink attribute type.
  908. Data - Supplies an optional pointer to the attribute data to be stored in
  909. the network packet. Even if no data buffer is supplied, a data length
  910. may be supplied for the case of child attributes that are yet to be
  911. appended.
  912. DataLength - Supplies the length of the data, in bytes.
  913. Return Value:
  914. Status code.
  915. --*/
  916. {
  917. PNETLINK_ATTRIBUTE Attribute;
  918. ULONG AttributeLength;
  919. ULONG PacketLength;
  920. AttributeLength = NETLINK_ATTRIBUTE_SIZE(DataLength);
  921. PacketLength = Packet->FooterOffset - Packet->DataOffset;
  922. if (PacketLength < AttributeLength) {
  923. return STATUS_BUFFER_TOO_SMALL;
  924. }
  925. Attribute = Packet->Buffer + Packet->DataOffset;
  926. Attribute->Length = NETLINK_ATTRIBUTE_LENGTH(DataLength);
  927. Attribute->Type = Type;
  928. if (Data != NULL) {
  929. RtlCopyMemory(NETLINK_ATTRIBUTE_DATA(Attribute), Data, DataLength);
  930. Packet->DataOffset += AttributeLength;
  931. } else {
  932. Packet->DataOffset += NETLINK_ATTRIBUTE_HEADER_LENGTH;
  933. }
  934. return STATUS_SUCCESS;
  935. }
  936. NETLINK_API
  937. KSTATUS
  938. NetlinkGetAttribute (
  939. PVOID Attributes,
  940. ULONG AttributesLength,
  941. USHORT Type,
  942. PVOID *Data,
  943. PUSHORT DataLength
  944. )
  945. /*++
  946. Routine Description:
  947. This routine parses the given attributes buffer and returns a pointer to
  948. the desired attribute.
  949. Arguments:
  950. Attributes - Supplies a pointer to the start of the generic command
  951. attributes.
  952. AttributesLength - Supplies the length of the attributes buffer, in bytes.
  953. Type - Supplies the netlink generic attribute type.
  954. Data - Supplies a pointer that receives a pointer to the data for the
  955. requested attribute type.
  956. DataLength - Supplies a pointer that receives the length of the requested
  957. attribute data.
  958. Return Value:
  959. Status code.
  960. --*/
  961. {
  962. PNETLINK_ATTRIBUTE Attribute;
  963. ULONG AttributeSize;
  964. Attribute = (PNETLINK_ATTRIBUTE)Attributes;
  965. while (AttributesLength != 0) {
  966. if ((AttributesLength < NETLINK_ATTRIBUTE_HEADER_LENGTH) ||
  967. (AttributesLength < Attribute->Length)) {
  968. break;
  969. }
  970. if (Attribute->Type == Type) {
  971. *DataLength = Attribute->Length - NETLINK_ATTRIBUTE_HEADER_LENGTH;
  972. *Data = NETLINK_ATTRIBUTE_DATA(Attribute);
  973. return STATUS_SUCCESS;
  974. }
  975. AttributeSize = NETLINK_ALIGN(Attribute->Length);
  976. Attribute = (PVOID)Attribute + AttributeSize;
  977. AttributesLength -= AttributeSize;
  978. }
  979. *Data = NULL;
  980. *DataLength = 0;
  981. return STATUS_NOT_FOUND;
  982. }
  983. NETLINK_API
  984. KSTATUS
  985. NetlinkJoinMulticastGroup (
  986. PNET_SOCKET Socket,
  987. ULONG GroupId
  988. )
  989. /*++
  990. Routine Description:
  991. This routine joins a socket to a multicast group by updating the socket's
  992. multicast group bitmap and adding the socket to the global list of socket's
  993. joined to multicast groups.
  994. Arguments:
  995. Socket - Supplies a pointer to the socket that is requesting to join a
  996. multicast group.
  997. GroupId - Supplies the ID of the multicast group to join.
  998. Return Value:
  999. Status code.
  1000. --*/
  1001. {
  1002. ULONG AlignedGroupId;
  1003. ULONG GroupCount;
  1004. ULONG GroupIndex;
  1005. ULONG GroupMask;
  1006. PNETLINK_SOCKET NetlinkSocket;
  1007. PULONG NewBitmap;
  1008. ULONG NewBitmapSize;
  1009. ULONG NewGroups;
  1010. PULONG ReleaseBitmap;
  1011. NetlinkSocket = (PNETLINK_SOCKET)Socket;
  1012. NewBitmap = NULL;
  1013. NewBitmapSize = 0;
  1014. NewGroups = 0;
  1015. //
  1016. // Expand the bitmap if necessary. The group ID should have been validated
  1017. // by the protocol layer before reaching this point in the stack.
  1018. //
  1019. GroupCount = NETLINK_SOCKET_BITMAP_GROUP_ID_COUNT(NetlinkSocket);
  1020. if (GroupId >= GroupCount) {
  1021. AlignedGroupId = ALIGN_RANGE_UP(GroupId + 1,
  1022. (sizeof(ULONG) * BITS_PER_BYTE));
  1023. NewGroups = AlignedGroupId - GroupCount;
  1024. NewBitmapSize = NetlinkSocket->MulticastBitmapSize +
  1025. (NewGroups / BITS_PER_BYTE);
  1026. NewBitmap = MmAllocatePagedPool(NewBitmapSize, NETLINK_ALLOCATION_TAG);
  1027. if (NewBitmap == NULL) {
  1028. return STATUS_INSUFFICIENT_RESOURCES;
  1029. }
  1030. }
  1031. GroupIndex = NETLINK_SOCKET_BITMAP_INDEX(GroupId);
  1032. GroupMask = NETLINK_SOCKET_BITMAP_MASK(GroupId);
  1033. KeAcquireSharedExclusiveLockExclusive(NetlinkMulticastLock);
  1034. if (GroupId >= NETLINK_SOCKET_BITMAP_GROUP_ID_COUNT(NetlinkSocket)) {
  1035. ASSERT(NewBitmapSize > NetlinkSocket->MulticastBitmapSize);
  1036. RtlCopyMemory(NewBitmap,
  1037. NetlinkSocket->MulticastBitmap,
  1038. NetlinkSocket->MulticastBitmapSize);
  1039. RtlZeroMemory((PVOID)NewBitmap + NetlinkSocket->MulticastBitmapSize,
  1040. (NewGroups / BITS_PER_BYTE));
  1041. ReleaseBitmap = NetlinkSocket->MulticastBitmap;
  1042. NetlinkSocket->MulticastBitmap = NewBitmap;
  1043. NetlinkSocket->MulticastBitmapSize = NewBitmapSize;
  1044. } else {
  1045. ReleaseBitmap = NewBitmap;
  1046. }
  1047. if ((NetlinkSocket->MulticastBitmap[GroupIndex] & GroupMask) == 0) {
  1048. NetlinkSocket->MulticastBitmap[GroupIndex] |= GroupMask;
  1049. NetlinkSocket->MulticastGroupCount += 1;
  1050. if (NetlinkSocket->MulticastListEntry.Next == NULL) {
  1051. INSERT_AFTER(&(NetlinkSocket->MulticastListEntry),
  1052. &NetlinkMulticastSocketList);
  1053. }
  1054. }
  1055. ASSERT(NetlinkSocket->MulticastListEntry.Next != NULL);
  1056. KeReleaseSharedExclusiveLockExclusive(NetlinkMulticastLock);
  1057. if (ReleaseBitmap != NULL) {
  1058. MmFreePagedPool(ReleaseBitmap);
  1059. }
  1060. return STATUS_SUCCESS;
  1061. }
  1062. NETLINK_API
  1063. VOID
  1064. NetlinkRemoveSocketsFromMulticastGroups (
  1065. ULONG ParentProtocolNumber,
  1066. ULONG GroupOffset,
  1067. ULONG GroupCount
  1068. )
  1069. /*++
  1070. Routine Description:
  1071. This routine removes any socket listening for multicast message from the
  1072. groups specified by the offset and count. It will only match sockets for
  1073. the given protocol.
  1074. Arguments:
  1075. ParentProtocolNumber - Supplies the protocol number of the protocol that
  1076. owns the given range of multicast groups.
  1077. GroupOffset - Supplies the offset into the multicast namespace for the
  1078. range of multicast groups from which the sockets should be removed.
  1079. GroupCount - Supplies the number of multicast groups from which the sockets
  1080. should be removed.
  1081. Return Value:
  1082. None.
  1083. --*/
  1084. {
  1085. PLIST_ENTRY CurrentEntry;
  1086. ULONG Index;
  1087. PNETLINK_SOCKET Socket;
  1088. if (LIST_EMPTY(&NetlinkMulticastSocketList) != FALSE) {
  1089. return;
  1090. }
  1091. KeAcquireSharedExclusiveLockExclusive(NetlinkMulticastLock);
  1092. CurrentEntry = NetlinkMulticastSocketList.Next;
  1093. while (CurrentEntry != &NetlinkMulticastSocketList) {
  1094. Socket = LIST_VALUE(CurrentEntry, NETLINK_SOCKET, MulticastListEntry);
  1095. CurrentEntry = CurrentEntry->Next;
  1096. if (Socket->NetSocket.Protocol->ParentProtocolNumber !=
  1097. ParentProtocolNumber) {
  1098. continue;
  1099. }
  1100. for (Index = 0; Index < GroupCount; Index += 1) {
  1101. NetlinkpLeaveMulticastGroup(&(Socket->NetSocket),
  1102. GroupOffset + Index,
  1103. TRUE);
  1104. }
  1105. }
  1106. KeReleaseSharedExclusiveLockExclusive(NetlinkMulticastLock);
  1107. return;
  1108. }
  1109. //
  1110. // --------------------------------------------------------- Internal Functions
  1111. //
  1112. VOID
  1113. NetlinkpProcessReceivedPackets (
  1114. PNET_LINK Link,
  1115. PNETWORK_ADDRESS SourceAddress,
  1116. PNETWORK_ADDRESS DestinationAddress,
  1117. PNET_PACKET_LIST PacketList,
  1118. PNET_PROTOCOL_ENTRY Protocol
  1119. )
  1120. /*++
  1121. Routine Description:
  1122. This routine processes a list of packets, handling netlink message parsing
  1123. and error handling that is common to all protocols.
  1124. Arguments:
  1125. Link - Supplies a pointer to the link that received the packets.
  1126. SourceAddress - Supplies a pointer to the source (remote) address that the
  1127. packet originated from. This memory will not be referenced once the
  1128. function returns, it can be stack allocated.
  1129. DestinationAddress - Supplies a pointer to the destination (local) address
  1130. that the packet is heading to. This memory will not be referenced once
  1131. the function returns, it can be stack allocated.
  1132. PacketList - Supplies a list of packets to process.
  1133. Protocol - Supplies a pointer to this protocol's protocol entry.
  1134. Return Value:
  1135. None.
  1136. --*/
  1137. {
  1138. ULONG Count;
  1139. PNETLINK_ADDRESS Destination;
  1140. ULONG GroupIndex;
  1141. ULONG GroupMask;
  1142. PULONG MulticastBitmap;
  1143. PNETLINK_SOCKET NetlinkSocket;
  1144. PNET_PACKET_BUFFER Packet;
  1145. PLIST_ENTRY PacketEntry;
  1146. PNET_SOCKET Socket;
  1147. PLIST_ENTRY SocketEntry;
  1148. //
  1149. // If a group ID is supplied in the address, then send the packet to all
  1150. // sockets listening to that multicast group. A socket must match on the
  1151. // protocol and have its bitmap set for the group. If a port is also
  1152. // specified in the address, do not send it to the socket with the port
  1153. // during multicast processing; fall through and do that at the end.
  1154. //
  1155. Destination = (PNETLINK_ADDRESS)DestinationAddress;
  1156. if (Destination->Group != 0) {
  1157. PacketEntry = PacketList->Head.Next;
  1158. while (PacketEntry != &(PacketList->Head)) {
  1159. Packet = LIST_VALUE(PacketEntry, NET_PACKET_BUFFER, ListEntry);
  1160. Packet->Flags |= NET_PACKET_FLAG_MULTICAST;
  1161. GroupIndex = NETLINK_SOCKET_BITMAP_INDEX(Destination->Group);
  1162. GroupMask = NETLINK_SOCKET_BITMAP_MASK(Destination->Group);
  1163. KeAcquireSharedExclusiveLockShared(NetlinkMulticastLock);
  1164. SocketEntry = NetlinkMulticastSocketList.Next;
  1165. while (SocketEntry != &NetlinkMulticastSocketList) {
  1166. NetlinkSocket = LIST_VALUE(SocketEntry,
  1167. NETLINK_SOCKET,
  1168. MulticastListEntry);
  1169. Socket = &(NetlinkSocket->NetSocket);
  1170. SocketEntry = SocketEntry->Next;
  1171. if (Socket->Protocol != Protocol) {
  1172. continue;
  1173. }
  1174. if (Socket->LocalAddress.Port == Destination->Port) {
  1175. continue;
  1176. }
  1177. Count = NETLINK_SOCKET_BITMAP_GROUP_ID_COUNT(NetlinkSocket);
  1178. if (Destination->Group >= Count) {
  1179. continue;
  1180. }
  1181. MulticastBitmap = NetlinkSocket->MulticastBitmap;
  1182. if ((MulticastBitmap[GroupIndex] & GroupMask) == 0) {
  1183. continue;
  1184. }
  1185. //
  1186. // This needs to be reconsidered if kernel sockets are signed
  1187. // up for multicast groups. Kernel sockets are known to respond
  1188. // to requests with multicast messages as an event notification
  1189. // mechanism. This could potentially deadlock as the lock is
  1190. // held during packet processing.
  1191. //
  1192. ASSERT((Socket->Flags & NET_SOCKET_FLAG_KERNEL) == 0);
  1193. NetlinkpProcessReceivedSocketData(Link,
  1194. Socket,
  1195. Packet,
  1196. SourceAddress,
  1197. DestinationAddress);
  1198. }
  1199. KeReleaseSharedExclusiveLockShared(NetlinkMulticastLock);
  1200. //
  1201. // Clear out the multicast group and send it on to the socket
  1202. // specified by the port.
  1203. //
  1204. Packet->Flags &= ~NET_PACKET_FLAG_MULTICAST;
  1205. PacketEntry = PacketEntry->Next;
  1206. }
  1207. Destination->Group = 0;
  1208. Socket = NULL;
  1209. //
  1210. // The kernel should never get any multicast packets, so just drop it
  1211. // now before getting to the kernel.
  1212. //
  1213. if (Destination->Port == NETLINK_KERNEL_PORT_ID) {
  1214. NetDestroyBufferList(PacketList);
  1215. goto ProcessReceivedPacketsEnd;
  1216. }
  1217. }
  1218. //
  1219. // Find the socket targeted by the destination address.
  1220. //
  1221. Socket = NetFindSocket(Protocol, DestinationAddress, SourceAddress);
  1222. if (Socket == NULL) {
  1223. goto ProcessReceivedPacketsEnd;
  1224. }
  1225. ASSERT(Socket->Protocol == Protocol);
  1226. //
  1227. // Send each packet on to the protocol layer for processing. The packet
  1228. // handling routines take ownership of a non-multicast packets and free
  1229. // them.
  1230. //
  1231. while (NET_PACKET_LIST_EMPTY(PacketList) == FALSE) {
  1232. Packet = LIST_VALUE(PacketList->Head.Next,
  1233. NET_PACKET_BUFFER,
  1234. ListEntry);
  1235. NET_REMOVE_PACKET_FROM_LIST(Packet, PacketList);
  1236. ASSERT((Packet->Flags & NET_PACKET_FLAG_MULTICAST) == 0);
  1237. NetlinkpProcessReceivedSocketData(Link,
  1238. Socket,
  1239. Packet,
  1240. SourceAddress,
  1241. DestinationAddress);
  1242. }
  1243. ProcessReceivedPacketsEnd:
  1244. if (Socket != NULL) {
  1245. IoSocketReleaseReference(&(Socket->KernelSocket));
  1246. }
  1247. return;
  1248. }
  1249. VOID
  1250. NetlinkpProcessReceivedSocketData (
  1251. PNET_LINK Link,
  1252. PNET_SOCKET Socket,
  1253. PNET_PACKET_BUFFER Packet,
  1254. PNETWORK_ADDRESS SourceAddress,
  1255. PNETWORK_ADDRESS DestinationAddress
  1256. )
  1257. /*++
  1258. Routine Description:
  1259. This routine handles received packet processing for a netlink socket.
  1260. Arguments:
  1261. Link - Supplies a pointer to the network link that received the packet.
  1262. Socket - Supplies a pointer to the socket that received the packet.
  1263. Packet - Supplies a pointer to a structure describing the incoming packet.
  1264. Use of this structure depends on its flags. If it is a multicast
  1265. packet, then it cannot be modified by this routine. Otherwise it can
  1266. be used as scratch space and modified.
  1267. SourceAddress - Supplies a pointer to the source (remote) address that the
  1268. packet originated from. This memory will not be referenced once the
  1269. function returns, it can be stack allocated.
  1270. DestinationAddress - Supplies a pointer to the destination (local) address
  1271. that the packet is heading to. This memory will not be referenced once
  1272. the function returns, it can be stack allocated.
  1273. Return Value:
  1274. None.
  1275. --*/
  1276. {
  1277. PNET_PROTOCOL_ENTRY Protocol;
  1278. //
  1279. // Netlink handles kernel sockets differently in order to reduce code
  1280. // duplication for error handling and message acknowledgement.
  1281. //
  1282. if ((Socket->Flags & NET_SOCKET_FLAG_KERNEL) != 0) {
  1283. NetlinkpProcessReceivedKernelData(Link,
  1284. Socket,
  1285. Packet,
  1286. SourceAddress,
  1287. DestinationAddress);
  1288. } else {
  1289. Protocol = Socket->Protocol;
  1290. Protocol->Interface.ProcessReceivedSocketData(Link,
  1291. Socket,
  1292. Packet,
  1293. SourceAddress,
  1294. DestinationAddress);
  1295. }
  1296. return;
  1297. }
  1298. VOID
  1299. NetlinkpProcessReceivedKernelData (
  1300. PNET_LINK Link,
  1301. PNET_SOCKET Socket,
  1302. PNET_PACKET_BUFFER Packet,
  1303. PNETWORK_ADDRESS SourceAddress,
  1304. PNETWORK_ADDRESS DestinationAddress
  1305. )
  1306. /*++
  1307. Routine Description:
  1308. This routine is handles received packet processing for a kernel socket.
  1309. Arguments:
  1310. Link - Supplies a pointer to the network link that received the packet.
  1311. Socket - Supplies a pointer to the socket that received the packet.
  1312. Packet - Supplies a pointer to a structure describing the incoming packet.
  1313. This structure may be used as a scratch space and this routine will
  1314. release it when it is done.
  1315. SourceAddress - Supplies a pointer to the source (remote) address that the
  1316. packet originated from. This memory will not be referenced once the
  1317. function returns, it can be stack allocated.
  1318. DestinationAddress - Supplies a pointer to the destination (local) address
  1319. that the packet is heading to. This memory will not be referenced once
  1320. the function returns, it can be stack allocated.
  1321. Return Value:
  1322. None.
  1323. --*/
  1324. {
  1325. PNETLINK_HEADER Header;
  1326. ULONG MessageSize;
  1327. ULONG PacketLength;
  1328. PNET_PROTOCOL_PROCESS_RECEIVED_SOCKET_DATA ProcessReceivedSocketData;
  1329. PNET_PROTOCOL_ENTRY Protocol;
  1330. KSTATUS Status;
  1331. Protocol = Socket->Protocol;
  1332. ProcessReceivedSocketData = Protocol->Interface.ProcessReceivedSocketData;
  1333. //
  1334. // Parse the packet for as many netlink messages as can be found, sending
  1335. // each one up to the protocol.
  1336. //
  1337. PacketLength = Packet->FooterOffset - Packet->DataOffset;
  1338. while (PacketLength >= NETLINK_HEADER_LENGTH) {
  1339. Header = Packet->Buffer + Packet->DataOffset;
  1340. Status = STATUS_SUCCESS;
  1341. //
  1342. // Toss any malformed messages that claim to go beyond the end of the
  1343. // packet.
  1344. //
  1345. MessageSize = NETLINK_ALIGN(Header->Length);
  1346. if (MessageSize > PacketLength) {
  1347. MessageSize = PacketLength;
  1348. Status = STATUS_DATA_LENGTH_MISMATCH;
  1349. goto ProcessReceivedKernelDataNextMessage;
  1350. }
  1351. //
  1352. // The kernel only handles requests.
  1353. //
  1354. if ((Header->Flags & NETLINK_HEADER_FLAG_REQUEST) == 0) {
  1355. goto ProcessReceivedKernelDataNextMessage;
  1356. }
  1357. //
  1358. // There is no work to do for standard messages other than replying
  1359. // with an ACK.
  1360. //
  1361. if (Header->Type < NETLINK_MESSAGE_TYPE_PROTOCOL_MINIMUM) {
  1362. goto ProcessReceivedKernelDataNextMessage;
  1363. }
  1364. Packet->FooterOffset = Packet->DataOffset + MessageSize;
  1365. Status = ProcessReceivedSocketData(Link,
  1366. Socket,
  1367. Packet,
  1368. SourceAddress,
  1369. DestinationAddress);
  1370. if (!KSUCCESS(Status)) {
  1371. goto ProcessReceivedKernelDataNextMessage;
  1372. }
  1373. ProcessReceivedKernelDataNextMessage:
  1374. //
  1375. // If this message was not successfully parsed or an ACK was requested,
  1376. // then send back an ACK or a NACK.
  1377. //
  1378. if (!KSUCCESS(Status) ||
  1379. ((Header->Flags & NETLINK_HEADER_FLAG_ACK) != 0)) {
  1380. Packet->FooterOffset = Packet->DataOffset + MessageSize;
  1381. NetlinkpSendAck(Socket, Packet, SourceAddress, Status);
  1382. }
  1383. Packet->DataOffset += MessageSize;
  1384. PacketLength -= MessageSize;
  1385. }
  1386. NetFreeBuffer(Packet);
  1387. return;
  1388. }
  1389. VOID
  1390. NetlinkpSendAck (
  1391. PNET_SOCKET Socket,
  1392. PNET_PACKET_BUFFER Packet,
  1393. PNETWORK_ADDRESS DestinationAddress,
  1394. KSTATUS PacketStatus
  1395. )
  1396. /*++
  1397. Routine Description:
  1398. This routine allocates, packages and sends an acknowledgement message.
  1399. Arguments:
  1400. Socket - Supplies a pointer to the netlink socket over which to send the
  1401. ACK.
  1402. Packet - Supplies a pointer to the network packet that is being
  1403. acknowledged.
  1404. DestinationAddress - Supplies a pointer to the address of the socket that
  1405. is to receive the ACK message.
  1406. PacketStatus - Supplies the error status to send with the ACK.
  1407. Return Value:
  1408. None.
  1409. --*/
  1410. {
  1411. ULONG AckLength;
  1412. PNET_PACKET_BUFFER AckPacket;
  1413. ULONG CopyLength;
  1414. PNETLINK_ERROR_MESSAGE ErrorMessage;
  1415. ULONG HeaderLength;
  1416. PNETLINK_HEADER OriginalHeader;
  1417. ULONG PayloadLength;
  1418. KSTATUS Status;
  1419. //
  1420. // Create the ACK packet with the appropriate error message based on the
  1421. // given status.
  1422. //
  1423. AckPacket = NULL;
  1424. CopyLength = NETLINK_HEADER_LENGTH;
  1425. PayloadLength = sizeof(NETLINK_ERROR_MESSAGE);
  1426. HeaderLength = NETLINK_HEADER_LENGTH;
  1427. if (!KSUCCESS(PacketStatus)) {
  1428. CopyLength = Packet->FooterOffset - Packet->DataOffset;
  1429. PayloadLength += CopyLength - NETLINK_HEADER_LENGTH;
  1430. }
  1431. AckLength = HeaderLength + PayloadLength;
  1432. Status = NetAllocateBuffer(0,
  1433. AckLength,
  1434. 0,
  1435. NULL,
  1436. 0,
  1437. &AckPacket);
  1438. if (!KSUCCESS(Status)) {
  1439. return;
  1440. }
  1441. OriginalHeader = Packet->Buffer + Packet->DataOffset;
  1442. Status = NetlinkAppendHeader(Socket,
  1443. AckPacket,
  1444. PayloadLength,
  1445. OriginalHeader->SequenceNumber,
  1446. NETLINK_MESSAGE_TYPE_ERROR,
  1447. 0);
  1448. if (!KSUCCESS(Status)) {
  1449. goto SendAckEnd;
  1450. }
  1451. ErrorMessage = AckPacket->Buffer + AckPacket->DataOffset;
  1452. ErrorMessage->Error = (INT)PacketStatus;
  1453. RtlCopyMemory(&(ErrorMessage->Header), OriginalHeader, CopyLength);
  1454. AckPacket->DataOffset += PayloadLength;
  1455. //
  1456. // Send the ACK packet back to where the original packet came from.
  1457. //
  1458. Status = NetlinkSendMessage(Socket, AckPacket, DestinationAddress);
  1459. if (!KSUCCESS(Status)) {
  1460. goto SendAckEnd;
  1461. }
  1462. SendAckEnd:
  1463. if (AckPacket != NULL) {
  1464. NetFreeBuffer(AckPacket);
  1465. }
  1466. return;
  1467. }
  1468. VOID
  1469. NetlinkpLeaveMulticastGroup (
  1470. PNET_SOCKET Socket,
  1471. ULONG GroupId,
  1472. BOOL LockHeld
  1473. )
  1474. /*++
  1475. Routine Description:
  1476. This routine removes a socket from a multicast group.
  1477. Arguments:
  1478. Socket - Supplies a pointer to the socket to remove from the group.
  1479. GroupId - Supplies the ID of the multicast group to leave.
  1480. LockHeld - Supplies a boolean indicating whether or not the global
  1481. multicast lock is already held.
  1482. Return Value:
  1483. None.
  1484. --*/
  1485. {
  1486. ULONG GroupIndex;
  1487. ULONG GroupMask;
  1488. PNETLINK_SOCKET NetlinkSocket;
  1489. NetlinkSocket = (PNETLINK_SOCKET)Socket;
  1490. if (GroupId >= NETLINK_SOCKET_BITMAP_GROUP_ID_COUNT(NetlinkSocket)) {
  1491. return;
  1492. }
  1493. GroupIndex = NETLINK_SOCKET_BITMAP_INDEX(GroupId);
  1494. GroupMask = NETLINK_SOCKET_BITMAP_MASK(GroupId);
  1495. if (LockHeld == FALSE) {
  1496. KeAcquireSharedExclusiveLockExclusive(NetlinkMulticastLock);
  1497. }
  1498. if ((NetlinkSocket->MulticastBitmap[GroupIndex] & GroupMask) != 0) {
  1499. NetlinkSocket->MulticastBitmap[GroupIndex] &= ~GroupMask;
  1500. NetlinkSocket->MulticastGroupCount -= 1;
  1501. if (NetlinkSocket->MulticastGroupCount == 0) {
  1502. LIST_REMOVE(&(NetlinkSocket->MulticastListEntry));
  1503. NetlinkSocket->MulticastListEntry.Next = NULL;
  1504. }
  1505. }
  1506. if (LockHeld == FALSE) {
  1507. KeReleaseSharedExclusiveLockExclusive(NetlinkMulticastLock);
  1508. }
  1509. return;
  1510. }