static struct event_pool * event_pool_new_poll (int count, int eventthreadcount) { struct event_pool *event_pool = NULL; int ret = -1; event_pool = GF_CALLOC (1, sizeof (*event_pool), gf_common_mt_event_pool); if (!event_pool) return NULL; event_pool->count = count; event_pool->reg = GF_CALLOC (event_pool->count, sizeof (*event_pool->reg), gf_common_mt_reg); if (!event_pool->reg) { GF_FREE (event_pool); return NULL; } pthread_mutex_init (&event_pool->mutex, NULL); ret = pipe (event_pool->breaker); if (ret == -1) { gf_msg ("poll", GF_LOG_ERROR, errno, LG_MSG_PIPE_CREATE_FAILED, "pipe creation failed"); GF_FREE (event_pool->reg); GF_FREE (event_pool); return NULL; } ret = fcntl (event_pool->breaker[0], F_SETFL, O_NONBLOCK); if (ret == -1) { gf_msg ("poll", GF_LOG_ERROR, errno, LG_MSG_SET_PIPE_FAILED, "could not set pipe to non blocking mode"); close (event_pool->breaker[0]); close (event_pool->breaker[1]); event_pool->breaker[0] = event_pool->breaker[1] = -1; GF_FREE (event_pool->reg); GF_FREE (event_pool); return NULL; } ret = fcntl (event_pool->breaker[1], F_SETFL, O_NONBLOCK); if (ret == -1) { gf_msg ("poll", GF_LOG_ERROR, errno, LG_MSG_SET_PIPE_FAILED, "could not set pipe to non blocking mode"); close (event_pool->breaker[0]); close (event_pool->breaker[1]); event_pool->breaker[0] = event_pool->breaker[1] = -1; GF_FREE (event_pool->reg); GF_FREE (event_pool); return NULL; } ret = event_register_poll (event_pool, event_pool->breaker[0], __flush_fd, NULL, 1, 0); if (ret == -1) { gf_msg ("poll", GF_LOG_ERROR, 0, LG_MSG_REGISTER_PIPE_FAILED, "could not register pipe fd with poll event loop"); close (event_pool->breaker[0]); close (event_pool->breaker[1]); event_pool->breaker[0] = event_pool->breaker[1] = -1; GF_FREE (event_pool->reg); GF_FREE (event_pool); return NULL; } if (eventthreadcount > 1) { gf_msg ("poll", GF_LOG_INFO, 0, LG_MSG_POLL_IGNORE_MULTIPLE_THREADS, "Currently poll " "does not use multiple event processing threads, " "thread count (%d) ignored", eventthreadcount); } return event_pool; }
pid_t pidinfo(pid_t pid, char **name) { char buf[NAME_MAX * 2] = { 0, }; FILE *f = NULL; char path[PATH_MAX] = { 0, }; char *p = NULL; int ret = 0; snprintf(path, sizeof path, PROC "/%d/status", pid); f = fopen(path, "r"); if (!f) return -1; if (name) *name = NULL; for (;;) { size_t len; memset(buf, 0, sizeof(buf)); if (fgets(buf, sizeof(buf), f) == NULL || (len = strlen(buf)) == 0 || buf[len - 1] != '\n') { pid = -1; goto out; } buf[len - 1] = '\0'; if (name && !*name) { p = strtail(buf, "Name:"); if (p) { while (isspace(*++p)) ; *name = gf_strdup(p); if (!*name) { pid = -2; goto out; } continue; } } p = strtail(buf, "PPid:"); if (p) break; } while (isspace(*++p)) ; ret = gf_string2int(p, &pid); if (ret == -1) pid = -1; out: fclose(f); if (pid == -1 && name && *name) GF_FREE(*name); if (pid == -2) fprintf(stderr, "out of memory\n"); return pid; }
static void readline_destructor (void *ptr) { GF_FREE (ptr); }
auth_result_t gf_auth (dict_t *input_params, dict_t *config_params) { auth_result_t result = AUTH_DONT_CARE; int ret = 0; char *name = NULL; char *searchstr = NULL; peer_info_t *peer_info = NULL; data_t *peer_info_data = NULL; data_t *allow_addr = NULL; data_t *reject_addr = NULL; char *addr_str = NULL; char *tmp = NULL; char *addr_cpy = NULL; char *service = NULL; uint16_t peer_port = 0; char is_inet_sdp = 0; char negate = 0; char match = 0; char peer_addr[UNIX_PATH_MAX]; char *type = NULL; gf_boolean_t allow_insecure = _gf_false; name = data_to_str (dict_get (input_params, "remote-subvolume")); if (!name) { gf_log ("authenticate/addr", GF_LOG_DEBUG, "remote-subvolume not specified"); goto out; } ret = gf_asprintf (&searchstr, "auth.addr.%s.allow", name); if (-1 == ret) { gf_log ("auth/addr", GF_LOG_DEBUG, "asprintf failed while setting search string"); goto out; } allow_addr = dict_get (config_params, searchstr); GF_FREE (searchstr); ret = gf_asprintf (&searchstr, "auth.addr.%s.reject", name); if (-1 == ret) { gf_log ("auth/addr", GF_LOG_ERROR, "asprintf failed while setting search string"); goto out; } reject_addr = dict_get (config_params, searchstr); GF_FREE (searchstr); if (!allow_addr) { /* TODO: backword compatibility */ ret = gf_asprintf (&searchstr, "auth.ip.%s.allow", name); if (-1 == ret) { gf_log ("auth/addr", GF_LOG_ERROR, "asprintf failed while setting search string"); goto out; } allow_addr = dict_get (config_params, searchstr); GF_FREE (searchstr); } if (!(allow_addr || reject_addr)) { gf_log ("auth/addr", GF_LOG_DEBUG, "none of the options auth.addr.%s.allow or " "auth.addr.%s.reject specified, returning auth_dont_care", name, name); goto out; } peer_info_data = dict_get (input_params, "peer-info"); if (!peer_info_data) { gf_log ("auth/addr", GF_LOG_ERROR, "peer-info not present"); goto out; } peer_info = data_to_ptr (peer_info_data); switch (((struct sockaddr *) &peer_info->sockaddr)->sa_family) { case AF_INET_SDP: is_inet_sdp = 1; ((struct sockaddr *) &peer_info->sockaddr)->sa_family = AF_INET; case AF_INET: case AF_INET6: { strcpy (peer_addr, peer_info->identifier); service = strrchr (peer_addr, ':'); *service = '\0'; service ++; if (is_inet_sdp) { ((struct sockaddr *) &peer_info->sockaddr)->sa_family = AF_INET_SDP; } ret = dict_get_str (config_params, "rpc-auth-allow-insecure", &type); if (ret == 0) { ret = gf_string2boolean (type, &allow_insecure); if (ret < 0) { gf_log ("auth/addr", GF_LOG_WARNING, "rpc-auth-allow-insecure option %s " "is not a valid bool option", type); goto out; } } peer_port = atoi (service); if (peer_port >= PRIVILEGED_PORT_CEILING && !allow_insecure) { gf_log ("auth/addr", GF_LOG_ERROR, "client is bound to port %d which is not privileged", peer_port); goto out; } break; case AF_UNIX: strcpy (peer_addr, peer_info->identifier); break; default: gf_log ("authenticate/addr", GF_LOG_ERROR, "unknown address family %d", ((struct sockaddr *) &peer_info->sockaddr)->sa_family); goto out; } } if (reject_addr) { addr_cpy = gf_strdup (reject_addr->data); if (!addr_cpy) goto out; addr_str = strtok_r (addr_cpy, ADDR_DELIMITER, &tmp); while (addr_str) { gf_log (name, GF_LOG_DEBUG, "rejected = \"%s\", received addr = \"%s\"", addr_str, peer_addr); if (addr_str[0] == '!') { negate = 1; addr_str++; } match = fnmatch (addr_str, peer_addr, 0); if (negate ? match : !match) { result = AUTH_REJECT; goto out; } addr_str = strtok_r (NULL, ADDR_DELIMITER, &tmp); } GF_FREE (addr_cpy); } if (allow_addr) { addr_cpy = gf_strdup (allow_addr->data); if (!addr_cpy) goto out; addr_str = strtok_r (addr_cpy, ADDR_DELIMITER, &tmp); while (addr_str) { gf_log (name, GF_LOG_DEBUG, "allowed = \"%s\", received addr = \"%s\"", addr_str, peer_addr); if (addr_str[0] == '!') { negate = 1; addr_str++; } match = fnmatch (addr_str, peer_addr, 0); if (negate ? match : !match) { result = AUTH_ACCEPT; goto out; } addr_str = strtok_r (NULL, ADDR_DELIMITER, &tmp); } } out: if (addr_cpy) GF_FREE (addr_cpy); return result; }
int32_t gf_resolve_ip6 (const char *hostname, uint16_t port, int family, void **dnscache, struct addrinfo **addr_info) { int32_t ret = 0; struct addrinfo hints; struct dnscache6 *cache = NULL; char service[NI_MAXSERV], host[NI_MAXHOST]; if (!hostname) { gf_log_callingfn ("resolver", GF_LOG_WARNING, "hostname is NULL"); return -1; } if (!*dnscache) { *dnscache = GF_CALLOC (1, sizeof (struct dnscache6), gf_common_mt_dnscache6); if (!*dnscache) return -1; } cache = *dnscache; if (cache->first && !cache->next) { freeaddrinfo(cache->first); cache->first = cache->next = NULL; gf_log ("resolver", GF_LOG_TRACE, "flushing DNS cache"); } if (!cache->first) { char *port_str = NULL; gf_log ("resolver", GF_LOG_TRACE, "DNS cache not present, freshly probing hostname: %s", hostname); memset(&hints, 0, sizeof(hints)); hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_ADDRCONFIG; ret = gf_asprintf (&port_str, "%d", port); if (-1 == ret) { gf_log ("resolver", GF_LOG_ERROR, "asprintf failed"); return -1; } if ((ret = getaddrinfo(hostname, port_str, &hints, &cache->first)) != 0) { gf_log ("resolver", GF_LOG_ERROR, "getaddrinfo failed (%s)", gai_strerror (ret)); GF_FREE (*dnscache); *dnscache = NULL; GF_FREE (port_str); return -1; } GF_FREE (port_str); cache->next = cache->first; } if (cache->next) { ret = getnameinfo((struct sockaddr *)cache->next->ai_addr, cache->next->ai_addrlen, host, sizeof (host), service, sizeof (service), NI_NUMERICHOST); if (ret != 0) { gf_log ("resolver", GF_LOG_ERROR, "getnameinfo failed (%s)", gai_strerror (ret)); goto err; } gf_log ("resolver", GF_LOG_DEBUG, "returning ip-%s (port-%s) for hostname: %s and port: %d", host, service, hostname, port); *addr_info = cache->next; } if (cache->next) cache->next = cache->next->ai_next; if (cache->next) { ret = getnameinfo((struct sockaddr *)cache->next->ai_addr, cache->next->ai_addrlen, host, sizeof (host), service, sizeof (service), NI_NUMERICHOST); if (ret != 0) { gf_log ("resolver", GF_LOG_ERROR, "getnameinfo failed (%s)", gai_strerror (ret)); goto err; } gf_log ("resolver", GF_LOG_DEBUG, "next DNS query will return: ip-%s port-%s", host, service); } return 0; err: freeaddrinfo (cache->first); cache->first = cache->next = NULL; GF_FREE (cache); *dnscache = NULL; return -1; }
transport_t * transport_load (dict_t *options, xlator_t *xl) { struct transport *trans = NULL, *return_trans = NULL; char *name = NULL; void *handle = NULL; char *type = NULL; char str[] = "ERROR"; int32_t ret = -1; int8_t is_tcp = 0, is_unix = 0, is_ibsdp = 0; volume_opt_list_t *vol_opt = NULL; GF_VALIDATE_OR_GOTO("transport", options, fail); GF_VALIDATE_OR_GOTO("transport", xl, fail); trans = GF_CALLOC (1, sizeof (struct transport), gf_common_mt_transport); GF_VALIDATE_OR_GOTO("transport", trans, fail); trans->xl = xl; type = str; /* Backward compatibility */ ret = dict_get_str (options, "transport-type", &type); if (ret < 0) { ret = dict_set_str (options, "transport-type", "socket"); if (ret < 0) gf_log ("dict", GF_LOG_DEBUG, "setting transport-type failed"); gf_log ("transport", GF_LOG_WARNING, "missing 'option transport-type'. defaulting to " "\"socket\""); } else { { /* Backword compatibility to handle * /client, * * /server. */ char *tmp = strchr (type, '/'); if (tmp) *tmp = '\0'; } is_tcp = strcmp (type, "tcp"); is_unix = strcmp (type, "unix"); is_ibsdp = strcmp (type, "ib-sdp"); if ((is_tcp == 0) || (is_unix == 0) || (is_ibsdp == 0)) { if (is_unix == 0) ret = dict_set_str (options, "transport.address-family", "unix"); if (is_ibsdp == 0) ret = dict_set_str (options, "transport.address-family", "inet-sdp"); if (ret < 0) gf_log ("dict", GF_LOG_DEBUG, "setting address-family failed"); ret = dict_set_str (options, "transport-type", "socket"); if (ret < 0) gf_log ("dict", GF_LOG_DEBUG, "setting transport-type failed"); } } ret = dict_get_str (options, "transport-type", &type); if (ret < 0) { GF_FREE (trans); gf_log ("transport", GF_LOG_ERROR, "'option transport-type <xx>' missing in volume '%s'", xl->name); goto fail; } ret = gf_asprintf (&name, "%s/%s.so", TRANSPORTDIR, type); if (-1 == ret) { gf_log ("transport", GF_LOG_ERROR, "asprintf failed"); goto fail; } gf_log ("transport", GF_LOG_DEBUG, "attempt to load file %s", name); handle = dlopen (name, RTLD_NOW|RTLD_GLOBAL); if (handle == NULL) { gf_log ("transport", GF_LOG_ERROR, "%s", dlerror ()); gf_log ("transport", GF_LOG_ERROR, "volume '%s': transport-type '%s' is not valid or " "not found on this machine", xl->name, type); GF_FREE (name); GF_FREE (trans); goto fail; } GF_FREE (name); trans->ops = dlsym (handle, "tops"); if (trans->ops == NULL) { gf_log ("transport", GF_LOG_ERROR, "dlsym (transport_ops) on %s", dlerror ()); GF_FREE (trans); goto fail; } trans->init = dlsym (handle, "init"); if (trans->init == NULL) { gf_log ("transport", GF_LOG_ERROR, "dlsym (gf_transport_init) on %s", dlerror ()); GF_FREE (trans); goto fail; } trans->fini = dlsym (handle, "fini"); if (trans->fini == NULL) { gf_log ("transport", GF_LOG_ERROR, "dlsym (gf_transport_fini) on %s", dlerror ()); GF_FREE (trans); goto fail; } vol_opt = GF_CALLOC (1, sizeof (volume_opt_list_t), gf_common_mt_volume_opt_list_t); vol_opt->given_opt = dlsym (handle, "options"); if (vol_opt->given_opt == NULL) { gf_log ("transport", GF_LOG_DEBUG, "volume option validation not specified"); } else { list_add_tail (&vol_opt->list, &xl->volume_options); if (-1 == validate_xlator_volume_options (xl, vol_opt->given_opt)) { gf_log ("transport", GF_LOG_ERROR, "volume option validation failed"); GF_FREE (trans); goto fail; } } ret = trans->init (trans); if (ret != 0) { gf_log ("transport", GF_LOG_ERROR, "'%s' initialization failed", type); GF_FREE (trans); goto fail; } pthread_mutex_init (&trans->lock, NULL); return_trans = trans; fail: return return_trans; }
static int glusterd_handle_mgmt_v3_unlock_fn (rpcsvc_request_t *req) { gd1_mgmt_v3_unlock_req lock_req = {{0},}; int32_t ret = -1; glusterd_op_lock_ctx_t *ctx = NULL; glusterd_peerinfo_t *peerinfo = NULL; xlator_t *this = NULL; gf_boolean_t is_synctasked = _gf_false; gf_boolean_t free_ctx = _gf_false; this = THIS; GF_ASSERT (this); GF_ASSERT (req); ret = xdr_to_generic (req->msg[0], &lock_req, (xdrproc_t)xdr_gd1_mgmt_v3_unlock_req); if (ret < 0) { gf_log (this->name, GF_LOG_ERROR, "Failed to decode unlock " "request received from peer"); req->rpc_err = GARBAGE_ARGS; goto out; } gf_log (this->name, GF_LOG_DEBUG, "Received volume unlock req " "from uuid: %s", uuid_utoa (lock_req.uuid)); if (glusterd_friend_find_by_uuid (lock_req.uuid, &peerinfo)) { gf_log (this->name, GF_LOG_WARNING, "%s doesn't " "belong to the cluster. Ignoring request.", uuid_utoa (lock_req.uuid)); ret = -1; goto out; } ctx = GF_CALLOC (1, sizeof (*ctx), gf_gld_mt_op_lock_ctx_t); if (!ctx) { ret = -1; goto out; } uuid_copy (ctx->uuid, lock_req.uuid); ctx->req = req; ctx->dict = dict_new (); if (!ctx->dict) { ret = -1; goto out; } ret = dict_unserialize (lock_req.dict.dict_val, lock_req.dict.dict_len, &ctx->dict); if (ret) { gf_log (this->name, GF_LOG_WARNING, "failed to unserialize the dictionary"); goto out; } is_synctasked = dict_get_str_boolean (ctx->dict, "is_synctasked", _gf_false); if (is_synctasked) { ret = glusterd_syctasked_mgmt_v3_unlock (req, &lock_req, ctx); /* The above function does not take ownership of ctx. * Therefore we need to free the ctx explicitly. */ free_ctx = _gf_true; } else { ret = glusterd_op_state_machine_mgmt_v3_unlock (req, &lock_req, ctx); } out: if (ret || free_ctx) { if (ctx->dict) dict_unref (ctx->dict); if (ctx) GF_FREE (ctx); } free (lock_req.dict.dict_val); gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); return ret; }
int32_t gf_store_retrieve_value (gf_store_handle_t *handle, char *key, char **value) { int32_t ret = -1; char *scan_str = NULL; char *iter_key = NULL; char *iter_val = NULL; char *free_str = NULL; struct stat st = {0,}; gf_store_op_errno_t store_errno = GD_STORE_SUCCESS; GF_ASSERT (handle); if (handle->locked == F_ULOCK) /* no locking is used handle->fd gets closed() after usage */ handle->fd = open (handle->path, O_RDWR); else /* handle->fd is valid already, kept open for lockf() */ lseek (handle->fd, 0, SEEK_SET); if (handle->fd == -1) { gf_log ("", GF_LOG_ERROR, "Unable to open file %s errno: %s", handle->path, strerror (errno)); goto out; } if (!handle->read) handle->read = fdopen (dup(handle->fd), "r"); else fseek (handle->read, 0, SEEK_SET); if (!handle->read) { gf_log ("", GF_LOG_ERROR, "Unable to open file %s errno: %s", handle->path, strerror (errno)); goto out; } ret = fstat (handle->fd, &st); if (ret < 0) { gf_log ("", GF_LOG_WARNING, "stat on file %s failed", handle->path); ret = -1; store_errno = GD_STORE_STAT_FAILED; goto out; } scan_str = GF_CALLOC (1, st.st_size, gf_common_mt_char); if (scan_str == NULL) { ret = -1; store_errno = GD_STORE_ENOMEM; goto out; } free_str = scan_str; do { ret = gf_store_read_and_tokenize (handle->read, scan_str, &iter_key, &iter_val, &store_errno); if (ret < 0) { gf_log ("", GF_LOG_TRACE, "error while reading key " "'%s': %s", key, gf_store_strerror (store_errno)); goto out; } gf_log ("", GF_LOG_TRACE, "key %s read", iter_key); if (!strcmp (key, iter_key)) { gf_log ("", GF_LOG_DEBUG, "key %s found", key); ret = 0; if (iter_val) *value = gf_strdup (iter_val); goto out; } } while (1); out: if (handle->read) { fclose (handle->read); handle->read = NULL; } if (handle->fd > 0 && handle->locked == F_ULOCK) { /* only invalidate handle->fd if not locked */ close (handle->fd); } GF_FREE (free_str); return ret; }
int32_t gf_store_iter_get_next (gf_store_iter_t *iter, char **key, char **value, gf_store_op_errno_t *op_errno) { int32_t ret = -1; char *scan_str = NULL; char *iter_key = NULL; char *iter_val = NULL; struct stat st = {0,}; gf_store_op_errno_t store_errno = GD_STORE_SUCCESS; GF_ASSERT (iter); GF_ASSERT (key); GF_ASSERT (value); ret = stat (iter->filepath, &st); if (ret < 0) { gf_log ("", GF_LOG_WARNING, "stat on file failed"); ret = -1; store_errno = GD_STORE_STAT_FAILED; goto out; } scan_str = GF_CALLOC (1, st.st_size, gf_common_mt_char); if (!scan_str) { ret = -1; store_errno = GD_STORE_ENOMEM; goto out; } ret = gf_store_read_and_tokenize (iter->file, scan_str, &iter_key, &iter_val, &store_errno); if (ret < 0) { goto out; } ret = gf_store_validate_key_value (iter->filepath, iter_key, iter_val, &store_errno); if (ret) goto out; *key = gf_strdup (iter_key); if (!*key) { ret = -1; store_errno = GD_STORE_ENOMEM; goto out; } *value = gf_strdup (iter_val); if (!*value) { ret = -1; store_errno = GD_STORE_ENOMEM; goto out; } ret = 0; out: GF_FREE (scan_str); if (ret) { GF_FREE (*key); GF_FREE (*value); *key = NULL; *value = NULL; } if (op_errno) *op_errno = store_errno; gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); return ret; }
void parse_entries_and_compare (char *option_str, char *peer_addr, char *subvol, char *subdir, auth_result_t *result, auth_result_t status) { char *entry = NULL; char *entry_cpy = NULL; char *directory = NULL; char *entries = NULL; char *addr_str = NULL; char *addr = NULL; char *tmp = NULL; char *tmpdir = NULL; int ret = 0; if (!subdir) { gf_log (subvol, GF_LOG_WARNING, "subdir entry not present, not performing any operation."); goto out; } entries = gf_strdup (option_str); if (!entries) goto out; if (entries[0] != '/' && !strchr (entries, '(')) { /* Backward compatible option */ ret = compare_addr_and_update (entries, peer_addr, subvol, ",", result, status); goto out; } entry = strtok_r (entries, ENTRY_DELIMITER, &tmp); while (entry) { entry_cpy = gf_strdup (entry); if (!entry_cpy) { goto out; } directory = strtok_r (entry_cpy, "(", &tmpdir); if (directory[0] != '/') goto out; /* send second portion, after ' =' if directory matches */ if (strcmp (subdir, directory)) goto next_entry; addr_str = strtok_r (NULL, ")", &tmpdir); if (!addr_str) goto out; addr = gf_strdup (addr_str); if (!addr) goto out; gf_log (subvol, GF_LOG_INFO, "Found an entry for dir %s (%s)," " performing validation", subdir, addr); ret = compare_addr_and_update (addr, peer_addr, subvol, ADDR_DELIMITER, result, status); if (ret == 0) { break; } GF_FREE (addr); addr = NULL; next_entry: entry = strtok_r (NULL, ENTRY_DELIMITER, &tmp); GF_FREE (entry_cpy); entry_cpy = NULL; } out: GF_FREE (entries); GF_FREE (entry_cpy); GF_FREE (addr); }
int32_t gf_store_retrieve_value (gf_store_handle_t *handle, char *key, char **value) { int32_t ret = -1; char *scan_str = NULL; char *iter_key = NULL; char *iter_val = NULL; char *free_str = NULL; struct stat st = {0,}; gf_store_op_errno_t store_errno = GD_STORE_SUCCESS; GF_ASSERT (handle); handle->fd = open (handle->path, O_RDWR); if (handle->fd == -1) { gf_log ("", GF_LOG_ERROR, "Unable to open file %s errno: %s", handle->path, strerror (errno)); goto out; } if (!handle->read) handle->read = fdopen (handle->fd, "r"); if (!handle->read) { gf_log ("", GF_LOG_ERROR, "Unable to open file %s errno: %s", handle->path, strerror (errno)); goto out; } ret = fstat (handle->fd, &st); if (ret < 0) { gf_log ("", GF_LOG_WARNING, "stat on file %s failed", handle->path); ret = -1; store_errno = GD_STORE_STAT_FAILED; goto out; } scan_str = GF_CALLOC (1, st.st_size, gf_common_mt_char); if (scan_str == NULL) { ret = -1; store_errno = GD_STORE_ENOMEM; goto out; } free_str = scan_str; do { ret = gf_store_read_and_tokenize (handle->read, scan_str, &iter_key, &iter_val, &store_errno); if (ret < 0) { gf_log ("", GF_LOG_TRACE, "error while reading key " "'%s': %s", key, gf_store_strerror (store_errno)); goto out; } gf_log ("", GF_LOG_TRACE, "key %s read", iter_key); if (!strcmp (key, iter_key)) { gf_log ("", GF_LOG_DEBUG, "key %s found", key); ret = 0; if (iter_val) *value = gf_strdup (iter_val); goto out; } } while (1); out: if (handle->fd > 0) { close (handle->fd); handle->read = NULL; } GF_FREE (free_str); return ret; }
auth_result_t gf_auth (dict_t *input_params, dict_t *config_params) { auth_result_t result = AUTH_DONT_CARE; int ret = 0; char *name = NULL; char *searchstr = NULL; peer_info_t *peer_info = NULL; data_t *peer_info_data = NULL; data_t *allow_addr = NULL; data_t *reject_addr = NULL; char *service = NULL; uint16_t peer_port = 0; char peer_addr[UNIX_PATH_MAX] = {0,}; char *type = NULL; gf_boolean_t allow_insecure = _gf_false; char *subdir = NULL; name = data_to_str (dict_get (input_params, "remote-subvolume")); if (!name) { gf_log ("authenticate/addr", GF_LOG_DEBUG, "remote-subvolume not specified"); goto out; } ret = gf_asprintf (&searchstr, "auth.addr.%s.allow", name); if (-1 == ret) { gf_log ("auth/addr", GF_LOG_DEBUG, "asprintf failed while setting search string"); goto out; } allow_addr = dict_get (config_params, searchstr); GF_FREE (searchstr); ret = gf_asprintf (&searchstr, "auth.addr.%s.reject", name); if (-1 == ret) { gf_log ("auth/addr", GF_LOG_ERROR, "asprintf failed while setting search string"); goto out; } reject_addr = dict_get (config_params, searchstr); GF_FREE (searchstr); if (!allow_addr) { /* TODO: backward compatibility */ ret = gf_asprintf (&searchstr, "auth.ip.%s.allow", name); if (-1 == ret) { gf_log ("auth/addr", GF_LOG_ERROR, "asprintf failed while setting search string"); goto out; } allow_addr = dict_get (config_params, searchstr); GF_FREE (searchstr); } if (!(allow_addr || reject_addr)) { gf_log ("auth/addr", GF_LOG_DEBUG, "none of the options auth.addr.%s.allow or " "auth.addr.%s.reject specified, returning auth_dont_care", name, name); goto out; } peer_info_data = dict_get (input_params, "peer-info"); if (!peer_info_data) { gf_log ("auth/addr", GF_LOG_ERROR, "peer-info not present"); goto out; } ret = dict_get_str (input_params, "subdir-mount", &subdir); if (ret) { subdir = "/"; } peer_info = data_to_ptr (peer_info_data); switch (((struct sockaddr *) &peer_info->sockaddr)->sa_family) { case AF_INET_SDP: case AF_INET: case AF_INET6: strcpy (peer_addr, peer_info->identifier); service = strrchr (peer_addr, ':'); *service = '\0'; service++; ret = dict_get_str (config_params, "rpc-auth-allow-insecure", &type); if (ret == 0) { ret = gf_string2boolean (type, &allow_insecure); if (ret < 0) { gf_log ("auth/addr", GF_LOG_WARNING, "rpc-auth-allow-insecure option %s " "is not a valid bool option", type); goto out; } } peer_port = atoi (service); if (peer_port >= PRIVILEGED_PORT_CEILING && !allow_insecure) { gf_log ("auth/addr", GF_LOG_ERROR, "client is bound to port %d which is not privileged", peer_port); result = AUTH_REJECT; goto out; } break; case AF_UNIX: strcpy (peer_addr, peer_info->identifier); break; default: gf_log ("authenticate/addr", GF_LOG_ERROR, "unknown address family %d", ((struct sockaddr *) &peer_info->sockaddr)->sa_family); goto out; } if (reject_addr) { parse_entries_and_compare (reject_addr->data, peer_addr, name, subdir, &result, AUTH_REJECT); if (result == AUTH_REJECT) goto out; } if (allow_addr) { parse_entries_and_compare (allow_addr->data, peer_addr, name, subdir, &result, AUTH_ACCEPT); } out: return result; }
/* * Add a new list entry to the cache. If an entry for this ID already exists, * update it. */ int gid_cache_add(gid_cache_t *cache, gid_list_t *gl) { gid_list_t *agl; int bucket; int i; time_t now; if (!gl || !gl->gl_list) return -1; if (!cache->gc_max_age) return 0; LOCK(&cache->gc_lock); now = time(NULL); /* * Scan for the first free entry or one that matches this id. The id * check is added to address a bug where the cache might contain an * expired entry for this id. Since lookup occurs in LRU order and * does not reclaim entries, it will always return failure on discovery * of an expired entry. This leads to duplicate entries being added, * which still do not satisfy lookups until the expired entry (and * everything before it) is reclaimed. * * We address this through reuse of an entry already allocated to this * id, whether expired or not, since we have obviously already received * more recent data. The entry is repopulated with the new data and a new * deadline and is pushed forward to reside as the last populated entry in * the bucket. */ bucket = gl->gl_id % cache->gc_nbuckets; agl = BUCKET_START(cache->gc_cache, bucket); for (i = 0; i < AUX_GID_CACHE_ASSOC; ++i, ++agl) { if (agl->gl_id == gl->gl_id) break; if (!agl->gl_list) break; } /* * The way we allocate free entries naturally places the newest * ones at the highest indices, so evicting the lowest makes * sense, but that also means we can't just replace it with the * one that caused the eviction. That would cause us to thrash * the first entry while others remain idle. Therefore, we * need to slide the other entries down and add the new one at * the end just as if the *last* slot had been free. * * Deadline expiration is also handled here, since the oldest * expired entry will be in the first position. This does mean * the bucket can stay full of expired entries if we're idle * but, if the small amount of extra memory or scan time before * we decide to evict someone ever become issues, we could * easily add a reaper thread. */ if (i >= AUX_GID_CACHE_ASSOC) { /* cache full, evict the first (LRU) entry */ i = 0; agl = BUCKET_START(cache->gc_cache, bucket); GF_FREE(agl->gl_list); } else if (agl->gl_list) { /* evict the old entry we plan to reuse */ GF_FREE(agl->gl_list); } /* * If we have evicted an entry, slide the subsequent populated entries * back and populate the last entry. */ for (; i < AUX_GID_CACHE_ASSOC - 1; i++) { if (!agl[1].gl_list) break; agl[0] = agl[1]; agl++; } agl->gl_id = gl->gl_id; agl->gl_uid = gl->gl_uid; agl->gl_gid = gl->gl_gid; agl->gl_count = gl->gl_count; agl->gl_list = gl->gl_list; agl->gl_deadline = now + cache->gc_max_age; UNLOCK(&cache->gc_lock); return 1; }
int bd_aio_readv_complete (struct bd_aio_cb *paiocb, int res, int res2) { call_frame_t *frame = NULL; xlator_t *this = NULL; struct iobuf *iobuf = NULL; struct iatt postbuf = {0,}; int op_ret = -1; int op_errno = 0; struct iovec iov; struct iobref *iobref = NULL; off_t offset = 0; bd_attr_t *bdatt = NULL; frame = paiocb->frame; this = frame->this; iobuf = paiocb->iobuf; offset = paiocb->offset; if (res < 0) { op_ret = -1; op_errno = -res; gf_log (this->name, GF_LOG_ERROR, "readv(async) failed fd=%p,size=%lu,offset=%llu (%d/%s)", paiocb->fd, paiocb->iocb.u.c.nbytes, (unsigned long long) paiocb->offset, res, strerror (op_errno)); goto out; } bd_inode_ctx_get (paiocb->fd->inode, this, &bdatt); memcpy (&postbuf, &bdatt->iatt, sizeof (struct iatt)); op_ret = res; op_errno = 0; iobref = iobref_new (); if (!iobref) { op_ret = -1; op_errno = ENOMEM; goto out; } iobref_add (iobref, iobuf); iov.iov_base = iobuf_ptr (iobuf); iov.iov_len = op_ret; /* Hack to notify higher layers of EOF. */ if (!postbuf.ia_size || (offset + iov.iov_len) >= postbuf.ia_size) op_errno = ENOENT; out: STACK_UNWIND_STRICT (readv, frame, op_ret, op_errno, &iov, 1, &postbuf, iobref, NULL); if (iobuf) iobuf_unref (iobuf); if (iobref) iobref_unref (iobref); GF_FREE (paiocb); return 0; }
/** * __exp_line_host_parse -- Extract the hosts in the line * and call helper functions to parse * the string. * * The call chain goes like this: * * 1) __exp_line_host_parse ("/test hostip(sec=sys,rw,anonuid=0)") * 2) __exp_line_ng_host_str_parse ("hostip(sec=sys,rw,anonuid=0)"); * 3) __exp_line_opt_parse("(sec=sys,rw,anonuid=0)"); * * * @line : The line to parse * @ng_dict : Double pointer to the dict we want to * insert hosts into. * * Allocates the dict, extracts host strings from the line, * parses them into a struct export_item structure and inserts * them in the dict. * * @return: success: GF_EXP_PARSE_SUCCESS * failure: GF_EXP_PARSE_ITEM_FAILURE on parse failure, * GF_EXP_PARSE_ITEM_NOT_FOUND if the host was not found, * -EINVAL on bad args, -ENOMEM on allocation errors. * * Not for external use. */ static int __exp_line_host_parse(const char *line, dict_t **host_dict) { dict_t *hosts = NULL; char *strmatch = NULL; int ret = -EINVAL; struct export_item *exp_host = NULL; data_t *hostdata = NULL; GF_VALIDATE_OR_GOTO(GF_EXP, line, out); GF_VALIDATE_OR_GOTO(GF_EXP, host_dict, out); *host_dict = NULL; /* Initialize a parser with the line to parse and the regex used to * parse it. */ ret = parser_set_string(hostname_parser, line); if (ret < 0) { goto out; } gf_msg_trace(GF_EXP, 0, "parsing line: %s", line); while ((strmatch = parser_get_next_match(hostname_parser))) { if (!hosts) { /* Allocate a new dictto store the netgroups. */ hosts = dict_new(); GF_CHECK_ALLOC(hosts, ret, free_and_out); } gf_msg_trace(GF_EXP, 0, "parsing hostname: %s", strmatch); ret = __exp_line_ng_host_str_parse(strmatch, &exp_host); if (ret != 0) { /* Parsing or other critical error, free allocated * memory and exit. The caller will handle the errors. */ _exp_dict_destroy(hosts); goto free_and_out; } /* Insert export item structure into the hosts dict. */ hostdata = bin_to_data(exp_host, sizeof(*exp_host)); dict_set(hosts, exp_host->name, hostdata); /* Free this matched string and continue parsing.*/ GF_FREE(strmatch); } /* If the hosts dict was not allocated, then we know that * no matches were found. */ if (!exp_host) { ret = GF_EXP_PARSE_ITEM_NOT_FOUND; parser_unset_string(hostname_parser); goto out; } ret = GF_EXP_PARSE_SUCCESS; *host_dict = hosts; free_and_out: parser_unset_string(hostname_parser); GF_FREE(strmatch); out: return ret; }
int gf_sql_delete_unwind (gf_sql_connection_t *sql_conn, gfdb_db_record_t *gfdb_db_record) { int ret = -1; char *gfid_str = NULL; char *pargfid_str = NULL; gfdb_time_t *modtime = NULL; CHECK_SQL_CONN (sql_conn, out); GF_VALIDATE_OR_GOTO (GFDB_STR_SQLITE3, gfdb_db_record, out); gfid_str = gf_strdup (uuid_utoa(gfdb_db_record->gfid)); if (!gfid_str) { gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_CREATE_FAILED, "Creating gfid string failed."); goto out; } /*Nuke all the entries for this GFID from DB*/ if (gfdb_db_record->gfdb_fop_path == GFDB_FOP_UNDEL_ALL) { gf_sql_delete_all(sql_conn, gfid_str); } /*Remove link entries only*/ else if (gfdb_db_record->gfdb_fop_path == GFDB_FOP_UNDEL) { pargfid_str = gf_strdup(uuid_utoa(gfdb_db_record->pargfid)); if (!pargfid_str) { gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_CREATE_FAILED, "Creating pargfid_str " "string failed."); goto out; } /* Special performance case: * Updating wind time in unwind for delete. This is done here * as in the wind path we will not know whether its the last * link or not. For a last link there is not use to update any * wind or unwind time!*/ if (gfdb_db_record->do_record_times) { /*Update the wind write times*/ modtime = &gfdb_db_record->gfdb_wind_change_time; ret = gf_update_time (sql_conn, gfid_str, modtime, gfdb_db_record->do_record_counters, _gf_true, isreadfop (gfdb_db_record->gfdb_fop_type)); if (ret) { gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_UPDATE_FAILED, "Failed update wind time in DB"); goto out; } } modtime = &gfdb_db_record->gfdb_unwind_change_time; ret = gf_sql_delete_link(sql_conn, gfid_str, pargfid_str, gfdb_db_record->file_name); if (ret) { gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_DELETE_FAILED, "Failed deleting link"); goto out; } if (gfdb_db_record->do_record_times && gfdb_db_record->do_record_uwind_time) { ret = gf_update_time (sql_conn, gfid_str, modtime, gfdb_db_record->do_record_counters, _gf_false, isreadfop(gfdb_db_record->gfdb_fop_type)); if (ret) { gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_UPDATE_FAILED, "Failed update " "unwind time in DB"); goto out; } } } else { gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_INVALID_UPLINK, "Invalid unlink option"); goto out; } ret = 0; out: GF_FREE (gfid_str); GF_FREE (pargfid_str); return ret; }
/** * cache_nfs_fh -- Places the nfs file handle in the underlying dict as we are * using as our cache. The key is "exportid:gfid:host_addr", the * value is an entry struct containing the export item that * was authorized for the operation and the file handle that was * authorized. * * @cache: The cache to place fh's in * @fh : The fh to cache * @host_addr: The address of the host * @export_item: The export item that was authorized * */ int cache_nfs_fh (struct auth_cache *cache, struct nfs3_fh *fh, const char *host_addr, struct export_item *export_item) { int ret = -EINVAL; char *hashkey = NULL; data_t *entry_data = NULL; time_t timestamp = 0; gf_boolean_t can_write = _gf_false; struct auth_cache_entry *entry = NULL; GF_VALIDATE_OR_GOTO (GF_NFS, host_addr, out); GF_VALIDATE_OR_GOTO (GF_NFS, cache, out); GF_VALIDATE_OR_GOTO (GF_NFS, fh, out); /* If a dict has not been allocated already, allocate it. */ if (!cache->cache_dict) { cache->cache_dict = dict_new (); if (!cache->cache_dict) { ret = -ENOMEM; goto out; } } /* If we could already find it in the cache, just return */ ret = auth_cache_lookup (cache, fh, host_addr, ×tamp, &can_write); if (ret == 0) { gf_msg_trace (GF_NFS, 0, "found cached auth/fh for host " "%s", host_addr); goto out; } make_hashkey (hashkey, fh, host_addr); entry = auth_cache_entry_init (); if (!entry) { ret = -ENOMEM; goto out; } entry->timestamp = time (NULL); entry->item = export_item; /* The cache entry will simply be the time that the entry * was cached. */ entry_data = bin_to_data (entry, sizeof (*entry)); if (!entry_data) { GF_FREE (entry); goto out; } ret = dict_set (cache->cache_dict, hashkey, entry_data); if (ret == -1) { GF_FREE (entry); goto out; } gf_msg_trace (GF_NFS, 0, "Caching file-handle (%s)", host_addr); ret = 0; out: return ret; }
int gf_sql_insert_wind (gf_sql_connection_t *sql_conn, gfdb_db_record_t *gfdb_db_record) { int ret = -1; gfdb_time_t *modtime = NULL; char *pargfid_str = NULL; char *gfid_str = NULL; char *old_pargfid_str = NULL; gf_boolean_t its_wind = _gf_true;/*remains true for this function*/ CHECK_SQL_CONN (sql_conn, out); GF_VALIDATE_OR_GOTO (GFDB_STR_SQLITE3, gfdb_db_record, out); gfid_str = gf_strdup (uuid_utoa (gfdb_db_record->gfid)); if (!gfid_str) { gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_CREATE_FAILED, "Creating gfid string failed."); goto out; } modtime = &gfdb_db_record->gfdb_wind_change_time; /* handle all dentry based operations */ if (isdentryfop (gfdb_db_record->gfdb_fop_type)) { /*Parent GFID is always set*/ pargfid_str = gf_strdup (uuid_utoa (gfdb_db_record->pargfid)); if (!pargfid_str) { gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_CREATE_FAILED, "Creating gfid string " "failed."); goto out; } /* handle create, mknod */ if (isdentrycreatefop (gfdb_db_record->gfdb_fop_type)) { /*insert link*/ ret = gf_sql_insert_link(sql_conn, gfid_str, pargfid_str, gfdb_db_record->file_name, gfdb_db_record->file_path, gfdb_db_record->link_consistency, gfdb_db_record->ignore_errors); if (ret) { gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_INSERT_FAILED, "Failed " "inserting link in DB"); goto out; } gfdb_db_record->islinkupdate = gfdb_db_record-> link_consistency; /* * Only for create/mknod insert wind time * for the first time * */ ret = gf_sql_insert_write_wind_time (sql_conn, gfid_str, modtime); if (ret) { gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_INSERT_FAILED, "Failed " "inserting wind time in DB"); goto out; } goto out; } /*handle rename, link */ else { /*rename*/ if (strlen (gfdb_db_record->old_file_name) != 0) { old_pargfid_str = gf_strdup (uuid_utoa ( gfdb_db_record->old_pargfid)); if (!old_pargfid_str) { gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_CREATE_FAILED, "Creating gfid string failed."); goto out; } ret = gf_sql_update_link (sql_conn, gfid_str, pargfid_str, gfdb_db_record->file_name, gfdb_db_record->file_path, old_pargfid_str, gfdb_db_record->old_file_name, gfdb_db_record-> link_consistency); if (ret) { gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_UPDATE_FAILED, "Failed updating link"); goto out; } gfdb_db_record->islinkupdate = gfdb_db_record-> link_consistency; } /*link*/ else { ret = gf_sql_insert_link (sql_conn, gfid_str, pargfid_str, gfdb_db_record->file_name, gfdb_db_record->file_path, gfdb_db_record->link_consistency, gfdb_db_record->ignore_errors); if (ret) { gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_INSERT_FAILED, "Failed inserting link in DB"); goto out; } gfdb_db_record->islinkupdate = gfdb_db_record-> link_consistency; } } } /* update times only when said!*/ if (gfdb_db_record->do_record_times) { /*All fops update times read or write*/ ret = gf_update_time (sql_conn, gfid_str, modtime, gfdb_db_record->do_record_counters, its_wind, isreadfop (gfdb_db_record->gfdb_fop_type)); if (ret) { gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_UPDATE_FAILED, "Failed update wind time" " in DB"); goto out; } } ret = 0; out: GF_FREE (gfid_str); GF_FREE (pargfid_str); GF_FREE (old_pargfid_str); return ret; }
static int glusterd_handle_post_validate_fn (rpcsvc_request_t *req) { int32_t ret = -1; gd1_mgmt_v3_post_val_req op_req = {{0},}; glusterd_peerinfo_t *peerinfo = NULL; xlator_t *this = NULL; char *op_errstr = NULL; dict_t *dict = NULL; dict_t *rsp_dict = NULL; this = THIS; GF_ASSERT (this); GF_ASSERT (req); ret = xdr_to_generic (req->msg[0], &op_req, (xdrproc_t)xdr_gd1_mgmt_v3_post_val_req); if (ret < 0) { gf_log (this->name, GF_LOG_ERROR, "Failed to decode post validation " "request received from peer"); req->rpc_err = GARBAGE_ARGS; goto out; } if (glusterd_friend_find_by_uuid (op_req.uuid, &peerinfo)) { gf_log (this->name, GF_LOG_WARNING, "%s doesn't " "belong to the cluster. Ignoring request.", uuid_utoa (op_req.uuid)); ret = -1; goto out; } dict = dict_new (); if (!dict) goto out; ret = dict_unserialize (op_req.dict.dict_val, op_req.dict.dict_len, &dict); if (ret) { gf_log (this->name, GF_LOG_WARNING, "failed to unserialize the dictionary"); goto out; } rsp_dict = dict_new (); if (!rsp_dict) { gf_log (this->name, GF_LOG_ERROR, "Failed to get new dictionary"); return -1; } ret = gd_mgmt_v3_post_validate_fn (op_req.op, op_req.op_ret, dict, &op_errstr, rsp_dict); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Post Validation failed on operation %s", gd_op_list[op_req.op]); } ret = glusterd_mgmt_v3_post_validate_send_resp (req, op_req.op, ret, op_errstr, rsp_dict); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to send Post Validation " "response for operation %s", gd_op_list[op_req.op]); goto out; } out: if (op_errstr && (strcmp (op_errstr, ""))) GF_FREE (op_errstr); free (op_req.dict.dict_val); if (dict) dict_unref (dict); if (rsp_dict) dict_unref (rsp_dict); gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); return ret; }
int gf_sql_insert_unwind (gf_sql_connection_t *sql_conn, gfdb_db_record_t *gfdb_db_record) { int ret = -1; gfdb_time_t *modtime = NULL; gf_boolean_t its_wind = _gf_true;/*remains true for this function*/ char *gfid_str = NULL; char *pargfid_str = NULL; CHECK_SQL_CONN (sql_conn, out); GF_VALIDATE_OR_GOTO (GFDB_STR_SQLITE3, gfdb_db_record, out); gfid_str = gf_strdup (uuid_utoa(gfdb_db_record->gfid)); if (!gfid_str) { gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_CREATE_FAILED, "Creating gfid string failed."); goto out; } /*Only update if recording unwind is set*/ if (gfdb_db_record->do_record_times && gfdb_db_record->do_record_uwind_time) { modtime = &gfdb_db_record->gfdb_unwind_change_time; ret = gf_update_time (sql_conn, gfid_str, modtime, gfdb_db_record->do_record_counters, (!its_wind), isreadfop (gfdb_db_record->gfdb_fop_type)); if (ret) { gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_UPDATE_FAILED, "Failed update unwind " "time in DB"); goto out; } } /*For link creation and changes we use link updated*/ if (gfdb_db_record->islinkupdate && isdentryfop(gfdb_db_record->gfdb_fop_type)) { pargfid_str = gf_strdup(uuid_utoa(gfdb_db_record->pargfid)); if (!pargfid_str) { gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_CREATE_FAILED, "Creating pargfid_str string failed."); goto out; } ret = gf_sql_update_link_flags (sql_conn, gfid_str, pargfid_str, gfdb_db_record->file_name, 0, _gf_true); if (ret) { gf_msg (GFDB_STR_SQLITE3, GF_LOG_ERROR, 0, LG_MSG_UPDATE_FAILED, "Failed updating link " "flags in unwind"); goto out; } } ret = 0; out: GF_FREE (gfid_str); GF_FREE (pargfid_str); return ret; }
auth_result_t gf_auth(dict_t *input_params, dict_t *config_params) { auth_result_t result = AUTH_DONT_CARE; int ret = 0; data_t *allow_user = NULL; data_t *username_data = NULL; data_t *passwd_data = NULL; data_t *password_data = NULL; char *username = NULL; char *password = NULL; char *brick_name = NULL; char *searchstr = NULL; char *username_str = NULL; char *tmp = NULL; char *username_cpy = NULL; gf_boolean_t using_ssl = _gf_false; gf_boolean_t strict_auth = _gf_false; username_data = dict_get(input_params, "ssl-name"); if (username_data) { gf_log("auth/login", GF_LOG_INFO, "connecting user name: %s", username_data->data); using_ssl = _gf_true; } else { ret = dict_get_str_boolean(config_params, "strict-auth-accept", _gf_false); if (ret == -1) strict_auth = _gf_false; else strict_auth = ret; username_data = dict_get(input_params, "username"); if (!username_data) { if (strict_auth) { gf_log("auth/login", GF_LOG_DEBUG, "username not found, strict auth" " configured returning REJECT"); result = AUTH_REJECT; } else { gf_log("auth/login", GF_LOG_DEBUG, "username not found, returning" " DONT-CARE"); } goto out; } password_data = dict_get(input_params, "password"); if (!password_data) { if (strict_auth) { gf_log("auth/login", GF_LOG_DEBUG, "password not found, strict auth" " configured returning REJECT"); result = AUTH_REJECT; } else { gf_log("auth/login", GF_LOG_WARNING, "password not found, returning" " DONT-CARE"); } goto out; } password = data_to_str(password_data); } username = data_to_str(username_data); brick_name = data_to_str(dict_get(input_params, "remote-subvolume")); if (!brick_name) { gf_log("auth/login", GF_LOG_ERROR, "remote-subvolume not specified"); result = AUTH_REJECT; goto out; } ret = gf_asprintf(&searchstr, "auth.login.%s.%s", brick_name, using_ssl ? "ssl-allow" : "allow"); if (-1 == ret) { gf_log("auth/login", GF_LOG_ERROR, "asprintf failed while setting search string, " "returning REJECT"); result = AUTH_REJECT; goto out; } allow_user = dict_get(config_params, searchstr); GF_FREE(searchstr); if (allow_user) { gf_log("auth/login", GF_LOG_INFO, "allowed user names: %s", allow_user->data); /* * There's a subtle difference between SSL and non-SSL behavior * if we can't match anything in the "while" loop below. * Intuitively, we should AUTH_REJECT if there's no match. * However, existing code depends on allowing untrusted users * to connect with *no credentials at all* by falling through * the loop. They're still distinguished from trusted users * who do provide a valid username and password (in fact that's * pretty much the only thing we use non-SSL login auth for), * but they are allowed to connect. It's wrong, but it's not * worth changing elsewhere. Therefore, we do the sane thing * only for SSL here. * * For SSL, if there's a list *you must be on it*. Note that * if there's no list we don't care. In that case (and the * ssl-allow=* case as well) authorization is effectively * disabled, though authentication and encryption are still * active. * * Read NOTE on strict_auth above. */ if (using_ssl || strict_auth) { result = AUTH_REJECT; } username_cpy = gf_strdup(allow_user->data); if (!username_cpy) goto out; username_str = strtok_r(username_cpy, " ,", &tmp); /* * We have to match a user's *authenticated* name to one in the * list. If we're using SSL, they're already authenticated. * Otherwise, they need a matching password to complete the * process. */ while (username_str) { if (!fnmatch(username_str, username, 0)) { if (using_ssl) { result = AUTH_ACCEPT; break; } ret = gf_asprintf(&searchstr, "auth.login.%s.password", username); if (-1 == ret) { gf_log("auth/login", GF_LOG_WARNING, "asprintf failed while setting search string"); goto out; } passwd_data = dict_get(config_params, searchstr); GF_FREE(searchstr); if (!passwd_data) { gf_log("auth/login", GF_LOG_ERROR, "wrong username/password combination"); result = AUTH_REJECT; goto out; } result = !((strcmp(data_to_str(passwd_data), password)) ? AUTH_ACCEPT : AUTH_REJECT); if (result == AUTH_REJECT) gf_log("auth/login", GF_LOG_ERROR, "wrong password for user %s", username); break; } username_str = strtok_r(NULL, " ,", &tmp); } } out: GF_FREE(username_cpy); return result; }
rbthash_table_t * rbthash_table_init (int buckets, rbt_hasher_t hfunc, rbt_data_destroyer_t dfunc, unsigned long expected_entries, struct mem_pool *entrypool) { rbthash_table_t *newtab = NULL; int ret = -1; if (!hfunc) { gf_log (GF_RBTHASH, GF_LOG_ERROR, "Hash function not given"); return NULL; } if (!entrypool && !expected_entries) { gf_log (GF_RBTHASH, GF_LOG_ERROR, "Both mem-pool and expected entries not provided"); return NULL; } if (entrypool && expected_entries) { gf_log (GF_RBTHASH, GF_LOG_ERROR, "Both mem-pool and expected entries are provided"); return NULL; } newtab = GF_CALLOC (1, sizeof (*newtab), gf_common_mt_rbthash_table_t); if (!newtab) return NULL; newtab->buckets = GF_CALLOC (buckets, sizeof (struct rbthash_bucket), gf_common_mt_rbthash_bucket); if (!newtab->buckets) { goto free_newtab; } if (expected_entries) { newtab->entrypool = mem_pool_new (rbthash_entry_t, expected_entries); if (!newtab->entrypool) { gf_log (GF_RBTHASH, GF_LOG_ERROR, "Failed to allocate mem-pool"); goto free_buckets; } newtab->pool_alloced = _gf_true; } else { newtab->entrypool = entrypool; } LOCK_INIT (&newtab->tablelock); newtab->numbuckets = buckets; ret = __rbthash_init_buckets (newtab, buckets); if (ret == -1) { gf_log (GF_RBTHASH, GF_LOG_ERROR, "Failed to init buckets"); if (newtab->pool_alloced) mem_pool_destroy (newtab->entrypool); } else { gf_log (GF_RBTHASH, GF_LOG_TRACE, "Inited hash table: buckets:" " %d", buckets); } newtab->hashfunc = hfunc; newtab->dfunc = dfunc; free_buckets: if (ret == -1) GF_FREE (newtab->buckets); free_newtab: if (ret == -1) { GF_FREE (newtab); newtab = NULL; } return newtab; }
int xlator_dynload (xlator_t *xl) { int ret = -1; char *name = NULL; void *handle = NULL; volume_opt_list_t *vol_opt = NULL; class_methods_t *vtbl = NULL; GF_VALIDATE_OR_GOTO ("xlator", xl, out); INIT_LIST_HEAD (&xl->volume_options); ret = gf_asprintf (&name, "%s/%s.so", XLATORDIR, xl->type); if (-1 == ret) { gf_log ("xlator", GF_LOG_ERROR, "asprintf failed"); goto out; } ret = -1; gf_log ("xlator", GF_LOG_TRACE, "attempt to load file %s", name); handle = dlopen (name, RTLD_NOW|RTLD_GLOBAL); if (!handle) { gf_log ("xlator", GF_LOG_WARNING, "%s", dlerror ()); goto out; } xl->dlhandle = handle; if (!(xl->fops = dlsym (handle, "fops"))) { gf_log ("xlator", GF_LOG_WARNING, "dlsym(fops) on %s", dlerror ()); goto out; } if (!(xl->cbks = dlsym (handle, "cbks"))) { gf_log ("xlator", GF_LOG_WARNING, "dlsym(cbks) on %s", dlerror ()); goto out; } /* * If class_methods exists, its contents override any definitions of * init or fini for that translator. Otherwise, we fall back to the * older method of looking for init and fini directly. */ vtbl = dlsym(handle,"class_methods"); if (vtbl) { xl->init = vtbl->init; xl->fini = vtbl->fini; xl->reconfigure = vtbl->reconfigure; xl->notify = vtbl->notify; } else { if (!(*VOID(&xl->init) = dlsym (handle, "init"))) { gf_log ("xlator", GF_LOG_WARNING, "dlsym(init) on %s", dlerror ()); goto out; } if (!(*VOID(&(xl->fini)) = dlsym (handle, "fini"))) { gf_log ("xlator", GF_LOG_WARNING, "dlsym(fini) on %s", dlerror ()); goto out; } if (!(*VOID(&(xl->reconfigure)) = dlsym (handle, "reconfigure"))) { gf_log ("xlator", GF_LOG_TRACE, "dlsym(reconfigure) on %s -- neglecting", dlerror()); } if (!(*VOID(&(xl->notify)) = dlsym (handle, "notify"))) { gf_log ("xlator", GF_LOG_TRACE, "dlsym(notify) on %s -- neglecting", dlerror ()); } } if (!(xl->dumpops = dlsym (handle, "dumpops"))) { gf_log ("xlator", GF_LOG_TRACE, "dlsym(dumpops) on %s -- neglecting", dlerror ()); } if (!(*VOID(&(xl->mem_acct_init)) = dlsym (handle, "mem_acct_init"))) { gf_log (xl->name, GF_LOG_TRACE, "dlsym(mem_acct_init) on %s -- neglecting", dlerror ()); } vol_opt = GF_CALLOC (1, sizeof (volume_opt_list_t), gf_common_mt_volume_opt_list_t); if (!vol_opt) { goto out; } if (!(vol_opt->given_opt = dlsym (handle, "options"))) { dlerror (); gf_log (xl->name, GF_LOG_TRACE, "Strict option validation not enforced -- neglecting"); } INIT_LIST_HEAD (&vol_opt->list); list_add_tail (&vol_opt->list, &xl->volume_options); fill_defaults (xl); ret = 0; out: GF_FREE (name); return ret; }
/** * __exp_line_opt_parse -- Parse the options part of an * exports or netgroups string. * * @opt_str : The option string to parse * @exp_opts : Double pointer to the options we are going * to allocate and setup. * * * @return: success: GF_EXP_PARSE_SUCCESS * failure: GF_EXP_PARSE_ITEM_FAILURE on parse failure, * -EINVAL on bad args, -ENOMEM on allocation errors. * * Not for external use. */ static int __exp_line_opt_parse(const char *opt_str, struct export_options **exp_opts) { struct export_options *opts = NULL; char *strmatch = NULL; int ret = -EINVAL; char *equals = NULL; ret = parser_set_string(options_parser, opt_str); if (ret < 0) goto out; while ((strmatch = parser_get_next_match(options_parser))) { if (!opts) { /* If the options have not been allocated, * allocate it. */ opts = _export_options_init(); if (!opts) { ret = -ENOMEM; parser_unset_string(options_parser); goto out; } } /* First, check for all the boolean options Second, check for * an '=', and check the available options there. The string * parsing here gets slightly messy, but the concept itself * is pretty simple. */ equals = strchr(strmatch, '='); if (strcmp(strmatch, "root") == 0) opts->root = _gf_true; else if (strcmp(strmatch, "ro") == 0) opts->rw = _gf_false; else if (strcmp(strmatch, "rw") == 0) opts->rw = _gf_true; else if (strcmp(strmatch, "nosuid") == 0) opts->nosuid = _gf_true; else if (equals) { ret = __exp_line_opt_key_value_parse(strmatch, opts); if (ret < 0) { /* This means invalid key value options were * specified, or memory allocation failed. * The ret value gets bubbled up to the caller. */ GF_FREE(strmatch); parser_unset_string(options_parser); _export_options_deinit(opts); goto out; } } else /* Cannot change to gf_msg. * gf_msg not giving output to STDOUT * Bug id : BZ1215017 */ gf_log(GF_EXP, GF_LOG_WARNING, "Could not find any valid options for " "string: %s", strmatch); GF_FREE(strmatch); } if (!opts) { /* If opts is not allocated * that means no matches were found * which is a parse error. Not marking * it as "not found" because it is a parse * error to not have options. */ ret = GF_EXP_PARSE_ITEM_FAILURE; parser_unset_string(options_parser); goto out; } *exp_opts = opts; parser_unset_string(options_parser); ret = GF_EXP_PARSE_SUCCESS; out: return ret; }
static void mountudp_program_3(struct svc_req *rqstp, register SVCXPRT *transp) { union { dirpath mountudpproc3_mnt_3_arg; } argument; char *result = NULL; xdrproc_t _xdr_argument = NULL, _xdr_result = NULL; char *(*local)(char *, struct svc_req *) = NULL; mountres3 *res = NULL; struct sockaddr_in *sin = NULL; sin = svc_getcaller (transp); inet_ntop (AF_INET, &sin->sin_addr, mnthost, INET_ADDRSTRLEN+1); switch (rqstp->rq_proc) { case NULLPROC: (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); return; case MOUNT3_MNT: _xdr_argument = (xdrproc_t) xdr_dirpath; _xdr_result = (xdrproc_t) xdr_mountres3; local = (char *(*)(char *, struct svc_req *)) mountudpproc3_mnt_3_svc; break; case MOUNT3_UMNT: _xdr_argument = (xdrproc_t) xdr_dirpath; _xdr_result = (xdrproc_t) xdr_mountstat3; local = (char *(*)(char *, struct svc_req *)) mountudpproc3_umnt_3_svc; break; default: svcerr_noproc (transp); return; } memset ((char *)&argument, 0, sizeof (argument)); if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { svcerr_decode (transp); return; } result = (*local)((char *)&argument, rqstp); if (result == NULL) { gf_log (GF_MNT, GF_LOG_DEBUG, "PROC returned error"); svcerr_systemerr (transp); } if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) { gf_log (GF_MNT, GF_LOG_ERROR, "svc_sendreply returned error"); svcerr_systemerr (transp); } if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { gf_log (GF_MNT, GF_LOG_ERROR, "unable to free arguments"); } if (result == NULL) return; /* free the result */ switch (rqstp->rq_proc) { case MOUNT3_MNT: res = (mountres3 *) result; GF_FREE (res->mountres3_u.mountinfo.fhandle.fhandle3_val); GF_FREE (res->mountres3_u.mountinfo.auth_flavors.auth_flavors_val); GF_FREE (res); break; case MOUNT3_UMNT: GF_FREE (result); break; } return; }
/** * __exp_line_ng_host_str_parse -- Parse the netgroup or host string * * e.g. @mygroup(<options>), parsing @mygroup and (<options>) * or myhost001.dom(<options>), parsing myhost001.dom and (<options>) * * @line : The line to parse * @exp_item : Double pointer to a struct export_item * * @return: success: GF_PARSE_SUCCESS * failure: GF_EXP_PARSE_ITEM_FAILURE on parse failure, * -EINVAL on bad args, -ENOMEM on allocation errors. * * Not for external use. */ static int __exp_line_ng_host_str_parse(char *str, struct export_item **exp_item) { struct export_item *item = NULL; int ret = -EINVAL; char *parens = NULL; char *optstr = NULL; struct export_options *exp_opts = NULL; char *item_name = NULL; GF_VALIDATE_OR_GOTO(GF_EXP, str, out); GF_VALIDATE_OR_GOTO(GF_EXP, exp_item, out); /* A netgroup/host string looks like this: * @test(sec=sys,rw,anonuid=0) or host(sec=sys,rw,anonuid=0) * We want to extract the name, 'test' or 'host' * Again, we could setup a regex and use it here, * but its simpler to find the '(' and copy until * there. */ parens = strchr(str, '('); if (!parens) { /* Parse error if there are no parens. */ ret = GF_EXP_PARSE_ITEM_FAILURE; goto out; } *parens = '\0'; /* Temporarily terminate it so we can do a copy */ if (strlen(str) > FQDN_MAX_LEN) { ret = GF_EXP_PARSE_ITEM_FAILURE; goto out; } /* Strip leading whitespaces */ while (*str == ' ' || *str == '\t') str++; item_name = gf_strdup(str); GF_CHECK_ALLOC(item_name, ret, out); gf_msg_trace(GF_EXP, 0, "found hostname/netgroup: %s", item_name); /* Initialize an export item for this */ item = _export_item_init(); GF_CHECK_ALLOC(item, ret, free_and_out); item->name = item_name; *parens = '('; /* Restore the string */ /* Options start at the parentheses */ optstr = parens; ret = __exp_line_opt_parse(optstr, &exp_opts); if (ret != 0) { /* Bubble up the error to the caller */ GF_REF_PUT(item); goto out; } item->opts = exp_opts; *exp_item = item; ret = GF_EXP_PARSE_SUCCESS; goto out; free_and_out: GF_FREE(item_name); out: return ret; }
static int invoke_rsync (int argc, char **argv) { int i = 0; char path[PATH_MAX] = {0,}; pid_t pid = -1; pid_t ppid = -1; pid_t pida[] = {-1, -1}; char *name = NULL; char buf[PATH_MAX + 1] = {0,}; int ret = 0; assert (argv[argc] == NULL); if (argc < 2 || strcmp (argv[1], "--server") != 0) goto error; for (i = 2; i < argc && argv[i][0] == '-'; i++); if (!(i == argc - 2 && strcmp (argv[i], ".") == 0 && argv[i + 1][0] == '/')) { fprintf (stderr, "need an rsync invocation without protected args\n"); goto error; } /* look up sshd we are spawned from */ for (pid = getpid () ;; pid = ppid) { ppid = pidinfo (pid, &name); if (ppid < 0) { fprintf (stderr, "sshd ancestor not found\n"); goto error; } if (strcmp (name, "sshd") == 0) { GF_FREE (name); break; } GF_FREE (name); } /* look up "ssh-sibling" gsyncd */ pida[0] = pid; ret = prociter (find_gsyncd, pida); if (ret == -1 || pida[1] == -1) { fprintf (stderr, "gsyncd sibling not found\n"); goto error; } /* check if rsync target matches gsyncd target */ sprintf (path, PROC"/%d/cwd", pida[1]); ret = readlink (path, buf, sizeof (buf)); if (ret == -1 || ret == sizeof (buf)) goto error; if (strcmp (argv[argc - 1], "/") == 0 /* root dir cannot be a target */ || (strcmp (argv[argc - 1], path) /* match against gluster target */ && strcmp (argv[argc - 1], buf) /* match against file target */) != 0) { fprintf (stderr, "rsync target does not match "GEOREP" session\n"); goto error; } argv[0] = RSYNC; execvp (RSYNC, argv); fprintf (stderr, "exec of "RSYNC" failed\n"); return 127; error: fprintf (stderr, "disallowed "RSYNC" invocation\n"); return 1; }
/** * __exp_line_ng_parse -- Extract the netgroups in the line * and call helper functions to parse * the string. * * The call chain goes like this: * * 1) __exp_line_ng_parse ("/test @test(sec=sys,rw,anonuid=0)") * 2) __exp_line_ng_str_parse ("@test(sec=sys,rw,anonuid=0)"); * 3) __exp_line_opt_parse("(sec=sys,rw,anonuid=0)"); * * * @line : The line to parse * @ng_dict : Double pointer to the dict we want to * insert netgroups into. * * Allocates the dict, extracts netgroup strings from the line, * parses them into a struct export_item structure and inserts * them in the dict. * * @return: success: GF_EXP_PARSE_SUCCESS * failure: GF_EXP_PARSE_ITEM_FAILURE on parse failure, * GF_EXP_PARSE_ITEM_NOT_FOUND if the netgroup was not found * -EINVAL on bad args, -ENOMEM on allocation errors. * * Not for external use. */ static int __exp_line_ng_parse(const char *line, dict_t **ng_dict) { dict_t *netgroups = NULL; char *strmatch = NULL; int ret = -EINVAL; struct export_item *exp_ng = NULL; data_t *ngdata = NULL; GF_VALIDATE_OR_GOTO(GF_EXP, line, out); GF_VALIDATE_OR_GOTO(GF_EXP, ng_dict, out); *ng_dict = NULL; /* Will be set if parse is successful */ /* Initialize a parser with the line to parse * and the regex used to parse it. */ ret = parser_set_string(netgroup_parser, line); if (ret < 0) { goto out; } gf_msg_trace(GF_EXP, 0, "parsing line: %s", line); while ((strmatch = parser_get_next_match(netgroup_parser))) { if (!netgroups) { /* Allocate a new dict to store the netgroups. */ netgroups = dict_new(); if (!netgroups) { ret = -ENOMEM; goto free_and_out; } } gf_msg_trace(GF_EXP, 0, "parsing netgroup: %s", strmatch); ret = __exp_line_ng_host_str_parse(strmatch, &exp_ng); if (ret != 0) { /* Parsing or other critical errors. * caller will handle return value. */ _exp_dict_destroy(netgroups); goto free_and_out; } ngdata = bin_to_data(exp_ng, sizeof(*exp_ng)); dict_set(netgroups, exp_ng->name, ngdata); /* Free this matched string and continue parsing. */ GF_FREE(strmatch); } /* If the netgroups dict was not allocated, then we know that * no matches were found. */ if (!netgroups) { ret = GF_EXP_PARSE_ITEM_NOT_FOUND; parser_unset_string(netgroup_parser); goto out; } ret = GF_EXP_PARSE_SUCCESS; *ng_dict = netgroups; free_and_out: parser_unset_string(netgroup_parser); GF_FREE(strmatch); out: return ret; }
int gf_strsplit (const char *str, const char *delim, char ***tokens, int *token_count) { char *_running = NULL; char *running = NULL; char *token = NULL; char **token_list = NULL; int count = 0; int i = 0; int j = 0; if (str == NULL || delim == NULL || tokens == NULL || token_count == NULL) { gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); return -1; } _running = gf_strdup (str); if (_running == NULL) return -1; running = _running; while ((token = strsep (&running, delim)) != NULL) { if (token[0] != '\0') count++; } GF_FREE (_running); _running = gf_strdup (str); if (_running == NULL) return -1; running = _running; if ((token_list = GF_CALLOC (count, sizeof (char *), gf_common_mt_char)) == NULL) { GF_FREE (_running); return -1; } while ((token = strsep (&running, delim)) != NULL) { if (token[0] == '\0') continue; token_list[i] = gf_strdup (token); if (token_list[i] == NULL) goto free_exit; i++; } GF_FREE (_running); *tokens = token_list; *token_count = count; return 0; free_exit: GF_FREE (_running); for (j = 0; j < i; j++) GF_FREE (token_list[j]); GF_FREE (token_list); return -1; }
int solaris_listxattr(const char *path, char *list, size_t size) { int attrdirfd = -1; ssize_t len = 0; DIR *dirptr = NULL; struct dirent *dent = NULL; int newfd = -1; char *mapped_path = NULL; int ret = -1; ret = solaris_xattr_resolve_path (path, &mapped_path); if (!ret) { attrdirfd = attropen (mapped_path, ".", O_RDONLY, 0); } else { attrdirfd = attropen (path, ".", O_RDONLY, 0); } if (attrdirfd >= 0) { newfd = dup(attrdirfd); dirptr = fdopendir(newfd); if (dirptr) { while ((dent = readdir(dirptr))) { size_t listlen = strlen(dent->d_name); if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) { /* we don't want "." and ".." here */ continue; } if (size == 0) { /* return the current size of the list of extended attribute names*/ len += listlen + 1; } else { /* check size and copy entry + null into list. */ if ((len + listlen + 1) > size) { errno = ERANGE; len = -1; break; } else { strncpy(list + len, dent->d_name, listlen); len += listlen; list[len] = '\0'; ++len; } } } if (closedir(dirptr) == -1) { close (attrdirfd); len = -1; goto out; } } else { close (attrdirfd); len = -1; goto out; } close (attrdirfd); } out: if (mapped_path) GF_FREE (mapped_path); return len; }