コード例 #1
0
ファイル: arp.cpp プロジェクト: mmanley/Antares
/*!	Creates a permanent local entry for the interface belonging to this protocol.
	You need to hold the cache lock when calling this function.
*/
static status_t
arp_update_local(arp_protocol *protocol)
{
	ASSERT_LOCKED_MUTEX(&sCacheLock);

	net_interface *interface = protocol->interface;
	in_addr_t inetAddress;

	if (interface->address == NULL) {
		// interface has not yet been set
		inetAddress = INADDR_ANY;
	} else
		inetAddress = ((sockaddr_in *)interface->address)->sin_addr.s_addr;

	sockaddr_dl address;
	address.sdl_len = sizeof(sockaddr_dl);
	address.sdl_family = AF_LINK;
	address.sdl_type = IFT_ETHER;
	address.sdl_e_type = ETHER_TYPE_IP;
	address.sdl_nlen = 0;
	address.sdl_slen = 0;
	address.sdl_alen = interface->device->address.length;
	memcpy(LLADDR(&address), interface->device->address.data, address.sdl_alen);

	memcpy(&protocol->hardware_address, &address, sizeof(sockaddr_dl));
		// cache the address in our protocol

	arp_entry *entry;
	status_t status = arp_update_entry(inetAddress, &address,
		ARP_FLAG_LOCAL | ARP_FLAG_PERMANENT, &entry);
	if (status == B_OK)
		entry->protocol = protocol;

	return status;
}
コード例 #2
0
ファイル: arp.cpp プロジェクト: mmanley/Antares
static void
handle_arp_reply(net_buffer *buffer, arp_header &header)
{
	if (sIgnoreReplies)
		return;

	MutexLocker locker(sCacheLock);
	arp_update_entry(header.protocol_sender, (sockaddr_dl *)buffer->source, 0);
}
コード例 #3
0
ファイル: arp.cpp プロジェクト: mmanley/Antares
static status_t
handle_arp_request(net_buffer *buffer, arp_header &header)
{
	MutexLocker locker(sCacheLock);

	if (!sIgnoreReplies) {
		arp_update_entry(header.protocol_sender,
			(sockaddr_dl *)buffer->source, 0);
			// remember the address of the sender as we might need it later
	}

	// check if this request is for us

	arp_entry *entry = arp_entry::Lookup(header.protocol_target);
	if (entry == NULL
		|| (entry->flags & (ARP_FLAG_LOCAL | ARP_FLAG_PUBLISH)) == 0) {
		// We're not the one to answer this request
		// TODO: instead of letting the other's request time-out, can we reply
		//	failure somehow?
		TRACE(("  not for us\n"));
		return B_ERROR;
	}

	// send a reply (by reusing the buffer we got)

	TRACE(("  send reply!\n"));
	header.opcode = htons(ARP_OPCODE_REPLY);

	memcpy(header.hardware_target, header.hardware_sender, ETHER_ADDRESS_LENGTH);
	header.protocol_target = header.protocol_sender;
	memcpy(header.hardware_sender, LLADDR(&entry->hardware_address),
		ETHER_ADDRESS_LENGTH);
	header.protocol_sender = entry->protocol_address;

	// exchange source and destination address
	memcpy(LLADDR((sockaddr_dl *)buffer->source), header.hardware_sender,
		ETHER_ADDRESS_LENGTH);
	memcpy(LLADDR((sockaddr_dl *)buffer->destination), header.hardware_target,
		ETHER_ADDRESS_LENGTH);

	buffer->flags = 0;
		// make sure this won't be a broadcast message

	return entry->protocol->next->module->send_data(entry->protocol->next,
		buffer);
}
コード例 #4
0
ファイル: arp.cpp プロジェクト: AmirAbrams/haiku
static status_t
arp_set_local_entry(arp_protocol* protocol, const sockaddr* local)
{
	MutexLocker locker(sCacheLock);

	net_interface* interface = protocol->interface;
	in_addr_t inetAddress;

	if (local == NULL) {
		// interface has not yet been set
		inetAddress = INADDR_ANY;
	} else
		inetAddress = ((sockaddr_in*)local)->sin_addr.s_addr;

	TRACE(("%s(): address %s\n", __FUNCTION__, inet_to_string(inetAddress)));

	if (protocol->local_address == 0)
		protocol->local_address = inetAddress;

	sockaddr_dl address;
	address.sdl_len = sizeof(sockaddr_dl);
	address.sdl_family = AF_LINK;
	address.sdl_type = IFT_ETHER;
	address.sdl_e_type = htons(ETHER_TYPE_IP);
	address.sdl_nlen = 0;
	address.sdl_slen = 0;
	address.sdl_alen = interface->device->address.length;
	memcpy(LLADDR(&address), interface->device->address.data, address.sdl_alen);

	memcpy(&protocol->hardware_address, &address, sizeof(sockaddr_dl));
		// cache the address in our protocol

	arp_entry* entry;
	status_t status = arp_update_entry(inetAddress, &address,
		ARP_FLAG_LOCAL | ARP_FLAG_PERMANENT, &entry);
	if (status == B_OK)
		entry->protocol = protocol;

	return status;
}
コード例 #5
0
ファイル: arp.cpp プロジェクト: mmanley/Antares
static status_t
arp_control(const char *subsystem, uint32 function, void *buffer,
	size_t bufferSize)
{
	struct arp_control control;
	if (bufferSize != sizeof(struct arp_control))
		return B_BAD_VALUE;
	if (user_memcpy(&control, buffer, sizeof(struct arp_control)) < B_OK)
		return B_BAD_ADDRESS;

	MutexLocker locker(sCacheLock);

	switch (function) {
		case ARP_SET_ENTRY:
		{
			sockaddr_dl hardwareAddress;

			hardwareAddress.sdl_len = sizeof(sockaddr_dl);
			hardwareAddress.sdl_family = AF_LINK;
			hardwareAddress.sdl_index = 0;
			hardwareAddress.sdl_type = IFT_ETHER;
			hardwareAddress.sdl_e_type = ETHER_TYPE_IP;
			hardwareAddress.sdl_nlen = hardwareAddress.sdl_slen = 0;
			hardwareAddress.sdl_alen = ETHER_ADDRESS_LENGTH;
			memcpy(hardwareAddress.sdl_data, control.ethernet_address,
				ETHER_ADDRESS_LENGTH);

			return arp_update_entry(control.address, &hardwareAddress,
				control.flags & (ARP_FLAG_PUBLISH | ARP_FLAG_PERMANENT
					| ARP_FLAG_REJECT));
		}

		case ARP_GET_ENTRY:
		{
			arp_entry *entry = arp_entry::Lookup(control.address);
			if (entry == NULL || !(entry->flags & ARP_FLAG_VALID))
				return B_ENTRY_NOT_FOUND;

			if (entry->hardware_address.sdl_alen == ETHER_ADDRESS_LENGTH) {
				memcpy(control.ethernet_address,
					entry->hardware_address.sdl_data, ETHER_ADDRESS_LENGTH);
			} else
				memset(control.ethernet_address, 0, ETHER_ADDRESS_LENGTH);

			control.flags = entry->flags & ARP_PUBLIC_FLAG_MASK;
			return user_memcpy(buffer, &control, sizeof(struct arp_control));
		}

		case ARP_GET_ENTRIES:
		{
			hash_iterator iterator;
			hash_open(sCache, &iterator);

			arp_entry *entry;
			uint32 i = 0;
			while ((entry = (arp_entry *)hash_next(sCache, &iterator)) != NULL
				&& i < control.cookie) {
				i++;
			}
			hash_close(sCache, &iterator, false);

			if (entry == NULL)
				return B_ENTRY_NOT_FOUND;

			control.cookie++;
			control.address = entry->protocol_address;
			if (entry->hardware_address.sdl_alen == ETHER_ADDRESS_LENGTH) {
				memcpy(control.ethernet_address,
					entry->hardware_address.sdl_data, ETHER_ADDRESS_LENGTH);
			} else
				memset(control.ethernet_address, 0, ETHER_ADDRESS_LENGTH);
			control.flags = entry->flags & ARP_PUBLIC_FLAG_MASK;

			return user_memcpy(buffer, &control, sizeof(struct arp_control));
		}

		case ARP_DELETE_ENTRY:
		{
			arp_entry *entry = arp_entry::Lookup(control.address);
			if (entry == NULL)
				return B_ENTRY_NOT_FOUND;
			if ((entry->flags & ARP_FLAG_LOCAL) != 0)
				return B_BAD_VALUE;

			entry->ScheduleRemoval();
			return B_OK;
		}

		case ARP_FLUSH_ENTRIES:
		{
			hash_iterator iterator;
			hash_open(sCache, &iterator);

			arp_entry *entry;
			while ((entry = (arp_entry *)hash_next(sCache, &iterator)) != NULL) {
				// we never flush local ARP entries
				if ((entry->flags & ARP_FLAG_LOCAL) != 0)
					continue;

				entry->ScheduleRemoval();
			}
			hash_close(sCache, &iterator, false);
			return B_OK;
		}

		case ARP_IGNORE_REPLIES:
			sIgnoreReplies = control.flags != 0;
			return B_OK;
	}

	return B_BAD_VALUE;
}