Example #1
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 \n",len);

  uint8_t *pkt = malloc(len);
  memcpy(pkt, packet, len);

  sr_ethernet_hdr_t *hdr = get_ethernet_hdr(pkt);
  
  enum sr_ethertype type = ntohs(hdr->ether_type);
  
  if (type == ethertype_arp) {
    char *inf_cpy = malloc(sr_IFACE_NAMELEN);
    memcpy(inf_cpy, interface, sr_IFACE_NAMELEN);
    handle_arp(sr, pkt, inf_cpy, len);
  } else if (type == ethertype_ip) {
    handle_ip(sr, pkt, len);
  } else {
    fprintf(stderr, "invalid packet type id in ethernet header\n");
  }

}/* end sr_ForwardPacket */
Example #2
0
void handle_ether(const struct timeval& t, WifipcapCallbacks *cbs, const u_char *ptr, int len)
{
    ether_hdr_t hdr;

    hdr.da = ether2MAC(ptr);
    hdr.sa = ether2MAC(ptr+6);
    hdr.type = EXTRACT_16BITS(ptr + 12);

    ptr += 14;
    len -= 14;

    cbs->HandleEthernet(t, &hdr, ptr, len);

    switch (hdr.type) {
    case ETHERTYPE_IP:
	handle_ip(t, cbs, ptr, len);
	return;
    case ETHERTYPE_IPV6:
	handle_ip6(t, cbs, ptr, len);
	return;
    case ETHERTYPE_ARP:
	handle_arp(t, cbs, ptr, len);
	return;
    default:
	cbs->HandleL2Unknown(t, hdr.type, ptr, len);
	return;
    }
}
Example #3
0
/**
 * Ethernet: Receives an ethernet-packet and handles it according to
 *      Receive-handle diagram.
 *
 * @return  ZERO - packet was handled or no packets received;
 *          NON ZERO - error condition occurs.
 */
int32_t
receive_ether(void) {
	int32_t bytes_received;
	struct ethhdr * ethh;

	memset(ether_packet, 0, ETH_MTU_SIZE);
	bytes_received = recv(0, ether_packet, ETH_MTU_SIZE, 0);

	if (!bytes_received) // No messages
		return 0;

	if (bytes_received < sizeof(struct ethhdr))
		return -1; // packet is too small

	ethh = (struct ethhdr *) ether_packet;

	if(memcmp(ethh->dest_mac, broadcast_mac, 6) != 0
	&& memcmp(ethh->dest_mac, multicast_mac, 3) != 0
	&& memcmp(ethh->dest_mac, own_mac, 6      ) != 0
	&& !is_multicast_mac(ethh->dest_mac))
		return -1; // packet is too small

	switch (htons(ethh -> type)) {
	case ETHERTYPE_IP:
		return handle_ipv4((uint8_t*) (ethh + 1),
		                   bytes_received - sizeof(struct ethhdr));
/*
	case ETHERTYPE_IPv6:
		return handle_ipv6(ether_packet + sizeof(struct ethhdr),
				bytes_received - sizeof(struct ethhdr));
*/
	case ETHERTYPE_ARP:
		return handle_arp((uint8_t*) (ethh + 1),
		           bytes_received - sizeof(struct ethhdr));
	default:
		break;
	}
	return -1; // unknown protocol
}
Example #4
0
static void read_packet(unsigned char* buf, uint16_t len) {
  if (len < sizeof(struct ether_header)) {
    lput_str("Ethernet header was too short");
    return;
  }
  struct ether_header* eth = (struct ether_header*)buf;
  if (memcmp(eth->dest, MAC_ADDRESS, ETHER_ADDR_LEN) != 0 &&
      memcmp(eth->dest, BROADCAST_ADDRESS, ETHER_ADDR_LEN) != 0) {
    lput_str("Ignoring packet not meant for me");
    return;
  } 
  uint16_t payload_len = len - sizeof(struct ether_header);
  unsigned char* payload = (unsigned char*)(eth + 1);
  ntohs(&eth->type);
  switch (eth->type) {
    case ETHERTYPE_IP:
      if (payload_len < sizeof(struct ip_header)) {
        lput_str("IP header was too short");
        return;
      }
      unsigned char* ip_payload = payload + sizeof(struct ip_header);
      uint16_t ip_payload_len = payload_len - sizeof(struct ip_header);
      handle_ip((struct ip_header*)payload, ip_payload, ip_payload_len);
      break;
    case ETHERTYPE_ARP:
      if (payload_len < sizeof(struct arp_header)) {
        lput_str("ARP header was too short");
        return;
      }
      handle_arp((struct arp_header*)payload);
      break;
    default:
      lput_str("Unknown ETHERTYPE:");
      lput16_hex(eth->type);
      lput_str("\r\n");
      break;
  }
}
Example #5
0
/***************************************************************************
 * 
 * Asynchronous receive thread
 *
 * The transmit and receive threads run independently of each other. There
 * is no record what was transmitted. Instead, the transmit thread sets a 
 * "SYN-cookie" in transmitted packets, which the receive thread will then
 * use to match up requests with responses.
 ***************************************************************************/
