usbd_status usb_allocmem(usbd_bus_handle bus, size_t size, size_t align, usb_dma_t *p) { bus_dma_tag_t tag = bus->dmatag; usbd_status err; struct usb_frag_dma *f; usb_dma_block_t *b; int i; /* compat w/ Net/OpenBSD */ if (align == 0) align = 1; /* If the request is large then just use a full block. */ if (size > USB_MEM_SMALL || align > USB_MEM_SMALL) { DPRINTFN(1, ("usb_allocmem: large alloc %d\n", (int)size)); size = (size + USB_MEM_BLOCK - 1) & ~(USB_MEM_BLOCK - 1); err = usb_block_allocmem(tag, size, align, &p->block); if (!err) { p->block->fullblock = 1; p->offs = 0; p->len = size; logmemory(alloc_full, p, NULL, size, align); } return (err); } crit_enter(); /* Check for free fragments. */ for (f = LIST_FIRST(&usb_frag_freelist); f; f = LIST_NEXT(f, next)) if (f->block->tag == tag) break; if (f == NULL) { DPRINTFN(1, ("usb_allocmem: adding fragments\n")); err = usb_block_allocmem(tag, USB_MEM_BLOCK, USB_MEM_SMALL,&b); if (err) { crit_exit(); return (err); } b->fullblock = 0; /* XXX - override the tag, ok since we never free it */ b->tag = tag; KASSERT(sizeof *f <= USB_MEM_SMALL, ("USB_MEM_SMALL(%d) is too small for struct usb_frag_dma(%zd)", USB_MEM_SMALL, sizeof *f)); for (i = 0; i < USB_MEM_BLOCK; i += USB_MEM_SMALL) { f = (struct usb_frag_dma *)((char *)b->kaddr + i); f->block = b; f->offs = i; LIST_INSERT_HEAD(&usb_frag_freelist, f, next); } f = LIST_FIRST(&usb_frag_freelist); } p->block = f->block; p->offs = f->offs; p->len = USB_MEM_SMALL; LIST_REMOVE(f, next); crit_exit(); logmemory(alloc_frag, p, NULL, size, align); DPRINTFN(5, ("usb_allocmem: use frag=%p size=%d\n", f, (int)size)); return (USBD_NORMAL_COMPLETION); }
/* process HTTP or SSDP requests */ int main(int argc, char * * argv) { int i; int shttpl = -1; /* socket for HTTP */ int sudp = -1; /* IP v4 socket for receiving SSDP */ #ifdef ENABLE_IPV6 int sudpv6 = -1; /* IP v6 socket for receiving SSDP */ #endif #ifdef ENABLE_NATPMP int * snatpmp = NULL; #endif #ifdef ENABLE_NFQUEUE int nfqh = -1; #endif #ifdef USE_IFACEWATCHER int sifacewatcher = -1; #endif int * snotify = NULL; int addr_count; LIST_HEAD(httplisthead, upnphttp) upnphttphead; struct upnphttp * e = 0; struct upnphttp * next; fd_set readset; /* for select() */ fd_set writeset; struct timeval timeout, timeofday, lasttimeofday = {0, 0}; int max_fd = -1; #ifdef USE_MINIUPNPDCTL int sctl = -1; LIST_HEAD(ctlstructhead, ctlelem) ctllisthead; struct ctlelem * ectl; struct ctlelem * ectlnext; #endif struct runtime_vars v; /* variables used for the unused-rule cleanup process */ struct rule_state * rule_list = 0; struct timeval checktime = {0, 0}; struct lan_addr_s * lan_addr; #ifdef ENABLE_6FC_SERVICE unsigned int next_pinhole_ts; #endif if(init(argc, argv, &v) != 0) return 1; /* count lan addrs */ addr_count = 0; for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next) addr_count++; if(addr_count > 0) { #ifndef ENABLE_IPV6 snotify = calloc(addr_count, sizeof(int)); #else /* one for IPv4, one for IPv6 */ snotify = calloc(addr_count * 2, sizeof(int)); #endif } #ifdef ENABLE_NATPMP if(addr_count > 0) { snatpmp = malloc(addr_count * sizeof(int)); for(i = 0; i < addr_count; i++) snatpmp[i] = -1; } #endif LIST_INIT(&upnphttphead); #ifdef USE_MINIUPNPDCTL LIST_INIT(&ctllisthead); #endif if( #ifdef ENABLE_NATPMP !GETFLAG(ENABLENATPMPMASK) && #endif !GETFLAG(ENABLEUPNPMASK) ) { syslog(LOG_ERR, "Why did you run me anyway?"); return 0; } syslog(LOG_INFO, "Starting%s%swith external interface %s", #ifdef ENABLE_NATPMP GETFLAG(ENABLENATPMPMASK) ? " NAT-PMP " : " ", #else " ", #endif GETFLAG(ENABLEUPNPMASK) ? "UPnP-IGD " : "", ext_if_name); if(GETFLAG(ENABLEUPNPMASK)) { /* open socket for HTTP connections. Listen on the 1st LAN address */ shttpl = OpenAndConfHTTPSocket((v.port > 0) ? v.port : 0); if(shttpl < 0) { syslog(LOG_ERR, "Failed to open socket for HTTP. EXITING"); return 1; } if(v.port <= 0) { struct sockaddr_in sockinfo; socklen_t len = sizeof(struct sockaddr_in); if (getsockname(shttpl, (struct sockaddr *)&sockinfo, &len) < 0) { syslog(LOG_ERR, "getsockname(): %m"); return 1; } v.port = ntohs(sockinfo.sin_port); } syslog(LOG_NOTICE, "HTTP listening on port %d", v.port); #ifdef ENABLE_IPV6 if(find_ipv6_addr(NULL, ipv6_addr_for_http_with_brackets, sizeof(ipv6_addr_for_http_with_brackets)) > 0) { syslog(LOG_NOTICE, "HTTP IPv6 address given to control points : %s", ipv6_addr_for_http_with_brackets); } else { memcpy(ipv6_addr_for_http_with_brackets, "[::1]", 6); syslog(LOG_WARNING, "no HTTP IPv6 address"); } #endif /* open socket for SSDP connections */ sudp = OpenAndConfSSDPReceiveSocket(0); if(sudp < 0) { syslog(LOG_NOTICE, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd"); if(SubmitServicesToMiniSSDPD(lan_addrs.lh_first->str, v.port) < 0) { syslog(LOG_ERR, "Failed to connect to MiniSSDPd. EXITING"); return 1; } } #ifdef ENABLE_IPV6 sudpv6 = OpenAndConfSSDPReceiveSocket(1); if(sudpv6 < 0) { syslog(LOG_WARNING, "Failed to open socket for receiving SSDP (IP v6)."); } #endif /* open socket for sending notifications */ if(OpenAndConfSSDPNotifySockets(snotify) < 0) { syslog(LOG_ERR, "Failed to open sockets for sending SSDP notify " "messages. EXITING"); return 1; } #ifdef USE_IFACEWATCHER /* open socket for kernel notifications about new network interfaces */ if (sudp >= 0) { sifacewatcher = OpenAndConfInterfaceWatchSocket(); if (sifacewatcher < 0) { syslog(LOG_ERR, "Failed to open socket for receiving network interface notifications"); } } #endif } #ifdef ENABLE_NATPMP /* open socket for NAT PMP traffic */ if(GETFLAG(ENABLENATPMPMASK)) { if(OpenAndConfNATPMPSockets(snatpmp) < 0) { syslog(LOG_ERR, "Failed to open sockets for NAT PMP."); } else { syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u", NATPMP_PORT); } #if 0 ScanNATPMPforExpiration(); #endif } #endif /* for miniupnpdctl */ #ifdef USE_MINIUPNPDCTL sctl = OpenAndConfCtlUnixSocket("/var/run/miniupnpd.ctl"); #endif #ifdef ENABLE_NFQUEUE if ( nfqueue != -1 && n_nfqix > 0) { nfqh = OpenAndConfNFqueue(); if(nfqh < 0) { syslog(LOG_ERR, "Failed to open fd for NFQUEUE."); return 1; } else { syslog(LOG_NOTICE, "Opened NFQUEUE %d",nfqueue); } } #endif /* main loop */ while(!quitting) { /* Correct startup_time if it was set with a RTC close to 0 */ if((startup_time<60*60*24) && (time(NULL)>60*60*24)) { set_startup_time(GETFLAG(SYSUPTIMEMASK)); } /* send public address change notifications if needed */ if(should_send_public_address_change_notif) { syslog(LOG_DEBUG, "should send external iface address change notification(s)"); #ifdef ENABLE_NATPMP if(GETFLAG(ENABLENATPMPMASK)) SendNATPMPPublicAddressChangeNotification(snatpmp, addr_count); #endif #ifdef ENABLE_EVENTS if(GETFLAG(ENABLEUPNPMASK)) { upnp_event_var_change_notify(EWanIPC); } #endif should_send_public_address_change_notif = 0; } /* Check if we need to send SSDP NOTIFY messages and do it if * needed */ if(gettimeofday(&timeofday, 0) < 0) { syslog(LOG_ERR, "gettimeofday(): %m"); timeout.tv_sec = v.notify_interval; timeout.tv_usec = 0; } else { /* the comparaison is not very precise but who cares ? */ if(timeofday.tv_sec >= (lasttimeofday.tv_sec + v.notify_interval)) { if (GETFLAG(ENABLEUPNPMASK)) SendSSDPNotifies2(snotify, (unsigned short)v.port, v.notify_interval << 1); memcpy(&lasttimeofday, &timeofday, sizeof(struct timeval)); timeout.tv_sec = v.notify_interval; timeout.tv_usec = 0; } else { timeout.tv_sec = lasttimeofday.tv_sec + v.notify_interval - timeofday.tv_sec; if(timeofday.tv_usec > lasttimeofday.tv_usec) { timeout.tv_usec = 1000000 + lasttimeofday.tv_usec - timeofday.tv_usec; timeout.tv_sec--; } else { timeout.tv_usec = lasttimeofday.tv_usec - timeofday.tv_usec; } } } /* remove unused rules */ if( v.clean_ruleset_interval && (timeofday.tv_sec >= checktime.tv_sec + v.clean_ruleset_interval)) { if(rule_list) { remove_unused_rules(rule_list); rule_list = NULL; } else { rule_list = get_upnp_rules_state_list(v.clean_ruleset_threshold); } memcpy(&checktime, &timeofday, sizeof(struct timeval)); } /* Remove expired port mappings, based on UPnP IGD LeaseDuration * or NAT-PMP lifetime) */ if(nextruletoclean_timestamp && ((unsigned int)timeofday.tv_sec >= nextruletoclean_timestamp)) { syslog(LOG_DEBUG, "cleaning expired Port Mappings"); get_upnp_rules_state_list(0); } if(nextruletoclean_timestamp && ((unsigned int)timeout.tv_sec >= (nextruletoclean_timestamp - timeofday.tv_sec))) { timeout.tv_sec = nextruletoclean_timestamp - timeofday.tv_sec; timeout.tv_usec = 0; syslog(LOG_DEBUG, "setting timeout to %u sec", (unsigned)timeout.tv_sec); } #ifdef ENABLE_NATPMP #if 0 /* Remove expired NAT-PMP mappings */ while(nextnatpmptoclean_timestamp && (timeofday.tv_sec >= nextnatpmptoclean_timestamp + startup_time)) { /*syslog(LOG_DEBUG, "cleaning expired NAT-PMP mappings");*/ if(CleanExpiredNATPMP() < 0) { syslog(LOG_ERR, "CleanExpiredNATPMP() failed"); break; } } if(nextnatpmptoclean_timestamp && timeout.tv_sec >= (nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec)) { /*syslog(LOG_DEBUG, "setting timeout to %d sec", nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec);*/ timeout.tv_sec = nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec; timeout.tv_usec = 0; } #endif #endif #ifdef ENABLE_6FC_SERVICE /* Clean up expired IPv6 PinHoles */ next_pinhole_ts = 0; upnp_clean_expired_pinholes(&next_pinhole_ts); if(next_pinhole_ts && timeout.tv_sec >= (int)(next_pinhole_ts - timeofday.tv_sec)) { timeout.tv_sec = next_pinhole_ts - timeofday.tv_sec; timeout.tv_usec = 0; } #endif /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */ FD_ZERO(&readset); FD_ZERO(&writeset); if (sudp >= 0) { FD_SET(sudp, &readset); max_fd = MAX( max_fd, sudp); #ifdef USE_IFACEWATCHER if (sifacewatcher >= 0) { FD_SET(sifacewatcher, &readset); max_fd = MAX(max_fd, sifacewatcher); } #endif } if (shttpl >= 0) { FD_SET(shttpl, &readset); max_fd = MAX( max_fd, shttpl); } #ifdef ENABLE_IPV6 if (sudpv6 >= 0) { FD_SET(sudpv6, &readset); max_fd = MAX( max_fd, sudpv6); } #endif #ifdef ENABLE_NFQUEUE if (nfqh >= 0) { FD_SET(nfqh, &readset); max_fd = MAX( max_fd, nfqh); } #endif i = 0; /* active HTTP connections count */ for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next) { if(e->socket >= 0) { if(e->state <= EWaitingForHttpContent) FD_SET(e->socket, &readset); else if(e->state == ESendingAndClosing) FD_SET(e->socket, &writeset); else continue; max_fd = MAX(max_fd, e->socket); i++; } } /* for debug */ #ifdef DEBUG if(i > 1) { syslog(LOG_DEBUG, "%d active incoming HTTP connections", i); } #endif #ifdef ENABLE_NATPMP for(i=0; i<addr_count; i++) { if(snatpmp[i] >= 0) { FD_SET(snatpmp[i], &readset); max_fd = MAX( max_fd, snatpmp[i]); } } #endif #ifdef USE_MINIUPNPDCTL if(sctl >= 0) { FD_SET(sctl, &readset); max_fd = MAX( max_fd, sctl); } for(ectl = ctllisthead.lh_first; ectl; ectl = ectl->entries.le_next) { if(ectl->socket >= 0) { FD_SET(ectl->socket, &readset); max_fd = MAX( max_fd, ectl->socket); } } #endif #ifdef ENABLE_EVENTS upnpevents_selectfds(&readset, &writeset, &max_fd); #endif if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0) { if(quitting) goto shutdown; if(errno == EINTR) continue; /* interrupted by a signal, start again */ syslog(LOG_ERR, "select(all): %m"); syslog(LOG_ERR, "Failed to select open sockets. EXITING"); return 1; /* very serious cause of error */ } #ifdef USE_MINIUPNPDCTL for(ectl = ctllisthead.lh_first; ectl;) { ectlnext = ectl->entries.le_next; if((ectl->socket >= 0) && FD_ISSET(ectl->socket, &readset)) { char buf[256]; int l; l = read(ectl->socket, buf, sizeof(buf)); if(l > 0) { /*write(ectl->socket, buf, l);*/ write_command_line(ectl->socket, argc, argv); write_option_list(ectl->socket); write_permlist(ectl->socket, upnppermlist, num_upnpperm); write_upnphttp_details(ectl->socket, upnphttphead.lh_first); write_ctlsockets_list(ectl->socket, ctllisthead.lh_first); write_ruleset_details(ectl->socket); #ifdef ENABLE_EVENTS write_events_details(ectl->socket); #endif /* close the socket */ close(ectl->socket); ectl->socket = -1; } else { close(ectl->socket); ectl->socket = -1; } } if(ectl->socket < 0) { LIST_REMOVE(ectl, entries); free(ectl); } ectl = ectlnext; } if((sctl >= 0) && FD_ISSET(sctl, &readset)) { int s; struct sockaddr_un clientname; struct ctlelem * tmp; socklen_t clientnamelen = sizeof(struct sockaddr_un); //syslog(LOG_DEBUG, "sctl!"); s = accept(sctl, (struct sockaddr *)&clientname, &clientnamelen); syslog(LOG_DEBUG, "sctl! : '%s'", clientname.sun_path); tmp = malloc(sizeof(struct ctlelem)); tmp->socket = s; LIST_INSERT_HEAD(&ctllisthead, tmp, entries); } #endif #ifdef ENABLE_EVENTS upnpevents_processfds(&readset, &writeset); #endif #ifdef ENABLE_NATPMP /* process NAT-PMP packets */ for(i=0; i<addr_count; i++) { if((snatpmp[i] >= 0) && FD_ISSET(snatpmp[i], &readset)) { ProcessIncomingNATPMPPacket(snatpmp[i]); } } #endif /* process SSDP packets */ if(sudp >= 0 && FD_ISSET(sudp, &readset)) { /*syslog(LOG_INFO, "Received UDP Packet");*/ ProcessSSDPRequest(sudp, (unsigned short)v.port); } #ifdef ENABLE_IPV6 if(sudpv6 >= 0 && FD_ISSET(sudpv6, &readset)) { syslog(LOG_INFO, "Received UDP Packet (IPv6)"); ProcessSSDPRequest(sudpv6, (unsigned short)v.port); } #endif #ifdef USE_IFACEWATCHER /* process kernel notifications */ if (sifacewatcher >= 0 && FD_ISSET(sifacewatcher, &readset)) ProcessInterfaceWatchNotify(sifacewatcher); #endif /* process active HTTP connections */ /* LIST_FOREACH macro is not available under linux */ for(e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next) { if(e->socket >= 0) { if(FD_ISSET(e->socket, &readset) || FD_ISSET(e->socket, &writeset)) { Process_upnphttp(e); } } } /* process incoming HTTP connections */ if(shttpl >= 0 && FD_ISSET(shttpl, &readset)) { int shttp; socklen_t clientnamelen; #ifdef ENABLE_IPV6 struct sockaddr_storage clientname; clientnamelen = sizeof(struct sockaddr_storage); #else struct sockaddr_in clientname; clientnamelen = sizeof(struct sockaddr_in); #endif shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen); if(shttp<0) { /* ignore EAGAIN, EWOULDBLOCK, EINTR, we just try again later */ if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) syslog(LOG_ERR, "accept(http): %m"); } else { struct upnphttp * tmp = 0; char addr_str[64]; sockaddr_to_string((struct sockaddr *)&clientname, addr_str, sizeof(addr_str)); syslog(LOG_INFO, "HTTP connection from %s", addr_str); /* Create a new upnphttp object and add it to * the active upnphttp object list */ tmp = New_upnphttp(shttp); if(tmp) { #ifdef ENABLE_IPV6 if(clientname.ss_family == AF_INET) { tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr; } else if(clientname.ss_family == AF_INET6) { struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&clientname; if(IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) { memcpy(&tmp->clientaddr, &addr->sin6_addr.s6_addr[12], 4); } else { tmp->ipv6 = 1; memcpy(&tmp->clientaddr_v6, &addr->sin6_addr, sizeof(struct in6_addr)); } } #else tmp->clientaddr = clientname.sin_addr; #endif LIST_INSERT_HEAD(&upnphttphead, tmp, entries); } else { syslog(LOG_ERR, "New_upnphttp() failed"); close(shttp); } } } #ifdef ENABLE_NFQUEUE /* process NFQ packets */ if(nfqh >= 0 && FD_ISSET(nfqh, &readset)) { /* syslog(LOG_INFO, "Received NFQUEUE Packet");*/ ProcessNFQUEUE(nfqh); } #endif /* delete finished HTTP connections */ for(e = upnphttphead.lh_first; e != NULL; ) { next = e->entries.le_next; if(e->state >= EToDelete) { LIST_REMOVE(e, entries); Delete_upnphttp(e); } e = next; } } /* end of main loop */ shutdown: /* close out open sockets */ while(upnphttphead.lh_first != NULL) { e = upnphttphead.lh_first; LIST_REMOVE(e, entries); Delete_upnphttp(e); } if (sudp >= 0) close(sudp); if (shttpl >= 0) close(shttpl); #ifdef ENABLE_IPV6 if (sudpv6 >= 0) close(sudpv6); #endif #ifdef USE_IFACEWATCHER if(sifacewatcher >= 0) close(sifacewatcher); #endif #ifdef ENABLE_NATPMP for(i=0; i<addr_count; i++) { if(snatpmp[i]>=0) { close(snatpmp[i]); snatpmp[i] = -1; } } #endif #ifdef USE_MINIUPNPDCTL if(sctl>=0) { close(sctl); sctl = -1; if(unlink("/var/run/miniupnpd.ctl") < 0) { syslog(LOG_ERR, "unlink() %m"); } } #endif if (GETFLAG(ENABLEUPNPMASK)) { #ifndef ENABLE_IPV6 if(SendSSDPGoodbye(snotify, addr_count) < 0) #else if(SendSSDPGoodbye(snotify, addr_count * 2) < 0) #endif { syslog(LOG_ERR, "Failed to broadcast good-bye notifications"); } #ifndef ENABLE_IPV6 for(i = 0; i < addr_count; i++) #else for(i = 0; i < addr_count * 2; i++) #endif close(snotify[i]); } if(pidfilename && (unlink(pidfilename) < 0)) { syslog(LOG_ERR, "Failed to remove pidfile %s: %m", pidfilename); } /* delete lists */ while(lan_addrs.lh_first != NULL) { lan_addr = lan_addrs.lh_first; LIST_REMOVE(lan_addrs.lh_first, list); free(lan_addr); } #ifdef ENABLE_NATPMP free(snatpmp); #endif free(snotify); closelog(); #ifndef DISABLE_CONFIG_FILE freeoptions(); #endif return 0; }
static usbd_status usb_block_allocmem(bus_dma_tag_t tag, size_t size, size_t align, usb_dma_block_t **dmap) { usb_dma_block_t *p; DPRINTFN(5, ("usb_block_allocmem: size=%lu align=%lu\n", (u_long)size, (u_long)align)); crit_enter(); /* First check the free list. */ for (p = LIST_FIRST(&usb_blk_freelist); p; p = LIST_NEXT(p, next)) { if (p->tag == tag && p->size >= size && p->align >= align) { LIST_REMOVE(p, next); usb_blk_nfree--; crit_exit(); *dmap = p; DPRINTFN(6,("usb_block_allocmem: free list size=%lu\n", (u_long)p->size)); logmemory(blkalloc2, p, NULL, size, align); return (USBD_NORMAL_COMPLETION); } } crit_exit(); DPRINTFN(6, ("usb_block_allocmem: no free\n")); p = kmalloc(sizeof *p, M_USB, M_INTWAIT); logmemory(blkalloc, p, NULL, size, align); if (bus_dma_tag_create(tag, align, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, size, NELEM(p->segs), size, BUS_DMA_ALLOCNOW, &p->tag) == ENOMEM) { goto free; } p->size = size; p->align = align; if (bus_dmamem_alloc(p->tag, &p->kaddr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT, &p->map)) goto tagfree; if (bus_dmamap_load(p->tag, p->map, p->kaddr, p->size, usbmem_callback, p, 0)) goto memfree; /* XXX - override the tag, ok since we never free it */ p->tag = tag; *dmap = p; return (USBD_NORMAL_COMPLETION); /* * XXX - do we need to _unload? is the order of _free and _destroy * correct? */ memfree: bus_dmamem_free(p->tag, p->kaddr, p->map); tagfree: bus_dma_tag_destroy(p->tag); free: kfree(p, M_USB); return (USBD_NOMEM); }
static void dview_free(DView *dv) { LIST_REMOVE(list, dv, DView); global_free(dv); }
/* * Parallel to llc_rtrequest. */ static void arp_rtrequest( int req, struct rtentry *rt, __unused struct sockaddr *sa) { struct sockaddr *gate = rt->rt_gateway; struct llinfo_arp *la = rt->rt_llinfo; static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK, 0, 0, 0, 0, 0, {0}}; struct timeval timenow; if (!arpinit_done) { panic("%s: ARP has not been initialized", __func__); /* NOTREACHED */ } lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED); RT_LOCK_ASSERT_HELD(rt); if (rt->rt_flags & RTF_GATEWAY) return; getmicrotime(&timenow); switch (req) { case RTM_ADD: /* * XXX: If this is a manually added route to interface * such as older version of routed or gated might provide, * restore cloning bit. */ if ((rt->rt_flags & RTF_HOST) == 0 && SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff) rt->rt_flags |= RTF_CLONING; if (rt->rt_flags & RTF_CLONING) { /* * Case 1: This route should come from a route to iface. */ if (rt_setgate(rt, rt_key(rt), (struct sockaddr *)&null_sdl) == 0) { gate = rt->rt_gateway; SDL(gate)->sdl_type = rt->rt_ifp->if_type; SDL(gate)->sdl_index = rt->rt_ifp->if_index; /* * In case we're called before 1.0 sec. * has elapsed. */ rt->rt_expire = MAX(timenow.tv_sec, 1); } break; } /* Announce a new entry if requested. */ if (rt->rt_flags & RTF_ANNOUNCE) { RT_UNLOCK(rt); dlil_send_arp(rt->rt_ifp, ARPOP_REQUEST, SDL(gate), rt_key(rt), NULL, rt_key(rt)); RT_LOCK(rt); } /*FALLTHROUGH*/ case RTM_RESOLVE: if (gate->sa_family != AF_LINK || gate->sa_len < sizeof(null_sdl)) { if (log_arp_warnings) log(LOG_DEBUG, "arp_rtrequest: bad gateway value\n"); break; } SDL(gate)->sdl_type = rt->rt_ifp->if_type; SDL(gate)->sdl_index = rt->rt_ifp->if_index; if (la != 0) break; /* This happens on a route change */ /* * Case 2: This route may come from cloning, or a manual route * add with a LL address. */ rt->rt_llinfo = la = arp_llinfo_alloc(); if (la == NULL) { if (log_arp_warnings) log(LOG_DEBUG, "%s: malloc failed\n", __func__); break; } rt->rt_llinfo_free = arp_llinfo_free; arp_inuse++, arp_allocated++; Bzero(la, sizeof(*la)); la->la_rt = rt; rt->rt_flags |= RTF_LLINFO; LIST_INSERT_HEAD(&llinfo_arp, la, la_le); /* * This keeps the multicast addresses from showing up * in `arp -a' listings as unresolved. It's not actually * functional. Then the same for broadcast. */ if (IN_MULTICAST(ntohl(SIN(rt_key(rt))->sin_addr.s_addr))) { RT_UNLOCK(rt); dlil_resolve_multi(rt->rt_ifp, rt_key(rt), gate, sizeof(struct sockaddr_dl)); RT_LOCK(rt); rt->rt_expire = 0; } else if (in_broadcast(SIN(rt_key(rt))->sin_addr, rt->rt_ifp)) { struct sockaddr_dl *gate_ll = SDL(gate); size_t broadcast_len; ifnet_llbroadcast_copy_bytes(rt->rt_ifp, LLADDR(gate_ll), sizeof(gate_ll->sdl_data), &broadcast_len); gate_ll->sdl_alen = broadcast_len; gate_ll->sdl_family = AF_LINK; gate_ll->sdl_len = sizeof(struct sockaddr_dl); /* In case we're called before 1.0 sec. has elapsed */ rt->rt_expire = MAX(timenow.tv_sec, 1); } if (SIN(rt_key(rt))->sin_addr.s_addr == (IA_SIN(rt->rt_ifa))->sin_addr.s_addr) { /* * This test used to be * if (loif.if_flags & IFF_UP) * It allowed local traffic to be forced * through the hardware by configuring the loopback down. * However, it causes problems during network configuration * for boards that can't receive packets they send. * It is now necessary to clear "useloopback" and remove * the route to force traffic out to the hardware. */ rt->rt_expire = 0; ifnet_lladdr_copy_bytes(rt->rt_ifp, LLADDR(SDL(gate)), SDL(gate)->sdl_alen = 6); if (useloopback) { #if IFNET_ROUTE_REFCNT /* Adjust route ref count for the interfaces */ if (rt->rt_if_ref_fn != NULL && rt->rt_ifp != lo_ifp) { rt->rt_if_ref_fn(lo_ifp, 1); rt->rt_if_ref_fn(rt->rt_ifp, -1); } #endif /* IFNET_ROUTE_REFCNT */ rt->rt_ifp = lo_ifp; } } break; case RTM_DELETE: if (la == 0) break; arp_inuse--; /* * Unchain it but defer the actual freeing until the route * itself is to be freed. rt->rt_llinfo still points to * llinfo_arp, and likewise, la->la_rt still points to this * route entry, except that RTF_LLINFO is now cleared. */ LIST_REMOVE(la, la_le); la->la_le.le_next = NULL; la->la_le.le_prev = NULL; rt->rt_flags &= ~RTF_LLINFO; if (la->la_hold != NULL) m_freem(la->la_hold); la->la_hold = NULL; } }
/* * Give our OK for a hook to be added. The hook name is of the * form "<family>/<type>/<proto>" where the three components may * be decimal numbers or else aliases from the above lists. * * Connecting a hook amounts to opening the socket. Disconnecting * the hook closes the socket and destroys the node as well. */ static int ng_ksocket_newhook(node_p node, hook_p hook, const char *name0) { struct thread *td = curthread; /* XXX broken */ const priv_p priv = NG_NODE_PRIVATE(node); char *s1, *s2, name[NG_HOOKSIZ]; int family, type, protocol, error; /* Check if we're already connected */ if (priv->hook != NULL) return (EISCONN); if (priv->flags & KSF_CLONED) { if (priv->flags & KSF_EMBRYONIC) { /* Remove ourselves from our parent's embryo list */ LIST_REMOVE(priv, siblings); priv->flags &= ~KSF_EMBRYONIC; } } else { /* Extract family, type, and protocol from hook name */ snprintf(name, sizeof(name), "%s", name0); s1 = name; if ((s2 = strchr(s1, '/')) == NULL) return (EINVAL); *s2++ = '\0'; family = ng_ksocket_parse(ng_ksocket_families, s1, 0); if (family == -1) return (EINVAL); s1 = s2; if ((s2 = strchr(s1, '/')) == NULL) return (EINVAL); *s2++ = '\0'; type = ng_ksocket_parse(ng_ksocket_types, s1, 0); if (type == -1) return (EINVAL); s1 = s2; protocol = ng_ksocket_parse(ng_ksocket_protos, s1, family); if (protocol == -1) return (EINVAL); /* Create the socket */ error = socreate(family, &priv->so, type, protocol, td->td_ucred, td); if (error != 0) return (error); /* XXX call soreserve() ? */ } /* OK */ priv->hook = hook; /* * In case of misconfigured routing a packet may reenter * ksocket node recursively. Decouple stack to avoid possible * panics about sleeping with locks held. */ NG_HOOK_FORCE_QUEUE(hook); return(0); }
int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item) { LIST_REMOVE(item, head); return 0; }
static void mainloop(void) { gtimer_t *gti; gti_callback_t *cb; struct timespec ts; while(tvheadend_running) { clock_gettime(CLOCK_REALTIME, &ts); /* 1sec stuff */ if (ts.tv_sec > dispatch_clock) { dispatch_clock = ts.tv_sec; spawn_reaper(); /* reap spawned processes */ comet_flush(); /* Flush idle comet mailboxes */ } /* Global timers */ pthread_mutex_lock(&global_lock); // TODO: there is a risk that if timers re-insert themselves to // the top of the list with a 0 offset we could loop indefinitely #if 0 tvhdebug("gtimer", "now %ld.%09ld", ts.tv_sec, ts.tv_nsec); LIST_FOREACH(gti, >imers, gti_link) tvhdebug("gtimer", " gti %p expire %ld.%08ld", gti, gti->gti_expire.tv_sec, gti->gti_expire.tv_nsec); #endif while((gti = LIST_FIRST(>imers)) != NULL) { if ((gti->gti_expire.tv_sec > ts.tv_sec) || ((gti->gti_expire.tv_sec == ts.tv_sec) && (gti->gti_expire.tv_nsec > ts.tv_nsec))) { ts = gti->gti_expire; break; } cb = gti->gti_callback; //tvhdebug("gtimer", "%p callback", gti); LIST_REMOVE(gti, gti_link); gti->gti_callback = NULL; cb(gti->gti_opaque); } /* Bound wait */ if ((LIST_FIRST(>imers) == NULL) || (ts.tv_sec > (dispatch_clock + 1))) { ts.tv_sec = dispatch_clock + 1; ts.tv_nsec = 0; } /* Wait */ //tvhdebug("gtimer", "wait till %ld.%09ld", ts.tv_sec, ts.tv_nsec); pthread_cond_timedwait(>imer_cond, &global_lock, &ts); pthread_mutex_unlock(&global_lock); } }