Example #1
0
int
parse_sflow_datagram(const char *bp, int len)
{
	const char *p = bp;
	u_int32_t addr_type, agent_id = 0, seqno, uptime, nrecords;
	int	i;

	timestamp = time(NULL);	/* timestamp for this sflow datagram */
	endp = bp + len;

	/* sflow datagram header */
	sflow_version 	= buffer_read_4(&p);
	if (sflow_version != 4 && sflow_version != 5) {
		warnx("unkonwn sflow version 0x%x", sflow_version);
		return (len);
	}
	addr_type = buffer_read_4(&p);
	switch (addr_type) {
	case 1: /* IPv4 */
		buffer_skip(&p, 4);
		break;
	case 2: /* IPv6 */
		buffer_skip(&p, 16);
		break;
	default:
		return (-1);
	}
	if (sflow_version >= 5) {
		agent_id	= buffer_read_4(&p);
	}
	seqno	 	= buffer_read_4(&p);
	uptime	 	= buffer_read_4(&p);
	nrecords 	= buffer_read_4(&p);

#if 1
	if (verbose > 1)
		fprintf(stderr, "sflow datagram: ver=%u, agent_id=%u, addr_type=%u, nrecords=%u\n",
		    sflow_version, agent_id, addr_type, nrecords);
#endif

	for (i = 0; i < nrecords; i++) {
		if (sflow_version >= 5)
			parse_sflow5(&p);
		else {
			if (parse_sflow4_sample(&p) < 0) {
				/* if parsing failed for v4, give up */
				if (verbose > 0)
					fprintf(stderr, "parse_sflow4 failed\n");
				break;
			}
		}
	}

	return (len);
}
Example #2
0
File: dns.c Project: lc7cl/www
int get_record(buffer_type *buffer,
               struct decompress_ctx * decompress, 
               struct rr *record)
{
    int ret;
    
    if (buffer == NULL || record == NULL)
        return -1;
    ret = dns_name_from_wire(buffer, decompress, record->name);
    if (ret == -1)
        return -1;
    if (!buffer_available(buffer, 2 * sizeof(u_int16_t)))
        return -1;
    record->type = buffer_read_u16(buffer);
    buffer_skip(buffer, 
                sizeof(u_int16_t) + sizeof(u_int32_t) + sizeof(u_int16_t));
    switch (record->type) {
    case TYPE_A:
        if (!buffer_available(buffer, sizeof(u_int32_t)))
            return -1;
        buffer_read(buffer, record->rdata, 4);
        break;
    case TYPE_CNAME:
        ret = dns_name_from_wire(buffer, decompress, record->rdata);
        if (ret == -1)
            return ret;
        break;
    default:
        return -1;
    }
    return 0;
}
Example #3
0
int
packet_encode_rr(query_type *q, domain_type *owner, rr_type *rr)
{
	size_t truncation_mark;
	uint16_t rdlength = 0;
	size_t rdlength_pos;
	uint16_t j;

	assert(q);
	assert(owner);
	assert(rr);

	/*
	 * If the record does not in fit in the packet the packet size
	 * will be restored to the mark.
	 */
	truncation_mark = buffer_position(q->packet);

	encode_dname(q, owner);
	buffer_write_u16(q->packet, rr->type);
	buffer_write_u16(q->packet, rr->klass);
	buffer_write_u32(q->packet, rr->ttl);

	/* Reserve space for rdlength. */
	rdlength_pos = buffer_position(q->packet);
	buffer_skip(q->packet, sizeof(rdlength));

	for (j = 0; j < rr->rdata_count; ++j) {
		switch (rdata_atom_wireformat_type(rr->type, j)) {
		case RDATA_WF_COMPRESSED_DNAME:
			encode_dname(q, rdata_atom_domain(rr->rdatas[j]));
			break;
		case RDATA_WF_UNCOMPRESSED_DNAME:
		{
			const dname_type *dname = domain_dname(
				rdata_atom_domain(rr->rdatas[j]));
			buffer_write(q->packet,
				     dname_name(dname), dname->name_size);
			break;
		}
		default:
			buffer_write(q->packet,
				     rdata_atom_data(rr->rdatas[j]),
				     rdata_atom_size(rr->rdatas[j]));
			break;
		}
	}

	if (!query_overflow(q)) {
		rdlength = (buffer_position(q->packet) - rdlength_pos
			    - sizeof(rdlength));
		buffer_write_u16_at(q->packet, rdlength_pos, rdlength);
		return 1;
	} else {
		buffer_set_position(q->packet, truncation_mark);
		query_clear_dname_offsets(q, truncation_mark);
		assert(!query_overflow(q));
		return 0;
	}
}
/**
 * IXFR.
 *
 */
static query_state
query_process_ixfr(query_type* q)
{
    uint16_t count = 0;
    ods_log_assert(q);
    ods_log_assert(q->buffer);
    ods_log_assert(buffer_pkt_qdcount(q->buffer) == 1);
    /* skip header and question section */
    buffer_skip(q->buffer, BUFFER_PKT_HEADER_SIZE);
    if (!buffer_skip_rr(q->buffer, 1)) {
        ods_log_error("[%s] dropped packet: zone %s received bad ixfr "
            "request (bad question section)", query_str, q->zone->name);
        return QUERY_DISCARDED;
    }
    /* answer section is empty */
    ods_log_assert(buffer_pkt_ancount(q->buffer) == 0);
    /* examine auth section */
    q->startpos = buffer_position(q->buffer);
    count = buffer_pkt_nscount(q->buffer);
    if (count) {
        if (!buffer_skip_dname(q->buffer) ||
            !query_parse_soa(q->buffer, &(q->serial))) {
            ods_log_error("[%s] dropped packet: zone %s received bad ixfr "
                "request (bad soa in auth section)", query_str, q->zone->name);
            return QUERY_DISCARDED;
        }
        ods_log_debug("[%s] found ixfr request zone %s serial=%u", query_str,
            q->zone->name, q->serial);
        return QUERY_PROCESSED;
    }
    ods_log_debug("[%s] ixfr request zone %s has no auth section", query_str,
        q->zone->name);
    q->serial = 0;
    return QUERY_PROCESSED;
}
Example #5
0
off_t
buffer_copy_IntInt(int Iin, int Tin,
                   void *Pfilter, int Tfilter,
                   int Iout, int Tout,
                   off_t limit, struct dpkg_error *err)
{
	struct buffer_data read_data = { .type = Tin, .arg.i = Iin };
	struct buffer_data filter = { .type = Tfilter, .arg.ptr = Pfilter };
	struct buffer_data write_data = { .type = Tout, .arg.i = Iout };

	return buffer_copy(&read_data, &filter, &write_data, limit, err);
}

off_t
buffer_copy_IntPtr(int Iin, int Tin,
                   void *Pfilter, int Tfilter,
                   void *Pout, int Tout,
                   off_t limit, struct dpkg_error *err)
{
	struct buffer_data read_data = { .type = Tin, .arg.i = Iin };
	struct buffer_data filter = { .type = Tfilter, .arg.ptr = Pfilter };
	struct buffer_data write_data = { .type = Tout, .arg.ptr = Pout };

	return buffer_copy(&read_data, &filter, &write_data, limit, err);
}

static off_t
buffer_skip(struct buffer_data *input, off_t limit, struct dpkg_error *err)
{
	struct buffer_data output;
	struct buffer_data filter;

	switch (input->type) {
	case BUFFER_READ_FD:
		if (lseek(input->arg.i, limit, SEEK_CUR) != -1)
			return limit;
		if (errno != ESPIPE)
			return dpkg_put_errno(err, _("failed to seek"));
		break;
	default:
		internerr("unknown data type %i", input->type);
	}

	output.type = BUFFER_WRITE_NULL;
	output.arg.ptr = NULL;
	filter.type = BUFFER_FILTER_NULL;
	filter.arg.ptr = NULL;

	return buffer_copy(input, &filter, &output, limit, err);
}

