Exemplo n.º 1
0
static int xfrd_parse_soa_info(buffer_type* packet, xfrd_soa_t* soa)
{
	if(!buffer_available(packet, 10))
		return 0;
	soa->type = htons(buffer_read_u16(packet));
	soa->klass = htons(buffer_read_u16(packet));
	soa->ttl = htonl(buffer_read_u32(packet));
	if(ntohs(soa->type) != TYPE_SOA || ntohs(soa->klass) != CLASS_IN)
	{
		return 0;
	}

	if(!buffer_available(packet, buffer_read_u16(packet)) /* rdata length */ ||
		!(soa->prim_ns[0] = dname_make_wire_from_packet(soa->prim_ns+1, packet, 1)) ||
		!(soa->email[0] = dname_make_wire_from_packet(soa->email+1, packet, 1)))
	{
		return 0;
	}
	soa->rdata_count = 7; /* rdata in SOA */
	soa->serial = htonl(buffer_read_u32(packet));
	soa->refresh = htonl(buffer_read_u32(packet));
	soa->retry = htonl(buffer_read_u32(packet));
	soa->expire = htonl(buffer_read_u32(packet));
	soa->minimum = htonl(buffer_read_u32(packet));

	return 1;
}
Exemplo n.º 2
0
size_t buffer_push(struct Buffer *buf, size_t size) {
	if (buffer_available(buf) < size)
		size = buffer_available(buf);

	buf->dataLen += size;
	return size;
}
Exemplo n.º 3
0
Arquivo: dns.c Projeto: 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;
}
Exemplo n.º 4
0
unsigned int buffer_putnoflush (buffer_ref b, char const *buf, unsigned int len)
{
  if (len > buffer_available(b))
  {
    buffer_clean(b) ;
    if (len > buffer_available(b)) len = buffer_available(b) ;
  }
  byte_copy(buffer_WPEEK(b), len, buf) ;
  buffer_WSEEK(b, len) ;
  return len ;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
/**
 * 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;

}
Exemplo n.º 7
0
int port_socket_want_read(port_t *self)
{
	port_socket_data_t *data = self->data;
	if (data->is_closing || data->is_connecting)
		return 0;
	return buffer_available(data->in_buf) > 0;
}
Exemplo n.º 8
0
static void
tcp_close(iodev_t *dev, int flags) {
//  tcp_cfg_t *cfg = tcp_getcfg(dev);

    switch (iodev_getstate(dev)) {
        case IODEV_NONE:
        case IODEV_INACTIVE:
        case IODEV_CLOSED:
        //  iodev_notify(dev, "serial close '%s' already closed", cfg->portname);
            // do nothing for these states, we are already closed
            break;
        default:
            // all states other than closing, we move to closing state
            iodev_setstate(dev, IODEV_CLOSING);
        case IODEV_CLOSING:
            // check to see if we have sent all data
            if (flags & IOFLAG_FLUSH) {
                if (buffer_available(iodev_tbuf(dev)))
                    break;  // still data in buffer, retry later
            //  tcflush(dev->fd, TCOFLUSH);
            }
        case IODEV_PENDING: // never flush if only pending
            close(dev->fd);
            dev->fd = -1;
            iodev_setstate(dev, IODEV_CLOSED);
            break;
    }
}
unsigned short buffer_write( register struct buffer_t * buffer, register const char * local, const unsigned short count )
{
	//write_ptr moves by number of bytes read
	unsigned short free = buffer_free( buffer );
	unsigned short can_write = count < free ? count : free ;
	char * buf_end = buffer->buffer + buffer->size;
	if( buffer->write_ptr + can_write > buf_end )
	{
		//will overflow. move existing data to start of buffer
		unsigned short need_move = buffer_available( buffer );
		buffer->write_ptr = buffer->buffer;
		while( need_move > 0 )
		{
			*(buffer->write_ptr++)=*(buffer->read_ptr++);
			need_move --;
		}
		//read ptr is now at the start of the buffer
		buffer->read_ptr  = buffer->buffer;
	}
	unsigned short written = can_write;
	while( can_write > 0 )
	{
		*(buffer->write_ptr++) = *(local++);
		can_write--;
	}

	return written; //number of bytes written

}
Exemplo n.º 10
0
apr_status_t port_socket_do_writable(port_t *self)
{
	port_socket_data_t *data = self->data;

	if (data->is_connecting)
	{
		process_t *proc = proc_lookup(pid_serial(self->owner_in));	  // owner_in
		if (proc)
		{
			xpool_t *tmp = xpool_make(self->pool);
			term_t msg = make_tuple2(A_TCP_CONNECTED, port_id(self, tmp), tmp);
			proc_new_mail(proc, msg);
			xpool_destroy(tmp);
		}

		data->is_connecting = 0;
	}

	if (buffer_len(data->out_buf) > 0)
	{
		apr_status_t rs;
		rs = buffer_socket_send(data->out_buf, data->sock);
		if (rs != 0)
			return rs;
	}

    if (data->is_closing && buffer_len(data->out_buf) == 0)
		return APR_EOF;	//make poll close0 the socket

	if (data->space_required && buffer_available(data->out_buf) >= data->required_size)
	{
		xpool_t *tmp = xpool_make(self->pool);
		int avail = buffer_available(data->out_buf);
		term_t msg = make_tuple3(A_TCP_SPACE, port_id(self, tmp), intnum(avail), tmp);
		process_t *proc = proc_lookup(pid_serial(self->owner_out));

		//TODO: insure that only owner can send to socket

		proc_new_mail(proc, msg);
		xpool_destroy(tmp);

		data->space_required = 0;
	}

	return APR_SUCCESS;
}
Exemplo n.º 11
0
rr_type *
packet_read_rr(region_type *region, domain_table_type *owners,
	       buffer_type *packet, int question_section)
{
	const dname_type *owner;
	uint16_t rdlength;
	ssize_t rdata_count;
	rdata_atom_type *rdatas;
	rr_type *result = (rr_type *) region_alloc(region, sizeof(rr_type));

	owner = dname_make_from_packet(region, packet, 1, 1);
	if (!owner || !buffer_available(packet, 2*sizeof(uint16_t))) {
		return NULL;
	}

	result->owner = domain_table_insert(owners, owner);
	result->type = buffer_read_u16(packet);
	result->klass = buffer_read_u16(packet);

	if (question_section) {
		result->ttl = 0;
		result->rdata_count = 0;
		result->rdatas = NULL;
		return result;
	} else if (!buffer_available(packet, sizeof(uint32_t) + sizeof(uint16_t))) {
		return NULL;
	}

	result->ttl = buffer_read_u32(packet);
	rdlength = buffer_read_u16(packet);

	if (!buffer_available(packet, rdlength)) {
		return NULL;
	}

	rdata_count = rdata_wireformat_to_rdata_atoms(
		region, owners, result->type, rdlength, packet, &rdatas);
	if (rdata_count == -1) {
		return NULL;
	}
	result->rdata_count = rdata_count;
	result->rdatas = rdatas;

	return result;
}
Exemplo n.º 12
0
static int
rdata_apl_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, 4)) {
        uint16_t address_family = buffer_read_u16(&packet);
        uint8_t prefix = buffer_read_u8(&packet);
        uint8_t length = buffer_read_u8(&packet);
        int negated = length & APL_NEGATION_MASK;
        int af = -1;

        length &= APL_LENGTH_MASK;
        switch (address_family) {
        case 1:
            af = AF_INET;
            break;
        case 2:
            af = AF_INET6;
            break;
        }
        if (af != -1 && buffer_available(&packet, length)) {
            char text_address[1000];
            uint8_t address[128];
            memset(address, 0, sizeof(address));
            buffer_read(&packet, address, length);
            if (inet_ntop(af, address, text_address, sizeof(text_address))) {
                buffer_printf(output, "%s%d:%s/%d",
                              negated ? "!" : "",
                              (int) address_family,
                              text_address,
                              (int) prefix);
                result = 1;
            }
        }
    }
    return result;
}
Exemplo n.º 13
0
apr_status_t buffer_socket_recv(buffer_t *self, apr_socket_t *sock)
{
	apr_status_t rs;
	apr_size_t len = buffer_available(self);
	char *space = self->node->first_avail;
	rs = apr_socket_recv(sock, space, &len);
	if (rs != 0)
		return rs;
	self->node->first_avail += (int)len;
	return 0;
}
void buffer_seek( register struct buffer_t * buffer, const unsigned short count){
	unsigned short available = buffer_available( buffer );
	unsigned short can_seek = count < available ? count : available ;
	
	buffer->read_ptr += can_seek;
	
	//whenever the read and write ptrs are equal, pounsigned short them all back to the start
	if(buffer->read_ptr == buffer->write_ptr )
	{
		buffer->read_ptr = buffer->write_ptr = buffer->buffer;	
	}
}
Exemplo n.º 15
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;
}
Exemplo n.º 16
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);
		}
	}
}
Exemplo n.º 17
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;
}
Exemplo n.º 18
0
void buffer_resize(buffer_t *self, int avail)
{
	int size, new_size;
	apr_memnode_t *new_node;

	if (buffer_available(self) >= avail)
		return;
	size = buffer_len(self);
	new_size = size + avail;
	new_node = apr_allocator_alloc(self->allocator, new_size);
	memcpy((char *)new_node + APR_MEMNODE_T_SIZE, buffer_ptr(self), size);
	apr_allocator_free(self->allocator, self->node);
	self->node = new_node;
	self->offset = 0;
}
Exemplo n.º 19
0
/**
 * Parse SOA RR in packet.
 * (kind of similar to xfrd_parse_soa)
 *
 */
static int
query_parse_soa(buffer_type* buffer, uint32_t* serial)
{
    ldns_rr_type type = 0;
    ods_log_assert(buffer);
    if (!buffer_available(buffer, 10)) {
        ods_log_error("[%s] bad soa: packet too short", query_str);
        return 0;
    }
    type = (ldns_rr_type) buffer_read_u16(buffer);
    if (type != LDNS_RR_TYPE_SOA) {
        ods_log_error("[%s] bad soa: rr is not soa (%d)", query_str, type);
        return 0;
    }
    (void)buffer_read_u16(buffer);
    (void)buffer_read_u32(buffer);
    /* rdata length */
    if (!buffer_available(buffer, buffer_read_u16(buffer))) {
        ods_log_error("[%s] bad soa: missing rdlength", query_str);
        return 0;
    }
    /* MNAME */
    if (!buffer_skip_dname(buffer)) {
        ods_log_error("[%s] bad soa: missing mname", query_str);
        return 0;
    }
    /* RNAME */
    if (!buffer_skip_dname(buffer)) {
        ods_log_error("[%s] bad soa: missing rname", query_str);
        return 0;
    }
    if (serial) {
        *serial = buffer_read_u32(buffer);
    }
    return 1;
}
Exemplo n.º 20
0
Arquivo: dns.c Projeto: 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;
}
unsigned short buffer_peek( register struct buffer_t * buffer, char * local, const unsigned short count)
{
	unsigned short available = buffer_available( buffer );
	unsigned short can_read = count < available ? count : available ;

	char * last = buffer->read_ptr + can_read;
	char * ptr = buffer->read_ptr;

	while( ptr != last )
	{
		*(local++) = *(ptr++);
	}
	
	return can_read; //number of bytes read

}
Exemplo n.º 22
0
static apr_status_t port_buffer_send(buffer_t *buf, term_t io)
{
	int avail;

	if (is_nil(io))
		return 0;

	avail = buffer_available(buf);
	if (is_int(io))
	{
		if (avail == 0)
			return APR_EINCOMPLETE;
		else
			buffer_put_byte(buf, int_value(io));
	}
	else if (is_binary(io))
	{
		int size = int_value2(bin_size(io));
		if (size > avail)
		{
			buffer_put_data(buf, bin_data(io), avail);
			return APR_EINCOMPLETE;
		}
		else
			buffer_put_data(buf, bin_data(io), size);
	}
	if (is_list(io))
	{
		while (is_cons(io))
		{
			apr_status_t rs;
			rs = port_buffer_send(buf, lst_value(io));
			if (rs != 0)
				return rs;
			io = lst_next(io);
		}
	}

	return APR_SUCCESS;
}
Exemplo n.º 23
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;
}
Exemplo n.º 24
0
/** find soa serial (if any) */
static int
udb_zone_get_serial(udb_base* udb, udb_ptr* zone, uint32_t* serial)
{
	udb_ptr domain, rrset, rr;
	buffer_type buffer;
	if(!udb_domain_find(udb, zone, ZONE(zone)->name, ZONE(zone)->namelen,
		&domain))
		return 0;
	if(!udb_rrset_find(udb, &domain, TYPE_SOA, &rrset)) {
		udb_ptr_unlink(&domain, udb);
		return 0;
	}
	/* got SOA rrset, use first RR */
	if(!RRSET(&rrset)->rrs.data) {
		udb_ptr_unlink(&domain, udb);
		udb_ptr_unlink(&rrset, udb);
		return 0;
	}
	udb_ptr_new(&rr, udb, &RRSET(&rrset)->rrs);
	udb_ptr_unlink(&domain, udb);
	udb_ptr_unlink(&rrset, udb);
	/* find serial */
	buffer_create_from(&buffer, RR(&rr)->wire, RR(&rr)->len);
	/* skip two dnames */
	if(!packet_skip_dname(&buffer) || !packet_skip_dname(&buffer)) {
		udb_ptr_unlink(&rr, udb);
		return 0;
	}
	if(!buffer_available(&buffer, 4*5)) { /* soa rdata u32s */
		udb_ptr_unlink(&rr, udb);
		return 0;
	}
	*serial = buffer_read_u32(&buffer);
	udb_ptr_unlink(&rr, udb);
	return 1;
}
Exemplo n.º 25
0
packet_t* packet_decode(buffer_t* buffer)
{
	int error = buffer_ok;
	uint16_t length;
	uint8_t id;

	buffer->position = 0;

	error |= buffer_get_short(buffer, &length);
	error |= buffer_get_byte(buffer, &id);
	error |= buffer_available(buffer) == length;

	if (error || length > 5000 || length == 0)
		return NULL;

	uint8_t payload[length];
	memcpy(payload, buffer->payload + buffer->position, length);

	packet_t* packet = safe_alloc(sizeof(packet_t));
	packet->id = id;
	packet->buffer = buffer_wrap(payload, length);
	packet->buffer->position = 0;
	return packet;
}
Exemplo n.º 26
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;
}
Exemplo n.º 27
0
ssize_t
rdata_wireformat_to_rdata_atoms(region_type *region,
				domain_table_type *owners,
				uint16_t rrtype,
				uint16_t data_size,
				buffer_type *packet,
				rdata_atom_type **rdatas)
{
	size_t end = buffer_position(packet) + data_size;
	size_t i;
	rdata_atom_type temp_rdatas[MAXRDATALEN];
	rrtype_descriptor_type *descriptor = rrtype_descriptor_by_type(rrtype);
	region_type *temp_region;

	assert(descriptor->maximum <= MAXRDATALEN);

	if (!buffer_available(packet, data_size)) {
		return -1;
	}

	temp_region = region_create(xalloc, free);

	for (i = 0; i < descriptor->maximum; ++i) {
		int is_domain = 0;
		int is_normalized = 0;
		int is_wirestore = 0;
		size_t length = 0;
		int required = i < descriptor->minimum;

		switch (rdata_atom_wireformat_type(rrtype, i)) {
		case RDATA_WF_COMPRESSED_DNAME:
		case RDATA_WF_UNCOMPRESSED_DNAME:
			is_domain = 1;
			is_normalized = 1;
			break;
		case RDATA_WF_LITERAL_DNAME:
			is_domain = 1;
			is_wirestore = 1;
			break;
		case RDATA_WF_BYTE:
			length = sizeof(uint8_t);
			break;
		case RDATA_WF_SHORT:
			length = sizeof(uint16_t);
			break;
		case RDATA_WF_LONG:
			length = sizeof(uint32_t);
			break;
		case RDATA_WF_TEXTS:
		case RDATA_WF_LONG_TEXT:
			length = end - buffer_position(packet);
			break;
		case RDATA_WF_TEXT:
		case RDATA_WF_BINARYWITHLENGTH:
			/* Length is stored in the first byte.  */
			length = 1;
			if (buffer_position(packet) + length <= end) {
				length += buffer_current(packet)[length - 1];
			}
			break;
		case RDATA_WF_A:
			length = sizeof(in_addr_t);
			break;
		case RDATA_WF_AAAA:
			length = IP6ADDRLEN;
			break;
		case RDATA_WF_ILNP64:
			length = IP6ADDRLEN/2;
			break;
		case RDATA_WF_EUI48:
			length = EUI48ADDRLEN;
			break;
		case RDATA_WF_EUI64:
			length = EUI64ADDRLEN;
			break;
		case RDATA_WF_BINARY:
			/* Remaining RDATA is binary.  */
			length = end - buffer_position(packet);
			break;
		case RDATA_WF_APL:
			length = (sizeof(uint16_t)    /* address family */
				  + sizeof(uint8_t)   /* prefix */
				  + sizeof(uint8_t)); /* length */
			if (buffer_position(packet) + length <= end) {
				/* Mask out negation bit.  */
				length += (buffer_current(packet)[length - 1]
					   & APL_LENGTH_MASK);
			}
			break;
		case RDATA_WF_IPSECGATEWAY:
			switch(rdata_atom_data(temp_rdatas[1])[0]) /* gateway type */ {
			default:
			case IPSECKEY_NOGATEWAY:
				length = 0;
				break;
			case IPSECKEY_IP4:
				length = IP4ADDRLEN;
				break;
			case IPSECKEY_IP6:
				length = IP6ADDRLEN;
				break;
			case IPSECKEY_DNAME:
				is_domain = 1;
				is_normalized = 1;
				is_wirestore = 1;
				break;
			}
			break;
		}

		if (is_domain) {
			const dname_type *dname;

			if (!required && buffer_position(packet) == end) {
				break;
			}

			dname = dname_make_from_packet(
				temp_region, packet, 1, is_normalized);
			if (!dname || buffer_position(packet) > end) {
				/* Error in domain name.  */
				region_destroy(temp_region);
				return -1;
			}
			if(is_wirestore) {
				temp_rdatas[i].data = (uint16_t *) region_alloc(
                                	region, sizeof(uint16_t) + ((size_t)dname->name_size));
				temp_rdatas[i].data[0] = dname->name_size;
				memcpy(temp_rdatas[i].data+1, dname_name(dname),
					dname->name_size);
			} else {
				temp_rdatas[i].domain
					= domain_table_insert(owners, dname);
				temp_rdatas[i].domain->usage ++;
			}
		} else {
			if (buffer_position(packet) + length > end) {
				if (required) {
					/* Truncated RDATA.  */
					region_destroy(temp_region);
					return -1;
				} else {
					break;
				}
			}
			if (!required && buffer_position(packet) == end) {
				break;
			}

			temp_rdatas[i].data = (uint16_t *) region_alloc(
				region, sizeof(uint16_t) + length);
			temp_rdatas[i].data[0] = length;
			buffer_read(packet, temp_rdatas[i].data + 1, length);
		}
	}

	if (buffer_position(packet) < end) {
		/* Trailing garbage.  */
		region_destroy(temp_region);
		return -1;
	}

	*rdatas = (rdata_atom_type *) region_alloc_array_init(
		region, temp_rdatas, i, sizeof(rdata_atom_type));
	region_destroy(temp_region);
	return (ssize_t)i;
}
Exemplo n.º 28
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;
}
Exemplo n.º 29
0
apr_status_t port_socket_set_option(port_t *self, term_t opt, term_t value)
{
	port_socket_data_t *data = self->data;
	if (opt == A_EXPECT)
	{
		if (!is_int(value))
			return APR_BADARG;
		data->expected_size = int_value2(value);
		if (data->expected_size < 0)
			return APR_BADARG;

		if (!is_pid(self->owner_in))
			return APR_ENOPROC;

		//enough data may already be there
		if (data->expected_size == 0 && buffer_len(data->in_buf) > 0 ||
			data->expected_size > 0 && buffer_len(data->in_buf) >= data->expected_size)
		{
			int len = (data->expected_size == 0)
				?buffer_len(data->in_buf)
				:data->expected_size;
			xpool_t *tmp = xpool_make(self->pool);
			term_t bin = make_binary(intnum(len), buffer_ptr(data->in_buf), tmp);
			term_t msg = make_tuple3(A_TCP, port_id(self, tmp), bin, tmp);
			process_t *proc = proc_lookup(pid_serial(self->owner_in));

			proc_new_mail(proc, msg);
			buffer_consume(data->in_buf, len);
			xpool_destroy(tmp);
		}
		else
			data->packet_expected = 1;
	}
	else if (opt == A_REQUIRE)
	{
		int size;
		if (!is_int(value))
			return APR_BADARG;
		size = int_value2(value);
		if (size < 0 || size > SOCK_OUTBUF_LEN)
			return APR_BADARG;

		data->required_size = size;

		if (buffer_available(data->out_buf) >= size)
		{
			xpool_t *tmp = xpool_make(self->pool);
			int avail = buffer_available(data->out_buf);
			term_t msg = make_tuple3(A_TCP_SPACE, port_id(self, tmp), intnum(avail), tmp);
			process_t *proc = proc_lookup(pid_serial(self->owner_out));

			//TODO: insure that only owner can send to socket

			proc_new_mail(proc, msg);
			xpool_destroy(tmp);

			data->space_required = 0;
		}
		else
			data->space_required = 1;
	}
	else
		return APR_BADARG;
	return APR_SUCCESS;
}
Exemplo n.º 30
0
static const char *special_commands(void *userdata, char letter, float value,
				    const char *remaining) {
  GCodeMachineControl_t *state = (GCodeMachineControl_t*)userdata;
  const int code = (int)value;

  if (letter == 'M') {
    int pin = -1;
    int aux_bit = -1;

    switch (code) {
    case 0: set_gpio(ESTOP_SW_GPIO); break;
    case 3:
    case 4:
      for (;;) {
        const char* after_pair = gcodep_parse_pair(remaining, &letter, &value,
                                                   state->msg_stream);
        if (after_pair == NULL) break;
        else if (letter == 'S') state->spindle_rpm = round2int(value);
        else break;
        remaining = after_pair;
      }
      if (state->spindle_rpm) {
        state->aux_bits |= AUX_BIT_SPINDLE_ON;
	if (code == 3) state->aux_bits &= ~AUX_BIT_SPINDLE_DIR;
        else state->aux_bits |= AUX_BIT_SPINDLE_DIR;
      }
      break;
    case 5: state->aux_bits &= ~(AUX_BIT_SPINDLE_ON | AUX_BIT_SPINDLE_DIR); break;
    case 7: state->aux_bits |= AUX_BIT_MIST; break;
    case 8: state->aux_bits |= AUX_BIT_FLOOD; break;
    case 9: state->aux_bits &= ~(AUX_BIT_MIST | AUX_BIT_FLOOD); break;
    case 10: state->aux_bits |= AUX_BIT_VACUUM; break;
    case 11: state->aux_bits &= ~AUX_BIT_VACUUM; break;
    case 42:
    case 62:
    case 63:
    case 64:
    case 65:
      for (;;) {
        const char* after_pair = gcodep_parse_pair(remaining, &letter, &value,
                                                   state->msg_stream);
        if (after_pair == NULL) break;
        if (letter == 'P') pin = round2int(value);
        else if (letter == 'S' && code == 42) aux_bit = round2int(value);
        else break;
        remaining = after_pair;
      }
      if (code == 62 || code == 64)
        aux_bit = 1;
      else if (code == 63 || code == 65)
        aux_bit = 0;
      if (pin >= 0 && pin <= MAX_AUX_PIN) {
        if (aux_bit >= 0 && aux_bit <= 1) {
          if (aux_bit) state->aux_bits |= 1 << pin;
          else state->aux_bits &= ~(1 << pin);
        } else if (code == 42 && state->msg_stream) {  // Just read operation.
          mprintf(state, "%d\n", (state->aux_bits >> pin) & 1);
	}
      }
      break;
    case 80: set_gpio(MACHINE_PWR_GPIO); break;
    case 81: clr_gpio(MACHINE_PWR_GPIO); break;
    case 105: mprintf(state, "T-300\n"); break;  // no temp yet.
    case 114:
      if (buffer_available(&state->buffer)) {
        struct AxisTarget *current = buffer_at(&state->buffer, 0);
        const int *mpos = current->position_steps;
        const float x = 1.0f * mpos[AXIS_X] / state->cfg.steps_per_mm[AXIS_X];
        const float y = 1.0f * mpos[AXIS_Y] / state->cfg.steps_per_mm[AXIS_Y];
        const float z = 1.0f * mpos[AXIS_Z] / state->cfg.steps_per_mm[AXIS_Z];
        const float e = 1.0f * mpos[AXIS_E] / state->cfg.steps_per_mm[AXIS_E];
        const float *origin = state->coordinate_display_origin;
        mprintf(state, "X:%.3f Y:%.3f Z:%.3f E:%.3f",
                x - origin[AXIS_X], y - origin[AXIS_Y], z - origin[AXIS_Z],
                e - origin[AXIS_E]);
        mprintf(state, " [ABS. MACHINE CUBE X:%.3f Y:%.3f Z:%.3f]", x, y, z);
        switch (state->homing_state) {
        case HOMING_STATE_NEVER_HOMED:
          mprintf(state, " (Unsure: machine never homed!)\n");
          break;
        case HOMING_STATE_HOMED_BUT_MOTORS_UNPOWERED:
          mprintf(state, " (Lower confidence: motor power off at "
                  "least once after homing)\n");
          break;
        case HOMING_STATE_HOMED:
          mprintf(state, " (confident: machine was homed)\n");
          break;
        }
      } else {
        mprintf(state, "// no current pos\n");
      }
      break;
    case 115: mprintf(state, "%s\n", VERSION_STRING); break;
    case 117:
      mprintf(state, "// Msg: %s\n", remaining); // TODO: different output ?
      remaining = NULL;  // consume the full line.
      break;
    case 119: {
      char any_enstops_found = 0;
      for (int axis = 0; axis < GCODE_NUM_AXES; ++axis) {
        struct EndstopConfig config = state->min_endstop[axis];
        if (config.endstop_number) {
          int value = get_gpio(get_endstop_gpio_descriptor(config));
          mprintf(state, "%c_min:%s ",
                  tolower(gcodep_axis2letter(axis)),
                  value == config.trigger_value ? "TRIGGERED" : "open");
          any_enstops_found = 1;
        }
        config = state->max_endstop[axis];
        if (config.endstop_number) {
          int value = get_gpio(get_endstop_gpio_descriptor(config));
          mprintf(state, "%c_max:%s ",
                  tolower(gcodep_axis2letter(axis)),
                  value == config.trigger_value ? "TRIGGERED" : "open");
          any_enstops_found = 1;
        }
      }
      if (any_enstops_found) {
        mprintf(state, "\n");
      } else {
        mprintf(state, "// This machine has no endstops configured.\n");
      }
    }
      break;
    case 999: clr_gpio(ESTOP_SW_GPIO); break;
    default:
      mprintf(state, "// BeagleG: didn't understand ('%c', %d, '%s')\n",
              letter, code, remaining);
      remaining = NULL;  // In this case, let's just discard remainig block.
      break;
    }