Exemplo n.º 1
0
/*
 * Build a dbus-object encapsulating a network device.
 * If @server is non-NULL, register the object with a canonical object path
 */
static ni_dbus_object_t *
__ni_objectmodel_build_autoip4_device_object(ni_dbus_server_t *server, ni_autoip_device_t *dev)
{
	ni_dbus_object_t *object;
	char object_path[256];

	if (dev->link.ifindex <= 0) {
		ni_error("%s: autoip4 device %s has bad ifindex %d", __func__, dev->ifname, dev->link.ifindex);
		return NULL;
	}

	if (server != NULL) {
		snprintf(object_path, sizeof(object_path), "Interface/%d", dev->link.ifindex);
		object = ni_dbus_server_register_object(server, object_path,
						&ni_objectmodel_autoip4dev_class,
						ni_autoip_device_get(dev));
	} else {
		object = ni_dbus_object_new(&ni_objectmodel_autoip4dev_class, NULL,
						ni_autoip_device_get(dev));
	}

	if (object == NULL)
		ni_fatal("Unable to create dbus object for autoip4 device %s", dev->ifname);

	ni_objectmodel_bind_compatible_interfaces(object);
	return object;
}
Exemplo n.º 2
0
/*
 * Register services and classes for dhcp4 supplicant service
 */
void
ni_objectmodel_autoip4_init(void)
{
	if (ni_objectmodel_init(NULL) == NULL)
		ni_fatal("Cannot initialize objectmodel, giving up.");
	ni_objectmodel_register_class(&ni_objectmodel_autoip4dev_class);
	ni_objectmodel_register_service(&ni_objectmodel_autoip4_service);
}
Exemplo n.º 3
0
int
__ni_process_run(ni_process_t *pi, int *pfd)
{
	const char *arg0 = pi->argv.data[0];
	pid_t pid;

	if (pi->pid != 0) {
		ni_error("Cannot execute process instance twice (%s)", pi->process->command);
		return -1;
	}

	if (!ni_file_executable(arg0)) {
		ni_error("Unable to run %s; does not exist or is not executable", arg0);
		return -1;
	}

	signal(SIGCHLD, ni_process_sigchild);

	if ((pid = fork()) < 0) {
		ni_error("%s: unable to fork child process: %m", __func__);
		return -1;
	}
	pi->pid = pid;

	if (pid == 0) {
		int maxfd;
		int fd;

		if (chdir("/") < 0)
			ni_warn("%s: unable to chdir to /: %m", __func__);

		close(0);
		if ((fd = open("/dev/null", O_RDONLY)) < 0)
			ni_warn("%s: unable to open /dev/null: %m", __func__);
		else if (dup2(fd, 0) < 0)
			ni_warn("%s: cannot dup null descriptor: %m", __func__);

		if (pfd) {
			if (dup2(pfd[1], 1) < 0 || dup2(pfd[1], 2) < 0)
				ni_warn("%s: cannot dup pipe out descriptor: %m", __func__);
		}

		maxfd = getdtablesize();
		for (fd = 3; fd < maxfd; ++fd)
			close(fd);

		/* NULL terminate argv and env lists */
		ni_string_array_append(&pi->argv, NULL);
		ni_string_array_append(&pi->environ, NULL);

		arg0 = pi->argv.data[0];
		execve(arg0, pi->argv.data, pi->environ.data);

		ni_fatal("%s: cannot execute %s: %m", __func__, arg0);
	}

	return 0;
}
Exemplo n.º 4
0
Arquivo: lldp.c Projeto: mchf/wicked
void
get_string(ni_dbus_variant_t *dict, const char *name, const char *value)
{
	if (strncmp(name, "default-", 8) != 0)
		ni_fatal("get_string: bad element name %s (should start with default-", name);
	if (value == NULL || *value == '\0')
		get_default(dict, name);
	else
		ni_dbus_dict_add_string(dict, name + 8, value);
}
Exemplo n.º 5
0
void *
xrealloc(void *ptr, size_t size)
{
	void *p = realloc(ptr, size);

	if (p == NULL)
		ni_fatal("allocation failed realloc(%p, %zu): %m", ptr, size);

	return p;
}
Exemplo n.º 6
0
void *
xcalloc(unsigned int count, size_t size)
{
	void *p = calloc(count, size);

	if (p == NULL)
		ni_fatal("allocation failed calloc(%u, %zu): %m", count, size);

	return p;
}
Exemplo n.º 7
0
/*
 * Alloc helpers with NULLL check
 */
