Mtftp4Rrq.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. /** @file
  2. Routines to process Rrq (download).
  3. (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
  4. Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include "Mtftp4Impl.h"
  8. /**
  9. The packet process callback for MTFTP download.
  10. @param UdpPacket The packet received
  11. @param EndPoint The local/remote access point of the packet
  12. @param IoStatus The status of the receiving
  13. @param Context Opaque parameter, which is the MTFTP session
  14. **/
  15. VOID
  16. EFIAPI
  17. Mtftp4RrqInput (
  18. IN NET_BUF *UdpPacket,
  19. IN UDP_END_POINT *EndPoint,
  20. IN EFI_STATUS IoStatus,
  21. IN VOID *Context
  22. );
  23. /**
  24. Start the MTFTP session to download.
  25. It will first initialize some of the internal states then build and send a RRQ
  26. request packet, at last, it will start receive for the downloading.
  27. @param Instance The Mtftp session
  28. @param Operation The MTFTP opcode, it may be a EFI_MTFTP4_OPCODE_RRQ
  29. or EFI_MTFTP4_OPCODE_DIR.
  30. @retval EFI_SUCCESS The mtftp download session is started.
  31. @retval Others Failed to start downloading.
  32. **/
  33. EFI_STATUS
  34. Mtftp4RrqStart (
  35. IN MTFTP4_PROTOCOL *Instance,
  36. IN UINT16 Operation
  37. )
  38. {
  39. EFI_STATUS Status;
  40. //
  41. // The valid block number range are [1, 0xffff]. For example:
  42. // the client sends an RRQ request to the server, the server
  43. // transfers the DATA1 block. If option negotiation is ongoing,
  44. // the server will send back an OACK, then client will send ACK0.
  45. //
  46. Status = Mtftp4InitBlockRange (&Instance->Blocks, 1, 0xffff);
  47. if (EFI_ERROR (Status)) {
  48. return Status;
  49. }
  50. Status = Mtftp4SendRequest (Instance);
  51. if (EFI_ERROR (Status)) {
  52. return Status;
  53. }
  54. return UdpIoRecvDatagram (Instance->UnicastPort, Mtftp4RrqInput, Instance, 0);
  55. }
  56. /**
  57. Build and send a ACK packet for the download session.
  58. @param Instance The Mtftp session
  59. @param BlkNo The BlkNo to ack.
  60. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the packet
  61. @retval EFI_SUCCESS The ACK has been sent
  62. @retval Others Failed to send the ACK.
  63. **/
  64. EFI_STATUS
  65. Mtftp4RrqSendAck (
  66. IN MTFTP4_PROTOCOL *Instance,
  67. IN UINT16 BlkNo
  68. )
  69. {
  70. EFI_MTFTP4_PACKET *Ack;
  71. NET_BUF *Packet;
  72. EFI_STATUS Status;
  73. Status = EFI_SUCCESS;
  74. Packet = NetbufAlloc (sizeof (EFI_MTFTP4_ACK_HEADER));
  75. if (Packet == NULL) {
  76. return EFI_OUT_OF_RESOURCES;
  77. }
  78. Ack = (EFI_MTFTP4_PACKET *)NetbufAllocSpace (
  79. Packet,
  80. sizeof (EFI_MTFTP4_ACK_HEADER),
  81. FALSE
  82. );
  83. ASSERT (Ack != NULL);
  84. Ack->Ack.OpCode = HTONS (EFI_MTFTP4_OPCODE_ACK);
  85. Ack->Ack.Block[0] = HTONS (BlkNo);
  86. Status = Mtftp4SendPacket (Instance, Packet);
  87. if (!EFI_ERROR (Status)) {
  88. Instance->AckedBlock = Instance->TotalBlock;
  89. }
  90. return Status;
  91. }
  92. /**
  93. Deliver the received data block to the user, which can be saved
  94. in the user provide buffer or through the CheckPacket callback.
  95. @param Instance The Mtftp session
  96. @param Packet The received data packet
  97. @param Len The packet length
  98. @retval EFI_SUCCESS The data is saved successfully
  99. @retval EFI_ABORTED The user tells to abort by return an error through
  100. CheckPacket
  101. @retval EFI_BUFFER_TOO_SMALL The user's buffer is too small and buffer length is
  102. updated to the actual buffer size needed.
  103. **/
  104. EFI_STATUS
  105. Mtftp4RrqSaveBlock (
  106. IN OUT MTFTP4_PROTOCOL *Instance,
  107. IN EFI_MTFTP4_PACKET *Packet,
  108. IN UINT32 Len
  109. )
  110. {
  111. EFI_MTFTP4_TOKEN *Token;
  112. EFI_STATUS Status;
  113. UINT16 Block;
  114. UINT64 Start;
  115. UINT32 DataLen;
  116. UINT64 BlockCounter;
  117. BOOLEAN Completed;
  118. Completed = FALSE;
  119. Token = Instance->Token;
  120. Block = NTOHS (Packet->Data.Block);
  121. DataLen = Len - MTFTP4_DATA_HEAD_LEN;
  122. //
  123. // This is the last block, save the block no
  124. //
  125. if (DataLen < Instance->BlkSize) {
  126. Completed = TRUE;
  127. Instance->LastBlock = Block;
  128. Mtftp4SetLastBlockNum (&Instance->Blocks, Block);
  129. }
  130. //
  131. // Remove this block number from the file hole. If Mtftp4RemoveBlockNum
  132. // returns EFI_NOT_FOUND, the block has been saved, don't save it again.
  133. // Note that : For bigger files, allowing the block counter to roll over
  134. // to accept transfers of unlimited size. So BlockCounter is memorised as
  135. // continuous block counter.
  136. //
  137. Status = Mtftp4RemoveBlockNum (&Instance->Blocks, Block, Completed, &BlockCounter);
  138. if (Status == EFI_NOT_FOUND) {
  139. return EFI_SUCCESS;
  140. } else if (EFI_ERROR (Status)) {
  141. return Status;
  142. }
  143. if (Token->CheckPacket != NULL) {
  144. Status = Token->CheckPacket (&Instance->Mtftp4, Token, (UINT16)Len, Packet);
  145. if (EFI_ERROR (Status)) {
  146. Mtftp4SendError (
  147. Instance,
  148. EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION,
  149. (UINT8 *)"User aborted download"
  150. );
  151. return EFI_ABORTED;
  152. }
  153. }
  154. if (Token->Buffer != NULL) {
  155. Start = MultU64x32 (BlockCounter - 1, Instance->BlkSize);
  156. if (Start + DataLen <= Token->BufferSize) {
  157. CopyMem ((UINT8 *)Token->Buffer + Start, Packet->Data.Data, DataLen);
  158. //
  159. // Update the file size when received the last block
  160. //
  161. if ((Instance->LastBlock == Block) && Completed) {
  162. Token->BufferSize = Start + DataLen;
  163. }
  164. } else if (Instance->LastBlock != 0) {
  165. //
  166. // Don't save the data if the buffer is too small, return
  167. // EFI_BUFFER_TOO_SMALL if received the last packet. This
  168. // will give a accurate file length.
  169. //
  170. Token->BufferSize = Start + DataLen;
  171. Mtftp4SendError (
  172. Instance,
  173. EFI_MTFTP4_ERRORCODE_DISK_FULL,
  174. (UINT8 *)"User provided memory block is too small"
  175. );
  176. return EFI_BUFFER_TOO_SMALL;
  177. }
  178. }
  179. return EFI_SUCCESS;
  180. }
  181. /**
  182. Function to process the received data packets.
  183. It will save the block then send back an ACK if it is active.
  184. @param Instance The downloading MTFTP session
  185. @param Packet The packet received
  186. @param Len The length of the packet
  187. @param Multicast Whether this packet is multicast or unicast
  188. @param Completed Return whether the download has completed
  189. @retval EFI_SUCCESS The data packet is successfully processed
  190. @retval EFI_ABORTED The download is aborted by the user
  191. @retval EFI_BUFFER_TOO_SMALL The user provided buffer is too small
  192. **/
  193. EFI_STATUS
  194. Mtftp4RrqHandleData (
  195. IN MTFTP4_PROTOCOL *Instance,
  196. IN EFI_MTFTP4_PACKET *Packet,
  197. IN UINT32 Len,
  198. IN BOOLEAN Multicast,
  199. OUT BOOLEAN *Completed
  200. )
  201. {
  202. EFI_STATUS Status;
  203. UINT16 BlockNum;
  204. INTN Expected;
  205. *Completed = FALSE;
  206. Status = EFI_SUCCESS;
  207. BlockNum = NTOHS (Packet->Data.Block);
  208. Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);
  209. ASSERT (Expected >= 0);
  210. //
  211. // If we are active (Master) and received an unexpected packet, transmit
  212. // the ACK for the block we received, then restart receiving the
  213. // expected one. If we are passive (Slave), save the block.
  214. //
  215. if (Instance->Master && (Expected != BlockNum)) {
  216. //
  217. // If Expected is 0, (UINT16) (Expected - 1) is also the expected Ack number (65535).
  218. //
  219. return Mtftp4RrqSendAck (Instance, (UINT16)(Expected - 1));
  220. }
  221. Status = Mtftp4RrqSaveBlock (Instance, Packet, Len);
  222. if (EFI_ERROR (Status)) {
  223. return Status;
  224. }
  225. //
  226. // Record the total received and saved block number.
  227. //
  228. Instance->TotalBlock++;
  229. //
  230. // Reset the passive client's timer whenever it received a
  231. // valid data packet.
  232. //
  233. if (!Instance->Master) {
  234. Mtftp4SetTimeout (Instance);
  235. }
  236. //
  237. // Check whether we have received all the blocks. Send the ACK if we
  238. // are active (unicast client or master client for multicast download).
  239. // If we have received all the blocks, send an ACK even if we are passive
  240. // to tell the server that we are done.
  241. //
  242. Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);
  243. if (Instance->Master || (Expected < 0)) {
  244. if (Expected < 0) {
  245. //
  246. // If we are passive client, then the just received Block maybe
  247. // isn't the last block. We need to send an ACK to the last block
  248. // to inform the server that we are done. If we are active client,
  249. // the Block == Instance->LastBlock.
  250. //
  251. BlockNum = Instance->LastBlock;
  252. *Completed = TRUE;
  253. } else {
  254. BlockNum = (UINT16)(Expected - 1);
  255. }
  256. if ((Instance->WindowSize == (Instance->TotalBlock - Instance->AckedBlock)) || (Expected < 0)) {
  257. Status = Mtftp4RrqSendAck (Instance, BlockNum);
  258. }
  259. }
  260. return Status;
  261. }
  262. /**
  263. Validate whether the options received in the server's OACK packet is valid.
  264. The options are valid only if:
  265. 1. The server doesn't include options not requested by us
  266. 2. The server can only use smaller blksize than that is requested
  267. 3. The server can only use the same timeout as requested
  268. 4. The server doesn't change its multicast channel.
  269. @param This The downloading Mtftp session
  270. @param Reply The options in the OACK packet
  271. @param Request The requested options
  272. @retval TRUE The options in the OACK is OK.
  273. @retval FALSE The options in the OACK is invalid.
  274. **/
  275. BOOLEAN
  276. Mtftp4RrqOackValid (
  277. IN MTFTP4_PROTOCOL *This,
  278. IN MTFTP4_OPTION *Reply,
  279. IN MTFTP4_OPTION *Request
  280. )
  281. {
  282. //
  283. // It is invalid for server to return options we don't request
  284. //
  285. if ((Reply->Exist &~Request->Exist) != 0) {
  286. return FALSE;
  287. }
  288. //
  289. // Server can only specify a smaller block size and window size to be used and
  290. // return the timeout matches that requested.
  291. //
  292. if ((((Reply->Exist & MTFTP4_BLKSIZE_EXIST) != 0) && (Reply->BlkSize > Request->BlkSize)) ||
  293. (((Reply->Exist & MTFTP4_WINDOWSIZE_EXIST) != 0) && (Reply->WindowSize > Request->WindowSize)) ||
  294. (((Reply->Exist & MTFTP4_TIMEOUT_EXIST) != 0) && (Reply->Timeout != Request->Timeout))
  295. )
  296. {
  297. return FALSE;
  298. }
  299. //
  300. // The server can send ",,master" to client to change its master
  301. // setting. But if it use the specific multicast channel, it can't
  302. // change the setting.
  303. //
  304. if (((Reply->Exist & MTFTP4_MCAST_EXIST) != 0) && (This->McastIp != 0)) {
  305. if ((Reply->McastIp != 0) && (Reply->McastIp != This->McastIp)) {
  306. return FALSE;
  307. }
  308. if ((Reply->McastPort != 0) && (Reply->McastPort != This->McastPort)) {
  309. return FALSE;
  310. }
  311. }
  312. return TRUE;
  313. }
  314. /**
  315. Configure a UDP IO port to receive the multicast.
  316. @param McastIo The UDP IO to configure
  317. @param Context The opaque parameter to the function which is the
  318. MTFTP session.
  319. @retval EFI_SUCCESS The UDP child is successfully configured.
  320. @retval Others Failed to configure the UDP child.
  321. **/
  322. EFI_STATUS
  323. EFIAPI
  324. Mtftp4RrqConfigMcastPort (
  325. IN UDP_IO *McastIo,
  326. IN VOID *Context
  327. )
  328. {
  329. MTFTP4_PROTOCOL *Instance;
  330. EFI_MTFTP4_CONFIG_DATA *Config;
  331. EFI_UDP4_CONFIG_DATA UdpConfig;
  332. EFI_IPv4_ADDRESS Group;
  333. EFI_STATUS Status;
  334. IP4_ADDR Ip;
  335. Instance = (MTFTP4_PROTOCOL *)Context;
  336. Config = &Instance->Config;
  337. UdpConfig.AcceptBroadcast = FALSE;
  338. UdpConfig.AcceptPromiscuous = FALSE;
  339. UdpConfig.AcceptAnyPort = FALSE;
  340. UdpConfig.AllowDuplicatePort = FALSE;
  341. UdpConfig.TypeOfService = 0;
  342. UdpConfig.TimeToLive = 64;
  343. UdpConfig.DoNotFragment = FALSE;
  344. UdpConfig.ReceiveTimeout = 0;
  345. UdpConfig.TransmitTimeout = 0;
  346. UdpConfig.UseDefaultAddress = Config->UseDefaultSetting;
  347. IP4_COPY_ADDRESS (&UdpConfig.StationAddress, &Config->StationIp);
  348. IP4_COPY_ADDRESS (&UdpConfig.SubnetMask, &Config->SubnetMask);
  349. UdpConfig.StationPort = Instance->McastPort;
  350. UdpConfig.RemotePort = 0;
  351. Ip = HTONL (Instance->ServerIp);
  352. IP4_COPY_ADDRESS (&UdpConfig.RemoteAddress, &Ip);
  353. Status = McastIo->Protocol.Udp4->Configure (McastIo->Protocol.Udp4, &UdpConfig);
  354. if (EFI_ERROR (Status)) {
  355. return Status;
  356. }
  357. if (!Config->UseDefaultSetting &&
  358. !EFI_IP4_EQUAL (&mZeroIp4Addr, &Config->GatewayIp))
  359. {
  360. //
  361. // The station IP address is manually configured and the Gateway IP is not 0.
  362. // Add the default route for this UDP instance.
  363. //
  364. Status = McastIo->Protocol.Udp4->Routes (
  365. McastIo->Protocol.Udp4,
  366. FALSE,
  367. &mZeroIp4Addr,
  368. &mZeroIp4Addr,
  369. &Config->GatewayIp
  370. );
  371. if (EFI_ERROR (Status)) {
  372. McastIo->Protocol.Udp4->Configure (McastIo->Protocol.Udp4, NULL);
  373. return Status;
  374. }
  375. }
  376. //
  377. // join the multicast group
  378. //
  379. Ip = HTONL (Instance->McastIp);
  380. IP4_COPY_ADDRESS (&Group, &Ip);
  381. return McastIo->Protocol.Udp4->Groups (McastIo->Protocol.Udp4, TRUE, &Group);
  382. }
  383. /**
  384. Function to process the OACK.
  385. It will first validate the OACK packet, then update the various negotiated parameters.
  386. @param Instance The download MTFTP session
  387. @param Packet The packet received
  388. @param Len The packet length
  389. @param Multicast Whether this packet is received as a multicast
  390. @param Completed Returns whether the download has completed. NOT
  391. used by this function.
  392. @retval EFI_DEVICE_ERROR Failed to create/start a multicast UDP child
  393. @retval EFI_TFTP_ERROR Some error happened during the process
  394. @retval EFI_SUCCESS The OACK is successfully processed.
  395. **/
  396. EFI_STATUS
  397. Mtftp4RrqHandleOack (
  398. IN OUT MTFTP4_PROTOCOL *Instance,
  399. IN EFI_MTFTP4_PACKET *Packet,
  400. IN UINT32 Len,
  401. IN BOOLEAN Multicast,
  402. OUT BOOLEAN *Completed
  403. )
  404. {
  405. MTFTP4_OPTION Reply;
  406. EFI_STATUS Status;
  407. INTN Expected;
  408. EFI_UDP4_PROTOCOL *Udp4;
  409. *Completed = FALSE;
  410. //
  411. // If already started the master download, don't change the
  412. // setting. Master download always succeeds.
  413. //
  414. Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);
  415. ASSERT (Expected != -1);
  416. if (Instance->Master && (Expected != 1)) {
  417. return EFI_SUCCESS;
  418. }
  419. //
  420. // Parse and validate the options from server
  421. //
  422. ZeroMem (&Reply, sizeof (MTFTP4_OPTION));
  423. Status = Mtftp4ParseOptionOack (Packet, Len, Instance->Operation, &Reply);
  424. if (EFI_ERROR (Status) ||
  425. !Mtftp4RrqOackValid (Instance, &Reply, &Instance->RequestOption))
  426. {
  427. //
  428. // Don't send an ERROR packet if the error is EFI_OUT_OF_RESOURCES.
  429. //
  430. if (Status != EFI_OUT_OF_RESOURCES) {
  431. Mtftp4SendError (
  432. Instance,
  433. EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION,
  434. (UINT8 *)"Malformatted OACK packet"
  435. );
  436. }
  437. return EFI_TFTP_ERROR;
  438. }
  439. if ((Reply.Exist & MTFTP4_MCAST_EXIST) != 0) {
  440. //
  441. // Save the multicast info. Always update the Master, only update the
  442. // multicast IP address, block size, window size, timeout at the first time.
  443. // If IP address is updated, create a UDP child to receive the multicast.
  444. //
  445. Instance->Master = Reply.Master;
  446. if (Instance->McastIp == 0) {
  447. if ((Reply.McastIp == 0) || (Reply.McastPort == 0)) {
  448. Mtftp4SendError (
  449. Instance,
  450. EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION,
  451. (UINT8 *)"Illegal multicast setting"
  452. );
  453. return EFI_TFTP_ERROR;
  454. }
  455. //
  456. // Create a UDP child then start receive the multicast from it.
  457. //
  458. Instance->McastIp = Reply.McastIp;
  459. Instance->McastPort = Reply.McastPort;
  460. if (Instance->McastUdpPort == NULL) {
  461. Instance->McastUdpPort = UdpIoCreateIo (
  462. Instance->Service->Controller,
  463. Instance->Service->Image,
  464. Mtftp4RrqConfigMcastPort,
  465. UDP_IO_UDP4_VERSION,
  466. Instance
  467. );
  468. if (Instance->McastUdpPort != NULL) {
  469. Status = gBS->OpenProtocol (
  470. Instance->McastUdpPort->UdpHandle,
  471. &gEfiUdp4ProtocolGuid,
  472. (VOID **)&Udp4,
  473. Instance->Service->Image,
  474. Instance->Handle,
  475. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  476. );
  477. if (EFI_ERROR (Status)) {
  478. UdpIoFreeIo (Instance->McastUdpPort);
  479. Instance->McastUdpPort = NULL;
  480. return EFI_DEVICE_ERROR;
  481. }
  482. }
  483. }
  484. if (Instance->McastUdpPort == NULL) {
  485. return EFI_DEVICE_ERROR;
  486. }
  487. Status = UdpIoRecvDatagram (Instance->McastUdpPort, Mtftp4RrqInput, Instance, 0);
  488. if (EFI_ERROR (Status)) {
  489. Mtftp4SendError (
  490. Instance,
  491. EFI_MTFTP4_ERRORCODE_ACCESS_VIOLATION,
  492. (UINT8 *)"Failed to create socket to receive multicast packet"
  493. );
  494. return Status;
  495. }
  496. //
  497. // Update the parameters used.
  498. //
  499. if (Reply.BlkSize != 0) {
  500. Instance->BlkSize = Reply.BlkSize;
  501. }
  502. if (Reply.WindowSize != 0) {
  503. Instance->WindowSize = Reply.WindowSize;
  504. }
  505. if (Reply.Timeout != 0) {
  506. Instance->Timeout = Reply.Timeout;
  507. }
  508. }
  509. } else {
  510. Instance->Master = TRUE;
  511. if (Reply.BlkSize != 0) {
  512. Instance->BlkSize = Reply.BlkSize;
  513. }
  514. if (Reply.WindowSize != 0) {
  515. Instance->WindowSize = Reply.WindowSize;
  516. }
  517. if (Reply.Timeout != 0) {
  518. Instance->Timeout = Reply.Timeout;
  519. }
  520. }
  521. //
  522. // Send an ACK to (Expected - 1) which is 0 for unicast download,
  523. // or tell the server we want to receive the Expected block.
  524. //
  525. return Mtftp4RrqSendAck (Instance, (UINT16)(Expected - 1));
  526. }
  527. /**
  528. The packet process callback for MTFTP download.
  529. @param UdpPacket The packet received
  530. @param EndPoint The local/remote access point of the packet
  531. @param IoStatus The status of the receiving
  532. @param Context Opaque parameter, which is the MTFTP session
  533. **/
  534. VOID
  535. EFIAPI
  536. Mtftp4RrqInput (
  537. IN NET_BUF *UdpPacket,
  538. IN UDP_END_POINT *EndPoint,
  539. IN EFI_STATUS IoStatus,
  540. IN VOID *Context
  541. )
  542. {
  543. MTFTP4_PROTOCOL *Instance;
  544. EFI_MTFTP4_PACKET *Packet;
  545. BOOLEAN Completed;
  546. BOOLEAN Multicast;
  547. EFI_STATUS Status;
  548. UINT16 Opcode;
  549. UINT32 Len;
  550. Instance = (MTFTP4_PROTOCOL *)Context;
  551. NET_CHECK_SIGNATURE (Instance, MTFTP4_PROTOCOL_SIGNATURE);
  552. Status = EFI_SUCCESS;
  553. Packet = NULL;
  554. Completed = FALSE;
  555. Multicast = FALSE;
  556. if (EFI_ERROR (IoStatus)) {
  557. Status = IoStatus;
  558. goto ON_EXIT;
  559. }
  560. ASSERT (UdpPacket != NULL);
  561. //
  562. // Find the port this packet is from to restart receive correctly.
  563. //
  564. Multicast = (BOOLEAN)(EndPoint->LocalAddr.Addr[0] == Instance->McastIp);
  565. if (UdpPacket->TotalSize < MTFTP4_OPCODE_LEN) {
  566. goto ON_EXIT;
  567. }
  568. //
  569. // Client send initial request to server's listening port. Server
  570. // will select a UDP port to communicate with the client. The server
  571. // is required to use the same port as RemotePort to multicast the
  572. // data.
  573. //
  574. if (EndPoint->RemotePort != Instance->ConnectedPort) {
  575. if (Instance->ConnectedPort != 0) {
  576. goto ON_EXIT;
  577. } else {
  578. Instance->ConnectedPort = EndPoint->RemotePort;
  579. }
  580. }
  581. //
  582. // Copy the MTFTP packet to a continuous buffer if it isn't already so.
  583. //
  584. Len = UdpPacket->TotalSize;
  585. if (UdpPacket->BlockOpNum > 1) {
  586. Packet = AllocatePool (Len);
  587. if (Packet == NULL) {
  588. Status = EFI_OUT_OF_RESOURCES;
  589. goto ON_EXIT;
  590. }
  591. NetbufCopy (UdpPacket, 0, Len, (UINT8 *)Packet);
  592. } else {
  593. Packet = (EFI_MTFTP4_PACKET *)NetbufGetByte (UdpPacket, 0, NULL);
  594. ASSERT (Packet != NULL);
  595. }
  596. Opcode = NTOHS (Packet->OpCode);
  597. //
  598. // Call the user's CheckPacket if provided. Abort the transmission
  599. // if CheckPacket returns an EFI_ERROR code.
  600. //
  601. if ((Instance->Token->CheckPacket != NULL) &&
  602. ((Opcode == EFI_MTFTP4_OPCODE_OACK) || (Opcode == EFI_MTFTP4_OPCODE_ERROR)))
  603. {
  604. Status = Instance->Token->CheckPacket (
  605. &Instance->Mtftp4,
  606. Instance->Token,
  607. (UINT16)Len,
  608. Packet
  609. );
  610. if (EFI_ERROR (Status)) {
  611. //
  612. // Send an error message to the server to inform it
  613. //
  614. if (Opcode != EFI_MTFTP4_OPCODE_ERROR) {
  615. Mtftp4SendError (
  616. Instance,
  617. EFI_MTFTP4_ERRORCODE_REQUEST_DENIED,
  618. (UINT8 *)"User aborted the transfer"
  619. );
  620. }
  621. Status = EFI_ABORTED;
  622. goto ON_EXIT;
  623. }
  624. }
  625. switch (Opcode) {
  626. case EFI_MTFTP4_OPCODE_DATA:
  627. if ((Len > (UINT32)(MTFTP4_DATA_HEAD_LEN + Instance->BlkSize)) ||
  628. (Len < (UINT32)MTFTP4_DATA_HEAD_LEN))
  629. {
  630. goto ON_EXIT;
  631. }
  632. Status = Mtftp4RrqHandleData (Instance, Packet, Len, Multicast, &Completed);
  633. break;
  634. case EFI_MTFTP4_OPCODE_OACK:
  635. if (Multicast || (Len <= MTFTP4_OPCODE_LEN)) {
  636. goto ON_EXIT;
  637. }
  638. Status = Mtftp4RrqHandleOack (Instance, Packet, Len, Multicast, &Completed);
  639. break;
  640. case EFI_MTFTP4_OPCODE_ERROR:
  641. Status = EFI_TFTP_ERROR;
  642. break;
  643. default:
  644. break;
  645. }
  646. ON_EXIT:
  647. //
  648. // Free the resources, then if !EFI_ERROR (Status), restart the
  649. // receive, otherwise end the session.
  650. //
  651. if ((Packet != NULL) && (UdpPacket->BlockOpNum > 1)) {
  652. FreePool (Packet);
  653. }
  654. if (UdpPacket != NULL) {
  655. NetbufFree (UdpPacket);
  656. }
  657. if (!EFI_ERROR (Status) && !Completed) {
  658. if (Multicast) {
  659. Status = UdpIoRecvDatagram (Instance->McastUdpPort, Mtftp4RrqInput, Instance, 0);
  660. } else {
  661. Status = UdpIoRecvDatagram (Instance->UnicastPort, Mtftp4RrqInput, Instance, 0);
  662. }
  663. }
  664. if (EFI_ERROR (Status) || Completed) {
  665. Mtftp4CleanOperation (Instance, Status);
  666. }
  667. }