static gboolean _nmp_netns_push_type (NMPNetns *self, int ns_types) { NetnsInfo *info; char sbuf[100]; _stack_ensure_init (); info = _stack_peek (); g_return_val_if_fail (info, FALSE); if (info->netns == self && info->ns_types == ns_types) { info->count++; _LOGt (self, "push#%u* %s (increase count to %d)", _stack_size () - 1, _ns_types_to_str (ns_types, ns_types, sbuf), info->count); return TRUE; } _LOGD (self, "push#%u %s", _stack_size (), _ns_types_to_str (ns_types, _stack_current_ns_types (self, ns_types), sbuf)); if (!_netns_switch_push (self, ns_types)) return FALSE; _stack_push (self, ns_types); return TRUE; }
// -----[ _radix_tree_enum_has_next ]-------------------------------- static int _radix_tree_enum_has_next(void * ctx) { _enum_ctx_t * ectx= (_enum_ctx_t *) ctx; // Depth first search while ((ectx->data == NULL) && (ectx->tree_item != NULL)) { if (ectx->tree_item->data != NULL) ectx->data= ectx->tree_item->data; // Move to next item if (ectx->tree_item->left != NULL) { if (ectx->tree_item->right != NULL) _stack_push(ectx->stack, ectx->tree_item->right, ectx->key_len+1, ectx->key+(1 << (ectx->tree->key_len-ectx->key_len-1))); ectx->tree_item= ectx->tree_item->left; ectx->key_len++; } else if (ectx->tree_item->right != NULL) { ectx->tree_item= ectx->tree_item->right; ectx->key= ectx->key+(1 << (ectx->tree->key_len-ectx->key_len-1)); ectx->key_len++; } else { if (stack_depth(ectx->stack) > 0) _stack_pop(ectx->stack, &ectx->tree_item, &ectx->key_len, &ectx->key); else ectx->tree_item= NULL; } } return (ectx->data != NULL); }
static void _stack_ensure_init_impl (void) { NMPNetns *netns; GError *error = NULL; nm_assert (!netns_stack); netns_stack = g_array_new (FALSE, FALSE, sizeof (NetnsInfo)); /* at the bottom of the stack we must try to create a netns instance * that we never pop. It's the base to which we need to return. */ netns = _netns_new (&error); if (!netns) { /* don't know how to recover from this error. Netns are not supported. */ _LOGE (NULL, "failed to create initial netns: %s", error->message); g_clear_error (&error); return; } _stack_push (netns, _CLONE_NS_ALL); /* we leak this instance inside netns_stack. It cannot be popped. */ g_object_unref (netns); }
NMPNetns * nmp_netns_new (void) { NMPNetns *self; int errsv; GError *error = NULL; _stack_ensure_init (); if (!_stack_peek ()) { /* there are no netns instances. We cannot create a new one * (because after unshare we couldn't return to the original one). */ return NULL; } if (unshare (_CLONE_NS_ALL) != 0) { errsv = errno; _LOGE (NULL, "failed to create new net and mnt namespace: %s", g_strerror (errsv)); return NULL; } if (mount ("", "/", "none", MS_SLAVE | MS_REC, NULL) != 0) { errsv = errno; _LOGE (NULL, "failed mount --make-rslave: %s", g_strerror (errsv)); goto err_out; } if (umount2 ("/sys", MNT_DETACH) != 0) { errsv = errno; _LOGE (NULL, "failed umount /sys: %s", g_strerror (errsv)); goto err_out; } if (mount ("sysfs", "/sys", "sysfs", 0, NULL) != 0) { errsv = errno; _LOGE (NULL, "failed mount /sys: %s", g_strerror (errsv)); goto err_out; } self = _netns_new (&error); if (!self) { _LOGE (NULL, "failed to create netns after unshare: %s", error->message); g_clear_error (&error); goto err_out; } _stack_push (self, _CLONE_NS_ALL); return self; err_out: _netns_switch_pop (NULL, _CLONE_NS_ALL); return NULL; }
/** * Call the 'fForEach' function for each non empty node. */ int radix_tree_for_each(gds_radix_tree_t * tree, FRadixTreeForEach fForEach, void * ctx) { gds_stack_t * stack= stack_create(tree->key_len); _radix_tree_item_t * tree_item; int result= 0; uint32_t key; uint8_t key_len; tree_item= tree->root; key= 0; key_len= 0; // Depth first search while (tree_item != NULL) { if (tree_item->data!= NULL) { result= fForEach(key, key_len, tree_item->data, ctx); if (result != 0) return result; } if (tree_item->left != NULL) { if (tree_item->right != NULL) _stack_push(stack, tree_item->right, key_len+1, key+(1 << (tree->key_len-key_len-1))); tree_item= tree_item->left; key_len++; } else if (tree_item->right != NULL) { tree_item= tree_item->right; key= key+(1 << (tree->key_len-key_len-1)); key_len++; } else { if (stack_depth(stack) > 0) _stack_pop(stack, &tree_item, &key_len, &key); else break; } } stack_destroy(&stack); return 0; }