off_t
buffer_skip_Int(int I, int T, off_t limit, struct dpkg_error *err)
{
	struct buffer_data input = { .type = T, .arg.i = I };

	return buffer_skip(&input, limit, err);
}
Example #6
0
void
xfrd_handle_passed_packet(buffer_type* packet, int acl_num)
{
	uint8_t qnamebuf[MAXDOMAINLEN];
	uint16_t qtype, qclass;
	const dname_type* dname;
	region_type* tempregion = region_create(xalloc, free);
	xfrd_zone_t* zone;

	buffer_skip(packet, QHEADERSZ);
	if(!packet_read_query_section(packet, qnamebuf, &qtype, &qclass)) {
		region_destroy(tempregion);
		return; /* drop bad packet */
	}

	dname = dname_make(tempregion, qnamebuf, 1);
	DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: got passed packet for %s, acl "
					   "%d", dname_to_string(dname,0), acl_num));

	/* find the zone */
	zone = (xfrd_zone_t*)rbtree_search(xfrd->zones, dname);
	if(!zone) {
		log_msg(LOG_INFO, "xfrd: incoming packet for unknown zone %s",
			dname_to_string(dname,0));
		region_destroy(tempregion);
		return; /* drop packet for unknown zone */
	}
	region_destroy(tempregion);

	/* handle */
	if(OPCODE(packet) == OPCODE_NOTIFY) {
		xfrd_soa_t soa;
		int have_soa = 0;
		int next;
		/* get serial from a SOA */
		if(ANCOUNT(packet) == 1 && packet_skip_dname(packet) &&
			xfrd_parse_soa_info(packet, &soa)) {
				have_soa = 1;
		}
		if(xfrd_handle_incoming_notify(zone, have_soa?&soa:NULL)) {
			if(zone->zone_handler.fd == -1
				&& zone->tcp_conn == -1 &&
				!zone->tcp_waiting && !zone->udp_waiting) {
					xfrd_set_refresh_now(zone);
			}
		}
		next = find_same_master_notify(zone, acl_num);
		if(next != -1) {
			zone->next_master = next;
			DEBUG(DEBUG_XFRD,1, (LOG_INFO,
				"xfrd: notify set next master to query %d",
				next));
		}
	}
	else {
		/* TODO handle incoming IXFR udp reply via port 53 */
	}
}
/*-------------------------------------------------------------------------*\
* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF 
* are not returned by the function and are discarded from the buffer
\*-------------------------------------------------------------------------*/
static int recvline(p_buffer buf, luaL_Buffer *b) {
    int err = IO_DONE;
    while (err == IO_DONE) {
        size_t count, pos; const char *data;
        err = buffer_get(buf, &data, &count);
        pos = 0;
        while (pos < count && data[pos] != '\n') {
            /* we ignore all \r's */
            if (data[pos] != '\r') luaL_addchar(b, data[pos]);
            pos++;
        }
        if (pos < count) { /* found '\n' */
            buffer_skip(buf, pos+1); /* skip '\n' too */
            break; /* we are done */
        } else /* reached the end of the buffer */
            buffer_skip(buf, pos);
    }
    return err;
}
Example #8
0
static char*
unmarshal_str(region_type* r, struct buffer* b)
{
	uint8_t nonnull = unmarshal_u8(b);
	if(nonnull) {
		char* result = region_strdup(r, (char*)buffer_current(b));
		size_t len = strlen((char*)buffer_current(b));
		buffer_skip(b, len+1);
		return result;
	} else return NULL;
}
Example #9
0
/*
 * Check the RRs in an IXFR/AXFR reply.
 * returns 0 on error, 1 on correct parseable packet.
 * done = 1 if the last SOA in an IXFR/AXFR has been seen.
 * soa then contains that soa info.
 * (soa contents is modified by the routine)
 */
static int
xfrd_xfr_check_rrs(xfrd_zone_t* zone, buffer_type* packet, size_t count,
	int *done, xfrd_soa_t* soa)
{
	/* first RR has already been checked */
	uint16_t type, rrlen;
	size_t i, soapos;
	for(i=0; i<count; ++i,++zone->msg_rr_count)
	{
		if(!packet_skip_dname(packet))
			return 0;
		if(!buffer_available(packet, 10))
			return 0;
		soapos = buffer_position(packet);
		type = buffer_read_u16(packet);
		(void)buffer_read_u16(packet); /* class */
		(void)buffer_read_u32(packet); /* ttl */
		rrlen = buffer_read_u16(packet);
		if(!buffer_available(packet, rrlen))
			return 0;
		if(type == TYPE_SOA) {
			/* check the SOAs */
			size_t mempos = buffer_position(packet);
			buffer_set_position(packet, soapos);
			if(!xfrd_parse_soa_info(packet, soa))
				return 0;
			if(zone->msg_rr_count == 1 &&
				ntohl(soa->serial) != zone->msg_new_serial) {
				/* 2nd RR is SOA with lower serial, this is an IXFR */
				zone->msg_is_ixfr = 1;
				if(!zone->soa_disk_acquired)
					return 0; /* got IXFR but need AXFR */
				if(ntohl(soa->serial) != ntohl(zone->soa_disk.serial))
					return 0; /* bad start serial in IXFR */
				zone->msg_old_serial = ntohl(soa->serial);
			}
			else if(ntohl(soa->serial) == zone->msg_new_serial) {
				/* saw another SOA of new serial. */
				if(zone->msg_is_ixfr == 1) {
					zone->msg_is_ixfr = 2; /* seen middle SOA in ixfr */
				} else {
					/* 2nd SOA for AXFR or 3rd newSOA for IXFR */
					*done = 1;
				}
			}
			buffer_set_position(packet, mempos);
		}
		buffer_skip(packet, rrlen);
	}
	/* packet seems to have a valid DNS RR structure */
	return 1;
}
/**
 * Add RR to query.
 *
 */
