示例#1
0
void print_packet(const struct sniff_ethernet *eth,
		 const struct sniff_ip *ip,
		 const struct sniff_tcp *tcp)
{	
	/* Ethernet */
	printf("DADDR:"); print_ethernet_addr(eth->dest_host);
	printf("SADDR:"); print_ethernet_addr(eth->src_host);
	printf("TYPE:%u\n", eth->ether_type);
	/* IP */
	printf(	"\tVERSION: %u\n"
		"\tHEADER LENGTH: %u\n"
		"\tTOTAL LENGTH: %u\n"
		"\tTOS: %u\n"
		"\tTTL: %u\n",
		IP_VER(ip),
		IP_HL(ip),
		ip->ip_len,
		ip->ip_tos,
		ip->ip_ttl);

	/* TCP */
	printf(	"\t\tSPORT: %u\n"
		"\t\tDPORT: %u\n"
		"\t\tSEQ: %u\n"
		"\t\tACK: %u\n", 
		ntohs(tcp->th_sport),
		ntohs(tcp->th_dport),
		tcp->th_seq,
		tcp->th_ack);
}
示例#2
0
void sr_handlepacket(struct sr_instance* sr,
        uint8_t * packet/* lent */,
        unsigned int len,
        char* interface/* lent */)
{
    /* REQUIRES */
    assert(sr);
    assert(packet);
    assert(interface);

    printf("*** -> Received packet of length %d on interface \"%s\"\n", len, interface);

    // Deconstruct the packet's ethernet header
    struct sr_ethernet_hdr *header = malloc(sizeof(struct sr_ethernet_hdr));
    memcpy(header, packet, sizeof(struct sr_ethernet_hdr));
    header->ether_type = htons(header->ether_type);

    // Determine proper routing behavior based on ether_type
    switch(header->ether_type) {
        case ETHERTYPE_ARP:
            {
                // Unpack the ARP header
                struct sr_arphdr *arp_header = malloc(sizeof(struct sr_arphdr));
                memcpy(arp_header, packet + 14, sizeof(struct sr_arphdr));
                arp_header->ar_op = ntohs(arp_header->ar_op);

                // Check the ARP opcode
                switch(arp_header->ar_op) {
                    case ARP_REQUEST:
                        handle_arp_request(sr, header, arp_header, interface);
                        break;
                    case ARP_REPLY:
                        printf("\tIt's an ARP reply!\n");
                        add_arp_cache_entry(cache, arp_header->ar_sip, arp_header->ar_sha);

                        struct in_addr addr = {arp_header->ar_sip};
                        printf("\tMapping %s to ", inet_ntoa(addr));
                        print_ethernet_addr(arp_header->ar_sha, stdout);
                        printf("\n");

                        // Scan for packets we can retransmit
                        struct ip_cache_entry *cache_entry = next_packet_with_dest(ip_cache, addr);
                        struct sr_if *iface = sr_get_interface(sr, interface);

                        while(cache_entry) {
                            // Wrap the IP packet in an ethernet header
                            uint8_t *wrapped_packet = pack_ethernet_packet(arp_header->ar_sha,
                                    iface->addr, ETHERTYPE_IP, cache_entry->packet,
                                    cache_entry->len);

                            // Send the newly wrapped packet
                            sr_send_packet(sr, wrapped_packet,
                                    sizeof(struct sr_ethernet_hdr) + cache_entry->len,
                                    iface->name);

                            // TODO: We're dumb are forgot this
                            cache_entry = next_packet_with_dest(ip_cache, addr);
                        }
                        break;
                }
                break;
            }
        case ETHERTYPE_IP:
            {
                // TODO
                printf("\tIt's an IP packet!\n");
                route_ip_packet(sr, packet, len, interface);
                break;
            }
        default:
            {
                printf("\tIt's an unknown packet type (ether_type = 0x%X)\n", header->ether_type);
                break;
            }
    }

} /* end sr_ForwardPacket */
示例#3
0
static void route_ip_packet(struct sr_instance *sr, uint8_t *packet, size_t len, char *interface) {
    // Copy the IP header
    struct ip *ip_header = calloc(1, sizeof(struct ip));
    memcpy(ip_header, packet + sizeof(struct sr_ethernet_hdr), sizeof(struct ip));

    // The IP header is a dirty liar
    int actual_header_length = ip_header->ip_hl * 4;
    int ip_packet_len = len - sizeof(struct sr_ethernet_hdr);

    // Decrement the TTL and check if it's 0
    ip_header->ip_ttl -= 1;
    if(ip_header->ip_ttl <= 0) {
        return;
    }

    // Zero out the old checksum
    ip_header->ip_sum = 0;

    // Create a buffer to calculate the checksum
    uint16_t *header_buffer;

    // Create a chunk of memory aligned to 16 bits
    posix_memalign((void **) &header_buffer, CHECKSUM_ALIGNMENT, actual_header_length);
    bzero(header_buffer, actual_header_length);

    // Copy required IP header fields
    memcpy(header_buffer, ip_header, sizeof(struct ip));

    // Copy the original IP header flags
    memcpy(header_buffer, packet + sizeof(struct sr_ethernet_hdr) + sizeof(struct ip),
            actual_header_length - sizeof(struct ip));

    // Calculate the new checksum
    ip_header->ip_sum = header_checksum(header_buffer, actual_header_length / 2);

    free(header_buffer);

    // Get the IP packet's destination
    struct in_addr destination_addr = ip_header->ip_dst;
    uint32_t destination_ip = destination_addr.s_addr;

    // Check if we're the destination
    struct sr_if *iface = sr_get_interface(sr, interface);
    if(destination_ip == iface->ip) {
        printf("Dropping packet bound for router on %s\n", interface);
        return;
    }

    // Check the routing table for the correct gateway to forward the packet through
    struct sr_rt *table_entry = search_routing_table(sr, destination_ip);

    printf("\tThe nexthop is %s\n", inet_ntoa(table_entry->gw));

    if(table_entry) {
        // Get the interface for the gateway
        struct sr_if *gw_iface = sr_get_interface(sr, table_entry->interface);

        // Determine the IP to forward to
        struct in_addr nexthop;

        // Determine if the IP to forward to is in our network
        if(table_entry->gw.s_addr == 0) {
            nexthop = destination_addr;
        } else {
            nexthop = table_entry->gw;
        }

        // Create an updated IP packet with the correct headers/data
        uint8_t *updated_packet = calloc(ip_packet_len, sizeof(uint8_t));
        memcpy(updated_packet, ip_header, actual_header_length);
        memcpy(updated_packet + actual_header_length,
                packet + sizeof(struct sr_ethernet_hdr ) + actual_header_length,
                len - sizeof(struct sr_ethernet_hdr ) - actual_header_length);

        // Search the ARP cache for the nexthop
        uint8_t *gw_addr = search_arp_cache(cache, nexthop.s_addr);

        if(gw_addr) {
            printf("\tForwarding packet bound for %s through next hop @ ",
                    inet_ntoa(destination_addr));
            printf("%s (", inet_ntoa(table_entry->gw));
            print_ethernet_addr(gw_addr, stdout);
            printf(")\n");

            uint8_t *buffer = pack_ethernet_packet(gw_addr, gw_iface->addr, ETHERTYPE_IP,
                    updated_packet, ip_packet_len);

            sr_send_packet(sr, buffer, len, gw_iface->name);
        } else {
            // Otherwise we cache the IP packet and make an ARP request
            printf("\tSending ARP request to %s (%s), to forward packet bound for ",
                    inet_ntoa(nexthop), gw_iface->name);
            printf("%s\n", inet_ntoa(destination_addr));

            add_ip_cache_entry(ip_cache, updated_packet, nexthop, ip_packet_len);
            send_arp_request(sr, gw_iface, nexthop);
        }

    } else {
        // TODO: What do we do here?
    }
}