Пример #1
0
/*!	If there are any arguments given, this will remove only the specified
	addresses from the interface named \a name.
	If there are no arguments, it will remove the complete interface with all
	of its addresses.
*/
void
delete_interface(const char* name, char* const* args, int32 argCount)
{
	BNetworkInterface interface(name);

	for (int32 i = 0; i < argCount; i++) {
		int family = get_address_family(args[i]);
		if (family != AF_UNSPEC)
			i++;

		BNetworkAddress address;
		if (!parse_address(family, args[i], address)) {
			fprintf(stderr, "%s: Could not parse address \"%s\".\n",
				kProgramName, args[i]);
			exit(1);
		}

		status_t status = interface.RemoveAddress(address);
		if (status != B_OK) {
			fprintf(stderr, "%s: Could not delete address %s from interface %s:"
				" %s\n", kProgramName, args[i], name, strerror(status));
		}
	}

	if (argCount == 0) {
		// Delete interface
		BNetworkRoster& roster = BNetworkRoster::Default();

		status_t status = roster.RemoveInterface(interface);
		if (status != B_OK) {
			fprintf(stderr, "%s: Could not delete interface %s: %s\n",
				kProgramName, name, strerror(errno));
		}
	}
}
Пример #2
0
static int	process_ping(ZBX_FPING_HOST *hosts, int hosts_count, int count, int interval, int size, int timeout,
		char *error, int max_error_len)
{
	const char	*__function_name = "process_ping";

	FILE		*f;
	char		*c, *c2, params[64];
	char		filename[MAX_STRING_LEN], tmp[MAX_STRING_LEN];
	int		i;
	ZBX_FPING_HOST	*host;
	double		sec;
	int 		ret = NOTSUPPORTED;

#ifdef HAVE_IPV6
	int		family;
	char		params6[64];
	char		fping_existence = 0;
#define	FPING_EXISTS	0x1
#define	FPING6_EXISTS	0x2

#endif	/* HAVE_IPV6 */

	assert(hosts);

	zabbix_log(LOG_LEVEL_DEBUG, "In %s() hosts_count:%d", __function_name, hosts_count);

	if (-1 == access(CONFIG_FPING_LOCATION, F_OK | X_OK))
	{
#if !defined(HAVE_IPV6)
		zbx_snprintf(error, max_error_len, "%s: %s", CONFIG_FPING_LOCATION, zbx_strerror(errno));
		return ret;
#endif
	}
	else
	{
#ifdef HAVE_IPV6
		fping_existence |= FPING_EXISTS;
#else
		if (NULL != CONFIG_SOURCE_IP)
		{
			if (FAIL == is_ip4(CONFIG_SOURCE_IP)) /* we do not have IPv4 family address in CONFIG_SOURCE_IP */
			{
				zbx_snprintf(error, max_error_len,
					"You should enable IPv6 support to use IPv6 family address for SourceIP '%s'.", CONFIG_SOURCE_IP);
				return ret;
			}
		}
#endif
	}

#ifdef HAVE_IPV6
	if (-1 == access(CONFIG_FPING6_LOCATION, F_OK | X_OK))
	{
		if (0 == (fping_existence & FPING_EXISTS))
		{
			zbx_snprintf(error, max_error_len, "At least one of '%s', '%s' must exist. Both are missing in the system.",
					CONFIG_FPING_LOCATION,
					CONFIG_FPING6_LOCATION);
			return ret;
		}
	}
	else
		fping_existence |= FPING6_EXISTS;
#endif	/* HAVE_IPV6 */

	i = zbx_snprintf(params, sizeof(params), "-q -C%d", count);
	if (0 != interval)
		i += zbx_snprintf(params + i, sizeof(params) - i, " -p%d", interval);
	if (0 != size)
		i += zbx_snprintf(params + i, sizeof(params) - i, " -b%d", size);
	if (0 != timeout)
		i += zbx_snprintf(params + i, sizeof(params) - i, " -t%d", timeout);

#ifdef HAVE_IPV6
	strscpy(params6, params);
#endif	/* HAVE_IPV6 */

	if (NULL != CONFIG_SOURCE_IP)
	{
#ifdef HAVE_IPV6
		if (0 != (fping_existence & FPING_EXISTS))
		{
			if (0 == source_ip_checked)
				get_source_ip_option(CONFIG_FPING_LOCATION, &source_ip_option, &source_ip_checked);
			if (NULL != source_ip_option)
				zbx_snprintf(params + i, sizeof(params) - i, " %s%s", source_ip_option, CONFIG_SOURCE_IP);
		}

		if (0 != (fping_existence & FPING6_EXISTS))
		{
			if (0 == source_ip6_checked)
				get_source_ip_option(CONFIG_FPING6_LOCATION, &source_ip6_option, &source_ip6_checked);
			if (NULL != source_ip6_option)
				zbx_snprintf(params6 + i, sizeof(params6) - i, " %s%s", source_ip6_option, CONFIG_SOURCE_IP);
		}
#else
		if (0 == source_ip_checked)
			get_source_ip_option(CONFIG_FPING_LOCATION, &source_ip_option, &source_ip_checked);
		if (NULL != source_ip_option)
			zbx_snprintf(params + i, sizeof(params) - i, " %s%s", source_ip_option, CONFIG_SOURCE_IP);
#endif	/* HAVE_IPV6 */
	}

	zbx_snprintf(filename, sizeof(filename), "%s/%s_%li.pinger", CONFIG_TMPDIR, progname, zbx_get_thread_id());

#ifdef HAVE_IPV6
	if (NULL != CONFIG_SOURCE_IP)
	{
		if (SUCCEED != get_address_family(CONFIG_SOURCE_IP, &family, error, max_error_len))
			return ret;

		if (family == PF_INET)
		{
			if (0 == (fping_existence & FPING_EXISTS))
			{
				zbx_snprintf(error, max_error_len, "File '%s' cannot be found in the system.",
						CONFIG_FPING_LOCATION);
				return ret;
			}

			zbx_snprintf(tmp, sizeof(tmp), "%s %s 2>&1 <%s", CONFIG_FPING_LOCATION, params, filename);
		}
		else
		{
			if (0 == (fping_existence & FPING6_EXISTS))
			{
				zbx_snprintf(error, max_error_len, "File '%s' cannot be found in the system.",
						CONFIG_FPING6_LOCATION);
				return ret;
			}

			zbx_snprintf(tmp, sizeof(tmp), "%s %s 2>&1 <%s", CONFIG_FPING6_LOCATION, params6, filename);
		}
	}
	else
	{
		i = 0;

		if (0 != (fping_existence & FPING_EXISTS))
			i += zbx_snprintf(tmp + i, sizeof(tmp) - i, "%s %s 2>&1 <%s;", CONFIG_FPING_LOCATION, params, filename);

		if (0 != (fping_existence & FPING6_EXISTS))
			i += zbx_snprintf(tmp + i, sizeof(tmp) - i, "%s %s 2>&1 <%s;", CONFIG_FPING6_LOCATION, params6, filename);
	}
#else
	zbx_snprintf(tmp, sizeof(tmp), "%s %s 2>&1 <%s", CONFIG_FPING_LOCATION, params, filename);
#endif	/* HAVE_IPV6 */

	if (NULL == (f = fopen(filename, "w")))
	{
		zbx_snprintf(error, max_error_len, "%s: %s", filename, zbx_strerror(errno));
		return ret;
	}

	zabbix_log(LOG_LEVEL_DEBUG, "%s", filename);

	for (i = 0; i < hosts_count; i++)
	{
		zabbix_log(LOG_LEVEL_DEBUG, "%s", hosts[i].addr);
		fprintf(f, "%s\n", hosts[i].addr);
	}

	fclose(f);

	zabbix_log(LOG_LEVEL_DEBUG, "%s", tmp);

	if (NULL == (f = popen(tmp, "r")))
	{
		zbx_snprintf(error, max_error_len, "%s: %s", tmp, zbx_strerror(errno));

		unlink(filename);

		return ret;
	}

	if (NULL == fgets(tmp, sizeof(tmp), f))
	{
		ret = SUCCEED; /* fping does not output anything for DNS names that fail to resolve */
	}
	else
	{
		do
		{
			zbx_rtrim(tmp, "\n");
			zabbix_log(LOG_LEVEL_DEBUG, "read line [%s]", tmp);

			host = NULL;

			if (NULL != (c = strchr(tmp, ' ')))
			{
				*c = '\0';
				for (i = 0; i < hosts_count; i++)
					if (0 == strcmp(tmp, hosts[i].addr))
					{
						host = &hosts[i];
						break;
					}
				*c = ' ';
			}

			if (NULL == host)
				continue;

			if (NULL == (c = strstr(tmp, " : ")))
				continue;

			/* when NIC bonding is used, there are also lines like */
			/* 192.168.1.2 : duplicate for [0], 96 bytes, 0.19 ms */

			if (NULL != strstr(tmp, "duplicate for"))
				continue;

			c += 3;

			do
			{
				if (NULL != (c2 = strchr(c, ' ')))
					*c2 = '\0';

				if (0 != strcmp(c, "-"))
				{
					sec = atof(c) / 1000; /* convert ms to seconds */

					if (host->rcv == 0 || host->min > sec)
						host->min = sec;
					if (host->rcv == 0 || host->max < sec)
						host->max = sec;
					host->avg = (host->avg * host->rcv + sec) / (host->rcv + 1);
					host->rcv++;
				}

				host->cnt++;

				if (NULL != c2)
					*c2++ = ' ';
			}
			while (NULL != (c = c2));

			ret = SUCCEED;
		}
		while (NULL != fgets(tmp, sizeof(tmp), f));
	}
	pclose(f);

	unlink(filename);

	if (NOTSUPPORTED == ret)
		zbx_snprintf(error, max_error_len, "fping failed: \"%s\"", tmp);

	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);

	return ret;
}
Пример #3
0
static int	process_ping(ZBX_FPING_HOST *hosts, int hosts_count, char *error, int max_error_len)
{
	FILE		*f;
	char		filename[MAX_STRING_LEN], tmp[MAX_STRING_LEN],
			*c, source_ip[64];
	int		i;
	ZBX_FPING_HOST	*host;
#ifdef HAVE_IPV6
	char		*fping;
	int		family;
#endif

	assert(hosts);

	zabbix_log(LOG_LEVEL_DEBUG, "In process_ping()");

	if (NULL != CONFIG_SOURCE_IP)
		zbx_snprintf(source_ip, sizeof(source_ip), "-S%s ", CONFIG_SOURCE_IP);
	else
		*source_ip = '\0';

	if (access(CONFIG_FPING_LOCATION, F_OK|X_OK) == -1)
	{
		zbx_snprintf(error, max_error_len, "%s: [%d] %s", CONFIG_FPING_LOCATION, errno, strerror(errno));
		return NOTSUPPORTED;
	}

	zbx_snprintf(filename, sizeof(filename), "%s/zabbix_server_%li.pinger",
			CONFIG_TMPDIR,
			zbx_get_thread_id());

#ifdef HAVE_IPV6
	if (access(CONFIG_FPING6_LOCATION, F_OK|X_OK) == -1)
	{
		zbx_snprintf(error, max_error_len, "%s: [%d] %s", CONFIG_FPING6_LOCATION, errno, strerror(errno));
		return NOTSUPPORTED;
	}

	if (NULL != CONFIG_SOURCE_IP)
	{
		if (NOTSUPPORTED == get_address_family(CONFIG_SOURCE_IP, &family, error, max_error_len))
			return NOTSUPPORTED;

		if (family == PF_INET)
			fping = CONFIG_FPING_LOCATION;
		else
			fping = CONFIG_FPING6_LOCATION;

		zbx_snprintf(tmp, sizeof(tmp), "%s %s-c3 2>/dev/null <%s",
				fping,
				source_ip,
				filename);
	}
	else
		zbx_snprintf(tmp, sizeof(tmp), "%s -c3 2>/dev/null <%s;%s -c3 2>/dev/null <%s",
				CONFIG_FPING_LOCATION,
				filename,
				CONFIG_FPING6_LOCATION,
				filename);
#else /* HAVE_IPV6 */
	zbx_snprintf(tmp, sizeof(tmp), "%s %s-c3 2>/dev/null <%s",
			CONFIG_FPING_LOCATION,
			source_ip,
			filename);
#endif /* HAVE_IPV6 */

	if (NULL == (f = fopen(filename, "w"))) {
		zbx_snprintf(error, max_error_len, "%s: [%d] %s", filename, errno, strerror(errno));
		return NOTSUPPORTED;
	}

	zabbix_log(LOG_LEVEL_DEBUG, "%s", filename);

	for (i = 0; i < hosts_count; i++)
	{
		zabbix_log(LOG_LEVEL_DEBUG, "%s", hosts[i].addr);
		fprintf(f, "%s\n", hosts[i].addr);
	}

	fclose(f);

	zabbix_log(LOG_LEVEL_DEBUG, "%s", tmp);

	if (0 == (f = popen(tmp, "r"))) {
		zbx_snprintf(error, max_error_len, "%s: [%d] %s", tmp, errno, strerror(errno));

		unlink(filename);

		return NOTSUPPORTED;
	}

	while (NULL != fgets(tmp, sizeof(tmp), f)) {
		zbx_rtrim(tmp, "\n");
		zabbix_log(LOG_LEVEL_DEBUG, "Update IP [%s]",
				tmp);

		/* 12fc::21 : [0], 76 bytes, 0.39 ms (0.39 avg, 0% loss) */

		host = NULL;

		if (NULL != (c = strchr(tmp, ' '))) {
			*c = '\0';
			for (i = 0; i < hosts_count; i++)
				if (0 == strcmp(tmp, hosts[i].addr)) {
					host = &hosts[i];
					break;
				}
		}

		if (NULL != host) {
			c++;
			if (NULL != (c = strchr(c, '('))) {
				c++;
				host->alive = 1;
				host->sec = atof(c)/1000;
			}
		}
	}
	pclose(f);

	unlink(filename);

	zabbix_log(LOG_LEVEL_DEBUG, "End of process_ping()");

	return SUCCEED;
}
Пример #4
0
void
configure_interface(int socket, const char* name, char* const* args,
	int32 argCount)
{
	ifreq request;
	if (!prepare_request(request, name))
		return;

	uint32 index = 0;
	if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) >= 0)
		index = request.ifr_index;

	bool hasAddress = false, hasMask = false, hasPeer = false;
	bool hasBroadcast = false, doAutoConfig = false;
	struct sockaddr address, mask, peer, broadcast;
	int mtu = -1, metric = -1, media = -1;
	int addFlags = 0, currentFlags = 0, removeFlags = 0;

	// try to parse address family

	int32 familyIndex;
	int32 i = 0;
	if (get_address_family(args[i], familyIndex))
		i++;

	if (kFamilies[familyIndex].family != AF_INET) {
		close(socket);

		// replace socket with one of the correct address family
		socket = ::socket(kFamilies[familyIndex].family, SOCK_DGRAM, 0);
		if (socket < 0) {
			fprintf(stderr, "%s: Address family \"%s\" is not available.\n",
				kProgramName, kFamilies[familyIndex].name);
			exit(1);
		}
	}

	if (index == 0) {
		// the interface does not exist yet, we have to add it first
		request.ifr_parameter.base_name[0] = '\0';
		request.ifr_parameter.device[0] = '\0';
		request.ifr_parameter.sub_type = 0;
			// the default device is okay for us

		if (ioctl(socket, SIOCAIFADDR, &request, sizeof(request)) < 0) {
			fprintf(stderr, "%s: Could not add interface: %s\n", kProgramName,
				strerror(errno));
			exit(1);
		}
	}

	// try to parse address

	if (parse_address(familyIndex, args[i], address)) {
		hasAddress = true;
		i++;

		if (parse_address(familyIndex, args[i], mask)) {
			hasMask = true;
			i++;
		}
	}

	// parse parameters and flags

	while (i < argCount) {
		if (!strcmp(args[i], "peer")) {
			if (!parse_address(familyIndex, args[i + 1], peer)) {
				fprintf(stderr, "%s: Option 'peer' needs valid address "
					"parameter\n", kProgramName);
				exit(1);
			}
			hasPeer = true;
			i++;
		} else if (!strcmp(args[i], "nm") || !strcmp(args[i], "netmask")) {
			if (hasMask) {
				fprintf(stderr, "%s: Netmask is specified twice\n",
					kProgramName);
				exit(1);
			}
			if (!parse_address(familyIndex, args[i + 1], mask)) {
				fprintf(stderr, "%s: Option 'netmask' needs valid address "
					"parameter\n", kProgramName);
				exit(1);
			}
			hasMask = true;
			i++;
		} else if (!strcmp(args[i], "bc") || !strcmp(args[i], "broadcast")) {
			if (hasBroadcast) {
				fprintf(stderr, "%s: broadcast address is specified twice\n",
					kProgramName);
				exit(1);
			}
			if (!parse_address(familyIndex, args[i + 1], broadcast)) {
				fprintf(stderr, "%s: Option 'broadcast' needs valid address "
					"parameter\n", kProgramName);
				exit(1);
			}
			hasBroadcast = true;
			addFlags |= IFF_BROADCAST;
			i++;
		} else if (!strcmp(args[i], "mtu")) {
			mtu = args[i + 1] ? strtol(args[i + 1], NULL, 0) : 0;
			if (mtu <= 500) {
				fprintf(stderr, "%s: Option 'mtu' expected valid max transfer "
					"unit size\n", kProgramName);
				exit(1);
			}
			i++;
		} else if (!strcmp(args[i], "metric")) {
			if (i + 1 >= argCount) {
				fprintf(stderr, "%s: Option 'metric' exptected parameter\n",
					kProgramName);
				exit(1);
			}
			metric = strtol(args[i + 1], NULL, 0);
			i++;
		} else if (!strcmp(args[i], "media")) {
			if (ioctl(socket, SIOCGIFMEDIA, &request,
					sizeof(struct ifreq)) < 0) {
				fprintf(stderr, "%s: Unable to detect media type\n",
					kProgramName);
				exit(1);
			}
			if (i + 1 >= argCount) {
				fprintf(stderr, "%s: Option 'media' exptected parameter\n",
					kProgramName);
				exit(1);
			}
			if (!media_parse_subtype(args[i + 1], IFM_TYPE(request.ifr_media),
					&media)) {
				fprintf(stderr, "%s: Invalid parameter for option 'media': "
					"'%s'\n", kProgramName, args[i + 1]);
				exit(1);
			}
			i++;
		} else if (!strcmp(args[i], "up") || !strcmp(args[i], "-down")) {
			addFlags |= IFF_UP;
		} else if (!strcmp(args[i], "down") || !strcmp(args[i], "-up")) {
			removeFlags |= IFF_UP;
		} else if (!strcmp(args[i], "bcast")) {
			addFlags |= IFF_BROADCAST;
		} else if (!strcmp(args[i], "-bcast")) {
			removeFlags |= IFF_BROADCAST;
		} else if (!strcmp(args[i], "promisc")) {
			addFlags |= IFF_PROMISC;
		} else if (!strcmp(args[i], "-promisc")) {
			removeFlags |= IFF_PROMISC;
		} else if (!strcmp(args[i], "allmulti")) {
			addFlags |= IFF_ALLMULTI;
		} else if (!strcmp(args[i], "-allmulti")) {
			removeFlags |= IFF_ALLMULTI;
		} else if (!strcmp(args[i], "loopback")) {
			addFlags |= IFF_LOOPBACK;
		} else if (!strcmp(args[i], "auto-config")) {
			doAutoConfig = true;
		} else
			usage(1);

		i++;
	}

	if ((addFlags & removeFlags) != 0) {
		fprintf(stderr, "%s: Contradicting flags specified\n", kProgramName);
		exit(1);
	}

	if (doAutoConfig && (hasAddress || hasMask || hasBroadcast || hasPeer)) {
		fprintf(stderr, "%s: Contradicting changes specified\n", kProgramName);
		exit(1);
	}

	// set address/mask/broadcast/peer

	if (hasAddress) {
		memcpy(&request.ifr_addr, &address, address.sa_len);

		if (ioctl(socket, SIOCSIFADDR, &request, sizeof(struct ifreq)) < 0) {
			fprintf(stderr, "%s: Setting address failed: %s\n", kProgramName,
				strerror(errno));
			exit(1);
		}
	}

	if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) < 0) {
		fprintf(stderr, "%s: Getting flags failed: %s\n", kProgramName,
			strerror(errno));
		exit(1);
	}
	currentFlags = request.ifr_flags;

	if (hasMask) {
		memcpy(&request.ifr_mask, &mask, mask.sa_len);

		if (ioctl(socket, SIOCSIFNETMASK, &request, sizeof(struct ifreq)) < 0) {
			fprintf(stderr, "%s: Setting subnet mask failed: %s\n",
				kProgramName, strerror(errno));
			exit(1);
		}
	}

	if (hasBroadcast) {
		memcpy(&request.ifr_broadaddr, &broadcast, broadcast.sa_len);

		if (ioctl(socket, SIOCSIFBRDADDR, &request, sizeof(struct ifreq)) < 0) {
			fprintf(stderr, "%s: Setting broadcast address failed: %s\n",
				kProgramName, strerror(errno));
			exit(1);
		}
	}

	if (hasPeer) {
		memcpy(&request.ifr_dstaddr, &peer, peer.sa_len);

		if (ioctl(socket, SIOCSIFDSTADDR, &request, sizeof(struct ifreq)) < 0) {
			fprintf(stderr, "%s: Setting peer address failed: %s\n",
				kProgramName, strerror(errno));
			exit(1);
		}
	}

	// set flags

	if (hasAddress || hasMask || hasBroadcast || hasPeer)
		removeFlags = IFF_AUTO_CONFIGURED | IFF_CONFIGURING;

	if (addFlags || removeFlags) {
		request.ifr_flags = (currentFlags & ~removeFlags) | addFlags;
		if (ioctl(socket, SIOCSIFFLAGS, &request, sizeof(struct ifreq)) < 0) {
			fprintf(stderr, "%s: Setting flags failed: %s\n", kProgramName,
				strerror(errno));
		}
	}

	// set options

	if (mtu != -1) {
		request.ifr_mtu = mtu;
		if (ioctl(socket, SIOCSIFMTU, &request, sizeof(struct ifreq)) < 0) {
			fprintf(stderr, "%s: Setting MTU failed: %s\n", kProgramName,
				strerror(errno));
		}
	}

	if (metric != -1) {
		request.ifr_metric = metric;
		if (ioctl(socket, SIOCSIFMETRIC, &request, sizeof(struct ifreq)) < 0) {
			fprintf(stderr, "%s: Setting metric failed: %s\n", kProgramName,
				strerror(errno));
		}
	}

	if (media != -1) {
		request.ifr_media = media;
		if (ioctl(socket, SIOCSIFMEDIA, &request, sizeof(struct ifreq)) < 0) {
			fprintf(stderr, "%s: Setting media failed: %s\n", kProgramName,
				strerror(errno));
		}
	}

	// start auto configuration, if asked for

	if (doAutoConfig) {
		BMessage message(kMsgConfigureInterface);
		message.AddString("device", name);
		BMessage address;
		address.AddString("family", "inet");
		address.AddBool("auto_config", true);
		message.AddMessage("address", &address);

		BMessenger networkServer(kNetServerSignature);
		if (networkServer.IsValid()) {
			BMessage reply;
			status_t status = networkServer.SendMessage(&message, &reply);
			if (status != B_OK) {
				fprintf(stderr, "%s: Sending auto-config message failed: %s\n",
					kProgramName, strerror(status));
			} else if (reply.FindInt32("status", &status) == B_OK
					&& status != B_OK) {
				fprintf(stderr, "%s: Auto-configuring failed: %s\n",
					kProgramName, strerror(status));
			}
		} else {
			fprintf(stderr, "%s: The net_server needs to run for the auto "
				"configuration!\n", kProgramName);
		}
	}
}
Пример #5
0
static int	process_ping(ZBX_FPING_HOST *hosts, int hosts_count, int count, int interval, int size, int timeout,
		char *error, int max_error_len)
{
	const char	*__function_name = "process_ping";

	FILE		*f;
	char		*c, params[64];
	char		filename[MAX_STRING_LEN], tmp[MAX_STRING_LEN];
	size_t		offset;
	ZBX_FPING_HOST	*host;
	double		sec;
	int 		i, ret = NOTSUPPORTED, index;

#ifdef HAVE_IPV6
	int		family;
	char		params6[64];
	char		fping_existence = 0;
#define	FPING_EXISTS	0x1
#define	FPING6_EXISTS	0x2

#endif	/* HAVE_IPV6 */

	assert(hosts);

	zabbix_log(LOG_LEVEL_DEBUG, "In %s() hosts_count:%d", __function_name, hosts_count);

	if (-1 == access(CONFIG_FPING_LOCATION, X_OK))
	{
#if !defined(HAVE_IPV6)
		zbx_snprintf(error, max_error_len, "%s: %s", CONFIG_FPING_LOCATION, zbx_strerror(errno));
		return ret;
#endif
	}
	else
	{
#ifdef HAVE_IPV6
		fping_existence |= FPING_EXISTS;
#else
		if (NULL != CONFIG_SOURCE_IP)
		{
			if (FAIL == is_ip4(CONFIG_SOURCE_IP)) /* we do not have IPv4 family address in CONFIG_SOURCE_IP */
			{
				zbx_snprintf(error, max_error_len,
					"You should enable IPv6 support to use IPv6 family address for SourceIP '%s'.", CONFIG_SOURCE_IP);
				return ret;
			}
		}
#endif
	}

#ifdef HAVE_IPV6
	if (-1 == access(CONFIG_FPING6_LOCATION, X_OK))
	{
		if (0 == (fping_existence & FPING_EXISTS))
		{
			zbx_snprintf(error, max_error_len, "At least one of '%s', '%s' must exist. Both are missing in the system.",
					CONFIG_FPING_LOCATION,
					CONFIG_FPING6_LOCATION);
			return ret;
		}
	}
	else
		fping_existence |= FPING6_EXISTS;
#endif	/* HAVE_IPV6 */

	offset = zbx_snprintf(params, sizeof(params), "-C%d", count);
	if (0 != interval)
		offset += zbx_snprintf(params + offset, sizeof(params) - offset, " -p%d", interval);
	if (0 != size)
		offset += zbx_snprintf(params + offset, sizeof(params) - offset, " -b%d", size);
	if (0 != timeout)
		offset += zbx_snprintf(params + offset, sizeof(params) - offset, " -t%d", timeout);

#ifdef HAVE_IPV6
	strscpy(params6, params);
#endif	/* HAVE_IPV6 */

	if (NULL != CONFIG_SOURCE_IP)
	{
#ifdef HAVE_IPV6
		if (0 != (fping_existence & FPING_EXISTS))
		{
			if (0 == source_ip_checked)
				get_source_ip_option(CONFIG_FPING_LOCATION, &source_ip_option, &source_ip_checked);
			if (NULL != source_ip_option)
				zbx_snprintf(params + offset, sizeof(params) - offset,
						" %s%s", source_ip_option, CONFIG_SOURCE_IP);
		}

		if (0 != (fping_existence & FPING6_EXISTS))
		{
			if (0 == source_ip6_checked)
				get_source_ip_option(CONFIG_FPING6_LOCATION, &source_ip6_option, &source_ip6_checked);
			if (NULL != source_ip6_option)
				zbx_snprintf(params6 + offset, sizeof(params6) - offset,
						" %s%s", source_ip6_option, CONFIG_SOURCE_IP);
		}
#else
		if (0 == source_ip_checked)
			get_source_ip_option(CONFIG_FPING_LOCATION, &source_ip_option, &source_ip_checked);
		if (NULL != source_ip_option)
			zbx_snprintf(params + offset, sizeof(params) - offset,
					" %s%s", source_ip_option, CONFIG_SOURCE_IP);
#endif	/* HAVE_IPV6 */
	}

	zbx_snprintf(filename, sizeof(filename), "%s/%s_%li.pinger", CONFIG_TMPDIR, progname, zbx_get_thread_id());

#ifdef HAVE_IPV6
	if (NULL != CONFIG_SOURCE_IP)
	{
		if (SUCCEED != get_address_family(CONFIG_SOURCE_IP, &family, error, max_error_len))
			return ret;

		if (family == PF_INET)
		{
			if (0 == (fping_existence & FPING_EXISTS))
			{
				zbx_snprintf(error, max_error_len, "File '%s' cannot be found in the system.",
						CONFIG_FPING_LOCATION);
				return ret;
			}

			zbx_snprintf(tmp, sizeof(tmp), "%s %s 2>&1 <%s", CONFIG_FPING_LOCATION, params, filename);
		}
		else
		{
			if (0 == (fping_existence & FPING6_EXISTS))
			{
				zbx_snprintf(error, max_error_len, "File '%s' cannot be found in the system.",
						CONFIG_FPING6_LOCATION);
				return ret;
			}

			zbx_snprintf(tmp, sizeof(tmp), "%s %s 2>&1 <%s", CONFIG_FPING6_LOCATION, params6, filename);
		}
	}
	else
	{
		offset = 0;

		if (0 != (fping_existence & FPING_EXISTS))
			offset += zbx_snprintf(tmp + offset, sizeof(tmp) - offset,
					"%s %s 2>&1 <%s;", CONFIG_FPING_LOCATION, params, filename);

		if (0 != (fping_existence & FPING6_EXISTS))
			zbx_snprintf(tmp + offset, sizeof(tmp) - offset,
					"%s %s 2>&1 <%s;", CONFIG_FPING6_LOCATION, params6, filename);
	}
#else
	zbx_snprintf(tmp, sizeof(tmp), "%s %s 2>&1 <%s", CONFIG_FPING_LOCATION, params, filename);
#endif	/* HAVE_IPV6 */

	if (NULL == (f = fopen(filename, "w")))
	{
		zbx_snprintf(error, max_error_len, "%s: %s", filename, zbx_strerror(errno));
		return ret;
	}

	zabbix_log(LOG_LEVEL_DEBUG, "%s", filename);

	for (i = 0; i < hosts_count; i++)
	{
		zabbix_log(LOG_LEVEL_DEBUG, "    %s", hosts[i].addr);
		fprintf(f, "%s\n", hosts[i].addr);
	}

	fclose(f);

	zabbix_log(LOG_LEVEL_DEBUG, "%s", tmp);

	if (NULL == (f = popen(tmp, "r")))
	{
		zbx_snprintf(error, max_error_len, "%s: %s", tmp, zbx_strerror(errno));

		unlink(filename);

		return ret;
	}

	if (NULL == fgets(tmp, sizeof(tmp), f))
	{
		ret = SUCCEED; /* fping does not output anything for DNS names that fail to resolve */
	}
	else
	{
		for (i = 0; i < hosts_count; i++)
		{
			hosts[i].status = zbx_malloc(NULL, count);
			memset(hosts[i].status, 0, count);
		}

		do
		{
			zbx_rtrim(tmp, "\n");
			zabbix_log(LOG_LEVEL_DEBUG, "read line [%s]", tmp);

			host = NULL;

			if (NULL != (c = strchr(tmp, ' ')))
			{
				*c = '\0';
				for (i = 0; i < hosts_count; i++)
					if (0 == strcmp(tmp, hosts[i].addr))
					{
						host = &hosts[i];
						break;
					}
				*c = ' ';
			}

			if (NULL == host)
				continue;

			if (NULL == (c = strstr(tmp, " : ")))
				continue;

			/* when NIC bonding is used, there are also lines like */
			/* 192.168.1.2 : duplicate for [0], 96 bytes, 0.19 ms */

			if (NULL != strstr(tmp, "duplicate for"))
				continue;

			c += 3;

			/* The were two issues with processing only the fping's final status line:  */
			/*   1) pinging broadcast addresses could have resulted in responses from   */
			/*      different hosts, which were counted as the target host responses;   */
			/*   2) there is a bug in fping (v3.8 at least) where pinging broadcast     */
			/*      address will result in no individual responses, but the final       */
			/*      status line might contain a bogus value.                            */
			/* Because of the above issues we must monitor the individual responses     */
			/* and mark the valid ones.                                                 */
			if ('[' == *c)
			{
				/* Fping appends response source address in format '[<- 10.3.0.10]' */
				/* if it does not match the target address. Ignore such responses.  */
				if (NULL != strstr(c + 1, "[<-"))
					continue;

				/* get the index of individual ping response */
				index = atoi(c + 1);

				if (0 > index || index >= count)
					continue;

				host->status[index] = 1;

				continue;
			}

			/* process status line for a host */
			index = 0;
			do
			{
				if (1 == host->status[index])
				{
					sec = atof(c) / 1000; /* convert ms to seconds */

					if (0 == host->rcv || host->min > sec)
						host->min = sec;
					if (0 == host->rcv || host->max < sec)
						host->max = sec;
					host->avg = (host->avg * host->rcv + sec) / (host->rcv + 1);
					host->rcv++;
				}
			}
			while (++index < count && NULL != (c = strchr(c + 1, ' ')));

			host->cnt = count;

			ret = SUCCEED;
		}
		while (NULL != fgets(tmp, sizeof(tmp), f));

		for (i = 0; i < hosts_count; i++)
			zbx_free(hosts[i].status);
	}
	pclose(f);

	unlink(filename);

	if (NOTSUPPORTED == ret)
		zbx_snprintf(error, max_error_len, "fping failed: \"%s\"", tmp);

	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);

	return ret;
}
Пример #6
0
int
main(int argc, char** argv)
{
	if (argc > 1 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")))
		usage(0);

	int32 mode = RTM_LIST;

	if (argc > 1) {
		if (!strcmp(argv[1], "delete")
			|| !strcmp(argv[1], "del")
			|| !strcmp(argv[1], "-d")) {
			// delete route
			if (argc < 3)
				usage(1);

			mode = RTM_DELETE;
		} else if (!strcmp(argv[1], "add")
			|| !strcmp(argv[1], "-a")) {
			// add route
			if (argc < 3)
				usage(1);

			mode = RTM_ADD;
		} else if (!strcmp(argv[1], "get")) {
			// get route for destination
			if (argc < 3)
				usage(1);

			mode = RTM_GET;
		}
	}

	int32 i = 2;
	int32 interfaceIndex = i;
	bool familySpecified = false;
	int32 familyIndex = 0;
	const char *interface = NULL;
	sockaddr_storage destination;
	sockaddr_storage mask;
	sockaddr_storage gateway;
	bool hasDestination = false, hasGateway = false, hasMask = false;
	bool defaultRoute = false;

	route_entry route;
	memset(&route, 0, sizeof(route_entry));

	while (i < argc && i < 5) {
		// try to parse address family
		if (i <= 3 && familyIndex == -1 && get_address_family(argv[i], familyIndex)) {
			familySpecified = true;
			if (i == 2)
				interfaceIndex = -1;
		}

		if (!strcmp(argv[i], "default")) {
			defaultRoute = true;
			route.flags = RTF_DEFAULT;
			i++;
			break;
		} else if (parse_address(familyIndex, argv[i], destination)) {
			hasDestination = true;
			i++;
			break;
		}

		i++;
	}

	if (!defaultRoute && !hasDestination && mode != RTM_LIST)
		usage(1);

	if (i == 3)
		interfaceIndex = -1;
	if (interfaceIndex != -1 && interfaceIndex < argc)
		interface = argv[interfaceIndex];

	if (i < argc && parse_address(familyIndex, argv[i], mask)) {
		hasMask = true;
		i++;
	}

	// parse options and flags

	while (i < argc) {
		if (!strcmp(argv[i], "gw") || !strcmp(argv[i], "gateway")) {
			if (!parse_address(familyIndex, argv[i + 1], gateway)) {
				fprintf(stderr, "%s: Option 'gw' needs valid address parameter\n",
					kProgramName);
				exit(1);
			}
			hasGateway = true;
			i++;
		} else if (!strcmp(argv[i], "nm") || !strcmp(argv[i], "netmask")) {
			if (hasMask) {
				fprintf(stderr, "%s: Netmask is specified twice\n",
					kProgramName);
				exit(1);
			}
			if (!parse_address(familyIndex, argv[i + 1], mask)) {
				fprintf(stderr, "%s: Option 'netmask' needs valid address parameter\n",
					kProgramName);
				exit(1);
			}
			hasMask = true;
			i++;
		} else if (!strcmp(argv[i], "mtu")) {
			route.mtu = argv[i + 1] ? strtol(argv[i + 1], NULL, 0) : 0;
			if (route.mtu <= 500) {
				fprintf(stderr, "%s: Option 'mtu' exptected valid max transfer unit size\n",
					kProgramName);
				exit(1);
			}
			i++;
		} else if (!strcmp(argv[i], "host")) {
			route.flags |= RTF_HOST;
		} else if (!strcmp(argv[i], "local")) {
			route.flags |= RTF_LOCAL;
		} else if (!strcmp(argv[i], "reject")) {
			route.flags |= RTF_REJECT;
		} else
			usage(1);

		i++;
	}

	if (hasDestination)
		route.destination = (sockaddr *)&destination;
	if (hasMask)
		route.mask = (sockaddr *)&mask;
	if (hasGateway) {
		route.gateway = (sockaddr *)&gateway;
		route.flags |= RTF_GATEWAY;
	}

	// we need a socket to talk to the networking stack
	int socket = ::socket(kFamilies[familyIndex].family, SOCK_DGRAM, 0);
	if (socket < 0) {
		fprintf(stderr, "%s: The requested address family is not available.\n",
			kProgramName);
		return 1;
	}

	switch (mode) {
		case RTM_ADD:
			if (interface == NULL) {
				fprintf(stderr, "%s: You need to specify an interface when adding a route.\n",
					kProgramName);
				usage(1);
			}

			add_route(socket, interface, route);
			break;
		case RTM_DELETE:
			if (interface == NULL) {
				fprintf(stderr, "%s: You need to specify an interface when removing a route.\n",
					kProgramName);
				usage(1);
			}

			delete_route(socket, interface, route);
			break;

		case RTM_LIST:
			if (familySpecified)
				list_routes(socket, interface, route);
			else {
				for (int32 i = 0; kFamilies[i].family >= 0; i++) {
					int socket = ::socket(kFamilies[familyIndex].family, SOCK_DGRAM, 0);
					if (socket < 0)
						continue;

					list_routes(socket, interface, route);
					close(socket);
				}
			}
			break;

		case RTM_GET:
			get_route(socket, route);
			break;
	}

	close(socket);
	return 0;
}
Пример #7
0
void
internal_function
__netlink_assert_response (int fd, ssize_t result)
{
  if (result < 0)
    {
      /* Check if the error is unexpected.  */
      bool terminate = false;
      int error_code = errno;
      int family = get_address_family (fd);
      if (family != AF_NETLINK)
        /* If the address family does not match (or getsockname
           failed), report the original error.  */
        terminate = true;
      else if (error_code == EBADF
          || error_code == ENOTCONN
          || error_code == ENOTSOCK
          || error_code == ECONNREFUSED)
        /* These errors indicate that the descriptor is not a
           connected socket.  */
        terminate = true;
      else if (error_code == EAGAIN || error_code == EWOULDBLOCK)
        {
          /* The kernel might return EAGAIN for other reasons than a
             non-blocking socket.  But if the socket is not blocking,
             it is not ours, so report the error.  */
          int mode = __fcntl (fd, F_GETFL, 0);
          if (mode < 0 || (mode & O_NONBLOCK) != 0)
            terminate = true;
        }
      if (terminate)
        {
          char message[200];
          if (family < 0)
            __snprintf (message, sizeof (message),
                        "Unexpected error %d on netlink descriptor %d",
                        error_code, fd);
          else
            __snprintf (message, sizeof (message),
                        "Unexpected error %d on netlink descriptor %d"
                        " (address family %d)",
                        error_code, fd, family);
          __libc_fatal (message);
        }
      else
        /* Restore orignal errno value.  */
        __set_errno (error_code);
    }
  else if (result < sizeof (struct nlmsghdr))
    {
      char message[200];
      int family = get_address_family (fd);
      if (family < 0)
          __snprintf (message, sizeof (message),
                      "Unexpected netlink response of size %zd"
                      " on descriptor %d",
                      result, fd);
      else
          __snprintf (message, sizeof (message),
                      "Unexpected netlink response of size %zd"
                      " on descriptor %d (address family %d)",
                      result, fd, family);
      __libc_fatal (message);
    }
}
Пример #8
0
static struct snmp_session	*snmp_open_session(DC_ITEM *item, char *err)
{
	const char		*__function_name = "snmp_open_session";
	struct snmp_session	session, *ss = NULL;
	char			addr[128];
#ifdef HAVE_IPV6
	int			family;
#endif

	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);

	snmp_sess_init(&session);

	switch (item->type)
	{
		case ITEM_TYPE_SNMPv1:
			session.version = SNMP_VERSION_1;
			break;
		case ITEM_TYPE_SNMPv2c:
			session.version = SNMP_VERSION_2c;
			break;
		case ITEM_TYPE_SNMPv3:
			session.version = SNMP_VERSION_3;
			break;
		default:
			THIS_SHOULD_NEVER_HAPPEN;
			break;
	}

#ifdef HAVE_IPV6
	if (SUCCEED != get_address_family(item->interface.addr, &family, err, MAX_STRING_LEN))
		goto end;

	if (family == PF_INET)
		zbx_snprintf(addr, sizeof(addr), "%s:%d", item->interface.addr, (int)item->interface.port);
	else
	{
		if (item->interface.useip)
			zbx_snprintf(addr, sizeof(addr), "udp6:[%s]:%d", item->interface.addr, (int)item->interface.port);
		else
			zbx_snprintf(addr, sizeof(addr), "udp6:%s:%d", item->interface.addr, (int)item->interface.port);
	}
#else
	zbx_snprintf(addr, sizeof(addr), "%s:%d", item->interface.addr, (int)item->interface.port);
#endif	/* HAVE_IPV6 */
	session.peername = addr;
	session.remote_port = item->interface.port;	/* remote_port is no longer used in latest versions of NET-SNMP */

	if (session.version == SNMP_VERSION_1 || session.version == SNMP_VERSION_2c)
	{
		session.community = (u_char *)item->snmp_community;
		session.community_len = strlen((void *)session.community);
		zabbix_log(LOG_LEVEL_DEBUG, "SNMP [%s@%s]", session.community, session.peername);
	}
	else if (session.version == SNMP_VERSION_3)
	{
		/* set the SNMPv3 user name */
		session.securityName = item->snmpv3_securityname;
		session.securityNameLen = strlen(session.securityName);

		/* set the security level to authenticated, but not encrypted */
		if (item->snmpv3_securitylevel == ITEM_SNMPV3_SECURITYLEVEL_NOAUTHNOPRIV)
		{
			session.securityLevel = SNMP_SEC_LEVEL_NOAUTH;
		}
		else if (item->snmpv3_securitylevel == ITEM_SNMPV3_SECURITYLEVEL_AUTHNOPRIV)
		{
			session.securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;

			/* set the authentication method to MD5 */
			session.securityAuthProto = usmHMACMD5AuthProtocol;
			session.securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN;
			session.securityAuthKeyLen = USM_AUTH_KU_LEN;

			if (SNMPERR_SUCCESS != generate_Ku(session.securityAuthProto,
					session.securityAuthProtoLen,
					(u_char *)item->snmpv3_authpassphrase,
					strlen(item->snmpv3_authpassphrase),
					session.securityAuthKey,
					&session.securityAuthKeyLen))
			{
				zbx_snprintf(err, MAX_STRING_LEN, "Error generating Ku from authentication pass phrase");
				goto end;
			}
		}
		else if (item->snmpv3_securitylevel == ITEM_SNMPV3_SECURITYLEVEL_AUTHPRIV)
		{
			session.securityLevel = SNMP_SEC_LEVEL_AUTHPRIV;

			/* set the authentication method to MD5 */
			session.securityAuthProto = usmHMACMD5AuthProtocol;
			session.securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN;
			session.securityAuthKeyLen = USM_AUTH_KU_LEN;

			if (SNMPERR_SUCCESS != generate_Ku(session.securityAuthProto,
					session.securityAuthProtoLen,
					(u_char *)item->snmpv3_authpassphrase,
					strlen(item->snmpv3_authpassphrase),
					session.securityAuthKey,
					&session.securityAuthKeyLen))
			{
				zbx_snprintf(err, MAX_STRING_LEN, "Error generating Ku from authentication pass phrase");
				goto end;
			}

			/* set the privacy method to DES */
			session.securityPrivProto = usmDESPrivProtocol;
			session.securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN;
			session.securityPrivKeyLen = USM_PRIV_KU_LEN;

			if (SNMPERR_SUCCESS != generate_Ku(session.securityAuthProto,
					session.securityAuthProtoLen,
					(u_char *)item->snmpv3_privpassphrase,
					strlen(item->snmpv3_privpassphrase),
					session.securityPrivKey,
					&session.securityPrivKeyLen))
			{
				zbx_snprintf(err, MAX_STRING_LEN, "Error generating Ku from privacy pass phrase");
				goto end;
			}
		}
		zabbix_log(LOG_LEVEL_DEBUG, "SNMPv3 [%s@%s]", session.securityName, session.peername);
	}

#ifdef HAVE_SNMP_SESSION_LOCALNAME
	if (NULL != CONFIG_SOURCE_IP)
		session.localname = CONFIG_SOURCE_IP;
#endif

	SOCK_STARTUP;

	if (NULL == (ss = snmp_open(&session)))
	{
		SOCK_CLEANUP;

		zbx_snprintf(err, MAX_STRING_LEN, "Cannot open snmp session");
	}
end:
	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);

	return ss;
}
Пример #9
0
void
configure_interface(const char* name, char* const* args, int32 argCount)
{
	// try to parse address family

	int32 i = 0;
	int family = get_address_family(args[i]);
	if (family != AF_UNSPEC)
		i++;

	// try to parse address

	BNetworkAddress address;
	BNetworkAddress mask;

	if (parse_address(family, args[i], address)) {
		i++;

		if (parse_address(family, args[i], mask))
			i++;
	}

	BNetworkInterface interface(name);
	if (!interface.Exists()) {
		// the interface does not exist yet, we have to add it first
		BNetworkRoster& roster = BNetworkRoster::Default();

		status_t status = roster.AddInterface(interface);
		if (status != B_OK) {
			fprintf(stderr, "%s: Could not add interface: %s\n", kProgramName,
				strerror(status));
			exit(1);
		}
	}

	BNetworkAddress broadcast;
	BNetworkAddress peer;
	int mtu = -1, metric = -1, media = -1;
	int addFlags = 0, currentFlags = 0, removeFlags = 0;
	bool doAutoConfig = false;

	// parse parameters and flags

	while (i < argCount) {
		if (!strcmp(args[i], "peer")) {
			if (!parse_address(family, args[i + 1], peer)) {
				fprintf(stderr, "%s: Option 'peer' needs valid address "
					"parameter\n", kProgramName);
				exit(1);
			}
			i++;
		} else if (!strcmp(args[i], "nm") || !strcmp(args[i], "netmask")) {
			if (!mask.IsEmpty()) {
				fprintf(stderr, "%s: Netmask or prefix length is specified "
					"twice\n", kProgramName);
				exit(1);
			}
			if (!parse_address(family, args[i + 1], mask)) {
				fprintf(stderr, "%s: Option 'netmask' needs valid address "
					"parameter\n", kProgramName);
				exit(1);
			}
			i++;
		} else if (!strcmp(args[i], "prefixlen") || !strcmp(args[i], "plen")
			|| !strcmp(args[i], "prefix-length")) {
			if (!mask.IsEmpty()) {
				fprintf(stderr, "%s: Netmask or prefix length is specified "
					"twice\n", kProgramName);
				exit(1);
			}

			// default to AF_INET if no address family has been specified yet
			if (family == AF_UNSPEC)
				family = AF_INET;

			if (!prefix_length_to_mask(family, args[i + 1], mask)) {
				fprintf(stderr, "%s: Option 'prefix-length %s' is invalid for "
					"this address family\n", kProgramName, args[i + 1]);
				exit(1);
			}
			i++;
		} else if (!strcmp(args[i], "bc") || !strcmp(args[i], "broadcast")) {
			if (!broadcast.IsEmpty()) {
				fprintf(stderr, "%s: broadcast address is specified twice\n",
					kProgramName);
				exit(1);
			}
			if (!parse_address(family, args[i + 1], broadcast)) {
				fprintf(stderr, "%s: Option 'broadcast' needs valid address "
					"parameter\n", kProgramName);
				exit(1);
			}
			addFlags |= IFF_BROADCAST;
			i++;
		} else if (!strcmp(args[i], "mtu")) {
			mtu = args[i + 1] ? strtol(args[i + 1], NULL, 0) : 0;
			if (mtu <= 500) {
				fprintf(stderr, "%s: Option 'mtu' expected valid max transfer "
					"unit size\n", kProgramName);
				exit(1);
			}
			i++;
		} else if (!strcmp(args[i], "metric")) {
			if (i + 1 >= argCount) {
				fprintf(stderr, "%s: Option 'metric' expected parameter\n",
					kProgramName);
				exit(1);
			}
			metric = strtol(args[i + 1], NULL, 0);
			i++;
		} else if (!strcmp(args[i], "media")) {
			media = interface.Media();
			if (media < 0) {
				fprintf(stderr, "%s: Unable to detect media type\n",
					kProgramName);
				exit(1);
			}
			if (i + 1 >= argCount) {
				fprintf(stderr, "%s: Option 'media' expected parameter\n",
					kProgramName);
				exit(1);
			}
			if (!media_parse_subtype(args[i + 1], IFM_TYPE(media), &media)) {
				fprintf(stderr, "%s: Invalid parameter for option 'media': "
					"'%s'\n", kProgramName, args[i + 1]);
				exit(1);
			}
			i++;
		} else if (!strcmp(args[i], "up") || !strcmp(args[i], "-down")) {
			addFlags |= IFF_UP;
		} else if (!strcmp(args[i], "down") || !strcmp(args[i], "-up")) {
			removeFlags |= IFF_UP;
		} else if (!strcmp(args[i], "bcast")) {
			addFlags |= IFF_BROADCAST;
		} else if (!strcmp(args[i], "-bcast")) {
			removeFlags |= IFF_BROADCAST;
		} else if (!strcmp(args[i], "promisc")) {
			addFlags |= IFF_PROMISC;
		} else if (!strcmp(args[i], "-promisc")) {
			removeFlags |= IFF_PROMISC;
		} else if (!strcmp(args[i], "allmulti")) {
			addFlags |= IFF_ALLMULTI;
		} else if (!strcmp(args[i], "-allmulti")) {
			removeFlags |= IFF_ALLMULTI;
		} else if (!strcmp(args[i], "loopback")) {
			addFlags |= IFF_LOOPBACK;
		} else if (!strcmp(args[i], "auto-config")) {
			doAutoConfig = true;
		} else
			usage(1);

		i++;
	}

	if ((addFlags & removeFlags) != 0) {
		fprintf(stderr, "%s: Contradicting flags specified\n", kProgramName);
		exit(1);
	}

	if (doAutoConfig && (!address.IsEmpty() || !mask.IsEmpty()
			|| !broadcast.IsEmpty() || !peer.IsEmpty())) {
		fprintf(stderr, "%s: Contradicting changes specified\n", kProgramName);
		exit(1);
	}

	// set address/mask/broadcast/peer

	if (!address.IsEmpty() || !mask.IsEmpty() || !broadcast.IsEmpty()) {
		BNetworkInterfaceAddress interfaceAddress;
		interfaceAddress.SetAddress(address);
		interfaceAddress.SetMask(mask);
		if (!broadcast.IsEmpty())
			interfaceAddress.SetBroadcast(broadcast);
		else if (!peer.IsEmpty())
			interfaceAddress.SetDestination(peer);

		status_t status = interface.SetAddress(interfaceAddress);
		if (status != B_OK) {
			fprintf(stderr, "%s: Setting address failed: %s\n", kProgramName,
				strerror(status));
			exit(1);
		}
	}

	currentFlags = interface.Flags();

	// set flags

	if (!address.IsEmpty() || !mask.IsEmpty() || !broadcast.IsEmpty()
		|| !peer.IsEmpty())
		removeFlags = IFF_AUTO_CONFIGURED | IFF_CONFIGURING;

	if (addFlags || removeFlags) {
		status_t status
			= interface.SetFlags((currentFlags & ~removeFlags) | addFlags);
		if (status != B_OK) {
			fprintf(stderr, "%s: Setting flags failed: %s\n", kProgramName,
				strerror(status));
		}
	}

	// set options

	if (mtu != -1) {
		status_t status = interface.SetMTU(mtu);
		if (status != B_OK) {
			fprintf(stderr, "%s: Setting MTU failed: %s\n", kProgramName,
				strerror(status));
		}
	}

	if (metric != -1) {
		status_t status = interface.SetMetric(metric);
		if (status != B_OK) {
			fprintf(stderr, "%s: Setting metric failed: %s\n", kProgramName,
				strerror(status));
		}
	}

	if (media != -1) {
		status_t status = interface.SetMedia(media);
		if (status != B_OK) {
			fprintf(stderr, "%s: Setting media failed: %s\n", kProgramName,
				strerror(status));
		}
	}

	// start auto configuration, if asked for

	if (doAutoConfig) {
		status_t status = interface.AutoConfigure(family);
		if (status == B_BAD_PORT_ID) {
			fprintf(stderr, "%s: The net_server needs to run for the auto "
				"configuration!\n", kProgramName);
		} else if (status != B_OK) {
			fprintf(stderr, "%s: Auto-configuring failed: %s\n", kProgramName,
				strerror(status));
		}
	}
}
Пример #10
0
interfaces_file *read_interfaces(char *filename) {
	
#line 1210 "ifupdown.nw"
FILE *f;
int line;
#line 1247 "ifupdown.nw"
char *buf = NULL;
size_t buf_len = 0;
#line 1447 "ifupdown.nw"
interface_defn *currif = NULL;
mapping_defn *currmap = NULL;
enum { NONE, IFACE, MAPPING } currently_processing = NONE;
#line 1458 "ifupdown.nw"
char firstword[80];
char *rest;
#line 1176 "ifupdown.nw"
	interfaces_file *defn;

	
#line 1195 "ifupdown.nw"
defn = malloc(sizeof(interfaces_file));
if (defn == NULL) {
	return NULL;
}
defn->allowups = NULL;
defn->mappings = NULL;
defn->ifaces = NULL;
#line 1179 "ifupdown.nw"
	
#line 1215 "ifupdown.nw"
f = fopen(filename, "r");
if ( f == NULL ) return NULL;
line = 0;

#line 1181 "ifupdown.nw"
	while (
#line 1255 "ifupdown.nw"
get_line(&buf,&buf_len,f,&line)
#line 1181 "ifupdown.nw"
                                             ) {
		
#line 1494 "ifupdown.nw"
rest = next_word(buf, firstword, 80);
if (rest == NULL) continue; /* blank line */

if (strcmp(firstword, "mapping") == 0) {
	
#line 1546 "ifupdown.nw"
currmap = malloc(sizeof(mapping_defn));
if (currmap == NULL) {
	
#line 2008 "ifupdown.nw"
perror(filename);
return NULL;
#line 1549 "ifupdown.nw"
}
#line 1553 "ifupdown.nw"
currmap->max_matches = 0;
currmap->n_matches = 0;
currmap->match = NULL;

while((rest = next_word(rest, firstword, 80))) {
	if (currmap->max_matches == currmap->n_matches) {
		char **tmp;
		currmap->max_matches = currmap->max_matches * 2 + 1;
		tmp = realloc(currmap->match, 
			sizeof(*tmp) * currmap->max_matches);
		if (tmp == NULL) {
			currmap->max_matches = (currmap->max_matches - 1) / 2;
			
#line 2008 "ifupdown.nw"
perror(filename);
return NULL;
#line 1566 "ifupdown.nw"
		}
		currmap->match = tmp;
	}

	currmap->match[currmap->n_matches++] = strdup(firstword);
}
#line 1575 "ifupdown.nw"
currmap->script = NULL;

currmap->max_mappings = 0;
currmap->n_mappings = 0;
currmap->mapping = NULL;
#line 1583 "ifupdown.nw"
{
	mapping_defn **where = &defn->mappings;
	while(*where != NULL) {
		where = &(*where)->next;
	}
	*where = currmap;
	currmap->next = NULL;
}
#line 1499 "ifupdown.nw"
	currently_processing = MAPPING;
} else if (strcmp(firstword, "iface") == 0) {
	
#line 1635 "ifupdown.nw"
{
	
#line 1668 "ifupdown.nw"
char iface_name[80];
char address_family_name[80];
char method_name[80];

#line 1638 "ifupdown.nw"
	
#line 1656 "ifupdown.nw"
currif = malloc(sizeof(interface_defn));
if (!currif) {
	
#line 2008 "ifupdown.nw"
perror(filename);
return NULL;
#line 1659 "ifupdown.nw"
}

#line 1640 "ifupdown.nw"
	
#line 1674 "ifupdown.nw"
rest = next_word(rest, iface_name, 80);
rest = next_word(rest, address_family_name, 80);
rest = next_word(rest, method_name, 80);

if (rest == NULL) {
	
#line 2013 "ifupdown.nw"
fprintf(stderr, "%s:%d: too few parameters for iface line\n", filename, line);
return NULL;
#line 1680 "ifupdown.nw"
}

if (rest[0] != '\0') {
	
#line 2018 "ifupdown.nw"
fprintf(stderr, "%s:%d: too many parameters for iface line\n", filename, line);
return NULL;
#line 1684 "ifupdown.nw"
}

#line 1642 "ifupdown.nw"
	
#line 1690 "ifupdown.nw"
currif->logical_iface = strdup(iface_name);
if (!currif->logical_iface) {
	
#line 2008 "ifupdown.nw"
perror(filename);
return NULL;
#line 1693 "ifupdown.nw"
}
#line 1643 "ifupdown.nw"
	
#line 1708 "ifupdown.nw"
currif->address_family = get_address_family(addr_fams, address_family_name);
if (!currif->address_family) {
	
#line 2023 "ifupdown.nw"
fprintf(stderr, "%s:%d: unknown address type\n", filename, line);
return NULL;
#line 1711 "ifupdown.nw"
}
#line 1644 "ifupdown.nw"
	
#line 1743 "ifupdown.nw"
currif->method = get_method(currif->address_family, method_name);
if (!currif->method) {
	
#line 2028 "ifupdown.nw"
fprintf(stderr, "%s:%d: unknown method\n", filename, line);
return NULL;
#line 1746 "ifupdown.nw"
	return NULL; /* FIXME */
}
#line 1645 "ifupdown.nw"
	
#line 1766 "ifupdown.nw"
currif->automatic = 1;
currif->max_options = 0;
currif->n_options = 0;
currif->option = NULL;

#line 1647 "ifupdown.nw"
	
#line 1782 "ifupdown.nw"
{
	interface_defn **where = &defn->ifaces; 
	while(*where != NULL) {
		if (duplicate_if(*where, currif)) {
			
#line 2033 "ifupdown.nw"
fprintf(stderr, "%s:%d: duplicate interface\n", filename, line);
return NULL;
#line 1787 "ifupdown.nw"
		}
		where = &(*where)->next;
	}

	*where = currif;
	currif->next = NULL;
}
#line 1648 "ifupdown.nw"
}
#line 1502 "ifupdown.nw"
	currently_processing = IFACE;
} else if (strcmp(firstword, "auto") == 0) {
	
#line 1898 "ifupdown.nw"
allowup_defn *auto_ups = get_allowup(&defn->allowups, "auto");
if (!auto_ups) {
	
#line 2008 "ifupdown.nw"
perror(filename);
return NULL;
#line 1901 "ifupdown.nw"
}
while((rest = next_word(rest, firstword, 80))) {
	if (!add_allow_up(filename, line, auto_ups, firstword))
		return NULL;
}
#line 1505 "ifupdown.nw"
	currently_processing = NONE;
} else if (strncmp(firstword, "allow-", 6) == 0 && strlen(firstword) > 6) {
	
#line 1908 "ifupdown.nw"
allowup_defn *allow_ups = get_allowup(&defn->allowups, firstword + 6);
if (!allow_ups) {
	
#line 2008 "ifupdown.nw"
perror(filename);
return NULL;
#line 1911 "ifupdown.nw"
}
while((rest = next_word(rest, firstword, 80))) {
	if (!add_allow_up(filename, line, allow_ups, firstword))
		return NULL;
}
#line 1508 "ifupdown.nw"
	currently_processing = NONE;
} else {
	
#line 1515 "ifupdown.nw"
switch(currently_processing) {
	case IFACE:
		
#line 1821 "ifupdown.nw"
if (strcmp(firstword, "post-up") == 0) {
	strcpy(firstword, "up");
}
if (strcmp(firstword, "pre-down") == 0) {
	strcpy(firstword, "down");
} 
#line 1830 "ifupdown.nw"
{
	int i;

	if (strlen (rest) == 0) {
		
#line 2059 "ifupdown.nw"
fprintf(stderr, "%s:%d: option with empty value\n", filename, line);
return NULL;
#line 1835 "ifupdown.nw"
	}

	if (strcmp(firstword, "pre-up") != 0 
	    && strcmp(firstword, "up") != 0
	    && strcmp(firstword, "down") != 0
	    && strcmp(firstword, "post-down") != 0)
        {
		for (i = 0; i < currif->n_options; i++) {
			if (strcmp(currif->option[i].name, firstword) == 0) {
				
#line 2044 "ifupdown.nw"
fprintf(stderr, "%s:%d: duplicate option\n", filename, line);
return NULL;
#line 1845 "ifupdown.nw"
			}
		}
	}
}
#line 1857 "ifupdown.nw"
if (currif->n_options >= currif->max_options) {
	
#line 1879 "ifupdown.nw"
{
	variable *opt;
	currif->max_options = currif->max_options + 10;
	opt = realloc(currif->option, sizeof(*opt) * currif->max_options);
	if (opt == NULL) {
		
#line 2008 "ifupdown.nw"
perror(filename);
return NULL;
#line 1885 "ifupdown.nw"
	}
	currif->option = opt;
}
#line 1859 "ifupdown.nw"
}

currif->option[currif->n_options].name = strdup(firstword);
currif->option[currif->n_options].value = strdup(rest);

if (!currif->option[currif->n_options].name) {
	
#line 2008 "ifupdown.nw"
perror(filename);
return NULL;
#line 1866 "ifupdown.nw"
}

if (!currif->option[currif->n_options].value) {
	
#line 2008 "ifupdown.nw"
perror(filename);
return NULL;
#line 1870 "ifupdown.nw"
}

currif->n_options++;	
#line 1518 "ifupdown.nw"
		break;
	case MAPPING:
		
#line 1598 "ifupdown.nw"
if (strcmp(firstword, "script") == 0) {
	
#line 1608 "ifupdown.nw"
if (currmap->script != NULL) {
	
#line 2049 "ifupdown.nw"
fprintf(stderr, "%s:%d: duplicate script in mapping\n", filename, line);
return NULL;
#line 1610 "ifupdown.nw"
} else {
	currmap->script = strdup(rest);
}
#line 1600 "ifupdown.nw"
} else if (strcmp(firstword, "map") == 0) {
	
#line 1616 "ifupdown.nw"
if (currmap->max_mappings == currmap->n_mappings) {
	char **opt;
	currmap->max_mappings = currmap->max_mappings * 2 + 1;
	opt = realloc(currmap->mapping, sizeof(*opt) * currmap->max_mappings);
	if (opt == NULL) {
		
#line 2008 "ifupdown.nw"
perror(filename);
return NULL;
#line 1622 "ifupdown.nw"
	}
	currmap->mapping = opt;
}
currmap->mapping[currmap->n_mappings] = strdup(rest);
currmap->n_mappings++;
#line 1602 "ifupdown.nw"
} else {
	
#line 2054 "ifupdown.nw"
fprintf(stderr, "%s:%d: misplaced option\n", filename, line);
return NULL;
#line 1604 "ifupdown.nw"
}
#line 1521 "ifupdown.nw"
		break;
	case NONE:
	default:
		
#line 2054 "ifupdown.nw"
fprintf(stderr, "%s:%d: misplaced option\n", filename, line);
return NULL;
#line 1525 "ifupdown.nw"
}
#line 1511 "ifupdown.nw"
}
#line 1183 "ifupdown.nw"
	}
	if (
#line 1267 "ifupdown.nw"
ferror(f) != 0
#line 1184 "ifupdown.nw"
                                           ) {
		
#line 2008 "ifupdown.nw"
perror(filename);
return NULL;
#line 1186 "ifupdown.nw"
	}

	
#line 1221 "ifupdown.nw"
fclose(f);
line = -1;

#line 1190 "ifupdown.nw"
	return defn;
}