Esempio n. 1
0
/*
 * Create a unique interface name
 */
const char *
ni_netdev_make_name(ni_netconfig_t *nc, const char *stem, unsigned int first)
{
	static char namebuf[64];
	unsigned int num;

	for (num = first; num < 65536; ++num) {
		snprintf(namebuf, sizeof(namebuf), "%s%u", stem, num);
		if (!ni_netdev_by_name(nc, namebuf))
			return namebuf;
	}

	return NULL;
}
Esempio n. 2
0
ni_netdev_t *
ni_netdev_ref_bind_ifindex(ni_netdev_ref_t *ref, ni_netconfig_t *nc)
{
	ni_netdev_t *dev;

	if (!ref || (!nc && !(nc = ni_global_state_handle(0))))
		return NULL;

	dev = ni_netdev_by_name(nc, ref->name);
	if (dev == NULL)
		return NULL;

	ref->index = dev->link.ifindex;
	return dev;
}
Esempio n. 3
0
ni_netdev_t *
ni_netdev_ref_resolve(ni_netdev_ref_t *ref, ni_netconfig_t *nc)
{
	ni_netdev_t *dev = NULL;

	if (!ref || (!nc && !(nc = ni_global_state_handle(0))))
		return NULL;

	if (ref->index && (dev = ni_netdev_by_index(nc, ref->index)))
		return dev;

	if (ref->name && (dev = ni_netdev_by_name(nc, ref->name)))
		return dev;

	return NULL;
}
Esempio n. 4
0
static int
__do_arp_validate_init(struct arp_handle *handle, ni_capture_devinfo_t *dev_info)
{
	ni_netconfig_t *nc;
	ni_netdev_t *dev;

	if (ni_server_listen_interface_events(NULL) < 0) {
		ni_error("unable to initialize netlink link listener");
		return NI_LSB_RC_ERROR;
	}
	if (ni_server_enable_interface_addr_events(NULL) < 0) {
		ni_error("unable to initialize netlink addr listener");
		return NI_LSB_RC_ERROR;
	}

	if (!(nc = ni_global_state_handle(1))) {
		ni_error("Cannot refresh interface list!");
		return NI_LSB_RC_ERROR;
	}

	if (!(dev = ni_netdev_by_name(nc, handle->ifname))) {
		ni_error("Cannot find interface with name '%s'",
				handle->ifname);
		return NI_LSB_RC_ERROR;
	}
	if (!ni_netdev_supports_arp(dev)) {
		ni_error("%s: arp is not supported/enabled", dev->name);
		return NI_LSB_RC_ERROR;
	}
	if (!ni_netdev_link_is_up(dev)) {
		ni_error("%s: link is not up", dev->name);
		return NI_LSB_RC_ERROR;
	}

	if (ni_capture_devinfo_init(dev_info, dev->name, &dev->link) < 0) {
		ni_error("%s: cannot initialize capture", dev->name);
		return NI_LSB_RC_ERROR;
	}

	return 0;
}
Esempio n. 5
0
/*
 * Process NEWLINK event
 */
