Ejemplo n.º 1
0
/*!
	Checks if an interface is valid, that is, if it has an address in any
	family, and, in case of ethernet, a hardware MAC address.
*/
bool
NetServer::_IsValidInterface(int socket, const char* name)
{
	ifreq request;
	if (!prepare_request(request, name))
		return B_ERROR;

	// check if it has an address

	int32 addresses = 0;

	for (int32 i = 0; kFamilies[i].family >= 0; i++) {
		int familySocket = ::socket(kFamilies[i].family, SOCK_DGRAM, 0);
		if (familySocket < 0)
			continue;

		if (ioctl(familySocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) == 0) {
			if (request.ifr_addr.sa_family == kFamilies[i].family)
				addresses++;
		}

		close(familySocket);
	}

	if (addresses == 0)
		return false;

	// check if it has a hardware address, too, in case of ethernet

	if (ioctl(socket, SIOCGIFPARAM, &request, sizeof(struct ifreq)) < 0)
		return false;

	int linkSocket = ::socket(AF_LINK, SOCK_DGRAM, 0);
	if (linkSocket < 0)
		return false;

	prepare_request(request, request.ifr_parameter.device);
	if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) < 0) {
		close(linkSocket);
		return false;
	}

	close(linkSocket);

	sockaddr_dl &link = *(sockaddr_dl *)&request.ifr_addr;
	if (link.sdl_type == IFT_ETHER && link.sdl_alen < 6)
		return false;

	return true;
}
Ejemplo n.º 2
0
status_t
NetServer::_DisableInterface(int socket, const char* name)
{
	ifreq request;
	if (!prepare_request(request, name))
		return B_ERROR;

	if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) < 0) {
		fprintf(stderr, "%s: Getting flags failed: %s\n", Name(), 
			strerror(errno));
		return B_ERROR;
	}
	// Set interface down
	request.ifr_flags &= ~(IFF_UP | IFF_AUTO_CONFIGURED | IFF_CONFIGURING);

	if (ioctl(socket, SIOCSIFFLAGS, &request, sizeof(struct ifreq)) < 0) {
		fprintf(stderr, "%s: Setting flags failed: %s\n", Name(), 
			strerror(errno));
		return B_ERROR;
	}

	fprintf(stderr, "%s: set %s interface down...\n", Name(), name); 
	
	return B_OK;
}
Ejemplo n.º 3
0
status_t
get_mac_address(const char* device, uint8* address)
{
	int socket = ::socket(AF_LINK, SOCK_DGRAM, 0);
	if (socket < 0)
		return errno;

	ifreq request;
	if (!prepare_request(request, device)) {
		close(socket);
		return B_ERROR;
	}

	if (ioctl(socket, SIOCGIFADDR, &request, sizeof(struct ifreq)) < 0) {
		close(socket);
		return errno;
	}

	close(socket);

	sockaddr_dl &link = *(sockaddr_dl *)&request.ifr_addr;
	if (link.sdl_type != IFT_ETHER)
		return B_BAD_TYPE;

	if (link.sdl_alen == 0)
		return B_ENTRY_NOT_FOUND;

	uint8 *mac = (uint8 *)LLADDR(&link);
	memcpy(address, mac, 6);

	return B_OK;
}
Ejemplo n.º 4
0
void
NetServer::_HandleDeviceMonitor(int socket, BMessage* message)
{
	int32 opcode;
	if (message->FindInt32("opcode", &opcode) != B_OK
		|| (opcode != B_ENTRY_CREATED && opcode != B_ENTRY_REMOVED))
		return;

	const char* path;
	const char* watchedPath;
	if (message->FindString("watched_path", &watchedPath) != B_OK
		|| message->FindString("path", &path) != B_OK)
		return;
		
	if (opcode == B_ENTRY_CREATED)
		_ConfigureDevice(socket, path);
	else {
		ifreq request;
		if (!prepare_request(request, path))
			return;
		
		if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) {
			fprintf(stderr, "%s: Could not delete interface %s: %s\n",
				Name(), path, strerror(errno));
		}
	}
}
Ejemplo n.º 5
0
Error HTTPClient::request(Method p_method, const String &p_url, const Vector<String> &p_headers, const String &p_body) {

	Error err = prepare_request(p_method, p_url, p_headers);
	if (err != OK)
		return err;
	godot_xhr_send_string(xhr_id, p_body.utf8().get_data());
	return OK;
}
Ejemplo n.º 6
0
Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const PoolVector<uint8_t> &p_body) {

	Error err = prepare_request(p_method, p_url, p_headers);
	if (err != OK)
		return err;
	PoolByteArray::Read read = p_body.read();
	godot_xhr_send_data(xhr_id, read.ptr(), p_body.size());
	return OK;
}
Ejemplo n.º 7
0
void
delete_interface(int socket, const char* name)
{
	ifreq request;
	if (!prepare_request(request, name))
		return;

	if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) {
		fprintf(stderr, "%s: Could not delete interface %s: %s\n",
			kProgramName, name, strerror(errno));
	}
}
Ejemplo n.º 8
0
void
delete_route(int socket, const char *interface, route_entry &route)
{
	ifreq request;
	if (!prepare_request(request, interface))
		return;

	request.ifr_route = route;

	if (ioctl(socket, SIOCDELRT, &request, sizeof(request)) < 0) {
		fprintf(stderr, "%s: Could not delete route for %s: %s\n",
			kProgramName, interface, strerror(errno));
	}
}
Ejemplo n.º 9
0
void
NetServer::_RemoveInvalidInterfaces(int socket)
{
	// get a list of all interfaces

	ifconf config;
	config.ifc_len = sizeof(config.ifc_value);
	if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0)
		return;

	uint32 count = (uint32)config.ifc_value;
	if (count == 0) {
		// there are no interfaces yet
		return;
	}

	void *buffer = malloc(count * sizeof(struct ifreq));
	if (buffer == NULL) {
		fprintf(stderr, "%s: Out of memory.\n", Name());
		return;
	}

	config.ifc_len = count * sizeof(struct ifreq);
	config.ifc_buf = buffer;
	if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) {
		free(buffer);
		return;
	}

	ifreq *interface = (ifreq *)buffer;

	for (uint32 i = 0; i < count; i++) {
		if (!_IsValidInterface(socket, interface->ifr_name)) {
			// remove invalid interface
			ifreq request;
			if (!prepare_request(request, interface->ifr_name))
				break;

			if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) {
				fprintf(stderr, "%s: Could not delete interface %s: %s\n",
					Name(), interface->ifr_name, strerror(errno));
			}
		}

		interface = (ifreq *)((addr_t)interface + IF_NAMESIZE
			+ interface->ifr_addr.sa_len);
	}

	free(buffer);
}
Ejemplo n.º 10
0
status_t
NetServer::_RemoveInterface(int socket, const char* name)
{
	ifreq request;
	if (!prepare_request(request, name))
		return B_ERROR;
		
	if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) {
		fprintf(stderr, "%s: Could not delete interface %s: %s\n",
			Name(), name, strerror(errno));
		return B_ERROR;
	}
	
	return B_OK;
}
Ejemplo n.º 11
0
static int
pcap_stats_haiku(pcap_t *handle, struct pcap_stat *stats)
{
	ifreq request;
	prepare_request(request, handle->md.device);

	if (ioctl(handle->fd, SIOCGIFSTATS, &request, sizeof(struct ifreq)) < 0) {
		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pcap_stats: %s",
			strerror(errno));
		return -1;
	}

	handle->md.stat.ps_recv += request.ifr_stats.receive.packets;
	handle->md.stat.ps_drop += request.ifr_stats.receive.dropped;
	*stats = handle->md.stat;
	return 0;
}
Ejemplo n.º 12
0
static int
pcap_stats_haiku(pcap_t *handle, struct pcap_stat *stats)
{
	struct pcap_haiku* handlep = (struct pcap_haiku*)handle->priv;
	ifreq request;
	int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
	if (socket < 0) {
		return -1;
	}
	prepare_request(request, handlep->device);
	if (ioctl(socket, SIOCGIFSTATS, &request, sizeof(struct ifreq)) < 0) {
		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pcap_stats: %s",
			strerror(errno));
		close(socket);
		return -1;
	}

	close(socket);
	handlep->stat.ps_recv += request.ifr_stats.receive.packets;
	handlep->stat.ps_drop += request.ifr_stats.receive.dropped;
	*stats = handlep->stat;
	return 0;
}
Ejemplo n.º 13
0
extern "C" pcap_t *
pcap_open_live(const char *device, int snapLength, int /*promisc*/,
	int /*timeout*/, char *errorBuffer)
{
	// TODO: handle promiscous mode!

	// we need a socket to talk to the networking stack
	int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
	if (socket < 0) {
		snprintf(errorBuffer, PCAP_ERRBUF_SIZE,
			"The networking stack doesn't seem to be available.\n");
		return NULL;
	}

	struct ifreq request;
	if (!prepare_request(request, device)) {
		snprintf(errorBuffer, PCAP_ERRBUF_SIZE,
			"Interface name \"%s\" is too long.", device);
		close(socket);
		return NULL;
	}

	// check if the interface exist
	if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) < 0) {
		snprintf(errorBuffer, PCAP_ERRBUF_SIZE,
			"Interface \"%s\" does not exist.\n", device);
		close(socket);
		return NULL;
	}

	// get link level interface for this interface

	if (ioctl(socket, SIOCGIFPARAM, &request, sizeof(struct ifreq)) < 0) {
		snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Cannot get link level: %s\n",
			strerror(errno));
		close(socket);
		return NULL;
	}

	close(socket);
		// no longer needed after this point

	socket = ::socket(AF_LINK, SOCK_DGRAM, 0);
	if (socket < 0) {
		snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "No link level: %s\n",
			strerror(errno));
		return NULL;
	}

	// start monitoring
	prepare_request(request, request.ifr_parameter.device);
	if (ioctl(socket, SIOCSPACKETCAP, &request, sizeof(struct ifreq)) < 0) {
		snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Cannot start monitoring: %s\n",
			strerror(errno));
		close(socket);
		return NULL;
	}

	pcap_t* handle = (pcap_t*)malloc(sizeof(pcap_t));
	if (handle == NULL) {
		snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "malloc: %s", strerror(errno));
		close(socket);
		return NULL;
	}

	memset(handle, 0, sizeof(pcap_t));

	handle->bufsize = 65536;
		// TODO: should be determined by interface MTU

	// allocate buffer for monitoring the device
	handle->buffer = (u_char*)malloc(handle->bufsize);
	if (handle->buffer == NULL) {
		snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "buffer malloc: %s",
			strerror(errno));
		free(handle);
		close(socket);
		return NULL;
	}

	handle->md.device = strdup(device);
	if (handle->md.device == NULL) {
		snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "strdup device: %s",
			strerror(errno));
		free(handle);
		close(socket);
		return NULL;
	}

	handle->snapshot = snapLength;
	handle->offset = 0;
	handle->selectable_fd = socket;
	handle->fd = socket;
	handle->linktype = DLT_EN10MB;
		// TODO: check interface type!

	handle->read_op = pcap_read_haiku;
	handle->setfilter_op = pcap_setfilter_haiku;
	handle->inject_op = pcap_inject_haiku;
	handle->stats_op = pcap_stats_haiku;

	// use default hooks where possible
	handle->getnonblock_op = pcap_getnonblock_fd;
	handle->setnonblock_op = pcap_setnonblock_fd;
	handle->close_op = pcap_close_common;

	return handle;
}
Ejemplo n.º 14
0
extern "C" int
pcap_platform_finddevs(pcap_if_t** _allDevices, char* errorBuffer)
{
	// we need a socket to talk to the networking stack
	int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
	if (socket < 0) {
		snprintf(errorBuffer, PCAP_ERRBUF_SIZE,
			"The networking stack doesn't seem to be available.\n");
		return -1;
	}

	// get a list of all interfaces

	ifconf config;
	config.ifc_len = sizeof(config.ifc_value);
	if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0) {
		close(socket);
		return -1;
	}

	uint32 count = (uint32)config.ifc_value;
	if (count == 0) {
		snprintf(errorBuffer, PCAP_ERRBUF_SIZE,
			"There are no interfaces defined!\n");
		close(socket);
		return -1;
	}

	void* buffer = malloc(count * sizeof(struct ifreq));
	if (buffer == NULL) {
		snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Out of memory.\n");
		close(socket);
		return -1;
	}

	config.ifc_len = count * sizeof(struct ifreq);
	config.ifc_buf = buffer;
	if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) {
		close(socket);
		return -1;
	}

	ifreq* interface = (ifreq*)buffer;

	for (uint32 i = 0; i < count; i++) {
		int flags = 0;

		// get interface type

		int linkSocket = ::socket(AF_LINK, SOCK_DGRAM, 0);
		if (linkSocket < 0) {
			fprintf(stderr, "No link level: %s\n", strerror(errno));
		} else {
			struct ifreq request;
			if (!prepare_request(request, interface->ifr_name)) {
				snprintf(errorBuffer, PCAP_ERRBUF_SIZE,
					"Interface name \"%s\" is too long.", interface->ifr_name);
				close(linkSocket);
				close(socket);
				return -1;
			}

			if (ioctl(socket, SIOCGIFPARAM, &request, sizeof(struct ifreq))
					== 0) {
				prepare_request(request, request.ifr_parameter.device);
				if (ioctl(linkSocket, SIOCGIFADDR, &request,
						sizeof(struct ifreq)) == 0) {
					sockaddr_dl &link = *(sockaddr_dl*)&request.ifr_addr;

					if (link.sdl_type == IFT_LOOP)
						flags = IFF_LOOPBACK;
				}
			}
			close(linkSocket);
		}

		pcap_add_if(_allDevices, interface->ifr_name, flags, NULL, errorBuffer);

		interface = (ifreq *)((addr_t)interface + IF_NAMESIZE
			+ interface->ifr_addr.sa_len);
	}

	free(buffer);
	close(socket);
	return 0;
}
Ejemplo n.º 15
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);
		}
	}
}
Ejemplo n.º 16
0
status_t
DHCPClient::_Negotiate(dhcp_state state)
{
	int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
	if (socket < 0)
		return errno;

	sockaddr_in local;
	memset(&local, 0, sizeof(struct sockaddr_in));
	local.sin_family = AF_INET;
	local.sin_len = sizeof(struct sockaddr_in);
	local.sin_port = htons(DHCP_CLIENT_PORT);
	local.sin_addr.s_addr = INADDR_ANY;

	// Enable reusing the port . This is needed in case there is more
	// than 1 interface that needs to be configured. Note that the only reason
	// this works is because there is code below to bind to a specific
	// interface.
	int option = 1;
	setsockopt(socket, SOL_SOCKET, SO_REUSEPORT, &option, sizeof(option));

	if (bind(socket, (struct sockaddr *)&local, sizeof(local)) < 0) {
		close(socket);
		return errno;
	}

	sockaddr_in broadcast;
	memset(&broadcast, 0, sizeof(struct sockaddr_in));
	broadcast.sin_family = AF_INET;
	broadcast.sin_len = sizeof(struct sockaddr_in);
	broadcast.sin_port = htons(DHCP_SERVER_PORT);
	broadcast.sin_addr.s_addr = INADDR_BROADCAST;

	option = 1;
	setsockopt(socket, SOL_SOCKET, SO_BROADCAST, &option, sizeof(option));

	if (state == INIT) {
		// The local interface does not have an address yet, bind the socket
		// to the device directly.
		int linkSocket = ::socket(AF_LINK, SOCK_DGRAM, 0);
		if (linkSocket >= 0) {
			// we need to know the index of the device to be able to bind to it
			ifreq request;
			prepare_request(request, Device());
			if (ioctl(linkSocket, SIOCGIFINDEX, &request, sizeof(struct ifreq))
					== 0) {
				setsockopt(socket, SOL_SOCKET, SO_BINDTODEVICE,
					&request.ifr_index, sizeof(int));
			}

			close(linkSocket);
		}
	}

	bigtime_t previousLeaseTime = fLeaseTime;
	fLeaseTime = 0;
	fRenewalTime = 0;
	fRebindingTime = 0;

	status_t status = B_ERROR;
	time_t timeout;
	uint32 tries;
	_ResetTimeout(socket, timeout, tries);

	dhcp_message discover(DHCP_DISCOVER);
	_PrepareMessage(discover, state);

	dhcp_message request(DHCP_REQUEST);
	_PrepareMessage(request, state);

	// send discover/request message
	_SendMessage(socket, state == INIT ? discover : request,
		state != RENEWAL ? broadcast : fServer);
		// no need to check the status; in case of an error we'll just send
		// the message again

	// receive loop until we've got an offer and acknowledged it

	while (state != ACKNOWLEDGED) {
		char buffer[2048];
		ssize_t bytesReceived = recvfrom(socket, buffer, sizeof(buffer),
			0, NULL, NULL);
		if (bytesReceived < 0 && errno == B_TIMED_OUT) {
			// depending on the state, we'll just try again
			if (!_TimeoutShift(socket, timeout, tries)) {
				close(socket);
				return B_TIMED_OUT;
			}

			if (state == INIT)
				_SendMessage(socket, discover, broadcast);
			else {
				_SendMessage(socket, request,
					state != RENEWAL ? broadcast : fServer);
			}

			continue;
		} else if (bytesReceived < 0)
			break;

		dhcp_message *message = (dhcp_message *)buffer;
		if (message->transaction_id != htonl(fTransactionID)
			|| !message->HasOptions()
			|| memcmp(message->mac_address, discover.mac_address,
				discover.hardware_address_length)) {
			// this message is not for us
			continue;
		}

		switch (message->Type()) {
			case DHCP_NONE:
			default:
				// ignore this message
				break;

			case DHCP_OFFER:
			{
				// first offer wins
				if (state != INIT)
					break;

				// collect interface options

				fAssignedAddress = message->your_address;

				fConfiguration.MakeEmpty();
				fConfiguration.AddString("device", Device());
				fConfiguration.AddBool("auto", true);

				BMessage address;
				address.AddString("family", "inet");
				address.AddString("address", _ToString(fAssignedAddress));
				_ParseOptions(*message, address);

				fConfiguration.AddMessage("address", &address);

				// request configuration from the server

				_ResetTimeout(socket, timeout, tries);
				state = REQUESTING;
				_PrepareMessage(request, state);

				status = _SendMessage(socket, request, broadcast);
					// we're sending a broadcast so that all potential offers
					// get an answer
				break;
			}

			case DHCP_ACK:
			{
				if (state != REQUESTING && state != REBINDING
					&& state != RENEWAL)
					continue;

				// TODO: we might want to configure the stuff, don't we?
				BMessage address;
				_ParseOptions(*message, address);
					// TODO: currently, only lease time and DNS is updated this way

				// our address request has been acknowledged
				state = ACKNOWLEDGED;

				// configure interface
				BMessage reply;
				status = Target().SendMessage(&fConfiguration, &reply);
				if (status == B_OK)
					status = reply.FindInt32("status", &fStatus);
				break;
			}

			case DHCP_NACK:
				if (state != REQUESTING)
					continue;

				// try again (maybe we should prefer other servers if this
				// happens more than once)
				status = _SendMessage(socket, discover, broadcast);
				if (status == B_OK)
					state = INIT;
				break;
		}
	}

	close(socket);

	if (status == B_OK && fLeaseTime > 0) {
		// notify early enough when the lease is
		if (fRenewalTime == 0)
			fRenewalTime = fLeaseTime * 2/3;
		if (fRebindingTime == 0)
			fRebindingTime = fLeaseTime * 5/6;

		bigtime_t now = system_time();
		_RestartLease(fRenewalTime);

		fLeaseTime += now;
		fRenewalTime += now;
		fRebindingTime += now;
			// make lease times absolute
	} else {
		fLeaseTime = previousLeaseTime;
		bigtime_t now = system_time();
		fRenewalTime = (fLeaseTime - now) * 2/3 + now;
		fRebindingTime = (fLeaseTime - now) * 5/6 + now;
	}

	return status;
}
Ejemplo n.º 17
0
int retrieve_stock_price(struct stock_price* price_info, char* url, parse_body_string_fun parse_body_string)
{
	int nret = 0;
	struct request * request = NULL;
	char *host_name = NULL;
	char *full_path = NULL;

	char *request_string = NULL;
	char *response_string = NULL;
	char *body_string = NULL;
	int body_size;
	char *p = NULL;

	struct ghbnwt_context *ctx = NULL;
	struct sockaddr_in sa;

	int res;
	int bufsize;

	int sock;

	url_parse (url, &host_name, &full_path);
	request = prepare_request(host_name, full_path);
	nret = 1;

	// Get server's ip adress.
	ctx =(struct ghbnwt_context *) malloc(sizeof(struct ghbnwt_context));
	ctx->host_name = host_name;
	ctx->hptr = gethostbyname (ctx->host_name);
	if (!ctx->hptr)
	{
		nret = -1;
		goto exit;
	}

	// Get socket descriptor.
	sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);

	// Connect to server.
	memset(&sa, 0, sizeof(sa));
	sa.sin_family = AF_INET;
	sa.sin_port = htons (80);
	memcpy (&sa.sin_addr, *ctx->hptr->h_addr_list, 4);
	if(-1 == connect (sock, (const struct sockaddr *)&sa, sizeof(sa)))
	{
		nret = -1;
		goto exit;
	}

	// Send request.
	p = request_string = organize_request_string(request);
	bufsize = strlen(request_string);
	res = 0;
	while (bufsize > 0)
	{
		res = send(sock, p, bufsize, 0);
		if (res <= 0)
			break;
		p += res;
		bufsize -= res;
	}

	// Receive response.
	response_string = receive_response(sock, &body_string, &body_size);
	if (response_string == NULL)
	{
		nret = -1;
	}
	else if (parse_response(response_string) == 200)
	{
		body_string = read_body(sock, body_string, body_size);
		if (body_string)
		{
			// Parse string of body
			if (body_string)
				parse_body_string(price_info, body_string);
		}
	}
	else
	{
		nret = -1;
	}

