tftp.c 4.7 KB

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