This is a low-level network debugging utility that utilizes raw packet i/o to construct and deconstruct tcp, udp, ipv4, arp, and icmp packets over ethernet.

Dependencies:   mbed

Committer:
etherealflaim
Date:
Tue Oct 12 05:32:59 2010 +0000
Revision:
0:d494b853ce97
Child:
6:66c4cd9073aa
Initial Publish - Slightly unfinished, but usable

Who changed what in which revision?

UserRevisionLine numberNew contents of line
etherealflaim 0:d494b853ce97 1 #include "mbed.h"
etherealflaim 0:d494b853ce97 2 #include "string.h"
etherealflaim 0:d494b853ce97 3
etherealflaim 0:d494b853ce97 4 #include "util/types.h"
etherealflaim 0:d494b853ce97 5 #include "util/log.h"
etherealflaim 0:d494b853ce97 6 #include "util/util.h"
etherealflaim 0:d494b853ce97 7 #include "sniffer.h"
etherealflaim 0:d494b853ce97 8 #include "scanner.h"
etherealflaim 0:d494b853ce97 9
etherealflaim 0:d494b853ce97 10 #include <string>
etherealflaim 0:d494b853ce97 11 #include <queue>
etherealflaim 0:d494b853ce97 12
etherealflaim 0:d494b853ce97 13 // The main logger (global scope)
etherealflaim 0:d494b853ce97 14 Sniffer sniffer;
etherealflaim 0:d494b853ce97 15 Log main_log;
etherealflaim 0:d494b853ce97 16 bool main_running = true;
etherealflaim 0:d494b853ce97 17
etherealflaim 0:d494b853ce97 18 Ethernet_MAC BROADCAST_MAC = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
etherealflaim 0:d494b853ce97 19 Ethernet_MAC your_mac;
etherealflaim 0:d494b853ce97 20
etherealflaim 0:d494b853ce97 21 IP_Address my_ip = {0x00, 0x00, 0x00, 0x00};
etherealflaim 0:d494b853ce97 22 IP_Address your_ip;
etherealflaim 0:d494b853ce97 23
etherealflaim 0:d494b853ce97 24 bool portscan_started = false;
etherealflaim 0:d494b853ce97 25 bool ip_determined = false;
etherealflaim 0:d494b853ce97 26
etherealflaim 0:d494b853ce97 27 LocalFileSystem local("local");
etherealflaim 0:d494b853ce97 28 queue<string> commands;
etherealflaim 0:d494b853ce97 29
etherealflaim 0:d494b853ce97 30 inline void loadCommands()
etherealflaim 0:d494b853ce97 31 {
etherealflaim 0:d494b853ce97 32 FILE *fp = fopen("/local/ntcmd.txt", "r");
etherealflaim 0:d494b853ce97 33 if (fp)
etherealflaim 0:d494b853ce97 34 {
etherealflaim 0:d494b853ce97 35 char buf[256];
etherealflaim 0:d494b853ce97 36 while (NULL != fgets(buf, 256, fp))
etherealflaim 0:d494b853ce97 37 {
etherealflaim 0:d494b853ce97 38 if (buf[0] == '#') continue;
etherealflaim 0:d494b853ce97 39 else if (strlen(buf) == 0) continue;
etherealflaim 0:d494b853ce97 40 else if (!strncmp(buf, "ping", 4)) commands.push("ping");
etherealflaim 0:d494b853ce97 41 else if (!strncmp(buf, "portscan", 8)) commands.push("portscan");
etherealflaim 0:d494b853ce97 42 else if (!strncmp(buf, "identify", 8)) commands.push("identify");
etherealflaim 0:d494b853ce97 43 else main_log.printf("Unknown command: %s", buf);
etherealflaim 0:d494b853ce97 44 }
etherealflaim 0:d494b853ce97 45 }
etherealflaim 0:d494b853ce97 46 else
etherealflaim 0:d494b853ce97 47 {
etherealflaim 0:d494b853ce97 48 // Write the ntcmd file with some help
etherealflaim 0:d494b853ce97 49 main_log.printf("No net tool command file found!");
etherealflaim 0:d494b853ce97 50 fp = fopen("/local/ntcmd.txt", "w");
etherealflaim 0:d494b853ce97 51 fprintf(fp, "# Net Tool Command File Help:\n");
etherealflaim 0:d494b853ce97 52 fprintf(fp, "# 1. Comments start with the pound sign\n");
etherealflaim 0:d494b853ce97 53 fprintf(fp, "# 2. Commands are on a line by themselves\n");
etherealflaim 0:d494b853ce97 54 fprintf(fp, "# Known commands:\n");
etherealflaim 0:d494b853ce97 55 fprintf(fp, "# 1. ping - Send a ping to the host computer every 30 seconds and write results to PING.TXT\n");
etherealflaim 0:d494b853ce97 56 fprintf(fp, "# 2. portscan - Scan the host computer and write open TCP ports to PORTSCAN.TXT\n");
etherealflaim 0:d494b853ce97 57 fprintf(fp, "# 3. identify - Write host computer information to IDENTITY.TXT\n");
etherealflaim 0:d494b853ce97 58 }
etherealflaim 0:d494b853ce97 59 fclose(fp);
etherealflaim 0:d494b853ce97 60 }
etherealflaim 0:d494b853ce97 61
etherealflaim 0:d494b853ce97 62 Ticker ping_timer;
etherealflaim 0:d494b853ce97 63 void ping()
etherealflaim 0:d494b853ce97 64 {
etherealflaim 0:d494b853ce97 65 #define PING_BUFEFERSIZE (sizeof(IP_PacketHeader) + sizeof(ICMP_Packet))
etherealflaim 0:d494b853ce97 66 u8 buffer[PING_BUFEFERSIZE];
etherealflaim 0:d494b853ce97 67 IP_PacketHeader *ip_packet = (IP_PacketHeader*)buffer;
etherealflaim 0:d494b853ce97 68 ICMP_Packet *ping_packet = (ICMP_Packet*)ip_packet->data;
etherealflaim 0:d494b853ce97 69
etherealflaim 0:d494b853ce97 70 memset(buffer, '\0', PING_BUFEFERSIZE);
etherealflaim 0:d494b853ce97 71
etherealflaim 0:d494b853ce97 72 *ip_packet = (IP_PacketHeader){0x04, 5, 0, sizeof(IP_PacketHeader)+sizeof(ICMP_Packet), 0, 0, 0, 0, 0, 32, IPPROTO_ICMP, 0x00, my_ip, your_ip};
etherealflaim 0:d494b853ce97 73 *ping_packet = (ICMP_Packet){ICMP_ECHO_REQUEST, 0x00, 0x00, 0x00, 0x00};
etherealflaim 0:d494b853ce97 74
etherealflaim 0:d494b853ce97 75 fix_endian_icmp(ping_packet);
etherealflaim 0:d494b853ce97 76 fix_endian_ip(ip_packet);
etherealflaim 0:d494b853ce97 77 ip_packet->header_checksum = checksum(ip_packet, sizeof(IP_PacketHeader), &ip_packet->header_checksum, 2);
etherealflaim 0:d494b853ce97 78 ping_packet->checksum = checksum(ping_packet, sizeof(ICMP_Packet), &ping_packet->checksum, 2);
etherealflaim 0:d494b853ce97 79
etherealflaim 0:d494b853ce97 80
etherealflaim 0:d494b853ce97 81 FILE *fp = fopen("/local/ping.txt", "w");
etherealflaim 0:d494b853ce97 82 fprintf(fp, "PING sent...\n");
etherealflaim 0:d494b853ce97 83 fclose(fp);
etherealflaim 0:d494b853ce97 84
etherealflaim 0:d494b853ce97 85 sniffer.inject(your_mac, ETHERTYPE_IPV4, buffer, PING_BUFEFERSIZE);
etherealflaim 0:d494b853ce97 86 }
etherealflaim 0:d494b853ce97 87
etherealflaim 0:d494b853ce97 88 void identify()
etherealflaim 0:d494b853ce97 89 {
etherealflaim 0:d494b853ce97 90 FILE *fp = fopen("/local/identity.txt", "w");
etherealflaim 0:d494b853ce97 91 fprintf(fp, "Connected host identity:\n");
etherealflaim 0:d494b853ce97 92
etherealflaim 0:d494b853ce97 93 u8 *octets = your_mac.octet;
etherealflaim 0:d494b853ce97 94 fprintf(fp, " MAC Address: %02X:%02X:%02X:%02X:%02X:%02X\n", octets[0],octets[1],octets[2],octets[3],octets[4],octets[5]);
etherealflaim 0:d494b853ce97 95
etherealflaim 0:d494b853ce97 96 octets = your_ip.octet;
etherealflaim 0:d494b853ce97 97 fprintf(fp, " IP Address: %d.%d.%d.%d\n", octets[0],octets[1],octets[2],octets[3]);
etherealflaim 0:d494b853ce97 98
etherealflaim 0:d494b853ce97 99 fclose(fp);
etherealflaim 0:d494b853ce97 100 }
etherealflaim 0:d494b853ce97 101
etherealflaim 0:d494b853ce97 102 int main() {
etherealflaim 0:d494b853ce97 103 // Enable logging via USB
etherealflaim 0:d494b853ce97 104 main_log.enable(LOG_USB);
etherealflaim 0:d494b853ce97 105 main_log.printf("");
etherealflaim 0:d494b853ce97 106
etherealflaim 0:d494b853ce97 107 // Startup sequence
etherealflaim 0:d494b853ce97 108 main_log.printf("Booting...");
etherealflaim 0:d494b853ce97 109 Scanner scanner(&sniffer); // Hooks into TCP handler
etherealflaim 0:d494b853ce97 110
etherealflaim 0:d494b853ce97 111 main_log.printf("Loading commands...");
etherealflaim 0:d494b853ce97 112 loadCommands();
etherealflaim 0:d494b853ce97 113
etherealflaim 0:d494b853ce97 114 main_log.printf("Starting...");
etherealflaim 0:d494b853ce97 115 while(main_running) {
etherealflaim 0:d494b853ce97 116 // Get the next frame
etherealflaim 0:d494b853ce97 117 sniffer.next();
etherealflaim 0:d494b853ce97 118
etherealflaim 0:d494b853ce97 119 // Handle ICMP packet
etherealflaim 0:d494b853ce97 120 if (sniffer.icmp_packet)
etherealflaim 0:d494b853ce97 121 {
etherealflaim 0:d494b853ce97 122 // If the packet is an ICMP ECHO (Ping) request
etherealflaim 0:d494b853ce97 123 if (sniffer.icmp_packet->type == ICMP_ECHO_REQUEST)
etherealflaim 0:d494b853ce97 124 {
etherealflaim 0:d494b853ce97 125 // Build the ICMP packet
etherealflaim 0:d494b853ce97 126 sniffer.icmp_packet->type = ICMP_ECHO_REPLY;
etherealflaim 0:d494b853ce97 127
etherealflaim 0:d494b853ce97 128 // Build the IP packet
etherealflaim 0:d494b853ce97 129 sniffer.ip_packet->destination = sniffer.ip_packet->source;
etherealflaim 0:d494b853ce97 130 sniffer.ip_packet->source = my_ip;
etherealflaim 0:d494b853ce97 131
etherealflaim 0:d494b853ce97 132 // Inject the packet
etherealflaim 0:d494b853ce97 133 fix_endian_icmp(sniffer.icmp_packet);
etherealflaim 0:d494b853ce97 134 fix_endian_ip(sniffer.ip_packet);
etherealflaim 0:d494b853ce97 135 sniffer.icmp_packet->checksum = checksum(sniffer.icmp_packet, sizeof(ICMP_Packet) + sniffer.data_bytes, &sniffer.icmp_packet->checksum, 2);
etherealflaim 0:d494b853ce97 136 sniffer.ip_packet->header_checksum = checksum(sniffer.ip_packet, sizeof(IP_PacketHeader), &sniffer.ip_packet->header_checksum, 2);
etherealflaim 0:d494b853ce97 137 sniffer.inject(sniffer.frame_header->source, ETHERTYPE_IPV4, sniffer.ip_packet, sizeof(IP_PacketHeader) + sizeof(ICMP_Packet) + sniffer.data_bytes);
etherealflaim 0:d494b853ce97 138 }
etherealflaim 0:d494b853ce97 139 else if (sniffer.icmp_packet->type == ICMP_ECHO_REPLY)
etherealflaim 0:d494b853ce97 140 {
etherealflaim 0:d494b853ce97 141 FILE *fp = fopen("/local/ping.txt", "a");
etherealflaim 0:d494b853ce97 142 fprintf(fp, "PING reply received\n");
etherealflaim 0:d494b853ce97 143 fclose(fp);
etherealflaim 0:d494b853ce97 144 }
etherealflaim 0:d494b853ce97 145 }
etherealflaim 0:d494b853ce97 146 // Handle ARP packet
etherealflaim 0:d494b853ce97 147 else if (sniffer.arp_packet)
etherealflaim 0:d494b853ce97 148 {
etherealflaim 0:d494b853ce97 149 // These conditions can be optimized a lot
etherealflaim 0:d494b853ce97 150 // Check for an ARP request
etherealflaim 0:d494b853ce97 151 if (is_nonzero_mem(sniffer.arp_packet->sender_hardware_address, 6) &&
etherealflaim 0:d494b853ce97 152 is_nonzero_mem(sniffer.arp_packet->sender_protocol_address, 4) &&
etherealflaim 0:d494b853ce97 153 is_nonzero_mem(my_ip.octet, 4) &&
etherealflaim 0:d494b853ce97 154 is_equal_mem(sniffer.arp_packet->target_protocol_address, my_ip.octet, 4) &&
etherealflaim 0:d494b853ce97 155 sniffer.arp_packet->operation == 1)
etherealflaim 0:d494b853ce97 156 {
etherealflaim 0:d494b853ce97 157 //main_log.printf("ARP Requested:");
etherealflaim 0:d494b853ce97 158 //main_log.printf(" Responding with IP - %03d.%03d.%03d.%03d", my_ip.octet[0],my_ip.octet[1],my_ip.octet[2],my_ip.octet[3]);
etherealflaim 0:d494b853ce97 159 Ethernet_MAC *targmac = (Ethernet_MAC*)sniffer.arp_packet->target_hardware_address;
etherealflaim 0:d494b853ce97 160 IP_Address *targip = (IP_Address*)sniffer.arp_packet->target_protocol_address;
etherealflaim 0:d494b853ce97 161 Ethernet_MAC *srcmac = (Ethernet_MAC*)sniffer.arp_packet->sender_hardware_address;
etherealflaim 0:d494b853ce97 162 IP_Address *srcip = (IP_Address*)sniffer.arp_packet->sender_protocol_address;
etherealflaim 0:d494b853ce97 163
etherealflaim 0:d494b853ce97 164 // Set the ARP options
etherealflaim 0:d494b853ce97 165 *targmac = *srcmac;
etherealflaim 0:d494b853ce97 166 *srcmac = sniffer.mac;
etherealflaim 0:d494b853ce97 167 *targip = *srcip;
etherealflaim 0:d494b853ce97 168 *srcip = my_ip;
etherealflaim 0:d494b853ce97 169 sniffer.arp_packet->operation = 2;
etherealflaim 0:d494b853ce97 170
etherealflaim 0:d494b853ce97 171 fix_endian_arp(sniffer.arp_packet);
etherealflaim 0:d494b853ce97 172 sniffer.inject(BROADCAST_MAC, ETHERTYPE_ARP, sniffer.arp_packet, sizeof(ARP_Packet));
etherealflaim 0:d494b853ce97 173
etherealflaim 0:d494b853ce97 174 if (!portscan_started) {
etherealflaim 0:d494b853ce97 175 portscan_started = true;
etherealflaim 0:d494b853ce97 176 }
etherealflaim 0:d494b853ce97 177 }
etherealflaim 0:d494b853ce97 178 // Check for an ARP announce
etherealflaim 0:d494b853ce97 179 if (is_nonzero_mem(sniffer.arp_packet->sender_hardware_address, 6) &&
etherealflaim 0:d494b853ce97 180 is_zero_mem (sniffer.arp_packet->sender_protocol_address, 4) &&
etherealflaim 0:d494b853ce97 181 is_zero_mem (sniffer.arp_packet->target_hardware_address, 6) &&
etherealflaim 0:d494b853ce97 182 sniffer.arp_packet->operation == 1)
etherealflaim 0:d494b853ce97 183 {
etherealflaim 0:d494b853ce97 184 if (ip_determined) continue;
etherealflaim 0:d494b853ce97 185 ip_determined = true;
etherealflaim 0:d494b853ce97 186
etherealflaim 0:d494b853ce97 187 //main_log.printf("ARP Announce Received:");
etherealflaim 0:d494b853ce97 188 my_ip = your_ip = *(IP_Address*)sniffer.arp_packet->target_protocol_address;
etherealflaim 0:d494b853ce97 189 main_log.printf("Host IP: %03d.%03d.%03d.%03d", my_ip.octet[0],my_ip.octet[1],my_ip.octet[2],my_ip.octet[3]);
etherealflaim 0:d494b853ce97 190 do { my_ip.octet[3]++; } while (!my_ip.octet[3]);
etherealflaim 0:d494b853ce97 191 main_log.printf("Tool IP: %03d.%03d.%03d.%03d", my_ip.octet[0],my_ip.octet[1],my_ip.octet[2],my_ip.octet[3]);
etherealflaim 0:d494b853ce97 192
etherealflaim 0:d494b853ce97 193 Ethernet_MAC *targmac = (Ethernet_MAC*)sniffer.arp_packet->target_hardware_address;
etherealflaim 0:d494b853ce97 194 IP_Address *targip = (IP_Address*)sniffer.arp_packet->target_protocol_address;
etherealflaim 0:d494b853ce97 195 Ethernet_MAC *srcmac = (Ethernet_MAC*)sniffer.arp_packet->sender_hardware_address;
etherealflaim 0:d494b853ce97 196 IP_Address *srcip = (IP_Address*)sniffer.arp_packet->sender_protocol_address;
etherealflaim 0:d494b853ce97 197
etherealflaim 0:d494b853ce97 198 your_mac = *srcmac;
etherealflaim 0:d494b853ce97 199
etherealflaim 0:d494b853ce97 200 // Set the ARP options
etherealflaim 0:d494b853ce97 201 *targmac = sniffer.mac;
etherealflaim 0:d494b853ce97 202 *srcmac = sniffer.mac;
etherealflaim 0:d494b853ce97 203 *targip = my_ip;
etherealflaim 0:d494b853ce97 204 *srcip = my_ip;
etherealflaim 0:d494b853ce97 205 sniffer.arp_packet->operation = 2;
etherealflaim 0:d494b853ce97 206
etherealflaim 0:d494b853ce97 207 fix_endian_arp(sniffer.arp_packet);
etherealflaim 0:d494b853ce97 208 sniffer.inject(BROADCAST_MAC, ETHERTYPE_ARP, sniffer.arp_packet, sizeof(ARP_Packet));
etherealflaim 0:d494b853ce97 209
etherealflaim 0:d494b853ce97 210 while (!commands.empty())
etherealflaim 0:d494b853ce97 211 {
etherealflaim 0:d494b853ce97 212 string command = commands.front();
etherealflaim 0:d494b853ce97 213 main_log.printf("NetTool> %s", command.c_str());
etherealflaim 0:d494b853ce97 214 if (command == "ping")
etherealflaim 0:d494b853ce97 215 ping_timer.attach(&ping, 30);
etherealflaim 0:d494b853ce97 216 else if (command == "portscan")
etherealflaim 0:d494b853ce97 217 scanner.start(sniffer.mac, your_mac, my_ip, your_ip);
etherealflaim 0:d494b853ce97 218 else if (command == "identify")
etherealflaim 0:d494b853ce97 219 identify();
etherealflaim 0:d494b853ce97 220 commands.pop();
etherealflaim 0:d494b853ce97 221 }
etherealflaim 0:d494b853ce97 222 }
etherealflaim 0:d494b853ce97 223 }
etherealflaim 0:d494b853ce97 224 else if (sniffer.tcp_packet)
etherealflaim 0:d494b853ce97 225 {
etherealflaim 0:d494b853ce97 226 }
etherealflaim 0:d494b853ce97 227 }
etherealflaim 0:d494b853ce97 228
etherealflaim 0:d494b853ce97 229 // This shouldn't really happen...
etherealflaim 0:d494b853ce97 230 main_log.printf("Terminating...");
etherealflaim 0:d494b853ce97 231 return 0;
etherealflaim 0:d494b853ce97 232 }