exit:
	// Close a connection.
	close(sock);

	// Reclaim heap memory space.
	free(host_name);
	free(full_path);
	free(request->headers);
	free(request);
	free(request_string);
	free(response_string);
	free(body_string);

	return nret;
}
Ejemplo n.º 18
0
void
list_interface(int socket, const char* name)
{
	ifreq request;
	if (!prepare_request(request, name))
		return;

	if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) < 0) {
		fprintf(stderr, "%s: Interface \"%s\" does not exist.\n", kProgramName,
			name);
		return;
	}

	printf("%s", name);
	size_t length = strlen(name);
	if (length < 8)
		putchar('\t');
	else
		printf("\n\t");

	// get link level interface for this interface

	int linkSocket = ::socket(AF_LINK, SOCK_DGRAM, 0);
	if (linkSocket < 0) {
		printf("No link level: %s\n", strerror(errno));
	} else {
		const char *type = "unknown";
		char address[256];
		strcpy(address, "none");

		if (ioctl(socket, SIOCGIFPARAM, &request, sizeof(struct ifreq)) == 0) {
			prepare_request(request, request.ifr_parameter.device);
			if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq))
					== 0) {
				sockaddr_dl &link = *(sockaddr_dl *)&request.ifr_addr;

				switch (link.sdl_type) {
					case IFT_ETHER:
					{
						type = "Ethernet";

						if (link.sdl_alen > 0) {
							uint8 *mac = (uint8 *)LLADDR(&link);
							sprintf(address, "%02x:%02x:%02x:%02x:%02x:%02x",
								mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
						} else
							strcpy(address, "not available");
						break;
					}
					case IFT_LOOP:
						type = "Local Loopback";
						break;
					case IFT_MODEM:
						type = "Modem";
						break;
				}
			}
		}

		printf("Hardware Type: %s, Address: %s\n", type, address);
		close(linkSocket);
	}

	if (ioctl(socket, SIOCGIFMEDIA, &request, sizeof(struct ifreq)) == 0
		&& (request.ifr_media & IFM_ACTIVE) != 0) {
		// dump media state in case we're linked
		const char* type = "unknown";
		bool show = false;

		for (int32 i = 0; kMediaTypes[i].type >= 0; i++) {
			// loopback don't really have a media anyway
			if (IFM_TYPE(request.ifr_media) == 0/*IFT_LOOP*/)
				break;
			// only check for generic or correct subtypes
			if (kMediaTypes[i].type &&
				kMediaTypes[i].type != IFM_TYPE(request.ifr_media))
				continue;
			for (int32 j = 0; kMediaTypes[i].subtypes[j].subtype >= 0; j++) {
				if (kMediaTypes[i].subtypes[j].subtype == IFM_SUBTYPE(request.ifr_media)) {
					// found a match
					type = kMediaTypes[i].subtypes[j].pretty;
					show = true;
					break;
				}
			}
		}

		if (show)
			printf("\tMedia Type: %s\n", type);
	}

	uint32 flags = 0;
	if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) == 0)
		flags = request.ifr_flags;

	for (int32 i = 0; kFamilies[i].family >= 0; i++) {
		int familySocket = ::socket(kFamilies[i].family, SOCK_DGRAM, 0);
		if (familySocket < 0)
			continue;

		if (ioctl(familySocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) == 0) {
			printf("\t%s addr: ", kFamilies[i].name);
			kFamilies[i].print_address(&request.ifr_addr);

			if ((flags & IFF_BROADCAST) != 0
				&& ioctl(familySocket, SIOCGIFBRDADDR, &request, sizeof(struct ifreq)) == 0
				&& request.ifr_broadaddr.sa_family == kFamilies[i].family) {
				printf(", Bcast: ");
				kFamilies[i].print_address(&request.ifr_broadaddr);
			}
			if (ioctl(familySocket, SIOCGIFNETMASK, &request, sizeof(struct ifreq)) == 0
				&& request.ifr_mask.sa_family == kFamilies[i].family) {
				printf(", Mask: ");
				kFamilies[i].print_address(&request.ifr_mask);
			}
			putchar('\n');
		}

		close(familySocket);
	}

	// Print MTU, metric, flags

	printf("\tMTU: ");
	if (ioctl(socket, SIOCGIFMTU, &request, sizeof(struct ifreq)) == 0)
		printf("%d", request.ifr_mtu);
	else
		printf("-");

	printf(", Metric: ");
	if (ioctl(socket, SIOCGIFMETRIC, &request, sizeof(struct ifreq)) == 0)
		printf("%d", request.ifr_metric);
	else
		printf("-");

	if (flags != 0) {
		const struct {
			int			value;
			const char	*name;
		} kFlags[] = {
			{IFF_UP, "up"},
			{IFF_NOARP, "noarp"},
			{IFF_BROADCAST, "broadcast"},
			{IFF_LOOPBACK, "loopback"},
			{IFF_PROMISC, "promiscuous"},
			{IFF_ALLMULTI, "allmulti"},
			{IFF_AUTOUP, "autoup"},
			{IFF_LINK, "link"},
			{IFF_AUTO_CONFIGURED, "auto-configured"},
			{IFF_CONFIGURING, "configuring"},
		};
		bool first = true;

		for (uint32 i = 0; i < sizeof(kFlags) / sizeof(kFlags[0]); i++) {
			if ((flags & kFlags[i].value) != 0) {
				if (first) {
					printf(",");
					first = false;
				}
				putchar(' ');
				printf(kFlags[i].name);
			}
		}
	}

	putchar('\n');

	// Print statistics

	if (ioctl(socket, SIOCGIFSTATS, &request, sizeof(struct ifreq)) == 0) {
		printf("\tReceive: %d packets, %d errors, %Ld bytes, %d mcasts, %d dropped\n",
			request.ifr_stats.receive.packets, request.ifr_stats.receive.errors,
			request.ifr_stats.receive.bytes, request.ifr_stats.receive.multicast_packets,
			request.ifr_stats.receive.dropped);
		printf("\tTransmit: %d packets, %d errors, %Ld bytes, %d mcasts, %d dropped\n",
			request.ifr_stats.send.packets, request.ifr_stats.send.errors,
			request.ifr_stats.send.bytes, request.ifr_stats.send.multicast_packets,
			request.ifr_stats.send.dropped);
		printf("\tCollisions: %d\n", request.ifr_stats.collisions);
	}

	putchar('\n');
}
Ejemplo n.º 19
0
int main(int argc, char **argv)
{
	int run_time = 30;
	int op = O_RDONLY;
	int qd = 4;
	int end_of_device = 0;
	int opt, i, j, max_req, rc, ios_ready, in_flight, count;
	unsigned long arena_size;
	unsigned long seed = time(NULL);
	unsigned long mix_seed = time(NULL);
	unsigned long random_range = 0;
	unsigned char *arena;
	struct iocb *iocbs;
	struct iocb *ioptr;
	struct iocb **iolist;
	struct iocb **iolist_ptr;
	struct io_event *events;
	struct timespec start, end, now;
	unsigned long total_data, total_writes, total_count;
	int min_data, max_data;
	io_context_t ioctx;
	double mbs, actual_time;

	struct option options[] = {
		{ "help", no_argument, NULL, 'h' },
		{ "write", optional_argument, NULL, 'w' },
		{ "loop", no_argument, NULL, 'l' },
		{ "mixseed", required_argument, NULL, 'm' },
		{ "qd", required_argument, NULL, 'q' },
		{ "random", optional_argument, NULL, 'r' },
		{ "range", required_argument, NULL, 'a' },
		{ "size", required_argument, NULL, 's' },
		{ "time", required_argument, NULL, 't' },
		{ NULL }
	};

	req_size = 1024 * 1024;
	write_pct = 0.0;

	for (;;) {
		opt = getopt_long(argc, argv, "hwlq:s:t:", options, NULL);

		if (opt == -1)
			break;

		switch (opt) {
		case 'w':
			op = O_RDWR;
			write_pct = 1.0;
			if (optarg)
				write_pct = strtod(optarg, NULL) / 100.0;
			if (write_pct < 1.0)
				random_offsets = 1;
			break;
		case 'l':
			loop_at_end = 1;
			break;
		case 'm':
			mix_seed = strtoul(optarg, NULL, 0);
			break;
		case 'q':
			qd = atoi(optarg);
			break;
		case 't':
			run_time = atoi(optarg);
			break;
		case 's':
			req_size = strtoul(optarg, NULL, 0);
			break;
		case 'r':
			random_offsets = 1;
			if (optarg)
				seed = strtoul(optarg, NULL, 0);
			else
				seed = time(NULL);
			break;
		case 'a':
			random_range = strtoul(optarg, NULL, 0);
			break;
		case 'h':
		case '?':
		default:
			usage(argv[0]);
			break;
		}
	}

	if (run_time < 1) {
		fprintf(stderr, "%s: run time must be at least 1 second\n",
				argv[0]);
		exit(1);
	}

	if (qd < 0 || qd > 64) {
		fprintf(stderr, "%s: queue depth must be between 1 and 64\n",
				argv[0]);
		exit(1);
	}

	if (req_size < 4096 || req_size > (16 * 1024 * 1024)) {
		fprintf(stderr, "%s: request size must be between 4K and 16M\n",
				argv[0]);
		exit(1);
	}

	/* Always do a multiple of a page for direct IO.
	 */
	req_size &= ~4095;

	if (random_range) {
		random_range /= req_size;
		if (random_range < 2) {
			fprintf(stderr, "%s: random range gives no "
					"randomness\n", argv[0]);
			exit(1);
		}
	}

	if (optind == argc) {
		fprintf(stderr, "%s: need devices to benchmark\n", argv[0]);
		exit(1);
	}

	ndev = argc - optind;
	devs = malloc(ndev * sizeof(*devs));
	if (!ndev) {
		fprintf(stderr, "%s: no memory for devices\n", argv[0]);
		exit(1);
	}

	for (i = 0; i < ndev; i++) {
		devs[i].replace = -1;
		devs[i].io_base = NULL;
		devs[i].offset = 0;
		devs[i].count = 0;
		devs[i].writes = 0;
		devs[i].status = ' ';
		devs[i].name = argv[optind++];
		devs[i].fd = open(devs[i].name, op|O_DIRECT|O_SYNC);
		if (devs[i].fd < 0) {
			fprintf(stderr, "%s: opening ", argv[0]);
			perror(devs[i].name);
			exit(1);
		}
		devs[i].size = lseek(devs[i].fd, 0, SEEK_END);
		if (devs[i].size < 0) {
			fprintf(stderr, "%s: lseek ", argv[0]);
			perror(devs[i].name);
			exit(1);
		}
		if (random_offsets) {
			unsigned long t = seed + i;

			devs[i].random_range = devs[i].size / req_size;
			if (random_range && devs[i].random_range > random_range)
				devs[i].random_range = random_range;

			devs[i].off_rand_state[2] = t >> 16;
			devs[i].off_rand_state[1] = t & 0xffff;
			devs[i].off_rand_state[0] = 0x330e;

			t = mix_seed + i;
			devs[i].rw_rand_state[2] = t >> 16;
			devs[i].rw_rand_state[1] = t & 0xffff;
			devs[i].rw_rand_state[0] = 0x330e;
		}
	}

	/* The arena needs to be big enough to host the maximum number of
	 * requests possible, plus an extra set of requests to pass around
	 * the devices to fairly share any memory fragmentation seen.
	 */
	max_req = ndev * qd;
	arena_size = (max_req + qd) * req_size;
	arena = mmap(NULL, arena_size, PROT_READ|PROT_WRITE,
			MAP_ANONYMOUS|MAP_POPULATE|MAP_PRIVATE, -1, 0);
	if (arena == MAP_FAILED) {
		fprintf(stderr, "%s: unable to allocate arena\n", argv[0]);
		exit(1);
	}

	memset(arena, 0, arena_size);

	iocbs = malloc(max_req * sizeof(*iocbs));
	if (!iocbs) {
		fprintf(stderr, "%s: no memory for IOCBs\n", argv[0]);
		exit(1);
	}

	iolist = malloc(max_req * sizeof(*iocbs));
	if (!iolist) {
		fprintf(stderr, "%s: no memory for IOCB list\n", argv[0]);
		exit(1);
	}

	events = malloc(max_req * sizeof(*events));
	if (!iolist) {
		fprintf(stderr, "%s: no memory for IOCB list\n", argv[0]);
		exit(1);
	}

	rc = io_queue_init(max_req, &ioctx);
	if (rc < 0) {
		fprintf(stderr, "%s: unable to initialize IO context: %s\n",
				argv[0], strerror(-rc));
		exit(1);
	}

	/* Prepopulate our IO requests
	 */
	ios_ready = 0;
	ioptr = iocbs;
	iolist_ptr = iolist;
	for (i = 0; i < qd; i++) {
		for (j = 0; j < ndev; j++) {
			if (!devs[j].io_base)
				devs[j].io_base = ioptr;

			/* Initial iocb prep, will be overwritten in
			 * prepare_request() with proper offset and operation.
			 */
			io_prep_pwrite(ioptr, devs[j].fd, arena, req_size, 0);
			ioptr->data = &devs[j];
			arena += req_size;

			if (prepare_request(&devs[j], ioptr)) {
				fprintf(stderr, "Premature end of device for "
						"%s\n", devs[j].name);
				exit(1);
			}

			*iolist_ptr++ = ioptr++;
			ios_ready++;
		}
	}

	/* Populate the replacement list
	 */
	buf_dev = 0;
	buf_next = NULL;
	buf_ready = NULL;
	for (i = 0; i < qd; i++) {
		buf_p = (struct buf_list *) arena;
		buf_p->next = buf_ready;
		buf_ready = buf_p;
		arena += req_size;
	}

	clock_gettime(CLOCK_MONOTONIC_HR, &now);
	end.tv_sec = now.tv_sec + run_time;
	end.tv_nsec = now.tv_nsec;

	devs[0].replace = 0;
	in_flight = 0;
	clock_gettime(CLOCK_MONOTONIC_HR, &start);

	/* Prime the IO pump with our prepared requests
	 */
	rc = io_submit(ioctx, ios_ready, iolist);
	if (rc < 0) {
		fprintf(stderr, "%s: io_submit() failed: %s\n",
				argv[0], strerror(-rc));
		exit(1);
	}

	in_flight += ios_ready;
	iolist_ptr = iolist;
	ios_ready = 0;

	/* Main IO loop
	 */
	while (time_before(&now, &end) && !end_of_device) {
		count = io_getevents(ioctx, 1, in_flight, events, NULL);
		if (count <= 0) {
			fprintf(stderr, "%s: io_getevents() failed: "
					"%s\n", argv[0], strerror(-rc));
			exit(1);
		}

		for (i = 0; i < count && !end_of_device; i++) {
			struct iocb *iocb = events[i].obj;
			struct dev_info *dev = iocb->data;

			if (events[i].res2) {
				fprintf(stderr, "%s: got error for %s:"
						" %lu\n", argv[0],
						dev->name, 
						events[i].res2);
				exit(1);
			}

			end_of_device = prepare_request(dev, iocb);
			if (!end_of_device) {
				*iolist_ptr++ = iocb;
				ios_ready++;
			}

			in_flight--;
		}

		/* If we're here, then odds are good we have IO to submit.
		 * Check just in case something woke us up other than an
		 * IO completion.
		 */
		if (ios_ready) {
			rc = io_submit(ioctx, ios_ready, iolist);
			if (rc < 0) {
				fprintf(stderr, "%s: io_submit() failed: %s\n",
						argv[0], strerror(-rc));
				exit(1);
			}

			in_flight += ios_ready;
			iolist_ptr = iolist;
			ios_ready = 0;
		}

		clock_gettime(CLOCK_MONOTONIC_HR, &now);
	}

	if (end_of_device) {
		actual_time = now.tv_nsec - start.tv_nsec;
		actual_time /= 10e9;
		actual_time += now.tv_sec - start.tv_sec;
	} else
		actual_time = run_time;

	/* Ok, test time is finished, drain outstanding requests
	 */
	while (in_flight) {
		count = io_getevents(ioctx, 1, in_flight, events, NULL);
		if (count <= 0) {
			fprintf(stderr, "%s: draining io_getevents() failed: "
					"%s\n", argv[0], strerror(-rc));
			exit(1);
		}

		for (i = 0; i < count; i++) {
			struct iocb *iocb = events[i].obj;
			struct dev_info *dev = iocb->data;

			if (events[i].res2) {
				fprintf(stderr, "%s: draining got error for %s:"
						" %lu\n", argv[0],
						dev->name, 
						events[i].res2);
				exit(1);
			}

			in_flight--;
		}
	}

	/* Find the targets that wrote the min and max data so we can
	 * calculate the skew.
	 */
	min_data = max_data = 0;
	total_data = total_writes = total_count= 0;
	for (i = 0; i < ndev; i++) {
		if (devs[i].count < devs[min_data].count)
			min_data = i;
		if (devs[i].count > devs[max_data].count)
			max_data = i;
		total_data += devs[i].count * req_size;
		total_writes += devs[i].writes;
		total_count += devs[i].count;
	}
	devs[min_data].status = 'm';
	devs[max_data].status = 'M';

	printf("run time: %.6f seconds%s\n", actual_time,
	       end_of_device ? " (end of device reached)" : "");
	printf("queue depth: %d\n", qd);
	printf("operation: %s ", random_offsets ? "random" : "sequential");
	if (write_pct >= 1.0)
		printf("write\n");
	else if (write_pct == 0.0)
		printf("read\n");
	else {
		printf("mixed (goal %.02f%% writes)\n", write_pct * 100);
		printf("random request seed: %lu\n", mix_seed);
	}
	if (random_offsets)
		printf("random offset seed: %lu\n", seed);
	if (random_range)
		printf("random range: %lu bytes\n", random_range * req_size);
	printf("request size: %lu bytes\n\n", req_size);

	for (i = 0; i < ndev; i++) {
		mbs = ((double) devs[i].count * req_size) / actual_time;
		mbs /= 1024 * 1024;
		printf("%c %s: %lu %.2f MB/s", devs[i].status,
			devs[i].name, devs[i].count * req_size, mbs);
		if (write_pct != 0.0 && write_pct < 1.0) {
			printf("  %02.f%% writes",
				100.0 * devs[i].writes / devs[i].count);
		}
		printf("\n");
	}

	mbs = (double) total_data / actual_time;
	mbs /= 1024 * 1024;
	printf("total: %lu %.2f MB/s", total_data, mbs);
	mbs = (double) (devs[max_data].count - devs[min_data].count);
	mbs *= req_size;
	mbs /= actual_time;
	mbs /= 1024 * 1024;
	printf(" skew %.2f MB/s", mbs);
	if (write_pct != 0.0 && write_pct < 1.0)
		printf("  %02.f%% writes", 100.0 * total_writes / total_count);
	printf("\n");

	return 0;
}
Ejemplo n.º 20
0
status_t
NetServer::_ConfigureInterface(int socket, BMessage& interface,
	bool fromMessage)
{
	const char *device;
	if (interface.FindString("device", &device) != B_OK)
		return B_BAD_VALUE;

	ifreq request;
	if (!prepare_request(request, device))
		return B_ERROR;

	bool startAutoConfig = false;

	int32 flags;
	if (interface.FindInt32("flags", &flags) < B_OK)
		flags = IFF_UP;

	bool autoConfigured;
	if (interface.FindBool("auto", &autoConfigured) == B_OK && autoConfigured)
		flags |= IFF_AUTO_CONFIGURED;

	int32 mtu;
	if (interface.FindInt32("mtu", &mtu) < B_OK)
		mtu = -1;

	int32 metric;
	if (interface.FindInt32("metric", &metric) < B_OK)
		metric = -1;

	BMessage addressMessage;
	for (int32 index = 0; interface.FindMessage("address", index,
			&addressMessage) == B_OK; index++) {
		const char* family;
		if (addressMessage.FindString("family", &family) < B_OK)
			continue;

		int32 familyIndex;
		if (!get_family_index(family, familyIndex)) {
			// we don't support this family
			continue;
		}

		int familySocket = socket;
		if (family_at_index(familyIndex) != AF_INET)
			socket = ::socket(family_at_index(familyIndex), SOCK_DGRAM, 0);
		if (socket < 0) {
			// the family is not available in this environment
			continue;
		}

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

		if (interfaceIndex == 0) {
			// we need to create the interface 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", Name(),
					strerror(errno));
				return errno;
			}
		}

		// retrieve addresses

		bool autoConfig;
		if (addressMessage.FindBool("auto_config", &autoConfig) != B_OK)
			autoConfig = false;