int
__ni_rtevent_newlink(ni_netconfig_t *nc, const struct sockaddr_nl *nladdr, struct nlmsghdr *h)
{
	char namebuf[IF_NAMESIZE+1] = {'\0'};
	ni_netdev_t *dev, *old;
	struct ifinfomsg *ifi;
	struct nlattr *nla;
	char *ifname = NULL;
	int old_flags = 0;

	if (!(ifi = ni_rtnl_ifinfomsg(h, RTM_NEWLINK)))
		return -1;

	if (ifi->ifi_family == AF_BRIDGE)
		return 0;

	old = ni_netdev_by_index(nc, ifi->ifi_index);
	ifname = if_indextoname(ifi->ifi_index, namebuf);
	if (!ifname) {
		/*
		 * device (index) does not exists any more;
		 * process deletion/cleanup of the device.
		 */
		if (old) {
			old_flags = old->link.ifflags;
			old->link.ifflags = 0;
			old->deleted = 1;

			__ni_netdev_process_events(nc, old, old_flags);
			ni_client_state_drop(old->link.ifindex);
			ni_netconfig_device_remove(nc, old);
		}
		return 0;
	}

	if (old) {
		if (!ni_string_eq(old->name, ifname)) {
			ni_debug_events("%s[%u]: device renamed to %s",
					old->name, old->link.ifindex, ifname);
			ni_string_dup(&old->name, ifname);
			__ni_netdev_event(nc, old, NI_EVENT_DEVICE_RENAME);
		}
		dev = old;
		old_flags = old->link.ifflags;
	} else {
		if (!(dev = ni_netdev_new(ifname, ifi->ifi_index))) {
			ni_warn("%s[%u]: unable to allocate memory for device",
					ifname, ifi->ifi_index);
			return -1;
		}
		dev->created = 1;
		ni_netconfig_device_append(nc, dev);
	}

	if (__ni_netdev_process_newlink(dev, h, ifi, nc) < 0) {
		ni_error("Problem parsing RTM_NEWLINK message for %s", ifname);
		return -1;
	}

	if ((ifname = dev->name)) {
		ni_netdev_t *conflict;

		conflict = ni_netdev_by_name(nc, ifname);
		if (conflict && conflict->link.ifindex != (unsigned int)ifi->ifi_index) {
			/*
			 * As the events often provide an already obsolete name [2 events,
			 * we process 1st with next in read buffer], we are reading the
			 * current dev->name in advance (above).
			 *
			 * On a rename like eth0->rename1->eth1, eth1->rename2->eth0, the
			 * current dev->name is already eth1 at processing time of eth0
			 * to rename1 event. This sometimes causes that we find eth1 in
			 * our device list [eth1 -> rename2 event in the read buffer].
			 *
			 * Just update the name of the conflicting device in advance too
			 * and when the interface does not exist any more, emit events.
			 */
			char *current = if_indextoname(conflict->link.ifindex, namebuf);
			if (current) {
				ni_string_dup(&conflict->name, current);
				__ni_netdev_event(nc, conflict, NI_EVENT_DEVICE_RENAME);
			} else {
				unsigned int ifflags = conflict->link.ifflags;
				conflict->link.ifflags = 0;
				conflict->deleted = 1;

				__ni_netdev_process_events(nc, conflict, ifflags);
				ni_client_state_drop(conflict->link.ifindex);
				ni_netconfig_device_remove(nc, conflict);
			}
		}
	}

	__ni_netdev_process_events(nc, dev, old_flags);

	if ((nla = nlmsg_find_attr(h, sizeof(*ifi), IFLA_WIRELESS)) != NULL)
		__ni_wireless_link_event(nc, dev, nla_data(nla), nla_len(nla));

	return 0;
}
Esempio n. 6
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;
}
Esempio n. 7
0
static int
ni_do_duid_create_ll_type(uint16_t type, int argc, char **argv)
{
	enum {	OPT_HELP = 'h', OPT_SCOPE = 's', OPT_UPDATE = 'u' };
	static struct option    options[] = {
		{ "help",	no_argument,		NULL,	OPT_HELP	},
		{ "scope",	required_argument,	NULL,	OPT_SCOPE	},
		{ "update",	no_argument,		NULL,	OPT_UPDATE	},
		{ NULL,		no_argument,		NULL,	0		}
	};
	int opt = 0, status = NI_WICKED_RC_USAGE;
	const char *scope = NULL;
	ni_bool_t update = FALSE;
	const char *ifname = NULL;
	const char *hwtype = NULL;
	const char *hwaddr = NULL;
	const char *hex = NULL;
	ni_opaque_t raw;

	optind = 1;
	while ((opt = getopt_long(argc, argv, "+hs:u", options, NULL)) != EOF) {
		switch (opt) {
		case OPT_UPDATE:
			update = TRUE;
			break;
		case OPT_SCOPE:
			if (optarg && !ni_string_eq(optarg, "default"))
				scope = optarg;
			break;
		case OPT_HELP:
			status = NI_WICKED_RC_SUCCESS;
		default:
		usage:
			fprintf(stderr,
				"Usage: %s [options] [ [ifname] | <hwtype> <hwaddr> ]\n"
				"\n"
				"Options:\n"
				"  --help, -h           show this help text and exit.\n"
				"  --scope <ifname>     create device specific duid instead of default\n"
				"  --update             create a duid and update duid map file\n"
				"\n"
				"Arguments:\n"
				"  ifname               get hardware type and address from interface\n"
				"  htwype               hardware type to use in the duid\n"
				"  htaddr               hardware address to use in the duid\n"
				"\n", argv[0]);
			ni_do_duid_create_ll_print_hwtypes(stderr);
			goto cleanup;
		}
	}
	switch (argc - optind) {
	case 2:
		hwtype = argv[optind++];
		hwaddr = argv[optind++];
		break;
	case 1:
		ifname = argv[optind++];
		break;
	case 0:
		break;
	default:
		goto usage;
	}

	status = NI_WICKED_RC_ERROR;
	if (scope && !ni_netdev_name_is_valid(scope)) {
		fprintf(stderr, "%s: invalid scope interface name '%s'\n", argv[0],
				ni_print_suspect(scope, ni_string_len(scope)));
		goto cleanup;
	}

	if (hwtype || hwaddr) {
		switch (type) {
		case NI_DUID_TYPE_LL:
			if (ni_duid_create_ll(&raw, hwtype, hwaddr))
				status = NI_WICKED_RC_SUCCESS;
			break;
		case NI_DUID_TYPE_LLT:
			if (ni_duid_create_llt(&raw, hwtype, hwaddr))
				status = NI_WICKED_RC_SUCCESS;
			break;
		default:
			break;
		}
		if (status != NI_WICKED_RC_SUCCESS) {
			fprintf(stderr, "%s: cannot create duid using hardware type '%s' and address '%s'\n",
				argv[0], hwtype, hwaddr);
			goto cleanup;
		}
	} else {
		ni_netconfig_t *nc = ni_global_state_handle(1);
		ni_netdev_t *dev = NULL;

		if (!nc) {
			fprintf(stderr, "%s: cannot retrieve interface properties", argv[0]);
			goto cleanup;
		}

		if (ifname) {
			dev = ni_netdev_by_name(nc, ifname);
			if (!dev || !ni_duid_create_from_device(&raw, type, dev)) {
				hwtype = dev ? ni_duid_hwtype_to_name(dev->link.hwaddr.type) : "missing";
				fprintf(stderr, "%s: unable to create %s duid using %s device '%s'\n",
					argv[0], ni_duid_type_to_name(type),
					hwtype ? hwtype : "unsupported", ifname);
				goto cleanup;
			}
		} else {
			dev = scope ? ni_netdev_by_name(nc, scope) : NULL;
			if (!ni_duid_create_pref_device(&raw, type, nc, dev)) {
				fprintf(stderr, "%s: unable to create any %s duid (no usable devices)",
					argv[0], ni_duid_type_to_name(type));
				goto cleanup;
			}
		}
	}

	status = NI_WICKED_RC_ERROR;
	hex = raw.len ? ni_duid_print_hex(&raw) : NULL;
	if (ni_string_empty(hex)) {
		fprintf(stderr, "%s: cannot format en duid as a colon-separated hex string\n", argv[0]);
		goto cleanup;
	}

	if (update) {
		status = ni_do_duid_create_update(scope, hex);
		if (status != NI_WICKED_RC_SUCCESS) {
			fprintf(stderr, "%s: cannot update duid map file using the created duid\n", argv[0]);
			goto cleanup;
		}
	}

	printf("%s\t%s\n", scope ? scope : "default", hex);
	status = NI_WICKED_RC_SUCCESS;

cleanup:
	return status;
}