void *
xmalloc(size_t size)
{
	void *p = malloc(size);

	if (p == NULL)
		ni_fatal("allocation failed malloc(%zu): %m", size);

	return p;
}
Exemplo n.º 8
0
char *
xstrdup(const char *string)
{
	char *p;

	if (string == NULL)
		return NULL;
	p = strdup(string);
	if (p == NULL)
		ni_fatal("allocation failed strdup(%s): %m", string);
	return p;
}
Exemplo n.º 9
0
const char *
ni_config_backupdir(void)
{
	ni_config_fslocation_t *fsloc = &ni_global.config->backupdir;
	static ni_bool_t firsttime = TRUE;

	if (firsttime) {
		if (ni_mkdir_maybe(fsloc->path, fsloc->mode) < 0)
			ni_fatal("Cannot create backup directory \"%s\": %m", fsloc->path);
		firsttime = FALSE;
	}

	return fsloc->path;
}
Exemplo n.º 10
0
/*
 * Open a file given O_* flags and permissions.
 */
static FILE *
__ni_file_open(const char *pathname, const char *fmode, unsigned int flags, unsigned int permissions)
{
	FILE *fp;
	int fd;

	if ((fd = open(pathname, flags, permissions)) < 0) {
		ni_error("unable to open file %s for %s: %m",
				pathname,
				(flags & O_ACCMODE) == O_RDONLY? "reading" : "writing");
		return NULL;
	}

	switch (flags & O_ACCMODE) {
	case O_RDONLY:
		fmode = "r"; break;

	case O_WRONLY:
		fmode = (flags & O_APPEND)? "a" : "w";
		break;

	case O_RDWR:
		fmode = (flags & O_APPEND)? "a+" : "w+";
		break;

	default:
		ni_fatal("%s: bad open mode 0%o", __func__, flags & O_ACCMODE);
	}

	fp = fdopen(fd, fmode);
	if (fp == NULL) {
		ni_error("%s: fdopen(%d, %s) failed: %m", __func__, fd, fmode);
		close(fd);
		return NULL;
	}

	return fp;
}
Exemplo n.º 11
0
/*
 * background the current process
 */
int
ni_daemonize(const char *pidfile, unsigned int permissions)
{
	pid_t pid;

	if (pidfile) {
		/* check if service is already running */

		pid = ni_pidfile_check(pidfile);
		if (pid < 0)
			return -1;

		if (pid > 0) {
			ni_error("cannot create pidfile %s: service already running", pidfile);
			return -1;
		}

		if (ni_file_exists(pidfile)) {
			if (unlink(pidfile) < 0) {
				ni_error("cannot remove stale pidfile %s: %m", pidfile);
				return -1;
			}
			ni_warn("removing stale pidfile %s", pidfile);
		}
	}

	if (pidfile && ni_pidfile_write(pidfile, permissions, getpid()) < 0)
		return -1;

	/* fork, chdir to root and close fds */
	if (daemon(0, 0) < 0)
		ni_fatal("unable to background process! daemon() failed: %m");

	if (pidfile)
		__ni_pidfile_write(pidfile, permissions, getpid(), 0);

	return 0;
}
Exemplo n.º 12
0
Arquivo: calls.c Projeto: mijos/wicked
/*
 * Create the client and return the handle of the root object
 */