#if 0
		if (autoConfig && fromMessage) {
			// we don't accept auto-config messages this way
			continue;
		}
#endif

		bool hasAddress = false, hasMask = false, hasPeer = false;
		bool hasBroadcast = false;
		struct sockaddr address, mask, peer, broadcast, gateway;
		const char* string;

		if (!autoConfig) {
			if (addressMessage.FindString("address", &string) == B_OK
				&& parse_address(familyIndex, string, address)) {
				hasAddress = true;

				if (addressMessage.FindString("mask", &string) == B_OK
					&& parse_address(familyIndex, string, mask))
					hasMask = true;
			}
			if (addressMessage.FindString("peer", &string) == B_OK
				&& parse_address(familyIndex, string, peer))
				hasPeer = true;
			if (addressMessage.FindString("broadcast", &string) == B_OK
				&& parse_address(familyIndex, string, broadcast))
				hasBroadcast = true;
		}

		route_entry route;
		memset(&route, 0, sizeof(route_entry));
		route.flags = RTF_STATIC | RTF_DEFAULT;

		request.ifr_route = route;

		if (autoConfig) {
			_QuitLooperForDevice(device);
			startAutoConfig = true;
		} else if (addressMessage.FindString("gateway", &string) == B_OK
			&& parse_address(familyIndex, string, gateway)) {
			// add gateway route, if we're asked for it

			ioctl(socket, SIOCDELRT, &request, sizeof(request));
				// Try to remove a previous default route, doesn't matter
				// if it fails.

			route.flags = RTF_STATIC | RTF_DEFAULT | RTF_GATEWAY;
			route.gateway = &gateway;

			request.ifr_route = route;
			if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) {
				fprintf(stderr, "%s: Could not add route for %s: %s\n",
					Name(), device, strerror(errno));
			}
		}

		// set addresses

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

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

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

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

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

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

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

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

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

		// set flags

		if (flags != 0) {
			request.ifr_flags = (currentFlags & ~IFF_CONFIGURING) | flags;
			if (!autoConfigured)
				request.ifr_flags = request.ifr_flags & ~IFF_AUTO_CONFIGURED;

			if (ioctl(familySocket, SIOCSIFFLAGS, &request, sizeof(struct ifreq)) < 0)
				fprintf(stderr, "%s: Setting flags failed: %s\n", Name(), strerror(errno));
		}

		// set options

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

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

	if (startAutoConfig) {
		// start auto configuration
		AutoconfigLooper* looper = new AutoconfigLooper(this, device);
		looper->Run();

		fDeviceMap[device] = looper;
	}

	return B_OK;
}
Ejemplo n.º 21
0
extern "C" pcap_t *
pcap_create_interface(const char *device, char *errorBuffer)
{
	// TODO: handle promiscous mode!

	// we need a socket to talk to the networking stack
	int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
	if (socket < 0) {
		snprintf(errorBuffer, PCAP_ERRBUF_SIZE,
			"The networking stack doesn't seem to be available.\n");
		return NULL;
	}

	struct ifreq request;
	if (!prepare_request(request, device)) {
		snprintf(errorBuffer, PCAP_ERRBUF_SIZE,
			"Interface name \"%s\" is too long.", device);
		close(socket);
		return NULL;
	}

	// check if the interface exist
	if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) < 0) {
		snprintf(errorBuffer, PCAP_ERRBUF_SIZE,
			"Interface \"%s\" does not exist.\n", device);
		close(socket);
		return NULL;
	}

	close(socket);
	// no longer needed after this point

	// get link level interface for this interface

	socket = ::socket(AF_LINK, SOCK_DGRAM, 0);
	if (socket < 0) {
		snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "No link level: %s\n",
			strerror(errno));
		return NULL;
	}

	// start monitoring
	if (ioctl(socket, SIOCSPACKETCAP, &request, sizeof(struct ifreq)) < 0) {
		snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Cannot start monitoring: %s\n",
			strerror(errno));
		close(socket);
		return NULL;
	}

	pcap_t* handle = pcap_create_common(errorBuffer,
		sizeof (struct pcap_haiku));
	if (handle == NULL) {
		snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "malloc: %s", strerror(errno));
		close(socket);
		return NULL;
	}

	handle->selectable_fd = socket;
	handle->fd = socket;
	
	handle->activate_op = pcap_activate_haiku;

	return handle;
}