tftp.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2010,2011 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <grub/misc.h>
  19. #include <grub/net/udp.h>
  20. #include <grub/net/ip.h>
  21. #include <grub/net/ethernet.h>
  22. #include <grub/net/netbuff.h>
  23. #include <grub/net.h>
  24. #include <grub/mm.h>
  25. #include <grub/dl.h>
  26. #include <grub/file.h>
  27. #include <grub/i18n.h>
  28. GRUB_MOD_LICENSE ("GPLv3+");
  29. /* IP port for the MTFTP server used for Intel's PXE */
  30. enum
  31. {
  32. MTFTP_SERVER_PORT = 75,
  33. MTFTP_CLIENT_PORT = 76,
  34. /* IP port for the TFTP server */
  35. TFTP_SERVER_PORT = 69
  36. };
  37. enum
  38. {
  39. TFTP_DEFAULTSIZE_PACKET = 512,
  40. };
  41. enum
  42. {
  43. TFTP_CODE_EOF = 1,
  44. TFTP_CODE_MORE = 2,
  45. TFTP_CODE_ERROR = 3,
  46. TFTP_CODE_BOOT = 4,
  47. TFTP_CODE_CFG = 5
  48. };
  49. enum
  50. {
  51. TFTP_RRQ = 1,
  52. TFTP_WRQ = 2,
  53. TFTP_DATA = 3,
  54. TFTP_ACK = 4,
  55. TFTP_ERROR = 5,
  56. TFTP_OACK = 6
  57. };
  58. enum
  59. {
  60. TFTP_EUNDEF = 0, /* not defined */
  61. TFTP_ENOTFOUND = 1, /* file not found */
  62. TFTP_EACCESS = 2, /* access violation */
  63. TFTP_ENOSPACE = 3, /* disk full or allocation exceeded */
  64. TFTP_EBADOP = 4, /* illegal TFTP operation */
  65. TFTP_EBADID = 5, /* unknown transfer ID */
  66. TFTP_EEXISTS = 6, /* file already exists */
  67. TFTP_ENOUSER = 7 /* no such user */
  68. };
  69. struct tftphdr {
  70. grub_uint16_t opcode;
  71. union {
  72. grub_int8_t rrq[TFTP_DEFAULTSIZE_PACKET];
  73. struct {
  74. grub_uint16_t block;
  75. grub_int8_t download[0];
  76. } data;
  77. struct {
  78. grub_uint16_t block;
  79. } ack;
  80. struct {
  81. grub_uint16_t errcode;
  82. grub_int8_t errmsg[TFTP_DEFAULTSIZE_PACKET];
  83. } err;
  84. struct {
  85. grub_int8_t data[TFTP_DEFAULTSIZE_PACKET+2];
  86. } oack;
  87. } u;
  88. } GRUB_PACKED ;
  89. typedef struct tftp_data
  90. {
  91. grub_uint64_t file_size;
  92. grub_uint64_t block;
  93. grub_uint32_t block_size;
  94. grub_uint64_t ack_sent;
  95. int have_oack;
  96. struct grub_error_saved save_err;
  97. grub_net_udp_socket_t sock;
  98. } *tftp_data_t;
  99. static grub_err_t
  100. ack (tftp_data_t data, grub_uint64_t block)
  101. {
  102. struct tftphdr *tftph_ack;
  103. grub_uint8_t nbdata[512];
  104. struct grub_net_buff nb_ack;
  105. grub_err_t err;
  106. nb_ack.head = nbdata;
  107. nb_ack.end = nbdata + sizeof (nbdata);
  108. grub_netbuff_clear (&nb_ack);
  109. grub_netbuff_reserve (&nb_ack, 512);
  110. err = grub_netbuff_push (&nb_ack, sizeof (tftph_ack->opcode)
  111. + sizeof (tftph_ack->u.ack.block));
  112. if (err)
  113. return err;
  114. tftph_ack = (struct tftphdr *) nb_ack.data;
  115. tftph_ack->opcode = grub_cpu_to_be16_compile_time (TFTP_ACK);
  116. tftph_ack->u.ack.block = grub_cpu_to_be16 (block);
  117. err = grub_net_send_udp_packet (data->sock, &nb_ack);
  118. if (err)
  119. return err;
  120. data->ack_sent = block;
  121. return GRUB_ERR_NONE;
  122. }
  123. static grub_err_t
  124. tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)),
  125. struct grub_net_buff *nb,
  126. void *f)
  127. {
  128. grub_file_t file = f;
  129. struct tftphdr *tftph = (void *) nb->data;
  130. tftp_data_t data = file->data;
  131. grub_err_t err;
  132. grub_uint8_t *ptr;
  133. if (nb->tail - nb->data < (grub_ssize_t) sizeof (tftph->opcode))
  134. {
  135. grub_dprintf ("tftp", "TFTP packet too small\n");
  136. return GRUB_ERR_NONE;
  137. }
  138. tftph = (struct tftphdr *) nb->data;
  139. switch (grub_be_to_cpu16 (tftph->opcode))
  140. {
  141. case TFTP_OACK:
  142. data->block_size = TFTP_DEFAULTSIZE_PACKET;
  143. data->have_oack = 1;
  144. for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;)
  145. {
  146. if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0)
  147. data->file_size = grub_strtoul ((char *) ptr + sizeof ("tsize\0")
  148. - 1, 0, 0);
  149. if (grub_memcmp (ptr, "blksize\0", sizeof ("blksize\0") - 1) == 0)
  150. data->block_size = grub_strtoul ((char *) ptr + sizeof ("blksize\0")
  151. - 1, 0, 0);
  152. while (ptr < nb->tail && *ptr)
  153. ptr++;
  154. ptr++;
  155. }
  156. data->block = 0;
  157. grub_netbuff_free (nb);
  158. err = ack (data, 0);
  159. grub_error_save (&data->save_err);
  160. return GRUB_ERR_NONE;
  161. case TFTP_DATA:
  162. if (nb->tail - nb->data < (grub_ssize_t) (sizeof (tftph->opcode)
  163. + sizeof (tftph->u.data.block)))
  164. {
  165. grub_dprintf ("tftp", "TFTP packet too small\n");
  166. return GRUB_ERR_NONE;
  167. }
  168. /*
  169. * Ack old/retransmitted block.
  170. *
  171. * The block number is a 16-bit counter, thus the maximum file size that
  172. * could be transfered is 65535 * block size. Most TFTP hosts support to
  173. * roll-over the block counter to allow unlimited transfer file size.
  174. *
  175. * This behavior is not defined in the RFC 1350 [0] but is implemented by
  176. * most TFTP clients and hosts.
  177. *
  178. * [0]: https://tools.ietf.org/html/rfc1350
  179. */
  180. if (grub_be_to_cpu16 (tftph->u.data.block) < ((grub_uint16_t) (data->block + 1)))
  181. ack (data, grub_be_to_cpu16 (tftph->u.data.block));
  182. /* Ignore unexpected block. */
  183. else if (grub_be_to_cpu16 (tftph->u.data.block) > ((grub_uint16_t) (data->block + 1)))
  184. grub_dprintf ("tftp", "TFTP unexpected block # %d\n", tftph->u.data.block);
  185. else
  186. {
  187. unsigned size;
  188. if (file->device->net->packs.count < 50)
  189. {
  190. err = ack (data, data->block + 1);
  191. if (err)
  192. return err;
  193. }
  194. else
  195. file->device->net->stall = 1;
  196. err = grub_netbuff_pull (nb, sizeof (tftph->opcode) +
  197. sizeof (tftph->u.data.block));
  198. if (err)
  199. return err;
  200. size = nb->tail - nb->data;
  201. data->block++;
  202. if (size < data->block_size)
  203. {
  204. if (data->ack_sent < data->block)
  205. ack (data, data->block);
  206. file->device->net->eof = 1;
  207. file->device->net->stall = 1;
  208. grub_net_udp_close (data->sock);
  209. data->sock = NULL;
  210. }
  211. /*
  212. * Prevent garbage in broken cards. Is it still necessary
  213. * given that IP implementation has been fixed?
  214. */
  215. if (size > data->block_size)
  216. {
  217. err = grub_netbuff_unput (nb, size - data->block_size);
  218. if (err)
  219. return err;
  220. }
  221. /* If there is data, puts packet in socket list. */
  222. if ((nb->tail - nb->data) > 0)
  223. {
  224. grub_net_put_packet (&file->device->net->packs, nb);
  225. /* Do not free nb. */
  226. return GRUB_ERR_NONE;
  227. }
  228. }
  229. grub_netbuff_free (nb);
  230. return GRUB_ERR_NONE;
  231. case TFTP_ERROR:
  232. data->have_oack = 1;
  233. grub_netbuff_free (nb);
  234. grub_error (GRUB_ERR_IO, "%s", tftph->u.err.errmsg);
  235. grub_error_save (&data->save_err);
  236. return GRUB_ERR_NONE;
  237. default:
  238. grub_netbuff_free (nb);
  239. return GRUB_ERR_NONE;
  240. }
  241. }
  242. /*
  243. * Create a normalized copy of the filename. Compress any string of consecutive
  244. * forward slashes to a single forward slash.
  245. */
  246. static void
  247. grub_normalize_filename (char *normalized, const char *filename)
  248. {
  249. char *dest = normalized;
  250. const char *src = filename;
  251. while (*src != '\0')
  252. {
  253. if (src[0] == '/' && src[1] == '/')
  254. src++;
  255. else
  256. *dest++ = *src++;
  257. }
  258. *dest = '\0';
  259. }
  260. static grub_err_t
  261. tftp_open (struct grub_file *file, const char *filename)
  262. {
  263. struct tftphdr *tftph;
  264. char *rrq;
  265. int i;
  266. int rrqlen;
  267. int hdrlen;
  268. grub_uint8_t open_data[1500];
  269. struct grub_net_buff nb;
  270. tftp_data_t data;
  271. grub_err_t err;
  272. grub_uint8_t *nbd;
  273. grub_net_network_level_address_t addr;
  274. data = grub_zalloc (sizeof (*data));
  275. if (!data)
  276. return grub_errno;
  277. nb.head = open_data;
  278. nb.end = open_data + sizeof (open_data);
  279. grub_netbuff_clear (&nb);
  280. grub_netbuff_reserve (&nb, 1500);
  281. err = grub_netbuff_push (&nb, sizeof (*tftph));
  282. if (err)
  283. {
  284. grub_free (data);
  285. return err;
  286. }
  287. tftph = (struct tftphdr *) nb.data;
  288. rrq = (char *) tftph->u.rrq;
  289. rrqlen = 0;
  290. tftph->opcode = grub_cpu_to_be16_compile_time (TFTP_RRQ);
  291. /*
  292. * Copy and normalize the filename to work-around issues on some TFTP
  293. * servers when file names are being matched for remapping.
  294. */
  295. grub_normalize_filename (rrq, filename);
  296. rrqlen += grub_strlen (rrq) + 1;
  297. rrq += grub_strlen (rrq) + 1;
  298. grub_strcpy (rrq, "octet");
  299. rrqlen += grub_strlen ("octet") + 1;
  300. rrq += grub_strlen ("octet") + 1;
  301. grub_strcpy (rrq, "blksize");
  302. rrqlen += grub_strlen ("blksize") + 1;
  303. rrq += grub_strlen ("blksize") + 1;
  304. grub_strcpy (rrq, "1024");
  305. rrqlen += grub_strlen ("1024") + 1;
  306. rrq += grub_strlen ("1024") + 1;
  307. grub_strcpy (rrq, "tsize");
  308. rrqlen += grub_strlen ("tsize") + 1;
  309. rrq += grub_strlen ("tsize") + 1;
  310. grub_strcpy (rrq, "0");
  311. rrqlen += grub_strlen ("0") + 1;
  312. rrq += grub_strlen ("0") + 1;
  313. hdrlen = sizeof (tftph->opcode) + rrqlen;
  314. err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen));
  315. if (err)
  316. {
  317. grub_free (data);
  318. return err;
  319. }
  320. file->not_easily_seekable = 1;
  321. file->data = data;
  322. err = grub_net_resolve_address (file->device->net->server, &addr);
  323. if (err)
  324. {
  325. grub_free (data);
  326. return err;
  327. }
  328. data->sock = grub_net_udp_open (addr,
  329. TFTP_SERVER_PORT, tftp_receive,
  330. file);
  331. if (!data->sock)
  332. {
  333. grub_free (data);
  334. return grub_errno;
  335. }
  336. /* Receive OACK packet. */
  337. nbd = nb.data;
  338. for (i = 0; i < GRUB_NET_TRIES; i++)
  339. {
  340. nb.data = nbd;
  341. err = grub_net_send_udp_packet (data->sock, &nb);
  342. if (err)
  343. {
  344. grub_net_udp_close (data->sock);
  345. grub_free (data);
  346. return err;
  347. }
  348. grub_net_poll_cards (GRUB_NET_INTERVAL + (i * GRUB_NET_INTERVAL_ADDITION),
  349. &data->have_oack);
  350. if (data->have_oack)
  351. break;
  352. }
  353. if (!data->have_oack)
  354. grub_error (GRUB_ERR_TIMEOUT, N_("time out opening `%s'"), filename);
  355. else
  356. grub_error_load (&data->save_err);
  357. if (grub_errno)
  358. {
  359. grub_net_udp_close (data->sock);
  360. grub_free (data);
  361. return grub_errno;
  362. }
  363. file->size = data->file_size;
  364. return GRUB_ERR_NONE;
  365. }
  366. static grub_err_t
  367. tftp_close (struct grub_file *file)
  368. {
  369. tftp_data_t data = file->data;
  370. if (data->sock)
  371. {
  372. grub_uint8_t nbdata[512];
  373. grub_err_t err;
  374. struct grub_net_buff nb_err;
  375. struct tftphdr *tftph;
  376. nb_err.head = nbdata;
  377. nb_err.end = nbdata + sizeof (nbdata);
  378. grub_netbuff_clear (&nb_err);
  379. grub_netbuff_reserve (&nb_err, 512);
  380. err = grub_netbuff_push (&nb_err, sizeof (tftph->opcode)
  381. + sizeof (tftph->u.err.errcode)
  382. + sizeof ("closed"));
  383. if (!err)
  384. {
  385. tftph = (struct tftphdr *) nb_err.data;
  386. tftph->opcode = grub_cpu_to_be16_compile_time (TFTP_ERROR);
  387. tftph->u.err.errcode = grub_cpu_to_be16_compile_time (TFTP_EUNDEF);
  388. grub_memcpy (tftph->u.err.errmsg, "closed", sizeof ("closed"));
  389. err = grub_net_send_udp_packet (data->sock, &nb_err);
  390. }
  391. if (err)
  392. grub_print_error ();
  393. grub_net_udp_close (data->sock);
  394. }
  395. grub_free (data);
  396. file->data = NULL;
  397. return GRUB_ERR_NONE;
  398. }
  399. static grub_err_t
  400. tftp_packets_pulled (struct grub_file *file)
  401. {
  402. tftp_data_t data = file->data;
  403. if (file->device->net->packs.count >= 50)
  404. return 0;
  405. if (!file->device->net->eof)
  406. file->device->net->stall = 0;
  407. if (data->ack_sent >= data->block)
  408. return 0;
  409. return ack (data, data->block);
  410. }
  411. static struct grub_net_app_protocol grub_tftp_protocol =
  412. {
  413. .name = "tftp",
  414. .open = tftp_open,
  415. .close = tftp_close,
  416. .packets_pulled = tftp_packets_pulled
  417. };
  418. GRUB_MOD_INIT (tftp)
  419. {
  420. grub_net_app_level_register (&grub_tftp_protocol);
  421. }
  422. GRUB_MOD_FINI (tftp)
  423. {
  424. grub_net_app_level_unregister (&grub_tftp_protocol);
  425. }