void rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout) { struct ssl_connect *sconn; if (F == NULL) return; sconn = rb_malloc(sizeof(struct ssl_connect)); sconn->data = data; sconn->callback = callback; sconn->timeout = timeout; F->connect = rb_malloc(sizeof(struct conndata)); F->connect->callback = callback; F->connect->data = data; F->type |= RB_FD_SSL; F->ssl = rb_malloc(sizeof(gnutls_session_t)); gnutls_init(F->ssl, GNUTLS_CLIENT); gnutls_set_default_priority(SSL_P(F)); gnutls_dh_set_prime_bits(SSL_P(F), 1024); gnutls_transport_set_ptr(SSL_P(F), (gnutls_transport_ptr_t) (long int)F->fd); rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn); if (do_ssl_handshake(F, rb_ssl_tryconn_cb)) { rb_ssl_connect_realcb(F, RB_OK, sconn); } }
void rb_ssl_accept_setup(rb_fde_t *F, rb_fde_t *new_F, struct sockaddr *st, int addrlen) { new_F->type |= RB_FD_SSL; new_F->ssl = rb_malloc(sizeof(gnutls_session_t)); new_F->accept = rb_malloc(sizeof(struct acceptdata)); new_F->accept->callback = F->accept->callback; new_F->accept->data = F->accept->data; rb_settimeout(new_F, 10, rb_ssl_timeout, NULL); memcpy(&new_F->accept->S, st, addrlen); new_F->accept->addrlen = addrlen; gnutls_init((gnutls_session_t *) new_F->ssl, GNUTLS_SERVER); gnutls_set_default_priority(SSL_P(new_F)); gnutls_credentials_set(SSL_P(new_F), GNUTLS_CRD_CERTIFICATE, x509); gnutls_dh_set_prime_bits(SSL_P(new_F), 1024); gnutls_transport_set_ptr(SSL_P(new_F), (gnutls_transport_ptr_t) (long int)rb_get_fd(new_F)); if (do_ssl_handshake(F, rb_ssl_tryaccept)) { struct acceptdata *ad = F->accept; F->accept = NULL; ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data); rb_free(ad); } }
void rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout) { gnutls_session_t *ssl; new_F->type |= RB_FD_SSL; ssl = new_F->ssl = rb_malloc(sizeof(gnutls_session_t)); new_F->accept = rb_malloc(sizeof(struct acceptdata)); new_F->accept->callback = cb; new_F->accept->data = data; rb_settimeout(new_F, timeout, rb_ssl_timeout, NULL); new_F->accept->addrlen = 0; gnutls_init(ssl, GNUTLS_SERVER); gnutls_set_default_priority(*ssl); gnutls_credentials_set(*ssl, GNUTLS_CRD_CERTIFICATE, x509); gnutls_dh_set_prime_bits(*ssl, 1024); gnutls_transport_set_ptr(*ssl, (gnutls_transport_ptr_t) (long int)new_F->fd); if (do_ssl_handshake(new_F, rb_ssl_tryaccept)) { struct acceptdata *ad = new_F->accept; new_F->accept = NULL; ad->callback(new_F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data); rb_free(ad); } }
void rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout) { ssl_connect_t *sconn; int ssl_err; if(F == NULL) return; sconn = rb_malloc(sizeof(ssl_connect_t)); sconn->data = data; sconn->callback = callback; sconn->timeout = timeout; F->connect = rb_malloc(sizeof(struct conndata)); F->connect->callback = callback; F->connect->data = data; F->type |= RB_FD_SSL; F->ssl = SSL_new(F->sctx->ssl_ctx); if(F->ssl == NULL) { F->sslerr.ssl_errno = get_last_err(); rb_lib_log("rb_ssl_start_Connected: SSL_new() fails: %s", ERR_error_string(F->sslerr.ssl_errno, NULL)); rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn); return; } SSL_set_fd((SSL *) F->ssl, F->fd); rb_setup_ssl_cb(F); rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn); if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0) { switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err)) { case SSL_ERROR_SYSCALL: if(rb_ignore_errno(errno)) case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: { F->sslerr.ssl_errno = get_last_err(); rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, rb_ssl_tryconn_cb, sconn); return; } default: F->sslerr.ssl_errno = get_last_err(); rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn); return; } } else { rb_ssl_connect_realcb(F, RB_OK, sconn); } }
/* See lookup_ip's comment */ struct dns_query * lookup_hostname(const char *ip, DNSCB callback, void *data) { struct dns_query *query = rb_malloc(sizeof(struct dns_query)); int aftype; if(!rb_inet_pton_sock(ip, (struct sockaddr *)&query->addr)) { rb_free(query); return NULL; } aftype = GET_SS_FAMILY(&query->addr); if(aftype == AF_INET) query->type = QUERY_PTR_A; else if(aftype == AF_INET6) query->type = QUERY_PTR_AAAA; else { rb_free(query); return NULL; } query->id = query_count++; query->callback = callback; query->data = data; query->query.ptr = query; query->query.callback = handle_lookup_hostname_reply; gethost_byaddr(&query->addr, &query->query); return query; }
/* A bit different from ircd... you just get a dns_query object. * * It gets freed whenever the res code gets back to us. */ struct dns_query * lookup_ip(const char *host, int aftype, DNSCB callback, void *data) { struct dns_query *query = rb_malloc(sizeof(struct dns_query)); int g_type; if(aftype == AF_INET) { query->type = QUERY_A; g_type = T_A; } else if(aftype == AF_INET6) { query->type = QUERY_AAAA; g_type = T_AAAA; } else { rb_free(query); return NULL; } query->id = query_count++; query->callback = callback; query->data = data; query->query.ptr = query; query->query.callback = handle_lookup_ip_reply; gethost_byname_type(host, &query->query, g_type); return query; }
/* * Warning: returns a dynamically allocated buffer, the user MUST * use free() / rb_free() if the function returns 1 */ static int get_res_nt(HKEY hKey, const char *subkey, char **obuf) { /* Test for the size we need */ DWORD size = 0; int result; result = RegQueryValueEx(hKey, subkey, 0, NULL, NULL, &size); if((result != ERROR_SUCCESS && result != ERROR_MORE_DATA) || !size) return 0; *obuf = rb_malloc(size + 1); if(!*obuf) return 0; if(RegQueryValueEx(hKey, subkey, 0, NULL, (LPBYTE) * obuf, &size) != ERROR_SUCCESS) { rb_free(*obuf); return 0; } if(size == 1) { rb_free(*obuf); return 0; } return 1; }
char *rb_zstring_to_c_alloc(rb_zstring_t *zs) { char *p; p = rb_malloc(zs->len+1); memcpy(p, zs->data, zs->len); return p; }
static void resolve_host(char **parv) { struct dns_request *req; char *requestid = parv[1]; char *iptype = parv[2]; char *rec = parv[3]; int flags; req = rb_malloc(sizeof(struct dns_request)); strcpy(req->reqid, requestid); req->revfwd = REQFWD; req->reqtype = FWDHOST; switch (*iptype) { case 6: flags = T_AAAA; break; default: flags = T_A; break; } req->query.ptr = req; req->query.callback = send_answer; gethost_byname_type(rec, &req->query, flags); }
static int rb_epoll_sched_event_signalfd(struct ev_entry *event, int when) { timer_t *id; struct sigevent ev; struct itimerspec ts; memset(&ev, 0, sizeof(ev)); event->comm_ptr = rb_malloc(sizeof(timer_t)); id = event->comm_ptr; ev.sigev_notify = SIGEV_SIGNAL; ev.sigev_signo = RTSIGNAL; ev.sigev_value.sival_ptr = event; if(timer_create(CLOCK_REALTIME, &ev, id) < 0) { rb_lib_log("timer_create: %s\n", strerror(errno)); return 0; } memset(&ts, 0, sizeof(ts)); ts.it_value.tv_sec = when; ts.it_value.tv_nsec = 0; if(event->frequency != 0) ts.it_interval = ts.it_value; if(timer_settime(*id, 0, &ts, NULL) < 0) { rb_lib_log("timer_settime: %s\n", strerror(errno)); return 0; } return 1; }
void rb_ssl_accept_setup(rb_fde_t *F, rb_fde_t *new_F, struct sockaddr *st, rb_socklen_t addrlen) { if(new_F->sctx == NULL) return; new_F->type |= RB_FD_SSL; new_F->ssl = SSL_new(new_F->sctx->ssl_ctx); if(new_F->ssl == NULL) { new_F->sslerr.ssl_errno = get_last_err(); rb_lib_log("rb_ssl_accept_setup: SSL_new() fails: %s", ERR_error_string(new_F->sslerr.ssl_errno, NULL)); new_F->accept->callback(new_F, RB_ERROR_SSL, NULL, 0, new_F->accept->data); return; } new_F->accept = rb_malloc(sizeof(struct acceptdata)); new_F->accept->callback = F->accept->callback; new_F->accept->data = F->accept->data; rb_settimeout(new_F, 10, rb_ssl_timeout, NULL); memcpy(&new_F->accept->S, st, addrlen); new_F->accept->addrlen = addrlen; SSL_set_fd((SSL *) new_F->ssl, rb_get_fd(new_F)); rb_setup_ssl_cb(new_F); rb_ssl_accept_common(new_F); }
static void rb_ssl_tryconn(rb_fde_t *F, int status, void *data) { struct ssl_connect *sconn = data; if (status != RB_OK) { rb_ssl_connect_realcb(F, status, sconn); return; } F->type |= RB_FD_SSL; rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn); F->ssl = rb_malloc(sizeof(gnutls_session_t)); gnutls_init(F->ssl, GNUTLS_CLIENT); gnutls_set_default_priority(SSL_P(F)); gnutls_dh_set_prime_bits(SSL_P(F), 1024); gnutls_transport_set_ptr(SSL_P(F), (gnutls_transport_ptr_t) (long int)F->fd); if (do_ssl_handshake(F, rb_ssl_tryconn_cb)) { rb_ssl_connect_realcb(F, RB_OK, sconn); } }
void rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout) { if(new_F->sctx == NULL) return; new_F->type |= RB_FD_SSL; new_F->ssl = SSL_new(new_F->sctx->ssl_ctx); if(new_F->ssl == NULL) { new_F->sslerr.ssl_errno = get_last_err(); rb_lib_log("rb_ssl_start_accepted: SSL_new() fails: %s", ERR_error_string(new_F->sslerr.ssl_errno, NULL)); cb(new_F, RB_ERROR_SSL, NULL, 0, data); return; } new_F->accept = rb_malloc(sizeof(struct acceptdata)); new_F->accept->callback = cb; new_F->accept->data = data; rb_settimeout(new_F, timeout, rb_ssl_timeout, NULL); new_F->accept->addrlen = 0; SSL_set_fd((SSL *) new_F->ssl, rb_get_fd(new_F)); rb_setup_ssl_cb(new_F); rb_ssl_accept_common(new_F); }
static struct scache_entry * find_or_add(const char *name) { int hash_index; struct scache_entry *ptr; ptr = scache_hash[hash_index = sc_hash(name)]; for (; ptr; ptr = ptr->next) { if(!irccmp(ptr->name, name)) return ptr; } ptr = (struct scache_entry *) rb_malloc(sizeof(struct scache_entry)); s_assert(0 != ptr); rb_strlcpy(ptr->name, name, sizeof(ptr->name)); ptr->info[0] = '\0'; ptr->flags = 0; ptr->known_since = rb_current_time(); ptr->last_connect = 0; ptr->last_split = 0; ptr->next = scache_hash[hash_index]; scache_hash[hash_index] = ptr; return ptr; }
/* * rb_init_netio * * This is a needed exported function which will be called to initialise * the network loop code. */ int rb_init_netio_kqueue(void) { kq = kqueue(); if(kq < 0) { return errno; } kqmax = getdtablesize(); kqlst = rb_malloc(sizeof(struct kevent) * kqmax); kqout = rb_malloc(sizeof(struct kevent) * kqmax); rb_open(kq, RB_FD_UNKNOWN, "kqueue fd"); zero_timespec.tv_sec = 0; zero_timespec.tv_nsec = 0; return 0; }
/* * rb_init_netio * * This is a needed exported function which will be called to initialise * the network loop code. */ int rb_init_netio_epoll(void) { can_do_event = 0; /* shut up gcc */ can_do_timerfd = 0; ep_info = rb_malloc(sizeof(struct epoll_info)); ep_info->pfd_size = getdtablesize(); ep_info->ep = epoll_create(ep_info->pfd_size); if(ep_info->ep < 0) { return -1; } rb_open(ep_info->ep, RB_FD_UNKNOWN, "epoll file descriptor"); ep_info->pfd = rb_malloc(sizeof(struct epoll_event) * ep_info->pfd_size); return 0; }
/* setup all the stuff a new child needs */ rb_helper * rb_helper_child(rb_helper_cb * read_cb, rb_helper_cb * error_cb, log_cb * ilog, restart_cb * irestart, die_cb * idie, size_t lb_heap_size, size_t dh_size, size_t fd_heap_size) { rb_helper *helper; int maxfd, x = 0; int ifd, ofd; char *tifd, *tofd, *tmaxfd; tifd = getenv("IFD"); tofd = getenv("OFD"); tmaxfd = getenv("MAXFD"); if(tifd == NULL || tofd == NULL || tmaxfd == NULL) return NULL; helper = rb_malloc(sizeof(rb_helper)); ifd = (int)strtol(tifd, NULL, 10); ofd = (int)strtol(tofd, NULL, 10); maxfd = (int)strtol(tmaxfd, NULL, 10); #ifndef _WIN32 for(x = 0; x < maxfd; x++) { if(x != ifd && x != ofd) close(x); } x = open("/dev/null", O_RDWR); if(ifd != 0 && ofd != 0) dup2(x, 0); if(ifd != 1 && ofd != 1) dup2(x, 1); if(ifd != 2 && ofd != 2) dup2(x, 2); if(x > 2) /* don't undo what we just did */ close(x); #else (void) x; /* shut gcc up */ #endif rb_lib_init(ilog, irestart, idie, 0, maxfd, dh_size, fd_heap_size); rb_linebuf_init(lb_heap_size); rb_linebuf_newbuf(&helper->sendq); rb_linebuf_newbuf(&helper->recvq); helper->ifd = rb_open(ifd, RB_FD_PIPE, "incoming connection"); helper->ofd = rb_open(ofd, RB_FD_PIPE, "outgoing connection"); rb_set_nb(helper->ifd); rb_set_nb(helper->ofd); helper->read_cb = read_cb; helper->error_cb = error_cb; return helper; }
rb_ssl_ctx * rb_setup_ssl_client(const char *ssl_cipher_list, const char *cert, const char *keyfile) { int ret; rb_ssl_ctx *sctx; sctx = rb_malloc(sizeof(rb_ssl_ctx)); mbedtls_ssl_config_init(&sctx->config); if ((ret = mbedtls_ssl_config_defaults(&sctx->config, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { rb_lib_log("rb_init_ssl: unable to initialize default SSL parameters for client context: -0x%x", -ret); return 0; } mbedtls_ssl_conf_rng(&sctx->config, mbedtls_ctr_drbg_random, &ctr_drbg); mbedtls_ssl_conf_authmode(&sctx->config, MBEDTLS_SSL_VERIFY_NONE); if(cert != NULL && keyfile != NULL) { mbedtls_x509_crt_init(&sctx->x509); ret = mbedtls_x509_crt_parse_file(&sctx->x509, cert); if (ret != 0) { rb_lib_log("rb_setup_ssl_client: failed to parse certificate '%s': -0x%x", cert, -ret); return 0; } mbedtls_pk_init(&sctx->serv_pk); ret = mbedtls_pk_parse_keyfile(&sctx->serv_pk, keyfile, NULL); if (ret != 0) { rb_lib_log("rb_setup_ssl_client: failed to parse private key '%s': -0x%x", keyfile, -ret); return 0; } if (&sctx->x509.next) mbedtls_ssl_conf_ca_chain(&sctx->config, sctx->x509.next, NULL); if ((ret = mbedtls_ssl_conf_own_cert(&sctx->config, &sctx->x509, &sctx->serv_pk)) != 0) { rb_lib_log("rb_setup_ssl_client: failed to set up own certificate: -0x%x", -ret); return 0; } } return sctx; }
size_t rb_zstring_serialized(rb_zstring_t *zs, void **buf, size_t *buflen) { uint8_t *p; size_t alloclen = sizeof(uint16_t) + zs->len; p = rb_malloc(sizeof(alloclen)); memcpy(p, &zs->len, sizeof(uint16_t)); p += sizeof(uint16_t); memcpy(p, zs->data, zs->len); return alloclen; }
static struct Listener * make_listener(struct rb_sockaddr_storage *addr) { struct Listener *listener = (struct Listener *) rb_malloc(sizeof(struct Listener)); s_assert(0 != listener); listener->name = me.name; listener->F = NULL; memcpy(&listener->addr, addr, sizeof(struct rb_sockaddr_storage)); listener->next = NULL; return listener; }
/* * rb_init_netio * * This is a needed exported function which will be called to initialise * the network loop code. */ int rb_init_netio_poll(void) { int fd; pollfd_list.pollfds = rb_malloc(rb_getmaxconnect() * (sizeof(struct pollfd))); pollfd_list.allocated = rb_getmaxconnect(); for(fd = 0; fd < rb_getmaxconnect(); fd++) { pollfd_list.pollfds[fd].fd = -1; } pollfd_list.maxindex = 0; return 0; }
void rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout) { struct ssl_connect *sconn; if(F == NULL) return; sconn = rb_malloc(sizeof(struct ssl_connect)); sconn->data = data; sconn->callback = callback; sconn->timeout = timeout; F->connect = rb_malloc(sizeof(struct conndata)); F->connect->callback = callback; F->connect->data = data; F->type |= RB_FD_SSL; F->ssl = rb_malloc(sizeof(mbedtls_ssl_context)); rb_ssl_setup_client_context(F); rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn); do_ssl_handshake(F, rb_ssl_tryconn_cb, (void *)sconn); }
/* * rb_init_netio * * This is a needed exported function which will be called to initialise * the network loop code. */ int rb_init_netio_devpoll(void) { dpfd = open("/dev/poll", O_RDWR); if(dpfd < 0) { return errno; } maxfd = getdtablesize() - 2; /* This makes more sense than HARD_FDLIMIT */ fdmask = rb_malloc(sizeof(fdmask) * maxfd + 1); rb_open(dpfd, RB_FD_UNKNOWN, "/dev/poll file descriptor"); return 0; }
/************************************************************************** * Create a red-black tree node; used internally by the red-black tree. **************************************************************************/ RedBlackNode* RedBlackNode_create(const float k, TrackRecord* p_val, RedBlackNode* p_p, color_t c) { RedBlackNode* p_rv = (RedBlackNode*) rb_malloc(); p_rv->p_up = p_p; p_rv->p_left = p_rv->p_right = NULL; p_rv->color = c; p_rv->key = k; LinkList_init(&p_rv->valList); LinkList_append(&(p_rv->valList), p_val); return p_rv; }
void rb_connect_tcp_ssl(rb_fde_t *F, struct sockaddr *dest, struct sockaddr *clocal, rb_socklen_t socklen, CNCB * callback, void *data, int timeout) { struct ssl_connect *sconn; if(F == NULL) return; sconn = rb_malloc(sizeof(struct ssl_connect)); sconn->data = data; sconn->callback = callback; sconn->timeout = timeout; rb_connect_tcp(F, dest, clocal, socklen, rb_ssl_tryconn, sconn, timeout); }
void rb_ssl_accept_setup(rb_fde_t *F, rb_fde_t *new_F, struct sockaddr *st, rb_socklen_t addrlen) { new_F->type |= RB_FD_SSL; new_F->ssl = rb_malloc(sizeof(mbedtls_ssl_context)); new_F->accept = rb_malloc(sizeof(struct acceptdata)); new_F->accept->callback = F->accept->callback; new_F->accept->data = F->accept->data; rb_settimeout(new_F, 10, rb_ssl_timeout, NULL); memcpy(&new_F->accept->S, st, addrlen); new_F->accept->addrlen = addrlen; rb_ssl_setup_srv_context(new_F); if(do_ssl_handshake(F, rb_ssl_tryaccept, NULL)) { struct acceptdata *ad = F->accept; F->accept = NULL; ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data); rb_free(ad); } }
static gnutls_datum_t * rb_load_file_into_datum_t(const char *file) { FILE *f; gnutls_datum_t *datum; struct stat fileinfo; if ((f = fopen(file, "r")) == NULL) return NULL; if (fstat(fileno(f), &fileinfo)) return NULL; datum = rb_malloc(sizeof(gnutls_datum_t)); if (fileinfo.st_size > 131072) /* deal with retards */ datum->size = 131072; else datum->size = fileinfo.st_size; datum->data = rb_malloc(datum->size + 1); fread(datum->data, datum->size, 1, f); fclose(f); return datum; }
int rb_init_netio_ports(void) { if((pe = port_create()) < 0) { return errno; } pemax = getdtablesize(); pelst = rb_malloc(sizeof(port_event_t) * pemax); zero_timespec.tv_sec = 0; zero_timespec.tv_nsec = 0; rb_set_time(); return 0; }
rb_ssl_ctx * rb_setup_ssl_client(const char *ssl_cipher_list, const char *cert, const char *keyfile) { /* this needs to have more customizations etc...client certificates perhaps as well */ rb_ssl_ctx *sctx; sctx = rb_malloc(sizeof(rb_ssl_ctx)); sctx->refcount = 1; sctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_options(sctx->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION); if(sctx->ssl_ctx == NULL) { rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL client context: %s", ERR_error_string(ERR_get_error(), NULL)); rb_free(sctx); return NULL; } if(ssl_cipher_list != NULL) { if(!SSL_CTX_set_cipher_list(sctx->ssl_ctx, ssl_cipher_list)) { rb_lib_log("rb_setup_ssl_client: Error setting ssl_cipher_list=\"%s\": %s", ssl_cipher_list, ERR_error_string(ERR_get_error(), NULL)); goto cleanup; } } if(cert != NULL && keyfile != NULL) { if(!SSL_CTX_use_PrivateKey_file(sctx->ssl_ctx, keyfile, SSL_FILETYPE_PEM)) { rb_lib_log("rb_setup_ssl_client: Error loading keyfile :%s", ERR_error_string(ERR_get_error(), NULL)); goto cleanup; } if(!SSL_CTX_use_certificate_chain_file(sctx->ssl_ctx, cert)) { rb_lib_log("rb_setup_ssl_client: Error loading certificate :%s", ERR_error_string(ERR_get_error(), NULL)); goto cleanup; } } return sctx; cleanup: SSL_CTX_free(sctx->ssl_ctx); rb_free(sctx); return NULL; }
size_t rb_zstring_deserialize(rb_zstring_t *zs, void *buf) { uint8_t *p = (uint8_t *)buf; memcpy(&zs->len, p, sizeof(uint16_t)); p += sizeof(uint16_t); if(zs->len == 0) { zs->data = NULL; return sizeof(uint16_t); } zs->data = rb_malloc(zs->len); memcpy(zs->data, p, zs->len); return zs->len + sizeof(uint16_t); }