ip4.c 69 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643
  1. /*++
  2. Copyright (c) 2013 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. ip4.c
  5. Abstract:
  6. This module implements support for the Internet Protocol version 4 (IPv4).
  7. Author:
  8. Evan Green 4-Apr-2013
  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/ip4.h>
  25. //
  26. // ---------------------------------------------------------------- Definitions
  27. //
  28. //
  29. // Define the maximum size of an IPv4 address string, including the null
  30. // terminator. The longest string would look something like
  31. // "255.255.255.255:65535"
  32. //
  33. #define IP4_MAX_ADDRESS_STRING 22
  34. //
  35. // Define the timeout for a set if IPv4 fragments, in microseconds.
  36. //
  37. #define IP4_FRAGMENT_TIMEOUT (15 * MICROSECONDS_PER_SECOND)
  38. //
  39. // Define the byte alignment for IPv4 fragment lengths.
  40. //
  41. #define IP4_FRAGMENT_ALIGNMENT 8
  42. //
  43. // Define the maximum number of fragments that can be stored at any one time.
  44. //
  45. #define IP4_MAX_FRAGMENT_COUNT 1000
  46. //
  47. // --------------------------------------------------------------------- Macros
  48. //
  49. //
  50. // Define macros to convert between fragment bytes and fragment offset units.
  51. //
  52. #define IP4_CONVERT_OFFSET_TO_BYTES(_Offset) (_Offset << 3)
  53. #define IP4_CONVERT_BYTES_TO_OFFSET(_Bytes) (_Bytes >> 3)
  54. //
  55. // ------------------------------------------------------ Data Type Definitions
  56. //
  57. /*++
  58. Structure Description:
  59. This structure defines an IPv4 fragmented packet node which represents one
  60. IPv4 packet that is in the process of being reassembled from its various
  61. fragments.
  62. Members:
  63. Node - Stores the Red-Black tree node information for this IPv4 packet.
  64. FargmentListHead - Stores the head of the list of fragments being
  65. reassembled into a packet.
  66. Timeout - Stores the time, in time ticks, at which the the attempt to
  67. reassemble this packet will be abandoned.
  68. LocalAddress - Stores the local IPv4 address for the packet.
  69. RemoteAddress - Stores the remote IPv4 address for the packet.
  70. Protocol - Stores the IPv4 protocol for which this packet is destined.
  71. Identification - Stores the IPv4 unique identification for the packet.
  72. --*/
  73. typedef struct _IP4_FRAGMENTED_PACKET_NODE {
  74. RED_BLACK_TREE_NODE Node;
  75. LIST_ENTRY FragmentListHead;
  76. ULONGLONG Timeout;
  77. ULONG LocalAddress;
  78. ULONG RemoteAddress;
  79. USHORT Protocol;
  80. USHORT Identification;
  81. } IP4_FRAGMENTED_PACKET_NODE, *PIP4_FRAGMENTED_PACKET_NODE;
  82. /*++
  83. Structure Description:
  84. This structure defines a fragment entry for an IPv4 packet. This entry
  85. may contain data from one or more fragments that have already been
  86. processed.
  87. Members:
  88. ListEntry - Stores pointer to the next and previous fragments in the list.
  89. Length - Stores the length, in bytes, of this fragment.
  90. Offset - Stores the offset, in 8 byte blocks, from the beginning of the
  91. packet.
  92. LastFragment - Stores a boolean indicating whether or not this fragment
  93. contains the last chunk of data for the packet.
  94. --*/
  95. typedef struct _IP4_FRAGMENT_ENTRY {
  96. LIST_ENTRY ListEntry;
  97. ULONG Length;
  98. USHORT Offset;
  99. BOOL LastFragment;
  100. } IP4_FRAGMENT_ENTRY, *PIP4_FRAGMENT_ENTRY;
  101. //
  102. // ----------------------------------------------- Internal Function Prototypes
  103. //
  104. KSTATUS
  105. NetpIp4InitializeLink (
  106. PNET_LINK Link
  107. );
  108. VOID
  109. NetpIp4DestroyLink (
  110. PNET_LINK Link
  111. );
  112. KSTATUS
  113. NetpIp4InitializeSocket (
  114. PNET_PROTOCOL_ENTRY ProtocolEntry,
  115. PNET_NETWORK_ENTRY NetworkEntry,
  116. ULONG NetworkProtocol,
  117. PNET_SOCKET NewSocket
  118. );
  119. KSTATUS
  120. NetpIp4BindToAddress (
  121. PNET_SOCKET Socket,
  122. PNET_LINK Link,
  123. PNETWORK_ADDRESS Address
  124. );
  125. KSTATUS
  126. NetpIp4Listen (
  127. PNET_SOCKET Socket
  128. );
  129. KSTATUS
  130. NetpIp4Connect (
  131. PNET_SOCKET Socket,
  132. PNETWORK_ADDRESS Address
  133. );
  134. KSTATUS
  135. NetpIp4Disconnect (
  136. PNET_SOCKET Socket
  137. );
  138. KSTATUS
  139. NetpIp4Close (
  140. PNET_SOCKET Socket
  141. );
  142. KSTATUS
  143. NetpIp4Send (
  144. PNET_SOCKET Socket,
  145. PNETWORK_ADDRESS Destination,
  146. PNET_SOCKET_LINK_OVERRIDE LinkOverride,
  147. PNET_PACKET_LIST PacketList
  148. );
  149. VOID
  150. NetpIp4ProcessReceivedData (
  151. PNET_LINK Link,
  152. PNET_PACKET_BUFFER Packet
  153. );
  154. ULONG
  155. NetpIp4PrintAddress (
  156. PNETWORK_ADDRESS Address,
  157. PSTR Buffer,
  158. ULONG BufferLength
  159. );
  160. KSTATUS
  161. NetpIp4GetSetInformation (
  162. PNET_SOCKET Socket,
  163. SOCKET_INFORMATION_TYPE InformationType,
  164. UINTN SocketOption,
  165. PVOID Data,
  166. PUINTN DataSize,
  167. BOOL Set
  168. );
  169. USHORT
  170. NetpIp4ChecksumData (
  171. PVOID Data,
  172. ULONG Length
  173. );
  174. KSTATUS
  175. NetpIp4TranslateNetworkAddress (
  176. PNETWORK_ADDRESS NetworkAddress,
  177. PNET_LINK Link,
  178. PNET_LINK_ADDRESS_ENTRY LinkAddress,
  179. PNETWORK_ADDRESS PhysicalAddress
  180. );
  181. PNET_PACKET_BUFFER
  182. NetpIp4ProcessPacketFragment (
  183. PNET_LINK Link,
  184. PNET_PACKET_BUFFER PacketFragment
  185. );
  186. COMPARISON_RESULT
  187. NetpIp4CompareFragmentedPacketEntries (
  188. PRED_BLACK_TREE Tree,
  189. PRED_BLACK_TREE_NODE FirstNode,
  190. PRED_BLACK_TREE_NODE SecondNode
  191. );
  192. VOID
  193. NetpIp4RemoveFragmentedPackets (
  194. PNET_SOCKET Socket
  195. );
  196. PIP4_FRAGMENTED_PACKET_NODE
  197. NetpIp4CreateFragmentedPacketNode (
  198. PIP4_HEADER Header
  199. );
  200. VOID
  201. NetpIp4DestroyFragmentedPacketNode (
  202. PIP4_FRAGMENTED_PACKET_NODE PacketNode
  203. );
  204. //
  205. // -------------------------------------------------------------------- Globals
  206. //
  207. BOOL NetIp4DebugPrintPackets = FALSE;
  208. //
  209. // Store values used to manage fragmented IPv4 packets.
  210. //
  211. ULONG NetIp4FragmentCount;
  212. PQUEUED_LOCK NetIp4FragmentedPacketLock;
  213. RED_BLACK_TREE NetIp4FragmentedPacketTree;
  214. //
  215. // ------------------------------------------------------------------ Functions
  216. //
  217. VOID
  218. NetpIp4Initialize (
  219. VOID
  220. )
  221. /*++
  222. Routine Description:
  223. This routine initializes support for IPv4 packets.
  224. Arguments:
  225. None.
  226. Return Value:
  227. None.
  228. --*/
  229. {
  230. NET_NETWORK_ENTRY NetworkEntry;
  231. KSTATUS Status;
  232. //
  233. // Initialize the IPv4 fragmented packet tree.
  234. //
  235. RtlRedBlackTreeInitialize(&NetIp4FragmentedPacketTree,
  236. 0,
  237. NetpIp4CompareFragmentedPacketEntries);
  238. NetIp4FragmentCount = 0;
  239. NetIp4FragmentedPacketLock = KeCreateQueuedLock();
  240. if (NetIp4FragmentedPacketLock == NULL) {
  241. ASSERT(FALSE);
  242. goto Ip4InitializeEnd;
  243. }
  244. //
  245. // Register the IPv4 handlers with the core networking library.
  246. //
  247. NetworkEntry.Domain = NetDomainIp4;
  248. NetworkEntry.ParentProtocolNumber = IP4_PROTOCOL_NUMBER;
  249. NetworkEntry.Interface.InitializeLink = NetpIp4InitializeLink;
  250. NetworkEntry.Interface.DestroyLink = NetpIp4DestroyLink;
  251. NetworkEntry.Interface.InitializeSocket = NetpIp4InitializeSocket;
  252. NetworkEntry.Interface.BindToAddress = NetpIp4BindToAddress;
  253. NetworkEntry.Interface.Listen = NetpIp4Listen;
  254. NetworkEntry.Interface.Connect = NetpIp4Connect;
  255. NetworkEntry.Interface.Disconnect = NetpIp4Disconnect;
  256. NetworkEntry.Interface.Close = NetpIp4Close;
  257. NetworkEntry.Interface.Send = NetpIp4Send;
  258. NetworkEntry.Interface.ProcessReceivedData = NetpIp4ProcessReceivedData;
  259. NetworkEntry.Interface.PrintAddress = NetpIp4PrintAddress;
  260. NetworkEntry.Interface.GetSetInformation = NetpIp4GetSetInformation;
  261. Status = NetRegisterNetworkLayer(&NetworkEntry, NULL);
  262. if (!KSUCCESS(Status)) {
  263. ASSERT(FALSE);
  264. }
  265. Ip4InitializeEnd:
  266. return;
  267. }
  268. KSTATUS
  269. NetpIp4InitializeLink (
  270. PNET_LINK Link
  271. )
  272. /*++
  273. Routine Description:
  274. This routine initializes any pieces of information needed by the network
  275. layer for a new link.
  276. Arguments:
  277. Link - Supplies a pointer to the new link.
  278. Return Value:
  279. Status code.
  280. --*/
  281. {
  282. PNET_LINK_ADDRESS_ENTRY AddressEntry;
  283. IP4_ADDRESS InitialAddress;
  284. KSTATUS Status;
  285. //
  286. // A dummy address with only the network filled in is required, otherwise
  287. // this link entry cannot be bound to in order to establish the real
  288. // address.
  289. //
  290. RtlZeroMemory((PNETWORK_ADDRESS)&InitialAddress, sizeof(NETWORK_ADDRESS));
  291. InitialAddress.Domain = NetDomainIp4;
  292. InitialAddress.Address = 0;
  293. Status = NetCreateLinkAddressEntry(Link,
  294. (PNETWORK_ADDRESS)&InitialAddress,
  295. NULL,
  296. NULL,
  297. FALSE,
  298. &AddressEntry);
  299. if (!KSUCCESS(Status)) {
  300. goto Ip4InitializeLinkEnd;
  301. }
  302. Ip4InitializeLinkEnd:
  303. if (!KSUCCESS(Status)) {
  304. if (AddressEntry != NULL) {
  305. NetDestroyLinkAddressEntry(Link, AddressEntry);
  306. }
  307. }
  308. return Status;
  309. }
  310. VOID
  311. NetpIp4DestroyLink (
  312. PNET_LINK Link
  313. )
  314. /*++
  315. Routine Description:
  316. This routine allows the network layer to tear down any state before a link
  317. is destroyed.
  318. Arguments:
  319. Link - Supplies a pointer to the dying link.
  320. Return Value:
  321. None.
  322. --*/
  323. {
  324. return;
  325. }
  326. KSTATUS
  327. NetpIp4InitializeSocket (
  328. PNET_PROTOCOL_ENTRY ProtocolEntry,
  329. PNET_NETWORK_ENTRY NetworkEntry,
  330. ULONG NetworkProtocol,
  331. PNET_SOCKET NewSocket
  332. )
  333. /*++
  334. Routine Description:
  335. This routine initializes any pieces of information needed by the network
  336. layer for the socket. The core networking library will fill in the common
  337. header when this routine returns.
  338. Arguments:
  339. ProtocolEntry - Supplies a pointer to the protocol information.
  340. NetworkEntry - Supplies a pointer to the network information.
  341. NetworkProtocol - Supplies the raw protocol value for this socket used on
  342. the network. This value is network specific.
  343. NewSocket - Supplies a pointer to the new socket. The network layer should
  344. at the very least add any needed header size.
  345. Return Value:
  346. Status code.
  347. --*/
  348. {
  349. ULONG MaxPacketSize;
  350. //
  351. // If this is coming from the raw protocol and the network protocol is the
  352. // raw, wildcard protocol, then this socket automatically gets the headers
  353. // included flag.
  354. //
  355. if ((ProtocolEntry->Type == NetSocketRaw) &&
  356. (NetworkProtocol == SOCKET_INTERNET_PROTOCOL_RAW)) {
  357. RtlAtomicOr32(&(NewSocket->Flags),
  358. NET_SOCKET_FLAG_NETWORK_HEADER_INCLUDED);
  359. }
  360. //
  361. // Determine if the maximum IPv4 packet size plus all existing headers and
  362. // footers is less than the current maximum packet size. If so, truncate
  363. // the maximum packet size. Note that the IPv4 maximum packet size includes
  364. // the size of the header.
  365. //
  366. MaxPacketSize = NewSocket->PacketSizeInformation.HeaderSize +
  367. IP4_MAX_PACKET_SIZE +
  368. NewSocket->PacketSizeInformation.FooterSize;
  369. if (NewSocket->PacketSizeInformation.MaxPacketSize > MaxPacketSize) {
  370. NewSocket->PacketSizeInformation.MaxPacketSize = MaxPacketSize;
  371. }
  372. //
  373. // Add the IPv4 header size for higher layers to perform the same
  374. // truncation procedure. Skip this for raw sockets using the raw protocol;
  375. // the must always supply an IPv4 header, so it doesn't make sense to add
  376. // it to the header size. It comes in the data packet.
  377. //
  378. if ((ProtocolEntry->Type != NetSocketRaw) ||
  379. (NetworkProtocol != SOCKET_INTERNET_PROTOCOL_RAW)) {
  380. NewSocket->PacketSizeInformation.HeaderSize += sizeof(IP4_HEADER);
  381. }
  382. NewSocket->HopLimit = IP4_INITIAL_TIME_TO_LIVE;
  383. return STATUS_SUCCESS;
  384. }
  385. KSTATUS
  386. NetpIp4BindToAddress (
  387. PNET_SOCKET Socket,
  388. PNET_LINK Link,
  389. PNETWORK_ADDRESS Address
  390. )
  391. /*++
  392. Routine Description:
  393. This routine binds the given socket to the specified network address.
  394. Arguments:
  395. Socket - Supplies a pointer to the socket to bind.
  396. Link - Supplies an optional pointer to a link to bind to.
  397. Address - Supplies a pointer to the address to bind the socket to.
  398. Return Value:
  399. Status code.
  400. --*/
  401. {
  402. BOOL AnyAddress;
  403. NET_SOCKET_BINDING_TYPE BindingType;
  404. PIP4_ADDRESS Ip4Address;
  405. NET_LINK_LOCAL_ADDRESS LocalInformation;
  406. ULONG Port;
  407. KSTATUS Status;
  408. Ip4Address = (PIP4_ADDRESS)Address;
  409. LocalInformation.Link = NULL;
  410. //
  411. // If a specific link is given, try to find the given address in that link.
  412. //
  413. if (Link != NULL) {
  414. if (Ip4Address->Address == 0) {
  415. BindingType = SocketUnbound;
  416. AnyAddress = TRUE;
  417. } else {
  418. BindingType = SocketLocallyBound;
  419. AnyAddress = FALSE;
  420. }
  421. Port = Address->Port;
  422. Address->Port = 0;
  423. Status = NetFindLinkForLocalAddress(Address,
  424. AnyAddress,
  425. Link,
  426. &LocalInformation);
  427. Address->Port = Port;
  428. if (!KSUCCESS(Status)) {
  429. goto Ip4BindToAddressEnd;
  430. }
  431. LocalInformation.LocalAddress.Port = Port;
  432. //
  433. // No specific link was passed.
  434. //
  435. } else {
  436. //
  437. // If the address is not the "unbound" address, then look for the link
  438. // that owns this address.
  439. //
  440. if (Ip4Address->Address != 0) {
  441. BindingType = SocketLocallyBound;
  442. Port = Address->Port;
  443. Address->Port = 0;
  444. Status = NetFindLinkForLocalAddress(Address,
  445. FALSE,
  446. NULL,
  447. &LocalInformation);
  448. Address->Port = Port;
  449. if (!KSUCCESS(Status)) {
  450. goto Ip4BindToAddressEnd;
  451. }
  452. LocalInformation.LocalAddress.Port = Port;
  453. //
  454. // No link nor address was passed, this is a generic bind to a port on
  455. // any address.
  456. //
  457. } else {
  458. BindingType = SocketUnbound;
  459. LocalInformation.Link = NULL;
  460. LocalInformation.LinkAddress = NULL;
  461. RtlCopyMemory(&(LocalInformation.LocalAddress),
  462. Address,
  463. sizeof(NETWORK_ADDRESS));
  464. }
  465. }
  466. //
  467. // Bind the socket to the local address. The socket remains inactive,
  468. // unable to receive packets.
  469. //
  470. Status = NetBindSocket(Socket, BindingType, &LocalInformation, NULL, 0);
  471. if (!KSUCCESS(Status)) {
  472. goto Ip4BindToAddressEnd;
  473. }
  474. Status = STATUS_SUCCESS;
  475. Ip4BindToAddressEnd:
  476. if (LocalInformation.Link != NULL) {
  477. NetLinkReleaseReference(LocalInformation.Link);
  478. }
  479. return Status;
  480. }
  481. KSTATUS
  482. NetpIp4Listen (
  483. PNET_SOCKET Socket
  484. )
  485. /*++
  486. Routine Description:
  487. This routine adds a bound socket to the list of listening sockets,
  488. officially allowing clients to attempt to connect to it.
  489. Arguments:
  490. Socket - Supplies a pointer to the socket to mark as listning.
  491. Return Value:
  492. Status code.
  493. --*/
  494. {
  495. NETWORK_ADDRESS LocalAddress;
  496. KSTATUS Status;
  497. RtlZeroMemory(&(Socket->RemoteAddress), sizeof(NETWORK_ADDRESS));
  498. if (Socket->BindingType == SocketBindingInvalid) {
  499. RtlZeroMemory(&LocalAddress, sizeof(NETWORK_ADDRESS));
  500. LocalAddress.Domain = NetDomainIp4;
  501. Status = NetpIp4BindToAddress(Socket, NULL, &LocalAddress);
  502. if (!KSUCCESS(Status)) {
  503. goto Ip4ListenEnd;
  504. }
  505. }
  506. Status = NetActivateSocket(Socket);
  507. if (!KSUCCESS(Status)) {
  508. goto Ip4ListenEnd;
  509. }
  510. Ip4ListenEnd:
  511. return Status;
  512. }
  513. KSTATUS
  514. NetpIp4Connect (
  515. PNET_SOCKET Socket,
  516. PNETWORK_ADDRESS Address
  517. )
  518. /*++
  519. Routine Description:
  520. This routine connects the given socket to a specific remote address. It
  521. will implicitly bind the socket if it is not yet locally bound.
  522. Arguments:
  523. Socket - Supplies a pointer to the socket to use for the connection.
  524. Address - Supplies a pointer to the remote address to bind this socket to.
  525. Return Value:
  526. Status code.
  527. --*/
  528. {
  529. ULONG Flags;
  530. KSTATUS Status;
  531. //
  532. // Fully bind the socket and activate it. It's ready to receive.
  533. //
  534. Flags = NET_SOCKET_BINDING_FLAG_ACTIVATE;
  535. Status = NetBindSocket(Socket, SocketFullyBound, NULL, Address, Flags);
  536. if (!KSUCCESS(Status)) {
  537. goto Ip4ConnectEnd;
  538. }
  539. Status = STATUS_SUCCESS;
  540. Ip4ConnectEnd:
  541. return Status;
  542. }
  543. KSTATUS
  544. NetpIp4Disconnect (
  545. PNET_SOCKET Socket
  546. )
  547. /*++
  548. Routine Description:
  549. This routine will disconnect the given socket from its remote address.
  550. Arguments:
  551. Socket - Supplies a pointer to the socket to disconnect.
  552. Return Value:
  553. Status code.
  554. --*/
  555. {
  556. KSTATUS Status;
  557. //
  558. // Roll the fully bound socket back to the locally bound state.
  559. //
  560. Status = NetDisconnectSocket(Socket);
  561. if (!KSUCCESS(Status)) {
  562. goto Ip4DisconnectEnd;
  563. }
  564. Status = STATUS_SUCCESS;
  565. Ip4DisconnectEnd:
  566. return Status;
  567. }
  568. KSTATUS
  569. NetpIp4Close (
  570. PNET_SOCKET Socket
  571. )
  572. /*++
  573. Routine Description:
  574. This routine closes a socket connection.
  575. Arguments:
  576. Socket - Supplies a pointer to the socket to shut down.
  577. Return Value:
  578. Status code.
  579. --*/
  580. {
  581. //
  582. // Deactivate the socket. This will most likely release a reference. There
  583. // should be at least one more sitting around.
  584. //
  585. ASSERT(Socket->KernelSocket.ReferenceCount > 1);
  586. NetDeactivateSocket(Socket);
  587. //
  588. // Now that the socket is deactiviated, destroy any pending fragments.
  589. //
  590. if (Socket->LocalAddress.Domain == NetDomainIp4) {
  591. KeAcquireQueuedLock(NetIp4FragmentedPacketLock);
  592. NetpIp4RemoveFragmentedPackets(Socket);
  593. KeReleaseQueuedLock(NetIp4FragmentedPacketLock);
  594. }
  595. return STATUS_SUCCESS;
  596. }
  597. KSTATUS
  598. NetpIp4Send (
  599. PNET_SOCKET Socket,
  600. PNETWORK_ADDRESS Destination,
  601. PNET_SOCKET_LINK_OVERRIDE LinkOverride,
  602. PNET_PACKET_LIST PacketList
  603. )
  604. /*++
  605. Routine Description:
  606. This routine sends data through the network.
  607. Arguments:
  608. Socket - Supplies a pointer to the socket to send the data to.
  609. Destination - Supplies a pointer to the network address to send to.
  610. LinkOverride - Supplies an optional pointer to a structure that contains
  611. all the necessary information to send data out a link on behalf
  612. of the given socket.
  613. PacketList - Supplies a pointer to a list of network packets to send. Data
  614. in these packets may be modified by this routine, but must not be used
  615. once this routine returns.
  616. Return Value:
  617. Status code. It is assumed that either all packets are submitted (if
  618. success is returned) or none of the packets were submitted (if a failing
  619. status is returned).
  620. --*/
  621. {
  622. ULONG BytesCompleted;
  623. ULONG BytesRemaining;
  624. USHORT Checksum;
  625. PLIST_ENTRY CurrentEntry;
  626. ULONG FooterSize;
  627. PNET_PACKET_BUFFER Fragment;
  628. ULONG FragmentLength;
  629. USHORT FragmentOffset;
  630. PIP4_HEADER Header;
  631. ULONG HeaderSize;
  632. PNET_LINK Link;
  633. PNET_LINK_ADDRESS_ENTRY LinkAddress;
  634. PIP4_ADDRESS LocalAddress;
  635. ULONG MaxFragmentLength;
  636. ULONG MaxPacketSize;
  637. PNET_PACKET_BUFFER Packet;
  638. PVOID PacketBuffer;
  639. PNETWORK_ADDRESS PhysicalNetworkAddress;
  640. NETWORK_ADDRESS PhysicalNetworkAddressBuffer;
  641. PIP4_ADDRESS RemoteAddress;
  642. PNET_DATA_LINK_SEND Send;
  643. PNETWORK_ADDRESS Source;
  644. KSTATUS Status;
  645. ULONG TotalLength;
  646. ASSERT((Socket->KernelSocket.Type == NetSocketRaw) ||
  647. (Socket->KernelSocket.Protocol ==
  648. Socket->Protocol->ParentProtocolNumber));
  649. //
  650. // If an override was supplied, prefer that link and link address.
  651. //
  652. if (LinkOverride != NULL) {
  653. Link = LinkOverride->LinkInformation.Link;
  654. LinkAddress = LinkOverride->LinkInformation.LinkAddress;
  655. MaxPacketSize = LinkOverride->PacketSizeInformation.MaxPacketSize;
  656. Source = &(LinkOverride->LinkInformation.LocalAddress);
  657. //
  658. // Otherwise use the socket's information.
  659. //
  660. } else {
  661. Link = Socket->Link;
  662. LinkAddress = Socket->LinkAddress;
  663. MaxPacketSize = Socket->PacketSizeInformation.MaxPacketSize;
  664. Source = &(Socket->LocalAddress);
  665. }
  666. LocalAddress = (PIP4_ADDRESS)Source;
  667. RemoteAddress = (PIP4_ADDRESS)Destination;
  668. //
  669. // There better be a link and link address.
  670. //
  671. ASSERT((Link != NULL) && (LinkAddress != NULL));
  672. //
  673. // Sending to the broadcast address must be specifically requested through
  674. // socket options.
  675. //
  676. if ((RemoteAddress->Address == IP4_BROADCAST_ADDRESS) &&
  677. ((Socket->Flags & NET_SOCKET_FLAG_BROADCAST_ENABLED) == 0)) {
  678. Status = STATUS_ACCESS_DENIED;
  679. goto Ip4SendEnd;
  680. }
  681. //
  682. // Figure out the physical network address for the given IP destination
  683. // address. This answer is the same for every packet. Use the cached
  684. // version in the network socket if it's there and the destination matches
  685. // the remote address in the net socket.
  686. //
  687. PhysicalNetworkAddress = &(Socket->RemotePhysicalAddress);
  688. if ((Destination != &(Socket->RemoteAddress)) ||
  689. (PhysicalNetworkAddress->Domain == NetDomainInvalid)) {
  690. if (Destination != &(Socket->RemoteAddress)) {
  691. PhysicalNetworkAddress = &PhysicalNetworkAddressBuffer;
  692. }
  693. Status = NetpIp4TranslateNetworkAddress(Destination,
  694. Link,
  695. LinkAddress,
  696. PhysicalNetworkAddress);
  697. if (!KSUCCESS(Status)) {
  698. goto Ip4SendEnd;
  699. }
  700. ASSERT(PhysicalNetworkAddress->Domain != NetDomainInvalid);
  701. }
  702. //
  703. // Add the IP4 and Ethernet headers to each packet.
  704. //
  705. CurrentEntry = PacketList->Head.Next;
  706. while (CurrentEntry != &(PacketList->Head)) {
  707. Packet = LIST_VALUE(CurrentEntry, NET_PACKET_BUFFER, ListEntry);
  708. CurrentEntry = CurrentEntry->Next;
  709. //
  710. // If the socket is supposed to include the IP header in its
  711. // packets, but this packet is too large, then fail without sending any
  712. // packets.
  713. //
  714. if ((Packet->DataSize > MaxPacketSize) &&
  715. ((Socket->Flags & NET_SOCKET_FLAG_NETWORK_HEADER_INCLUDED) != 0)) {
  716. Status = STATUS_MESSAGE_TOO_LONG;
  717. goto Ip4SendEnd;
  718. //
  719. // If the current packet's total data size (including all headers and
  720. // footers) is larger than the socket's/link's maximum size, then the
  721. // IP layer needs to break it into multiple fragments.
  722. //
  723. } else if (Packet->DataSize > MaxPacketSize) {
  724. //
  725. // Determine the size of the remaining headers and footers that
  726. // will be added to each fragment. These can be determined from the
  727. // current packet's data offset, total size and footer offset.
  728. //
  729. HeaderSize = Packet->DataOffset;
  730. FooterSize = Packet->DataSize - Packet->FooterOffset;
  731. //
  732. // Determine the maximum size of each fragment based on the headers
  733. // and footers required.
  734. //
  735. MaxFragmentLength = MaxPacketSize - HeaderSize - FooterSize;
  736. MaxFragmentLength = ALIGN_RANGE_DOWN(MaxFragmentLength,
  737. IP4_FRAGMENT_ALIGNMENT);
  738. //
  739. // Iterate over the current packet, breaking it up into multiple
  740. // fragments.
  741. //
  742. PacketBuffer = Packet->Buffer + Packet->DataOffset;
  743. BytesCompleted = 0;
  744. BytesRemaining = Packet->FooterOffset - Packet->DataOffset;
  745. while (BytesRemaining != 0) {
  746. FragmentLength = MaxFragmentLength;
  747. if (FragmentLength > BytesRemaining) {
  748. FragmentLength = BytesRemaining;
  749. }
  750. Status = NetAllocateBuffer(HeaderSize,
  751. FragmentLength,
  752. FooterSize,
  753. Link,
  754. 0,
  755. &Fragment);
  756. if (!KSUCCESS(Status)) {
  757. goto Ip4SendEnd;
  758. }
  759. //
  760. // Copy the data from the packet to the fragment.
  761. //
  762. RtlCopyMemory(Fragment->Buffer + Fragment->DataOffset,
  763. PacketBuffer,
  764. FragmentLength);
  765. //
  766. // Get a pointer to the header, which is right before the data.
  767. //
  768. ASSERT(Fragment->DataOffset > sizeof(IP4_HEADER));
  769. Fragment->DataOffset -= sizeof(IP4_HEADER);
  770. Header = (PIP4_HEADER)(Fragment->Buffer + Fragment->DataOffset);
  771. //
  772. // Fill out that IPv4 header.
  773. //
  774. Header->VersionAndHeaderLength =
  775. IP4_VERSION | (UCHAR)(sizeof(IP4_HEADER) / sizeof(ULONG));
  776. Header->Type = 0;
  777. TotalLength = Fragment->FooterOffset - Fragment->DataOffset;
  778. Header->TotalLength = CPU_TO_NETWORK16(TotalLength);
  779. Header->Identification =
  780. CPU_TO_NETWORK16(Socket->SendPacketCount);
  781. ASSERT(IS_ALIGNED(BytesCompleted, IP4_FRAGMENT_ALIGNMENT) != 0);
  782. FragmentOffset = IP4_CONVERT_BYTES_TO_OFFSET(BytesCompleted);
  783. FragmentOffset &= IP4_FRAGMENT_OFFSET_MASK;
  784. FragmentOffset <<= IP4_FRAGMENT_OFFSET_SHIFT;
  785. if (FragmentLength != BytesRemaining) {
  786. FragmentOffset |= (IP4_FLAG_MORE_FRAGMENTS <<
  787. IP4_FRAGMENT_FLAGS_SHIFT);
  788. }
  789. Header->FragmentOffset = CPU_TO_NETWORK16(FragmentOffset);
  790. Header->TimeToLive = Socket->HopLimit;
  791. ASSERT(Socket->KernelSocket.Protocol !=
  792. SOCKET_INTERNET_PROTOCOL_RAW);
  793. Header->Protocol = Socket->KernelSocket.Protocol;
  794. Header->SourceAddress = LocalAddress->Address;
  795. Header->DestinationAddress = RemoteAddress->Address;
  796. Header->HeaderChecksum = 0;
  797. if ((Link->Properties.ChecksumFlags &
  798. NET_LINK_CHECKSUM_FLAG_TRANSMIT_IP_OFFLOAD) == 0) {
  799. Checksum = NetpIp4ChecksumData((PSHORT)Header,
  800. sizeof(IP4_HEADER));
  801. Header->HeaderChecksum = CPU_TO_NETWORK16(Checksum);
  802. } else {
  803. Fragment->Flags |= NET_PACKET_FLAG_IP_CHECKSUM_OFFLOAD;
  804. }
  805. //
  806. // Add the fragment to the list of packets.
  807. //
  808. NET_INSERT_PACKET_BEFORE(Fragment, Packet, PacketList);
  809. PacketBuffer += FragmentLength;
  810. BytesCompleted += FragmentLength;
  811. BytesRemaining -= FragmentLength;
  812. }
  813. //
  814. // Remove the original packet. It just got fragmented. And move on
  815. // to the next packet ID.
  816. //
  817. Socket->SendPacketCount += 1;
  818. NET_REMOVE_PACKET_FROM_LIST(Packet, PacketList);
  819. NetFreeBuffer(Packet);
  820. continue;
  821. }
  822. //
  823. // Add the IP4 network header unless it is already included.
  824. //
  825. if ((Socket->Flags & NET_SOCKET_FLAG_NETWORK_HEADER_INCLUDED) == 0) {
  826. //
  827. // Get a pointer to the header, which is right before the data.
  828. //
  829. ASSERT(Packet->DataOffset > sizeof(IP4_HEADER));
  830. Packet->DataOffset -= sizeof(IP4_HEADER);
  831. Header = (PIP4_HEADER)(Packet->Buffer + Packet->DataOffset);
  832. //
  833. // Fill out that IPv4 header.
  834. //
  835. Header->VersionAndHeaderLength = IP4_VERSION |
  836. (UCHAR)(sizeof(IP4_HEADER) /
  837. sizeof(ULONG));
  838. Header->Type = 0;
  839. TotalLength = Packet->FooterOffset - Packet->DataOffset;
  840. Header->TotalLength = CPU_TO_NETWORK16(TotalLength);
  841. Header->Identification = CPU_TO_NETWORK16(Socket->SendPacketCount);
  842. Socket->SendPacketCount += 1;
  843. Header->FragmentOffset = 0;
  844. Header->TimeToLive = Socket->HopLimit;
  845. ASSERT(Socket->KernelSocket.Protocol !=
  846. SOCKET_INTERNET_PROTOCOL_RAW);
  847. Header->Protocol = Socket->KernelSocket.Protocol;
  848. Header->SourceAddress = LocalAddress->Address;
  849. Header->DestinationAddress = RemoteAddress->Address;
  850. Header->HeaderChecksum = 0;
  851. if ((Link->Properties.ChecksumFlags &
  852. NET_LINK_CHECKSUM_FLAG_TRANSMIT_IP_OFFLOAD) == 0) {
  853. Checksum = NetpIp4ChecksumData((PVOID)Header,
  854. sizeof(IP4_HEADER));
  855. Header->HeaderChecksum = Checksum;
  856. } else {
  857. Packet->Flags |= NET_PACKET_FLAG_IP_CHECKSUM_OFFLOAD;
  858. }
  859. //
  860. // Otherwise the packet may need to be shifted. Unless this is a raw
  861. // socket using the "raw" protocol, the packet was created thinking
  862. // that the IPv4 header needed to be included by the network layer. The
  863. // flags now indicate that the IPv4 header is included by the caller.
  864. // The packet needs to be properly aligned for the hardware, so it
  865. // needs to be shifted by the IPv4 header size.
  866. //
  867. } else {
  868. ASSERT(Socket->KernelSocket.Type == NetSocketRaw);
  869. //
  870. // This can be skipped if the socket is signed up to use the "raw"
  871. // protocol. The IPv4 header size isn't added to such sockets upon
  872. // initialization.
  873. //
  874. if (Socket->KernelSocket.Protocol != SOCKET_INTERNET_PROTOCOL_RAW) {
  875. ASSERT(Packet->DataOffset > sizeof(IP4_HEADER));
  876. Header = (PIP4_HEADER)(Packet->Buffer +
  877. Packet->DataOffset -
  878. sizeof(IP4_HEADER));
  879. TotalLength = Packet->DataSize - Packet->DataOffset;
  880. RtlCopyMemory(Header,
  881. Packet->Buffer + Packet->DataOffset,
  882. TotalLength);
  883. Packet->DataOffset -= sizeof(IP4_HEADER);
  884. Packet->FooterOffset -= sizeof(IP4_HEADER);
  885. Packet->DataSize -= sizeof(IP4_HEADER);
  886. }
  887. }
  888. }
  889. //
  890. // The packets are all ready to go, send them down the link.
  891. //
  892. Send = Link->DataLinkEntry->Interface.Send;
  893. Status = Send(Link->DataLinkContext,
  894. PacketList,
  895. &(LinkAddress->PhysicalAddress),
  896. PhysicalNetworkAddress,
  897. Socket->Network->ParentProtocolNumber);
  898. if (!KSUCCESS(Status)) {
  899. goto Ip4SendEnd;
  900. }
  901. Status = STATUS_SUCCESS;
  902. Ip4SendEnd:
  903. if (NetIp4DebugPrintPackets != FALSE) {
  904. RtlDebugPrint("Net: IP4 Packet send from ");
  905. NetDebugPrintAddress(Source);
  906. RtlDebugPrint(" to ");
  907. NetDebugPrintAddress(Destination);
  908. RtlDebugPrint(" : %d.\n", Status);
  909. }
  910. return Status;
  911. }
  912. VOID
  913. NetpIp4ProcessReceivedData (
  914. PNET_LINK Link,
  915. PNET_PACKET_BUFFER Packet
  916. )
  917. /*++
  918. Routine Description:
  919. This routine is called to process a received packet.
  920. Arguments:
  921. Link - Supplies a pointer to the link that received the packet.
  922. Packet - Supplies a pointer to a structure describing the incoming packet.
  923. This structure may be used as a scratch space while this routine
  924. executes and the packet travels up the stack, but will not be accessed
  925. after this routine returns.
  926. Return Value:
  927. None. When the function returns, the memory associated with the packet may
  928. be reclaimed and reused.
  929. --*/
  930. {
  931. USHORT ComputedChecksum;
  932. IP4_ADDRESS DestinationAddress;
  933. USHORT FragmentFlags;
  934. USHORT FragmentOffset;
  935. PIP4_HEADER Header;
  936. ULONG HeaderSize;
  937. PNET_PROTOCOL_ENTRY ProtocolEntry;
  938. PNET_PACKET_BUFFER ReassembledPacket;
  939. IP4_ADDRESS SourceAddress;
  940. USHORT TotalLength;
  941. ReassembledPacket = NULL;
  942. Header = (PIP4_HEADER)(Packet->Buffer + Packet->DataOffset);
  943. //
  944. // Check the protocol version and header length.
  945. //
  946. if ((Header->VersionAndHeaderLength & IP4_VERSION_MASK) != IP4_VERSION) {
  947. RtlDebugPrint("Invalid IPv4 version. Byte: 0x%02x.\n",
  948. Header->VersionAndHeaderLength);
  949. goto Ip4ProcessReceivedDataEnd;
  950. }
  951. HeaderSize = (Header->VersionAndHeaderLength & IP4_HEADER_LENGTH_MASK) *
  952. sizeof(ULONG);
  953. if (HeaderSize < sizeof(IP4_HEADER)) {
  954. RtlDebugPrint("Invalid IPv4 header length. Byte: 0x%02x.\n",
  955. Header->VersionAndHeaderLength);
  956. goto Ip4ProcessReceivedDataEnd;
  957. }
  958. //
  959. // Validate the total length field.
  960. //
  961. TotalLength = NETWORK_TO_CPU16(Header->TotalLength);
  962. if (TotalLength > (Packet->FooterOffset - Packet->DataOffset)) {
  963. RtlDebugPrint("Invalid IPv4 total length %d is bigger than packet "
  964. "data, which is only %d bytes large.\n",
  965. TotalLength,
  966. (Packet->FooterOffset - Packet->DataOffset));
  967. goto Ip4ProcessReceivedDataEnd;
  968. }
  969. //
  970. // Validate the header checksum, which with the checksum field should work
  971. // out to zero. Skip this if the checksum was offloaded and valid.
  972. //
  973. if (((Packet->Flags & NET_PACKET_FLAG_IP_CHECKSUM_OFFLOAD) == 0) ||
  974. ((Packet->Flags & NET_PACKET_FLAG_IP_CHECKSUM_FAILED) != 0)) {
  975. ComputedChecksum = NetpIp4ChecksumData((PVOID)Header, HeaderSize);
  976. if (ComputedChecksum != 0) {
  977. RtlDebugPrint("Invalid IPv4 header checksum. Computed checksum: "
  978. "0x%04x, should have been zero.\n",
  979. ComputedChecksum);
  980. goto Ip4ProcessReceivedDataEnd;
  981. }
  982. }
  983. //
  984. // Initialize the network address.
  985. //
  986. RtlZeroMemory(&SourceAddress, sizeof(NETWORK_ADDRESS));
  987. RtlZeroMemory(&DestinationAddress, sizeof(NETWORK_ADDRESS));
  988. SourceAddress.Domain = NetDomainIp4;
  989. SourceAddress.Address = Header->SourceAddress;
  990. DestinationAddress.Domain = NetDomainIp4;
  991. DestinationAddress.Address = Header->DestinationAddress;
  992. //
  993. // Update the packet's size. Raw sockets should get everything at the IPv4
  994. // layer. So, lop any footers beyond the IPv4 packet. IPv4 has no footer
  995. // itself.
  996. //
  997. Packet->FooterOffset = Packet->DataOffset + TotalLength;
  998. //
  999. // If this is part of a fragmented datagram, add it to the mix with hopes
  1000. // of completing the reassembly of the protocol layer packet.
  1001. //
  1002. FragmentOffset = NETWORK_TO_CPU16(Header->FragmentOffset);
  1003. FragmentFlags = (FragmentOffset >> IP4_FRAGMENT_FLAGS_SHIFT) &
  1004. IP4_FRAGMENT_FLAGS_MASK;
  1005. FragmentOffset = (FragmentOffset >> IP4_FRAGMENT_OFFSET_SHIFT) &
  1006. IP4_FRAGMENT_OFFSET_MASK;
  1007. if (((FragmentFlags & IP4_FLAG_MORE_FRAGMENTS) != 0) ||
  1008. (FragmentOffset != 0)) {
  1009. if (NetIp4DebugPrintPackets != FALSE) {
  1010. RtlDebugPrint("IP4: Fragment for protocol %d:\n%20s: ",
  1011. Header->Protocol,
  1012. "LocalAddress");
  1013. NetDebugPrintAddress((PNETWORK_ADDRESS)&DestinationAddress);
  1014. RtlDebugPrint("\n%20s: ", "RemoteAddress");
  1015. NetDebugPrintAddress((PNETWORK_ADDRESS)&SourceAddress);
  1016. RtlDebugPrint("\n%20s: 0x%x\n"
  1017. "%20s: 0x%x\n"
  1018. "%20s: 0x%x\n",
  1019. "ID",
  1020. NETWORK_TO_CPU16(Header->Identification),
  1021. "Offset",
  1022. FragmentOffset,
  1023. "Flags",
  1024. FragmentFlags);
  1025. }
  1026. //
  1027. // If the "do not fragment" flag is also set, skip this fragment.
  1028. //
  1029. if ((FragmentFlags & IP4_FLAG_DO_NOT_FRAGMENT) != 0) {
  1030. goto Ip4ProcessReceivedDataEnd;
  1031. }
  1032. ReassembledPacket = NetpIp4ProcessPacketFragment(Link, Packet);
  1033. if (ReassembledPacket == NULL) {
  1034. goto Ip4ProcessReceivedDataEnd;
  1035. }
  1036. Packet = ReassembledPacket;
  1037. //
  1038. // Update the header information. There is no reason to validate it. It
  1039. // just got created from a trusted source.
  1040. //
  1041. Header = (PIP4_HEADER)(Packet->Buffer + Packet->DataOffset);
  1042. HeaderSize = (Header->VersionAndHeaderLength & IP4_HEADER_LENGTH_MASK) *
  1043. sizeof(ULONG);
  1044. TotalLength = NETWORK_TO_CPU16(Header->TotalLength);
  1045. //
  1046. // Otherwise notify the debugger of a complete packet's arrival.
  1047. //
  1048. } else if (NetIp4DebugPrintPackets != FALSE) {
  1049. RtlDebugPrint("Net: IP4 Packet received from ");
  1050. NetDebugPrintAddress((PNETWORK_ADDRESS)&SourceAddress);
  1051. RtlDebugPrint(" to ");
  1052. NetDebugPrintAddress((PNETWORK_ADDRESS)&DestinationAddress);
  1053. RtlDebugPrint("\n");
  1054. }
  1055. //
  1056. // Give raw sockets a chance to look at the packet.
  1057. //
  1058. NetRawSocketsProcessReceivedData(Link,
  1059. Packet,
  1060. (PNETWORK_ADDRESS)&SourceAddress,
  1061. (PNETWORK_ADDRESS)&DestinationAddress,
  1062. Header->Protocol);
  1063. //
  1064. // Find the local protocol entry for the protocol specified in the header
  1065. // and process the packet.
  1066. //
  1067. ProtocolEntry = NetGetProtocolEntry(Header->Protocol);
  1068. if (ProtocolEntry == NULL) {
  1069. RtlDebugPrint("No protocol found for IPv4 packet protocol number "
  1070. "0x%02x.\n",
  1071. Header->Protocol);
  1072. goto Ip4ProcessReceivedDataEnd;
  1073. }
  1074. //
  1075. // Update the packet's data offset so that it starts at the protocol layer.
  1076. //
  1077. Packet->DataOffset += HeaderSize;
  1078. ProtocolEntry->Interface.ProcessReceivedData(
  1079. Link,
  1080. Packet,
  1081. (PNETWORK_ADDRESS)&SourceAddress,
  1082. (PNETWORK_ADDRESS)&DestinationAddress,
  1083. ProtocolEntry);
  1084. Ip4ProcessReceivedDataEnd:
  1085. if (ReassembledPacket != NULL) {
  1086. NetFreeBuffer(ReassembledPacket);
  1087. }
  1088. return;
  1089. }
  1090. ULONG
  1091. NetpIp4PrintAddress (
  1092. PNETWORK_ADDRESS Address,
  1093. PSTR Buffer,
  1094. ULONG BufferLength
  1095. )
  1096. /*++
  1097. Routine Description:
  1098. This routine is called to convert a network address into a string, or
  1099. determine the length of the buffer needed to convert an address into a
  1100. string.
  1101. Arguments:
  1102. Address - Supplies an optional pointer to a network address to convert to
  1103. a string.
  1104. Buffer - Supplies an optional pointer where the string representation of
  1105. the address will be returned.
  1106. BufferLength - Supplies the length of the supplied buffer, in bytes.
  1107. Return Value:
  1108. Returns the maximum length of any address if no network address is
  1109. supplied.
  1110. Returns the actual length of the network address string if a network address
  1111. was supplied, including the null terminator.
  1112. --*/
  1113. {
  1114. UCHAR Components[4];
  1115. PIP4_ADDRESS Ip4Address;
  1116. ULONG Length;
  1117. if (Address == NULL) {
  1118. return IP4_MAX_ADDRESS_STRING;
  1119. }
  1120. ASSERT(Address->Domain == NetDomainIp4);
  1121. Ip4Address = (PIP4_ADDRESS)Address;
  1122. Components[0] = (UCHAR)(Ip4Address->Address);
  1123. Components[1] = (UCHAR)(Ip4Address->Address >> 8);
  1124. Components[2] = (UCHAR)(Ip4Address->Address >> 16);
  1125. Components[3] = (UCHAR)(Ip4Address->Address >> 24);
  1126. //
  1127. // If the buffer is present, print that bad boy out.
  1128. //
  1129. if (Ip4Address->Port != 0) {
  1130. Length = RtlPrintToString(Buffer,
  1131. BufferLength,
  1132. CharacterEncodingDefault,
  1133. "%d.%d.%d.%d:%d",
  1134. Components[0],
  1135. Components[1],
  1136. Components[2],
  1137. Components[3],
  1138. Ip4Address->Port);
  1139. } else {
  1140. Length = RtlPrintToString(Buffer,
  1141. BufferLength,
  1142. CharacterEncodingDefault,
  1143. "%d.%d.%d.%d",
  1144. Components[0],
  1145. Components[1],
  1146. Components[2],
  1147. Components[3]);
  1148. }
  1149. return Length;
  1150. }
  1151. KSTATUS
  1152. NetpIp4GetSetInformation (
  1153. PNET_SOCKET Socket,
  1154. SOCKET_INFORMATION_TYPE InformationType,
  1155. UINTN Option,
  1156. PVOID Data,
  1157. PUINTN DataSize,
  1158. BOOL Set
  1159. )
  1160. /*++
  1161. Routine Description:
  1162. This routine gets or sets properties of the given socket.
  1163. Arguments:
  1164. Socket - Supplies a pointer to the socket to get or set information for.
  1165. InformationType - Supplies the socket information type category to which
  1166. specified option belongs.
  1167. Option - Supplies the option to get or set, which is specific to the
  1168. information type. The type of this value is generally
  1169. SOCKET_<information_type>_OPTION.
  1170. Data - Supplies a pointer to the data buffer where the data is either
  1171. returned for a get operation or given for a set operation.
  1172. DataSize - Supplies a pointer that on input constains the size of the data
  1173. buffer. On output, this contains the required size of the data buffer.
  1174. Set - Supplies a boolean indicating if this is a get operation (FALSE) or
  1175. a set operation (TRUE).
  1176. Return Value:
  1177. STATUS_SUCCESS on success.
  1178. STATUS_INVALID_PARAMETER if the information type is incorrect.
  1179. STATUS_BUFFER_TOO_SMALL if the data buffer is too small to receive the
  1180. requested option.
  1181. STATUS_NOT_SUPPORTED_BY_PROTOCOL if the socket option is not supported by
  1182. the socket.
  1183. --*/
  1184. {
  1185. ULONG BooleanOption;
  1186. ULONG Flags;
  1187. ULONG IntegerOption;
  1188. SOCKET_IP4_OPTION Ip4Option;
  1189. UINTN RequiredSize;
  1190. PVOID Source;
  1191. KSTATUS Status;
  1192. if (InformationType != SocketInformationIp4) {
  1193. Status = STATUS_INVALID_PARAMETER;
  1194. goto Ip4GetSetInformationEnd;
  1195. }
  1196. RequiredSize = 0;
  1197. Source = NULL;
  1198. Status = STATUS_SUCCESS;
  1199. Ip4Option = (SOCKET_IP4_OPTION)Option;
  1200. switch (Ip4Option) {
  1201. case SocketIp4OptionHeaderIncluded:
  1202. RequiredSize = sizeof(ULONG);
  1203. if (Set != FALSE) {
  1204. //
  1205. // Setting the header included option is only allowed on raw
  1206. // sockets that are not operating on the "raw" network protocol.
  1207. //
  1208. if ((Socket->KernelSocket.Type != NetSocketRaw) ||
  1209. (Socket->KernelSocket.Protocol ==
  1210. SOCKET_INTERNET_PROTOCOL_RAW)) {
  1211. Status = STATUS_NOT_SUPPORTED_BY_PROTOCOL;
  1212. break;
  1213. }
  1214. if (*DataSize < RequiredSize) {
  1215. *DataSize = RequiredSize;
  1216. Status = STATUS_BUFFER_TOO_SMALL;
  1217. break;
  1218. }
  1219. BooleanOption = *((PULONG)Data);
  1220. if (BooleanOption != FALSE) {
  1221. RtlAtomicOr32(&(Socket->Flags),
  1222. NET_SOCKET_FLAG_NETWORK_HEADER_INCLUDED);
  1223. } else {
  1224. RtlAtomicAnd32(&(Socket->Flags),
  1225. ~NET_SOCKET_FLAG_NETWORK_HEADER_INCLUDED);
  1226. }
  1227. } else {
  1228. Source = &BooleanOption;
  1229. BooleanOption = FALSE;
  1230. Flags = Socket->Flags;
  1231. if ((Flags & NET_SOCKET_FLAG_NETWORK_HEADER_INCLUDED) != 0) {
  1232. BooleanOption = TRUE;
  1233. }
  1234. }
  1235. break;
  1236. case SocketIp4OptionTimeToLive:
  1237. RequiredSize = sizeof(ULONG);
  1238. if (Set != FALSE) {
  1239. if (*DataSize < RequiredSize) {
  1240. *DataSize = RequiredSize;
  1241. Status = STATUS_BUFFER_TOO_SMALL;
  1242. break;
  1243. }
  1244. IntegerOption = *((PULONG)Data);
  1245. if (IntegerOption > MAX_UCHAR) {
  1246. Status = STATUS_INVALID_PARAMETER;
  1247. break;
  1248. }
  1249. Socket->HopLimit = (UCHAR)IntegerOption;
  1250. } else {
  1251. Source = &IntegerOption;
  1252. IntegerOption = Socket->HopLimit;
  1253. }
  1254. break;
  1255. case SocketIp4OptionJoinMulticastGroup:
  1256. case SocketIp4OptionLeaveMulticastGroup:
  1257. case SocketIp4OptionMulticastInterface:
  1258. case SocketIp4OptionMulticastTimeToLive:
  1259. case SocketIp4OptionMulticastLoopback:
  1260. //
  1261. // TODO: Implement IPv4 multicast.
  1262. //
  1263. default:
  1264. Status = STATUS_NOT_SUPPORTED_BY_PROTOCOL;
  1265. break;
  1266. }
  1267. if (!KSUCCESS(Status)) {
  1268. goto Ip4GetSetInformationEnd;
  1269. }
  1270. //
  1271. // Truncate all copies for get requests down to the required size and
  1272. // always return the required size on set requests.
  1273. //
  1274. if (*DataSize > RequiredSize) {
  1275. *DataSize = RequiredSize;
  1276. }
  1277. //
  1278. // For get requests, copy the gathered information to the supplied data
  1279. // buffer.
  1280. //
  1281. if (Set == FALSE) {
  1282. ASSERT(Source != NULL);
  1283. RtlCopyMemory(Data, Source, *DataSize);
  1284. //
  1285. // If the copy truncated the data, report that the given buffer was too
  1286. // small. The caller can choose to ignore this if the truncated data is
  1287. // enough.
  1288. //
  1289. if (*DataSize < RequiredSize) {
  1290. *DataSize = RequiredSize;
  1291. Status = STATUS_BUFFER_TOO_SMALL;
  1292. goto Ip4GetSetInformationEnd;
  1293. }
  1294. }
  1295. Ip4GetSetInformationEnd:
  1296. return Status;
  1297. }
  1298. //
  1299. // --------------------------------------------------------- Internal Functions
  1300. //
  1301. USHORT
  1302. NetpIp4ChecksumData (
  1303. PVOID Data,
  1304. ULONG Length
  1305. )
  1306. /*++
  1307. Routine Description:
  1308. This routine checksums a section of data for use in an IP datagram
  1309. checksum and returns it in network byte order.
  1310. Arguments:
  1311. Data - Supplies a pointer to the data to checksum.
  1312. Length - Supplies the number of bytes to checksum. This must be an even
  1313. number.
  1314. Return Value:
  1315. Returns the checksum of the data.
  1316. --*/
  1317. {
  1318. PUCHAR BytePointer;
  1319. PULONG LongPointer;
  1320. ULONG NextValue;
  1321. USHORT ShortOne;
  1322. PUSHORT ShortPointer;
  1323. USHORT ShortTwo;
  1324. ULONG Sum;
  1325. ASSERT((Length & 0x1) == 0);
  1326. Sum = 0;
  1327. LongPointer = (PULONG)Data;
  1328. while (Length >= sizeof(ULONG)) {
  1329. NextValue = *LongPointer;
  1330. LongPointer += 1;
  1331. Sum += NextValue;
  1332. if (Sum < NextValue) {
  1333. Sum += 1;
  1334. }
  1335. Length -= sizeof(ULONG);
  1336. }
  1337. BytePointer = (PUCHAR)LongPointer;
  1338. if (Length == sizeof(USHORT)) {
  1339. ShortPointer = (PUSHORT)BytePointer;
  1340. NextValue = (USHORT)*ShortPointer;
  1341. Sum += NextValue;
  1342. if (Sum < NextValue) {
  1343. Sum += 1;
  1344. }
  1345. }
  1346. //
  1347. // Fold the 32-bit value down to 16-bits.
  1348. //
  1349. ShortOne = (USHORT)Sum;
  1350. ShortTwo = (USHORT)(Sum >> 16);
  1351. ShortTwo += ShortOne;
  1352. if (ShortTwo < ShortOne) {
  1353. ShortTwo += 1;
  1354. }
  1355. return (USHORT)~ShortTwo;
  1356. }
  1357. KSTATUS
  1358. NetpIp4TranslateNetworkAddress (
  1359. PNETWORK_ADDRESS NetworkAddress,
  1360. PNET_LINK Link,
  1361. PNET_LINK_ADDRESS_ENTRY LinkAddress,
  1362. PNETWORK_ADDRESS PhysicalAddress
  1363. )
  1364. /*++
  1365. Routine Description:
  1366. This routine translates a network level address to a physical address.
  1367. Arguments:
  1368. NetworkAddress - Supplies a pointer to the network address to translate.
  1369. Link - Supplies a pointer to the link to use.
  1370. LinkAddress - Supplies a pointer to the link address entry to use for this
  1371. request.
  1372. PhysicalAddress - Supplies a pointer where the corresponding physical
  1373. address for this network address will be returned.
  1374. Return Value:
  1375. Status code.
  1376. --*/
  1377. {
  1378. ULONG BitsDifferentInSubnet;
  1379. NETWORK_ADDRESS DefaultGateway;
  1380. PIP4_ADDRESS Ip4Address;
  1381. PIP4_ADDRESS LocalIpAddress;
  1382. BOOL LockHeld;
  1383. KSTATUS Status;
  1384. PIP4_ADDRESS SubnetMask;
  1385. ASSERT(KeGetRunLevel() == RunLevelLow);
  1386. Ip4Address = (PIP4_ADDRESS)NetworkAddress;
  1387. //
  1388. // This function is very simple: it perform some filtering on known
  1389. // addresses, and if none of those match passes it on to the link layer.
  1390. // Start by checking against 0.0.0.0, an invalid address.
  1391. //
  1392. if (Ip4Address->Address == 0) {
  1393. return STATUS_INVALID_ADDRESS;
  1394. }
  1395. //
  1396. // Check against the broadcast address, which automatically translates to
  1397. // the broadcast link address.
  1398. //
  1399. if (Ip4Address->Address == IP4_BROADCAST_ADDRESS) {
  1400. Link->DataLinkEntry->Interface.GetBroadcastAddress(PhysicalAddress);
  1401. return STATUS_SUCCESS;
  1402. }
  1403. //
  1404. // Make sure the link address is still configured when using it.
  1405. //
  1406. KeAcquireQueuedLock(Link->QueuedLock);
  1407. LockHeld = TRUE;
  1408. if (LinkAddress->Configured == FALSE) {
  1409. Status = STATUS_NO_NETWORK_CONNECTION;
  1410. goto Ip4TranslateNetworkAddressEnd;
  1411. }
  1412. //
  1413. // Check to see if the destination address is in the subnet. If it is,
  1414. // then pass it down directly to get translated. Otherwise, pass down the
  1415. // gateway address.
  1416. //
  1417. LocalIpAddress = (PIP4_ADDRESS)&(LinkAddress->Address);
  1418. SubnetMask = (PIP4_ADDRESS)&(LinkAddress->Subnet);
  1419. //
  1420. // This calculates if any bits are different within the subnet mask. If
  1421. // they are, then the destination is outside of the subnet and should go to
  1422. // the default gateway.
  1423. //
  1424. BitsDifferentInSubnet = ((Ip4Address->Address ^ LocalIpAddress->Address) &
  1425. SubnetMask->Address);
  1426. if (BitsDifferentInSubnet != 0) {
  1427. RtlCopyMemory(&DefaultGateway,
  1428. &(LinkAddress->DefaultGateway),
  1429. sizeof(NETWORK_ADDRESS));
  1430. NetworkAddress = &DefaultGateway;
  1431. }
  1432. KeReleaseQueuedLock(Link->QueuedLock);
  1433. LockHeld = FALSE;
  1434. //
  1435. // Well, it looks like a run-of-the-mill IP address, so pass it on to get
  1436. // translated.
  1437. //
  1438. Status = NetTranslateNetworkAddress(NetworkAddress,
  1439. Link,
  1440. LinkAddress,
  1441. PhysicalAddress);
  1442. Ip4TranslateNetworkAddressEnd:
  1443. if (LockHeld != FALSE) {
  1444. KeReleaseQueuedLock(Link->QueuedLock);
  1445. }
  1446. return Status;
  1447. }
  1448. PNET_PACKET_BUFFER
  1449. NetpIp4ProcessPacketFragment (
  1450. PNET_LINK Link,
  1451. PNET_PACKET_BUFFER PacketFragment
  1452. )
  1453. /*++
  1454. Routine Description:
  1455. This routine processes a fragment of an IPv4 packet. The fragment will get
  1456. added to the list of received fragments. If it is the missing piece and
  1457. completes the original packet, then the reassembled packet will be returned.
  1458. Arguments:
  1459. Link - Supplies a pointer to the owning network link.
  1460. PacketFragment - Supplies a pointer to the IPv4 fragment. This packet
  1461. includes the IPv4 header.
  1462. Return Value:
  1463. Returns a pointer to a reassembled packet if the given fragment completed
  1464. the packet. Returns NULL if the fragment was not enough to form a completed
  1465. packet.
  1466. --*/
  1467. {
  1468. ULONG AllocationSize;
  1469. USHORT Checksum;
  1470. PNET_PACKET_BUFFER CompletedPacket;
  1471. PLIST_ENTRY CurrentEntry;
  1472. PVOID DestinationBuffer;
  1473. PRED_BLACK_TREE_NODE FoundNode;
  1474. USHORT FragmentEnd;
  1475. PIP4_FRAGMENT_ENTRY FragmentEntry;
  1476. USHORT FragmentFlags;
  1477. ULONG FragmentLength;
  1478. USHORT FragmentOffset;
  1479. PIP4_HEADER Header;
  1480. ULONG HeaderSize;
  1481. BOOL JoinNext;
  1482. BOOL JoinPrevious;
  1483. BOOL LastFragment;
  1484. PIP4_FRAGMENT_ENTRY NewFragment;
  1485. PIP4_HEADER NewHeader;
  1486. PIP4_FRAGMENT_ENTRY NextEntry;
  1487. PIP4_FRAGMENTED_PACKET_NODE PacketNode;
  1488. PIP4_FRAGMENT_ENTRY PreviousEntry;
  1489. IP4_FRAGMENTED_PACKET_NODE SearchNode;
  1490. PVOID SourceBuffer;
  1491. USHORT StartingOffset;
  1492. KSTATUS Status;
  1493. ULONG TotalLength;
  1494. CompletedPacket = NULL;
  1495. Header = (PIP4_HEADER)(PacketFragment->Buffer + PacketFragment->DataOffset);
  1496. KeAcquireQueuedLock(NetIp4FragmentedPacketLock);
  1497. //
  1498. // Run through the tree and remove any entries that have expired.
  1499. //
  1500. NetpIp4RemoveFragmentedPackets(NULL);
  1501. //
  1502. // If there are too many packets, then exit.
  1503. //
  1504. if (NetIp4FragmentCount > IP4_MAX_FRAGMENT_COUNT) {
  1505. goto Ip4ProcessPacketFragmentEnd;
  1506. }
  1507. //
  1508. // Now that the tree has been purged of old entries, attempt to find an
  1509. // existing entry for this fragment.
  1510. //
  1511. SearchNode.LocalAddress = Header->DestinationAddress;
  1512. SearchNode.RemoteAddress = Header->SourceAddress;
  1513. SearchNode.Protocol = Header->Protocol;
  1514. SearchNode.Identification = NETWORK_TO_CPU16(Header->Identification);
  1515. FoundNode = RtlRedBlackTreeSearch(&NetIp4FragmentedPacketTree,
  1516. &(SearchNode.Node));
  1517. //
  1518. // If an entry is found the new fragment will be inserted in the existing
  1519. // packt's list of fragments.
  1520. //
  1521. if (FoundNode != NULL) {
  1522. PacketNode = RED_BLACK_TREE_VALUE(FoundNode,
  1523. IP4_FRAGMENTED_PACKET_NODE,
  1524. Node);
  1525. //
  1526. // Otherwise a new fragmented packet needs to be created before the
  1527. // fragment can be inserted.
  1528. //
  1529. } else {
  1530. PacketNode = NetpIp4CreateFragmentedPacketNode(Header);
  1531. if (PacketNode == NULL) {
  1532. goto Ip4ProcessPacketFragmentEnd;
  1533. }
  1534. }
  1535. //
  1536. // Determine the fragment's flags and offset.
  1537. //
  1538. FragmentOffset = NETWORK_TO_CPU16(Header->FragmentOffset);
  1539. FragmentFlags = (FragmentOffset >> IP4_FRAGMENT_FLAGS_SHIFT) &
  1540. IP4_FRAGMENT_FLAGS_MASK;
  1541. FragmentOffset = (FragmentOffset >> IP4_FRAGMENT_OFFSET_SHIFT) &
  1542. IP4_FRAGMENT_OFFSET_MASK;
  1543. ASSERT(((FragmentFlags & IP4_FLAG_MORE_FRAGMENTS) != 0) ||
  1544. ((FragmentOffset & IP4_FRAGMENT_OFFSET_MASK) != 0));
  1545. //
  1546. // Find this fragment's place in the list. It goes before the first entry
  1547. // with a larger offset.
  1548. //
  1549. NextEntry = NULL;
  1550. PreviousEntry = NULL;
  1551. CurrentEntry = PacketNode->FragmentListHead.Next;
  1552. while (CurrentEntry != &(PacketNode->FragmentListHead)) {
  1553. FragmentEntry = LIST_VALUE(CurrentEntry, IP4_FRAGMENT_ENTRY, ListEntry);
  1554. CurrentEntry = CurrentEntry->Next;
  1555. if (FragmentEntry->Offset <= FragmentOffset) {
  1556. PreviousEntry = FragmentEntry;
  1557. continue;
  1558. }
  1559. NextEntry = FragmentEntry;
  1560. break;
  1561. }
  1562. JoinNext = FALSE;
  1563. JoinPrevious = FALSE;
  1564. LastFragment = FALSE;
  1565. NewFragment = NULL;
  1566. StartingOffset = FragmentOffset;
  1567. HeaderSize = (Header->VersionAndHeaderLength & IP4_HEADER_LENGTH_MASK) *
  1568. sizeof(ULONG);
  1569. //
  1570. // Calculate the length of the fragment, not including the IPv4 header.
  1571. // That doesn't need to be saved for a packet fragment. A valid header will
  1572. // be rebuilt once all the fragments are received.
  1573. //
  1574. FragmentLength = PacketFragment->FooterOffset -
  1575. PacketFragment->DataOffset;
  1576. ASSERT(FragmentLength == NETWORK_TO_CPU16(Header->TotalLength));
  1577. FragmentLength -= HeaderSize;
  1578. TotalLength = FragmentLength;
  1579. //
  1580. // If a previous fragment exists, combine it with the new fragment if they
  1581. // are adjacent. Ignore overlapping fragments.
  1582. //
  1583. if (PreviousEntry != NULL) {
  1584. ASSERT(IS_ALIGNED(PreviousEntry->Length, IP4_FRAGMENT_ALIGNMENT));
  1585. FragmentEnd = PreviousEntry->Offset +
  1586. IP4_CONVERT_BYTES_TO_OFFSET(PreviousEntry->Length);
  1587. if (FragmentEnd == FragmentOffset) {
  1588. TotalLength += PreviousEntry->Length;
  1589. ASSERT(PreviousEntry->LastFragment == FALSE);
  1590. StartingOffset = PreviousEntry->Offset;
  1591. JoinPrevious = TRUE;
  1592. } else if (FragmentEnd > FragmentOffset) {
  1593. if (NetIp4DebugPrintPackets != FALSE) {
  1594. RtlDebugPrint("IP4: Ignoring overlapping fragment at offset "
  1595. "0x%x.\n",
  1596. FragmentOffset);
  1597. }
  1598. goto Ip4ProcessPacketFragmentEnd;
  1599. }
  1600. }
  1601. //
  1602. // If a next fragment exists, combine it with the new fragment if they are
  1603. // adjacent. Ignore overlapping fragments.
  1604. //
  1605. if (NextEntry != NULL) {
  1606. ASSERT(IS_ALIGNED(TotalLength, IP4_FRAGMENT_ALIGNMENT));
  1607. FragmentEnd = StartingOffset + IP4_CONVERT_BYTES_TO_OFFSET(TotalLength);
  1608. if (FragmentEnd == NextEntry->Offset) {
  1609. TotalLength += NextEntry->Length;
  1610. LastFragment = NextEntry->LastFragment;
  1611. JoinNext = TRUE;
  1612. } else if (FragmentEnd > NextEntry->Offset) {
  1613. if (NetIp4DebugPrintPackets != FALSE) {
  1614. RtlDebugPrint("IP4: Ignoring overlapping fragment at offset "
  1615. "0x%x.\n",
  1616. FragmentOffset);
  1617. }
  1618. goto Ip4ProcessPacketFragmentEnd;
  1619. }
  1620. }
  1621. //
  1622. // Record if the new fragment is the last fragment.
  1623. //
  1624. if ((FragmentFlags & IP4_FLAG_MORE_FRAGMENTS) == 0) {
  1625. LastFragment = TRUE;
  1626. }
  1627. //
  1628. // If the total length is now greater than the maximum packet size, exit.
  1629. // Something suspicious is up with these fragments.
  1630. //
  1631. if (TotalLength > IP4_MAX_PACKET_SIZE) {
  1632. NetpIp4DestroyFragmentedPacketNode(PacketNode);
  1633. goto Ip4ProcessPacketFragmentEnd;
  1634. }
  1635. //
  1636. // After the coalescing, if the last fragment is included and the starting
  1637. // offset is zero, then the packet is complete.
  1638. //
  1639. FragmentEntry = NULL;
  1640. if ((LastFragment != FALSE) && (StartingOffset == 0)) {
  1641. Status = NetAllocateBuffer(sizeof(IP4_HEADER),
  1642. TotalLength,
  1643. 0,
  1644. Link,
  1645. 0,
  1646. &CompletedPacket);
  1647. if (!KSUCCESS(Status)) {
  1648. ASSERT(CompletedPacket == NULL);
  1649. goto Ip4ProcessPacketFragmentEnd;
  1650. }
  1651. DestinationBuffer = CompletedPacket->Buffer +
  1652. CompletedPacket->DataOffset;
  1653. //
  1654. // Otherwise allocate a new fragment to contain the new fragment and any
  1655. // adjacent fragments.
  1656. //
  1657. } else {
  1658. AllocationSize = sizeof(IP4_FRAGMENT_ENTRY) + TotalLength;
  1659. NewFragment = MmAllocatePagedPool(AllocationSize, IP4_ALLOCATION_TAG);
  1660. if (NewFragment == NULL) {
  1661. goto Ip4ProcessPacketFragmentEnd;
  1662. }
  1663. NewFragment->LastFragment = LastFragment;
  1664. NewFragment->Length = TotalLength;
  1665. NewFragment->Offset = StartingOffset;
  1666. DestinationBuffer = (PVOID)(NewFragment + 1);
  1667. NetIp4FragmentCount += 1;
  1668. }
  1669. //
  1670. // Copy the data into the destination buffer.
  1671. //
  1672. if (JoinPrevious != FALSE) {
  1673. SourceBuffer = (PVOID)(PreviousEntry + 1);
  1674. RtlCopyMemory(DestinationBuffer, SourceBuffer, PreviousEntry->Length);
  1675. DestinationBuffer += PreviousEntry->Length;
  1676. }
  1677. SourceBuffer = PacketFragment->Buffer +
  1678. PacketFragment->DataOffset +
  1679. HeaderSize;
  1680. RtlCopyMemory(DestinationBuffer, SourceBuffer, FragmentLength);
  1681. DestinationBuffer += FragmentLength;
  1682. if (JoinNext != FALSE) {
  1683. SourceBuffer = (PVOID)(NextEntry + 1);
  1684. RtlCopyMemory(DestinationBuffer, SourceBuffer, NextEntry->Length);
  1685. }
  1686. //
  1687. // If the packet was completed, finish up by destroying the packet node and
  1688. // adding an IP4 header.
  1689. //
  1690. if (CompletedPacket != NULL) {
  1691. NetpIp4DestroyFragmentedPacketNode(PacketNode);
  1692. //
  1693. // Fill out the IPv4 header. Raw sockets get an accurate IPv4 header
  1694. // once all the fragments arrive.
  1695. //
  1696. CompletedPacket->DataOffset -= sizeof(IP4_HEADER);
  1697. NewHeader = CompletedPacket->Buffer + CompletedPacket->DataOffset;
  1698. NewHeader->VersionAndHeaderLength = IP4_VERSION |
  1699. (UCHAR)(sizeof(IP4_HEADER) /
  1700. sizeof(ULONG));
  1701. NewHeader->Type = 0;
  1702. TotalLength = CompletedPacket->FooterOffset -
  1703. CompletedPacket->DataOffset;
  1704. NewHeader->TotalLength = CPU_TO_NETWORK16(TotalLength);
  1705. NewHeader->Identification = Header->Identification;
  1706. NewHeader->FragmentOffset = 0;
  1707. NewHeader->TimeToLive = Header->TimeToLive;
  1708. NewHeader->Protocol = Header->Protocol;
  1709. NewHeader->SourceAddress = Header->SourceAddress;
  1710. NewHeader->DestinationAddress = Header->DestinationAddress;
  1711. NewHeader->HeaderChecksum = 0;
  1712. Checksum = NetpIp4ChecksumData((PSHORT)Header, sizeof(IP4_HEADER));
  1713. NewHeader->HeaderChecksum = Checksum;
  1714. //
  1715. // Otherwise insert the new fragment into the appropriate position.
  1716. //
  1717. } else {
  1718. ASSERT(NewFragment != NULL);
  1719. //
  1720. // If a previous entry exists then the entry gets inserted after that
  1721. // entry.
  1722. //
  1723. if (PreviousEntry != NULL) {
  1724. INSERT_AFTER(&(NewFragment->ListEntry),
  1725. &(PreviousEntry->ListEntry));
  1726. //
  1727. // Otherwise the new fragment is first in the list.
  1728. //
  1729. } else {
  1730. ASSERT(((NextEntry != NULL) &&
  1731. (NextEntry->ListEntry.Previous ==
  1732. &(PacketNode->FragmentListHead))) ||
  1733. (LIST_EMPTY(&(PacketNode->FragmentListHead)) != FALSE));
  1734. INSERT_AFTER(&(NewFragment->ListEntry),
  1735. &(PacketNode->FragmentListHead));
  1736. }
  1737. //
  1738. // Remove any entries that were coalesced.
  1739. //
  1740. if (JoinPrevious != FALSE) {
  1741. LIST_REMOVE(&(PreviousEntry->ListEntry));
  1742. MmFreePagedPool(PreviousEntry);
  1743. NetIp4FragmentCount -= 1;
  1744. }
  1745. if (JoinNext != FALSE) {
  1746. LIST_REMOVE(&(NextEntry->ListEntry));
  1747. MmFreePagedPool(NextEntry);
  1748. NetIp4FragmentCount -= 1;
  1749. }
  1750. }
  1751. Ip4ProcessPacketFragmentEnd:
  1752. KeReleaseQueuedLock(NetIp4FragmentedPacketLock);
  1753. return CompletedPacket;
  1754. }
  1755. COMPARISON_RESULT
  1756. NetpIp4CompareFragmentedPacketEntries (
  1757. PRED_BLACK_TREE Tree,
  1758. PRED_BLACK_TREE_NODE FirstNode,
  1759. PRED_BLACK_TREE_NODE SecondNode
  1760. )
  1761. /*++
  1762. Routine Description:
  1763. This routine compares two Red-Black tree nodes, in this case two IPv4
  1764. fragmented packet nodes.
  1765. Arguments:
  1766. Tree - Supplies a pointer to the Red-Black tree that owns both nodes.
  1767. FirstNode - Supplies a pointer to the left side of the comparison.
  1768. SecondNode - Supplies a pointer to the second side of the comparison.
  1769. Return Value:
  1770. Same if the two nodes have the same value.
  1771. Ascending if the first node is less than the second node.
  1772. Descending if the second node is less than the first node.
  1773. --*/
  1774. {
  1775. PIP4_FRAGMENTED_PACKET_NODE FirstPacket;
  1776. PIP4_FRAGMENTED_PACKET_NODE SecondPacket;
  1777. FirstPacket = RED_BLACK_TREE_VALUE(FirstNode,
  1778. IP4_FRAGMENTED_PACKET_NODE,
  1779. Node);
  1780. SecondPacket = RED_BLACK_TREE_VALUE(SecondNode,
  1781. IP4_FRAGMENTED_PACKET_NODE,
  1782. Node);
  1783. if (FirstPacket->Protocol != SecondPacket->Protocol) {
  1784. if (FirstPacket->Protocol < SecondPacket->Protocol) {
  1785. return ComparisonResultAscending;
  1786. } else {
  1787. return ComparisonResultDescending;
  1788. }
  1789. }
  1790. if (FirstPacket->RemoteAddress != SecondPacket->RemoteAddress) {
  1791. if (FirstPacket->RemoteAddress < SecondPacket->RemoteAddress) {
  1792. return ComparisonResultAscending;
  1793. } else {
  1794. return ComparisonResultDescending;
  1795. }
  1796. }
  1797. if (FirstPacket->LocalAddress != SecondPacket->LocalAddress) {
  1798. if (FirstPacket->LocalAddress < SecondPacket->LocalAddress) {
  1799. return ComparisonResultAscending;
  1800. } else {
  1801. return ComparisonResultDescending;
  1802. }
  1803. }
  1804. if (FirstPacket->Identification != SecondPacket->Identification) {
  1805. if (FirstPacket->Identification < SecondPacket->Identification) {
  1806. return ComparisonResultAscending;
  1807. } else {
  1808. return ComparisonResultDescending;
  1809. }
  1810. }
  1811. return ComparisonResultSame;
  1812. }
  1813. VOID
  1814. NetpIp4RemoveFragmentedPackets (
  1815. PNET_SOCKET Socket
  1816. )
  1817. /*++
  1818. Routine Description:
  1819. This routine removes fragmented packets from the tree of fragmented
  1820. packets. If a socket is supplied, then it removes all of the packets for
  1821. that socket. Otherwise it removes all of the expired packets, for all
  1822. sockets.
  1823. Arguments:
  1824. Socket - Supplies an optional pointer to a network socket.
  1825. Return Value:
  1826. None.
  1827. --*/
  1828. {
  1829. ULONGLONG CurrentTime;
  1830. PIP4_ADDRESS LocalAddress;
  1831. PIP4_FRAGMENTED_PACKET_NODE PacketNode;
  1832. PIP4_ADDRESS RemoteAddress;
  1833. PRED_BLACK_TREE_NODE TreeNode;
  1834. ASSERT(KeIsQueuedLockHeld(NetIp4FragmentedPacketLock) != FALSE);
  1835. //
  1836. // If a socket was supplied, remove all pending fragments for the local
  1837. // address, remote address, and protocol tuple.
  1838. //
  1839. if (Socket != NULL) {
  1840. ASSERT(Socket->LocalAddress.Domain == NetDomainIp4);
  1841. ASSERT((Socket->RemoteAddress.Domain == NetDomainIp4) ||
  1842. (Socket->RemoteAddress.Domain == NetDomainInvalid));
  1843. LocalAddress = (PIP4_ADDRESS)&(Socket->LocalAddress);
  1844. RemoteAddress = (PIP4_ADDRESS)&(Socket->RemoteAddress);
  1845. //
  1846. // Otherwise collect the current time as only the expired packets will be
  1847. // removed.
  1848. //
  1849. } else {
  1850. CurrentTime = HlQueryTimeCounter();
  1851. }
  1852. //
  1853. // Iterate over the tree and remove the appropriate packets.
  1854. //
  1855. TreeNode = RtlRedBlackTreeGetNextNode(&NetIp4FragmentedPacketTree,
  1856. FALSE,
  1857. NULL);
  1858. while (TreeNode != NULL) {
  1859. PacketNode = RED_BLACK_TREE_VALUE(TreeNode,
  1860. IP4_FRAGMENTED_PACKET_NODE,
  1861. Node);
  1862. TreeNode = RtlRedBlackTreeGetNextNode(&NetIp4FragmentedPacketTree,
  1863. FALSE,
  1864. TreeNode);
  1865. if (Socket != NULL) {
  1866. if ((PacketNode->LocalAddress != LocalAddress->Address) ||
  1867. (PacketNode->RemoteAddress != RemoteAddress->Address) ||
  1868. (PacketNode->Protocol !=
  1869. Socket->Protocol->ParentProtocolNumber)) {
  1870. continue;
  1871. }
  1872. } else {
  1873. if (PacketNode->Timeout > CurrentTime) {
  1874. continue;
  1875. }
  1876. }
  1877. //
  1878. // This packet needs to be destroyed.
  1879. //
  1880. NetpIp4DestroyFragmentedPacketNode(PacketNode);
  1881. }
  1882. return;
  1883. }
  1884. PIP4_FRAGMENTED_PACKET_NODE
  1885. NetpIp4CreateFragmentedPacketNode (
  1886. PIP4_HEADER Header
  1887. )
  1888. /*++
  1889. Routine Description:
  1890. This routine allocates a new fragmented packet node and inserts it into the
  1891. tree.
  1892. Arguments:
  1893. Header - Supplies a pointer to the header of the fragmented IPv4 packet.
  1894. Return Value:
  1895. Returns a pointer to the newly created fragmented packet node on success or
  1896. NULL on failure.
  1897. --*/
  1898. {
  1899. PIP4_FRAGMENTED_PACKET_NODE NewNode;
  1900. KSTATUS Status;
  1901. ULONGLONG Timeout;
  1902. //
  1903. // Allocate the new fragmented packet node and insert it into the tree.
  1904. //
  1905. NewNode = MmAllocatePagedPool(sizeof(IP4_FRAGMENTED_PACKET_NODE),
  1906. IP4_ALLOCATION_TAG);
  1907. if (NewNode == NULL) {
  1908. Status = STATUS_INSUFFICIENT_RESOURCES;
  1909. goto Ip4CreateFragmentedPacketNodeEnd;
  1910. }
  1911. RtlZeroMemory(NewNode, sizeof(IP4_FRAGMENTED_PACKET_NODE));
  1912. INITIALIZE_LIST_HEAD(&(NewNode->FragmentListHead));
  1913. NewNode->LocalAddress = Header->DestinationAddress;
  1914. NewNode->RemoteAddress = Header->SourceAddress;
  1915. NewNode->Protocol = Header->Protocol;
  1916. NewNode->Identification = NETWORK_TO_CPU16(Header->Identification);
  1917. Timeout = HlQueryTimeCounter() +
  1918. KeConvertMicrosecondsToTimeTicks(IP4_FRAGMENT_TIMEOUT);
  1919. NewNode->Timeout = Timeout;
  1920. RtlRedBlackTreeInsert(&NetIp4FragmentedPacketTree, &(NewNode->Node));
  1921. Status = STATUS_SUCCESS;
  1922. Ip4CreateFragmentedPacketNodeEnd:
  1923. if (!KSUCCESS(Status)) {
  1924. if (NewNode != NULL) {
  1925. NetpIp4DestroyFragmentedPacketNode(NewNode);
  1926. NewNode = NULL;
  1927. }
  1928. }
  1929. return NewNode;
  1930. }
  1931. VOID
  1932. NetpIp4DestroyFragmentedPacketNode (
  1933. PIP4_FRAGMENTED_PACKET_NODE PacketNode
  1934. )
  1935. /*++
  1936. Routine Description:
  1937. This routine destroys the given fragmented packet node, removing it from
  1938. the tree and destroying any fragments associated with it.
  1939. Arguments:
  1940. PacketNode - Supplies a pointer to the fragmented packet node to destroy.
  1941. Return Value:
  1942. None.
  1943. --*/
  1944. {
  1945. PIP4_FRAGMENT_ENTRY FragmentEntry;
  1946. if (PacketNode->Node.Parent != NULL) {
  1947. RtlRedBlackTreeRemove(&NetIp4FragmentedPacketTree, &(PacketNode->Node));
  1948. }
  1949. while (LIST_EMPTY(&(PacketNode->FragmentListHead)) == FALSE) {
  1950. FragmentEntry = LIST_VALUE(PacketNode->FragmentListHead.Next,
  1951. IP4_FRAGMENT_ENTRY,
  1952. ListEntry);
  1953. LIST_REMOVE(&(FragmentEntry->ListEntry));
  1954. MmFreePagedPool(FragmentEntry);
  1955. NetIp4FragmentCount -= 1;
  1956. }
  1957. MmFreePagedPool(PacketNode);
  1958. return;
  1959. }