|
| 1 | +#include <arpa/inet.h> |
| 2 | +#include <ifaddrs.h> |
| 3 | +#include <linux/if_packet.h> |
| 4 | +#include <net/ethernet.h> |
| 5 | +#include <net/if.h> |
| 6 | +#include <netinet/in.h> |
| 7 | +#include <signal.h> |
| 8 | +#include <stdio.h> |
| 9 | +#include <stdlib.h> |
| 10 | +#include <string.h> |
| 11 | +#include <sys/ioctl.h> |
| 12 | +#include <sys/socket.h> |
| 13 | +#include <sys/types.h> |
| 14 | +#include <time.h> |
| 15 | +#include <unistd.h> |
| 16 | + |
| 17 | +int main(void) { |
| 18 | + printf("Enumerated network interfaces:\n"); |
| 19 | + struct ifaddrs *ifap, *it; |
| 20 | + getifaddrs(&ifap); |
| 21 | + // MAC address |
| 22 | + char MAC[12][18]; |
| 23 | + int index = 0; |
| 24 | + for (it = ifap; it; it = it->ifa_next) { |
| 25 | + unsigned char *mac = ((struct sockaddr_ll *)it->ifa_addr)->sll_addr; |
| 26 | + if (it->ifa_addr->sa_family == AF_INET && (it->ifa_flags & IFF_UP) == 1) |
| 27 | + index = if_nametoindex(it->ifa_name); |
| 28 | + if (it->ifa_addr->sa_family == AF_PACKET) |
| 29 | + sprintf(MAC[if_nametoindex(it->ifa_name)], |
| 30 | + "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], |
| 31 | + mac[4], mac[5]); |
| 32 | + } |
| 33 | + // Network address |
| 34 | + for (it = ifap; it; it = it->ifa_next) { |
| 35 | + if (it->ifa_addr->sa_family == AF_INET) { |
| 36 | + char inet_addr[INET_ADDRSTRLEN], netmask_addr[INET_ADDRSTRLEN], |
| 37 | + masked_addr[INET_ADDRSTRLEN]; |
| 38 | + struct in_addr *it_addr = &((struct sockaddr_in *)it->ifa_addr)->sin_addr, |
| 39 | + *it_netmask = |
| 40 | + &((struct sockaddr_in *)it->ifa_netmask)->sin_addr, |
| 41 | + masked_in; |
| 42 | + inet_ntop(AF_INET, it_addr, inet_addr, INET_ADDRSTRLEN); |
| 43 | + inet_ntop(AF_INET, it_netmask, netmask_addr, INET_ADDRSTRLEN); |
| 44 | + masked_in.s_addr = it_addr->s_addr | (~it_netmask->s_addr); |
| 45 | + inet_ntop(AF_INET, &masked_in, masked_addr, INET_ADDRSTRLEN); |
| 46 | + unsigned int idx = if_nametoindex(it->ifa_name); |
| 47 | + printf("%u - %-8s %16s %#x (%s) %s\n", idx, it->ifa_name, inet_addr, |
| 48 | + ntohl(it_netmask->s_addr), masked_addr, MAC[idx]); |
| 49 | + } |
| 50 | + } |
| 51 | + freeifaddrs(ifap); |
| 52 | + // username |
| 53 | + srand(time(NULL)); |
| 54 | + char username[48] = "["; |
| 55 | + sprintf(username, "%05d%05d[", rand() % 100000, rand() % 100000); |
| 56 | + printf("Enter your name: "); |
| 57 | + scanf("%s", username + 11); |
| 58 | + printf("Welcome, '%s'!\n", username + 11); |
| 59 | + struct ether_header *hdr; |
| 60 | + const size_t len_ether_header = sizeof(struct ether_header), |
| 61 | + user_len = strlen(username); |
| 62 | + const unsigned short protocol = htons(ETH_P_IP + 1); |
| 63 | + // child receive message |
| 64 | + unsigned int pid; |
| 65 | + if ((pid = fork()) == 0) { |
| 66 | + char recv_msg[4096]; |
| 67 | + int recv_sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); |
| 68 | + while (1) { |
| 69 | + recv(recv_sock, recv_msg, 4096, 0); |
| 70 | + hdr = (struct ether_header *)recv_msg; |
| 71 | + if (hdr->ether_type == protocol && |
| 72 | + strncmp(username, recv_msg + len_ether_header, user_len) != 0) { |
| 73 | + unsigned char *mac = hdr->ether_shost; |
| 74 | + printf(">>> <%02x:%02x:%02x:%02x:%02x:%02x> %s", mac[0], mac[1], mac[2], |
| 75 | + mac[3], mac[4], mac[5], recv_msg + len_ether_header + 10); |
| 76 | + } |
| 77 | + } |
| 78 | + return 0; |
| 79 | + } |
| 80 | + // link layer address |
| 81 | + struct sockaddr_ll addr; |
| 82 | + addr.sll_family = AF_PACKET; |
| 83 | + addr.sll_protocol = ETH_P_IP + 1; |
| 84 | + addr.sll_halen = ETH_ALEN; |
| 85 | + addr.sll_ifindex = index; |
| 86 | + for (size_t i = 0; i < 6; ++i) addr.sll_addr[i] = 0xff; |
| 87 | + // ethernet header |
| 88 | + char send_msg[4096] = {}; |
| 89 | + hdr = (struct ether_header *)send_msg; |
| 90 | + for (size_t i = 0; i < 6; ++i) { |
| 91 | + char m1 = MAC[index][i * 3], m2 = MAC[index][i * 3 + 1]; |
| 92 | + int d1 = m1 >= '0' && m1 <= '9' ? m1 - '0' : m1 - 'a' + 10, |
| 93 | + d2 = m2 >= '0' && m2 <= '9' ? m2 - '0' : m2 - 'a' + 10; |
| 94 | + hdr->ether_shost[i] = d1 * 16 + d2; |
| 95 | + hdr->ether_dhost[i] = 0xff; |
| 96 | + } |
| 97 | + hdr->ether_type = htons(ETH_P_IP + 1); |
| 98 | + // send message |
| 99 | + size_t len = len_ether_header, msg_len = 0; |
| 100 | + for (size_t i = 0; i < user_len; ++i) send_msg[len++] = username[i]; |
| 101 | + send_msg[len++] = ']'; |
| 102 | + send_msg[len++] = ':'; |
| 103 | + send_msg[len++] = ' '; |
| 104 | + int send_sock = socket(AF_PACKET, SOCK_RAW, protocol); |
| 105 | + while (fgets(send_msg + len, 4000, stdin)) { |
| 106 | + msg_len = strlen(send_msg + len) + 1; |
| 107 | + if (msg_len == 2) continue; |
| 108 | + send_msg[len + msg_len] = '\0'; |
| 109 | + sendto(send_sock, send_msg, len + msg_len, 0, (struct sockaddr *)&addr, |
| 110 | + sizeof(struct sockaddr_ll)); |
| 111 | + } |
| 112 | + kill(pid, SIGTERM); |
| 113 | + return 0; |
| 114 | +} |
0 commit comments