Exemple #1
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));
		}
	}
}
Exemple #2
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;
	BNetworkAddress destination;
	BNetworkAddress mask;
	BNetworkAddress gateway;
	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 && familySpecified == false
				&& 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)) {
			i++;
			break;
		}

		i++;
	}

	if (!defaultRoute && destination.IsEmpty() && 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))
		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);
			}
			i++;
		} else if (!strcmp(argv[i], "nm") || !strcmp(argv[i], "netmask")) {
			if (!mask.IsEmpty()) {
				fprintf(stderr, "%s: Netmask or prefix length 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);
			}
			i++;
		} else if (!strcmp(argv[i], "plen") || !strcmp(argv[i], "prefixlen")
			|| !strcmp(argv[i], "prefix-length")) {
			if (!mask.IsEmpty()) {
				fprintf(stderr, "%s: Netmask or prefix length is specified "
					"twice\n", kProgramName);
				exit(1);
			}
			if (!prefix_length_to_mask(familyIndex, argv[i + 1], mask)) {
				fprintf(stderr, "%s: Option 'prefixlen' is invalid for this "
					"address family\n", kProgramName);
				exit(1);
			}
			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 (!destination.IsEmpty())
		route.destination = (sockaddr*)destination;
	if (!mask.IsEmpty())
		route.mask = (sockaddr*)mask;
	if (!gateway.IsEmpty()) {
		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[i].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;
}