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; }
size_t buffer_push(struct Buffer *buf, size_t size) { if (buffer_available(buf) < size) size = buffer_available(buf); buf->dataLen += size; return size; }
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; }
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 ; }
/* * 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; }
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; }
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 }
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; }
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; }
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; }
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; } }
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; }
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); } } }
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; }
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; }
/** * 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; }
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 }
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; }
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; }
/** 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; }
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; }
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; }
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; }
/* 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; }
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; }
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; }