int
query_add_rr(query_type* q, ldns_rr* rr)
{
    size_t i = 0;
    size_t tc_mark = 0;
    size_t rdlength_pos = 0;
    uint16_t rdlength = 0;

    ods_log_assert(q);
    ods_log_assert(q->buffer);
    ods_log_assert(rr);

    /* set truncation mark, in case rr does not fit */
    tc_mark = buffer_position(q->buffer);
    /* owner type class ttl */
    if (!buffer_available(q->buffer, ldns_rdf_size(ldns_rr_owner(rr)))) {
        goto query_add_rr_tc;
    }
    buffer_write_rdf(q->buffer, ldns_rr_owner(rr));
    if (!buffer_available(q->buffer, sizeof(uint16_t) + sizeof(uint16_t) +
        sizeof(uint32_t) + sizeof(rdlength))) {
        goto query_add_rr_tc;
    }
    buffer_write_u16(q->buffer, (uint16_t) ldns_rr_get_type(rr));
    buffer_write_u16(q->buffer, (uint16_t) ldns_rr_get_class(rr));
    buffer_write_u32(q->buffer, (uint32_t) ldns_rr_ttl(rr));
    /* skip rdlength */
    rdlength_pos = buffer_position(q->buffer);
    buffer_skip(q->buffer, sizeof(rdlength));
    /* write rdata */
    for (i=0; i < ldns_rr_rd_count(rr); i++) {
        if (!buffer_available(q->buffer, ldns_rdf_size(ldns_rr_rdf(rr, i)))) {
            goto query_add_rr_tc;
        }
        buffer_write_rdf(q->buffer, ldns_rr_rdf(rr, i));
    }

    if (!query_overflow(q)) {
        /* write rdlength */
        rdlength = buffer_position(q->buffer) - rdlength_pos - sizeof(rdlength);
        buffer_write_u16_at(q->buffer, rdlength_pos, rdlength);
        /* position updated by buffer_write() */
        return 1;
    }

query_add_rr_tc:
    buffer_set_position(q->buffer, tc_mark);
    ods_log_assert(!query_overflow(q));
    return 0;

}
Example #11
0
int
packet_skip_dname(buffer_type *packet)
{
	while (1) {
		uint8_t label_size;
		if (!buffer_available(packet, 1))
			return 0;

		label_size = buffer_read_u8(packet);
		if (label_size == 0) {
			return 1;
		} else if ((label_size & 0xc0) != 0) {
			if (!buffer_available(packet, 1))
				return 0;
			buffer_skip(packet, 1);
			return 1;
		} else if (!buffer_available(packet, label_size)) {
			return 0;
		} else {
			buffer_skip(packet, label_size);
		}
	}
}
Example #12
0
int
packet_skip_rr(buffer_type *packet, int question_section)
{
	if (!packet_skip_dname(packet))
		return 0;

	if (question_section) {
		if (!buffer_available(packet, 4))
			return 0;
		buffer_skip(packet, 4);
	} else {
		uint16_t rdata_size;
		if (!buffer_available(packet, 10))
			return 0;
		buffer_skip(packet, 8);
		rdata_size = buffer_read_u16(packet);
		if (!buffer_available(packet, rdata_size))
			return 0;
		buffer_skip(packet, rdata_size);
	}

	return 1;
}
/*-------------------------------------------------------------------------*\
* Reads a fixed number of bytes (buffered)
\*-------------------------------------------------------------------------*/
static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b) {
    int err = IO_DONE;
    size_t total = 0;
    while (err == IO_DONE) {
        size_t count; const char *data;
        err = buffer_get(buf, &data, &count);
        count = MIN(count, wanted - total);
        luaL_addlstring(b, data, count);
        buffer_skip(buf, count);
        total += count;
        if (total >= wanted) break;
    }
    return err;
}
Example #14
0
File: dns.c Project: lc7cl/www
int skip_record(buffer_type *buffer)
{
    char* p;
    u_int16_t rdlength;

    p = buffer_current(buffer);
    while (*p != '\0') {
        if (buffer_available(buffer, *p + 1))
            buffer_skip(buffer, *p + 1);
        else
            return -1;
        p = buffer_current(buffer);
    }
    if (*p != '\0')
        return -1;
    if (!buffer_available(buffer, 11))
        return -1;
    buffer_skip(buffer, 1);
    buffer_skip(buffer, 8);
    rdlength = buffer_read_u16(buffer);
    if (buffer_available(buffer, rdlength))
        return 0;
    return -1;
}
/*-------------------------------------------------------------------------*\
* Reads everything until the connection is closed (buffered)
\*-------------------------------------------------------------------------*/
static int recvall(p_buffer buf, luaL_Buffer *b) {
    int err = IO_DONE;
    size_t total = 0;
    while (err == IO_DONE) {
        const char *data; size_t count;
        err = buffer_get(buf, &data, &count);
        total += count;
        luaL_addlstring(b, data, count);
        buffer_skip(buf, count);
    }
    if (err == IO_CLOSED) {
        if (total > 0) return IO_DONE;
        else return IO_CLOSED;
    } else return err;
}
Example #16
0
static int
rdata_base64_to_string(buffer_type *output, rdata_atom_type rdata,
	rr_type* ATTR_UNUSED(rr))
{
	int length;
	size_t size = rdata_atom_size(rdata);
	if(size == 0)
		return 1;
	buffer_reserve(output, size * 2 + 1);
	length = __b64_ntop(rdata_atom_data(rdata), size,
			  (char *) buffer_current(output), size * 2);
	if (length > 0) {
		buffer_skip(output, length);
	}
	return length != -1;
}
Example #17
0
static int
rdata_nxt_to_string(buffer_type *output, rdata_atom_type rdata,
	rr_type* ATTR_UNUSED(rr))
{
	size_t i;
	uint8_t *bitmap = rdata_atom_data(rdata);
	size_t bitmap_size = rdata_atom_size(rdata);

	for (i = 0; i < bitmap_size * 8; ++i) {
		if (get_bit(bitmap, i)) {
			buffer_printf(output, "%s ", rrtype_to_string(i));
		}
	}

	buffer_skip(output, -1);

	return 1;
}
Example #18
0
static int
rdata_base64_to_string(buffer_type *output, rdata_atom_type rdata,
	rr_type* ATTR_UNUSED(rr))
{
	int length;
	size_t size = rdata_atom_size(rdata);
	if(size == 0) {
		/* single zero represents empty buffer */
		buffer_write(output, "0", 1);
		return 1;
	}
	buffer_reserve(output, size * 2 + 1);
	length = b64_ntop(rdata_atom_data(rdata), size,
			  (char *) buffer_current(output), size * 2);
	if (length > 0) {
		buffer_skip(output, length);
	}
	return length != -1;
}
Example #19
0
static int
rdata_base32_to_string(buffer_type *output, rdata_atom_type rdata,
	rr_type* ATTR_UNUSED(rr))
{
	int length;
	size_t size = rdata_atom_size(rdata);
	if(size == 0) {
		buffer_write(output, "-", 1);
		return 1;
	}
	size -= 1; /* remove length byte from count */
	buffer_reserve(output, size * 2 + 1);
	length = b32_ntop(rdata_atom_data(rdata)+1, size,
			  (char *) buffer_current(output), size * 2);
	if (length > 0) {
		buffer_skip(output, length);
	}
	return length != -1;
}
Example #20
0
void
xfrd_setup_packet(buffer_type* packet,
	uint16_t type, uint16_t klass, const dname_type* dname)
{
	/* Set up the header */
	buffer_clear(packet);
	ID_SET(packet, qid_generate());
	FLAGS_SET(packet, 0);
	OPCODE_SET(packet, OPCODE_QUERY);
	QDCOUNT_SET(packet, 1);
	ANCOUNT_SET(packet, 0);
	NSCOUNT_SET(packet, 0);
	ARCOUNT_SET(packet, 0);
	buffer_skip(packet, QHEADERSZ);

	/* The question record. */
	buffer_write(packet, dname_name(dname), dname->name_size);
	buffer_write_u16(packet, type);
	buffer_write_u16(packet, klass);
}
Example #21
0
static int
rdata_nsec_to_string(buffer_type *output, rdata_atom_type rdata,
	rr_type* ATTR_UNUSED(rr))
{
	size_t saved_position = buffer_position(output);
	buffer_type packet;
	int insert_space = 0;

	buffer_create_from(
		&packet, rdata_atom_data(rdata), rdata_atom_size(rdata));

	while (buffer_available(&packet, 2)) {
		uint8_t window = buffer_read_u8(&packet);
		uint8_t bitmap_size = buffer_read_u8(&packet);
		uint8_t *bitmap = buffer_current(&packet);
		int i;

		if (!buffer_available(&packet, bitmap_size)) {
			buffer_set_position(output, saved_position);
			return 0;
		}

		for (i = 0; i < bitmap_size * 8; ++i) {
			if (get_bit(bitmap, i)) {
				buffer_printf(output,
					      "%s%s",
					      insert_space ? " " : "",
					      rrtype_to_string(
						      window * 256 + i));
				insert_space = 1;
			}
		}
		buffer_skip(&packet, bitmap_size);
	}

	return 1;
}
Example #22
0
static int
rdata_services_to_string(buffer_type *output, rdata_atom_type rdata,
	rr_type* ATTR_UNUSED(rr))
{
	int result = 0;
	buffer_type packet;

	buffer_create_from(
		&packet, rdata_atom_data(rdata), rdata_atom_size(rdata));

	if (buffer_available(&packet, 1)) {
		uint8_t protocol_number = buffer_read_u8(&packet);
		ssize_t bitmap_size = buffer_remaining(&packet);
		uint8_t *bitmap = buffer_current(&packet);
		struct protoent *proto = getprotobynumber(protocol_number);

		if (proto) {
			int i;

			buffer_printf(output, "%s", proto->p_name);

			for (i = 0; i < bitmap_size * 8; ++i) {
				if (get_bit(bitmap, i)) {
					struct servent *service = getservbyport((int)htons(i), proto->p_name);
					if (service) {
						buffer_printf(output, " %s", service->s_name);
					} else {
						buffer_printf(output, " %d", i);
					}
				}
			}
			buffer_skip(&packet, bitmap_size);
			result = 1;
		}
	}
	return result;
}
Example #23
0
/* parse the received packet. returns xfrd packet result code. */
static enum xfrd_packet_result
xfrd_parse_received_xfr_packet(xfrd_zone_t* zone, buffer_type* packet,
	xfrd_soa_t* soa)
{
	size_t rr_count;
	size_t qdcount = QDCOUNT(packet);
	size_t ancount = ANCOUNT(packet), ancount_todo;
	int done = 0;

	/* has to be axfr / ixfr reply */
	if(!buffer_available(packet, QHEADERSZ)) {
		log_msg(LOG_INFO, "packet too small");
		return xfrd_packet_bad;
	}

	/* only check ID in first response message. Could also check that
	 * AA bit and QR bit are set, but not needed.
	 */
	DEBUG(DEBUG_XFRD,2, (LOG_INFO,
		"got query with ID %d and %d needed", ID(packet), zone->query_id));
	if(ID(packet) != zone->query_id) {
		log_msg(LOG_ERR, "xfrd: zone %s received bad query id from %s, "
				 "dropped",
			zone->apex_str, zone->master->ip_address_spec);
		return xfrd_packet_bad;
	}
	/* check RCODE in all response messages */
	if(RCODE(packet) != RCODE_OK) {
		log_msg(LOG_ERR, "xfrd: zone %s received error code %s from "
				 "%s",
			zone->apex_str, rcode2str(RCODE(packet)),
			zone->master->ip_address_spec);
		if (RCODE(packet) == RCODE_IMPL ||
			RCODE(packet) == RCODE_FORMAT) {
			return xfrd_packet_notimpl;
		}
		return xfrd_packet_bad;
	}
	/* check TSIG */
	if(zone->master->key_options) {
		if(!xfrd_xfr_process_tsig(zone, packet)) {
			DEBUG(DEBUG_XFRD,1, (LOG_ERR, "dropping xfr reply due "
				"to bad TSIG"));
			return xfrd_packet_bad;
		}
	}
	buffer_skip(packet, QHEADERSZ);

	/* skip question section */
	for(rr_count = 0; rr_count < qdcount; ++rr_count) {
		if (!packet_skip_rr(packet, 1)) {
			log_msg(LOG_ERR, "xfrd: zone %s, from %s: bad RR in "
					 		 "question section",
				zone->apex_str, zone->master->ip_address_spec);
			return xfrd_packet_bad;
		}
	}
	if(zone->msg_rr_count == 0 && ancount == 0) {
		if(zone->tcp_conn == -1 && TC(packet)) {
			DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: TC flagged"));
			return xfrd_packet_tcp;
		}
		DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: too short xfr packet: no "
					       			   "answer"));
		return xfrd_packet_bad;
	}
	ancount_todo = ancount;

	if(zone->msg_rr_count == 0) {
		/* parse the first RR, see if it is a SOA */
		if(!packet_skip_dname(packet) ||
			!xfrd_parse_soa_info(packet, soa))
		{
			DEBUG(DEBUG_XFRD,1, (LOG_ERR, "xfrd: zone %s, from %s: "
						      "no SOA begins answer"
						      " section",
				zone->apex_str, zone->master->ip_address_spec));
			return xfrd_packet_bad;
		}
		if(zone->soa_disk_acquired != 0 &&
			zone->state != xfrd_zone_expired /* if expired - accept anything */ &&
			compare_serial(ntohl(soa->serial), ntohl(zone->soa_disk.serial)) < 0) {
			DEBUG(DEBUG_XFRD,1, (LOG_INFO,
				"xfrd: zone %s ignoring old serial from %s",
				zone->apex_str, zone->master->ip_address_spec));
			VERBOSITY(1, (LOG_INFO,
				"xfrd: zone %s ignoring old serial from %s",
				zone->apex_str, zone->master->ip_address_spec));
			return xfrd_packet_bad;
		}
		if(zone->soa_disk_acquired != 0 && zone->soa_disk.serial == soa->serial) {
			DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: zone %s got "
						       "update indicating "
						       "current serial",
				zone->apex_str));
			/* (even if notified) the lease on the current soa is renewed */
			zone->soa_disk_acquired = xfrd_time();
			if(zone->soa_nsd.serial == soa->serial)
				zone->soa_nsd_acquired = xfrd_time();
			xfrd_set_zone_state(zone, xfrd_zone_ok);
 			DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: zone %s is ok",
				zone->apex_str));
			if(zone->soa_notified_acquired == 0) {
				/* not notified or anything, so stop asking around */
				zone->round_num = -1; /* next try start a new round */
				xfrd_set_timer_refresh(zone);
				return xfrd_packet_newlease;
			}
			/* try next master */
			return xfrd_packet_bad;
		}
		DEBUG(DEBUG_XFRD,1, (LOG_INFO, "IXFR reply has ok serial (have \
%u, reply %u).", ntohl(zone->soa_disk.serial), ntohl(soa->serial)));
		/* serial is newer than soa_disk */
		if(ancount == 1) {
			/* single record means it is like a notify */
			(void)xfrd_handle_incoming_notify(zone, soa);
		}
		else if(zone->soa_notified_acquired && zone->soa_notified.serial &&
			compare_serial(ntohl(zone->soa_notified.serial), ntohl(soa->serial)) < 0) {
			/* this AXFR/IXFR notifies me that an even newer serial exists */
			zone->soa_notified.serial = soa->serial;
		}
		zone->msg_new_serial = ntohl(soa->serial);
		zone->msg_rr_count = 1;
		zone->msg_is_ixfr = 0;
		if(zone->soa_disk_acquired)
			zone->msg_old_serial = ntohl(zone->soa_disk.serial);
		else zone->msg_old_serial = 0;
		ancount_todo = ancount - 1;
	}

	if(zone->tcp_conn == -1 && TC(packet)) {
		DEBUG(DEBUG_XFRD,1, (LOG_INFO,
			"xfrd: zone %s received TC from %s. retry tcp.",
			zone->apex_str, zone->master->ip_address_spec));
		return xfrd_packet_tcp;
	}

	if(zone->tcp_conn == -1 && ancount < 2) {
		/* too short to be a real ixfr/axfr data transfer: need at */
		/* least two RRs in the answer section. */
		/* The serial is newer, so try tcp to this master. */
		DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: udp reply is short. Try "
					       			   "tcp anyway."));
		return xfrd_packet_tcp;
	}

	if(!xfrd_xfr_check_rrs(zone, packet, ancount_todo, &done, soa))
	{
		DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: zone %s sent bad xfr "
					       			   "reply.", zone->apex_str));
		return xfrd_packet_bad;
	}
	if(zone->tcp_conn == -1 && done == 0) {
		DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: udp reply incomplete"));
		return xfrd_packet_bad;
	}
	if(done == 0)
		return xfrd_packet_more;
	if(zone->master->key_options) {
		if(zone->tsig.updates_since_last_prepare != 0) {
			log_msg(LOG_INFO, "xfrd: last packet of reply has no "
					 		  "TSIG");
			return xfrd_packet_bad;
		}
	}
	return xfrd_packet_transfer;
}
Example #24
0
int
dname_make_wire_from_packet(uint8_t *buf, buffer_type *packet,
                       int allow_pointers)
{
	int done = 0;
	uint8_t visited[(MAX_PACKET_SIZE+7)/8];
	size_t dname_length = 0;
	const uint8_t *label;
	ssize_t mark = -1;

	memset(visited, 0, (buffer_limit(packet)+7)/8);

	while (!done) {
		if (!buffer_available(packet, 1)) {
/* 			error("dname out of bounds"); */
			return 0;
		}

		if (get_bit(visited, buffer_position(packet))) {
/* 			error("dname loops"); */
			return 0;
		}
		set_bit(visited, buffer_position(packet));

		label = buffer_current(packet);
		if (label_is_pointer(label)) {
			size_t pointer;
			if (!allow_pointers) {
				return 0;
			}
			if (!buffer_available(packet, 2)) {
/* 				error("dname pointer out of bounds"); */
				return 0;
			}
			pointer = label_pointer_location(label);
			if (pointer >= buffer_limit(packet)) {
/* 				error("dname pointer points outside packet"); */
				return 0;
			}
			buffer_skip(packet, 2);
			if (mark == -1) {
				mark = buffer_position(packet);
			}
			buffer_set_position(packet, pointer);
		} else if (label_is_normal(label)) {
			size_t length = label_length(label) + 1;
			done = label_is_root(label);
			if (!buffer_available(packet, length)) {
/* 				error("dname label out of bounds"); */
				return 0;
			}
			if (dname_length + length >= MAXDOMAINLEN+1) {
/* 				error("dname too large"); */
				return 0;
			}
			buffer_read(packet, buf + dname_length, length);
			dname_length += length;
		} else {
/* 			error("bad label type"); */
			return 0;
		}
	}

	if (mark != -1) {
		buffer_set_position(packet, mark);
	}

	return dname_length;
}
Example #25
0
static void
handle_tcp_writing(netio_type *netio,
		   netio_handler_type *handler,
		   netio_event_types_type event_types)
{
	struct tcp_handler_data *data
		= (struct tcp_handler_data *) handler->user_data;
	ssize_t sent;
	struct query *q = data->query;

	if (event_types & NETIO_EVENT_TIMEOUT) {
		/* Connection timed out.  */
		cleanup_tcp_handler(netio, handler);
		return;
	}

	assert(event_types & NETIO_EVENT_WRITE);

	if (data->bytes_transmitted < sizeof(q->tcplen)) {
		/* Writing the response packet length.  */
		uint16_t n_tcplen = htons(q->tcplen);
		sent = write(handler->fd,
			     (const char *) &n_tcplen + data->bytes_transmitted,
			     sizeof(n_tcplen) - data->bytes_transmitted);
		if (sent == -1) {
			if (errno == EAGAIN || errno == EINTR) {
				/*
				 * Write would block, wait until
				 * socket becomes writable again.
				 */
				return;
			} else {
#ifdef ECONNRESET
				if(verbosity >= 2 || errno != ECONNRESET)
#endif /* ECONNRESET */
#ifdef EPIPE
					if(verbosity >= 2 || errno != EPIPE)
#endif /* EPIPE 'broken pipe' */
				log_msg(LOG_ERR, "failed writing to tcp: %s", strerror(errno));
				cleanup_tcp_handler(netio, handler);
				return;
			}
		}

		data->bytes_transmitted += sent;
		if (data->bytes_transmitted < sizeof(q->tcplen)) {
			/*
			 * Writing not complete, wait until socket
			 * becomes writable again.
			 */
			return;
		}

		assert(data->bytes_transmitted == sizeof(q->tcplen));
	}

	assert(data->bytes_transmitted < q->tcplen + sizeof(q->tcplen));

	sent = write(handler->fd,
		     buffer_current(q->packet),
		     buffer_remaining(q->packet));
	if (sent == -1) {
		if (errno == EAGAIN || errno == EINTR) {
			/*
			 * Write would block, wait until
			 * socket becomes writable again.
			 */
			return;
		} else {
#ifdef ECONNRESET
			if(verbosity >= 2 || errno != ECONNRESET)
#endif /* ECONNRESET */
#ifdef EPIPE
					if(verbosity >= 2 || errno != EPIPE)
#endif /* EPIPE 'broken pipe' */
			log_msg(LOG_ERR, "failed writing to tcp: %s", strerror(errno));
			cleanup_tcp_handler(netio, handler);
			return;
		}
	}

	buffer_skip(q->packet, sent);
	data->bytes_transmitted += sent;
	if (data->bytes_transmitted < q->tcplen + sizeof(q->tcplen)) {
		/*
		 * Still more data to write when socket becomes
		 * writable again.
		 */
		return;
	}

	assert(data->bytes_transmitted == q->tcplen + sizeof(q->tcplen));

	if (data->query_state == QUERY_IN_AXFR) {
		/* Continue processing AXFR and writing back results.  */
		buffer_clear(q->packet);
		data->query_state = query_axfr(data->nsd, q);
		if (data->query_state != QUERY_PROCESSED) {
			query_add_optional(data->query, data->nsd);

			/* Reset data. */
			buffer_flip(q->packet);
			q->tcplen = buffer_remaining(q->packet);
			data->bytes_transmitted = 0;
			/* Reset timeout.  */
			handler->timeout->tv_sec = data->nsd->tcp_timeout;
			handler->timeout->tv_nsec = 0;
			timespec_add(handler->timeout, netio_current_time(netio));

			/*
			 * Write data if/when the socket is writable
			 * again.
			 */
			return;
		}
	}

	/*
	 * Done sending, wait for the next request to arrive on the
	 * TCP socket by installing the TCP read handler.
	 */
	if (data->nsd->tcp_query_count > 0 &&
		data->query_count >= data->nsd->tcp_query_count) {

		(void) shutdown(handler->fd, SHUT_WR);
	}

	data->bytes_transmitted = 0;

	handler->timeout->tv_sec = data->nsd->tcp_timeout;
	handler->timeout->tv_nsec = 0;
	timespec_add(handler->timeout, netio_current_time(netio));

	handler->event_types = NETIO_EVENT_READ | NETIO_EVENT_TIMEOUT;
	handler->event_handler = handle_tcp_reading;
}
Example #26
0
static void
handle_udp(netio_type *ATTR_UNUSED(netio),
	   netio_handler_type *handler,
	   netio_event_types_type event_types)
{
	struct udp_handler_data *data
		= (struct udp_handler_data *) handler->user_data;
	int received, sent;
	struct query *q = data->query;

	if (!(event_types & NETIO_EVENT_READ)) {
		return;
	}

	/* Account... */
#ifdef BIND8_STATS
	if (data->socket->addr->ai_family == AF_INET) {
		STATUP(data->nsd, qudp);
	} else if (data->socket->addr->ai_family == AF_INET6) {
		STATUP(data->nsd, qudp6);
	}
#endif

	/* Initialize the query... */
	query_reset(q, UDP_MAX_MESSAGE_LEN, 0);

	received = recvfrom(handler->fd,
			    buffer_begin(q->packet),
			    buffer_remaining(q->packet),
			    0,
			    (struct sockaddr *)&q->addr,
			    &q->addrlen);
	if (received == -1) {
		if (errno != EAGAIN && errno != EINTR) {
			log_msg(LOG_ERR, "recvfrom failed: %s", strerror(errno));
			STATUP(data->nsd, rxerr);
			/* No zone statup */
		}
	} else {
		buffer_skip(q->packet, received);
		buffer_flip(q->packet);

		/* Process and answer the query... */
		if (server_process_query(data->nsd, q) != QUERY_DISCARDED) {
#ifdef BIND8_STATS
			if (RCODE(q->packet) == RCODE_OK && !AA(q->packet)) {
				STATUP(data->nsd, nona);
				ZTATUP(q->zone, nona);
			}

# ifdef USE_ZONE_STATS
			if (data->socket->addr->ai_family == AF_INET) {
				ZTATUP(q->zone, qudp);
			} else if (data->socket->addr->ai_family == AF_INET6) {
				ZTATUP(q->zone, qudp6);
			}
# endif
#endif

			/* Add EDNS0 and TSIG info if necessary.  */
			query_add_optional(q, data->nsd);

			buffer_flip(q->packet);

			sent = sendto(handler->fd,
				      buffer_begin(q->packet),
				      buffer_remaining(q->packet),
				      0,
				      (struct sockaddr *) &q->addr,
				      q->addrlen);
			if (sent == -1) {
				log_msg(LOG_ERR, "sendto failed: %s", strerror(errno));
				STATUP(data->nsd, txerr);
				ZTATUP(q->zone, txerr);
			} else if ((size_t) sent != buffer_remaining(q->packet)) {
				log_msg(LOG_ERR, "sent %d in place of %d bytes", sent, (int) buffer_remaining(q->packet));
#ifdef BIND8_STATS
			} else {
				/* Account the rcode & TC... */
				STATUP2(data->nsd, rcode, RCODE(q->packet));
				ZTATUP2(q->zone, rcode, RCODE(q->packet));
				if (TC(q->packet)) {
					STATUP(data->nsd, truncated);
					ZTATUP(q->zone, truncated);
				}
#endif /* BIND8_STATS */
			}
#ifdef BIND8_STATS
		} else {
			STATUP(data->nsd, dropped);
# ifdef USE_ZONE_STATS
			if (q->zone) {
				ZTATUP(q->zone, dropped);
			}
# endif
#endif
		}
	}
}
Example #27
0
static void
handle_tcp_reading(netio_type *netio,
		   netio_handler_type *handler,
		   netio_event_types_type event_types)
{
	struct tcp_handler_data *data
		= (struct tcp_handler_data *) handler->user_data;
	ssize_t received;

	if (event_types & NETIO_EVENT_TIMEOUT) {
		/* Connection timed out.  */
		cleanup_tcp_handler(netio, handler);
		return;
	}

	if (data->nsd->tcp_query_count > 0 &&
		data->query_count >= data->nsd->tcp_query_count) {
		/* No more queries allowed on this tcp connection.  */
		cleanup_tcp_handler(netio, handler);
		return;
	}

	assert(event_types & NETIO_EVENT_READ);

	if (data->bytes_transmitted == 0) {
		query_reset(data->query, TCP_MAX_MESSAGE_LEN, 1);
	}

	/*
	 * Check if we received the leading packet length bytes yet.
	 */
	if (data->bytes_transmitted < sizeof(uint16_t)) {
		received = read(handler->fd,
				(char *) &data->query->tcplen
				+ data->bytes_transmitted,
				sizeof(uint16_t) - data->bytes_transmitted);
		if (received == -1) {
			if (errno == EAGAIN || errno == EINTR) {
				/*
				 * Read would block, wait until more
				 * data is available.
				 */
				return;
			} else {
#ifdef ECONNRESET
				if (verbosity >= 2 || errno != ECONNRESET)
#endif /* ECONNRESET */
				log_msg(LOG_ERR, "failed reading from tcp: %s", strerror(errno));
				cleanup_tcp_handler(netio, handler);
				return;
			}
		} else if (received == 0) {
			/* EOF */
			cleanup_tcp_handler(netio, handler);
			return;
		}

		data->bytes_transmitted += received;
		if (data->bytes_transmitted < sizeof(uint16_t)) {
			/*
			 * Not done with the tcplen yet, wait for more
			 * data to become available.
			 */
			return;
		}

		assert(data->bytes_transmitted == sizeof(uint16_t));

		data->query->tcplen = ntohs(data->query->tcplen);

		/*
		 * Minimum query size is:
		 *
		 *     Size of the header (12)
		 *   + Root domain name   (1)
		 *   + Query class        (2)
		 *   + Query type         (2)
		 */
		if (data->query->tcplen < QHEADERSZ + 1 + sizeof(uint16_t) + sizeof(uint16_t)) {
			VERBOSITY(2, (LOG_WARNING, "packet too small, dropping tcp connection"));
			cleanup_tcp_handler(netio, handler);
			return;
		}

		if (data->query->tcplen > data->query->maxlen) {
			VERBOSITY(2, (LOG_WARNING, "insufficient tcp buffer, dropping connection"));
			cleanup_tcp_handler(netio, handler);
			return;
		}

		buffer_set_limit(data->query->packet, data->query->tcplen);
	}

	assert(buffer_remaining(data->query->packet) > 0);

	/* Read the (remaining) query data.  */
	received = read(handler->fd,
			buffer_current(data->query->packet),
			buffer_remaining(data->query->packet));
	if (received == -1) {
		if (errno == EAGAIN || errno == EINTR) {
			/*
			 * Read would block, wait until more data is
			 * available.
			 */
			return;
		} else {
#ifdef ECONNRESET
			if (verbosity >= 2 || errno != ECONNRESET)
#endif /* ECONNRESET */
			log_msg(LOG_ERR, "failed reading from tcp: %s", strerror(errno));
			cleanup_tcp_handler(netio, handler);
			return;
		}
	} else if (received == 0) {
		/* EOF */
		cleanup_tcp_handler(netio, handler);
		return;
	}

	data->bytes_transmitted += received;
	buffer_skip(data->query->packet, received);
	if (buffer_remaining(data->query->packet) > 0) {
		/*
		 * Message not yet complete, wait for more data to
		 * become available.
		 */
		return;
	}

	assert(buffer_position(data->query->packet) == data->query->tcplen);

	/* Account... */
#ifdef BIND8_STATS
# ifndef INET6
	STATUP(data->nsd, ctcp);
# else
	if (data->query->addr.ss_family == AF_INET) {
		STATUP(data->nsd, ctcp);
	} else if (data->query->addr.ss_family == AF_INET6) {
		STATUP(data->nsd, ctcp6);
	}
# endif
#endif /* BIND8_STATS */

	/* We have a complete query, process it.  */

	/* tcp-query-count: handle query counter ++ */
	data->query_count++;

	buffer_flip(data->query->packet);
	data->query_state = server_process_query(data->nsd, data->query);
	if (data->query_state == QUERY_DISCARDED) {
		/* Drop the packet and the entire connection... */
		STATUP(data->nsd, dropped);
#if defined(BIND8_STATS) && defined(USE_ZONE_STATS)
		if (data->query->zone) {
			ZTATUP(data->query->zone, dropped);
		}
#endif
		cleanup_tcp_handler(netio, handler);
		return;
	}

#ifdef BIND8_STATS
	if (RCODE(data->query->packet) == RCODE_OK
	    && !AA(data->query->packet))
	{
		STATUP(data->nsd, nona);
		ZTATUP(data->query->zone, nona);
	}

# ifdef USE_ZONE_STATS
#  ifndef INET6
	ZTATUP(data->query->zone, ctcp);
#  else
	if (data->query->addr.ss_family == AF_INET) {
		ZTATUP(data->query->zone, ctcp);
	} else if (data->query->addr.ss_family == AF_INET6) {
		ZTATUP(data->query->zone, ctcp6);
	}
#  endif
# endif /* USE_ZONE_STATS */

#endif /* BIND8_STATS */

	query_add_optional(data->query, data->nsd);

	/* Switch to the tcp write handler.  */
	buffer_flip(data->query->packet);
	data->query->tcplen = buffer_remaining(data->query->packet);
	data->bytes_transmitted = 0;

	handler->timeout->tv_sec = data->nsd->tcp_timeout;
	handler->timeout->tv_nsec = 0L;
	timespec_add(handler->timeout, netio_current_time(netio));

	handler->event_types = NETIO_EVENT_WRITE | NETIO_EVENT_TIMEOUT;
	handler->event_handler = handle_tcp_writing;
}
Example #28
0
int
parse_sflow4_sample(const char **p)
{
	u_int32_t sample_type, packetdata_type;
	u_int32_t seqno, src_id, srate, total, drops, input, output;
	u_int32_t protocol, framelen, snaplen;
	u_int32_t interval, counters_version;
	u_int32_t nextended, extended_type, addr_type;
	u_int32_t aspath_len, asn_len, community_len, str_len;
	int i;

	sample_type	= buffer_read_4(p);
	if (verbose > 1)
		fprintf(stderr, "sflow4: sample_type:%u\n", sample_type);
	switch (sample_type) {
	case 1: /* flow sample */
		seqno 	= buffer_read_4(p);
		src_id 	= buffer_read_4(p);
		srate 	= buffer_read_4(p);
		total 	= buffer_read_4(p);
		drops 	= buffer_read_4(p);
		input 	= buffer_read_4(p);
		output 	= buffer_read_4(p);

		sampling_rate = srate;
		
		packetdata_type	= buffer_read_4(p);
		if (verbose > 1)
			fprintf(stderr, "flow_sample: packetdata_type:%u, srate:%u\n",
				packetdata_type, srate);

		switch (packetdata_type) {
		case 1: /* header */
			protocol = buffer_read_4(p);
			framelen = buffer_read_4(p);
			snaplen  = buffer_read_4(p);

			if (verbose > 0)
				fprintf(stderr, "header: framelen:%u, snaplen:%u, proto:%u\n",
			    		framelen, snaplen, protocol);

			/* clear aguri_flow to be filled in parsers */
			memset(&aguri_flow, 0, sizeof(aguri_flow));

			switch (protocol) {
			case 1: /* ethernet */
				snapend = *p + snaplen;
				etherhdr_parse(*p, snaplen);
				break;
			default:
				if (verbose > 0)
					fprintf(stderr, "unknown proto:%u\n",
			    			protocol);
				break;
			}

			buffer_skip(p, snaplen);

			if (aguri_flow.agflow_fs.fs_ipver != 0) {
				/* flow info was filled by the parser:
				 * for frame_length, we remove 4 bytes of FCS
				 * to be consistent with pcap
				 */
				aguri_flow.agflow_packets = htonl(1 * srate);
				aguri_flow.agflow_bytes = htonl((framelen - 4) * srate);
				aguri_flow.agflow_first = aguri_flow.agflow_last = htonl((u_int32_t)timestamp);

				if (debug == 0) {
					if (fwrite(&aguri_flow, sizeof(aguri_flow), 1, stdout) != 1)
						err(1, "fwrite failed!");
				} else
					print_flow(&aguri_flow);
			}
			
			break;
		case 2: /* IPv4 */
			buffer_skip(p, 8*4);
			if (verbose > 0)
				fprintf(stderr, "packetdata IPv4 not supported\n");
			break;
		case 3: /* IPv6 */
			buffer_skip(p, 14*4);
			if (verbose > 0)
				fprintf(stderr, "packetdata IPv6 not supported\n");
			break;
		default:
			if (verbose > 0)
				fprintf(stderr, "unknown packetdata_type:%u\n", packetdata_type);
			return (-1);
		}

		/* extended data */
		nextended = buffer_read_4(p);
		if (verbose > 0)
			fprintf(stderr, "extended data:%u\n", nextended);
		for (i = 0; i < nextended; i++) {
			extended_type = buffer_read_4(p);
			switch (extended_type) {
			case 1: /* switch */
				buffer_skip(p, 4*4);
				break;
			case 2: /* router */
				addr_type = buffer_read_4(p);
				switch (addr_type) {
				case 1: /* IPv4 */
					buffer_skip(p, 4);
					break;
				case 2: /* IPv6 */
					buffer_skip(p, 16);
					break;
				default:
					return (-1);
				}
				buffer_skip(p, 2*4);
				break;
			case 3: /* gateway */
				buffer_skip(p, 3*4);
				aspath_len = buffer_read_4(p);
				while (aspath_len-- > 0) {
					buffer_skip(p, 4);
					if (sflow_version >= 4) {
						asn_len = buffer_read_4(p);
						while (asn_len-- > 0)
							buffer_skip(p, 4);
					}
				}
				community_len = buffer_read_4(p);
				buffer_skip(p, community_len * 4);
				buffer_skip(p, 4);
				break;
			case 4: /* user */
				str_len = buffer_read_4(p);
				buffer_skip(p, str_len);
				str_len = buffer_read_4(p);
				buffer_skip(p, str_len);
				break;
			case 5: /* url */
				buffer_skip(p, 4);
				str_len = buffer_read_4(p);
				buffer_skip(p, str_len);
				break;
			default:
				return (-1);
			}
		}
		break;
	case 2: /* counter sample */
		seqno 	= buffer_read_4(p);
		src_id 	= buffer_read_4(p);
		interval = buffer_read_4(p);
		counters_version = buffer_read_4(p);
		if (verbose > 0)
			fprintf(stderr, "counter sample: type:%u\n", counters_version);
		switch (counters_version) {
		case 1: /* generic */
			buffer_skip(p, 22*4);
			break;
		case 2: /* ethernet */
			buffer_skip(p, 22*4);
			buffer_skip(p, 13*4);
			break;
		case 3: /* tokenring */
			buffer_skip(p, 22*4);
			buffer_skip(p, 18*4);
			break;
		case 4: /* fddi */
			buffer_skip(p, 22*4);
			break;
		case 5: /* 100basevg */
			buffer_skip(p, 22*4);
			buffer_skip(p, 20*4);
			break;
		case 6: /* wan */
			buffer_skip(p, 22*4);
			break;
		case 7: /* vlan */
			buffer_skip(p, 7*4);
			break;
		default:
			if (verbose > 0)
				fprintf(stderr, "counter sample %d not supported\n",
				    counters_version);
			return (-1);
		}
		break;
	default:
		if (verbose > 0)
			fprintf(stderr, "unknown sample_type %u\n", sample_type);
		return (-1);
	}
	
	return (0);
}
Example #29
0
int
parse_sflow5(const char **p)
{
	u_int32_t format, len;
	u_int32_t seqno, src_id, srate, total, drops, input, output, nrecords;
	u_int32_t record_type, record_len;
	u_int32_t protocol, framelen, stripped;
	int snaplen, i;

	format	= buffer_read_4(p) & 0xfff;
	len	= buffer_read_4(p);
	if (verbose > 1)
		fprintf(stderr, "sflow5: format:%u, len:%u\n",
				format, len);
	switch (format) {
	case 1: /* flow sample */
		seqno 	= buffer_read_4(p);
		src_id 	= buffer_read_4(p);
		srate 	= buffer_read_4(p);
		total 	= buffer_read_4(p);
		drops 	= buffer_read_4(p);
		input 	= buffer_read_4(p);
		output 	= buffer_read_4(p);
		nrecords	= buffer_read_4(p);

		sampling_rate = srate;

		if (verbose > 1)
			fprintf(stderr, "flow sample: srate:%u, nrecords:%u\n",
				srate, nrecords);

		for (i = 0; i < nrecords; i++) {
			record_type	= buffer_read_4(p);
			record_len	= buffer_read_4(p);

			/* clear aguri_flow to be filled in parsers */
			memset(&aguri_flow, 0, sizeof(aguri_flow));

			switch (record_type) {
			case 1: /* raw packet header */
				protocol = buffer_read_4(p);
				framelen = buffer_read_4(p);
				stripped = buffer_read_4(p);
				record_len -= 12;
				if (verbose > 1)
					fprintf(stderr, "record type: raw header: proto:%u, rlen:%u flen:%u, stripped:%u\n",
				    		protocol, record_len, framelen, stripped);
				switch (protocol) {
				case 1: /* ethernet */
					/* read the first 4 bytes for snaplen */
					snaplen = ntohl(*((u_int32_t *)*p));
					snapend = *p + 4 + snaplen;
					/* frame_length holds ethernet frame
					 * length; we remove 4 bytes of FCS to
					 * be consistent with pcap
					 */
					frame_length = framelen - 4;
					etherhdr_parse(*p + 4, snaplen);
					break;
				default:
					break;
				}
				buffer_skip(p, record_len);
				break;
			default:
				if (verbose > 1)
					fprintf(stderr, "record type:%u, len:%u\n",
				    		record_type, record_len);
				buffer_skip(p, record_len);
				break;
			} /* switch */

			if (aguri_flow.agflow_fs.fs_ipver != 0) {
				/* flow info was filled by the parser:
				 * for frame_length, we remove 4 bytes of FCS
				 * to be consistent with pcap
				 */
				aguri_flow.agflow_packets = htonl(1 * srate);
				aguri_flow.agflow_bytes = htonl((framelen - 4) * srate);
				aguri_flow.agflow_first = aguri_flow.agflow_last = htonl((u_int32_t)timestamp);

				if (debug == 0) {
					if (fwrite(&aguri_flow, sizeof(aguri_flow), 1, stdout) != 1)
						err(1, "fwrite failed!");
				} else
					print_flow(&aguri_flow);
			}

		}  /* nrecords in sample */
		break;
	case 2: /* counter sample */
		buffer_skip(p, len);
		break;
	case 3: /* expanded flow sample */
		buffer_skip(p, len);
		break;
	case 4: /* expanded counter sample */
		buffer_skip(p, len);
		break;
	default:
		buffer_skip(p, len);
		break;
	}

	return (0);
}
/**
 * NOTIFY.
 *
 */
