tftp.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  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/priority_queue.h>
  28. #include <grub/i18n.h>
  29. GRUB_MOD_LICENSE ("GPLv3+");
  30. /* IP port for the MTFTP server used for Intel's PXE */
  31. enum
  32. {
  33. MTFTP_SERVER_PORT = 75,
  34. MTFTP_CLIENT_PORT = 76,
  35. /* IP port for the TFTP server */
  36. TFTP_SERVER_PORT = 69
  37. };
  38. enum
  39. {
  40. TFTP_DEFAULTSIZE_PACKET = 512,
  41. };
  42. enum
  43. {
  44. TFTP_CODE_EOF = 1,
  45. TFTP_CODE_MORE = 2,
  46. TFTP_CODE_ERROR = 3,
  47. TFTP_CODE_BOOT = 4,
  48. TFTP_CODE_CFG = 5
  49. };
  50. enum
  51. {
  52. TFTP_RRQ = 1,
  53. TFTP_WRQ = 2,
  54. TFTP_DATA = 3,
  55. TFTP_ACK = 4,
  56. TFTP_ERROR = 5,
  57. TFTP_OACK = 6
  58. };
  59. enum
  60. {
  61. TFTP_EUNDEF = 0, /* not defined */
  62. TFTP_ENOTFOUND = 1, /* file not found */
  63. TFTP_EACCESS = 2, /* access violation */
  64. TFTP_ENOSPACE = 3, /* disk full or allocation exceeded */
  65. TFTP_EBADOP = 4, /* illegal TFTP operation */
  66. TFTP_EBADID = 5, /* unknown transfer ID */
  67. TFTP_EEXISTS = 6, /* file already exists */
  68. TFTP_ENOUSER = 7 /* no such user */
  69. };
  70. struct tftphdr {
  71. grub_uint16_t opcode;
  72. union {
  73. grub_int8_t rrq[TFTP_DEFAULTSIZE_PACKET];
  74. struct {
  75. grub_uint16_t block;
  76. grub_int8_t download[0];
  77. } data;
  78. struct {
  79. grub_uint16_t block;
  80. } ack;
  81. struct {
  82. grub_uint16_t errcode;
  83. grub_int8_t errmsg[TFTP_DEFAULTSIZE_PACKET];
  84. } err;
  85. struct {
  86. grub_int8_t data[TFTP_DEFAULTSIZE_PACKET+2];
  87. } oack;
  88. } u;
  89. } GRUB_PACKED ;
  90. typedef struct tftp_data
  91. {
  92. grub_uint64_t file_size;
  93. grub_uint64_t block;
  94. grub_uint32_t block_size;
  95. grub_uint64_t ack_sent;
  96. int have_oack;
  97. struct grub_error_saved save_err;
  98. grub_net_udp_socket_t sock;
  99. grub_priority_queue_t pq;
  100. } *tftp_data_t;
  101. static int
  102. cmp_block (grub_uint16_t a, grub_uint16_t b)
  103. {
  104. grub_int16_t i = (grub_int16_t) (a - b);
  105. if (i > 0)
  106. return +1;
  107. if (i < 0)
  108. return -1;
  109. return 0;
  110. }
  111. static int
  112. cmp (const void *a__, const void *b__)
  113. {
  114. struct grub_net_buff *a_ = *(struct grub_net_buff **) a__;
  115. struct grub_net_buff *b_ = *(struct grub_net_buff **) b__;
  116. struct tftphdr *a = (struct tftphdr *) a_->data;
  117. struct tftphdr *b = (struct tftphdr *) b_->data;
  118. /* We want the first elements to be on top. */
  119. return -cmp_block (grub_be_to_cpu16 (a->u.data.block), grub_be_to_cpu16 (b->u.data.block));
  120. }
  121. static grub_err_t
  122. ack (tftp_data_t data, grub_uint64_t block)
  123. {
  124. struct tftphdr *tftph_ack;
  125. grub_uint8_t nbdata[512];
  126. struct grub_net_buff nb_ack;
  127. grub_err_t err;
  128. nb_ack.head = nbdata;
  129. nb_ack.end = nbdata + sizeof (nbdata);
  130. grub_netbuff_clear (&nb_ack);
  131. grub_netbuff_reserve (&nb_ack, 512);
  132. err = grub_netbuff_push (&nb_ack, sizeof (tftph_ack->opcode)
  133. + sizeof (tftph_ack->u.ack.block));
  134. if (err)
  135. return err;
  136. tftph_ack = (struct tftphdr *) nb_ack.data;
  137. tftph_ack->opcode = grub_cpu_to_be16_compile_time (TFTP_ACK);
  138. tftph_ack->u.ack.block = grub_cpu_to_be16 (block);
  139. err = grub_net_send_udp_packet (data->sock, &nb_ack);
  140. if (err)
  141. return err;
  142. data->ack_sent = block;
  143. return GRUB_ERR_NONE;
  144. }
  145. static grub_err_t
  146. tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)),
  147. struct grub_net_buff *nb,
  148. void *f)
  149. {
  150. grub_file_t file = f;
  151. struct tftphdr *tftph = (void *) nb->data;
  152. tftp_data_t data = file->data;
  153. grub_err_t err;
  154. grub_uint8_t *ptr;
  155. if (nb->tail - nb->data < (grub_ssize_t) sizeof (tftph->opcode))
  156. {
  157. grub_dprintf ("tftp", "TFTP packet too small\n");
  158. return GRUB_ERR_NONE;
  159. }
  160. tftph = (struct tftphdr *) nb->data;
  161. switch (grub_be_to_cpu16 (tftph->opcode))
  162. {
  163. case TFTP_OACK:
  164. data->block_size = TFTP_DEFAULTSIZE_PACKET;
  165. data->have_oack = 1;
  166. for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;)
  167. {
  168. if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0)
  169. data->file_size = grub_strtoul ((char *) ptr + sizeof ("tsize\0")
  170. - 1, 0, 0);
  171. if (grub_memcmp (ptr, "blksize\0", sizeof ("blksize\0") - 1) == 0)
  172. data->block_size = grub_strtoul ((char *) ptr + sizeof ("blksize\0")
  173. - 1, 0, 0);
  174. while (ptr < nb->tail && *ptr)
  175. ptr++;
  176. ptr++;
  177. }
  178. data->block = 0;
  179. grub_netbuff_free (nb);
  180. err = ack (data, 0);
  181. grub_error_save (&data->save_err);
  182. return GRUB_ERR_NONE;
  183. case TFTP_DATA:
  184. if (nb->tail - nb->data < (grub_ssize_t) (sizeof (tftph->opcode)
  185. + sizeof (tftph->u.data.block)))
  186. {
  187. grub_dprintf ("tftp", "TFTP packet too small\n");
  188. return GRUB_ERR_NONE;
  189. }
  190. err = grub_priority_queue_push (data->pq, &nb);
  191. if (err)
  192. return err;
  193. {
  194. struct grub_net_buff **nb_top_p, *nb_top;
  195. while (1)
  196. {
  197. nb_top_p = grub_priority_queue_top (data->pq);
  198. if (!nb_top_p)
  199. return GRUB_ERR_NONE;
  200. nb_top = *nb_top_p;
  201. tftph = (struct tftphdr *) nb_top->data;
  202. if (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) >= 0)
  203. break;
  204. ack (data, grub_be_to_cpu16 (tftph->u.data.block));
  205. grub_netbuff_free (nb_top);
  206. grub_priority_queue_pop (data->pq);
  207. }
  208. while (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) == 0)
  209. {
  210. unsigned size;
  211. grub_priority_queue_pop (data->pq);
  212. if (file->device->net->packs.count < 50)
  213. err = ack (data, data->block + 1);
  214. else
  215. {
  216. file->device->net->stall = 1;
  217. err = 0;
  218. }
  219. if (err)
  220. return err;
  221. err = grub_netbuff_pull (nb_top, sizeof (tftph->opcode) +
  222. sizeof (tftph->u.data.block));
  223. if (err)
  224. return err;
  225. size = nb_top->tail - nb_top->data;
  226. data->block++;
  227. if (size < data->block_size)
  228. {
  229. if (data->ack_sent < data->block)
  230. ack (data, data->block);
  231. file->device->net->eof = 1;
  232. file->device->net->stall = 1;
  233. grub_net_udp_close (data->sock);
  234. data->sock = NULL;
  235. }
  236. /* Prevent garbage in broken cards. Is it still necessary
  237. given that IP implementation has been fixed?
  238. */
  239. if (size > data->block_size)
  240. {
  241. err = grub_netbuff_unput (nb_top, size - data->block_size);
  242. if (err)
  243. return err;
  244. }
  245. /* If there is data, puts packet in socket list. */
  246. if ((nb_top->tail - nb_top->data) > 0)
  247. grub_net_put_packet (&file->device->net->packs, nb_top);
  248. else
  249. grub_netbuff_free (nb_top);
  250. }
  251. }
  252. return GRUB_ERR_NONE;
  253. case TFTP_ERROR:
  254. data->have_oack = 1;
  255. grub_netbuff_free (nb);
  256. grub_error (GRUB_ERR_IO, (char *) tftph->u.err.errmsg);
  257. grub_error_save (&data->save_err);
  258. return GRUB_ERR_NONE;
  259. default:
  260. grub_netbuff_free (nb);
  261. return GRUB_ERR_NONE;
  262. }
  263. }
  264. static void
  265. destroy_pq (tftp_data_t data)
  266. {
  267. struct grub_net_buff **nb_p;
  268. while ((nb_p = grub_priority_queue_top (data->pq)))
  269. {
  270. grub_netbuff_free (*nb_p);
  271. grub_priority_queue_pop (data->pq);
  272. }
  273. grub_priority_queue_destroy (data->pq);
  274. }
  275. static grub_err_t
  276. tftp_open (struct grub_file *file, const char *filename)
  277. {
  278. struct tftphdr *tftph;
  279. char *rrq;
  280. int i;
  281. int rrqlen;
  282. int hdrlen;
  283. grub_uint8_t open_data[1500];
  284. struct grub_net_buff nb;
  285. tftp_data_t data;
  286. grub_err_t err;
  287. grub_uint8_t *nbd;
  288. grub_net_network_level_address_t addr;
  289. data = grub_zalloc (sizeof (*data));
  290. if (!data)
  291. return grub_errno;
  292. nb.head = open_data;
  293. nb.end = open_data + sizeof (open_data);
  294. grub_netbuff_clear (&nb);
  295. grub_netbuff_reserve (&nb, 1500);
  296. err = grub_netbuff_push (&nb, sizeof (*tftph));
  297. if (err)
  298. {
  299. grub_free (data);
  300. return err;
  301. }
  302. tftph = (struct tftphdr *) nb.data;
  303. rrq = (char *) tftph->u.rrq;
  304. rrqlen = 0;
  305. tftph->opcode = grub_cpu_to_be16_compile_time (TFTP_RRQ);
  306. grub_strcpy (rrq, filename);
  307. rrqlen += grub_strlen (filename) + 1;
  308. rrq += grub_strlen (filename) + 1;
  309. grub_strcpy (rrq, "octet");
  310. rrqlen += grub_strlen ("octet") + 1;
  311. rrq += grub_strlen ("octet") + 1;
  312. grub_strcpy (rrq, "blksize");
  313. rrqlen += grub_strlen ("blksize") + 1;
  314. rrq += grub_strlen ("blksize") + 1;
  315. grub_strcpy (rrq, "1024");
  316. rrqlen += grub_strlen ("1024") + 1;
  317. rrq += grub_strlen ("1024") + 1;
  318. grub_strcpy (rrq, "tsize");
  319. rrqlen += grub_strlen ("tsize") + 1;
  320. rrq += grub_strlen ("tsize") + 1;
  321. grub_strcpy (rrq, "0");
  322. rrqlen += grub_strlen ("0") + 1;
  323. rrq += grub_strlen ("0") + 1;
  324. hdrlen = sizeof (tftph->opcode) + rrqlen;
  325. err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen));
  326. if (err)
  327. {
  328. grub_free (data);
  329. return err;
  330. }
  331. file->not_easily_seekable = 1;
  332. file->data = data;
  333. data->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), cmp);
  334. if (!data->pq)
  335. {
  336. grub_free (data);
  337. return grub_errno;
  338. }
  339. err = grub_net_resolve_address (file->device->net->server, &addr);
  340. if (err)
  341. {
  342. destroy_pq (data);
  343. grub_free (data);
  344. return err;
  345. }
  346. data->sock = grub_net_udp_open (addr,
  347. TFTP_SERVER_PORT, tftp_receive,
  348. file);
  349. if (!data->sock)
  350. {
  351. destroy_pq (data);
  352. grub_free (data);
  353. return grub_errno;
  354. }
  355. /* Receive OACK packet. */
  356. nbd = nb.data;
  357. for (i = 0; i < GRUB_NET_TRIES; i++)
  358. {
  359. nb.data = nbd;
  360. err = grub_net_send_udp_packet (data->sock, &nb);
  361. if (err)
  362. {
  363. grub_net_udp_close (data->sock);
  364. destroy_pq (data);
  365. grub_free (data);
  366. return err;
  367. }
  368. grub_net_poll_cards (GRUB_NET_INTERVAL + (i * GRUB_NET_INTERVAL_ADDITION),
  369. &data->have_oack);
  370. if (data->have_oack)
  371. break;
  372. }
  373. if (!data->have_oack)
  374. grub_error (GRUB_ERR_TIMEOUT, N_("time out opening `%s'"), filename);
  375. else
  376. grub_error_load (&data->save_err);
  377. if (grub_errno)
  378. {
  379. grub_net_udp_close (data->sock);
  380. destroy_pq (data);
  381. grub_free (data);
  382. return grub_errno;
  383. }
  384. file->size = data->file_size;
  385. return GRUB_ERR_NONE;
  386. }
  387. static grub_err_t
  388. tftp_close (struct grub_file *file)
  389. {
  390. tftp_data_t data = file->data;
  391. if (data->sock)
  392. {
  393. grub_uint8_t nbdata[512];
  394. grub_err_t err;
  395. struct grub_net_buff nb_err;
  396. struct tftphdr *tftph;
  397. nb_err.head = nbdata;
  398. nb_err.end = nbdata + sizeof (nbdata);
  399. grub_netbuff_clear (&nb_err);
  400. grub_netbuff_reserve (&nb_err, 512);
  401. err = grub_netbuff_push (&nb_err, sizeof (tftph->opcode)
  402. + sizeof (tftph->u.err.errcode)
  403. + sizeof ("closed"));
  404. if (!err)
  405. {
  406. tftph = (struct tftphdr *) nb_err.data;
  407. tftph->opcode = grub_cpu_to_be16_compile_time (TFTP_ERROR);
  408. tftph->u.err.errcode = grub_cpu_to_be16_compile_time (TFTP_EUNDEF);
  409. grub_memcpy (tftph->u.err.errmsg, "closed", sizeof ("closed"));
  410. err = grub_net_send_udp_packet (data->sock, &nb_err);
  411. }
  412. if (err)
  413. grub_print_error ();
  414. grub_net_udp_close (data->sock);
  415. }
  416. destroy_pq (data);
  417. grub_free (data);
  418. return GRUB_ERR_NONE;
  419. }
  420. static grub_err_t
  421. tftp_packets_pulled (struct grub_file *file)
  422. {
  423. tftp_data_t data = file->data;
  424. if (file->device->net->packs.count >= 50)
  425. return 0;
  426. if (!file->device->net->eof)
  427. file->device->net->stall = 0;
  428. if (data->ack_sent >= data->block)
  429. return 0;
  430. return ack (data, data->block);
  431. }
  432. static struct grub_net_app_protocol grub_tftp_protocol =
  433. {
  434. .name = "tftp",
  435. .open = tftp_open,
  436. .close = tftp_close,
  437. .packets_pulled = tftp_packets_pulled
  438. };
  439. GRUB_MOD_INIT (tftp)
  440. {
  441. grub_net_app_level_register (&grub_tftp_protocol);
  442. }
  443. GRUB_MOD_FINI (tftp)
  444. {
  445. grub_net_app_level_unregister (&grub_tftp_protocol);
  446. }