/*! 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); }
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; }
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; }
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; }
/*! 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; }
/*! 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; }
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; }
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; }
/*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; }
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; }
/*! 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; }