tftp.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #include <rtthread.h>
  2. #include <dfs_posix.h>
  3. #include <lwip/sockets.h>
  4. #include <finsh.h>
  5. #define TFTP_PORT 69
  6. /* opcode */
  7. #define TFTP_RRQ 1 /* read request */
  8. #define TFTP_WRQ 2 /* write request */
  9. #define TFTP_DATA 3 /* data */
  10. #define TFTP_ACK 4 /* ACK */
  11. #define TFTP_ERROR 5 /* error */
  12. rt_uint8_t tftp_buffer[512 + 4];
  13. /* tftp client */
  14. void tftp_get(const char* host, const char* dir, const char* filename)
  15. {
  16. int fd, sock_fd, sock_opt;
  17. struct sockaddr_in tftp_addr, from_addr;
  18. rt_uint32_t length;
  19. socklen_t fromlen;
  20. /* make local file name */
  21. rt_snprintf((char*)tftp_buffer, sizeof(tftp_buffer),
  22. "%s/%s", dir, filename);
  23. /* open local file for write */
  24. fd = open((char*)tftp_buffer, O_RDWR | O_CREAT, 0);
  25. if (fd < 0)
  26. {
  27. rt_kprintf("can't open local filename\n");
  28. return;
  29. }
  30. /* connect to tftp server */
  31. inet_aton(host, (struct in_addr*)&(tftp_addr.sin_addr));
  32. tftp_addr.sin_family = AF_INET;
  33. tftp_addr.sin_port = htons(TFTP_PORT);
  34. sock_fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
  35. if (sock_fd < 0)
  36. {
  37. close(fd);
  38. rt_kprintf("can't create a socket\n");
  39. return ;
  40. }
  41. /* set socket option */
  42. sock_opt = 5000; /* 5 seconds */
  43. lwip_setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &sock_opt, sizeof(sock_opt));
  44. /* make tftp request */
  45. tftp_buffer[0] = 0; /* opcode */
  46. tftp_buffer[1] = TFTP_RRQ; /* RRQ */
  47. length = rt_sprintf((char *)&tftp_buffer[2], "%s", filename) + 2;
  48. tftp_buffer[length] = 0; length ++;
  49. length += rt_sprintf((char*)&tftp_buffer[length], "%s", "octet");
  50. tftp_buffer[length] = 0; length ++;
  51. fromlen = sizeof(struct sockaddr_in);
  52. /* send request */
  53. lwip_sendto(sock_fd, tftp_buffer, length, 0,
  54. (struct sockaddr *)&tftp_addr, fromlen);
  55. do
  56. {
  57. length = lwip_recvfrom(sock_fd, tftp_buffer, sizeof(tftp_buffer), 0,
  58. (struct sockaddr *)&from_addr, &fromlen);
  59. if (length > 0)
  60. {
  61. write(fd, (char*)&tftp_buffer[4], length - 4);
  62. rt_kprintf("#");
  63. /* make ACK */
  64. tftp_buffer[0] = 0; tftp_buffer[1] = TFTP_ACK; /* opcode */
  65. /* send ACK */
  66. lwip_sendto(sock_fd, tftp_buffer, 4, 0,
  67. (struct sockaddr *)&from_addr, fromlen);
  68. }
  69. } while (length == 516);
  70. if (length == 0) rt_kprintf("timeout\n");
  71. else rt_kprintf("done\n");
  72. close(fd);
  73. lwip_close(sock_fd);
  74. }
  75. FINSH_FUNCTION_EXPORT(tftp_get, get file from tftp server);
  76. void tftp_put(const char* host, const char* dir, const char* filename)
  77. {
  78. int fd, sock_fd, sock_opt;
  79. struct sockaddr_in tftp_addr, from_addr;
  80. rt_uint32_t length, block_number = 0;
  81. socklen_t fromlen;
  82. /* make local file name */
  83. rt_snprintf((char*)tftp_buffer, sizeof(tftp_buffer),
  84. "%s/%s", dir, filename);
  85. /* open local file for write */
  86. fd = open((char*)tftp_buffer, O_RDONLY, 0);
  87. if (fd < 0)
  88. {
  89. rt_kprintf("can't open local filename\n");
  90. return;
  91. }
  92. /* connect to tftp server */
  93. inet_aton(host, (struct in_addr*)&(tftp_addr.sin_addr));
  94. tftp_addr.sin_family = AF_INET;
  95. tftp_addr.sin_port = htons(TFTP_PORT);
  96. sock_fd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
  97. if (sock_fd < 0)
  98. {
  99. close(fd);
  100. rt_kprintf("can't create a socket\n");
  101. return ;
  102. }
  103. /* set socket option */
  104. sock_opt = 5000; /* 5 seconds */
  105. lwip_setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &sock_opt, sizeof(sock_opt));
  106. /* make tftp request */
  107. tftp_buffer[0] = 0; /* opcode */
  108. tftp_buffer[1] = TFTP_WRQ; /* WRQ */
  109. length = rt_sprintf((char *)&tftp_buffer[2], "%s", filename) + 2;
  110. tftp_buffer[length] = 0; length ++;
  111. length += rt_sprintf((char*)&tftp_buffer[length], "%s", "octet");
  112. tftp_buffer[length] = 0; length ++;
  113. fromlen = sizeof(struct sockaddr_in);
  114. /* send request */
  115. lwip_sendto(sock_fd, tftp_buffer, length, 0,
  116. (struct sockaddr *)&tftp_addr, fromlen);
  117. /* wait ACK 0 */
  118. length = lwip_recvfrom(sock_fd, tftp_buffer, sizeof(tftp_buffer), 0,
  119. (struct sockaddr *)&from_addr, &fromlen);
  120. if (!(tftp_buffer[0] == 0 &&
  121. tftp_buffer[1] == TFTP_ACK &&
  122. tftp_buffer[2] == 0 &&
  123. tftp_buffer[3] == 0))
  124. {
  125. rt_kprintf("tftp server error\n");
  126. close(fd);
  127. return;
  128. }
  129. block_number = 1;
  130. while (1)
  131. {
  132. length = read(fd, (char*)&tftp_buffer[4], 512);
  133. if (length > 0)
  134. {
  135. /* make opcode and block number */
  136. tftp_buffer[0] = 0; tftp_buffer[1] = TFTP_DATA;
  137. tftp_buffer[2] = (block_number >> 8) & 0xff;
  138. tftp_buffer[3] = block_number & 0xff;
  139. lwip_sendto(sock_fd, tftp_buffer, length + 4, 0,
  140. (struct sockaddr *)&from_addr, fromlen);
  141. }
  142. else
  143. {
  144. rt_kprintf("done\n");
  145. break; /* no data yet */
  146. }
  147. /* receive ack */
  148. length = lwip_recvfrom(sock_fd, tftp_buffer, sizeof(tftp_buffer), 0,
  149. (struct sockaddr *)&from_addr, &fromlen);
  150. if (length > 0)
  151. {
  152. if ((tftp_buffer[0] == 0 &&
  153. tftp_buffer[1] == TFTP_ACK &&
  154. tftp_buffer[2] == (block_number >> 8) & 0xff) &&
  155. tftp_buffer[3] == (block_number & 0xff))
  156. {
  157. block_number ++;
  158. rt_kprintf("#");
  159. }
  160. else
  161. {
  162. rt_kprintf("server respondes with an error\n");
  163. break;
  164. }
  165. }
  166. else if (length == 0)
  167. {
  168. rt_kprintf("server timeout\n");
  169. break;
  170. }
  171. }
  172. close(fd);
  173. lwip_close(sock_fd);
  174. }
  175. FINSH_FUNCTION_EXPORT(tftp_put, put file to tftp server);