Esempio n. 1
0
int packet_get_line(struct strbuf *out,
	char **src_buf, size_t *src_len)
{
	int len;

	if (*src_len < 4)
		return -1;
	len = packet_length(*src_buf);
	if (len < 0)
		return -1;
	if (!len) {
		*src_buf += 4;
		*src_len -= 4;
		packet_trace("0000", 4, 0);
		return 0;
	}
	if (*src_len < len)
		return -2;

	*src_buf += 4;
	*src_len -= 4;
	len -= 4;

	strbuf_add(out, *src_buf, len);
	*src_buf += len;
	*src_len -= len;
	packet_trace(out->buf, out->len, 0);
	return len;
}
Esempio n. 2
0
int packet_read(int fd, char **src_buf, size_t *src_len,
		char *buffer, unsigned size, int options)
{
	int len, ret;
	char linelen[4];

	ret = get_packet_data(fd, src_buf, src_len, linelen, 4, options);
	if (ret < 0)
		return ret;
	len = packet_length(linelen);
	if (len < 0)
		die("protocol error: bad line length character: %.4s", linelen);
	if (!len) {
		packet_trace("0000", 4, 0);
		return 0;
	}
	len -= 4;
	if (len >= size)
		die("protocol error: bad line length %d", len);
	ret = get_packet_data(fd, src_buf, src_len, buffer, len, options);
	if (ret < 0)
		return ret;

	if ((options & PACKET_READ_CHOMP_NEWLINE) &&
	    len && buffer[len-1] == '\n')
		len--;

	buffer[len] = 0;
	packet_trace(buffer, len, 0);
	return len;
}
Esempio n. 3
0
int packet_flush_gently(int fd)
{
	packet_trace("0000", 4, 1);
	if (write_in_full(fd, "0000", 4) == 4)
		return 0;
	return error("flush packet write failed");
}
Esempio n. 4
0
int packet_read_line(int fd, char *buffer, unsigned size)
{
	int len;
	char linelen[4];

	safe_read(fd, linelen, 4);
	len = packet_length(linelen);
	if (len < 0)
		die("protocol error: bad line length character: %.4s", linelen);
	if (!len) {
		packet_trace("0000", 4, 0);
		return 0;
	}
	len -= 4;
	if (len >= size)
		die("protocol error: bad line length %d", len);
	safe_read(fd, buffer, len);
	buffer[len] = 0;
	packet_trace(buffer, len, 0);
	return len;
}
Esempio n. 5
0
/***************************************************************************
 * wrapper for libpcap's sendpacket
 *
 * PORTABILITY: WINDOWS and PF_RING
 * For performance, Windows and PF_RING can queue up multiple packets, then
 * transmit them all in a chunk. If we stop and wait for a bit, we need
 * to flush the queue to force packets to be transmitted immediately.
 ***************************************************************************/
