├── contributors.txt ├── .gitignore ├── client.sh ├── server.sh ├── README.md ├── test_server.c ├── Makefile ├── test_client.c ├── tunnel.h ├── icmptunnel.c ├── icmp.h ├── icmp.c └── tunnel.c /contributors.txt: -------------------------------------------------------------------------------- 1 | Nishanth Devarajan 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | test_client 3 | test_server 4 | icmptunnel 5 | -------------------------------------------------------------------------------- /client.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Assigining an IP address and mask to 'tun0' interface 4 | ifconfig tun0 mtu 1500 up 10.0.1.2 netmask 255.255.255.0 5 | 6 | # Modifying IP routing tables 7 | route del default 8 | # 'server' is the IP address of the proxy server 9 | # 'gateway' and 'interface' can be obtained by usint the command: 'route -n' 10 | route add -host gw dev 11 | route add default gw 10.0.1.1 tun0 12 | -------------------------------------------------------------------------------- /server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Assigining an IP address and mask to 'tun0' interface 4 | ifconfig tun0 mtu 1500 up 10.0.1.1 netmask 255.255.255.0 5 | 6 | # Preventing the kernel to reply to any ICMP pings 7 | echo 1 | dd of=/proc/sys/net/ipv4/icmp_echo_ignore_all 8 | 9 | # Enabling IP forwarding 10 | echo 1 | dd of=/proc/sys/net/ipv4/ip_forward 11 | 12 | # Adding an iptables rule to masquerade for 10.0.0.0/8 13 | iptables -t nat -A POSTROUTING -s 10.0.0.0/8 -j MASQUERADE 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Installation 2 | 3 | Download repo and run `make` on client and server 4 | 5 | On server run the tunnel, the following: 6 | ``` 7 | ./icmptunnel -s 10.0.1.1 8 | ``` 9 | 10 | On the client, find gateway and its NIC, then go to client.sh: 11 | replace \ with the IP address of the proxy server, \ with gateway address 12 | Make sure your DNS server can access the proxy 13 | 14 | Run the tunnel on the client: 15 | ``` 16 | ./icmptunnel -c 17 | ``` 18 | The client should now be able to access the internet. 19 | -------------------------------------------------------------------------------- /test_server.c: -------------------------------------------------------------------------------- 1 | #include "icmp.h" 2 | 3 | #include 4 | #include 5 | 6 | 7 | int main() 8 | { 9 | struct icmp_packet packet; 10 | int sock_fd; 11 | 12 | sock_fd = open_icmp_socket(); 13 | bind_icmp_socket(sock_fd); 14 | 15 | printf("server initialized\n"); 16 | while(1) 17 | { 18 | receive_icmp_packet(sock_fd, &packet); 19 | printf("%s\n", packet.src_addr); 20 | printf("%s\n", packet.dest_addr); 21 | printf("%d\n", packet.type); 22 | printf("%s\n", packet.payload); 23 | } 24 | 25 | close_icmp_socket(sock_fd); 26 | } -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-I. 3 | DEPS = icmp.h tunnel.h 4 | 5 | %.o: %.c $(DEPS) 6 | $(CC) -c -o $@ $< $(CFLAGS) 7 | 8 | icmptunnel: icmptunnel.o icmp.o tunnel.o 9 | $(CC) -o icmptunnel icmp.o tunnel.o icmptunnel.o $(CFLAGS) 10 | 11 | test_server: icmp.o test_server.o 12 | $(CC) -o test_server icmp.o test_server.o $(CFLAGS) 13 | 14 | test_client: icmp.o test_client.o 15 | $(CC) -o test_client icmp.o test_client.o $(CFLAGS) 16 | 17 | test: test_server test_client 18 | 19 | all: icmptunnel test_server test_client 20 | 21 | clean: 22 | rm -f *.o test_server test_client icmptunnel 23 | -------------------------------------------------------------------------------- /test_client.c: -------------------------------------------------------------------------------- 1 | #include "icmp.h" 2 | #include 3 | 4 | int main() 5 | { 6 | struct icmp_packet packet; 7 | char *src_ip; 8 | char *dest_ip; 9 | int sock_fd; 10 | 11 | src_ip = "127.0.0.2"; 12 | dest_ip = "127.0.0.1"; 13 | 14 | strncpy(packet.src_addr, src_ip, strlen(src_ip) + 1); 15 | strncpy(packet.dest_addr, dest_ip, strlen(dest_ip) + 1); 16 | set_reply_type(&packet); 17 | packet.payload = "ZZZZZZ"; 18 | packet.payload_size = strlen(packet.payload); 19 | 20 | sock_fd = open_icmp_socket(); 21 | 22 | send_icmp_packet(sock_fd, &packet); 23 | 24 | close_icmp_socket(sock_fd); 25 | } 26 | -------------------------------------------------------------------------------- /tunnel.h: -------------------------------------------------------------------------------- 1 | /** 2 | * tunnel.h 3 | */ 4 | 5 | #ifndef tunnel_gaurd 6 | #define tunnel_gaurd 7 | 8 | #define SERVER_SCRIPT "server.sh" 9 | #define CLIENT_SCRIPT "client.sh" 10 | 11 | /** 12 | * Function to allocate a tunnel 13 | */ 14 | int tun_alloc(char *dev, int flags); 15 | 16 | /** 17 | * Function to read from a tunnel 18 | */ 19 | int tun_read(int tun_fd, char *buffer, int length); 20 | 21 | /** 22 | * Function to write to a tunnel 23 | */ 24 | int tun_write(int tun_fd, char *buffer, int length); 25 | 26 | /** 27 | * Function to run the tunnel 28 | */ 29 | void run_tunnel(char *dest, int server); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /icmptunnel.c: -------------------------------------------------------------------------------- 1 | /** 2 | * icmp_tunnel.c 3 | */ 4 | 5 | #include "tunnel.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #define ARG_SERVER_MODE "-s" 12 | #define ARG_CLIENT_MODE "-c" 13 | 14 | void usage() 15 | { 16 | printf("Wrong argument\n"); 17 | fprintf(stdout, "usage: icmptunnel [-s serverip] | [-c clientip]\n"); 18 | } 19 | 20 | int main(int argc, char *argv[]) 21 | { 22 | char ip_addr[100] = {0,}; 23 | if ((argc < 3) || ((strlen(argv[2]) + 1) > sizeof(ip_addr))) { 24 | usage(); 25 | exit(EXIT_FAILURE); 26 | } 27 | memcpy(ip_addr, argv[2], strlen(argv[2]) + 1); 28 | 29 | if (strncmp(argv[1], ARG_SERVER_MODE, strlen(argv[1])) == 0) { 30 | run_tunnel(ip_addr, 1); 31 | } 32 | else if (strncmp(argv[1], ARG_CLIENT_MODE, strlen(argv[1])) == 0) { 33 | run_tunnel(ip_addr, 0); 34 | } 35 | else { 36 | usage(); 37 | exit(EXIT_FAILURE); 38 | } 39 | 40 | return EXIT_SUCCESS; 41 | } 42 | -------------------------------------------------------------------------------- /icmp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * icmp.h 3 | */ 4 | 5 | #ifndef icmp_guard 6 | #define icmp_guard 7 | 8 | // Maximum transmission unit 9 | #define MTU 1500 10 | 11 | struct icmp_packet 12 | { 13 | char src_addr[100]; 14 | char dest_addr[100]; 15 | int type; 16 | char *payload; 17 | int payload_size; 18 | }; 19 | 20 | /** 21 | * Function to set packet type as ECHO 22 | */ 23 | void set_echo_type(struct icmp_packet *packet); 24 | 25 | /** 26 | * Function to set packet type as REPLY 27 | */ 28 | void set_reply_type(struct icmp_packet *packet); 29 | 30 | /** 31 | * Function to open a socket for icmp 32 | */ 33 | int open_icmp_socket(); 34 | 35 | /** 36 | * Function to bind the socket to INADDR_ANY 37 | */ 38 | void bind_icmp_socket(int sock_fd); 39 | 40 | /** 41 | * Function to send ICMP Packet 42 | */ 43 | void send_icmp_packet(int sock_fd, struct icmp_packet *packet_details); 44 | 45 | /** 46 | * Function to receive ICMP Packet 47 | */ 48 | void receive_icmp_packet(int sock_fd, struct icmp_packet *packet_details); 49 | 50 | /** 51 | * Function to close the icmp socket 52 | */ 53 | void close_icmp_socket(int sock_fd); 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /icmp.c: -------------------------------------------------------------------------------- 1 | /** 2 | * icmp.c 3 | */ 4 | 5 | #include "icmp.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | /** 16 | * Function to calculate checksum 17 | */ 18 | uint16_t in_cksum(uint16_t *addr, int len); 19 | 20 | /** 21 | * Function to fill up common headers for IP and ICMP 22 | */ 23 | void prepare_headers(struct iphdr *ip, struct icmphdr *icmp); 24 | 25 | /** 26 | * Function to set packet type as ECHO 27 | */ 28 | void set_echo_type(struct icmp_packet *packet) 29 | { 30 | packet->type = ICMP_ECHO; 31 | } 32 | 33 | /** 34 | * Function to set packet type as REPLY 35 | */ 36 | void set_reply_type(struct icmp_packet *packet) 37 | { 38 | packet->type = ICMP_ECHOREPLY; 39 | } 40 | 41 | /** 42 | * Function to open a socket for icmp 43 | */ 44 | int open_icmp_socket() 45 | { 46 | int sock_fd, on = 1; 47 | 48 | sock_fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); 49 | 50 | if (sock_fd == -1) { 51 | perror("Unable to open ICMP socket\n"); 52 | exit(EXIT_FAILURE); 53 | } 54 | 55 | // Providing IP Headers 56 | if (setsockopt(sock_fd, IPPROTO_IP, IP_HDRINCL, (const char *)&on, sizeof(on)) == -1) { 57 | perror("Unable to set IP_HDRINCL socket option\n"); 58 | exit(EXIT_FAILURE); 59 | } 60 | 61 | return sock_fd; 62 | } 63 | 64 | /** 65 | * Function to bind the socket to INADDR_ANY 66 | */ 67 | void bind_icmp_socket(int sock_fd) 68 | { 69 | struct sockaddr_in servaddr; 70 | 71 | // Initializing servaddr to bind to all interfaces 72 | memset(&servaddr, 0, sizeof(struct sockaddr_in)); 73 | servaddr.sin_family = AF_INET; 74 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 75 | 76 | // binding the socket 77 | if (bind(sock_fd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr_in)) == -1) { 78 | perror("Unable to bind\n"); 79 | exit(EXIT_FAILURE); 80 | } 81 | } 82 | 83 | /** 84 | * Function to send ICMP Packet 85 | */ 86 | void send_icmp_packet(int sock_fd, struct icmp_packet *packet_details) 87 | { 88 | // Source and destination IPs 89 | struct in_addr src_addr; 90 | struct in_addr dest_addr; 91 | 92 | struct iphdr *ip; 93 | struct icmphdr *icmp; 94 | char *icmp_payload; 95 | 96 | int packet_size; 97 | char *packet; 98 | 99 | struct sockaddr_in servaddr; 100 | 101 | inet_pton(AF_INET, packet_details->src_addr, &src_addr); 102 | inet_pton(AF_INET, packet_details->dest_addr, &dest_addr); 103 | 104 | packet_size = sizeof(struct iphdr) + sizeof(struct icmphdr) + packet_details->payload_size; 105 | packet = calloc(packet_size, sizeof(uint8_t)); 106 | if (packet == NULL) { 107 | perror("No memory available\n"); 108 | close_icmp_socket(sock_fd); 109 | exit(EXIT_FAILURE); 110 | } 111 | 112 | // Initializing header and payload pointers 113 | ip = (struct iphdr *)packet; 114 | icmp = (struct icmphdr *)(packet + sizeof(struct iphdr)); 115 | icmp_payload = (char *)(packet + sizeof(struct iphdr) + sizeof(struct icmphdr)); 116 | 117 | prepare_headers(ip, icmp); 118 | 119 | ip->tot_len = htons(packet_size); 120 | ip->saddr = src_addr.s_addr; 121 | ip->daddr = dest_addr.s_addr; 122 | 123 | memcpy(icmp_payload, packet_details->payload, packet_details->payload_size); 124 | 125 | icmp->type = packet_details->type; 126 | icmp->checksum = 0; 127 | icmp->checksum = in_cksum((unsigned short *)icmp, sizeof(struct icmphdr) + packet_details->payload_size); 128 | 129 | memset(&servaddr, 0, sizeof(struct sockaddr_in)); 130 | servaddr.sin_family = AF_INET; 131 | servaddr.sin_addr.s_addr = dest_addr.s_addr; 132 | 133 | // Sending the packet 134 | sendto(sock_fd, packet, packet_size, 0, (struct sockaddr *)&servaddr, sizeof(struct sockaddr_in)); 135 | 136 | free(packet); 137 | } 138 | 139 | /** 140 | * Function to receive an ICMP packet 141 | */ 142 | void receive_icmp_packet(int sock_fd, struct icmp_packet *packet_details) 143 | { 144 | struct sockaddr_in src_addr; 145 | struct sockaddr_in dest_addr; 146 | 147 | struct iphdr *ip; 148 | struct icmphdr *icmp; 149 | char *icmp_payload; 150 | 151 | int packet_size; 152 | char *packet; 153 | 154 | int src_addr_size; 155 | 156 | packet = calloc(MTU, sizeof(uint8_t)); 157 | if (packet == NULL) { 158 | perror("No memory available\n"); 159 | close_icmp_socket(sock_fd); 160 | exit(-1); 161 | } 162 | 163 | src_addr_size = sizeof(struct sockaddr_in); 164 | 165 | // Receiving packet 166 | packet_size = recvfrom(sock_fd, packet, MTU, 0, (struct sockaddr *)&(src_addr), &src_addr_size); 167 | 168 | ip = (struct iphdr *)packet; 169 | icmp = (struct icmphdr *)(packet + sizeof(struct iphdr)); 170 | icmp_payload = (char *)(packet + sizeof(struct iphdr) + sizeof(struct icmphdr)); 171 | 172 | // Filling up packet_details 173 | inet_ntop(AF_INET, &(ip->saddr), packet_details->src_addr, INET_ADDRSTRLEN); 174 | inet_ntop(AF_INET, &(ip->daddr), packet_details->dest_addr, INET_ADDRSTRLEN); 175 | packet_details->type = icmp->type; 176 | packet_details->payload_size = packet_size - sizeof(struct iphdr) - sizeof(struct icmphdr); 177 | packet_details->payload = calloc(packet_details->payload_size, sizeof(uint8_t)); 178 | if (packet_details->payload == NULL) { 179 | perror("No memory available\n"); 180 | close_icmp_socket(sock_fd); 181 | exit(-1); 182 | } 183 | 184 | memcpy(packet_details->payload, icmp_payload, packet_details->payload_size); 185 | 186 | free(packet); 187 | } 188 | 189 | /** 190 | * Function to close the icmp socket 191 | */ 192 | void close_icmp_socket(int sock_fd) 193 | { 194 | close(sock_fd); 195 | } 196 | 197 | /** 198 | * Function to calculate checksum 199 | */ 200 | uint16_t in_cksum(uint16_t *addr, int len) 201 | { 202 | int nleft = len; 203 | uint32_t sum = 0; 204 | uint16_t *w = addr; 205 | uint16_t answer = 0; 206 | 207 | // Adding 16 bits sequentially in sum 208 | while (nleft > 1) { 209 | sum += *w; 210 | nleft -= 2; 211 | w++; 212 | } 213 | 214 | // If an odd byte is left 215 | if (nleft == 1) { 216 | *(unsigned char *) (&answer) = *(unsigned char *) w; 217 | sum += answer; 218 | } 219 | 220 | sum = (sum >> 16) + (sum & 0xffff); 221 | sum += (sum >> 16); 222 | answer = ~sum; 223 | 224 | return answer; 225 | } 226 | 227 | /** 228 | * Function to fill up common headers for IP and ICMP 229 | */ 230 | void prepare_headers(struct iphdr *ip, struct icmphdr *icmp) 231 | { 232 | ip->version = 4; 233 | ip->ihl = 5; 234 | ip->tos = 0; 235 | ip->id = rand(); 236 | ip->frag_off = 0; 237 | ip->ttl = 255; 238 | ip->protocol = IPPROTO_ICMP; 239 | 240 | icmp->code = 0; 241 | icmp->un.echo.sequence = rand(); 242 | icmp->un.echo.id = rand(); 243 | icmp->checksum = 0; 244 | } 245 | -------------------------------------------------------------------------------- /tunnel.c: -------------------------------------------------------------------------------- 1 | /** 2 | * tunnel.c 3 | */ 4 | 5 | #include "icmp.h" 6 | #include "tunnel.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | 26 | #define DEFAULT_ROUTE "0.0.0.0" 27 | 28 | /** 29 | * Function to allocate a tunnel 30 | */ 31 | int tun_alloc(char *dev, int flags) 32 | { 33 | struct ifreq ifr; 34 | int tun_fd, err; 35 | char *clonedev = "/dev/net/tun"; 36 | printf("[DEBUG] Allocating tunnel\n"); 37 | 38 | tun_fd = open(clonedev, O_RDWR); 39 | 40 | if(tun_fd == -1) { 41 | perror("Unable to open clone device\n"); 42 | exit(EXIT_FAILURE); 43 | } 44 | 45 | memset(&ifr, 0, sizeof(ifr)); 46 | 47 | ifr.ifr_flags = flags; 48 | 49 | if (*dev) { 50 | strncpy(ifr.ifr_name, dev, IFNAMSIZ); 51 | } 52 | 53 | if ((err=ioctl(tun_fd, TUNSETIFF, (void *)&ifr)) < 0) { 54 | close(tun_fd); 55 | fprintf(stderr, "Error returned by ioctl(): %s\n", strerror(err)); 56 | perror("Error in tun_alloc()\n"); 57 | exit(EXIT_FAILURE); 58 | } 59 | 60 | printf("[DEBUG] Allocatating tunnel2"); 61 | 62 | printf("[DEBUG] Created tunnel %s\n", dev); 63 | 64 | return tun_fd; 65 | } 66 | 67 | /** 68 | * Function to read from a tunnel 69 | */ 70 | int tun_read(int tun_fd, char *buffer, int length) 71 | { 72 | int bytes_read; 73 | printf("[DEBUG] Reading from tunnel\n"); 74 | bytes_read = read(tun_fd, buffer, length); 75 | 76 | if (bytes_read == -1) { 77 | perror("Unable to read from tunnel\n"); 78 | exit(EXIT_FAILURE); 79 | } 80 | else { 81 | return bytes_read; 82 | } 83 | } 84 | 85 | /** 86 | * Function to write to a tunnel 87 | */ 88 | int tun_write(int tun_fd, char *buffer, int length) 89 | { 90 | int bytes_written; 91 | printf("[DEBUG] Writing to tunnel\n"); 92 | bytes_written = write(tun_fd, buffer, length); 93 | 94 | if (bytes_written == -1) { 95 | perror("Unable to write to tunnel\n"); 96 | exit(EXIT_FAILURE); 97 | } 98 | else { 99 | return bytes_written; 100 | } 101 | } 102 | 103 | /** 104 | * Function to configure the network 105 | */ 106 | void configure_network(int server) 107 | { 108 | int pid, status; 109 | char path[100]; 110 | char *const args[] = {path, NULL}; 111 | 112 | if (server) { 113 | if (sizeof(SERVER_SCRIPT) > sizeof(path)){ 114 | perror("Server script path is too long\n"); 115 | exit(EXIT_FAILURE); 116 | } 117 | strncpy(path, SERVER_SCRIPT, strlen(SERVER_SCRIPT) + 1); 118 | } 119 | else { 120 | if (sizeof(CLIENT_SCRIPT) > sizeof(path)){ 121 | perror("Client script path is too long\n"); 122 | exit(EXIT_FAILURE); 123 | } 124 | strncpy(path, CLIENT_SCRIPT, strlen(CLIENT_SCRIPT) + 1); 125 | } 126 | 127 | pid = fork(); 128 | 129 | if (pid == -1) { 130 | perror("Unable to fork\n"); 131 | exit(EXIT_FAILURE); 132 | } 133 | 134 | if (pid==0) { 135 | // Child process, run the script 136 | exit(execv(path, args)); 137 | } 138 | else { 139 | // Parent process 140 | waitpid(pid, &status, 0); 141 | if (WEXITSTATUS(status) == 0) { 142 | // Script executed correctly 143 | printf("[DEBUG] Script ran successfully\n"); 144 | } 145 | else { 146 | // Some error 147 | printf("[DEBUG] Error in running script\n"); 148 | } 149 | } 150 | } 151 | 152 | 153 | /** 154 | * Function to run the tunnel 155 | */ 156 | void run_tunnel(char *dest, int server) 157 | { 158 | struct icmp_packet packet; 159 | int tun_fd, sock_fd; 160 | 161 | fd_set fs; 162 | 163 | tun_fd = tun_alloc("tun0", IFF_TUN | IFF_NO_PI); 164 | 165 | printf("[DEBUG] Starting tunnel - Dest: %s, Server: %d\n", dest, server); 166 | printf("[DEBUG] Opening ICMP socket\n"); 167 | sock_fd = open_icmp_socket(); 168 | 169 | if (server) { 170 | printf("[DEBUG] Binding ICMP socket\n"); 171 | bind_icmp_socket(sock_fd); 172 | } 173 | 174 | configure_network(server); 175 | 176 | while (1) { 177 | FD_ZERO(&fs); 178 | FD_SET(tun_fd, &fs); 179 | FD_SET(sock_fd, &fs); 180 | 181 | select(tun_fd>sock_fd?tun_fd+1:sock_fd+1, &fs, NULL, NULL, NULL); 182 | 183 | if (FD_ISSET(tun_fd, &fs)) { 184 | printf("[DEBUG] Data needs to be readed from tun device\n"); 185 | // Reading data from tun device and sending ICMP packet 186 | 187 | printf("[DEBUG] Preparing ICMP packet to be sent\n"); 188 | // Preparing ICMP packet to be sent 189 | memset(&packet, 0, sizeof(struct icmp_packet)); 190 | printf("[DEBUG] Destination address: %s\n", dest); 191 | 192 | if (sizeof(DEFAULT_ROUTE) > sizeof(packet.src_addr)){ 193 | perror("Lack of space: size of DEFAULT_ROUTE > size of src_addr\n"); 194 | close(tun_fd); 195 | close(sock_fd); 196 | exit(EXIT_FAILURE); 197 | } 198 | strncpy(packet.src_addr, DEFAULT_ROUTE, strlen(DEFAULT_ROUTE) + 1); 199 | 200 | if ((strlen(dest) + 1) > sizeof(packet.dest_addr)){ 201 | perror("Lack of space for copy size of DEFAULT_ROUTE > size of dest_addr\n"); 202 | close(sock_fd); 203 | exit(EXIT_FAILURE); 204 | } 205 | strncpy(packet.dest_addr, dest, strlen(dest) + 1); 206 | 207 | if(server) { 208 | set_reply_type(&packet); 209 | } 210 | else { 211 | set_echo_type(&packet); 212 | } 213 | packet.payload = calloc(MTU, sizeof(uint8_t)); 214 | if (packet.payload == NULL){ 215 | perror("No memory available\n"); 216 | exit(EXIT_FAILURE); 217 | } 218 | 219 | packet.payload_size = tun_read(tun_fd, packet.payload, MTU); 220 | if(packet.payload_size == -1) { 221 | perror("Error while reading from tun device\n"); 222 | exit(EXIT_FAILURE); 223 | } 224 | 225 | printf("[DEBUG] Sending ICMP packet with payload_size: %d, payload: %s\n", packet.payload_size, packet.payload); 226 | // Sending ICMP packet 227 | send_icmp_packet(sock_fd, &packet); 228 | 229 | free(packet.payload); 230 | } 231 | 232 | if (FD_ISSET(sock_fd, &fs)) { 233 | printf("[DEBUG] Received ICMP packet\n"); 234 | // Reading data from remote socket and sending to tun device 235 | 236 | // Getting ICMP packet 237 | memset(&packet, 0, sizeof(struct icmp_packet)); 238 | receive_icmp_packet(sock_fd, &packet); 239 | 240 | printf("[DEBUG] Read ICMP packet with src: %s, dest: %s, payload_size: %d, payload: %s\n", packet.src_addr, packet.dest_addr, packet.payload_size, packet.payload); 241 | // Writing out to tun device 242 | tun_write(tun_fd, packet.payload, packet.payload_size); 243 | 244 | printf("[DEBUG] Src address being copied: %s\n", packet.src_addr); 245 | strncpy(dest, packet.src_addr, strlen(packet.src_addr) + 1); 246 | } 247 | } 248 | 249 | } 250 | --------------------------------------------------------------------------------