void print_ip(ip_hdr *ip) { indent(1); printf("IPv4 Packet Header (%d bytes)\n", 4*ip->ip_hl); indent(2); printf("Version = %d\n", ip->ip_v); indent(2); printf("Header Length = %d\n", 4*ip->ip_hl); indent(2); printf("Terms of Service = 0x%X\n", ip->ip_tos); indent(2); printf("Total Length = %d\n", ntohs(ip->ip_len)); indent(2); printf("Identification = 0x%X\n", ntohs(ip->ip_id)); indent(2); printf("Fragment Offset Field = 0x%X\n", ntohs(ip->ip_off)); indent(2); printf("TTL (Time to Live) = %d\n", ip->ip_ttl); indent(2); printf("Protocol = "); switch(ip->ip_p) { case 1: { printf("ICMP\n"); break; } case 6: { printf("TCP\n"); break; } default: { printf("%d\n", ip->ip_p); break; } } indent(2); printf("Header Checksum = 0x%X\n", ntohs(ip->ip_sum)); indent(2); print_ip_address("Src IP Address", ip->ip_src); indent(2); print_ip_address("Dst IP Address", ip->ip_dst); }
void print_arp_hdr(const uint8_t *packet, unsigned int len) { assert(packet); arp_hdr *arp = get_arp_hdr(packet, len); indent(1); printf("ARP Packet (%d bytes)\n", sizeof(arp_hdr)); indent(2); printf("Hardware Type: "); switch(ntohs(arp->arp_hrd)) { case 1: { printf("Ethernet\n"); break; } default: { printf("%X\n", ntohs(arp->arp_hrd)); break; } } indent(2); printf("Protocol Type = %X (IP)\n", ntohs(arp->arp_pro)); indent(2); printf("Hardware Address Length = %d\n", arp->arp_hln); indent(2); printf("Protocol Address Length = %d\n", arp->arp_pln); indent(2); printf("Opcode = "); switch(ntohs(arp->arp_op)) { case 1: { printf("Request\n"); break; } case 2: { printf("Reply\n"); break; } default: { printf("%X\n", arp->arp_op); break; } } indent(2); print_mac_address("Src Hardware Address", arp->arp_sha); indent(2); print_ip_address("Src Protocol Address", arp->arp_sip); indent(2); print_mac_address("Dst Hardware Address", arp->arp_tha); indent(2); print_ip_address("Dst Protocol Address", arp->arp_tip); }
void print_pwospf(pwospf_hdr *pwospf) { struct in_addr ip_addr; indent(1); printf("PWOSPFv2 Packet Header (%d bytes)\n", ntohs(pwospf->pwospf_len)); indent(2); printf("Version = %d\n", pwospf->pwospf_ver); indent(2); printf("Type = %d\n", pwospf->pwospf_type); indent(2); printf("Length = %d\n", ntohs(pwospf->pwospf_len)); indent(2); ip_addr.s_addr = pwospf->pwospf_rid; print_ip_address("Router ID", ip_addr); indent(2); printf("Area ID = %X\n", ntohl(pwospf->pwospf_aid)); indent(2); printf("Checksum = %X\n", ntohs(pwospf->pwospf_sum)); indent(2); printf("Autype = %d\n", ntohs(pwospf->pwospf_atype)); indent(2); printf("Authentication = %X\n", ntohl(pwospf->pwospf_auth1)); indent(2); printf("Authentication = %X\n", ntohl(pwospf->pwospf_auth2)); switch(pwospf->pwospf_type) { case PWOSPF_TYPE_HELLO: { pwospf_hello_hdr *hello = (pwospf_hello_hdr *) ( ((uint8_t *)pwospf) + sizeof(pwospf_hdr) ); indent(2); print_ip_address("Net Mask", hello->pwospf_mask); indent(2); printf("HelloInt = %d\n", ntohs(hello->pwospf_hint)); indent(2); printf("Padding = %X\n", hello->pwospf_pad); break; } case PWOSPF_TYPE_LINK_STATE_UPDATE: { pwospf_lsu_hdr *lsu = (pwospf_lsu_hdr *) ( ((uint8_t *)pwospf) + sizeof(pwospf_hdr) ); pwospf_lsu_adv *iface_adv = (pwospf_lsu_adv *) ( ((uint8_t *)lsu) + sizeof(pwospf_lsu_hdr) ); indent(2); printf("Sequence = %d\n", ntohs(lsu->pwospf_seq)); indent(2); printf("TTL = %d\n", ntohs(lsu->pwospf_ttl)); indent(2); printf("No. of Adverisements = %d\n", ntohl(lsu->pwospf_num)); int i; for(i=0; i < ntohl(lsu->pwospf_num); i++) { indent(2); printf("Advertisement #%d\n", i); indent(3); print_ip_address("Subnet", iface_adv->pwospf_sub); indent(3); print_ip_address("Mask", iface_adv->pwospf_mask); indent(3); ip_addr.s_addr = iface_adv->pwospf_rid; print_ip_address("Router ID", ip_addr); /* next advertisment */ iface_adv += 1; } break; } default: indent(2); printf("Invalid PWOSPF Type\n"); } }
static int process_received_frame ( const int frame_len ) { // At the moment, we can only reply to a single ARP query for our MAC address. // Use a command like this to make this routine generate an answer: // With Ubuntu's arping: // arping -c 1 -f -w 10 -I dpi-tap1 192.168.254.1 // With Thomas Habets' arping: // sudo ./arping -w 10000000 -c 1 -i dpi-tap1 192.168.254.1 const int ARP_FRAME_LENGTH = 42; if ( frame_len < ARP_FRAME_LENGTH ) { uart_print( UART1_BASE_ADDR, "The frame is too short to be the kind of ARP frame we are looking for." EOL ); return 0; } int pos = 0; if ( eth_rx_packet[ pos + 0 ] != BROADCAST_ADDRESS_5 || eth_rx_packet[ pos + 1 ] != BROADCAST_ADDRESS_4 || eth_rx_packet[ pos + 2 ] != BROADCAST_ADDRESS_3 || eth_rx_packet[ pos + 3 ] != BROADCAST_ADDRESS_2 || eth_rx_packet[ pos + 4 ] != BROADCAST_ADDRESS_1 || eth_rx_packet[ pos + 5 ] != BROADCAST_ADDRESS_0 ) { uart_print( UART1_BASE_ADDR, "The target MAC address is not broadcast." EOL ); return 0; } pos += MAC_ADDR_LEN; const int src_mac_addr_pos = pos; uart_print( UART1_BASE_ADDR, "Received broadcast frame from MAC address " ); print_mac_address( ð_rx_packet[ pos ] ); uart_print( UART1_BASE_ADDR, EOL ); pos += MAC_ADDR_LEN; const unsigned char ARP_PROTOCOL_HI = 0x08; const unsigned char ARP_PROTOCOL_LO = 0x06; if ( eth_rx_packet[ pos + 0 ] != ARP_PROTOCOL_HI || eth_rx_packet[ pos + 1 ] != ARP_PROTOCOL_LO ) { uart_print( UART1_BASE_ADDR, "The frame does not contain ARP protocol data." EOL ); return 0; } pos += 2; const unsigned char ETHERNET_HARDWARE_TYPE_HI = 0x00; const unsigned char ETHERNET_HARDWARE_TYPE_LO = 0x01; if ( eth_rx_packet[ pos + 0 ] != ETHERNET_HARDWARE_TYPE_HI || eth_rx_packet[ pos + 1 ] != ETHERNET_HARDWARE_TYPE_LO ) { uart_print( UART1_BASE_ADDR, "The ARP frame does not contain the Ethernet hardware type." EOL ); return 0; } pos += 2; const unsigned char IP_PROTOCOL_HI = 0x08; const unsigned char IP_PROTOCOL_LO = 0x00; if ( eth_rx_packet[ pos + 0 ] != IP_PROTOCOL_HI || eth_rx_packet[ pos + 1 ] != IP_PROTOCOL_LO ) { uart_print( UART1_BASE_ADDR, "The ARP frame is not about the IP protocol." EOL ); return 0; } pos += 2; const unsigned char HARDWARE_SIZE = MAC_ADDR_LEN; if ( eth_rx_packet[ pos ] != HARDWARE_SIZE ) { uart_print( UART1_BASE_ADDR, "The ARP frame has an invalid hardware size." EOL ); return 0; } pos += 1; const unsigned char PROTOCOL_SIZE = IP_ADDR_LEN; if ( eth_rx_packet[ pos ] != PROTOCOL_SIZE ) { uart_print( UART1_BASE_ADDR, "The ARP frame has an invalid protocol size." EOL ); return 0; } pos += 1; const unsigned char OPCODE_REQUEST_HI = 0x00; const unsigned char OPCODE_REQUEST_LO = 0x01; const unsigned char OPCODE_REPLY_HI = 0x00; const unsigned char OPCODE_REPLY_LO = 0x02; if ( eth_rx_packet[ pos + 0 ] != OPCODE_REQUEST_HI || eth_rx_packet[ pos + 1 ] != OPCODE_REQUEST_LO ) { uart_print( UART1_BASE_ADDR, "The ARP frame is not an ARP request." EOL ); return 0; } pos += 2; uart_print( UART1_BASE_ADDR, "The ARP sender MAC address is " ); print_mac_address( ð_rx_packet[ pos ] ); uart_print( UART1_BASE_ADDR, EOL ); pos += MAC_ADDR_LEN; const int src_ip_addr_pos = pos; uart_print( UART1_BASE_ADDR, "The ARP sender IP address is " ); print_ip_address( ð_rx_packet[ pos ] ); uart_print( UART1_BASE_ADDR, EOL ); pos += IP_ADDR_LEN; uart_print( UART1_BASE_ADDR, "The target MAC address is " ); print_mac_address( ð_rx_packet[ pos ] ); uart_print( UART1_BASE_ADDR, EOL ); // Linux uses 0x000000 here, but arping uses 0xFFFFFF. const int is_zero = eth_rx_packet[ pos + 0 ] == 0 && eth_rx_packet[ pos + 1 ] == 0 && eth_rx_packet[ pos + 2 ] == 0 && eth_rx_packet[ pos + 3 ] == 0 && eth_rx_packet[ pos + 4 ] == 0 && eth_rx_packet[ pos + 5 ] == 0; const int is_bcast = eth_rx_packet[ pos + 0 ] == BROADCAST_ADDRESS_5 && eth_rx_packet[ pos + 1 ] == BROADCAST_ADDRESS_4 && eth_rx_packet[ pos + 2 ] == BROADCAST_ADDRESS_3 && eth_rx_packet[ pos + 3 ] == BROADCAST_ADDRESS_2 && eth_rx_packet[ pos + 4 ] == BROADCAST_ADDRESS_1 && eth_rx_packet[ pos + 5 ] == BROADCAST_ADDRESS_0; if ( !is_zero && !is_bcast ) { uart_print( UART1_BASE_ADDR, "The target MAC address is neither zero nor 0xFF." EOL ); return 0; } pos += MAC_ADDR_LEN; uart_print( UART1_BASE_ADDR, "The target IP address is " ); print_ip_address( ð_rx_packet[ pos ] ); uart_print( UART1_BASE_ADDR, EOL ); if ( eth_rx_packet[ pos + 0 ] != OWN_IP_ADDRESS_0 || eth_rx_packet[ pos + 1 ] != OWN_IP_ADDRESS_1 || eth_rx_packet[ pos + 2 ] != OWN_IP_ADDRESS_2 || eth_rx_packet[ pos + 3 ] != OWN_IP_ADDRESS_3 ) { uart_print( UART1_BASE_ADDR, "The target IP address is not ours." EOL ); return 0; } pos += IP_ADDR_LEN; if ( pos != ARP_FRAME_LENGTH ) { uart_print( UART1_BASE_ADDR, "Internal error parsing the frame." EOL ); return 0; } // Build the ARP reply. pos = 0; copy_mac_address( ð_rx_packet[ src_mac_addr_pos ], ð_tx_packet[ pos ] ); pos += MAC_ADDR_LEN; write_own_mac_addr( ð_tx_packet[ pos ] ); pos += MAC_ADDR_LEN; eth_tx_packet[ pos + 0 ] = ARP_PROTOCOL_HI; eth_tx_packet[ pos + 1 ] = ARP_PROTOCOL_LO; pos += 2; eth_tx_packet[ pos + 0 ] = ETHERNET_HARDWARE_TYPE_HI; eth_tx_packet[ pos + 1 ] = ETHERNET_HARDWARE_TYPE_LO; pos += 2; eth_tx_packet[ pos + 0 ] = IP_PROTOCOL_HI; eth_tx_packet[ pos + 1 ] = IP_PROTOCOL_LO; pos += 2; eth_tx_packet[ pos + 0 ] = HARDWARE_SIZE; pos += 1; eth_tx_packet[ pos + 0 ] = PROTOCOL_SIZE; pos += 1; eth_tx_packet[ pos + 0 ] = OPCODE_REPLY_HI; eth_tx_packet[ pos + 1 ] = OPCODE_REPLY_LO; pos += 2; write_own_mac_addr( ð_tx_packet[ pos ] ); pos += MAC_ADDR_LEN; eth_tx_packet[ pos + 0 ] = OWN_IP_ADDRESS_0; eth_tx_packet[ pos + 1 ] = OWN_IP_ADDRESS_1; eth_tx_packet[ pos + 2 ] = OWN_IP_ADDRESS_2; eth_tx_packet[ pos + 3 ] = OWN_IP_ADDRESS_3; pos += IP_ADDR_LEN; copy_mac_address( ð_rx_packet[ src_mac_addr_pos ], ð_tx_packet[ pos ] ); pos += MAC_ADDR_LEN; copy_ip_address( ð_rx_packet[ src_ip_addr_pos ], ð_tx_packet[ pos ] ); pos += IP_ADDR_LEN; if ( pos != ARP_FRAME_LENGTH ) { uart_print( UART1_BASE_ADDR, "Internal error building the ARP reply frame." EOL ); return 0; } // After the ARP information, at the end of the Ethernet packet, comes the dummy CRC, // which should be 4 bytes with value 0xDEADF00D. uart_print( UART1_BASE_ADDR, "Sending the ARP reply..." EOL ); start_ethernet_send( ARP_FRAME_LENGTH ); wait_until_frame_was_sent(); uart_print( UART1_BASE_ADDR, "Reply sent." EOL ); return 1; }