int
rawsock_send_packet(
    struct Adapter *adapter,
    const unsigned char *packet,
    unsigned length,
    unsigned flush)
{
    if (adapter == 0)
        return 0;

    /* Print --packet-trace if debugging */
    if (adapter->is_packet_trace) {
        packet_trace(stdout, adapter->pt_start, packet, length, 1);
    }

    /* PF_RING */
    if (adapter->ring) {
        int err = PF_RING_ERROR_NO_TX_SLOT_AVAILABLE;

        while (err == PF_RING_ERROR_NO_TX_SLOT_AVAILABLE) {
            err = PFRING.send(adapter->ring, packet, length, (unsigned char)flush);
        }
        if (err < 0)
            LOG(1, "pfring:xmit: ERROR %d\n", err);
        return err;
    }

    /* WINDOWS PCAP */
    if (adapter->sendq) {
        int err;
        struct pcap_pkthdr hdr;
        hdr.len = length;
        hdr.caplen = length;

        err = pcap_sendqueue_queue(adapter->sendq, &hdr, packet);
        if (err) {
            rawsock_flush(adapter);
            pcap_sendqueue_queue(adapter->sendq, &hdr, packet);
        }

        if (flush) {
            rawsock_flush(adapter);
        }

        return 0;
    }

    /* LIBPCAP */
    if (adapter->pcap)
        return pcap_sendpacket(adapter->pcap, packet, length);

    return 0;
}
Esempio n. 6
0
static void format_packet(struct strbuf *out, const char *fmt, va_list args)
{
	size_t orig_len, n;

	orig_len = out->len;
	strbuf_addstr(out, "0000");
	strbuf_vaddf(out, fmt, args);
	n = out->len - orig_len;

	if (n > LARGE_PACKET_MAX)
		die("protocol error: impossibly long line");

	set_packet_header(&out->buf[orig_len], n);
	packet_trace(out->buf + orig_len + 4, n - 4, 1);
}
Esempio n. 7
0
static int packet_write_gently(const int fd_out, const char *buf, size_t size)
{
	static char packet_write_buffer[LARGE_PACKET_MAX];
	size_t packet_size;

	if (size > sizeof(packet_write_buffer) - 4)
		return error("packet write failed - data exceeds max packet size");

	packet_trace(buf, size, 1);
	packet_size = size + 4;
	set_packet_header(packet_write_buffer, packet_size);
	memcpy(packet_write_buffer + 4, buf, size);
	if (write_in_full(fd_out, packet_write_buffer, packet_size) == packet_size)
		return 0;
	return error("packet write failed");
}
Esempio n. 8
0
static unsigned format_packet(const char *fmt, va_list args)
{
	static char hexchar[] = "0123456789abcdef";
	unsigned n;

	n = vsnprintf(buffer + 4, sizeof(buffer) - 4, fmt, args);
	if (n >= sizeof(buffer)-4)
		die("protocol error: impossibly long line");
	n += 4;
	buffer[0] = hex(n >> 12);
	buffer[1] = hex(n >> 8);
	buffer[2] = hex(n >> 4);
	buffer[3] = hex(n);
	packet_trace(buffer+4, n-4, 1);
	return n;
}
Esempio n. 9
0
static void  CTCT_Write( DEVBLK* pDEVBLK,   U32   sCount,
                         BYTE*   pIOBuf,    BYTE* pUnitStat,
                         U32*    pResidual )
{
    PCTCIHDR   pFrame;                  // -> Frame header
    PCTCISEG   pSegment;                // -> Segment in buffer
    U16        sOffset;                 // Offset of next frame
    U16        sSegLen;                 // Current segment length
    U16        sDataLen;                // Length of IP Frame data
    int        iPos;                    // Offset into buffer
    U16        i;                       // Array subscript
    int        rc;                      // Return code
    BYTE       szStackID[33];           // VSE IP stack identity
    U32        iStackCmd;               // VSE IP stack command

    // Check that CCW count is sufficient to contain block header
    if( sCount < sizeof( CTCIHDR ) )
    {
        WRMSG(HHC00906, "E", SSID_TO_LCSS(pDEVBLK->ssid), pDEVBLK->devnum, sCount );

        pDEVBLK->sense[0] = SENSE_DC;
        *pUnitStat        = CSW_CE | CSW_DE | CSW_UC;
        return;
    }

    // Fix-up frame pointer
    pFrame = (PCTCIHDR)pIOBuf;

    // Extract the frame length from the header
    FETCH_HW( sOffset, pFrame->hwOffset );


    // Check for special VSE TCP/IP stack command packet
    if( sOffset == 0 && sCount == 40 )
    {
        // Extract the 32-byte stack identity string
        for( i = 0;
             i < sizeof( szStackID ) - 1 && i < sCount - 4;
             i++)
            szStackID[i] = guest_to_host( pIOBuf[i+4] );

        szStackID[i] = '\0';

        // Extract the stack command word
        FETCH_FW( iStackCmd, *((FWORD*)&pIOBuf[36]) );

        // Display stack command and discard the packet
        WRMSG(HHC00907, "I", SSID_TO_LCSS(pDEVBLK->ssid), pDEVBLK->devnum, szStackID, iStackCmd );

        *pUnitStat = CSW_CE | CSW_DE;
        *pResidual = 0;
        return;
    }

    // Check for special L/390 initialization packet
    if( sOffset == 0 )
    {
        // Return normal status and discard the packet
        *pUnitStat = CSW_CE | CSW_DE;
        *pResidual = 0;
        return;
    }

#if 0
    // Notes: It appears that TurboLinux has gotten sloppy in their
    //        ways. They are now giving us buffer sizes that are
    //        greater than the CCW count, but the segment size
    //        is within the count.
    // Check that the frame offset is valid
    if( sOffset < sizeof( CTCIHDR ) || sOffset > sCount )
    {
        logmsg( _("CTC101W %4.4X: Write buffer contains invalid "
                  "frame offset %u\n"),
                pDEVBLK->devnum, sOffset );

        pDEVBLK->sense[0] = SENSE_CR;
        *pUnitStat        = CSW_CE | CSW_DE | CSW_UC;
        return;
    }
#endif

    // Adjust the residual byte count
    *pResidual -= sizeof( CTCIHDR );

    // Process each segment in the buffer
    for( iPos  = sizeof( CTCIHDR );
         iPos  < sOffset;
         iPos += sSegLen )
    {
        // Check that the segment is fully contained within the block
        if( iPos + sizeof( CTCISEG ) > sOffset )
        {
            WRMSG(HHC00908, "E", SSID_TO_LCSS(pDEVBLK->ssid), pDEVBLK->devnum, iPos );

            pDEVBLK->sense[0] = SENSE_DC;
            *pUnitStat        = CSW_CE | CSW_DE | CSW_UC;
            return;
        }

        // Fix-up segment header in the I/O buffer
        pSegment = (PCTCISEG)(pIOBuf + iPos);

        // Extract the segment length from the segment header
        FETCH_HW( sSegLen, pSegment->hwLength );

        // Check that the segment length is valid
        if( ( sSegLen        < sizeof( CTCISEG ) ) ||
            ( (U32)iPos + sSegLen > sOffset      ) ||
            ( (U32)iPos + sSegLen > sCount       ) )
        {
            WRMSG(HHC00909, "E", SSID_TO_LCSS(pDEVBLK->ssid), pDEVBLK->devnum, sSegLen, iPos );

            pDEVBLK->sense[0] = SENSE_DC;
            *pUnitStat        = CSW_CE | CSW_DE | CSW_UC;
            return;
        }

        // Calculate length of IP frame data
        sDataLen = sSegLen - sizeof( CTCISEG );

        // Trace the IP packet before sending
        if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep )
        {
            WRMSG(HHC00934, "I", SSID_TO_LCSS(pDEVBLK->ssid), pDEVBLK->devnum, pDEVBLK->filename );
            if( pDEVBLK->ccwtrace )
                packet_trace( pSegment->bData, sDataLen, '>' );
        }

        // Write the IP packet
        rc = write_socket( pDEVBLK->fd, pSegment->bData, sDataLen );

        if( rc < 0 )
        {
            WRMSG(HHC00936, "E", SSID_TO_LCSS(pDEVBLK->ssid), pDEVBLK->devnum, pDEVBLK->filename,
                    strerror( HSO_errno ) );

            pDEVBLK->sense[0] = SENSE_EC;
            *pUnitStat        = CSW_CE | CSW_DE | CSW_UC;
            return;
        }

        // Adjust the residual byte count
        *pResidual -= sSegLen;

        // We are done if current segment satisfies CCW count
        if( (U32)iPos + sSegLen == sCount )
        {
            *pResidual -= sSegLen;
            *pUnitStat = CSW_CE | CSW_DE;
            return;
        }
    }

    // Set unit status and residual byte count
    *pUnitStat = CSW_CE | CSW_DE;
    *pResidual = 0;
}
Esempio n. 10
0
/*
 * If we buffered things up above (we don't, but we should),
 * we'd flush it here
 */
