A messenger application for Raspberry Pi Zerofor A.U.TH (Real time Embedded systems).
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

112 lines
3.1 KiB

  1. /*!
  2. * \file client.c
  3. *
  4. * \author Christos Choutouridis AEM:8997 <cchoutou@ece.auth.gr>
  5. */
  6. #include <sys/socket.h>
  7. #include <arpa/inet.h>
  8. #include <netinet/ip_icmp.h>
  9. #include <sys/time.h>
  10. #include <unistd.h>
  11. #include <string.h>
  12. #include <stdio.h>
  13. #include "client.h"
  14. // Calculating the Check Sum
  15. static unsigned short _checksum(void *b, int len) {
  16. unsigned short *buf = b;
  17. unsigned int sum=0;
  18. unsigned short result;
  19. for ( sum = 0; len > 1; len -= 2 )
  20. sum += *buf++;
  21. if ( len == 1 )
  22. sum += *(unsigned char*)buf;
  23. sum = (sum >> 16) + (sum & 0xFFFF);
  24. sum += (sum >> 16);
  25. result = ~sum;
  26. return result;
  27. }
  28. static void _mk_ping_pkt (ping_pkt_t* pkt) {
  29. memset ((void*)&pkt->hdr, 0, sizeof(pkt->hdr));
  30. //memset ((void*)&pkt->msg, '0', sizeof(pkt->msg));
  31. pkt->msg[PING_MSG_S -1] = 0;
  32. pkt->hdr.type = ICMP_ECHO;
  33. pkt->hdr.un.echo.id = getpid();
  34. pkt->hdr.un.echo.sequence = 0;
  35. pkt->hdr.checksum = _checksum (&pkt, sizeof(pkt));
  36. }
  37. bool ping (device_t* dev) {
  38. static int sockfd =-1;
  39. int ttl_val =64;
  40. struct timeval tv_out = { 1, 0 };
  41. if (sockfd == -1 && dev) {
  42. // create socket and set options at ip to TTL and value to 64 and timeout of recv
  43. if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1) {
  44. log_error ("Error: Can not create raw socket for icmp\n");
  45. return false;
  46. }
  47. #ifndef NO_DEBUG
  48. log_debug("Debug: Raw socket for icmp created\n");
  49. #endif
  50. int ret = setsockopt(sockfd, SOL_IP, IP_TTL, &ttl_val, sizeof(ttl_val));
  51. ret |= setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv_out, sizeof(tv_out));
  52. if (ret == -1) {
  53. log_error ("Error: Can not set options to socket\n");
  54. close (sockfd);
  55. sockfd =-1;
  56. return false;
  57. }
  58. #ifndef NO_DEBUG
  59. log_debug("Debug: Raw socket options set\n");
  60. #endif
  61. }
  62. if (!dev) {
  63. // Close socket
  64. close (sockfd);
  65. sockfd =-1;
  66. #ifndef NO_DEBUG
  67. log_debug ("Debug: Raw socket closed\n");
  68. #endif
  69. return true;
  70. }
  71. else {
  72. // ping packet structure
  73. ping_pkt_t pkt;
  74. _mk_ping_pkt (&pkt);
  75. int st;
  76. //send packet
  77. struct sockaddr_in ping_addr = {
  78. .sin_family = AF_INET,
  79. .sin_addr = { htonl (device2addr (dev)) }
  80. };
  81. if ((st=sendto (sockfd, &pkt, sizeof(pkt), 0, (struct sockaddr*)&ping_addr, sizeof(ping_addr))) <= 0)
  82. return false;
  83. #ifndef NO_DEBUG
  84. log_debug ("Debug: Echo send to %s\n", inet_ntoa(ping_addr.sin_addr));
  85. #endif
  86. //receive packet
  87. struct sockaddr_in r_addr;
  88. socklen_t addr_len =sizeof(r_addr);
  89. if ((st=recvfrom (sockfd, &pkt, sizeof(pkt), 0, (struct sockaddr*)&r_addr, &addr_len)) <= 0)
  90. return false;
  91. #ifndef NO_DEBUG
  92. log_debug ("Debug: Echo received from %s\n", inet_ntoa(ping_addr.sin_addr));
  93. #endif
  94. return (pkt.hdr.type == 69 && pkt.hdr.code == 0) ? true: false;
  95. }
  96. return false;
  97. }