static int32_t oftr_decode_openflow(const char *input, size_t input_len, char *output, size_t output_len) { if (input_len < sizeof(ofp::Header)) { return buf_copy(output, output_len, "Buffer size < 8 bytes", true); } if (input_len > 0xffff) { return buf_copy(output, output_len, "Buffer size > 65535 bytes", true); } if (ofp::Big16_unaligned(ofp::BytePtr(input) + 2) != input_len) { return buf_copy(output, output_len, "Message length does not match buffer size", true); } ofp::Message message{input, input_len}; message.normalize(); ofp::yaml::Decoder decoder{&message, false, false}; auto err = decoder.error(); if (!err.empty()) { return buf_copy(output, output_len, err.data(), err.size(), true); } auto result = decoder.result(); return buf_copy(output, output_len, result.data(), result.size(), false); }
/* * copy_str_to_buffer() * - res: response representation * - data: text data, in our case almost text representation of error * - pad: the size of pad (for how much bytes the string should be * padded * * The function copy_str_to_buffer ensures copy of text buffer into response * buffer. * * Return value: 0 if there is no environment error * -1 if there is some enviroment error such as insufficiency * of memory */ static int copy_str_to_buffer(struct stun_msg* res, const char* data, UINT_T pad) { USHORT_T pad_len; UINT_T data_len; UCHAR_T empty[pad]; data_len = strlen(data); memset(&empty, 0, pad); pad_len = (pad - data_len%pad) % pad; if (buf_copy(&res->msg, (void *) data, sizeof(UCHAR_T)*data_len) != 0) { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: copy_str_to_buffer: failed to copy buffer\n"); #endif return FATAL_ERROR; } if (pad_len != 0) { if (buf_copy(&res->msg, &empty, pad_len) != 0) { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: copy_str_to_buffer: failed to pad\n"); #endif return FATAL_ERROR; } } return pad_len; }
/* * stun_add_address_attr() * - res: response representation * - af: address family * - port: port * - ip_addr: represent both IPv4 and IPv6, the differences is in * length * - type: type of attribute * - do_xor: if the port should be XOR-ed or not. * * The function stun_add_address_attr ensures copy of any IP attribute into * response buffer. * * Return value: 0 if there is no environment error * -1 if there is some enviroment error such as insufficiency * of memory */ int stun_add_address_attr(struct stun_msg* res, UINT_T af, USHORT_T port, UINT_T* ip_addr, USHORT_T type, int do_xor) { struct stun_attr attr; UINT_T id[IP_ADDR]; int ip_struct_len; int i; ip_struct_len = 0; attr.type = htons(type); res->ip_addr.port = (do_xor) ? htons(port) ^ MAGIC_COOKIE_2B : htons(port); switch(af) { case AF_INET: ip_struct_len = sizeof(struct stun_ip_addr) - 3*sizeof(UINT_T); res->ip_addr.family = htons(IPV4_FAMILY); memcpy(res->ip_addr.ip, ip_addr, IPV4_LEN); res->ip_addr.ip[0] = (do_xor) ? res->ip_addr.ip[0] ^ MAGIC_COOKIE : res->ip_addr.ip[0]; break; #ifdef USE_IPV6 case AF_INET6: ip_struct_len = sizeof(struct stun_ip_addr); res->ip_addr.family = htons(IPV6_FAMILY); memcpy(&res->ip_addr.ip, ip_addr, IPV6_LEN); memcpy(id, &res->hdr.id, sizeof(struct transaction_id)); for (i=0; i<IP_ADDR; i++) { res->ip_addr.ip[i] = (do_xor) ? res->ip_addr.ip[i] ^ id[i] : res->ip_addr.ip[i]; } break; #endif /* USE_IPV6 */ default: break; } attr.len = htons(ip_struct_len); /* copy type and attribute's length */ if (buf_copy(&res->msg, (void *) &attr, sizeof(struct stun_attr)) != 0) { return FATAL_ERROR; } /* copy family, port and IP */ if (buf_copy(&res->msg, (void *) &res->ip_addr, ip_struct_len) != 0) { return FATAL_ERROR; } return 0; }
static int32_t oftr_encode_openflow(const char *input, size_t input_len, uint8_t version, char *output, size_t output_len) { llvm::StringRef text{input, input_len}; ofp::yaml::Encoder encoder{text, true, 1, version}; auto err = encoder.error(); if (!err.empty()) { return buf_copy(output, output_len, err.data(), err.size(), true); } return buf_copy(output, output_len, encoder.data(), encoder.size(), false); }
/* * add_unknown_attr() * - res: response representation * - unknown: link list of unknown attributes * * The function add_unknown_attr ensures copy of link list of unknown * attributes into response buffer. * * Return value: 0 if there is no environment error * -1 if there is some enviroment error such as insufficiency * of memory * */ static int add_unknown_attr(struct stun_msg* res, struct stun_unknown_att* unknown) { struct stun_attr attr; struct stun_unknown_att* tmp_unknown; UINT_T counter; USHORT_T orig_len; counter = 0; orig_len = res->msg.buf.len; tmp_unknown = unknown; attr.type = htons(UNKNOWN_ATTRIBUTES_ATTR); attr.len = htons(0); if (buf_copy(&res->msg, (void *) &attr, sizeof(struct stun_attr)) != 0) { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: add_unknown_attr: failed to copy buffer\n"); #endif return FATAL_ERROR; } while (tmp_unknown != NULL) { if (buf_copy(&res->msg, (void *)&tmp_unknown->type, sizeof(USHORT_T)) != 0) { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: add_unknown_attr: failed to copy unknown attribute\n"); #endif return FATAL_ERROR; } tmp_unknown = tmp_unknown->next; ++counter; } attr.len = htons(res->msg.buf.len - orig_len); memcpy(&res->msg.buf.s[orig_len], (void *)&attr, sizeof(struct stun_attr)); /* check if there is an odd number of unknown attributes and if yes, * repeat one of them because of padding to 32 */ if (counter/2 != 0 && unknown != NULL) { if (buf_copy(&res->msg, (void *)&unknown->type, sizeof(USHORT_T))!=0) { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: add_unknown_attr: failed to padd\n"); #endif return FATAL_ERROR; } } return 0; }
/* * dbg_write(client, adr, buf, len) * * Writes "len" bytes from "buf" to the memory of client "client" at its address "adr". * * Return value: * 0 Successful * 1 Error * */ int dbg_write(sid_t client, uintptr_t adr, const void* buf, size_t len) { uintptr_t l__offset = adr & 0xfff; uint8_t* l__tmp = dbg_prep_access(client, adr, len, PGA_WRITE); if (l__tmp == NULL) return 1; /* Write data to buf */ buf_copy(&l__tmp[l__offset], buf, len); if (*tls_errno) { dbg_isprintf("Can't copy data in dbg_write, because of %i.\n", *tls_errno); *tls_errno = 0; pmap_free(l__tmp); return 1; } /* Awake the client */ hymk_awake_subject(client); /* Free the buffer */ pmap_free(l__tmp); return 0; }
/* * stun_add_common_text_attr() * - res: structure representing response * - type: type of attribute * - value: attribute's value * - pad: size of pad * * The function stun_add_common_text_attr copy attribute with string value * into response buffer. * * Return value: 0 if there is no environment error * -1 if there is some enviroment error such as insufficiency * of memory */ static int stun_add_common_text_attr(struct stun_msg* res, USHORT_T type, char* value, USHORT_T pad) { struct stun_attr attr; if (value == NULL) { LOG(L_INFO, "INFO: stun_add_common_text_attr: value is NULL\n"); return 0; } attr.type = htons(type); attr.len = htons(strlen(value)); if (buf_copy(&res->msg, (void *) &attr, sizeof(struct stun_attr)) != 0) { return FATAL_ERROR; } if (copy_str_to_buffer(res, value, pad) < 0) { return FATAL_ERROR; } return 0; }
pstr STDCALL str_copylen( pstr ps, pubyte src, uint len ) { ps->use--; // print("String Load %i %x\n", len, src ); buf_copy( ps, src, len ); return buf_appendch( ps, 0 ); }
static struct buf *from_buf(struct buf *buf) { struct buf *ret = buf_new(); buf_copy(ret, buf); return ret; }
static bool tls_crypt_v2_wrap_client_key(struct buffer *wkc, const struct key2 *src_key, const struct buffer *src_metadata, struct key_ctx *server_key, struct gc_arena *gc) { cipher_ctx_t *cipher_ctx = server_key->cipher; struct buffer work = alloc_buf_gc(TLS_CRYPT_V2_MAX_WKC_LEN + cipher_ctx_block_size(cipher_ctx), gc); /* Calculate auth tag and synthetic IV */ uint8_t *tag = buf_write_alloc(&work, TLS_CRYPT_TAG_SIZE); if (!tag) { msg(M_WARN, "ERROR: could not write tag"); return false; } uint16_t net_len = htons(sizeof(src_key->keys) + BLEN(src_metadata) + TLS_CRYPT_V2_TAG_SIZE + sizeof(uint16_t)); hmac_ctx_t *hmac_ctx = server_key->hmac; hmac_ctx_reset(hmac_ctx); hmac_ctx_update(hmac_ctx, (void *)&net_len, sizeof(net_len)); hmac_ctx_update(hmac_ctx, (void *)src_key->keys, sizeof(src_key->keys)); hmac_ctx_update(hmac_ctx, BPTR(src_metadata), BLEN(src_metadata)); hmac_ctx_final(hmac_ctx, tag); dmsg(D_CRYPTO_DEBUG, "TLS-CRYPT WRAP TAG: %s", format_hex(tag, TLS_CRYPT_TAG_SIZE, 0, gc)); /* Use the 128 most significant bits of the tag as IV */ ASSERT(cipher_ctx_reset(cipher_ctx, tag)); /* Overflow check (OpenSSL requires an extra block in the dst buffer) */ if (buf_forward_capacity(&work) < (sizeof(src_key->keys) + BLEN(src_metadata) + sizeof(net_len) + cipher_ctx_block_size(cipher_ctx))) { msg(M_WARN, "ERROR: could not crypt: insufficient space in dst"); return false; } /* Encrypt */ int outlen = 0; ASSERT(cipher_ctx_update(cipher_ctx, BEND(&work), &outlen, (void *)src_key->keys, sizeof(src_key->keys))); ASSERT(buf_inc_len(&work, outlen)); ASSERT(cipher_ctx_update(cipher_ctx, BEND(&work), &outlen, BPTR(src_metadata), BLEN(src_metadata))); ASSERT(buf_inc_len(&work, outlen)); ASSERT(cipher_ctx_final(cipher_ctx, BEND(&work), &outlen)); ASSERT(buf_inc_len(&work, outlen)); ASSERT(buf_write(&work, &net_len, sizeof(net_len))); return buf_copy(wkc, &work); }
static int32_t oftr_version(char *output, size_t output_len) { std::string libofpCommit{LIBOFP_GIT_COMMIT_LIBOFP}; std::string buf; llvm::raw_string_ostream oss{buf}; oss << LIBOFP_VERSION_STRING << " (" << libofpCommit.substr(0, 7) << ")"; oss << " <" << LIBOFP_GITHUB_URL << ">"; oss.flush(); return buf_copy(output, output_len, buf.data(), buf.size(), false); }
/* * stun_add_common_integer_attr() * - res: structure representing response * - type: type of attribute * - value: attribute's value * * The function stun_add_common_integer_attr copy attribute with integer value * into response buffer. * * Return value: 0 if there is no environment error * -1 if there is some enviroment error such as insufficiency * of memory */ int stun_add_common_integer_attr(struct stun_msg* res, USHORT_T type, UINT_T value) { struct stun_attr attr; attr.type = htons(type); attr.len = htons(sizeof(UINT_T)); if (buf_copy(&res->msg, (void *) &attr, sizeof(struct stun_attr)) != 0) { return FATAL_ERROR; } value = htonl(value); if (buf_copy(&res->msg, (void *) &value, sizeof(UINT_T)) != 0) { return FATAL_ERROR; } return 0; }
int dynbuf_copybuf(struct dynbuf *d, const void *buf, size_t len) { unsigned char *b; if(dynbuf_need(d, (len + 1)) != 0) return -1; /* error! */ buf_copy(d->buf, buf, len); d->p = len; b = d->buf; b[d->p] = 'Z'; /* "offensive programming" */ return 0; /* no error */ }
int pkt_load(pkt_t K, uchar_t P, uchar_t T, uchar_t *buf, size_t N) { /* fail if N too large for pkt_t: */ if(N > (sizeof(pkt_t) - 3)){ errno = ERANGE; return -1; } K[0] = P; K[1] = T; K[2] = (uint8_t)N; buf_copy(&K[3], buf, N); return 0; }
HIDDEN int parse_backup_line(struct protstream *in, time_t *ts, struct buf *cmd, struct dlist **kin) { struct dlist *dl = NULL; struct buf buf = BUF_INITIALIZER; int64_t t; int c; c = prot_getc(in); if (c == '#') eatline(in, c); else prot_ungetc(c, in); c = getint64(in, &t); if (c == EOF) goto fail; c = getword(in, &buf); if (c == EOF) goto fail; c = dlist_parse(&dl, /*parsekeys*/ 1, 1, in); if (!dl) { fprintf(stderr, "\ndidn't parse dlist, error %i\n", c); goto fail; } if (c == '\r') c = prot_getc(in); if (c != '\n') { fprintf(stderr, "expected newline, got '%c'\n", c); eatline(in, c); goto fail; } if (kin) *kin = dl; if (cmd) buf_copy(cmd, &buf); if (ts) *ts = (time_t) t; buf_free(&buf); return c; fail: if (dl) dlist_free(&dl); buf_free(&buf); return c; }
int dynbuf_putbuf(dynbuf *d, const void *buf, size_t len) { unsigned char *b; if(!d->n) return dynbuf_copybuf(d, buf, len); if(dynbuf_grow(d, (len + 1)) != 0) return -1; /* error! */ buf_copy((d->buf + d->p), buf, len); d->p += len; b = d->buf; b[d->p] = 'Q'; /* "offensive programming" */ return 0; /* no error */ }
static void act_copy (void) { fileoffset_t marktop, marksize; if (!marking) { display_beep(); strcpy (message, "Set mark first"); return; } marktop = cur_pos; marksize = mark_point - cur_pos; if (marksize < 0) { marktop += marksize; marksize = -marksize; } if (cutbuffer) buf_free (cutbuffer); cutbuffer = buf_copy (filedata, marksize, marktop); marking = FALSE; }
void buffer_list_aggregate_separator (struct buffer_list *bl, const size_t max, const char *sep) { int sep_len = strlen(sep); if (bl->head) { struct buffer_entry *more = bl->head; size_t size = 0; int count = 0; for (count = 0; more && size <= max; ++count) { size += BLEN(&more->buf) + sep_len; more = more->next; } if (count >= 2) { int i; struct buffer_entry *e = bl->head, *f; ALLOC_OBJ_CLEAR (f, struct buffer_entry); f->buf.data = malloc (size); check_malloc_return (f->buf.data); f->buf.capacity = size; for (i = 0; e && i < count; ++i) { struct buffer_entry *next = e->next; buf_copy (&f->buf, &e->buf); buf_write(&f->buf, sep, sep_len); free_buf (&e->buf); free (e); e = next; } bl->head = f; f->next = more; if (!more) bl->tail = f; } } }
static void test_buffer_time_tracking(void *arg) { buf_t *buf=NULL, *buf2=NULL; struct timeval tv0; const time_t START = 1389288246; const uint32_t START_MSEC = (uint32_t) ((uint64_t)START * 1000); int i; char tmp[4096]; (void)arg; crypto_rand(tmp, sizeof(tmp)); tv0.tv_sec = START; tv0.tv_usec = 0; buf = buf_new_with_capacity(3000); /* rounds up to next power of 2. */ tt_assert(buf); /* Empty buffer means the timestamp is 0. */ tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC)); tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+1000)); tor_gettimeofday_cache_set(&tv0); write_to_buf("ABCDEFG", 7, buf); tt_int_op(1000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+1000)); buf2 = buf_copy(buf); tt_assert(buf2); tt_int_op(1234, OP_EQ, buf_get_oldest_chunk_timestamp(buf2, START_MSEC+1234)); /* Now add more bytes; enough to overflow the first chunk. */ tv0.tv_usec += 123 * 1000; tor_gettimeofday_cache_set(&tv0); for (i = 0; i < 600; ++i) write_to_buf("ABCDEFG", 7, buf); tt_int_op(4207, OP_EQ, buf_datalen(buf)); /* The oldest bytes are still in the front. */ tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2000)); /* Once those bytes are dropped, the chunk is still on the first * timestamp. */ fetch_from_buf(tmp, 100, buf); tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2000)); /* But once we discard the whole first chunk, we get the data in the second * chunk. */ fetch_from_buf(tmp, 4000, buf); tt_int_op(107, OP_EQ, buf_datalen(buf)); tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2123)); /* This time we'll be grabbing a chunk from the freelist, and making sure its time gets updated */ tv0.tv_sec += 5; tv0.tv_usec = 617*1000; tor_gettimeofday_cache_set(&tv0); for (i = 0; i < 600; ++i) write_to_buf("ABCDEFG", 7, buf); tt_int_op(4307, OP_EQ, buf_datalen(buf)); tt_int_op(2000, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+2123)); fetch_from_buf(tmp, 4000, buf); fetch_from_buf(tmp, 306, buf); tt_int_op(0, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+5617)); tt_int_op(383, OP_EQ, buf_get_oldest_chunk_timestamp(buf, START_MSEC+6000)); done: buf_free(buf); buf_free(buf2); }
static bool tls_crypt_v2_unwrap_client_key(struct key2 *client_key, struct buffer *metadata, struct buffer wrapped_client_key, struct key_ctx *server_key) { const char *error_prefix = __func__; bool ret = false; struct gc_arena gc = gc_new(); /* The crypto API requires one extra cipher block of buffer head room when * decrypting, which nicely matches the tag size of WKc. So * TLS_CRYPT_V2_MAX_WKC_LEN is always large enough for the plaintext. */ uint8_t plaintext_buf_data[TLS_CRYPT_V2_MAX_WKC_LEN] = { 0 }; struct buffer plaintext = { 0 }; dmsg(D_TLS_DEBUG_MED, "%s: unwrapping client key (len=%d): %s", __func__, BLEN(&wrapped_client_key), format_hex(BPTR(&wrapped_client_key), BLEN(&wrapped_client_key), 0, &gc)); if (TLS_CRYPT_V2_MAX_WKC_LEN < BLEN(&wrapped_client_key)) { CRYPT_ERROR("wrapped client key too big"); } /* Decrypt client key and metadata */ uint16_t net_len = 0; const uint8_t *tag = BPTR(&wrapped_client_key); if (BLEN(&wrapped_client_key) < sizeof(net_len)) { CRYPT_ERROR("failed to read length"); } memcpy(&net_len, BEND(&wrapped_client_key) - sizeof(net_len), sizeof(net_len)); if (ntohs(net_len) != BLEN(&wrapped_client_key)) { dmsg(D_TLS_DEBUG_LOW, "%s: net_len=%u, BLEN=%i", __func__, ntohs(net_len), BLEN(&wrapped_client_key)); CRYPT_ERROR("invalid length"); } buf_inc_len(&wrapped_client_key, -(int)sizeof(net_len)); if (!buf_advance(&wrapped_client_key, TLS_CRYPT_TAG_SIZE)) { CRYPT_ERROR("failed to read tag"); } if (!cipher_ctx_reset(server_key->cipher, tag)) { CRYPT_ERROR("failed to initialize IV"); } buf_set_write(&plaintext, plaintext_buf_data, sizeof(plaintext_buf_data)); int outlen = 0; if (!cipher_ctx_update(server_key->cipher, BPTR(&plaintext), &outlen, BPTR(&wrapped_client_key), BLEN(&wrapped_client_key))) { CRYPT_ERROR("could not decrypt client key"); } ASSERT(buf_inc_len(&plaintext, outlen)); if (!cipher_ctx_final(server_key->cipher, BEND(&plaintext), &outlen)) { CRYPT_ERROR("cipher final failed"); } ASSERT(buf_inc_len(&plaintext, outlen)); /* Check authentication */ uint8_t tag_check[TLS_CRYPT_TAG_SIZE] = { 0 }; hmac_ctx_reset(server_key->hmac); hmac_ctx_update(server_key->hmac, (void *)&net_len, sizeof(net_len)); hmac_ctx_update(server_key->hmac, BPTR(&plaintext), BLEN(&plaintext)); hmac_ctx_final(server_key->hmac, tag_check); if (memcmp_constant_time(tag, tag_check, sizeof(tag_check))) { dmsg(D_CRYPTO_DEBUG, "tag : %s", format_hex(tag, sizeof(tag_check), 0, &gc)); dmsg(D_CRYPTO_DEBUG, "tag_check: %s", format_hex(tag_check, sizeof(tag_check), 0, &gc)); CRYPT_ERROR("client key authentication error"); } if (buf_len(&plaintext) < sizeof(client_key->keys)) { CRYPT_ERROR("failed to read client key"); } memcpy(&client_key->keys, BPTR(&plaintext), sizeof(client_key->keys)); ASSERT(buf_advance(&plaintext, sizeof(client_key->keys))); if (!buf_copy(metadata, &plaintext)) { CRYPT_ERROR("metadata too large for supplied buffer"); } ret = true; error_exit: if (!ret) { secure_memzero(client_key, sizeof(*client_key)); } buf_clear(&plaintext); gc_free(&gc); return ret; }
pstr STDCALL str_copy( pstr dest, pstr src ) { return buf_copy( ( pbuf )dest, str_ptr( src ), src->use ); }
static int32_t buf_copy(char *output, size_t output_len, const char *str, bool error) { return buf_copy(output, output_len, str, strlen(str), error); }
static int foreach(struct dbengine *db, const char *prefix, size_t prefixlen, foreach_p *goodp, foreach_cb *cb, void *rock, struct txn **mytid) { int r = CYRUSDB_OK; int offset; unsigned long len; const char *p, *pend; const char *dataend; /* for use inside the loop, but we need the values to be retained * from loop to loop */ struct buf keybuf = BUF_INITIALIZER; int dontmove = 0; /* For when we have a transaction running */ struct buf savebuf = BUF_INITIALIZER; /* for the local iteration so that the db can change out from under us */ const char *dbbase = NULL; size_t dblen = 0; int dbfd = -1; struct buf prefixbuf = BUF_INITIALIZER; r = starttxn_or_refetch(db, mytid); if (r) return r; if (!mytid) { /* No transaction, use the fast method to avoid stomping on our * memory map if changes happen */ dbfd = dup(db->fd); if(dbfd == -1) return CYRUSDB_IOERROR; map_refresh(dbfd, 1, &dbbase, &dblen, db->size, db->fname, 0); /* drop our read lock on the file, since we don't really care * if it gets replaced out from under us, our mmap stays on the * old version */ lock_unlock(db->fd, db->fname); } else { /* use the same variables as in the no transaction case, just to * get things set up */ dbbase = db->base; dblen = db->len; } if (prefix) { encode(prefix, prefixlen, &prefixbuf); offset = bsearch_mem_mbox(prefixbuf.s, dbbase, db->size, 0, &len); } else { offset = 0; } p = dbbase + offset; pend = dbbase + db->size; while (p < pend) { if (!dontmove) { GETENTRY(p) } else dontmove = 0; /* does it still match prefix? */ if (keybuf.len < (size_t) prefixbuf.len) break; if (prefixbuf.len && memcmp(keybuf.s, prefixbuf.s, prefixbuf.len)) break; if (!goodp || goodp(rock, keybuf.s, keybuf.len, DATA(db), DATALEN(db))) { unsigned long ino = db->ino; unsigned long sz = db->size; if(mytid) { /* transaction present, this means we do the slow way */ buf_copy(&savebuf, &keybuf); } /* make callback */ r = cb(rock, keybuf.s, keybuf.len, DATA(db), DATALEN(db)); if (r) break; if (mytid) { /* reposition? (we made a change) */ if (!(ino == db->ino && sz == db->size)) { /* something changed in the file; reseek */ buf_cstring(&savebuf); offset = bsearch_mem_mbox(savebuf.s, db->base, db->size, 0, &len); p = db->base + offset; GETENTRY(p); /* 'key' might not equal 'savebuf'. if it's different, we want to stay where we are. if it's the same, we should move on to the next one */ if (!buf_cmp(&savebuf, &keybuf)) { p = dataend + 1; } else { /* 'savebuf' got deleted, so we're now pointing at the right thing */ dontmove = 1; } } } } p = dataend + 1; } if (!mytid) { /* cleanup the fast method */ map_free(&dbbase, &dblen); close(dbfd); } buf_free(&savebuf); buf_free(&keybuf); buf_free(&prefixbuf); return r; }
/* * add_error_code() * - res: response representation * - error_code: value of error type * * The function add_error_code ensures copy of link list of unknown * attributes into response buffer. * * Return value: 0 if there is no environment error * -1 if there is some enviroment error such as insufficiency * of memory */ static int add_error_code(struct stun_msg* res, USHORT_T error_code) { struct stun_attr attr; USHORT_T orig_len; USHORT_T two_bytes; int text_pad; char err[2]; orig_len = res->msg.buf.len; text_pad = 0; /* the type and length will be copy as last one because of unknown length*/ if (res->msg.buf.len < sizeof(struct stun_attr)) { if (reallock_buffer(&res->msg, sizeof(struct stun_attr)) != 0) { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: add_error_code: failed to reallocate buffer\n"); #endif return FATAL_ERROR; } } res->msg.buf.len += sizeof(struct stun_attr); res->msg.empty -= sizeof(struct stun_attr); /* first two bytes are empty */ two_bytes = 0x0000; if (buf_copy(&res->msg, (void *) &two_bytes, sizeof(USHORT_T)) != 0) { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: add_error_code: failed to copy buffer\n"); #endif return FATAL_ERROR; } err[0] = error_code / 100; err[1] = error_code % 100; if (buf_copy(&res->msg, (void *) err, sizeof(UCHAR_T)*2) != 0) { return FATAL_ERROR; } switch (error_code) { case TRY_ALTERNATE_ERR: text_pad = copy_str_to_buffer(res, TRY_ALTERNATE_TXT, PAD4); break; case BAD_REQUEST_ERR: text_pad = copy_str_to_buffer(res, BAD_REQUEST_TXT, PAD4); break; case UNAUTHORIZED_ERR: text_pad = copy_str_to_buffer(res, UNAUTHORIZED_TXT, PAD4); break; case UNKNOWN_ATTRIBUTE_ERR: text_pad = copy_str_to_buffer(res, UNKNOWN_ATTRIBUTE_TXT, PAD4); break; case STALE_CREDENTIALS_ERR: text_pad = copy_str_to_buffer(res, STALE_CREDENTIALS_TXT, PAD4); break; case INTEGRITY_CHECK_ERR: text_pad = copy_str_to_buffer(res, INTEGRITY_CHECK_TXT, PAD4); break; case MISSING_USERNAME_ERR: text_pad = copy_str_to_buffer(res, MISSING_USERNAME_TXT, PAD4); break; case USE_TLS_ERR: text_pad = copy_str_to_buffer(res, USE_TLS_TXT, PAD4); break; case MISSING_REALM_ERR: text_pad = copy_str_to_buffer(res, MISSING_REALM_TXT, PAD4); break; case MISSING_NONCE_ERR: text_pad = copy_str_to_buffer(res, MISSING_NONCE_TXT, PAD4); break; case UNKNOWN_USERNAME_ERR: text_pad = copy_str_to_buffer(res, UNKNOWN_USERNAME_TXT, PAD4); break; case STALE_NONCE_ERR: text_pad = copy_str_to_buffer(res, STALE_NONCE_TXT, PAD4); break; case SERVER_ERROR_ERR: text_pad = copy_str_to_buffer(res, SERVER_ERROR_TXT, PAD4); break; case GLOBAL_FAILURE_ERR: text_pad = copy_str_to_buffer(res, GLOBAL_FAILURE_TXT, PAD4); break; default: LOG(L_ERR, "ERROR: STUN: Unknown error code.\n"); break; } if (text_pad < 0) { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: add_error_code: text_pad is negative\n"); #endif goto error; } attr.type = htons(ERROR_CODE_ATTR); /* count length of "value" field -> without type and lehgth field */ attr.len = htons(res->msg.buf.len - orig_len - text_pad - sizeof(struct stun_attr)); memcpy(&res->msg.buf.s[orig_len], (void *)&attr, sizeof(struct stun_attr)); return 0; error: return FATAL_ERROR; }
static int stun_create_response( struct stun_msg* req, struct stun_msg* res, struct receive_info* ri, struct stun_unknown_att* unknown, UINT_T error_code) { /* * Alloc some space for response. * Optimalization? - maybe it would be better to use biggish static array. */ res->msg.buf.s = (char *) pkg_malloc(sizeof(char)*STUN_MSG_LEN); if (res->msg.buf.s == NULL) { LOG(L_ERR, "ERROR: STUN: out of memory\n"); return FATAL_ERROR; } memset(res->msg.buf.s, 0, sizeof(char)*STUN_MSG_LEN); res->msg.buf.len = 0; res->msg.empty = STUN_MSG_LEN; /* use magic cookie and transaction ID from request */ memcpy(&res->hdr.id, &req->hdr.id, sizeof(struct transaction_id)); /* the correct body length will be added ASAP it will be known */ res->hdr.len = htons(0); if (error_code == RESPONSE_OK) { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: stun_create_response: creating normal response\n"); #endif res->hdr.type = htons(BINDING_RESPONSE); /* copy header into msg buffer */ if (buf_copy(&res->msg, (void *) &res->hdr, sizeof(struct stun_hdr)) != 0) { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: stun_create_response: failed to copy buffer\n"); #endif return FATAL_ERROR; } /* * If the SER received message in old format, then the body will * contain MAPPED-ADDRESS attribute instead of XOR-MAPPED-ADDRESS * attribute. */ if (req->old == 0) { if (stun_add_address_attr(res, ri->src_ip.af, ri->src_port, ri->src_ip.u.addr32, XOR_MAPPED_ADDRESS_ATTR, XOR) != 0) { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: stun_create_response: failed to add address\n"); #endif return FATAL_ERROR; } } else { if (stun_add_address_attr(res, ri->src_ip.af, ri->src_port, ri->src_ip.u.addr32, MAPPED_ADDRESS_ATTR, !XOR) != 0) { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: stun_create_response: failed to add address\n"); #endif return FATAL_ERROR; } } } else { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: stun_create_response: creating error response\n"); #endif res->hdr.type = htons(BINDING_ERROR_RESPONSE); if (buf_copy(&res->msg, (void *) &res->hdr, sizeof(struct stun_hdr)) != 0) { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: stun_create_response: failed to copy buffer\n"); #endif return FATAL_ERROR; } if (add_error_code(res, error_code) != 0) { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: stun_create_response: failed to add error code\n"); #endif return FATAL_ERROR; } if (unknown != NULL) { if (add_unknown_attr(res, unknown) != 0) { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: stun_create_response: failed to add unknown attribute\n"); #endif return FATAL_ERROR; } } } if (req->old == 0) { /* * add optional information about server; attribute SOFTWARE is part of * rfc5389.txt * */ if (stun_add_common_text_attr(res, SOFTWARE_ATTR, SERVER_HDR, PAD4)!=0) { #ifdef EXTRA_DEBUG LOG(L_DBG, "DEBUG: stun_create_response: failed to add common text attribute\n"); #endif return FATAL_ERROR; } } res->hdr.len = htons(res->msg.buf.len - sizeof(struct stun_hdr)); memcpy(&res->msg.buf.s[sizeof(USHORT_T)], (void *) &res->hdr.len, sizeof(USHORT_T)); return 0; }
/* * mem_realloc(mem, size) * * Resizes the memory block that is pointed * by "mem" to "size" bytes. * If "mem" is "NULL", the function will work * like mem_alloc. If "size" is 0, the function * will free the memory area. * * The function tries to expand the current area * at is current memory position. If this is not * possible, it will move the content to a new * memory block with the size "size". If an * area should be shrinked content at the end * of the memory area can be lost. * * Return value: * Pointer to the new area of "size" bytes. * NULL if failed. * */ void* mem_realloc(void* mem, size_t nsz) { void* l__retval = NULL; block_t *l__block = NULL; size_t l__block_sz = 0; /* Will we do nothing? */ if ((mem == NULL) && (nsz == 0)) { *tls_errno = ERR_INVALID_ARGUMENT; return NULL; } /* We just want to allocate a new area */ if (mem == NULL) return mem_alloc(nsz); /* We just want to free the area */ if (nsz == NULL) {mem_free(mem); return NULL;} mtx_lock(&lib_heap_mutex, -1); /* Get the memory block of "mem" */ l__block = lib_find_ubl_block((uintptr_t)mem); if (l__block == NULL) { *tls_errno = ERR_INVALID_ADDRESS; mtx_unlock(&lib_heap_mutex); return NULL; } l__block_sz = l__block->size; /* Is there a need for resizing it? */ if (l__block_sz == nsz) { l__retval = (void*)l__block->data; mtx_unlock(&lib_heap_mutex); return l__retval; } /* * Shrink a block * -------------- * */ if (l__block->size > nsz) { size_t l__rest = l__block->size - nsz; block_t *l__newblock = NULL; uintptr_t l__newblock_start = 0; /* Can we create a new free memory area ? */ if (l__rest <= sizeof(block_t)) { l__retval = (void*)l__block->data; /* No it is too small. No effect. */ mtx_unlock(&lib_heap_mutex); return l__retval; } l__block->size = nsz; l__block->fbl = lib_get_right_fbl(nsz); l__rest -= sizeof(block_t); /* Create the new free block */ l__newblock_start = l__block->data + nsz; l__newblock = lib_create_free_entry(l__newblock_start, l__rest, LIB_BLOCKSTAT_FREE, l__block ); /* Try to unify it with your neighbourhood */ lib_unify_free_entry(l__newblock); /* Should we shrink the heap? */ if (lib_last_gbl_entry == l__newblock) { lib_shrink_heap(); } else { /* Can we clean the entry? */ lib_clean_free_entry(l__newblock); } l__retval = (void*)l__block->data; mtx_unlock(&lib_heap_mutex); return l__retval; } /* * Expand a block * -------------- * * Is there a free block in the "upper" neighbourhood, * we can merge with? */ if (l__block->gbl_ls.n != NULL) { block_t *l__tmp_n = l__block->gbl_ls.n; /* Is it a free area? */ if (l__tmp_n->status != LIB_BLOCKSTAT_USED) { size_t l__tmpsz = nsz - l__block->size; /* It seems to fit exactly */ if ((l__tmp_n->size + sizeof(block_t)) == l__tmpsz) { /* Just merge them completly */ lib_remove_from_fbl(l__tmp_n); block_t *l__tmpnx = l__tmp_n->gbl_ls.n; if (l__tmpnx != NULL) { l__tmpnx->gbl_ls.p = l__block; } else { lib_last_gbl_entry = l__block; } l__block->gbl_ls.n = l__tmpnx; l__block->size = nsz; l__block->fbl = lib_get_right_fbl(l__block->size); l__retval = (void*)l__block->data; mtx_unlock(&lib_heap_mutex); return l__retval; } /* It is graeter than, so we have to split it */ else if (l__tmp_n->size > l__tmpsz) { if (lib_split_free_entry(l__tmp_n, l__tmpsz) != - 1) { /* Now we have our fitting entry */ block_t *l__tmpnx = l__tmp_n->gbl_ls.n; lib_remove_from_ubl(l__tmp_n); if (l__tmpnx != NULL) { l__tmpnx->gbl_ls.p = l__block; } else { lib_last_gbl_entry = l__block; } l__block->gbl_ls.n = l__tmpnx; l__block->size = nsz; l__block->fbl = lib_get_right_fbl(l__block->size); l__retval = (void*)l__block->data; mtx_unlock(&lib_heap_mutex); return l__retval; } } } } /* * Okay, it seems we haven't found a fitting block in our * direct environment, so we have to choose another one, * copy us to it and free our old block. * */ mtx_unlock(&lib_heap_mutex); l__retval = mem_alloc(nsz); if (l__block_sz > nsz) l__block_sz = nsz; buf_copy(l__retval, mem, l__block_sz); mem_free(mem); return l__retval; }
void *memcpy(void *dest, const void *src, size_t n) { buf_copy(dest, src, n); return dest; }