static query_state
query_process_notify(query_type* q, ldns_rr_type qtype, void* engine)
{
    engine_type* e = (engine_type*) engine;
    dnsin_type* dnsin = NULL;
    uint16_t count = 0;
    uint16_t rrcount = 0;
    uint32_t serial = 0;
    size_t pos = 0;
    char address[128];
    if (!e || !q || !q->zone) {
        return QUERY_DISCARDED;
    }
    ods_log_assert(e->dnshandler);
    ods_log_assert(q->zone->name);
    ods_log_debug("[%s] incoming notify for zone %s", query_str,
        q->zone->name);
    if (buffer_pkt_rcode(q->buffer) != LDNS_RCODE_NOERROR ||
        buffer_pkt_qr(q->buffer) ||
        !buffer_pkt_aa(q->buffer) ||
        buffer_pkt_tc(q->buffer) ||
        buffer_pkt_rd(q->buffer) ||
        buffer_pkt_ra(q->buffer) ||
        buffer_pkt_ad(q->buffer) ||
        buffer_pkt_cd(q->buffer) ||
        buffer_pkt_qdcount(q->buffer) != 1 ||
        buffer_pkt_ancount(q->buffer) > 1 ||
        qtype != LDNS_RR_TYPE_SOA) {
        return query_formerr(q);
    }
    if (!q->zone->adinbound || q->zone->adinbound->type != ADAPTER_DNS) {
        ods_log_error("[%s] zone %s is not configured to have input dns "
            "adapter", query_str, q->zone->name);
        return query_notauth(q);
    }
    ods_log_assert(q->zone->adinbound->config);
    dnsin = (dnsin_type*) q->zone->adinbound->config;
    if (!acl_find(dnsin->allow_notify, &q->addr, q->tsig_rr)) {
        if (addr2ip(q->addr, address, sizeof(address))) {
            ods_log_info("[%s] unauthorized notify for zone %s from client %s: "
                "no acl matches", query_str, q->zone->name, address);
        } else {
            ods_log_info("[%s] unauthorized notify for zone %s from unknown "
                "client: no acl matches", query_str, q->zone->name);
        }
        return query_notauth(q);
    }
    ods_log_assert(q->zone->xfrd);
    /* skip header and question section */
    buffer_skip(q->buffer, BUFFER_PKT_HEADER_SIZE);
    count = buffer_pkt_qdcount(q->buffer);
    for (rrcount = 0; rrcount < count; rrcount++) {
        if (!buffer_skip_rr(q->buffer, 1)) {
            ods_log_error("[%s] dropped packet: zone %s received bad notify "
                "(bad question section)", query_str, q->zone->name);
            return QUERY_DISCARDED;
        }
    }
    pos = buffer_position(q->buffer);

    /* examine answer section */
    count = buffer_pkt_ancount(q->buffer);
    if (count) {
        if (!buffer_skip_dname(q->buffer) ||
            !query_parse_soa(q->buffer, &serial)) {
            ods_log_error("[%s] dropped packet: zone %s received bad notify "
                "(bad soa in answer section)", query_str, q->zone->name);
            return QUERY_DISCARDED;
        }
        lock_basic_lock(&q->zone->xfrd->serial_lock);
        q->zone->xfrd->serial_notify = serial;
        q->zone->xfrd->serial_notify_acquired = time_now();
        if (!util_serial_gt(q->zone->xfrd->serial_notify,
            q->zone->xfrd->serial_disk)) {
            ods_log_debug("[%s] ignore notify: already got zone %s serial "
                "%u on disk", query_str, q->zone->name,
                q->zone->xfrd->serial_notify);
            lock_basic_unlock(&q->zone->xfrd->serial_lock);
            goto send_notify_ok;
        }
        lock_basic_unlock(&q->zone->xfrd->serial_lock);
    } else {
        lock_basic_lock(&q->zone->xfrd->serial_lock);
        q->zone->xfrd->serial_notify = 0;
        q->zone->xfrd->serial_notify_acquired = 0;
        lock_basic_unlock(&q->zone->xfrd->serial_lock);
    }
    /* forward notify to xfrd */
    xfrd_set_timer_now(q->zone->xfrd);
    dnshandler_fwd_notify(e->dnshandler, buffer_begin(q->buffer),
        buffer_remaining(q->buffer));

send_notify_ok:
    /* send notify ok */
    buffer_pkt_set_qr(q->buffer);
    buffer_pkt_set_aa(q->buffer);
    buffer_pkt_set_ancount(q->buffer, 0);

    buffer_clear(q->buffer); /* lim = pos, pos = 0; */
    buffer_set_position(q->buffer, pos);
    buffer_set_limit(q->buffer, buffer_capacity(q->buffer));
    q->reserved_space = edns_rr_reserved_space(q->edns_rr);
    q->reserved_space += tsig_rr_reserved_space(q->tsig_rr);
    return QUERY_PROCESSED;
}