ni_dbus_object_t *
ni_call_create_client(void)
{
	static ni_dbus_object_t *root_object = NULL;

	if (root_object == NULL) {
		ni_dbus_client_t *client;

		ni_objectmodel_init(NULL);

		/* Use ni_objectmodel_create_client() */
		client = ni_create_dbus_client(NI_OBJECTMODEL_DBUS_BUS_NAME);
		if (!client)
			ni_fatal("Unable to connect to wicked dbus service");

		root_object = ni_dbus_client_object_new(client,
					&ni_dbus_anonymous_class,
					NI_OBJECTMODEL_OBJECT_PATH,
					NI_OBJECTMODEL_INTERFACE,
					NULL);
	}

	return root_object;
}
Exemplo n.º 13
0
int
ni_dhcp4_tester_run(ni_dhcp4_tester_t *opts)
{
	ni_netconfig_t *nc;
	ni_netdev_t *ifp = NULL;
	ni_dhcp4_device_t *dev = NULL;
	ni_dhcp4_request_t *req = NULL;
	unsigned int link_timeout = 20;
	int rv;

	if (opts->timeout && opts->timeout != -1U) {
		link_timeout = (opts->timeout * 2) / 3;
		opts->timeout -= link_timeout;
	}

	if (!opts || ni_string_empty(opts->ifname))
		ni_fatal("Invalid start parameters!");

	dhcp4_tester_opts   = *opts;
	dhcp4_tester_status = NI_WICKED_RC_ERROR;

	if (!(nc = ni_global_state_handle(1)))
		ni_fatal("Cannot refresh interface list!");

	if (!(ifp = ni_netdev_by_name(nc, opts->ifname)))
		ni_fatal("Cannot find interface with name '%s'", opts->ifname);

	if (!ni_dhcp4_supported(ifp))
		ni_fatal("DHCPv4 not supported on '%s'", opts->ifname);

	if (!(dev = ni_dhcp4_device_new(ifp->name, &ifp->link)))
		ni_fatal("Cannot allocate dhcp4 client for '%s'", opts->ifname);

	ni_dhcp4_set_event_handler(ni_dhcp4_tester_protocol_event);

	if (!(req = ni_dhcp4_request_new())) {
		ni_error("Cannot allocate dhcp4 request");
		goto failure;
	}

	if (!ni_dhcp4_tester_req_init(req, opts->request))
		goto failure;

	if (!ni_netdev_link_is_up(ifp)) {
		ni_netdev_req_t *ifreq;
		ni_debug_dhcp("%s: Link is not up, trying to bring it up",
				ifp->name);

		ifreq = ni_netdev_req_new();
		ifreq->ifflags = NI_IFF_LINK_UP | NI_IFF_NETWORK_UP;
		if ((rv = ni_system_interface_link_change(ifp, ifreq)) < 0) {
			ni_error("%s: Unable to set up link", ifp->name);
			ni_netdev_req_free(ifreq);
			goto failure;
		}
		ni_netdev_req_free(ifreq);

		do {
			sleep(1);

			if (!(nc = ni_global_state_handle(1)))
				goto failure;

			if (!(ifp = ni_netdev_by_index(nc, dev->link.ifindex)))
				break;

			if (ni_netdev_link_is_up(ifp))
				break;

			ni_debug_dhcp("%s: Link is not (yet) up", ifp->name);
		} while (link_timeout-- > 1);

		if (!ifp || !ni_netdev_link_is_up(ifp) || !link_timeout) {
			ni_error("%s: Unable to bring link up",
				ifp && ifp->name ? ifp->name : dev->ifname);
			goto failure;
		}

		/* Do not try to send too early, even link is reported up now */
		sleep(1);
	}

	if (opts->timeout && opts->timeout != -1U)
		req->acquire_timeout = opts->timeout;

	req->broadcast = opts->broadcast;

	if ((rv = ni_dhcp4_acquire(dev, req)) < 0) {
		ni_error("%s: DHCP4v6 acquire request %s failed: %s",
				dev->ifname, ni_uuid_print(&req->uuid),
				ni_strerror(rv));
		goto failure;
	}

	dhcp4_tester_status = NI_WICKED_RC_IN_PROGRESS;
	while (!ni_caught_terminal_signal()) {
		long timeout;

		timeout = ni_timer_next_timeout();

		if (ni_socket_wait(timeout) != 0)
			break;
	}
	ni_server_deactivate_interface_events();
	ni_socket_deactivate_all();

failure:
	if (dev)
		ni_dhcp4_device_put(dev);
	if (req)
		ni_dhcp4_request_free(req);
	return dhcp4_tester_status;
}
Exemplo n.º 14
0
static int
ni_do_ifup_nanny(int argc, char **argv)
{
	enum  { OPT_HELP, OPT_IFCONFIG, OPT_CONTROL_MODE, OPT_STAGE, OPT_TIMEOUT,
		OPT_SKIP_ACTIVE, OPT_SKIP_ORIGIN, OPT_PERSISTENT, OPT_TRANSIENT,
#ifdef NI_TEST_HACKS
		OPT_IGNORE_PRIO, OPT_IGNORE_STARTMODE,
#endif
	};

	static struct option ifup_options[] = {
		{ "help",	no_argument,       NULL,	OPT_HELP },
		{ "ifconfig",	required_argument, NULL,	OPT_IFCONFIG },
		{ "mode",	required_argument, NULL,	OPT_CONTROL_MODE },
		{ "boot-stage",	required_argument, NULL,	OPT_STAGE },
		{ "skip-active",required_argument, NULL,	OPT_SKIP_ACTIVE },
		{ "skip-origin",required_argument, NULL,	OPT_SKIP_ORIGIN },
		{ "timeout",	required_argument, NULL,	OPT_TIMEOUT },
		{ "transient", 	no_argument,		NULL,	OPT_TRANSIENT },
#ifdef NI_TEST_HACKS
		{ "ignore-prio",no_argument, NULL,	OPT_IGNORE_PRIO },
		{ "ignore-startmode",no_argument, NULL,	OPT_IGNORE_STARTMODE },
#endif
		{ "persistent",	no_argument, NULL,	OPT_PERSISTENT },
		{ NULL }
	};

	ni_ifmatcher_t ifmatch;
	ni_ifworker_array_t ifmarked;
	ni_string_array_t opt_ifconfig = NI_STRING_ARRAY_INIT;
	ni_bool_t check_prio = TRUE, set_persistent = FALSE;
	ni_bool_t opt_transient = FALSE;
	int c, status = NI_WICKED_RC_USAGE;
	unsigned int timeout = 0;
	ni_fsm_t *fsm;

	fsm = ni_fsm_new();
	ni_assert(fsm);
	ni_fsm_require_register_type("reachable", ni_ifworker_reachability_check_new);

	memset(&ifmatch, 0, sizeof(ifmatch));
	memset(&ifmarked, 0, sizeof(ifmarked));

	/* Allow ifup on all interfaces we have config for */
	ifmatch.require_configured = FALSE;
	ifmatch.allow_persistent = TRUE;
	ifmatch.require_config = TRUE;

	optind = 1;
	while ((c = getopt_long(argc, argv, "", ifup_options, NULL)) != EOF) {
		switch (c) {
		case OPT_IFCONFIG:
			ni_string_array_append(&opt_ifconfig, optarg);
			break;

		case OPT_CONTROL_MODE:
			ifmatch.mode = optarg;
			break;

		case OPT_STAGE:
			ifmatch.boot_stage= optarg;
			break;

		case OPT_TIMEOUT:
			if (!strcmp(optarg, "infinite")) {
				timeout = NI_IFWORKER_INFINITE_TIMEOUT;
			} else {
				unsigned int sec;

				if (ni_parse_uint(optarg, &sec, 10) < 0) {
					ni_error("ifup: cannot parse timeout option \"%s\"", optarg);
					goto usage;
				}
				timeout = sec * 1000; /* sec -> msec */
			}
			break;

		case OPT_SKIP_ORIGIN:
			ifmatch.skip_origin = optarg;
			break;

		case OPT_SKIP_ACTIVE:
			ifmatch.skip_active = TRUE;
			break;

#ifdef NI_TEST_HACKS
		case OPT_IGNORE_PRIO:
			check_prio = FALSE;
			break;

		case OPT_IGNORE_STARTMODE:
			ifmatch.ignore_startmode = TRUE;
			break;
#endif

		case OPT_PERSISTENT:
			set_persistent = TRUE;
			break;

		case OPT_TRANSIENT:
			opt_transient = TRUE;
			break;

		default:
		case OPT_HELP:
usage:
			fprintf(stderr,
				"wicked [options] ifup [ifup-options] <ifname ...>|all\n"
				"\nSupported ifup-options:\n"
				"  --help\n"
				"      Show this help text.\n"
				"  --transient\n"
				"      Enable transient interface return codes\n"
				"  --ifconfig <pathname>\n"
				"      Read interface configuration(s) from file/directory rather than using system config\n"
				"  --mode <label>\n"
				"      Only touch interfaces with matching control <mode>\n"
				"  --boot-stage <label>\n"
				"      Only touch interfaces with matching <boot-stage>\n"
				"  --skip-active\n"
				"      Do not touch running interfaces\n"
				"  --skip-origin <name>\n"
				"      Skip interfaces that have a configuration origin of <name>\n"
				"      Usually, you would use this with the name \"firmware\" to avoid\n"
				"      touching interfaces that have been set up via firmware (like iBFT) previously\n"
				"  --timeout <nsec>\n"
				"      Timeout after <nsec> seconds\n"
#ifdef NI_TEST_HACKS
				"  --ignore-prio\n"
				"      Ignore checking the config origin priorities\n"
				"  --ignore-startmode\n"
				"      Ignore checking the STARTMODE=off and STARTMODE=manual configs\n"
#endif
				"  --persistent\n"
				"      Set interface into persistent mode (no regular ifdown allowed)\n"
				);
			goto cleanup;
		}
	}

	if (optind >= argc) {
		fprintf(stderr, "Missing interface argument\n");
		goto usage;
	}

	if (!ni_client_create(fsm, &ifmarked) || !ni_fsm_refresh_state(fsm)) {
		/* Severe error we always explicitly return */
		status = NI_WICKED_RC_ERROR;
		goto cleanup;
	}

	if (opt_ifconfig.count == 0) {
		const ni_string_array_t *sources = ni_config_sources("ifconfig");

		if (sources && sources->count)
			ni_string_array_copy(&opt_ifconfig, sources);

		if (opt_ifconfig.count == 0) {
			ni_error("ifup: unable to load interface config source list");
			status = NI_WICKED_RC_NOT_CONFIGURED;
			goto cleanup;
		}
	}

	if (!ni_ifconfig_load(fsm, opt_global_rootdir, &opt_ifconfig, check_prio, TRUE)) {
		status = NI_WICKED_RC_NOT_CONFIGURED;
		goto cleanup;
	}

	/* Client waits for device-up events for WAIT_FOR_INTERFACES */
	if (timeout)
		ni_wait_for_interfaces = timeout; /* One set by user */
	else
		ni_wait_for_interfaces *= 1000;   /* in msec */

	if (ni_wait_for_interfaces)
		fsm->worker_timeout = ni_wait_for_interfaces;

	if (ni_fsm_build_hierarchy(fsm) < 0) {
		ni_error("ifup: unable to build device hierarchy");
		/* Severe error we always explicitly return */
		status = NI_WICKED_RC_ERROR;
		goto cleanup;
	}

	status = NI_WICKED_RC_SUCCESS;

	/* Get workers that match given criteria */
	while (optind < argc) {
		ifmatch.name = argv[optind++];

		if (!strcmp(ifmatch.name, "boot")) {
			ifmatch.name = "all";
			ifmatch.mode = "boot";
		}

		ni_fsm_get_matching_workers(fsm, &ifmatch, &ifmarked);
	}

	if (!ni_ifup_start_policies(&ifmarked, set_persistent))
		status = NI_WICKED_RC_NOT_CONFIGURED;

	/* Wait for device-up events */
	ni_timer_register(ni_wait_for_interfaces, ni_client_timer_expires, &status);
	while (status == NI_WICKED_RC_SUCCESS) {
		/* status is already success */
		if (0 == ifmarked.count)
			break;

		if (ni_socket_wait(ni_wait_for_interfaces) != 0)
			ni_fatal("ni_socket_wait failed");

		ni_timer_next_timeout();
	}

	/* Do not report any transient errors to systemd (e.g. dhcp
	 * or whatever not ready in time) -- returning an error may
	 * cause to stop the network completely.
	 */
	if (!opt_transient)
		status = NI_LSB_RC_SUCCESS;

cleanup:
	ni_ifworker_array_destroy(&ifmarked);
	ni_string_array_destroy(&opt_ifconfig);
	return status;
}