traceroute.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #include "socket.h"
  2. #include "w5500.h"
  3. #include "ping.h"
  4. #define MAX_HOPS 30
  5. #define PORT 33434
  6. #define BUF_LEN 32
  7. extern void ping_wait_ms(int ms);
  8. uint8_t traceroute(uint8_t s, uint8_t* dest_addr) {
  9. uint8_t ttl = 1;
  10. uint8_t hops = 0;
  11. int ret;
  12. uint8_t curr_addr[4];
  13. uint8_t curr_name[64];
  14. while (ttl <= MAX_HOPS) {
  15. uint8_t sr = getSn_SR(s);
  16. eth_printf("SR: %02X", sr);
  17. switch (sr) {
  18. case SOCK_CLOSED:
  19. close(s);
  20. IINCHIP_WRITE(Sn_PROTO(s), IPPROTO_ICMP); // set ICMP Protocol
  21. if ((ret = socket(s, Sn_MR_IPRAW, 3000, 0)) != s) {
  22. eth_printf("socket %d fail %d", s, ret);
  23. return SOCKET_ERROR;
  24. }
  25. while (getSn_SR(s) != SOCK_IPRAW);
  26. ping_wait_ms(1000); // Wait for a bit
  27. break;
  28. case SOCK_IPRAW:
  29. send_traceroute_request(s, dest_addr, ttl);
  30. while (1) {
  31. uint16_t len = getSn_RX_RSR(s);
  32. if (len > 0) {
  33. uint8_t recv_addr[4];
  34. receive_traceroute_reply(s, recv_addr, len);
  35. eth_printf("Hop %d: %d.%d.%d.%d\n", ttl, recv_addr[0], recv_addr[1], recv_addr[2], recv_addr[3]);
  36. if (memcmp(recv_addr, dest_addr, 4) == 0) {
  37. eth_printf("Destination reached: %d.%d.%d.%d\n", recv_addr[0], recv_addr[1], recv_addr[2], recv_addr[3]);
  38. return 0; // Destination reached
  39. }
  40. break;
  41. }
  42. ping_wait_ms(50); // Wait a bit before retrying
  43. }
  44. break;
  45. default:
  46. break;
  47. }
  48. ttl++;
  49. if (ttl > MAX_HOPS) {
  50. eth_printf("Max hops reached.\n");
  51. break;
  52. }
  53. }
  54. return FUNCTION_ERROR;
  55. }
  56. void send_traceroute_request(uint8_t s, uint8_t* dest_addr, uint8_t ttl) {
  57. PINGMSGR PingRequest;
  58. uint16_t i;
  59. PingRequest.Type = PING_REQUEST;
  60. PingRequest.Code = CODE_ZERO;
  61. PingRequest.ID = htons(RandomID++);
  62. PingRequest.SeqNum = htons(RandomSeqNum++);
  63. for (i = 0; i < BUF_LEN; i++) {
  64. PingRequest.Data[i] = (i) % 8;
  65. }
  66. PingRequest.CheckSum = 0;
  67. PingRequest.CheckSum = htons(checksum((uint8_t*)&PingRequest, sizeof(PingRequest)));
  68. set_ttl(s, ttl); // Set TTL value for each packet sent
  69. sendto(s, (uint8_t*)&PingRequest, sizeof(PingRequest), dest_addr, PORT);
  70. eth_printf("Send traceroute request (TTL: %d) to %d.%d.%d.%d\n", ttl, dest_addr[0], dest_addr[1], dest_addr[2], dest_addr[3]);
  71. }
  72. void receive_traceroute_reply(uint8_t s, uint8_t* addr, uint16_t len) {
  73. uint16_t tmp_checksum;
  74. uint8_t data_buf[128];
  75. uint16_t rlen = recvfrom(s, data_buf, len, addr, &PORT);
  76. if (data_buf[0] == PING_REPLY) {
  77. PINGMSGR PingReply;
  78. PingReply.Type = data_buf[0];
  79. PingReply.Code = data_buf[1];
  80. PingReply.CheckSum = (data_buf[3] << 8) + data_buf[2];
  81. PingReply.ID = (data_buf[5] << 8) + data_buf[4];
  82. PingReply.SeqNum = (data_buf[7] << 8) + data_buf[6];
  83. tmp_checksum = ~checksum(data_buf, rlen);
  84. if (tmp_checksum != 0xffff) {
  85. eth_printf("Checksum failed\n");
  86. } else {
  87. eth_printf("Received reply from %d.%d.%d.%d: ID=%x SeqNum=%x\n", addr[0], addr[1], addr[2], addr[3], PingReply.ID, PingReply.SeqNum);
  88. }
  89. }
  90. }
  91. void set_ttl(uint8_t s, uint8_t ttl) {
  92. IINCHIP_WRITE(Sn_TTL(s), ttl);
  93. }
  94. uint16_t checksum(uint8_t* data_buf, uint16_t len) {
  95. uint16_t sum, tsum, i, j;
  96. uint32_t lsum;
  97. j = len >> 1;
  98. lsum = 0;
  99. tsum = 0;
  100. for (i = 0; i < j; ++i) {
  101. tsum = data_buf[i * 2];
  102. tsum = tsum << 8;
  103. tsum += data_buf[i * 2 + 1];
  104. lsum += tsum;
  105. }
  106. if (len % 2) {
  107. tsum = data_buf[i * 2];
  108. lsum += (tsum << 8);
  109. }
  110. sum = (uint16_t)lsum;
  111. sum = ~(sum + (lsum >> 16));
  112. return sum;
  113. }