Beispiel #1
0
/*!	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;
}
// Subtract rectangle from q
void paint_q_sub( rect_t *r )
{
    pqel_t *pqel;

    ASSERT_LOCKED_MUTEX( &rect_list_lock );

again:
    queue_iterate( &rect_list, pqel, pqel_t *, chain )
    {

        // r includes qe - delete qe
        if( rect_includes( r, &pqel->r ) )
        {
            queue_remove( &rect_list, pqel, pqel_t *, chain );
            goto again;
        }

        // r intersects w qe - divide in two
        if( rect_intersects( r, &pqel->r ) )
        {
            rect_t out1, out2;

            rect_sub( &out1, &out2, r, &pqel->r );

            if( !rect_empty( &out1 ) )
            {
                pqel_t *new1 = mkel( &out1 );  if( !new1 ) return;
                queue_enter(&rect_list, new1, pqel_t *, chain);
            }
Beispiel #3
0
static int pipefs_is_dir_empty(struct pipefs_vnode *dir)
{
	ASSERT(dir->stream.type == STREAM_TYPE_DIR);
	ASSERT_LOCKED_MUTEX(&dir->stream.u.dir.dir_lock);

	return !dir->stream.u.dir.dir_head;
}
Beispiel #4
0
static void insert_cookie_in_jar(struct pipefs_vnode *dir, struct pipefs_cookie *cookie)
{
	ASSERT(dir->stream.type == STREAM_TYPE_DIR);
	ASSERT_LOCKED_MUTEX(&dir->stream.u.dir.dir_lock);

	cookie->u.dir.next = dir->stream.u.dir.jar_head;
	dir->stream.u.dir.jar_head = cookie;
	cookie->u.dir.prev = NULL;
}
Beispiel #5
0
static int pipefs_insert_in_dir(struct pipefs_vnode *dir, struct pipefs_vnode *v)
{
	ASSERT(dir->stream.type == STREAM_TYPE_DIR);
	ASSERT_LOCKED_MUTEX(&dir->stream.u.dir.dir_lock);

	v->dir_next = dir->stream.u.dir.dir_head;
	dir->stream.u.dir.dir_head = v;

	v->parent = dir;
	return 0;
}
Beispiel #6
0
/*!	Updates the entry determined by \a protocolAddress with the specified
	\a hardwareAddress.
	If such an entry does not exist yet, a new entry is added. If you try
	to update a local existing entry but didn't ask for it (by setting
	\a flags to ARP_FLAG_LOCAL), an error is returned.

	This function does not lock the cache - you have to do it yourself
	before calling it.
*/
static status_t
arp_update_entry(in_addr_t protocolAddress, sockaddr_dl *hardwareAddress,
	uint32 flags, arp_entry **_entry = NULL)
{
	ASSERT_LOCKED_MUTEX(&sCacheLock);
	TRACE(("%s(%s, %s, flags 0x%" B_PRIx32 ")\n", __FUNCTION__,
		inet_to_string(protocolAddress), mac_to_string(LLADDR(hardwareAddress)),
		flags));

	arp_entry *entry = arp_entry::Lookup(protocolAddress);
	if (entry != NULL) {
		// We disallow updating of entries that had been resolved before,
		// but to a different address (only for those that belong to a
		// specific address - redefining INADDR_ANY is always allowed).
		// Right now, you have to manually purge the ARP entries (or wait some
		// time) to let us switch to the new address.
		if (protocolAddress != INADDR_ANY
			&& entry->hardware_address.sdl_alen != 0
			&& memcmp(LLADDR(&entry->hardware_address),
				LLADDR(hardwareAddress), ETHER_ADDRESS_LENGTH)) {
			uint8* data = LLADDR(hardwareAddress);
			dprintf("ARP host %08x updated with different hardware address "
				"%02x:%02x:%02x:%02x:%02x:%02x.\n", protocolAddress,
				data[0], data[1], data[2], data[3], data[4], data[5]);
			return B_ERROR;
		}

		entry->hardware_address = *hardwareAddress;
		entry->timestamp = system_time();
	} else {
		entry = arp_entry::Add(protocolAddress, hardwareAddress, flags);
		if (entry == NULL)
			return B_NO_MEMORY;
	}

	delete_request_buffer(entry);

	if ((entry->flags & ARP_FLAG_PERMANENT) == 0) {
		// (re)start the stale timer
		entry->timer_state = ARP_STATE_STALE;
		sStackModule->set_timer(&entry->timer, ARP_STALE_TIMEOUT);
	}

	if ((entry->flags & ARP_FLAG_REJECT) != 0)
		entry->MarkFailed();
	else
		entry->MarkValid();

	if (_entry)
		*_entry = entry;

	return B_OK;
}
Beispiel #7
0
/*!	Scans the domain list for the specified family.
	You need to hold the sDomainLock when calling this function.
*/
static net_domain_private*
lookup_domain(int family)
{
	ASSERT_LOCKED_MUTEX(&sDomainLock);

	DomainList::Iterator iterator = sDomains.GetIterator();
	while (net_domain_private* domain = iterator.Next()) {
		if (domain->family == family)
			return domain;
	}

	return NULL;
}
slab*
HashedObjectCache::ObjectSlab(void* object) const
{
	ASSERT_LOCKED_MUTEX(&lock);

	HashedSlab* slab = hash_table.Lookup(::lower_boundary(object, slab_size));
	if (slab == NULL) {
		panic("hash object cache %p: unknown object %p", this, object);
		return NULL;
	}

	return slab;
}
Beispiel #9
0
static void remove_cookie_from_jar(struct pipefs_vnode *dir, struct pipefs_cookie *cookie)
{
	ASSERT(dir->stream.type == STREAM_TYPE_DIR);
	ASSERT_LOCKED_MUTEX(&dir->stream.u.dir.dir_lock);

	if(cookie->u.dir.next)
		cookie->u.dir.next->u.dir.prev = cookie->u.dir.prev;
	if(cookie->u.dir.prev)
		cookie->u.dir.prev->u.dir.next = cookie->u.dir.next;
	if(dir->stream.u.dir.jar_head == cookie)
		dir->stream.u.dir.jar_head = cookie->u.dir.next;

	cookie->u.dir.prev = cookie->u.dir.next = NULL;
}
Beispiel #10
0
static struct pipefs_vnode *pipefs_find_in_dir(struct pipefs_vnode *dir, const char *path)
{
	struct pipefs_vnode *v;

