/* * Manually shut down a context. This allows the caller to force destruction * of all connections and state associated with the context. */ void robin_shutdown_context(robin_context context) { struct robin_state *s, *s_n; robin_context dummy = context; robin_con con, con_n; int last = 0; if (context->refcount == 1) last = 1; /* uncount the user's context handle, then abort states */ ROBIN_DEL_CONTEXT(dummy, context); /* context was just freed */ if (last) return; /* shutdown all the connections, before touching the context */ for (con = TAILQ_FIRST(&context->con.list); con != TAILQ_END(&context->con.list); con = con_n) { con_n = TAILQ_NEXT(con, entry); robin_shutdown_con(context, con); } /* abort all state entries still held */ for (s = TAILQ_FIRST(&context->state); s != TAILQ_END(&context->state); s = s_n) { s_n = TAILQ_NEXT(s, entry); robin_state_abort(s, ROBIN_DISCONNECTED); } }
int tl_event_node_insert(struct tl_event_node * node) { struct tl_event_node * insertPos; tl_manage_t tm; assert(node); assert(node->m_event.m_tl); assert(node->m_event.m_tl->m_manage); tm = node->m_event.m_tl->m_manage; insertPos = TAILQ_FIRST(&tm->m_event_queue); while(insertPos != TAILQ_END(&tm->m_event_queue) && insertPos->m_execute_time <= node->m_execute_time) { insertPos = TAILQ_NEXT(insertPos, m_next); } if (insertPos == TAILQ_END(&tm->m_event_queue)) { TAILQ_INSERT_TAIL(&tm->m_event_queue, node, m_next); } else { TAILQ_INSERT_BEFORE(insertPos, node, m_next); } node->m_state = tl_event_node_state_in_event_queue; return 0; }
/* * Free the robin_con structure. This does NOT free/shutdown the pigeon * control structure. robin_do_shutdown() should be used to safely shutdown * and free without looping. * * XXX USERS SHOULD NEVER CALL THIS FUNCTION DIRECTLY XXX */ void robin_free_con(robin_context context, robin_con con) { robin_con p; struct robin_state *s, *s_n; /* Make sure the con is in this context's list */ TAILQ_FOREACH(p, &context->con.list, entry) if (p == con) break; if (p == TAILQ_END(&context->con.list)) return; /* set a destruction pointer to prevent looping */ if (con->destroying) return; else con->destroying = 1; if (robin_verbose & ROBIN_LOG_CONNECT) log_debug("==] CON %p free", con); /* take out of the connection list early */ TAILQ_REMOVE(&context->con.list, con, entry); /* unset the 'master' connection */ if (con->context->con.master == con) con->context->con.master = NULL; /* abort STATE_CONN entries that match this connection */ for (s = TAILQ_FIRST(&context->state); s != TAILQ_END(&context->state); s = s_n) { s_n = TAILQ_NEXT(s, entry); if (s->con == con) { /* unreference the connection always */ s->con = NULL; /* remove the state sometimes */ if ((s->state & STATE_CONN)) robin_state_abort(s, ROBIN_DISCONNECTED); else robin_state_resend(s); } } dns_abort_byarg(con); ROBIN_DEL_CONTEXT(con->context, context); free_RobinHosts(&con->connect.hosts); evtimer_del(&con->connect.timer); free(con); }
/** * drm_vblank_off - disable vblank events on a CRTC * @dev: DRM device * @crtc: CRTC in question * * Caller must hold event lock. */ void drm_vblank_off(struct drm_device *dev, int crtc) { struct drmevlist *list; struct drm_pending_event *ev, *tmp; struct drm_pending_vblank_event *vev; struct timeval now; unsigned int seq; mtx_enter(&dev->vbl_lock); vblank_disable_and_save(dev, crtc); wakeup(&dev->vbl_queue[crtc]); list = &dev->vbl_events; /* Send any queued vblank events, lest the natives grow disquiet */ seq = drm_vblank_count_and_time(dev, crtc, &now); mtx_enter(&dev->event_lock); for (ev = TAILQ_FIRST(list); ev != TAILQ_END(list); ev = tmp) { tmp = TAILQ_NEXT(ev, link); vev = (struct drm_pending_vblank_event *)ev; if (vev->pipe != crtc) continue; DRM_DEBUG("Sending premature vblank event on disable: \ wanted %d, current %d\n", vev->event.sequence, seq); TAILQ_REMOVE(list, ev, link); drm_vblank_put(dev, vev->pipe); send_vblank_event(dev, vev, seq, &now); } mtx_leave(&dev->event_lock); mtx_leave(&dev->vbl_lock); }
void drm_handle_vblank_events(struct drm_device *dev, int crtc) { struct drmevlist *list; struct drm_pending_event *ev, *tmp; struct drm_pending_vblank_event *vev; struct timeval now; u_int seq; list = &dev->vblank->vb_crtcs[crtc].vbl_events; microtime(&now); seq = drm_vblank_count(dev, crtc); mtx_enter(&dev->event_lock); for (ev = TAILQ_FIRST(list); ev != TAILQ_END(list); ev = tmp) { tmp = TAILQ_NEXT(ev, link); vev = (struct drm_pending_vblank_event *)ev; if ((seq - vev->event.sequence) > (1 << 23)) continue; DPRINTF("%s: got vblank event on crtc %d, value %d\n", __func__, crtc, seq); vev->event.sequence = seq; vev->event.tv_sec = now.tv_sec; vev->event.tv_usec = now.tv_usec; drm_vblank_put(dev, crtc); TAILQ_REMOVE(list, ev, link); TAILQ_INSERT_TAIL(&ev->file_priv->evlist, ev, link); wakeup(&ev->file_priv->evlist); selwakeup(&ev->file_priv->rsel); } mtx_leave(&dev->event_lock); }
void mem_buffer_end(struct mem_buffer_pos * pos, struct mem_buffer * buffer) { assert(pos); assert(buffer); pos->m_buffer = buffer; pos->m_trunk = TAILQ_END(&buffer->m_trunks); pos->m_pos_in_trunk = 0; }
void robin_free_context(robin_context context) { struct robin_state *s, *s_n; robin_con con, con_n; /* manual decrement, this should be the last one */ context->refcount--; if (context->refcount > 0) { log_debug("context has %u operations in progress", context->refcount); return; } /* abort all state entries still held */ for (s = TAILQ_FIRST(&context->state); s != TAILQ_END(&context->state); s = s_n) { s_n = TAILQ_NEXT(s, entry); robin_state_abort(s, ROBIN_DISCONNECTED); } /* shutdown all the connections, before touching the context */ for (con = TAILQ_FIRST(&context->con.list); con != TAILQ_END(&context->con.list); con = con_n) { con_n = TAILQ_NEXT(con, entry); robin_shutdown_con(context, con); } tb_free_error_table(context->et_list); /* free cell (containing hosts) after connections shut down */ free_RobinCell(&context->cell); if (context->con.username) free(context->con.username); if (context->con.servname) free(context->con.servname); if (context->con.ccache) free(context->con.ccache); free(context); }
static void send_pktq(struct pktq *pktq) { struct pkt *pkt, *next; for (pkt = TAILQ_FIRST(pktq); pkt != TAILQ_END(pktq); pkt = next) { next = TAILQ_NEXT(pkt, pkt_next); TAILQ_REMOVE(pktq, pkt, pkt_next); send_pkt(pkt); } }
void mem_buffer_begin(struct mem_buffer_pos * pos, struct mem_buffer * buffer) { assert(pos); assert(buffer); pos->m_buffer = buffer; pos->m_pos_in_trunk = 0; pos->m_trunk = TAILQ_FIRST(&buffer->m_trunks); while(pos->m_trunk != TAILQ_END(&buffer->m_trunks) && pos->m_trunk->m_size <= 0) { pos->m_trunk = TAILQ_NEXT(pos->m_trunk, m_next); } }
/* * add a packet to a stream */ int stream_add(struct stream_object *so, struct log_header_packet *pck, char *buf) { struct so_list *pl, *tmp; /* skip ack packet or zero lenght packet */ if (pck->len == 0) return 0; /* the packet is good, add it */ SAFE_CALLOC(pl, 1, sizeof(struct so_list)); /* create the packet object */ memcpy(&pl->po.L3.src, &pck->L3_src, sizeof(struct ip_addr)); memcpy(&pl->po.L3.dst, &pck->L3_dst, sizeof(struct ip_addr)); pl->po.L4.src = pck->L4_src; pl->po.L4.dst = pck->L4_dst; pl->po.L4.proto = pck->L4_proto; SAFE_CALLOC(pl->po.DATA.data, pck->len, sizeof(char)); memcpy(pl->po.DATA.data, buf, pck->len); pl->po.DATA.len = pck->len; /* set the stream direction */ /* this is the first packet in the stream */ if (TAILQ_FIRST(&so->so_head) == TAILQ_END(&so->so_head)) { pl->side = STREAM_SIDE1; /* init the pointer to the first packet */ so->side1.so_curr = pl; so->side2.so_curr = pl; /* check the previous one and set it accordingly */ } else { tmp = TAILQ_LAST(&so->so_head, so_list_head); if (!ip_addr_cmp(&tmp->po.L3.src, &pl->po.L3.src)) /* same direction */ pl->side = tmp->side; else /* change detected */ pl->side = (tmp->side == STREAM_SIDE1) ? STREAM_SIDE2 : STREAM_SIDE1; } /* add to the queue */ TAILQ_INSERT_TAIL(&so->so_head, pl, next); return pck->len; }
static void fragroute_process(const struct pcap_pkthdr *hdr, void *buf, size_t len, void *arg) { struct pktq pktq; struct pkt *pkt, *next; if ((pkt = pkt_new()) == NULL) { warn("pkt_new"); return; } if (ETH_HDR_LEN + len > PKT_BUF_LEN) { warn("dropping oversized packet"); return; } memcpy(pkt->pkt_data + ETH_HDR_LEN, buf, len); pkt->pkt_end = pkt->pkt_data + ETH_HDR_LEN + len; pkt_decorate(pkt); if (pkt->pkt_ip == NULL) { warn("dropping non-IP packet"); return; } eth_pack_hdr(pkt->pkt_eth, ctx.dmac.addr_eth, ctx.smac.addr_eth, ETH_TYPE_IP); pkt->pkt_ip->ip_src = ctx.src.addr_ip; ip_checksum(pkt->pkt_ip, len); /* Forward this packet along as is. */ if(ctx.dfile && eth_send(ctx.eth, pkt->pkt_data, pkt->pkt_end - pkt->pkt_data) < 0) warn("eth_send"); TAILQ_INIT(&pktq); TAILQ_INSERT_TAIL(&pktq, pkt, pkt_next); mod_apply(&pktq); for (pkt = TAILQ_FIRST(&pktq); pkt != TAILQ_END(&pktq); pkt = next) { next = TAILQ_NEXT(pkt, pkt_next); _resend_outgoing(pkt); } }
static int tl_manage_dispatch_event(tl_manage_t tm, int maxCount) { int rv = 0; int count = 0; for(; rv == 0 && maxCount > 0 && tm->m_action_begin_pos == tm->m_action_end_pos; --maxCount) { struct tl_event_node * node = TAILQ_FIRST(&tm->m_event_queue); if (node == TAILQ_END(tm->m_event_queue) || node->m_execute_time > tm->m_time_current) { break; } TAILQ_REMOVE(&tm->m_event_queue, node, m_next); node->m_state = tl_event_node_state_free; tl_event_do_dispatch(&node->m_event, rv); if (node->m_repeatCount > 0) { --node->m_repeatCount; } if (node->m_repeatCount != 0) { node->m_execute_time += node->m_span; if (tl_event_node_insert(node) != 0) { tl_event_node_free(node); } } else { tl_event_node_free(node); } tl_event_queue_clear(&tm->m_event_building_queue); ++count; } return rv == 0 ? count : rv; }
/* * Robin connection shutdown. This is user-safe, and calls the internal robin * callbacks for the pigeon connection, which will internally call * robin_free_con(). If the pigeon has already been freed, or was never init'd */ void robin_shutdown_con(robin_context context, robin_con con) { robin_con p; if (robin_verbose & ROBIN_LOG_CONNECT) log_debug("==] CON %p shutdown", con); /* Make sure the con is in this context's list */ TAILQ_FOREACH(p, &context->con.list, entry) if (p == con) break; if (p == TAILQ_END(&context->con.list)) return; if (con->p) pigeon_shutdown(&con->p); else robin_free_con(context, con); }
int tbsymbol_set(tbsymbol_head *head, const char *name, const char *value, int persist) { tbsymbol *sym; TAILQ_FOREACH(sym, head, entry) if (strcmp(name, sym->name) == 0) break; if (sym != TAILQ_END(head)) { if (sym->persist == 1) return TBOX_EXISTS; else { free(sym->name); free(sym->value); TAILQ_REMOVE(head, sym, entry); free(sym); } } if ((sym = calloc(1, sizeof(*sym))) == NULL) return TBOX_NOMEM; if ((sym->name = strdup(name)) == NULL) { free(sym); return TBOX_NOMEM; } if ((sym->value = strdup(value)) == NULL) { free(sym->name); free(sym); return TBOX_NOMEM; } sym->used = 0; sym->persist = persist; TAILQ_INSERT_TAIL(head, sym, entry); return TBOX_SUCCESS; }
/* * search a pattern into the stream * returns - NULL if not found * - the packet containing the string if found */ struct so_list * stream_search(struct stream_object *so, u_char *buf, size_t buflen, int mode) { u_char *tmpbuf = NULL, *find; size_t offset = 0, len = 0; struct so_list *so_curr = NULL, *first; size_t po_off = 0; /* get the values into temp variable */ switch (mode) { case STREAM_SIDE1: so_curr = so->side1.so_curr; po_off = so->side1.po_off; break; case STREAM_SIDE2: so_curr = so->side2.so_curr; po_off = so->side2.po_off; break; } first = so_curr; /* create the buffer from the current position to the end */ for ( ; so_curr != TAILQ_END(so->so_head); so_curr = TAILQ_NEXT(so_curr, next)) { /* skip packet in the wrong side */ if (so_curr->side != mode) { po_off = 0; continue; } if (so_curr == first) len += so_curr->po.DATA.len - po_off; else len += so_curr->po.DATA.len; SAFE_REALLOC(tmpbuf, len); /* * add the packet to the end of the buffer * containing the whole conversation */ if (so_curr == first) memcpy(tmpbuf, so_curr->po.DATA.data + po_off, so_curr->po.DATA.len - po_off); else memcpy(tmpbuf + len - so_curr->po.DATA.len, so_curr->po.DATA.data, so_curr->po.DATA.len); } /* the buffer is found in the conversation */ if ((find = memmem(tmpbuf, len, buf, buflen)) != NULL) { offset = find - tmpbuf; SAFE_FREE(tmpbuf); /* move the stream pointers to the buffer found */ stream_move(so, offset, SEEK_CUR, mode); switch (mode) { case STREAM_SIDE1: return so->side1.so_curr; case STREAM_SIDE2: return so->side2.so_curr; } } SAFE_FREE(tmpbuf); return NULL; }
/* * move the pointers into the stream */ int stream_move(struct stream_object *so, size_t offset, int whence, int mode) { size_t tmp_size = 0; size_t move = 0; struct so_list *so_curr = NULL; size_t po_off = 0; /* get the values into temp variable */ switch (mode) { case STREAM_SIDE1: so_curr = so->side1.so_curr; po_off = so->side1.po_off; break; case STREAM_SIDE2: so_curr = so->side2.so_curr; po_off = so->side2.po_off; break; } /* no movement */ if (offset == 0) return 0; /* * the offest is calculated from the beginning, * so move to the first packet */ if (whence == SEEK_SET) { so_curr = TAILQ_FIRST(&so->so_head); po_off = 0; } /* the other mode is SEEK_CUR */ /* search the first packet matching the selected mode */ while (so_curr->side != mode) { so_curr = TAILQ_NEXT(so_curr, next); /* don't go after the end of the stream */ if (so_curr == TAILQ_END(&so->pl_head)) return 0; } while (offset) { /* get the lenght to jump to in the current po */ tmp_size = (so_curr->po.DATA.len - po_off < offset) ? so_curr->po.DATA.len - po_off : offset; /* update the offset */ po_off += tmp_size; /* decrement the total offset by the packet lenght */ offset -= tmp_size; /* update the total movement */ move += tmp_size; /* we have reached the end of the packet, go to the next one */ if (po_off == so_curr->po.DATA.len) { /* search the next packet matching the selected mode */ do { /* don't go after the end of the stream */ if (TAILQ_NEXT(so_curr, next) != TAILQ_END(&so->pl_head)) so_curr = TAILQ_NEXT(so_curr, next); else goto move_end; } while (so_curr->side != mode); /* reset the offset for the packet */ po_off = 0; } } move_end: /* restore the value in the real stream object */ switch (mode) { case STREAM_SIDE1: so->side1.so_curr = so_curr; so->side1.po_off = po_off; break; case STREAM_SIDE2: so->side2.so_curr = so_curr; so->side2.po_off = po_off; break; } return move; }
/* * Allocate physical memory from the given physical address range. * Called by DMA-safe memory allocation methods. */ int _bus_dmamem_alloc_range(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment, bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags, paddr_t low, paddr_t high) { paddr_t curaddr, lastaddr; struct vm_page *m; struct pglist mlist; int curseg, error; #ifdef DEBUG_DMA printf("alloc_range: t=%p size=%lx align=%lx boundary=%lx segs=%p nsegs=%x rsegs=%p flags=%x lo=%lx hi=%lx\n", t, size, alignment, boundary, segs, nsegs, rsegs, flags, low, high); #endif /* DEBUG_DMA */ /* Always round the size. */ size = round_page(size); TAILQ_INIT(&mlist); /* * Allocate pages from the VM system. */ error = uvm_pglistalloc(size, low, high, alignment, boundary, &mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0); if (error) return (error); /* * Compute the location, size, and number of segments actually * returned by the VM code. */ m = TAILQ_FIRST(&mlist); curseg = 0; lastaddr = segs[curseg].ds_addr = VM_PAGE_TO_PHYS(m); segs[curseg].ds_len = PAGE_SIZE; #ifdef DEBUG_DMA printf("alloc: page %lx\n", lastaddr); #endif /* DEBUG_DMA */ m = TAILQ_NEXT(m, pageq); for (; m != TAILQ_END(&mlist); m = TAILQ_NEXT(m, pageq)) { curaddr = VM_PAGE_TO_PHYS(m); #ifdef DIAGNOSTIC if (curaddr < low || curaddr >= high) { printf("uvm_pglistalloc returned non-sensical" " address 0x%lx\n", curaddr); panic("_bus_dmamem_alloc_range"); } #endif /* DIAGNOSTIC */ #ifdef DEBUG_DMA printf("alloc: page %lx\n", curaddr); #endif /* DEBUG_DMA */ if (curaddr == (lastaddr + PAGE_SIZE)) segs[curseg].ds_len += PAGE_SIZE; else { curseg++; segs[curseg].ds_addr = curaddr; segs[curseg].ds_len = PAGE_SIZE; } lastaddr = curaddr; } *rsegs = curseg + 1; return (0); }
/* * Allocate physical memory from the given physical address range. * Called by DMA-safe memory allocation methods. */ int _dmamem_alloc_range(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment, bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags, paddr_t low, paddr_t high) { paddr_t curaddr, lastaddr; vm_page_t m; struct pglist mlist; int curseg, error, plaflag; /* Always round the size. */ size = round_page(size); /* * Allocate pages from the VM system. */ plaflag = flags & BUS_DMA_NOWAIT ? UVM_PLA_NOWAIT : UVM_PLA_WAITOK; if (flags & BUS_DMA_ZERO) plaflag |= UVM_PLA_ZERO; TAILQ_INIT(&mlist); error = uvm_pglistalloc(size, low, high, alignment, boundary, &mlist, nsegs, plaflag); if (error) return (error); /* * Compute the location, size, and number of segments actually * returned by the VM code. */ m = TAILQ_FIRST(&mlist); curseg = 0; lastaddr = segs[curseg].ds_addr = (*t->_pa_to_device)(VM_PAGE_TO_PHYS(m)); segs[curseg].ds_len = PAGE_SIZE; m = TAILQ_NEXT(m, pageq); for (; m != TAILQ_END(&mlist); m = TAILQ_NEXT(m, pageq)) { curaddr = VM_PAGE_TO_PHYS(m); #ifdef DIAGNOSTIC if (curaddr < low || curaddr >= high) { printf("vm_page_alloc_memory returned non-sensical" " address 0x%lx\n", curaddr); panic("_dmamem_alloc_range"); } #endif curaddr = (*t->_pa_to_device)(curaddr); if (curaddr == (lastaddr + PAGE_SIZE)) segs[curseg].ds_len += PAGE_SIZE; else { curseg++; segs[curseg].ds_addr = curaddr; segs[curseg].ds_len = PAGE_SIZE; } lastaddr = curaddr; } *rsegs = curseg + 1; return (0); }
/* * read data from the stream * mode can be: * STREAM_SIDE1 reads only from the first side (usually client to server) * STREAM_SIDE2 reads only from the other side */ int stream_read(struct stream_object *so, u_char *buf, size_t size, int mode) { size_t buf_off = 0; size_t tmp_size = 0; struct so_list *so_curr = NULL; size_t po_off = 0; /* get the values into temp variable */ switch (mode) { case STREAM_SIDE1: so_curr = so->side1.so_curr; po_off = so->side1.po_off; break; case STREAM_SIDE2: so_curr = so->side2.so_curr; po_off = so->side2.po_off; break; } /* search the first packet matching the selected mode */ while (so_curr->side != mode) { so_curr = TAILQ_NEXT(so_curr, next); /* don't go after the end of the stream */ if (so_curr == TAILQ_END(&so->pl_head)) return 0; } /* size is decremented while it is copied in the buffer */ while (size) { /* get the size to be copied from the current po */ tmp_size = (so_curr->po.DATA.len - po_off < size) ? so_curr->po.DATA.len - po_off : size; /* fill the buffer */ memcpy(buf + buf_off, so_curr->po.DATA.data + po_off, tmp_size); /* the offset is the portion of the data copied into the buffer */ po_off += tmp_size; /* update the pointer into the buffer */ buf_off += tmp_size; /* decrement the total size to be copied */ size -= tmp_size; /* we have reached the end of the packet, go to the next one */ if (po_off == so_curr->po.DATA.len) { /* search the next packet matching the selected mode */ do { /* don't go after the end of the stream */ if (TAILQ_NEXT(so_curr, next) != TAILQ_END(&so->pl_head)) so_curr = TAILQ_NEXT(so_curr, next); else goto read_end; } while (so_curr->side != mode); /* reset the offset for the packet */ po_off = 0; } } read_end: /* restore the value in the real stream object */ switch (mode) { case STREAM_SIDE1: so->side1.so_curr = so_curr; so->side1.po_off = po_off; break; case STREAM_SIDE2: so->side2.so_curr = so_curr; so->side2.po_off = po_off; break; } /* return the total byte read */ return buf_off; }