Ejemplo n.º 1
0
Archivo: hub.c Proyecto: nizox/hub
void
hub_uninit(struct hub *hub)
{
  struct peer *ptr = hub->peers;

  tnt_tun_iface_set_status(&hub->tun, TNT_STATUS_ALL_DOWN);
  tnt_tun_close(&hub->tun);
  if (hub->tun.interface) {
    free(hub->tun.interface);
  }

  evutil_closesocket(event_get_fd(hub->levent));
  evutil_closesocket(event_get_fd(hub->ievent));
  event_free(hub->levent);
  event_free(hub->ievent);

  while (ptr)
  {
    struct peer *tmp = ptr->next;

    free(ptr->addr);
    free(ptr);
    ptr = tmp;
  }
}
Ejemplo n.º 2
0
Archivo: event.c Proyecto: kghost/lldpd
/*
 * Update SNMP event loop.
 *
 * New events are added and some other are removed. This function
 * should be called every time a SNMP event happens: either when
 * handling a SNMP packet, a SNMP timeout or when sending a SNMP
 * packet. This function will keep libevent in sync with NetSNMP.
 *
 * @param base The libevent base we are working on.
 */
static void
levent_snmp_update(struct lldpd *cfg)
{
	int maxfd = 0;
	int block = 1;
	fd_set fdset;
	struct timeval timeout;
	static int howmany = 0;
	int added = 0, removed = 0, current = 0;
	struct lldpd_events *snmpfd, *snmpfd_next;

	/* snmp_select_info() can be tricky to understand. We set `block` to
	   1 to means that we don't request a timeout. snmp_select_info()
	   will reset `block` to 0 if it wants us to setup a timeout. In
	   this timeout, `snmp_timeout()` should be invoked.
	   
	   Each FD in `fdset` will need to be watched for reading. If one of
	   them become active, `snmp_read()` should be called on it.
	*/
	
	FD_ZERO(&fdset);
	snmp_select_info(&maxfd, &fdset, &timeout, &block);
	
	/* We need to untrack any event whose FD is not in `fdset`
	   anymore */
	for (snmpfd = TAILQ_FIRST(levent_snmp_fds(cfg));
	     snmpfd;
	     snmpfd = snmpfd_next) {
		snmpfd_next = TAILQ_NEXT(snmpfd, next);
		if (event_get_fd(snmpfd->ev) >= maxfd ||
		    (!FD_ISSET(event_get_fd(snmpfd->ev), &fdset))) {
			event_free(snmpfd->ev);
			TAILQ_REMOVE(levent_snmp_fds(cfg), snmpfd, next);
			free(snmpfd);
			removed++;
		} else {
			FD_CLR(event_get_fd(snmpfd->ev), &fdset);
			current++;
		}
	}
	
	/* Invariant: FD in `fdset` are not in list of FD */
	for (int fd = 0; fd < maxfd; fd++) {
		if (FD_ISSET(fd, &fdset)) {
			levent_snmp_add_fd(cfg, fd);
			added++;
		}
	}
	current += added;
	if (howmany != current) {
		log_debug("event", "added %d events, removed %d events, total of %d events",
			   added, removed, current);
		howmany = current;
	}

	/* If needed, handle timeout */
	if (evtimer_add(cfg->g_snmp_timeout, block?NULL:&timeout) == -1)
		log_warnx("event", "unable to schedule timeout function for SNMP");
}
Ejemplo n.º 3
0
int32_t kqueue_add( void * arg, struct event * ev )
{
    struct kevent kev;
    struct kqueuer * poller = (struct kqueuer *)arg;

    memset( &kev, 0, sizeof(kev) );

    if ( ev->events & EV_READ )
    {
        kev.flags = EV_ADD;
        kev.udata = (void *)ev;
        kev.filter = EVFILT_READ;
        kev.ident = event_get_fd((event_t)ev);
#ifdef NOTE_EOF
        kev.fflags = NOTE_EOF;
#endif
        if ( !(ev->events & EV_PERSIST) )
        {
            kev.flags |= EV_ONESHOT;
        }

        if ( kqueue_insert( poller, &kev ) != 0 )
        {
            return -1;
        }

        ev->status |= EVSTATUS_X_KQINKERNEL;
    }

    if ( ev->events & EV_WRITE )
    {
        kev.flags = EV_ADD;
        kev.udata = (void *)ev;
        kev.filter = EVFILT_WRITE;
        kev.ident = event_get_fd((event_t)ev);
        if ( !(ev->events & EV_PERSIST) )
        {
            kev.flags |= EV_ONESHOT;
        }

        if ( kqueue_insert( poller, &kev ) != 0 )
        {
            return -2;
        }

        ev->status |= EVSTATUS_X_KQINKERNEL;
    }

    return 0;
}
Ejemplo n.º 4
0
void Listener::on_delete(){
  MYDEBUG("delete listener");
  event_del(listener);
  if (this->flags & LEV_OPT_CLOSE_ON_FREE)
    evutil_closesocket(event_get_fd(this->listener));
  event_free(this->listener);
}
Ejemplo n.º 5
0
static evutil_socket_t
event_listener_getfd(struct evconnlistener *lev)
{
	struct evconnlistener_event *lev_e =
	    EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
	return event_get_fd(&lev_e->listener);
}
Ejemplo n.º 6
0
int
main() {
        pipe(pp);
        struct event_base *base = event_base_new();
        evr = event_new(base, pp[0], EV_READ, read_cb, NULL);
        evw = event_new(base, pp[1], EV_WRITE  | EV_TIMEOUT, write_cb, NULL);

        event_add(evw, NULL);
        event_add(evr, NULL);

        struct event_base *outbase;
        int fdout;
        event_get_assignment(evw, NULL, &fdout, NULL, NULL, NULL);		/* Note fdout. */
        outbase = event_get_base(evw);		/* outbase == base */
        event_callback_fn cb = event_get_callback(evw);
        assert(write_cb == cb);
        assert(NULL == event_get_callback_arg(evw));

        assert(EV_WRITE|EV_TIMEOUT == event_get_events(evw));

        assert(pp[1] == event_get_fd(evw));
        assert(event_initialized(evw) == 1);

        test_num_events();
        event_base_dispatch(base);

        return 0;
}
Ejemplo n.º 7
0
void
cmd_tcp_eread(evutil_socket_t fd, short which, void *arg)
{
	extern FILE *honeyd_servicefp;
	struct tcp_con *con = arg;
	char line[1024];
	int nread;
	struct command *cmd = &con->cmd;

	TRACE(fd, nread = read(fd, line, sizeof(line)));

	if (nread <= 0) {
		if (cmd->fdwantclose) {
			/* Stdin is already closed */
			cmd_free(&con->cmd);
			
			tcp_sendfin(con);
		} else {
			/* Now stdin will takes us down */
			cmd->fdwantclose = 1;
		}
		return;
	}

	if (nread == sizeof(line))
		nread--;
	line[nread] = '\0';
	
	honeyd_log_service(honeyd_servicefp, IP_PROTO_TCP, &con->conhdr, line);

	TRACE(event_get_fd(cmd->peread), event_add(cmd->peread, NULL));
}
Ejemplo n.º 8
0
static void ss_forward_pkt(redudp_client *client, struct sockaddr * destaddr, void *data, size_t pktlen)
{
    ss_client *ssclient = (void*)(client + 1);
    ss_instance * ss = (ss_instance *)(client->instance+1);
    struct sockaddr_in * relayaddr = &client->instance->config.relayaddr;
    struct msghdr msg;
    struct iovec io[1];
    ssize_t outgoing;
    int rc;
    ss_header_ipv4 header;
    size_t len = 0;
    size_t fwdlen = 0;
    void * buff = client->instance->shared_buff;

    /* build and send header */
    // TODO: Better implementation and IPv6 Support
    header.addr_type = ss_addrtype_ipv4;
    header.addr = ((struct sockaddr_in *)destaddr)->sin_addr.s_addr;
    header.port = ((struct sockaddr_in *)destaddr)->sin_port;

    if (enc_ctx_init(&ss->info, &ss->e_ctx, 1)) {
        redudp_log_error(client, LOG_ERR, "Shadowsocks UDP failed to initialize encryption context.");
        return;
    }
    rc = ss_encrypt(&ss->e_ctx, (char *)&header, sizeof(header), buff, &len);
    if (rc)
    {
        if (len + pktlen < MAX_UDP_PACKET_SIZE)
            rc = ss_encrypt(&ss->e_ctx, (char *)data, pktlen, buff+len, &fwdlen);
        else
            rc = 0;
    }
    enc_ctx_free(&ss->e_ctx);
    if (!rc)
    {
        redudp_log_error(client, LOG_DEBUG, "Can't encrypt packet, dropping it");
        return;
    }
    fwdlen += len;

    memset(&msg, 0, sizeof(msg));
    msg.msg_name = relayaddr;
    msg.msg_namelen = sizeof(*relayaddr);
    msg.msg_iov = io;
    msg.msg_iovlen = SIZEOF_ARRAY(io);

    io[0].iov_base = buff;
    io[0].iov_len = fwdlen;

    outgoing = sendmsg(event_get_fd(&ssclient->udprelay), &msg, 0);
    if (outgoing == -1) {
        redudp_log_errno(client, LOG_DEBUG, "sendmsg: Can't forward packet, dropping it");
        return;
    }
    else if (outgoing != fwdlen) {
        redudp_log_error(client, LOG_DEBUG, "sendmsg: I was sending %zd bytes, but only %zd were sent.", fwdlen, outgoing);
        return;
    }
}
Ejemplo n.º 9
0
static void
ev_watch_update(AvahiWatch *w, AvahiWatchEvent a_events)
{
  if (w->ev)
    event_del(w->ev);

  _ev_watch_add(w, (int)event_get_fd(w->ev), a_events);
}
Ejemplo n.º 10
0
int32_t kqueue_del( void * arg, struct event * ev )
{
    struct kevent kev;
    struct kqueuer * poller = (struct kqueuer *)arg;

    if ( !(ev->status & EVSTATUS_X_KQINKERNEL) )
    {
        //
        // 该事件已经不在KQUEUE中了, 直接返回成功
        //
        return 0;
    }

    memset( &kev, 0, sizeof(kev) );

    if ( ev->events & EV_READ )
    {
        kev.flags = EV_DELETE;
        kev.filter = EVFILT_READ;
        kev.ident = event_get_fd((event_t)ev);

        if ( kqueue_insert( poller, &kev ) != 0 )
        {
            return -2;
        }

        ev->status &= ~EVSTATUS_X_KQINKERNEL;
    }

    if ( ev->events & EV_WRITE )
    {
        kev.flags = EV_DELETE;
        kev.filter = EVFILT_WRITE;
        kev.ident = event_get_fd((event_t)ev);

        if ( kqueue_insert( poller, &kev ) != 0 )
        {
            return -3;
        }

        ev->status &= ~EVSTATUS_X_KQINKERNEL;
    }

    return 0;
}
Ejemplo n.º 11
0
static void ss_client_fini(redudp_client *client)
{
    ss_client *ssclient = (void*)(client + 1);
    if (event_initialized(&ssclient->udprelay)) {
        close(event_get_fd(&ssclient->udprelay));
        if (event_del(&ssclient->udprelay) == -1)
            redudp_log_errno(client, LOG_ERR, "event_del");
    }
}
Ejemplo n.º 12
0
static void
event_listener_destroy(struct evconnlistener *lev)
{
	struct evconnlistener_event *lev_e =
	    EVUTIL_UPCAST(lev, struct evconnlistener_event, base);

	event_del(&lev_e->listener);
	if (lev->flags & LEV_OPT_CLOSE_ON_FREE)
		evutil_closesocket(event_get_fd(&lev_e->listener));
	event_debug_unassign(&lev_e->listener);
}
Ejemplo n.º 13
0
static void
be_socket_destruct(struct bufferevent *bufev)
{
	struct bufferevent_private *bufev_p =
	    EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
	evutil_socket_t fd;
	EVUTIL_ASSERT(bufev->be_ops == &bufferevent_ops_socket);

	fd = event_get_fd(&bufev->ev_read);

	if ((bufev_p->options & BEV_OPT_CLOSE_ON_FREE) && fd >= 0)
		EVUTIL_CLOSESOCKET(fd);
}
Ejemplo n.º 14
0
static void ss_pkt_from_server(int fd, short what, void *_arg)
{
    redudp_client *client = _arg;
    ss_client *ssclient = (void*)(client + 1);
    ss_instance * ss = (ss_instance *)(client->instance+1);
    ss_header_ipv4  * header;
    ssize_t pktlen;
    size_t  fwdlen;
    struct sockaddr_in udprelayaddr;
    int rc;
    void * buff = client->instance->shared_buff;
    void * buff2 = ss->buff;

    assert(fd == event_get_fd(&ssclient->udprelay));

    pktlen = red_recv_udp_pkt(fd, buff, MAX_UDP_PACKET_SIZE, &udprelayaddr, NULL);
    if (pktlen == -1)
        return;

    if (enc_ctx_init(&ss->info, &ss->d_ctx, 0)) {
        redudp_log_error(client, LOG_ERR, "Shadowsocks UDP failed to initialize decryption context.");
        return;
    }
    rc = ss_decrypt(&ss->d_ctx, buff, pktlen, buff2, &fwdlen);
    enc_ctx_free(&ss->d_ctx);
    if (!rc) {
        redudp_log_error(client, LOG_DEBUG, "Can't decrypt packet, dropping it");
        return;
    }
    header = (ss_header_ipv4 *)buff2;
    // We do not verify src address, but at least, we need to ensure address type is correct.
    if (header->addr_type != ss_addrtype_ipv4) {
        redudp_log_error(client, LOG_DEBUG, "Got address type #%u instead of expected #%u (IPv4).",
                        header->addr_type, ss_addrtype_ipv4);
        return;
    }

    struct sockaddr_in pktaddr = {
        .sin_family = AF_INET,
        .sin_addr   = { header->addr },
        .sin_port   = header->port,
    };

    if (fwdlen < sizeof(*header)) {
        redudp_log_error(client, LOG_DEBUG, "Packet too short.");
        return;
    }
    fwdlen -= sizeof(*header);
    redudp_fwd_pkt_to_sender(client, buff2 + sizeof(*header), fwdlen, &pktaddr);
}
Ejemplo n.º 15
0
static int
be_socket_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op,
    union bufferevent_ctrl_data *data)
{
	switch (op) {
	case BEV_CTRL_SET_FD:
		be_socket_setfd(bev, data->fd);
		return 0;
	case BEV_CTRL_GET_FD:
		data->fd = event_get_fd(&bev->ev_read);
		return 0;
	case BEV_CTRL_GET_UNDERLYING:
	default:
		return -1;
	}
}
Ejemplo n.º 16
0
Archivo: hub.c Proyecto: nizox/hub
static void
broadcast_to_peers(struct hub *hub, const char *buf, size_t buflen)
{
  ssize_t n;
  struct peer *ptr = hub->peers;

  while (ptr)
  {
    n = sendto(event_get_fd(hub->levent), buf, buflen, 0,
        ptr->addr, ptr->addrlen);
    if (n > 0)
      ptr->sent += n;
    else
      fprintf(stderr, "Failed sending %i bytes to %s\n",
          buflen, ptr->name);
    ptr = ptr->next;
  }
}
Ejemplo n.º 17
0
Archivo: event.c Proyecto: kghost/lldpd
void
levent_hardware_release(struct lldpd_hardware *hardware)
{
	struct lldpd_events *ev, *ev_next;
	event_free(hardware->h_timer); hardware->h_timer = NULL;
	if (!hardware->h_recv) return;

	log_debug("event", "release events for %s", hardware->h_ifname);
	for (ev = TAILQ_FIRST(levent_hardware_fds(hardware));
	     ev;
	     ev = ev_next) {
		ev_next = TAILQ_NEXT(ev, next);
		/* We may close several time the same FD. This is harmless. */
		close(event_get_fd(ev->ev));
		event_free(ev->ev);
		TAILQ_REMOVE(levent_hardware_fds(hardware), ev, next);
		free(ev);
	}
	free(levent_hardware_fds(hardware));
}
Ejemplo n.º 18
0
void socket_read_cb(int fd, short events, void *arg)
{
  char msg[4096];
  struct event *ev = (struct event*)arg;
  int len = read(fd, msg, sizeof(msg) - 1);



  if( len <= 0 )
  {
    printf("some error happen when read\n");
    close(event_get_fd(ev));
    event_free(ev);
    return ;
  }

  msg[len] = '\0';
  printf("recv the client msg: %s", msg);

  char reply_msg[4096] = "I have recvieced the msg: ";
  strcat(reply_msg + strlen(reply_msg), msg);

  write(fd, reply_msg, strlen(reply_msg) );
}
Ejemplo n.º 19
0
int
cleanup_main (struct state *state)
{
  int i;
  for (i = 0; i < E_MAX; ++i)
    {
      struct event *e = state->events[i];
      if (e)
        {
          int fd = event_get_fd (e);
          if (fd >= 0 && ! (event_get_events (e) & EV_SIGNAL))
            close (fd);
          event_free (e);
        }
    }
  /* The other half was closed above. */
  platform->file_close (state->tlsdate_monitor_fd);
  if (state->tlsdate_pid)
    {
      platform->process_signal (state->tlsdate_pid, SIGKILL);
      platform->process_wait (state->tlsdate_pid, NULL, 0 /* !forever */);
    }
  /* Best effort to tear it down if it is still alive. */
  close(state->setter_notify_fd);
  close(state->setter_save_fd);
  if (state->setter_pid)
    {
      platform->process_signal (state->setter_pid, SIGKILL);
      platform->process_wait (state->setter_pid, NULL, 0 /* !forever */);
    }
  /* TODO(wad) Add dbus_cleanup() */
  if (state->base)
    event_base_free (state->base);
  memset(state, 0, sizeof(*state));
  return 0;
}
Ejemplo n.º 20
0
int
rs_packet_send (struct rs_packet *pkt, void *user_data)
{
  struct rs_connection *conn = NULL;
  int err = 0;

  assert (pkt);
  assert (pkt->conn);
  conn = pkt->conn;

  if (_conn_is_open_p (conn))
    packet_do_send (pkt);
  else
    if (_conn_open (conn, pkt))
      return -1;

  assert (conn->evb);
  assert (conn->active_peer);
  assert (conn->fd >= 0);

  conn->user_data = user_data;

  if (conn->bev)		/* TCP */
    {
      bufferevent_setcb (conn->bev, NULL, tcp_write_cb, tcp_event_cb, pkt);
      bufferevent_enable (conn->bev, EV_WRITE);
    }
  else				/* UDP */
    {
      event_assign (conn->wev, conn->evb, event_get_fd (conn->wev),
		    EV_WRITE, event_get_callback (conn->wev), pkt);
      err = event_add (conn->wev, NULL);
      if (err < 0)
	return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
				    "event_add: %s",
				    evutil_gai_strerror (err));
    }

  /* Do dispatch, unless the user wants to do it herself.  */
  if (!conn_user_dispatch_p (conn))
    {
      conn->callbacks.sent_cb = _wcb;
      conn->user_data = pkt;
      rs_debug (("%s: entering event loop\n", __func__));
      err = event_base_dispatch (conn->evb);
      if (err < 0)
	return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
				    "event_base_dispatch: %s",
				    evutil_gai_strerror (err));
      rs_debug (("%s: event loop done\n", __func__));
      conn->callbacks.sent_cb = NULL;
      conn->user_data = NULL;

      if ((pkt->flags & RS_PACKET_SENT) == 0)
	{
	  assert (rs_err_conn_peek_code (conn));
	  return rs_err_conn_peek_code (conn);
	}
    }

  return RSE_OK;
}
Ejemplo n.º 21
0
int32_t epoll_add( void * arg, struct event * ev )
{
    int32_t fd = 0;
    int32_t op = 0, events = 0;

    struct epoll_event epollevent;
    struct eventpair * eventpair = NULL;
    struct epoller * poller = (struct epoller *)arg;

    fd = event_get_fd( (event_t)ev );
    if ( fd < 0 )
    {
        return -3;
    }
    else if ( fd >= poller->npairs )
    {
        if ( epoll_insert( poller, fd ) != 0 )
        {
            return -1;
        }
    }

    events = 0;
    op = EPOLL_CTL_ADD;
    eventpair = &( poller->evpairs[fd] );

    if ( eventpair->evread != NULL )
    {
        events |= EPOLLIN;
        op = EPOLL_CTL_MOD;
    }
    if ( eventpair->evwrite != NULL )
    {
        events |= EPOLLOUT;
        op = EPOLL_CTL_MOD;
    }

    if ( ev->events & EV_READ )
    {
        events |= EPOLLIN;
    }
    if ( ev->events & EV_WRITE )
    {
        events |= EPOLLOUT;
    }

    epollevent.data.u64 = 0;    /* avoid valgrind warnning */
    epollevent.data.fd = fd;
    epollevent.events = events;

    if ( epoll_ctl( poller->epollfd, op, fd, &epollevent ) == -1 )
    {
        return -2;
    }

    if ( ev->events & EV_READ )
    {
        eventpair->evread = ev;
    }
    if ( ev->events & EV_WRITE )
    {
        eventpair->evwrite = ev;
    }

    return 0;
}
Ejemplo n.º 22
0
int32_t epoll_del( void * arg, struct event * ev )
{
    int32_t fd = 0;
    int32_t op = 0, events = 0;
    int32_t delwrite = 1, delread = 1;

    struct epoll_event epollevent;
    struct eventpair * eventpair = NULL;
    struct epoller * poller = (struct epoller *)arg;

    fd = event_get_fd((event_t)ev);
    if ( fd >= poller->npairs )
    {
        return -1;
    }

    // 简单的删除指定的事件
    events = 0;
    op = EPOLL_CTL_DEL;
    eventpair = &( poller->evpairs[fd] );

    if ( ev->events & EV_READ )
    {
        events |= EPOLLIN;
    }
    if ( ev->events & EV_WRITE )
    {
        events |= EPOLLOUT;
    }

    // 删除的同时查看该描述符是否支持了其他事件
    // 如有, 则不能直接简单的删除
    if ( (events & (EPOLLIN|EPOLLOUT)) != (EPOLLIN|EPOLLOUT) )
    {
        if ( (events & EPOLLIN) && eventpair->evwrite != NULL )
        {
            // 删除的是读事件, 写事件仍然要监听
            // 并且还需要从写事件中查看是否支持了边缘触发模式
            delwrite = 0;
            events = EPOLLOUT;
            op = EPOLL_CTL_MOD;
        }
        else if ( (events & EPOLLOUT) && eventpair->evread != NULL )
        {
            // 删除的是写事件, 读事件仍然要监听
            // 并且还需要从读事件中查看是否支持了边缘触发模式
            delread = 0;
            events = EPOLLIN;
            op = EPOLL_CTL_MOD;
        }
    }

    epollevent.data.u64 = 0;    /* avoid valgrind warnning */
    epollevent.data.fd = fd;
    epollevent.events = events;

    if ( delread )
    {
        eventpair->evread = NULL;
    }
    if ( delwrite )
    {
        eventpair->evwrite = NULL;
    }

    return epoll_ctl( poller->epollfd, op, fd, &epollevent ) == -1 ? -2 : 0;
}
Ejemplo n.º 23
0
int
tnt_fork(int imsg_fds[2]) {
    pid_t pid;
    struct imsgbuf ibuf;
    struct imsg_data data;
    struct passwd *pw;
    struct event_base *evbase = NULL;
    struct event *sigterm = NULL;
    struct event *sigint = NULL;
    struct event *imsg_event = NULL;
    struct server server;
    struct event_config *evcfg;

    switch ((pid = fork())) {
        case -1:
            log_err(TNT_OSERR, "fork");
            break;
        case 0:
            tnt_setproctitle("[unpriv]");
            log_set_prefix("unpriv");
            break;
        default:
            tnt_setproctitle("[priv]");
            log_set_prefix("priv");
            return pid;
    }

    if ((pw = getpwnam(TNETACLE_USER)) == NULL) {
        log_errx(1, "unknown user " TNETACLE_USER);
        return TNT_NOUSER;
    }

    /*Allocate the event config*/
    evcfg = event_config_new();

    /* Initialize the OpenSSL library */
    SSL_library_init();
    SSL_load_error_strings();
    /* We MUST have entropy, or else there's no point to crypto. */
    if (!RAND_poll())
    {
        log_errx(TNT_SOFTWARE, "[INIT] failed to find an entropy source");
        /* never returns */
    }

    if (serv_opts.encryption)
        server.server_ctx = evssl_init();
    else
        server.server_ctx = NULL;

    tnt_priv_drop(pw);

#if defined(Darwin)
    /* It's sad isn't it ?*/
    event_config_avoid_method(evcfg, "kqueue");
    event_config_avoid_method(evcfg, "poll");
    event_config_avoid_method(evcfg, "devpoll");
    if ((evbase = event_base_new_with_config(evcfg)) == NULL) {
        log_err(1, "libevent");
    }
#else
    if ((evbase = event_base_new_with_config(evcfg)) == NULL) {
        log_err(1, "libevent");
    }
#endif

    sigterm = event_new(evbase, SIGTERM, EV_SIGNAL, &chld_sighdlr, evbase);
    sigint = event_new(evbase, SIGINT, EV_SIGNAL, &chld_sighdlr, evbase);

    signal(SIGPIPE, SIG_IGN);
    signal(SIGHUP, SIG_IGN);
    signal(SIGCHLD, SIG_DFL);

    if (server_init(&server, evbase) == -1)
        log_errx(1, "failed to init the server socket");

    data.ibuf = &ibuf;
    data.evbase = evbase;
    data.server = &server;
    imsg_event = init_pipe_endpoint(imsg_fds, &data);

    event_add(sigterm, NULL);
    event_add(sigint, NULL);
    event_add(imsg_event, NULL);

    log_info("tnetacle ready");

    /* Immediately request the creation of a tun interface */
    imsg_compose(&ibuf, IMSG_CREATE_DEV, 0, 0, -1, NULL, 0);

    log_info("starting event loop");
    event_base_dispatch(evbase);

    /* cleanely exit */
    msgbuf_write(&ibuf.w);
    msgbuf_clear(&ibuf.w);

    /* Shutdown the server */
    server_delete(&server);

    /*
     * It may look like we freed this one twice,
     * once here and once in tnetacled.c but this is not the case.
     * Please don't erase this !
     */

    event_free(sigterm);
    event_free(sigint);
    close(event_get_fd(imsg_event));
    event_free(imsg_event);
    event_base_free(evbase);
    event_config_free(evcfg);

    log_info("tnetacle exiting");
    exit(TNT_OK);
}