	ASSERT(dir->stream.type == STREAM_TYPE_DIR);
	ASSERT_LOCKED_MUTEX(&dir->stream.u.dir.dir_lock);

	if(!strcmp(path, "."))
		return dir;
	if(!strcmp(path, ".."))
		return dir->parent;

	for(v = dir->stream.u.dir.dir_head; v; v = v->dir_next) {
		if(strcmp(v->name, path) == 0) {
			return v;
		}
	}
	return NULL;
}
Beispiel #11
0
/*static*/ arp_entry *
arp_entry::Add(in_addr_t protocolAddress, sockaddr_dl *hardwareAddress,
	uint32 flags)
{
	ASSERT_LOCKED_MUTEX(&sCacheLock);

	arp_entry *entry = new (std::nothrow) arp_entry;
	if (entry == NULL)
		return NULL;

	entry->protocol_address = protocolAddress;
	entry->flags = flags;
	entry->timestamp = system_time();
	entry->protocol = NULL;
	entry->request_buffer = NULL;
	entry->timer_state = ARP_NO_STATE;
	sStackModule->init_timer(&entry->timer, arp_timer, entry);

	if (hardwareAddress != NULL) {
		// this entry is already resolved
		entry->hardware_address = *hardwareAddress;
		entry->hardware_address.sdl_e_type = ETHER_TYPE_IP;
	} else {
		// this entry still needs to be resolved
		entry->hardware_address.sdl_alen = 0;
	}
	if (entry->hardware_address.sdl_len != sizeof(sockaddr_dl)) {
		// explicitly set correct length in case our caller hasn't...
		entry->hardware_address.sdl_len = sizeof(sockaddr_dl);
	}

	if (hash_insert(sCache, entry) != B_OK) {
		// We can delete the entry here with the sCacheLock held, since it's
		// guaranteed there are no timers pending.
		delete entry;
		return NULL;
	}

	return entry;
}
Beispiel #12
0
static int pipefs_remove_from_dir(struct pipefs_vnode *dir, struct pipefs_vnode *findit)
{
	struct pipefs_vnode *v;
	struct pipefs_vnode *last_v;

	ASSERT(dir->stream.type == STREAM_TYPE_DIR);
	ASSERT_LOCKED_MUTEX(&dir->stream.u.dir.dir_lock);

	for(v = dir->stream.u.dir.dir_head, last_v = NULL; v; last_v = v, v = v->dir_next) {
		if(v == findit) {
			/* make sure all dircookies dont point to this vnode */
			update_dircookies(dir, v);

			if(last_v)
				last_v->dir_next = v->dir_next;
			else
				dir->stream.u.dir.dir_head = v->dir_next;
			v->dir_next = NULL;
			return 0;
		}
	}
	return -1;
}
Beispiel #13
0
/*!	Address resolver function: prepares and triggers the ARP request necessary
	to retrieve the hardware address for \a address.

	You need to have the sCacheLock held when calling this function.
*/
static status_t
arp_start_resolve(net_datalink_protocol *protocol, in_addr_t address,
	arp_entry **_entry)
{
	ASSERT_LOCKED_MUTEX(&sCacheLock);

	// create an unresolved ARP entry as a placeholder
	arp_entry *entry = arp_entry::Add(address, NULL, 0);
	if (entry == NULL)
		return B_NO_MEMORY;

	// prepare ARP request

	entry->request_buffer = gBufferModule->create(256);
	if (entry->request_buffer == NULL) {
		entry->ScheduleRemoval();
		return B_NO_MEMORY;
	}

	NetBufferPrepend<arp_header> bufferHeader(entry->request_buffer);
	status_t status = bufferHeader.Status();
	if (status < B_OK) {
		entry->ScheduleRemoval();
		return status;
	}

	// prepare ARP header

	net_device *device = protocol->interface->device;
	arp_header &header = bufferHeader.Data();

	header.hardware_type = htons(ARP_HARDWARE_TYPE_ETHER);
	header.protocol_type = htons(ETHER_TYPE_IP);
	header.hardware_length = ETHER_ADDRESS_LENGTH;
	header.protocol_length = sizeof(in_addr_t);
	header.opcode = htons(ARP_OPCODE_REQUEST);

	memcpy(header.hardware_sender, device->address.data, ETHER_ADDRESS_LENGTH);
	if (protocol->interface->address != NULL) {
		header.protocol_sender
			= ((sockaddr_in *)protocol->interface->address)->sin_addr.s_addr;
	} else {
		header.protocol_sender = 0;
			// TODO: test if this actually works - maybe we should use
			// INADDR_BROADCAST instead
	}

	memset(header.hardware_target, 0, ETHER_ADDRESS_LENGTH);
	header.protocol_target = address;

	// prepare source and target addresses

	struct sockaddr_dl &source = *(struct sockaddr_dl *)
		entry->request_buffer->source;
	source.sdl_len = sizeof(sockaddr_dl);
	source.sdl_family = AF_LINK;
	source.sdl_index = device->index;
	source.sdl_type = IFT_ETHER;
	source.sdl_e_type = ETHER_TYPE_ARP;
	source.sdl_nlen = source.sdl_slen = 0;
	source.sdl_alen = ETHER_ADDRESS_LENGTH;
	memcpy(source.sdl_data, device->address.data, ETHER_ADDRESS_LENGTH);

	entry->request_buffer->flags = MSG_BCAST;
		// this is a broadcast packet, we don't need to fill in the destination

	entry->protocol = protocol;
	entry->timer_state = ARP_STATE_REQUEST;
	sStackModule->set_timer(&entry->timer, 0);
		// start request timer

	*_entry = entry;
	return B_OK;
}