void packet_flush(int fd)
{
	packet_trace("0000", 4, 1);
	write_or_die(fd, "0000", 4);
}
Esempio n. 11
0
void  CTCI_Write( DEVBLK* pDEVBLK,   U16   sCount,
                  BYTE*   pIOBuf,    BYTE* pUnitStat,
                  U16*    pResidual )
{
    PCTCBLK    pCTCBLK  = (PCTCBLK)pDEVBLK->dev_data;
    PCTCIHDR   pFrame;                  // -> Frame header
    PCTCISEG   pSegment;                // -> Segment in buffer
    U16        sOffset;                 // Offset of next frame
    U16        sSegLen;                 // Current segment length
    U16        sDataLen;                // Length of IP Frame data
    int        iPos;                    // Offset into buffer
    U16        i;                       // Array subscript
    int        rc;                      // Return code
    BYTE       szStackID[33];           // VSE IP stack identity
    U32        iStackCmd;               // VSE IP stack command

    // Check that CCW count is sufficient to contain block header
    if( sCount < sizeof( CTCIHDR ) )
    {
        logmsg( _("HHCCT042E %4.4X: Write CCW count %u is invalid\n"),
                pDEVBLK->devnum, sCount );

        pDEVBLK->sense[0] = SENSE_DC;
        *pUnitStat        = CSW_CE | CSW_DE | CSW_UC;

        return;
    }

    // Fix-up frame pointer
    pFrame = (PCTCIHDR)pIOBuf;

    // Extract the frame length from the header
    FETCH_HW( sOffset, pFrame->hwOffset );

    // Check for special VSE TCP/IP stack command packet
    if( sOffset == 0 && sCount == 40 )
    {
        // Extract the 32-byte stack identity string
        for( i = 0;
             i < sizeof( szStackID ) - 1 && i < sCount - 4;
             i++)
            szStackID[i] = guest_to_host( pIOBuf[i+4] );
        szStackID[i] = '\0';

        // Extract the stack command word
        FETCH_FW( iStackCmd, *((FWORD*)&pIOBuf[36]) );

        // Display stack command and discard the packet
        logmsg( _("HHCCT043I %4.4X: Interface command: %s %8.8X\n"),
                pDEVBLK->devnum, szStackID, iStackCmd );

        *pUnitStat = CSW_CE | CSW_DE;
        *pResidual = 0;

        return;
    }

    // Check for special L/390 initialization packet
    if( sOffset == 0 )
    {
        // Return normal status and discard the packet
        *pUnitStat = CSW_CE | CSW_DE;
        *pResidual = 0;

        return;
    }

#if 0
    // Notes: It appears that TurboLinux has gotten sloppy in their
    //        ways. They are now giving us buffer sizes that are
    //        greater than the CCW count, but the segment size
    //        is within the count.
    // Check that the frame offset is valid
    if( sOffset < sizeof( CTCIHDR ) || sOffset > sCount )
    {
        logmsg( _("CTC101W %4.4X: Write buffer contains invalid "
                  "frame offset %u\n"),
                pDEVBLK->devnum, sOffset );

        pDEVBLK->sense[0] = SENSE_CR;
        *pUnitStat        = CSW_CE | CSW_DE | CSW_UC;

        return;
    }
#endif

    // Adjust the residual byte count
    *pResidual -= sizeof( CTCIHDR );

    // Process each segment in the buffer
    for( iPos  = sizeof( CTCIHDR );
         iPos  < sOffset;
         iPos += sSegLen )
    {
        // Check that the segment is fully contained within the block
        if( iPos + sizeof( CTCISEG ) > sOffset )
        {
            logmsg( _("HHCCT044E %4.4X: Write buffer contains incomplete "
                      "segment header at offset %4.4X\n"),
                    pDEVBLK->devnum, iPos );

            pDEVBLK->sense[0] = SENSE_DC;
            *pUnitStat        = CSW_CE | CSW_DE | CSW_UC;
            return;
        }

        // Fix-up segment header in the I/O buffer
        pSegment = (PCTCISEG)(pIOBuf + iPos);

        // Extract the segment length from the segment header
        FETCH_HW( sSegLen, pSegment->hwLength );

        // Check that the segment length is valid
        if( ( sSegLen        < sizeof( CTCISEG ) ) ||
            ( iPos + sSegLen > sOffset           ) ||
            ( iPos + sSegLen > sCount            ) )
        {
            logmsg( _("HHCCT045E %4.4X: Write buffer contains invalid "
                    "segment length %u at offset %4.4X\n"),
                    pDEVBLK->devnum, sSegLen, iPos );

            pDEVBLK->sense[0] = SENSE_DC;
            *pUnitStat        = CSW_CE | CSW_DE | CSW_UC;
            return;
        }

        // Calculate length of IP frame data
        sDataLen = sSegLen - sizeof( CTCISEG );

        // Trace the IP packet before sending to TUN device
        if( pCTCBLK->fDebug )
        {
            logmsg( _("HHCCT046I %4.4X: Sending packet to %s:\n"),
                    pDEVBLK->devnum, pCTCBLK->szTUNDevName );
            packet_trace( pSegment->bData, sDataLen );
        }

        // Write the IP packet to the TUN/TAP interface
        rc = TUNTAP_Write( pCTCBLK->fd, pSegment->bData, sDataLen );

        if( rc < 0 )
        {
            logmsg( _("HHCCT047E %4.4X: Error writing to %s: rc=%d errno=%d %s\n"),
                    pDEVBLK->devnum, pCTCBLK->szTUNDevName,
                    rc, errno, strerror(errno));
        }

        /* Kludge for Ubuntu 10.04 by Martin Truebner */
        if (rc == -1 && errno == 22) rc = 0;

        if (rc < 0)
        {
            pDEVBLK->sense[0] = SENSE_EC;
            *pUnitStat        = CSW_CE | CSW_DE | CSW_UC;
            return;
        }

        // Adjust the residual byte count
        *pResidual -= sSegLen;

        // We are done if current segment satisfies CCW count
        if( iPos + sSegLen == sCount )
        {
            *pResidual -= sSegLen;
            *pUnitStat = CSW_CE | CSW_DE;
            return;
        }
    }

    // Set unit status and residual byte count
    *pUnitStat = CSW_CE | CSW_DE;
    *pResidual = 0;
}
Esempio n. 12
0
/***************************************************************************
 * wrapper for libpcap's sendpacket
 *
 * PORTABILITY: WINDOWS and PF_RING
 * For performance, Windows and PF_RING can queue up multiple packets, then
 * transmit them all in a chunk. If we stop and wait for a bit, we need
 * to flush the queue to force packets to be transmitted immediately.
 ***************************************************************************/
