/*! * \file client.c * * \author Christos Choutouridis AEM:8997 */ #include #include #include #include #include #include #include #include "client.h" // Calculating the Check Sum static unsigned short _checksum(void *b, int len) { unsigned short *buf = b; unsigned int sum=0; unsigned short result; for ( sum = 0; len > 1; len -= 2 ) sum += *buf++; if ( len == 1 ) sum += *(unsigned char*)buf; sum = (sum >> 16) + (sum & 0xFFFF); sum += (sum >> 16); result = ~sum; return result; } static void _mk_ping_pkt (ping_pkt_t* pkt) { memset ((void*)&pkt->hdr, 0, sizeof(pkt->hdr)); //memset ((void*)&pkt->msg, '0', sizeof(pkt->msg)); pkt->msg[PING_MSG_S -1] = 0; pkt->hdr.type = ICMP_ECHO; pkt->hdr.un.echo.id = getpid(); pkt->hdr.un.echo.sequence = 0; pkt->hdr.checksum = _checksum (&pkt, sizeof(pkt)); } bool ping (device_t* dev) { static int sockfd =-1; int ttl_val =64; struct timeval tv_out = { 1, 0 }; if (sockfd == -1 && dev) { // create socket and set options at ip to TTL and value to 64 and timeout of recv if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1) { log_error ("Error: Can not create raw socket for icmp\n"); return false; } #ifndef NO_DEBUG log_debug("Debug: Raw socket for icmp created\n"); #endif int ret = setsockopt(sockfd, SOL_IP, IP_TTL, &ttl_val, sizeof(ttl_val)); ret |= setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv_out, sizeof(tv_out)); if (ret == -1) { log_error ("Error: Can not set options to socket\n"); close (sockfd); sockfd =-1; return false; } #ifndef NO_DEBUG log_debug("Debug: Raw socket options set\n"); #endif } if (!dev) { // Close socket close (sockfd); sockfd =-1; #ifndef NO_DEBUG log_debug ("Debug: Raw socket closed\n"); #endif return true; } else { // ping packet structure ping_pkt_t pkt; _mk_ping_pkt (&pkt); int st; //send packet struct sockaddr_in ping_addr = { .sin_family = AF_INET, .sin_addr = { htonl (device2addr (dev)) } }; if ((st=sendto (sockfd, &pkt, sizeof(pkt), 0, (struct sockaddr*)&ping_addr, sizeof(ping_addr))) <= 0) return false; #ifndef NO_DEBUG log_debug ("Debug: Echo send to %s\n", inet_ntoa(ping_addr.sin_addr)); #endif //receive packet struct sockaddr_in r_addr; socklen_t addr_len =sizeof(r_addr); if ((st=recvfrom (sockfd, &pkt, sizeof(pkt), 0, (struct sockaddr*)&r_addr, &addr_len)) <= 0) return false; #ifndef NO_DEBUG log_debug ("Debug: Echo received from %s\n", inet_ntoa(ping_addr.sin_addr)); #endif return (pkt.hdr.type == 69 && pkt.hdr.code == 0) ? true: false; } return false; }