From a9ccd38adc2965f67a90781253f4bfc9c9b887ed Mon Sep 17 00:00:00 2001 From: Andrew Bettison Date: Mon, 25 Nov 2013 16:43:32 +1030 Subject: [PATCH] Improve overlay buffer ob_xxx() primitives All ob_append_xxx(b,...) functions return void ob_makespace() returns 1 if successful, 0 if not Add ob_overrun(b) predicate to check for overrun after any number of appends --- commandline.c | 27 ++-- conf_schema.h | 1 + mavlink.c | 2 +- overlay_address.c | 73 +++++---- overlay_address.h | 4 +- overlay_buffer.c | 347 +++++++++++++++++++++------------------- overlay_buffer.h | 56 +++---- overlay_link.c | 52 +++--- overlay_mdp.c | 42 +++-- overlay_mdp_services.c | 5 +- overlay_olsr.c | 3 +- overlay_packetformats.c | 18 +-- overlay_payload.c | 66 ++++---- overlay_queue.c | 71 ++++---- rhizome_packetformats.c | 38 +++-- rhizome_sync.c | 35 ++-- route_link.c | 109 ++++++------- serval.h | 2 +- 18 files changed, 458 insertions(+), 493 deletions(-) diff --git a/commandline.c b/commandline.c index 5aed982a..cf5c146e 100644 --- a/commandline.c +++ b/commandline.c @@ -1101,24 +1101,25 @@ int app_trace(const struct cli_parsed *parsed, struct cli_context *context) mdp.out.dst.port=MDP_PORT_TRACE; mdp.packetTypeAndFlags=MDP_TX; struct overlay_buffer *b = ob_static(mdp.out.payload, sizeof(mdp.out.payload)); - ob_append_byte(b, SID_SIZE); ob_append_bytes(b, srcsid.binary, SID_SIZE); - ob_append_byte(b, SID_SIZE); ob_append_bytes(b, dstsid.binary, SID_SIZE); - - mdp.out.payload_length = ob_position(b); - cli_printf(context, "Tracing the network path from %s to %s", - alloca_tohex_sid_t(srcsid), alloca_tohex_sid_t(dstsid)); - cli_delim(context, "\n"); - cli_flush(context); - - int ret=overlay_mdp_send(mdp_sockfd, &mdp, MDP_AWAITREPLY, 5000); + int ret; + if (ob_overrun(b)) + ret = WHY("overlay buffer overrun"); + else { + mdp.out.payload_length = ob_position(b); + cli_printf(context, "Tracing the network path from %s to %s", + alloca_tohex_sid_t(srcsid), alloca_tohex_sid_t(dstsid)); + cli_delim(context, "\n"); + cli_flush(context); + ret = overlay_mdp_send(mdp_sockfd, &mdp, MDP_AWAITREPLY, 5000); + if (ret) + WHYF("overlay_mdp_send returned %d", ret); + } ob_free(b); - if (ret) - WHYF("overlay_mdp_send returned %d", ret); - else{ + if (ret == 0) { int offset=0; { // skip the first two sid's diff --git a/conf_schema.h b/conf_schema.h index ac41acc3..82e005b3 100644 --- a/conf_schema.h +++ b/conf_schema.h @@ -246,6 +246,7 @@ ATOM(bool_t, mavlink, 0, boolean,, "") ATOM(bool_t, mavlink_payloads, 0, boolean,, "") ATOM(bool_t, mavlinkfsm, 0, boolean,, "") ATOM(bool_t, peers, 0, boolean,, "") +ATOM(bool_t, overlaybuffer, 0, boolean,, "") ATOM(bool_t, overlayframes, 0, boolean,, "") ATOM(bool_t, overlayabbreviations, 0, boolean,, "") ATOM(bool_t, overlayrouting, 0, boolean,, "") diff --git a/mavlink.c b/mavlink.c index 3150789e..0fb88230 100644 --- a/mavlink.c +++ b/mavlink.c @@ -141,7 +141,7 @@ int decode_rs_8(data_t *data, int *eras_pos, int no_eras, int pad); int mavlink_encode_packet(struct overlay_interface *interface) { int count = ob_remaining(interface->tx_packet); - int startP = !ob_position(interface->tx_packet); + int startP = (ob_position(interface->tx_packet) == 0); int endP = 1; if (count+6+32 > 255){ count = 255-6-32; diff --git a/overlay_address.c b/overlay_address.c index 2d371b8b..982900a1 100644 --- a/overlay_address.c +++ b/overlay_address.c @@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. since for things like number resolution we are happy to send repeat requests. */ +#include #include "serval.h" #include "conf.h" #include "str.h" @@ -234,35 +235,28 @@ int overlay_broadcast_drop_check(struct broadcast *addr) } } -int overlay_broadcast_append(struct overlay_buffer *b, struct broadcast *broadcast) +void overlay_broadcast_append(struct overlay_buffer *b, struct broadcast *broadcast) { - return ob_append_bytes(b, broadcast->id, BROADCAST_LEN); + ob_append_bytes(b, broadcast->id, BROADCAST_LEN); } // append an appropriate abbreviation into the address -int overlay_address_append(struct decode_context *context, struct overlay_buffer *b, struct subscriber *subscriber) +void overlay_address_append(struct decode_context *context, struct overlay_buffer *b, struct subscriber *subscriber) { - if (!subscriber) - return WHY("No address supplied"); - - if(context - && subscriber == context->point_to_point_device){ - if (ob_append_byte(b, OA_CODE_P2P_YOU)) - return -1; - }else if(context + assert(subscriber != NULL); + if (context && subscriber == context->point_to_point_device) + ob_append_byte(b, OA_CODE_P2P_YOU); + else if(context && !subscriber->send_full && subscriber == my_subscriber && context->point_to_point_device - && (context->encoding_header==0 || !context->interface->local_echo)){ - if (ob_append_byte(b, OA_CODE_P2P_ME)) - return -1; - }else if (context && subscriber==context->sender){ - if (ob_append_byte(b, OA_CODE_SELF)) - return -1; - }else if(context && subscriber==context->previous){ - if (ob_append_byte(b, OA_CODE_PREVIOUS)) - return -1; - }else{ + && (context->encoding_header==0 || !context->interface->local_echo)) + ob_append_byte(b, OA_CODE_P2P_ME); + else if (context && subscriber==context->sender) + ob_append_byte(b, OA_CODE_SELF); + else if (context && subscriber==context->previous) + ob_append_byte(b, OA_CODE_PREVIOUS); + else { int len=SID_SIZE; if (subscriber->send_full){ subscriber->send_full=0; @@ -273,17 +267,15 @@ int overlay_address_append(struct decode_context *context, struct overlay_buffer if (len>SID_SIZE) len=SID_SIZE; } - if (ob_append_byte(b, len)) - return -1; - if (ob_append_bytes(b, subscriber->sid.binary, len)) - return -1; + ob_append_byte(b, len); + ob_append_bytes(b, subscriber->sid.binary, len); } if (context) context->previous = subscriber; - return 0; } -static int add_explain_response(struct subscriber *subscriber, void *context){ +static int add_explain_response(struct subscriber *subscriber, void *context) +{ struct decode_context *response = context; // only explain a SID once every half second. time_ms_t now = gettime_ms(); @@ -292,8 +284,13 @@ static int add_explain_response(struct subscriber *subscriber, void *context){ subscriber->last_explained = now; if (!response->please_explain){ - response->please_explain = calloc(sizeof(struct overlay_frame),1); - response->please_explain->payload=ob_new(); + if ((response->please_explain = emalloc_zero(sizeof(struct overlay_frame))) == NULL) + return 1; // stop walking + if ((response->please_explain->payload = ob_new()) == NULL) { + free(response->please_explain); + response->please_explain = NULL; + return 1; // stop walking + } ob_limitsize(response->please_explain->payload, 1024); } @@ -309,11 +306,10 @@ static int add_explain_response(struct subscriber *subscriber, void *context){ // add the whole subscriber id to the payload, stop if we run out of space DEBUGF("Adding full sid by way of explanation %s", alloca_tohex_sid_t(subscriber->sid)); - if (ob_append_byte(response->please_explain->payload, SID_SIZE)) + ob_append_byte(response->please_explain->payload, SID_SIZE); + ob_append_bytes(response->please_explain->payload, subscriber->sid.binary, SID_SIZE); + if (ob_overrun(response->please_explain->payload)) return 1; - if (ob_append_bytes(response->please_explain->payload, subscriber->sid.binary, SID_SIZE)) - return 1; - // let the routing engine know that we had to explain this sid, we probably need to re-send routing info link_explained(subscriber); return 0; @@ -345,7 +341,8 @@ static int find_subscr_buffer(struct decode_context *context, struct overlay_buf // add the abbreviation you told me about if (!context->please_explain){ context->please_explain = calloc(sizeof(struct overlay_frame),1); - context->please_explain->payload=ob_new(); + if ((context->please_explain->payload = ob_new()) == NULL) + return -1; ob_limitsize(context->please_explain->payload, MDP_MTU); } @@ -396,7 +393,8 @@ int overlay_address_parse(struct decode_context *context, struct overlay_buffer // add the abbreviation you told me about if (!context->please_explain){ context->please_explain = calloc(sizeof(struct overlay_frame),1); - context->please_explain->payload=ob_new(); + if ((context->please_explain->payload = ob_new()) == NULL) + return -1; ob_limitsize(context->please_explain->payload, MDP_MTU); } @@ -433,8 +431,9 @@ int overlay_address_parse(struct decode_context *context, struct overlay_buffer int send_please_explain(struct decode_context *context, struct subscriber *source, struct subscriber *destination){ IN(); struct overlay_frame *frame=context->please_explain; - if (!frame) + if (frame == NULL) RETURN(0); + assert(frame->payload != NULL); frame->type = OF_TYPE_PLEASEEXPLAIN; if (source) @@ -466,7 +465,7 @@ int send_please_explain(struct decode_context *context, struct subscriber *sourc } frame->queue=OQ_MESH_MANAGEMENT; - if (!overlay_payload_enqueue(frame)) + if (overlay_payload_enqueue(frame) != -1) RETURN(0); op_free(frame); RETURN(-1); diff --git a/overlay_address.h b/overlay_address.h index 5a529a7b..7796e469 100644 --- a/overlay_address.h +++ b/overlay_address.h @@ -119,8 +119,8 @@ int process_explain(struct overlay_frame *frame); int overlay_broadcast_drop_check(struct broadcast *addr); int overlay_broadcast_generate_address(struct broadcast *addr); -int overlay_broadcast_append(struct overlay_buffer *b, struct broadcast *broadcast); -int overlay_address_append(struct decode_context *context, struct overlay_buffer *b, struct subscriber *subscriber); +void overlay_broadcast_append(struct overlay_buffer *b, struct broadcast *broadcast); +void overlay_address_append(struct decode_context *context, struct overlay_buffer *b, struct subscriber *subscriber); int overlay_broadcast_parse(struct overlay_buffer *b, struct broadcast *broadcast); int overlay_address_parse(struct decode_context *context, struct overlay_buffer *b, struct subscriber **subscriber); diff --git a/overlay_buffer.c b/overlay_buffer.c index f066838f..d6dc957f 100644 --- a/overlay_buffer.c +++ b/overlay_buffer.c @@ -17,6 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include #include "serval.h" #include "conf.h" #include "mem.h" @@ -30,57 +31,56 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. In either case, functions that don't take an offset use and advance the position. */ - - struct overlay_buffer *ob_new(void) { - struct overlay_buffer *ret=calloc(sizeof(struct overlay_buffer),1); - if (!ret) return NULL; - + struct overlay_buffer *ret = emalloc_zero(sizeof(struct overlay_buffer)); + if (ret == NULL) + return NULL; ob_unlimitsize(ret); - return ret; } // index an existing static buffer. // and allow other callers to use the ob_ convenience methods for reading and writing up to size bytes. -struct overlay_buffer *ob_static(unsigned char *bytes, int size){ - struct overlay_buffer *ret=calloc(sizeof(struct overlay_buffer),1); - if (!ret) return NULL; +struct overlay_buffer *ob_static(unsigned char *bytes, int size) +{ + struct overlay_buffer *ret = emalloc_zero(sizeof(struct overlay_buffer)); + if (ret == NULL) + return NULL; ret->bytes = bytes; ret->allocSize = size; ret->allocated = NULL; ob_unlimitsize(ret); - return ret; } // create a new overlay buffer from an existing piece of another buffer. // Both buffers will point to the same memory region. // It is up to the caller to ensure this buffer is not used after the parent buffer is freed. -struct overlay_buffer *ob_slice(struct overlay_buffer *b, int offset, int length){ +struct overlay_buffer *ob_slice(struct overlay_buffer *b, int offset, int length) +{ if (offset+length > b->allocSize) { WHY("Buffer isn't long enough to slice"); - return NULL; + return NULL; } - - struct overlay_buffer *ret=calloc(sizeof(struct overlay_buffer),1); - if (!ret) + struct overlay_buffer *ret = emalloc_zero(sizeof(struct overlay_buffer)); + if (ret == NULL) return NULL; ret->bytes = b->bytes+offset; ret->allocSize = length; ret->allocated = NULL; ob_unlimitsize(ret); - return ret; } -struct overlay_buffer *ob_dup(struct overlay_buffer *b){ - struct overlay_buffer *ret=calloc(sizeof(struct overlay_buffer),1); +struct overlay_buffer *ob_dup(struct overlay_buffer *b) +{ + struct overlay_buffer *ret = emalloc_zero(sizeof(struct overlay_buffer)); + if (ret == NULL) + return NULL; ret->sizeLimit = b->sizeLimit; ret->position = b->position; ret->checkpointLength = b->checkpointLength; - if (b->bytes && b->allocSize){ // duplicate any bytes that might be relevant int byteCount = b->sizeLimit; @@ -88,97 +88,88 @@ struct overlay_buffer *ob_dup(struct overlay_buffer *b){ byteCount = b->position; if (byteCount > b->allocSize) byteCount = b->allocSize; - - ob_append_bytes(ret, b->bytes, byteCount); + if (byteCount) + ob_append_bytes(ret, b->bytes, byteCount); } return ret; } -int ob_free(struct overlay_buffer *b) +void ob_free(struct overlay_buffer *b) { - if (!b) return WHY("Asked to free NULL"); - if (b->bytes && b->allocated) free(b->allocated); - // we're about to free this anyway, why are we clearing it? - b->bytes=NULL; - b->allocated=NULL; - b->allocSize=0; - b->sizeLimit=0; + assert(b != NULL); + if (b->allocated) + free(b->allocated); free(b); - return 0; } int ob_checkpoint(struct overlay_buffer *b) { - if (!b) return WHY("Asked to checkpoint NULL"); - b->checkpointLength=b->position; + assert(b != NULL); + b->checkpointLength = b->position; return 0; } int ob_rewind(struct overlay_buffer *b) { - if (!b) return WHY("Asked to rewind NULL"); - b->position=b->checkpointLength; + assert(b != NULL); + b->position = b->checkpointLength; return 0; } -int ob_limitsize(struct overlay_buffer *b,int bytes) +void ob_limitsize(struct overlay_buffer *b, int bytes) { - if (!b) return WHY("Asked to limit size of NULL"); - if (b->position>bytes) return WHY("Length of data in buffer already exceeds size limit"); - if (b->checkpointLength>bytes) return WHY("Checkpointed length of data in buffer already exceeds size limit"); - if (b->bytes && (!b->allocated) && bytes > b->allocSize) return WHY("Size limit exceeds buffer size"); - if (bytes<0) return WHY("Can't limit buffer to a negative size"); + assert(b != NULL); + assert(bytes >= 0); + assert(b->position >= 0); + assert(b->position <= bytes); + assert(b->checkpointLength <= bytes); + if (b->bytes && b->allocated == NULL) + assert(bytes <= b->allocSize); b->sizeLimit=bytes; - return 0; } -int ob_unlimitsize(struct overlay_buffer *b) +void ob_unlimitsize(struct overlay_buffer *b) { - if (!b) return WHY("b is NULL"); - b->sizeLimit=-1; - return 0; + assert(b != NULL); + b->sizeLimit = -1; } -int ob_flip(struct overlay_buffer *b) +void ob_flip(struct overlay_buffer *b) { - b->checkpointLength=0; - if (ob_limitsize(b, b->position)) - return -1; - b->position=0; - return 0; + b->checkpointLength = 0; + ob_limitsize(b, b->position); + b->position = 0; } -int _ob_makespace(struct __sourceloc __whence, struct overlay_buffer *b,int bytes) +/* Return 1 if space is available, 0 if not. + */ +ssize_t ob_makespace(struct overlay_buffer *b, size_t bytes) { - if (b->sizeLimit != -1 && b->position + bytes > b->sizeLimit) { - if (config.debug.packetformats) - DEBUGF("asked for space to %u, beyond size limit of %u", b->position + bytes, b->sizeLimit); - return -1; - } - - // already enough space? - if (b->position + bytes <= b->allocSize) + assert(b != NULL); + assert(b->position >= 0); + if (b->sizeLimit != -1) + assert(b->sizeLimit >= 0); + assert(b->allocSize >= 0); + if (b->position) + assert(b->bytes != NULL); + if (b->sizeLimit != -1 && b->position + bytes > b->sizeLimit) + return 0; + if (b->position + bytes <= b->allocSize) + return 1; + // Don't realloc a static buffer. + if (b->bytes && b->allocated == NULL) return 0; - - if (b->bytes && !b->allocated) - return WHY("Can't resize a static buffer"); - - if (0) - DEBUGF("ob_makespace(%p,%d)\n b->bytes=%p,b->position=%d,b->allocSize=%d\n", - b,bytes,b->bytes,b->position,b->allocSize); - int newSize=b->position+bytes; if (newSize<64) newSize=64; if (newSize&63) newSize+=64-(newSize&63); - if (newSize>1024) { - if (newSize&1023) newSize+=1024-(newSize&1023); - } - if (newSize>65536) { - if (newSize&65535) newSize+=65536-(newSize&65535); - } - if (0) DEBUGF("realloc(b->bytes=%p,newSize=%d)", b->bytes,newSize); + if (newSize>1024 && (newSize&1023)) + newSize+=1024-(newSize&1023); + if (newSize>65536 && (newSize&65535)) + newSize+=65536-(newSize&65535); + if (config.debug.overlaybuffer) + DEBUGF("realloc(b->bytes=%p,newSize=%d)", b->bytes,newSize); /* XXX OSX realloc() seems to be able to corrupt things if the heap is not happy when calling realloc(), making debugging memory corruption much harder. - So will do a three-stage malloc,bcopy,free to see if we can tease bugs out that way. */ + So will do a three-stage malloc,bcopy,free to see if we can tease bugs out that way. */ /* unsigned char *r=realloc(b->bytes,newSize); if (!r) return WHY("realloc() failed"); @@ -196,94 +187,99 @@ int _ob_makespace(struct __sourceloc __whence, struct overlay_buffer *b,int byte sleep_ms(36000000); } } - unsigned char *new=malloc(newSize+4096); - if (!new) return WHY("realloc() failed"); + unsigned char *new = emalloc(newSize+4096); { int i; for(i=0;i<4096;i++) new[newSize+i]=0xbd; } #else - unsigned char *new=malloc(newSize); + unsigned char *new = emalloc(newSize); #endif + if (!new) + return 0; bcopy(b->bytes,new,b->position); - if (b->allocated) free(b->allocated); + if (b->allocated) { + assert(b->allocated == b->bytes); + free(b->allocated); + } b->bytes=new; b->allocated=new; b->allocSize=newSize; - return 0; + return 1; } - - /* Functions that append data and increase the size of the buffer if possible / required */ -int _ob_append_byte(struct __sourceloc __whence, struct overlay_buffer *b,unsigned char byte) +void ob_append_byte(struct overlay_buffer *b,unsigned char byte) { - if (_ob_makespace(__whence, b,1)) return WHY("ob_makespace() failed"); - b->bytes[b->position++] = byte; - return 0; + const int bytes = 1; + if (ob_makespace(b, bytes)) + b->bytes[b->position] = byte; + b->position += bytes; } -unsigned char *_ob_append_space(struct __sourceloc __whence, struct overlay_buffer *b,int count) +unsigned char *ob_append_space(struct overlay_buffer *b, int count) { - if (_ob_makespace(__whence, b,count)) { - WHY("ob_makespace() failed"); - return NULL; - } - - unsigned char *r=&b->bytes[b->position]; - b->position+=count; + assert(count > 0); + unsigned char *r = ob_makespace(b, count) ? &b->bytes[b->position] : NULL; + b->position += count; return r; } -int _ob_append_bytes(struct __sourceloc __whence, struct overlay_buffer *b, const unsigned char *bytes, int count) +void ob_append_bytes(struct overlay_buffer *b, const unsigned char *bytes, int count) { - if (_ob_makespace(__whence, b,count)) return WHY("ob_makespace() failed"); - - bcopy(bytes,&b->bytes[b->position],count); - b->position+=count; - return 0; + assert(count > 0); + unsigned char *r = ob_makespace(b, count) ? &b->bytes[b->position] : NULL; + if (r) + bcopy(bytes, r, count); + b->position += count; + if (r) + bcopy(bytes, r, count); } -int _ob_append_buffer(struct __sourceloc __whence, struct overlay_buffer *b, struct overlay_buffer *s){ - return _ob_append_bytes(__whence, b, s->bytes, s->position); +void append_buffer(struct overlay_buffer *b, struct overlay_buffer *s) +{ + ob_append_bytes(b, s->bytes, s->position); } -int _ob_append_ui16(struct __sourceloc __whence, struct overlay_buffer *b, uint16_t v) +void ob_append_ui16(struct overlay_buffer *b, uint16_t v) { - if (_ob_makespace(__whence, b, 2)) return WHY("ob_makespace() failed"); - b->bytes[b->position] = (v >> 8) & 0xFF; - b->bytes[b->position+1] = v & 0xFF; - b->position+=2; - return 0; + const int bytes = 2; + if (ob_makespace(b, bytes)) { + b->bytes[b->position] = (v >> 8) & 0xFF; + b->bytes[b->position+1] = v & 0xFF; + } + b->position += bytes; } -int _ob_append_ui32(struct __sourceloc __whence, struct overlay_buffer *b, uint32_t v) +void ob_append_ui32(struct overlay_buffer *b, uint32_t v) { - if (_ob_makespace(__whence, b, 4)) return WHY("ob_makespace() failed"); - b->bytes[b->position] = (v >> 24) & 0xFF; - b->bytes[b->position+1] = (v >> 16) & 0xFF; - b->bytes[b->position+2] = (v >> 8) & 0xFF; - b->bytes[b->position+3] = v & 0xFF; - b->position+=4; - return 0; + const int bytes = 4; + if (ob_makespace(b, bytes)) { + b->bytes[b->position] = (v >> 24) & 0xFF; + b->bytes[b->position+1] = (v >> 16) & 0xFF; + b->bytes[b->position+2] = (v >> 8) & 0xFF; + b->bytes[b->position+3] = v & 0xFF; + } + b->position += bytes; } -int _ob_append_ui64(struct __sourceloc __whence, struct overlay_buffer *b, uint64_t v) +void ob_append_ui64(struct overlay_buffer *b, uint64_t v) { - if (_ob_makespace(__whence, b, 8)) return WHY("ob_makespace() failed"); - b->bytes[b->position] = (v >> 56) & 0xFF; - b->bytes[b->position+1] = (v >> 48) & 0xFF; - b->bytes[b->position+2] = (v >> 40) & 0xFF; - b->bytes[b->position+3] = (v >> 32) & 0xFF; - b->bytes[b->position+4] = (v >> 24) & 0xFF; - b->bytes[b->position+5] = (v >> 16) & 0xFF; - b->bytes[b->position+6] = (v >> 8) & 0xFF; - b->bytes[b->position+7] = v & 0xFF; - b->position+=8; - return 0; + const int bytes = 8; + if (ob_makespace(b, bytes)) { + b->bytes[b->position] = (v >> 56) & 0xFF; + b->bytes[b->position+1] = (v >> 48) & 0xFF; + b->bytes[b->position+2] = (v >> 40) & 0xFF; + b->bytes[b->position+3] = (v >> 32) & 0xFF; + b->bytes[b->position+4] = (v >> 24) & 0xFF; + b->bytes[b->position+5] = (v >> 16) & 0xFF; + b->bytes[b->position+6] = (v >> 8) & 0xFF; + b->bytes[b->position+7] = v & 0xFF; + } + b->position += bytes; } int measure_packed_uint(uint64_t v){ @@ -320,36 +316,28 @@ int unpack_uint(unsigned char *buffer, int buff_size, uint64_t *v){ return i; } -int _ob_append_packed_ui32(struct __sourceloc __whence, struct overlay_buffer *b, uint32_t v) +void ob_append_packed_ui32(struct overlay_buffer *b, uint32_t v) { - do{ - - if (_ob_append_byte(__whence, b, (v&0x7f) | (v>0x7f?0x80:0))) - return -1; - v = v>>7; - - }while(v!=0); - return 0; + do { + ob_append_byte(b, (v&0x7f) | (v>0x7f?0x80:0)); + v = v >> 7; + } while (v != 0); } -int _ob_append_packed_ui64(struct __sourceloc __whence, struct overlay_buffer *b, uint64_t v) +void ob_append_packed_ui64(struct overlay_buffer *b, uint64_t v) { - do{ - - if (ob_append_byte(b, (v&0x7f) | (v>0x7f?0x80:0))) - return -1; - v = v>>7; - - }while(v!=0); - return 0; + do { + ob_append_byte(b, (v&0x7f) | (v>0x7f?0x80:0)); + v = v >> 7; + } while (v != 0); } -int _ob_append_rfs(struct __sourceloc __whence, struct overlay_buffer *b, int l) +void ob_append_rfs(struct overlay_buffer *b, int l) { - if (l<0||l>0xffff) return -1; - - b->var_length_offset=b->position; - return _ob_append_ui16(__whence, b,l); + assert(l >= 0); + assert(l <= 0xffff); + b->var_length_offset = b->position; + ob_append_ui16(b, l); } @@ -359,7 +347,8 @@ int _ob_append_rfs(struct __sourceloc __whence, struct overlay_buffer *b, int l) // make sure a range of bytes is valid for reading -int test_offset(struct overlay_buffer *b,int start,int length){ +int test_offset(struct overlay_buffer *b,int start,int length) +{ if (!b) return -1; if (start<0) return -1; if (b->sizeLimit>=0 && start+length>b->sizeLimit) return -1; @@ -471,39 +460,59 @@ int ob_get(struct overlay_buffer *b){ return b->bytes[b->position++]; } -int ob_set_ui16(struct overlay_buffer *b, int offset, uint16_t v) +void ob_set_ui16(struct overlay_buffer *b, int offset, uint16_t v) { - if (test_offset(b, offset, 2)) - return -1; - + assert(b != NULL); + assert(offset >= 0); + if (b->sizeLimit != -1) + assert(offset + 2 <= b->sizeLimit); + assert(offset + 2 <= b->allocSize); b->bytes[offset] = (v >> 8) & 0xFF; b->bytes[offset+1] = v & 0xFF; - return 0; } -int ob_set(struct overlay_buffer *b, int ofs, unsigned char byte) +void ob_set(struct overlay_buffer *b, int offset, unsigned char byte) { - if (test_offset(b, ofs, 1)) - return -1; - b->bytes[ofs] = byte; - return 0; + assert(b != NULL); + assert(offset >= 0); + if (b->sizeLimit != -1) + assert(offset + 1 <= b->sizeLimit); + assert(offset + 1 <= b->allocSize); + b->bytes[offset] = byte; } -int ob_patch_rfs(struct overlay_buffer *b){ - return ob_set_ui16(b,b->var_length_offset,b->position - (b->var_length_offset + 2)); +void ob_patch_rfs(struct overlay_buffer *b) +{ + ob_set_ui16(b,b->var_length_offset,b->position - (b->var_length_offset + 2)); } -int ob_position(struct overlay_buffer *b){ +int ob_position(struct overlay_buffer *b) +{ return b->position; } -int ob_limit(struct overlay_buffer *b){ + +int ob_limit(struct overlay_buffer *b) +{ return b->sizeLimit; } -int ob_remaining(struct overlay_buffer *b){ + +int ob_remaining(struct overlay_buffer *b) +{ + assert(b->sizeLimit != -1); return b->sizeLimit - b->position; } -unsigned char *ob_ptr(struct overlay_buffer *b){ + +int ob_overrun(struct overlay_buffer *b) +{ + assert(b->allocSize >= 0); + if (b->sizeLimit != -1) + assert(b->sizeLimit >= 0); + return b->position > (b->sizeLimit != -1 && b->sizeLimit < b->allocSize ? b->sizeLimit : b->allocSize); +} + +unsigned char *ob_ptr(struct overlay_buffer *b) +{ return b->bytes; } diff --git a/overlay_buffer.h b/overlay_buffer.h index 49cc8ca8..5f2b2897 100644 --- a/overlay_buffer.h +++ b/overlay_buffer.h @@ -17,8 +17,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef _SERVALD_OVERLAY_BUFFER_H -#define _SERVALD_OVERLAY_BUFFER_H +#ifndef __SERVALD__OVERLAY_BUFFER_H +#define __SERVALD__OVERLAY_BUFFER_H struct overlay_buffer { unsigned char *bytes; @@ -46,39 +46,28 @@ struct overlay_buffer *ob_new(void); struct overlay_buffer *ob_static(unsigned char *bytes, int size); struct overlay_buffer *ob_slice(struct overlay_buffer *b, int offset, int length); struct overlay_buffer *ob_dup(struct overlay_buffer *b); -int ob_free(struct overlay_buffer *b); +void ob_free(struct overlay_buffer *b); int ob_checkpoint(struct overlay_buffer *b); int ob_rewind(struct overlay_buffer *b); -int ob_limitsize(struct overlay_buffer *b,int bytes); -int ob_flip(struct overlay_buffer *b); -int ob_unlimitsize(struct overlay_buffer *b); -int _ob_makespace(struct __sourceloc whence, struct overlay_buffer *b,int bytes); -int ob_set(struct overlay_buffer *b, int ofs, unsigned char byte); +void ob_limitsize(struct overlay_buffer *b,int bytes); +void ob_flip(struct overlay_buffer *b); +void ob_unlimitsize(struct overlay_buffer *b); +ssize_t ob_makespace(struct overlay_buffer *b, size_t bytes); +void ob_set(struct overlay_buffer *b, int ofs, unsigned char byte); +void ob_set_ui16(struct overlay_buffer *b, int offset, uint16_t v); +void ob_patch_rfs(struct overlay_buffer *b); -int _ob_append_byte(struct __sourceloc whence, struct overlay_buffer *b,unsigned char byte); -int _ob_append_bytes(struct __sourceloc whence, struct overlay_buffer *b,const unsigned char *bytes,int count); -int _ob_append_buffer(struct __sourceloc whence, struct overlay_buffer *b,struct overlay_buffer *s); -unsigned char *_ob_append_space(struct __sourceloc whence, struct overlay_buffer *b,int count); -int _ob_append_ui16(struct __sourceloc whence, struct overlay_buffer *b, uint16_t v); -int _ob_append_ui32(struct __sourceloc whence, struct overlay_buffer *b, uint32_t v); -int _ob_append_ui64(struct __sourceloc whence, struct overlay_buffer *b, uint64_t v); -int _ob_append_packed_ui32(struct __sourceloc whence, struct overlay_buffer *b, uint32_t v); -int _ob_append_packed_ui64(struct __sourceloc whence, struct overlay_buffer *b, uint64_t v); -int _ob_append_rfs(struct __sourceloc whence, struct overlay_buffer *b,int l); +void ob_append_byte(struct overlay_buffer *b,unsigned char byte); +void ob_append_bytes(struct overlay_buffer *b,const unsigned char *bytes,int count); +void ob_append_buffer(struct overlay_buffer *b,struct overlay_buffer *s); +unsigned char *ob_append_space(struct overlay_buffer *b,int count); +void ob_append_ui16(struct overlay_buffer *b, uint16_t v); +void ob_append_ui32(struct overlay_buffer *b, uint32_t v); +void ob_append_ui64(struct overlay_buffer *b, uint64_t v); +void ob_append_packed_ui32(struct overlay_buffer *b, uint32_t v); +void ob_append_packed_ui64(struct overlay_buffer *b, uint64_t v); +void ob_append_rfs(struct overlay_buffer *b,int l); -#define ob_makespace(b, bytes) _ob_makespace(__WHENCE__, b, bytes) -#define ob_append_byte(b, byte) _ob_append_byte(__WHENCE__, b, byte) -#define ob_append_bytes(b, bytes, count) _ob_append_bytes(__WHENCE__, b, bytes, count) -#define ob_append_buffer(b, s) _ob_append_buffer(__WHENCE__, b, s) -#define ob_append_space(b, count) _ob_append_space(__WHENCE__, b, count) -#define ob_append_ui16(b, v) _ob_append_ui16(__WHENCE__, b, v) -#define ob_append_ui32(b, v) _ob_append_ui32(__WHENCE__, b, v) -#define ob_append_ui64(b, v) _ob_append_ui64(__WHENCE__, b, v) -#define ob_append_packed_ui32(b, v) _ob_append_packed_ui32(__WHENCE__, b, v) -#define ob_append_packed_ui64(b, v) _ob_append_packed_ui64(__WHENCE__, b, v) -#define ob_append_rfs(b, l) _ob_append_rfs(__WHENCE__, b, l) - -int ob_patch_rfs(struct overlay_buffer *b); // get one byte, -ve number indicates failure int ob_getbyte(struct overlay_buffer *b,int ofs); // get one byte from the current position, -ve number indicates failure @@ -89,7 +78,6 @@ uint64_t ob_get_ui64(struct overlay_buffer *b); uint32_t ob_get_ui32(struct overlay_buffer *b); uint16_t ob_get_ui16(struct overlay_buffer *b); int ob_dump(struct overlay_buffer *b,char *desc); -int ob_set_ui16(struct overlay_buffer *b, int offset, uint16_t v); uint32_t ob_get_packed_ui32(struct overlay_buffer *b); uint64_t ob_get_packed_ui64(struct overlay_buffer *b); @@ -98,5 +86,7 @@ uint64_t ob_get_packed_ui64(struct overlay_buffer *b); int ob_position(struct overlay_buffer *b); int ob_limit(struct overlay_buffer *b); int ob_remaining(struct overlay_buffer *b); +int ob_overrun(struct overlay_buffer *b); unsigned char* ob_ptr(struct overlay_buffer *b); -#endif + +#endif //__SERVALD__OVERLAY_BUFFER_H diff --git a/overlay_link.c b/overlay_link.c index e66e992c..220d605a 100644 --- a/overlay_link.c +++ b/overlay_link.c @@ -1,3 +1,4 @@ +#include #include "serval.h" #include "conf.h" #include "str.h" @@ -222,14 +223,14 @@ int overlay_send_probe(struct subscriber *peer, struct network_destination *dest frame->ttl=1; frame->queue=queue; frame->destinations[frame->destination_count++].destination=add_destination_ref(destination); - frame->payload = ob_new(); - frame->source_full = 1; - // TODO call mdp payload encryption / signing without calling overlay_mdp_dispatch... - - if (overlay_mdp_encode_ports(frame->payload, MDP_PORT_ECHO, MDP_PORT_PROBE)){ + if ((frame->payload = ob_new()) == NULL) { op_free(frame); return -1; } + frame->source_full = 1; + // TODO call mdp payload encryption / signing without calling overlay_mdp_dispatch... + + overlay_mdp_encode_ports(frame->payload, MDP_PORT_ECHO, MDP_PORT_PROBE); // not worried about byte order here as we are the only node that should be parsing the contents. unsigned char *dst=ob_append_space(frame->payload, sizeof(struct probe_contents)); if (!dst){ @@ -254,25 +255,21 @@ int overlay_send_probe(struct subscriber *peer, struct network_destination *dest } // append the address of a unicast link into a packet buffer -static int overlay_append_unicast_address(struct subscriber *subscriber, struct overlay_buffer *buff) +static void overlay_append_unicast_address(struct subscriber *subscriber, struct overlay_buffer *buff) { - if (subscriber->destination - && subscriber->destination->unicast - && subscriber->destination->address.sin_family==AF_INET){ - if (overlay_address_append(NULL, buff, subscriber)) - return -1; - if (ob_append_ui32(buff, subscriber->destination->address.sin_addr.s_addr)) - return -1; - if (ob_append_ui16(buff, subscriber->destination->address.sin_port)) - return -1; - ob_checkpoint(buff); + if ( subscriber->destination + && subscriber->destination->unicast + && subscriber->destination->address.sin_family==AF_INET + ) { + overlay_address_append(NULL, buff, subscriber); + ob_append_ui32(buff, subscriber->destination->address.sin_addr.s_addr); + ob_append_ui16(buff, subscriber->destination->address.sin_port); if (config.debug.overlayrouting) DEBUGF("Added STUN info for %s", alloca_tohex_sid_t(subscriber->sid)); }else{ if (config.debug.overlayrouting) DEBUGF("Unable to give address of %s, %d", alloca_tohex_sid_t(subscriber->sid),subscriber->reachable); } - return 0; } int overlay_mdp_service_stun_req(overlay_mdp_frame *mdp) @@ -296,22 +293,20 @@ int overlay_mdp_service_stun_req(overlay_mdp_frame *mdp) struct overlay_buffer *replypayload = ob_static(reply.out.payload, sizeof(reply.out.payload)); ob_checkpoint(replypayload); - while(ob_remaining(payload)>0){ + while (ob_remaining(payload) > 0) { struct subscriber *subscriber=NULL; - if (overlay_address_parse(NULL, payload, &subscriber)) break; - if (!subscriber){ if (config.debug.overlayrouting) DEBUGF("Unknown subscriber"); continue; } - - if (overlay_append_unicast_address(subscriber, replypayload)) + overlay_append_unicast_address(subscriber, replypayload); + if (ob_overrun(payload)) break; + ob_checkpoint(replypayload); } - ob_rewind(replypayload); reply.out.payload_length=ob_position(replypayload); @@ -388,11 +383,12 @@ int overlay_send_stun_request(struct subscriber *server, struct subscriber *requ struct overlay_buffer *payload = ob_static(mdp.out.payload, sizeof(mdp.out.payload)); overlay_address_append(NULL, payload, request); - mdp.out.payload_length=ob_position(payload); - if (config.debug.overlayrouting) - DEBUGF("Sending STUN request to %s", alloca_tohex_sid_t(server->sid)); - overlay_mdp_dispatch(&mdp,0 /* system generated */, - NULL,0); + if (!ob_overrun(payload)) { + mdp.out.payload_length=ob_position(payload); + if (config.debug.overlayrouting) + DEBUGF("Sending STUN request to %s", alloca_tohex_sid_t(server->sid)); + overlay_mdp_dispatch(&mdp, 0 /* system generated */, NULL,0); + } ob_free(payload); return 0; } diff --git a/overlay_mdp.c b/overlay_mdp.c index 80eb3fb8..67c58cce 100644 --- a/overlay_mdp.c +++ b/overlay_mdp.c @@ -267,9 +267,7 @@ static int overlay_mdp_decode_header(struct overlay_buffer *buff, overlay_mdp_fr if (!same) port = ob_get_packed_ui32(buff); mdp->in.src.port = port; - - int len=ob_remaining(buff); - + int len = ob_remaining(buff); if (len<0) return WHY("MDP payload is too short"); mdp->in.payload_length=len; @@ -316,10 +314,8 @@ int overlay_mdp_decrypt(struct overlay_frame *f, overlay_mdp_frame *mdp) if (!k) RETURN(WHY("I don't have the private key required to decrypt that")); - if (0){ - dump("frame",&f->payload->bytes[f->payload->position], - ob_remaining(f->payload)); - } + if (0) + dump("frame",&f->payload->bytes[f->payload->position], ob_remaining(f->payload)); unsigned char *nonce=ob_get_bytes_ptr(f->payload, nb); if (!nonce) @@ -529,18 +525,14 @@ int overlay_mdp_check_binding(struct subscriber *subscriber, mdp_port_t port, in ); } -int overlay_mdp_encode_ports(struct overlay_buffer *plaintext, mdp_port_t dst_port, mdp_port_t src_port) +void overlay_mdp_encode_ports(struct overlay_buffer *plaintext, mdp_port_t dst_port, mdp_port_t src_port) { mdp_port_t port = dst_port << 1; if (dst_port == src_port) port |= 1; - if (ob_append_packed_ui32(plaintext, port)) - return -1; - if (dst_port != src_port){ - if (ob_append_packed_ui32(plaintext, src_port)) - return -1; - } - return 0; + ob_append_packed_ui32(plaintext, port); + if (dst_port != src_port) + ob_append_packed_ui32(plaintext, src_port); } static struct overlay_buffer * encrypt_payload( @@ -564,13 +556,15 @@ static struct overlay_buffer * encrypt_payload( cipher_len+=zb; struct overlay_buffer *ret = ob_new(); + if (ret == NULL) + return NULL; unsigned char *nonce = ob_append_space(ret, nb+cipher_len); - unsigned char *cipher_text = nonce + nb; if (!nonce){ ob_free(ret); return NULL; } + unsigned char *cipher_text = nonce + nb; if (generate_nonce(nonce,nb)){ ob_free(ret); @@ -644,8 +638,9 @@ int overlay_send_frame(struct overlay_frame *frame, struct overlay_buffer *plain case OF_CRYPTO_SIGNED: // Lets just append some space into the existing payload buffer for the signature, without copying it. frame->payload = plaintext; - ob_makespace(frame->payload,SIGNATURE_BYTES); - if (crypto_sign_message(frame->source, ob_ptr(frame->payload), frame->payload->allocSize, &frame->payload->position)){ + if ( ob_makespace(frame->payload, SIGNATURE_BYTES) != SIGNATURE_BYTES + || crypto_sign_message(frame->source, ob_ptr(frame->payload), frame->payload->allocSize, &frame->payload->position) == -1 + ) { op_free(frame); return -1; } @@ -773,14 +768,13 @@ int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP, // copy the plain text message into a new buffer, with the wire encoded port numbers struct overlay_buffer *plaintext=ob_new(); - if (!plaintext) + if (plaintext == NULL) RETURN(-1); - if (overlay_mdp_encode_ports(plaintext, mdp->out.dst.port, mdp->out.src.port)){ - ob_free(plaintext); - RETURN (-1); - } - if (ob_append_bytes(plaintext, mdp->out.payload, mdp->out.payload_length)){ + overlay_mdp_encode_ports(plaintext, mdp->out.dst.port, mdp->out.src.port); + if (mdp->out.payload_length) + ob_append_bytes(plaintext, mdp->out.payload, mdp->out.payload_length); + if (ob_overrun(plaintext)) { ob_free(plaintext); RETURN(-1); } diff --git a/overlay_mdp_services.c b/overlay_mdp_services.c index 38138692..8298a135 100644 --- a/overlay_mdp_services.c +++ b/overlay_mdp_services.c @@ -334,15 +334,14 @@ static int overlay_mdp_service_trace(overlay_mdp_frame *mdp){ ob_unlimitsize(b); // always write a full sid into the payload my_subscriber->send_full=1; - if (overlay_address_append(&context, b, my_subscriber)){ + overlay_address_append(&context, b, my_subscriber); + if (ob_overrun(b)) { ret = WHYF("Unable to append my address to the trace"); goto end; } - mdp->out.payload_length = ob_position(b); mdp->out.src.sid = my_subscriber->sid; mdp->out.dst.sid = next->sid; - ret = overlay_mdp_dispatch(mdp, 0, NULL, 0); end: ob_free(b); diff --git a/overlay_olsr.c b/overlay_olsr.c index 6eec98cd..9eb2d0d1 100644 --- a/overlay_olsr.c +++ b/overlay_olsr.c @@ -253,6 +253,8 @@ int olsr_send(struct overlay_frame *frame){ struct decode_context context; bzero(&context, sizeof context); struct overlay_buffer *b=ob_new(); + if (b == NULL) + return 0; // build olsr specific frame header ob_append_byte(b, PACKET_FORMAT_NUMBER); @@ -260,7 +262,6 @@ int olsr_send(struct overlay_frame *frame){ // address the packet as transmitted by me overlay_address_append(&context, b, my_subscriber); - overlay_address_append(&context, b, frame->source); overlay_broadcast_append(b, &frame->broadcast_id); ob_append_byte(b, frame->modifiers); diff --git a/overlay_packetformats.c b/overlay_packetformats.c index c61a53a8..c2c39208 100644 --- a/overlay_packetformats.c +++ b/overlay_packetformats.c @@ -42,20 +42,16 @@ int overlay_packet_init_header(int packet_version, int encapsulation, if (encapsulation !=ENCAP_OVERLAY && encapsulation !=ENCAP_SINGLE) return WHY("Invalid packet encapsulation"); - if (ob_append_byte(buff, packet_version)) - return -1; - if (ob_append_byte(buff, encapsulation)) - return -1; + ob_append_byte(buff, packet_version); + ob_append_byte(buff, encapsulation); - if (context->interface->point_to_point - && context->interface->other_device - && packet_version>=1) + if ( context->interface->point_to_point + && context->interface->other_device + && packet_version>=1 + ) context->point_to_point_device = context->interface->other_device; - context->encoding_header=1; - - if (overlay_address_append(context, buff, my_subscriber)) - return -1; + overlay_address_append(context, buff, my_subscriber); context->encoding_header=0; context->sender = my_subscriber; diff --git a/overlay_payload.c b/overlay_payload.c index ec88c117..05f43215 100644 --- a/overlay_payload.c +++ b/overlay_payload.c @@ -51,34 +51,28 @@ static int overlay_frame_build_header(int packet_version, struct decode_context if (type!=OF_TYPE_DATA) flags |= PAYLOAD_FLAG_LEGACY_TYPE; - if (ob_append_byte(buff, flags)) return -1; + ob_append_byte(buff, flags); - if (!(flags & PAYLOAD_FLAG_SENDER_SAME)){ - if (overlay_address_append(context, buff, source)) return -1; - } + if (!(flags & PAYLOAD_FLAG_SENDER_SAME)) + overlay_address_append(context, buff, source); if (flags & PAYLOAD_FLAG_TO_BROADCAST){ - if (!(flags & PAYLOAD_FLAG_ONE_HOP)){ - if (overlay_broadcast_append(buff, broadcast)) return -1; - } - }else{ - if (overlay_address_append(context, buff, destination)) return -1; - if (!(flags & PAYLOAD_FLAG_ONE_HOP)){ - if (overlay_address_append(context, buff, next_hop)) return -1; - } + if (!(flags & PAYLOAD_FLAG_ONE_HOP)) + overlay_broadcast_append(buff, broadcast); + } else { + overlay_address_append(context, buff, destination); + if (!(flags & PAYLOAD_FLAG_ONE_HOP)) + overlay_address_append(context, buff, next_hop); } - if (!(flags & PAYLOAD_FLAG_ONE_HOP)){ - if (ob_append_byte(buff, ttl | ((queue&3)<<5))) return -1; - } + if (!(flags & PAYLOAD_FLAG_ONE_HOP)) + ob_append_byte(buff, ttl | ((queue&3)<<5)); - if (flags & PAYLOAD_FLAG_LEGACY_TYPE){ - if (ob_append_byte(buff, type)) return -1; - } + if (flags & PAYLOAD_FLAG_LEGACY_TYPE) + ob_append_byte(buff, type); if (packet_version >= 1) - if (ob_append_byte(buff, sequence)) - return -1; + ob_append_byte(buff, sequence); return 0; } @@ -112,20 +106,17 @@ int overlay_frame_append_payload(struct decode_context *context, int encapsulati p->queue, p->type, p->modifiers, will_retransmit, p->ttl, p->mdp_sequence&0xFF, broadcast, p->next_hop, - p->destination, p->source)) + p->destination, p->source) == -1) goto cleanup; - if (encapsulation == ENCAP_OVERLAY){ - if (ob_append_ui16(b, ob_position(p->payload))) - goto cleanup; - } + if (encapsulation == ENCAP_OVERLAY) + ob_append_ui16(b, ob_position(p->payload)); - if (ob_append_bytes(b, ob_ptr(p->payload), ob_position(p->payload))) { - WHYF("could not append payload of %u bytes", ob_position(p->payload)); - goto cleanup; - } - - return 0; + if (ob_position(p->payload)) + ob_append_bytes(b, ob_ptr(p->payload), ob_position(p->payload)); + + if (!ob_overrun(b)) + return 0; cleanup: ob_rewind(b); @@ -150,13 +141,18 @@ struct overlay_frame *op_dup(struct overlay_frame *in) if (!in) return NULL; /* clone the frame */ - struct overlay_frame *out=malloc(sizeof(struct overlay_frame)); - if (!out) { WHY("malloc() failed"); return NULL; } + struct overlay_frame *out = emalloc(sizeof(struct overlay_frame)); + if (out == NULL) + return NULL; /* copy main data structure */ bcopy(in,out,sizeof(struct overlay_frame)); - if (in->payload) - out->payload=ob_dup(in->payload); + if (in->payload) { + if ((out->payload = ob_dup(in->payload)) == NULL) { + free(out); + return NULL; + } + } return out; } diff --git a/overlay_queue.c b/overlay_queue.c index 88815418..10170057 100644 --- a/overlay_queue.c +++ b/overlay_queue.c @@ -17,6 +17,7 @@ */ +#include #include "serval.h" #include "conf.h" #include "overlay_buffer.h" @@ -150,11 +151,9 @@ int overlay_payload_enqueue(struct overlay_frame *p) Complain if there are too many frames in the queue. */ - if (!p) return WHY("Cannot queue NULL"); - - if (p->queue>=OQ_MAX) - return WHY("Invalid queue specified"); - + assert(p != NULL); + assert(p->queue < OQ_MAX); + assert(p->payload != NULL); overlay_txqueue *queue = &overlay_tx[p->queue]; if (config.debug.packettx) @@ -162,18 +161,15 @@ int overlay_payload_enqueue(struct overlay_frame *p) p->destination?alloca_tohex_sid_t_trunc(p->destination->sid, 14): alloca_tohex(p->broadcast_id.id, BROADCAST_LEN), p->queue, queue->length); - if (p->payload && ob_remaining(p->payload)<0){ - // HACK, maybe should be done in each caller - // set the size of the payload based on the position written - ob_limitsize(p->payload,ob_position(p->payload)); - } + if (ob_overrun(p->payload)) + return WHY("Packet content overrun -- not queueing"); + if (ob_position(p->payload) >= MDP_MTU) + FATAL("Queued packet is too big"); + if (queue->length>=queue->maxLength) return WHYF("Queue #%d congested (size = %d)",p->queue,queue->maxLength); - if (ob_position(p->payload)>=MDP_MTU) - FATAL("Queued packet is too big"); - // it should be safe to try sending all packets with an mdp sequence if (p->packet_version<=0) p->packet_version=1; @@ -226,11 +222,13 @@ int overlay_payload_enqueue(struct overlay_frame *p) return 0; } -static void +static int overlay_init_packet(struct outgoing_packet *packet, int packet_version, - struct network_destination *destination){ + struct network_destination *destination) +{ packet->context.interface = destination->interface; - packet->buffer=ob_new(); + if ((packet->buffer = ob_new()) == NULL) + return -1; packet->packet_version = packet_version; packet->context.packet_version = packet_version; packet->destination = add_destination_ref(destination); @@ -238,20 +236,24 @@ overlay_init_packet(struct outgoing_packet *packet, int packet_version, packet->seq=-1; else packet->seq = destination->sequence_number = (destination->sequence_number + 1) & 0xFFFF; - ob_limitsize(packet->buffer, destination->interface->mtu); - - int i=destination->interface - overlay_interfaces; - overlay_packet_init_header(packet_version, destination->encapsulation, - &packet->context, packet->buffer, - destination->unicast, - i, packet->seq); + int i = destination->interface - overlay_interfaces; + if (overlay_packet_init_header(packet_version, destination->encapsulation, + &packet->context, packet->buffer, + destination->unicast, + i, packet->seq) == -1 + ) { + ob_free(packet->buffer); + packet->buffer = NULL; + return -1; + } packet->header_length = ob_position(packet->buffer); if (config.debug.overlayframes) DEBUGF("Creating %d packet for interface %s, seq %d, %s", packet_version, destination->interface->name, destination->sequence_number, destination->unicast?"unicast":"broadcast"); + return 0; } int overlay_queue_schedule_next(time_ms_t next_allowed_packet){ @@ -331,8 +333,9 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim while(frame){ if (frame->enqueued_at + queue->latencyTarget < now){ if (config.debug.overlayframes) - DEBUGF("Dropping frame type %x for %s due to expiry timeout", - frame->type, frame->destination?alloca_tohex_sid_t(frame->destination->sid):"All"); + DEBUGF("Dropping frame type %x (length %d) for %s due to expiry timeout", + frame->type, frame->payload->checkpointLength, + frame->destination?alloca_tohex_sid_t(frame->destination->sid):"All"); frame = overlay_queue_remove(queue, frame); continue; } @@ -411,11 +414,11 @@ overlay_stuff_packet(struct outgoing_packet *packet, overlay_txqueue *queue, tim // send a packet to this destination if (frame->source_full) my_subscriber->send_full=1; - - overlay_init_packet(packet, frame->packet_version, dest); - destination_index=i; - frame->destinations[i].sent_sequence = dest->sequence_number; - break; + if (overlay_init_packet(packet, frame->packet_version, dest) != -1) { + destination_index=i; + frame->destinations[i].sent_sequence = dest->sequence_number; + break; + } } } } @@ -532,12 +535,12 @@ static void overlay_send_packet(struct sched_ent *alarm){ overlay_fill_send_packet(&packet, gettime_ms()); } -int overlay_send_tick_packet(struct network_destination *destination){ +int overlay_send_tick_packet(struct network_destination *destination) +{ struct outgoing_packet packet; bzero(&packet, sizeof(struct outgoing_packet)); - overlay_init_packet(&packet, 0, destination); - - overlay_fill_send_packet(&packet, gettime_ms()); + if (overlay_init_packet(&packet, 0, destination) != -1) + overlay_fill_send_packet(&packet, gettime_ms()); return 0; } diff --git a/rhizome_packetformats.c b/rhizome_packetformats.c index 092976f4..01af7c16 100644 --- a/rhizome_packetformats.c +++ b/rhizome_packetformats.c @@ -168,11 +168,12 @@ static int append_bars(struct overlay_buffer *e, sqlite_retry_state *retry, cons DEBUG("Found a BAR that is the wrong size - ignoring"); continue; } - if (ob_append_bytes(e, (unsigned char *)data, blob_bytes)){ + if (ob_remaining(e) < blob_bytes) { // out of room count--; break; } + ob_append_bytes(e, (unsigned char *)data, blob_bytes); *last_rowid=rowid; } if (statement) @@ -184,7 +185,8 @@ static int append_bars(struct overlay_buffer *e, sqlite_retry_state *retry, cons Always advertise the most recent 3 manifests in the table, cycle through the rest of the table, adding 17 BAR's at a time */ int64_t bundles_available=0; -void overlay_rhizome_advertise(struct sched_ent *alarm){ +void overlay_rhizome_advertise(struct sched_ent *alarm) +{ bundles_available=0; static int64_t bundle_last_rowid=INT64_MAX; @@ -197,7 +199,7 @@ void overlay_rhizome_advertise(struct sched_ent *alarm){ int (*oldfunc)() = sqlite_set_tracefunc(is_debug_rhizome_ads); sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT; - // DEPRECATE REST OF THIS CODE WHICH SEEMS TO BE CAUSING TOO MUCH CHATTER + // TODO: DEPRECATE REST OF THIS CODE WHICH SEEMS TO BE CAUSING TOO MUCH CHATTER // ESPECIALLY FOR PACKET-RADIO goto end; @@ -216,31 +218,28 @@ void overlay_rhizome_advertise(struct sched_ent *alarm){ frame->source = my_subscriber; frame->ttl = 1; frame->queue = OQ_OPPORTUNISTIC; - frame->payload = ob_new(); + if ((frame->payload = ob_new()) == NULL) { + op_free(frame); + goto end; + } ob_limitsize(frame->payload, 800); - ob_append_byte(frame->payload, 2); ob_append_ui16(frame->payload, rhizome_http_server_port); - int64_t rowid=0; int count = append_bars(frame->payload, &retry, "SELECT BAR,ROWID FROM MANIFESTS ORDER BY ROWID DESC LIMIT 3", &rowid); - if (count>=3){ if (bundle_last_rowid>rowid || bundle_last_rowid<=0) bundle_last_rowid=rowid; - count = append_bars(frame->payload, &retry, "SELECT BAR,ROWID FROM MANIFESTS WHERE ROWID < ? ORDER BY ROWID DESC LIMIT 17", &bundle_last_rowid); if (count<17) bundle_last_rowid=INT64_MAX; } - - if (overlay_payload_enqueue(frame)) + if (overlay_payload_enqueue(frame) == -1) op_free(frame); - end: sqlite_set_tracefunc(oldfunc); alarm->alarm = gettime_ms()+config.rhizome.advertise.interval; @@ -262,21 +261,20 @@ int rhizome_advertise_manifest(struct subscriber *dest, rhizome_manifest *m){ else frame->ttl = 1; frame->queue = OQ_OPPORTUNISTIC; - frame->payload = ob_new(); - + if ((frame->payload = ob_new()) == NULL) + goto error; ob_limitsize(frame->payload, 800); - - if (ob_append_byte(frame->payload, HAS_PORT|HAS_MANIFESTS)) goto error; - if (ob_append_ui16(frame->payload, is_rhizome_http_enabled()?rhizome_http_server_port:0)) goto error; - if (ob_append_ui16(frame->payload, m->manifest_all_bytes)) goto error; - if (ob_append_bytes(frame->payload, m->manifestdata, m->manifest_all_bytes)) goto error; + ob_append_byte(frame->payload, HAS_PORT|HAS_MANIFESTS); + ob_append_ui16(frame->payload, is_rhizome_http_enabled()?rhizome_http_server_port:0); + ob_append_ui16(frame->payload, m->manifest_all_bytes); + ob_append_bytes(frame->payload, m->manifestdata, m->manifest_all_bytes); ob_append_byte(frame->payload, 0xFF); - if (overlay_payload_enqueue(frame)) goto error; + if (overlay_payload_enqueue(frame) == -1) + goto error; if (config.debug.rhizome_ads) DEBUGF("Advertising manifest %s %"PRId64" to %s", alloca_tohex_rhizome_bid_t(m->cryptoSignPublic), m->version, dest?alloca_tohex_sid_t(dest->sid):"broadcast"); return 0; - error: op_free(frame); return -1; diff --git a/rhizome_sync.c b/rhizome_sync.c index 415b0944..98162614 100644 --- a/rhizome_sync.c +++ b/rhizome_sync.c @@ -321,21 +321,16 @@ static void sync_process_bar_list(struct subscriber *subscriber, struct rhizome_ } -static int append_response(struct overlay_buffer *b, uint64_t token, const unsigned char *bar) +static void append_response(struct overlay_buffer *b, uint64_t token, const unsigned char *bar) { - if (ob_append_packed_ui64(b, token)) - return -1; - if (bar){ - if (ob_append_bytes(b, bar, RHIZOME_BAR_BYTES)) - return -1; - }else{ + ob_append_packed_ui64(b, token); + if (bar) + ob_append_bytes(b, bar, RHIZOME_BAR_BYTES); + else{ unsigned char *ptr = ob_append_space(b, RHIZOME_BAR_BYTES); - if (!ptr) - return -1; - bzero(ptr, RHIZOME_BAR_BYTES); + if (ptr) + bzero(ptr, RHIZOME_BAR_BYTES); } - ob_checkpoint(b); - return 0; } static uint64_t max_token=0; @@ -400,24 +395,26 @@ static void sync_send_response(struct subscriber *dest, int forwards, uint64_t t // make sure we include the exact rowid that was requested, even if we just deleted / replaced the manifest if (count==0 && rowid!=token){ if (token!=HEAD_FLAG){ - if (append_response(b, token, NULL)) + ob_checkpoint(b); + append_response(b, token, NULL); + if (ob_overrun(b)) ob_rewind(b); - else{ + else { count++; last = token; } }else token = rowid; } - - if (append_response(b, rowid, bar)) + ob_checkpoint(b); + append_response(b, rowid, bar); + if (ob_overrun(b)) ob_rewind(b); else { last = rowid; count++; } } - if (count >= max_count && rowid <= max_token) break; } @@ -427,7 +424,9 @@ static void sync_send_response(struct subscriber *dest, int forwards, uint64_t t // send a zero lower bound if we reached the end of our manifest list if (count && count < max_count && !forwards){ - if (append_response(b, 0, NULL)) + ob_checkpoint(b); + append_response(b, 0, NULL); + if (ob_overrun(b)) ob_rewind(b); else { last = 0; diff --git a/route_link.c b/route_link.c index 17e1310e..e7581ec7 100644 --- a/route_link.c +++ b/route_link.c @@ -467,48 +467,27 @@ static int append_link_state(struct overlay_buffer *payload, char flags, flags|=FLAG_HAS_ACK; if (drop_rate!=-1) flags|=FLAG_HAS_DROP_RATE; - int length_pos = ob_position(payload); - if (ob_append_byte(payload, 0)) - return -1; - - if (ob_append_byte(payload, flags)) - return -1; - - if (overlay_address_append(NULL, payload, receiver)) - return -1; - - if (ob_append_byte(payload, version)) - return -1; - + ob_append_byte(payload, 0); + ob_append_byte(payload, flags); + overlay_address_append(NULL, payload, receiver); + ob_append_byte(payload, version); if (transmitter) - if (overlay_address_append(NULL, payload, transmitter)) - return -1; - - if (interface!=-1) - if (ob_append_byte(payload, interface)) - return -1; - - if (ack_sequence!=-1){ - if (ob_append_byte(payload, ack_sequence)) - return -1; - if (ob_append_ui32(payload, ack_mask)) - return -1; + overlay_address_append(NULL, payload, transmitter); + if (interface != -1) + ob_append_byte(payload, interface); + if (ack_sequence != -1){ + ob_append_byte(payload, ack_sequence); + ob_append_ui32(payload, ack_mask); } - - if (drop_rate!=-1) - if (ob_append_byte(payload, drop_rate)) - return -1; - - + if (drop_rate != -1) + ob_append_byte(payload, drop_rate); // TODO insert future fields here - - + if (ob_overrun(payload)) + return -1; // patch the record length int end_pos = ob_position(payload); - if (ob_set(payload, length_pos, end_pos - length_pos)) - return -1; - + ob_set(payload, length_pos, end_pos - length_pos); ob_checkpoint(payload); return 0; } @@ -710,12 +689,15 @@ static int send_legacy_self_announce_ack(struct neighbour *neighbour, struct lin frame->ttl = 6; frame->destination = neighbour->subscriber; frame->source = my_subscriber; - frame->payload = ob_new(); + if ((frame->payload = ob_new()) == NULL) { + op_free(frame); + return -1; + } ob_append_ui32(frame->payload, neighbour->last_update); ob_append_ui32(frame->payload, now); ob_append_byte(frame->payload, link->neighbour_interface); frame->queue=OQ_MESH_MANAGEMENT; - if (overlay_payload_enqueue(frame)){ + if (overlay_payload_enqueue(frame) == -1) { op_free(frame); return -1; } @@ -787,12 +769,16 @@ static int send_neighbour_link(struct neighbour *n) send_legacy_self_announce_ack(n, n->best_link, now); n->last_update = now; } else { - struct overlay_frame *frame=emalloc_zero(sizeof(struct overlay_frame)); + struct overlay_frame *frame = emalloc_zero(sizeof(struct overlay_frame)); frame->type=OF_TYPE_DATA; frame->source=my_subscriber; frame->ttl=1; frame->queue=OQ_MESH_MANAGEMENT; - frame->payload = ob_new(); + if ((frame->payload = ob_new()) == NULL) { + op_free(frame); + RETURN(-1); + } + frame->send_hook = neighbour_link_sent; frame->send_context = n->subscriber; frame->resend=-1; @@ -825,7 +811,7 @@ static int send_neighbour_link(struct neighbour *n) append_link_state(frame->payload, flags, n->subscriber, my_subscriber, n->best_link->neighbour_interface, 1, n->best_link->ack_sequence, n->best_link->ack_mask, -1); - if (overlay_payload_enqueue(frame)) + if (overlay_payload_enqueue(frame) == -1) op_free(frame); n->best_link->ack_counter = ACK_WINDOW; @@ -885,27 +871,25 @@ static void link_send(struct sched_ent *alarm) frame->source=my_subscriber; frame->ttl=1; frame->queue=OQ_MESH_MANAGEMENT; - frame->payload = ob_new(); - ob_limitsize(frame->payload, 400); - - overlay_mdp_encode_ports(frame->payload, MDP_PORT_LINKSTATE, MDP_PORT_LINKSTATE); - ob_checkpoint(frame->payload); - int pos = ob_position(frame->payload); - - enum_subscribers(NULL, append_link, frame->payload); - - ob_rewind(frame->payload); - - if (ob_position(frame->payload) == pos) - op_free(frame); - else if (overlay_payload_enqueue(frame)) - op_free(frame); - - if (neighbours){ - alarm->deadline = alarm->alarm; - schedule(alarm); - }else - alarm->alarm=0; + if ((frame->payload = ob_new()) == NULL) + WHY("Cannot send link details"); + else { + ob_limitsize(frame->payload, 400); + overlay_mdp_encode_ports(frame->payload, MDP_PORT_LINKSTATE, MDP_PORT_LINKSTATE); + ob_checkpoint(frame->payload); + int pos = ob_position(frame->payload); + enum_subscribers(NULL, append_link, frame->payload); + ob_rewind(frame->payload); + if (ob_position(frame->payload) == pos) + op_free(frame); + else if (overlay_payload_enqueue(frame)) + op_free(frame); + if (neighbours){ + alarm->deadline = alarm->alarm; + schedule(alarm); + }else + alarm->alarm=0; + } } static void update_alarm(time_ms_t limit){ @@ -1113,7 +1097,6 @@ static struct link_out *create_out_link(struct neighbour *neighbour, overlay_int ret->destination = create_unicast_destination(*addr, interface); else ret->destination = add_destination_ref(interface->destination); - if (config.debug.linkstate) DEBUGF("LINK STATE; Create possible %s link_out for neighbour %s on interface %s", unicast?"unicast":"broadcast", diff --git a/serval.h b/serval.h index 1c0a6373..62b2bcf6 100644 --- a/serval.h +++ b/serval.h @@ -576,7 +576,7 @@ int overlay_mdp_reply(int sock,struct sockaddr_un *recvaddr, socklen_t recvaddrl overlay_mdp_frame *mdpreply); int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP, struct sockaddr_un *recvaddr, socklen_t recvaddrlen); -int overlay_mdp_encode_ports(struct overlay_buffer *plaintext, mdp_port_t dst_port, mdp_port_t src_port); +void overlay_mdp_encode_ports(struct overlay_buffer *plaintext, mdp_port_t dst_port, mdp_port_t src_port); int overlay_mdp_dnalookup_reply(const sockaddr_mdp *dstaddr, const sid_t *resolved_sidp, const char *uri, const char *did, const char *name); struct vomp_call_state;