int
rawsock_send_packet(
    struct Adapter *adapter,
    const unsigned char *packet,
    unsigned length,
    unsigned flush)
{
    if (adapter == 0)
        return 0;
    
    /* Print --packet-trace if debugging */
    if (adapter->is_packet_trace) {
        packet_trace(stdout, packet, length, 1);
    }

    /* PF_RING */
    if (adapter->ring) {
        int err = PF_RING_ERROR_NO_TX_SLOT_AVAILABLE;

        while (err == PF_RING_ERROR_NO_TX_SLOT_AVAILABLE) {
            err = PFRING.send(adapter->ring, packet, length, (unsigned char)flush);
        }
        if (err < 0)
            LOG(1, "pfring:xmit: ERROR %d\n", err);
        return err;
    }

    /* WINDOWS PCAP */
    if (adapter->sendq) {
        int err;
        struct pcap_pkthdr hdr;
        hdr.len = length;
        hdr.caplen = length;

        err = pcap_sendqueue_queue(adapter->sendq, &hdr, packet);
        if (err) {
            //printf("sendpacket() failed %d\n", x);
            //for (;;)
            pcap_sendqueue_transmit(adapter->pcap, adapter->sendq, 0);
            //printf("pcap_send_queue)() returned %u\n", x);
            pcap_sendqueue_destroy(adapter->sendq);
            adapter->sendq =  pcap_sendqueue_alloc(SENDQ_SIZE);
            pcap_sendqueue_queue(adapter->sendq, &hdr, packet);
            //("sendpacket() returned %d\n", x);
            //exit(1);
        } else
            ; //printf("+%u\n", count++);
        if (flush) {
            pcap_sendqueue_transmit(adapter->pcap, adapter->sendq, 0);

            /* Dude, I totally forget why this step is necessary. I vaguely
             * remember there's a good reason for it though */
            pcap_sendqueue_destroy(adapter->sendq);
            adapter->sendq =  pcap_sendqueue_alloc(SENDQ_SIZE);
        }
        return 0;
    }

    /* LIBPCAP */
    if (adapter->pcap)
        return pcap_sendpacket(adapter->pcap, packet, length);

    return 0;
}
Esempio n. 13
0
/*
 * If we buffered things up above (we don't, but we should),
 * we'd flush it here
 */
