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 06:48:59 2010 +0000
Revision:
8:1c1f6ce348c6
Parent:
7:e34ae4c7eb79
Documentation

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