|
| 1 | +#include "zdtmtst.h" |
| 2 | + |
| 3 | +const char *test_doc = "static test for ICMP socket\n"; |
| 4 | +const char *test_author = "समीर सिंह Sameer Singh <[email protected]>\n"; |
| 5 | + |
| 6 | +/* Description: |
| 7 | + * Send a ping to localhost using ICMP socket |
| 8 | + */ |
| 9 | + |
| 10 | +#include <string.h> |
| 11 | +#include <unistd.h> |
| 12 | +#include <sys/socket.h> |
| 13 | +#include <netinet/in.h> |
| 14 | +#if defined(ZDTM_IPV6) |
| 15 | +#include <netinet/icmp6.h> |
| 16 | +#else |
| 17 | +#include <netinet/ip_icmp.h> |
| 18 | +#endif |
| 19 | +#include <arpa/inet.h> |
| 20 | +#include <sys/time.h> |
| 21 | +#include <netdb.h> |
| 22 | + |
| 23 | +#include "sysctl.h" |
| 24 | + |
| 25 | +#define PACKET_SIZE 64 |
| 26 | +#define RECV_TIMEOUT 1 |
| 27 | + |
| 28 | +static int echo_id = 1234; |
| 29 | + |
| 30 | +#if defined(ZDTM_IPV6) |
| 31 | +#define TEST_ICMP_ECHOREPLY ICMP6_ECHOREPLY |
| 32 | +#else |
| 33 | +#define TEST_ICMP_ECHOREPLY ICMP_ECHOREPLY |
| 34 | +#endif |
| 35 | +int main(int argc, char **argv) |
| 36 | +{ |
| 37 | + int ret, sock, seq = 0; |
| 38 | + char packet[PACKET_SIZE], recv_packet[PACKET_SIZE]; |
| 39 | + |
| 40 | + struct timeval tv; |
| 41 | +#if defined(ZDTM_IPV6) |
| 42 | + struct sockaddr_in6 addr, recv_addr; |
| 43 | +#else |
| 44 | + struct icmphdr icmp_header, *icmp_reply; |
| 45 | +#endif |
| 46 | + struct sockaddr_in addr, recv_addr; |
| 47 | + socklen_t addr_len; |
| 48 | + |
| 49 | + // Allow GIDs 0-58468 to open an unprivileged ICMP socket |
| 50 | + if (sysctl_write_str("/proc/sys/net/ipv4/ping_group_range", "0 58468")) |
| 51 | + return -1; |
| 52 | + |
| 53 | + test_init(argc, argv); |
| 54 | + |
| 55 | +#if defined(ZDTM_IPV6) |
| 56 | + sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6); |
| 57 | +#else |
| 58 | + sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP); |
| 59 | +#endif |
| 60 | + if (sock < 0) { |
| 61 | + pr_perror("Can't create socket"); |
| 62 | + return 1; |
| 63 | + } |
| 64 | + |
| 65 | + tv.tv_sec = RECV_TIMEOUT; |
| 66 | + tv.tv_usec = 0; |
| 67 | + if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { |
| 68 | + pr_perror("Can't set socket option"); |
| 69 | + return 1; |
| 70 | + } |
| 71 | + |
| 72 | + memset(&addr, 0, sizeof(addr)); |
| 73 | + memset(&icmp_header, 0, sizeof(icmp_header)); |
| 74 | +#if defined(ZDTM_IPV6) |
| 75 | + addr.sin6_family = AF_INET6; |
| 76 | + inet_pton(AF_INET6, "::1", &addr.sin6_addr); |
| 77 | + |
| 78 | + icmp_header.icmp6_type = ICMP6_ECHO_REQUEST; |
| 79 | + icmp_header.icmp6_code = 0; |
| 80 | + icmp_header.icmp6_id = echo_id; |
| 81 | + icmp_header.icmp6_seq = seq; |
| 82 | +#else |
| 83 | + addr.sin_family = AF_INET; |
| 84 | + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); |
| 85 | + |
| 86 | + icmp_header.type = ICMP_ECHO; |
| 87 | + icmp_header.code = 0; |
| 88 | + icmp_header.un.echo.id = echo_id; |
| 89 | + icmp_header.un.echo.sequence = seq; |
| 90 | +#endif |
| 91 | + |
| 92 | + memcpy(packet, &icmp_header, sizeof(icmp_header)); |
| 93 | + memset(packet + sizeof(icmp_header), 0xa5, |
| 94 | + PACKET_SIZE - sizeof(icmp_header)); |
| 95 | + |
| 96 | + test_daemon(); |
| 97 | + test_waitsig(); |
| 98 | + |
| 99 | + ret = sendto(sock, packet, PACKET_SIZE, 0, |
| 100 | + (struct sockaddr *)&addr, sizeof(addr)); |
| 101 | + |
| 102 | + if (ret < 0) { |
| 103 | + fail("Can't send"); |
| 104 | + return 1; |
| 105 | + } |
| 106 | + |
| 107 | + addr_len = sizeof(recv_addr); |
| 108 | + |
| 109 | + ret = recvfrom(sock, recv_packet, sizeof(recv_packet), 0, |
| 110 | + (struct sockaddr *)&recv_addr, &addr_len); |
| 111 | + |
| 112 | + if (ret < 0) { |
| 113 | + fail("Can't recv"); |
| 114 | + return 1; |
| 115 | + } |
| 116 | + |
| 117 | + icmp_reply = (struct icmphdr *)recv_packet; |
| 118 | + |
| 119 | + if (icmp_reply->type != ICMP_ECHOREPLY) { |
| 120 | + fail("Got no ICMP_ECHO_REPLY"); |
| 121 | + return 1; |
| 122 | + } |
| 123 | + |
| 124 | + close(sock); |
| 125 | + |
| 126 | + pass(); |
| 127 | + return 0; |
| 128 | +} |
0 commit comments