static void
receive_thread(void *v)
{
    struct ThreadPair *parms = (struct ThreadPair *)v;
    const struct Masscan *masscan = parms->masscan;
    struct Output *out;
    struct DedupTable *dedup;
    struct PcapFile *pcapfile = NULL;
    struct TCP_ConnectionTable *tcpcon = 0;


    LOG(1, "recv: start receive thread #%u\n", parms->nic_index);

    /* Lock this thread to a CPU. Transmit threads are on even CPUs,
     * receive threads on odd CPUs */
    if (pixie_cpu_get_count() > 1) {
        unsigned cpu_count = pixie_cpu_get_count();
        unsigned cpu = parms->nic_index * 2 + 1;
        while (cpu >= cpu_count) {
            cpu -= cpu_count;
            cpu++;
        }
        pixie_cpu_set_affinity(cpu);
    }

    /*
     * If configured, open a --pcap file for saving raw packets. This is
     * so that we can debug scans, but also so that we can look at the
     * strange things people send us. Note that we don't record transmitted
     * packets, just the packets we've received.
     */
    /*if (masscan->pcap_filename[0])
        pcapfile = pcapfile_openwrite(masscan->pcap_filename, 1);*/

    /*
     * Open output. This is where results are reported when saving
     * the --output-format to the --output-filename
     */
    out = output_create(masscan);

    /*
     * Create deduplication table. This is so when somebody sends us
     * multiple responses, we only record the first one.
     */
    dedup = dedup_create();

    /*
     * Create a TCP connection table for interacting with live
     * connections when doing --banners
     */
    if (masscan->is_banners) {
        tcpcon = tcpcon_create_table(
            (size_t)((masscan->max_rate/5) / masscan->nic_count), 
            parms->transmit_queue, 
            parms->packet_buffers,
            &parms->tmplset->pkts[Proto_TCP],
            output_report_banner,
            out,
            masscan->tcb.timeout
            );
        if (masscan->http_user_agent_length)
        tcpcon_set_parameter(   tcpcon, 
                                "http-user-agent",
                                masscan->http_user_agent_length,
                                masscan->http_user_agent);

    }

    /*
     * In "offline" mode, we don't have any receive threads, so simply
     * wait until transmitter thread is done then go to the end
     */
    if (masscan->is_offline) {
        while (!control_c_pressed_again)
            pixie_usleep(10000);
        parms->done_receiving = 1;
        goto end;
    }

    /*
     * Receive packets. This is where we catch any responses and print
     * them to the terminal.
     */
    LOG(1, "begin receive thread\n");
    while (!control_c_pressed_again) {
        int status;
        unsigned length;
        unsigned secs;
        unsigned usecs;
        const unsigned char *px;
        int err;
        unsigned x;
        struct PreprocessedInfo parsed;
        unsigned ip_me;
        unsigned port_me;
        unsigned ip_them;
        unsigned port_them;
        unsigned seqno_me;
        unsigned seqno_them;
        unsigned cookie;

        /*
         * RECIEVE
         *
         * This is the boring part of actually receiving a packet
         */
        err = rawsock_recv_packet(
                    parms->adapter,
                    &length,
                    &secs,
                    &usecs,
                    &px);
        
        if (err != 0)
            continue;
        

        /*
         * Do any TCP event timeouts based on the current timestamp from
         * the packet. For example, if the connection has been open for
         * around 10 seconds, we'll close the connection. (--banners)
         */
        if (tcpcon) {
            tcpcon_timeouts(tcpcon, secs, usecs);
        }

        if (length > 1514)
            continue;
        
        /*
         * "Preprocess" the response packet. This means to go through and
         * figure out where the TCP/IP headers are and the locations of
         * some fields, like IP address and port numbers.
         */
        x = preprocess_frame(px, length, 1, &parsed);
        if (!x)
            continue; /* corrupt packet */
        ip_me = parsed.ip_dst[0]<<24 | parsed.ip_dst[1]<<16
            | parsed.ip_dst[2]<< 8 | parsed.ip_dst[3]<<0;
        ip_them = parsed.ip_src[0]<<24 | parsed.ip_src[1]<<16
            | parsed.ip_src[2]<< 8 | parsed.ip_src[3]<<0;
        port_me = parsed.port_dst;
        port_them = parsed.port_src;
        seqno_them = TCP_SEQNO(px, parsed.transport_offset);
        seqno_me = TCP_ACKNO(px, parsed.transport_offset);
        cookie = syn_cookie(ip_them, port_them, ip_me, port_me) & 0xFFFFFFFF;


        /* verify: my IP address */
        if (!is_my_ip(&parms->src, ip_me))
            continue;

        
        /*
         * Handle non-TCP protocols
         */
        switch (parsed.found) {
            case FOUND_ARP:
                LOGip(2, ip_them, 0, "-> ARP [%u] \n", px[parsed.found_offset]);
				switch (px[parsed.found_offset + 6]<<8 | px[parsed.found_offset+7]) {
				case 1: /* request */
					/* This function will transmit a "reply" to somebody's ARP request
					 * for our IP address (as part of our user-mode TCP/IP).
					 * Since we completely bypass the TCP/IP stack, we  have to handle ARPs
					 * ourself, or the router will lose track of us.*/
					arp_response(   ip_me,
									parms->adapter_mac,
									px, length,
									parms->packet_buffers,
									parms->transmit_queue);
					break;
				case 2: /* response */
					/* This is for "arp scan" mode, where we are ARPing targets rather
					 * than port scanning them */

					/* If we aren't doing an ARP scan, then ignore ARP responses */
					if (!masscan->is_arp)
						break;

					/* If this response isn't in our range, then ignore it */
					if (!rangelist_is_contains(&masscan->targets, ip_them))
						break;

					/* Ignore duplicates */
		            if (dedup_is_duplicate(dedup, ip_them, 0))
						continue;

					/* ...everything good, so now report this response */
	                handle_arp(out, px, length, &parsed);
					break;
				}
                continue;
            case FOUND_UDP:
            case FOUND_DNS:
                if (!is_nic_port(masscan, port_me))
                    continue;
                if (parms->masscan->nmap.packet_trace)
                    packet_trace(stdout, px, length, 0);
                handle_udp(out, px, length, &parsed);
                continue;
            case FOUND_ICMP:
                handle_icmp(out, px, length, &parsed);
                continue;
            case FOUND_TCP:
                /* fall down to below */
                break;
            default:
                continue;
        }
        

        /* verify: my port number */
        if (!is_my_port(&parms->src, port_me))
            continue;
        if (parms->masscan->nmap.packet_trace)
            packet_trace(stdout, px, length, 0);

        /* Save raw packet in --pcap file */
        if (pcapfile) {
            pcapfile_writeframe(
                pcapfile,
                px,
                length,
                length,
                secs,
                usecs);
        }

        {
            char buf[64];
            LOGip(5, ip_them, port_them, "-> TCP ackno=0x%08x flags=0x%02x(%s)\n", 
                seqno_me, 
                TCP_FLAGS(px, parsed.transport_offset),
                reason_string(TCP_FLAGS(px, parsed.transport_offset), buf, sizeof(buf)));
        }

        /* If recording --banners, create a new "TCP Control Block (TCB)" */
        if (tcpcon) {
            struct TCP_Control_Block *tcb;

            /* does a TCB already exist for this connection? */
            tcb = tcpcon_lookup_tcb(tcpcon,
                            ip_me, ip_them,
                            port_me, port_them);

            if (TCP_IS_SYNACK(px, parsed.transport_offset)) {
                if (cookie != seqno_me - 1) {
                    LOG(2, "%u.%u.%u.%u - bad cookie: ackno=0x%08x expected=0x%08x\n", 
                        (ip_them>>24)&0xff, (ip_them>>16)&0xff, (ip_them>>8)&0xff, (ip_them>>0)&0xff, 
                        seqno_me-1, cookie);
                    continue;
                }

                if (tcb == NULL) {
                    tcb = tcpcon_create_tcb(tcpcon,
                                    ip_me, ip_them, 
                                    port_me, port_them, 
                                    seqno_me, seqno_them+1);
                }

                tcpcon_handle(tcpcon, tcb, TCP_WHAT_SYNACK, 
                    0, 0, secs, usecs, seqno_them+1);

            } else if (tcb) {
                /* If this is an ACK, then handle that first */
                if (TCP_IS_ACK(px, parsed.transport_offset)) {
                    tcpcon_handle(tcpcon, tcb, TCP_WHAT_ACK, 
                        0, seqno_me, secs, usecs, seqno_them);
                }

                /* If this contains payload, handle that */
                if (parsed.app_length) {
                    tcpcon_handle(tcpcon, tcb, TCP_WHAT_DATA, 
                        px + parsed.app_offset, parsed.app_length,
                        secs, usecs, seqno_them);
                }

                /* If this is a FIN, handle that. Note that ACK + 
                 * payload + FIN can come together */
                if (TCP_IS_FIN(px, parsed.transport_offset) 
                    && !TCP_IS_RST(px, parsed.transport_offset)) {
                    tcpcon_handle(tcpcon, tcb, TCP_WHAT_FIN, 
                        0, 0, secs, usecs, seqno_them);
                }

                /* If this is a RST, then we'll be closing the connection */
                if (TCP_IS_RST(px, parsed.transport_offset)) {
                    tcpcon_handle(tcpcon, tcb, TCP_WHAT_RST, 
                        0, 0, secs, usecs, seqno_them);
                }
            } else if (TCP_IS_FIN(px, parsed.transport_offset)) {
                /* 
                 * NO TCB!
                 *  This happens when we've sent a FIN, deleted our connection,
                 *  but the other side didn't get the packet.
                 */
                if (!TCP_IS_RST(px, parsed.transport_offset))
                tcpcon_send_FIN(
                    tcpcon,
                    ip_me, ip_them,
                    port_me, port_them,
                    seqno_them, seqno_me);
            }

        }