void packet_flush(int fd)
{
	packet_trace("0000", 4, 1);
	safe_write(fd, "0000", 4);
}
Esempio n. 14
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);
            }

        }
Esempio n. 15
0
static void*  CTCI_ReadThread( PCTCBLK pCTCBLK )
{
    DEVBLK*  pDEVBLK = pCTCBLK->pDEVBLK[0];
    int      iLength;
    BYTE     szBuff[2048];

    // ZZ FIXME: Try to avoid race condition at startup with hercifc
    SLEEP(10);

    pCTCBLK->pid = getpid();

    while( pCTCBLK->fd != -1 && !pCTCBLK->fCloseInProgress )
    {
        // Read frame from the TUN/TAP interface
        iLength = TUNTAP_Read( pCTCBLK->fd, szBuff, sizeof(szBuff) );

        // Check for error condition
        if( iLength < 0 )
        {
            logmsg( _("HHCCT048E %4.4X: Error reading from %s: %s\n"),
                pDEVBLK->devnum, pCTCBLK->szTUNDevName,
                strerror( errno ) );
            SLEEP(1);           // (purposeful long delay)
            continue;
        }

        if( iLength == 0 )      // (probably EINTR; ignore)
            continue;

        if( pCTCBLK->fDebug )
        {
            logmsg( _("HHCCT049I %4.4X: Received packet from %s (%d bytes):\n"),
                    pDEVBLK->devnum, pCTCBLK->szTUNDevName, iLength );
            packet_trace( szBuff, iLength );
        }

        // Enqueue frame on buffer, if buffer is full, keep trying
        while( CTCI_EnqueueIPFrame( pDEVBLK, szBuff, iLength ) < 0
            && pCTCBLK->fd != -1 && !pCTCBLK->fCloseInProgress )
        {
            if( EMSGSIZE == errno )     // (if too large for buffer)
            {
                if( pCTCBLK->fDebug )
                    logmsg( _("HHCCT072W %4.4X: Packet too big; dropped.\n"),
                            pDEVBLK->devnum );
                break;                  // (discard it...)
            }

            ASSERT( ENOBUFS == errno );

            // Don't use sched_yield() here; use an actual non-dispatchable
            // delay instead so as to allow another [possibly lower priority]
            // thread to 'read' (remove) some packet(s) from our frame buffer.
            usleep( CTC_DELAY_USECS );  // (wait a bit before retrying...)
        }
    }

    // We must do the close since we were the one doing the i/o...

    VERIFY( pCTCBLK->fd == -1 || TUNTAP_Close( pCTCBLK->fd ) == 0 );
    pCTCBLK->fd = -1;

    return NULL;
}
Esempio n. 16
0
static void  CTCT_Read( DEVBLK* pDEVBLK,   U32   sCount,
                        BYTE*   pIOBuf,    BYTE* pUnitStat,
                        U32*    pResidual, BYTE* pMore )
{
    PCTCIHDR    pFrame   = NULL;       // -> Frame header
    PCTCISEG    pSegment = NULL;       // -> Segment in buffer
    fd_set      rfds;                  // Read FD_SET
    int         iRetVal;               // Return code from 'select'
    int         iLength  = 0;

    static struct timeval tv;          // Timeout time for 'select'


    // Limit how long we should wait for data to come in
    FD_ZERO( &rfds );
    FD_SET( pDEVBLK->fd, &rfds );

    tv.tv_sec  = CTC_READ_TIMEOUT_SECS;
    tv.tv_usec = 0;

    iRetVal = select( pDEVBLK->fd + 1, &rfds, NULL, NULL, &tv );

    switch( iRetVal )
    {
    case 0:
        *pUnitStat = CSW_CE | CSW_DE | CSW_UC | CSW_SM;
        pDEVBLK->sense[0] = 0;
        return;

    case -1:
        if( HSO_errno == HSO_EINTR )
            return;

        WRMSG(HHC00973, "E", SSID_TO_LCSS(pDEVBLK->ssid), pDEVBLK->devnum, pDEVBLK->filename,
              strerror( HSO_errno ) );

        pDEVBLK->sense[0] = SENSE_EC;
        *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
        return;

    default:
        break;
    }

    // Read an IP packet from the TUN device
    iLength = read_socket( pDEVBLK->fd, pDEVBLK->buf, pDEVBLK->bufsize );

    // Check for other error condition
    if( iLength < 0 )
    {
        WRMSG(HHC00973, "E", SSID_TO_LCSS(pDEVBLK->ssid), pDEVBLK->devnum, pDEVBLK->filename,
              strerror( HSO_errno ) );
        pDEVBLK->sense[0] = SENSE_EC;
        *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
        return;
    }

    // Trace the packet received from the TUN device
    if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep )
    {
        WRMSG(HHC00913, "I", SSID_TO_LCSS(pDEVBLK->ssid), pDEVBLK->devnum, iLength, "TUN" );
        packet_trace( pDEVBLK->buf, iLength, '<' );
    }

    // Fix-up Frame pointer
    pFrame = (PCTCIHDR)pIOBuf;

    // Fix-up Segment pointer
    pSegment = (PCTCISEG)( pIOBuf + sizeof( CTCIHDR ) );

    // Initialize segment
    memset( pSegment, 0, iLength + sizeof( CTCISEG ) );

    // Update next frame offset
    STORE_HW( pFrame->hwOffset,
              (U16)(iLength + sizeof( CTCIHDR ) + sizeof( CTCISEG )) );

    // Store segment length
    STORE_HW( pSegment->hwLength, (U16)(iLength + sizeof( CTCISEG )) );

    // Store Frame type
    STORE_HW( pSegment->hwType, ETH_TYPE_IP );

    // Copy data
    memcpy( pSegment->bData, pDEVBLK->buf, iLength );

    // Fix-up frame pointer and terminate block
    pFrame = (PCTCIHDR)( pIOBuf + sizeof( CTCIHDR ) +
                         sizeof( CTCISEG ) + iLength );
    STORE_HW( pFrame->hwOffset, 0x0000 );

    // Calculate #of bytes returned including two slack bytes
    iLength += sizeof( CTCIHDR ) + sizeof( CTCISEG ) + 2;

    if( sCount < (U32)iLength )
    {
        *pMore     = 1;
        *pResidual = 0;

        iLength    = sCount;
    }
    else
    {
        *pMore      = 0;
        *pResidual -= iLength;
    }

    // Set unit status
    *pUnitStat = CSW_CE | CSW_DE;
}
Esempio n. 17
0
void packet_buf_flush(struct strbuf *buf)
{
	packet_trace("0000", 4, 1);
	strbuf_add(buf, "0000", 4);
}
Esempio n. 18
0
void  CTCI_Read( DEVBLK* pDEVBLK,   U16   sCount,
                 BYTE*   pIOBuf,    BYTE* pUnitStat,
                 U16*    pResidual, BYTE* pMore )
{
    PCTCBLK     pCTCBLK  = (PCTCBLK)pDEVBLK->dev_data;
    PCTCIHDR    pFrame   = NULL;
    size_t      iLength  = 0;
    int         rc       = 0;

    for ( ; ; )
    {
        obtain_lock( &pCTCBLK->Lock );

        if( !pCTCBLK->fDataPending )
        {
            struct timespec waittime;
            struct timeval  now;

            release_lock( &pCTCBLK->Lock );

            gettimeofday( &now, NULL );

            waittime.tv_sec  = now.tv_sec  + CTC_READ_TIMEOUT_SECS;
            waittime.tv_nsec = now.tv_usec * 1000;

            obtain_lock( &pCTCBLK->EventLock );
            rc = timed_wait_condition( &pCTCBLK->Event,
                                       &pCTCBLK->EventLock,
                                       &waittime );
            release_lock( &pCTCBLK->EventLock );

            if( rc == ETIMEDOUT || rc == EINTR )
            {
                // check for halt condition
                if( pDEVBLK->scsw.flag2 & SCSW2_FC_HALT ||
                    pDEVBLK->scsw.flag2 & SCSW2_FC_CLEAR )
                {
                    if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep )
                        logmsg( _("HHCCT040I %4.4X: Halt or Clear Recognized\n"),
                                pDEVBLK->devnum );

                    *pUnitStat = CSW_CE | CSW_DE;
                    *pResidual = sCount;
                    return;
                }

                continue;
            }

            obtain_lock( &pCTCBLK->Lock );
        }

        // Sanity check
        if( pCTCBLK->iFrameOffset == 0 )
        {
            release_lock( &pCTCBLK->Lock );
            continue;
        }

        // Fix-up frame pointer and terminate block
        pFrame = (PCTCIHDR)( pCTCBLK->bFrameBuffer +
                  sizeof( CTCIHDR ) +
                  pCTCBLK->iFrameOffset );

        STORE_HW( pFrame->hwOffset, 0x0000 );

        // (fix for day-1 bug offered by Vince Weaver [[email protected]])
//      iLength = pCTCBLK->iFrameOffset + sizeof( CTCIHDR ) + 2;
        iLength = pCTCBLK->iFrameOffset + sizeof( CTCIHDR );

        if( sCount < iLength )
        {
            *pMore     = 1;
            *pResidual = 0;

            iLength    = sCount;
        }
        else
        {
            *pMore      = 0;
            *pResidual -= iLength;
        }

        *pUnitStat = CSW_CE | CSW_DE;

        memcpy( pIOBuf, pCTCBLK->bFrameBuffer, iLength );

        if( pCTCBLK->fDebug )
        {
            logmsg( _("HHCCT041I %4.4X: CTC Received Frame (%d bytes):\n"),
                    pDEVBLK->devnum, iLength );
            packet_trace( pCTCBLK->bFrameBuffer, iLength );
        }

        // Reset frame buffer
        pCTCBLK->iFrameOffset  = 0;
        pCTCBLK->fDataPending  = 0;

        release_lock( &pCTCBLK->Lock );

        return;
    }
}