Beispiel #1
0
int
show_session_msg(struct imsg *imsg)
{
	struct rsession		*con;
	char			 a[128], b[128];
	struct timeval		 tv_now;

	switch (imsg->hdr.type) {
	case IMSG_CTL_SESSION:
		con = imsg->data;

		(void)print_host(&con->se_in.ss, a, sizeof(a));
		(void)print_host(&con->se_out.ss, b, sizeof(b));
		printf("session %u:%u %s:%u -> %s:%u\t%s\n",
		    imsg->hdr.peerid, con->se_id,
		    a, ntohs(con->se_in.port), b, ntohs(con->se_out.port),
		    con->se_done ? "DONE" : "RUNNING");

		getmonotime(&tv_now);
		print_time(&tv_now, &con->se_tv_start, a, sizeof(a));
		print_time(&tv_now, &con->se_tv_last, b, sizeof(b));
		printf("\tage %s, idle %s, relay %u, pid %u",
		    a, b, con->se_relayid, con->se_pid);
		if (con->se_mark)
			printf(", mark %u", con->se_mark);
		printf("\n");
		break;
	case IMSG_CTL_END:
		return (1);
	default:
		errx(1, "wrong message in session: %u", imsg->hdr.type);
		break;
	}
	return (0);
}
Beispiel #2
0
static void message(const char *profile, const char *fmt, ...)
{
  static char *previous = 0;
  static struct timeval zen;
  static const struct timeval tmo = { 0, 100 * 1000 };
  struct timeval now, dif;
  int gap = 0;

  getmonotime(&now);
  timersub(&now, &zen, &dif);
  if( timercmp(&tmo, &dif, <) )
  {
    zen = now;
    gap = 1;
  }

  if( !xstrsame(previous, profile) )
  {
    xstrset(&previous, profile);
    gap = 1;
  }
  if( gap ) printf("\n");

  va_list va;
  va_start(va, fmt);
  vprintf(fmt, va);
  va_end(va);
}
static void timeout_init(struct timeval *tmo, int msec)
{
  struct timeval now;
  getmonotime(&now,0);
  tmo->tv_sec  = (msec / 1000);
  tmo->tv_usec = (msec % 1000) * 1000;
  timeradd(tmo, &now, tmo);
}
Beispiel #4
0
int
relay_dns_request(struct rsession *con)
{
	struct relay		*rlay = con->se_relay;
	struct relay_dns_priv	*priv = con->se_priv;
	u_int8_t		*buf = EVBUFFER_DATA(con->se_out.output);
	size_t			 len = EVBUFFER_LENGTH(con->se_out.output);
	struct relay_dnshdr	*hdr;
	socklen_t		 slen;

	if (buf == NULL || priv == NULL || len < 1)
		return (-1);
	if (debug)
		relay_dns_log(con, buf, len);

	getmonotime(&con->se_tv_start);

	if (!TAILQ_EMPTY(&rlay->rl_tables)) {
		if (relay_from_table(con) != 0)
			return (-1);
	} else if (con->se_out.ss.ss_family == AF_UNSPEC) {
		bcopy(&rlay->rl_conf.dstss, &con->se_out.ss,
		    sizeof(con->se_out.ss));
		con->se_out.port = rlay->rl_conf.dstport;
	}

	if ((con->se_out.s = relay_udp_socket(&con->se_out.ss,
	    con->se_out.port, rlay->rl_proto)) == -1)
		return (-1);
	slen = con->se_out.ss.ss_len;

	hdr = (struct relay_dnshdr *)buf;
	hdr->dns_id = htons(priv->dp_inkey);

 retry:
	if (sendto(con->se_out.s, buf, len, 0,
	    (struct sockaddr *)&con->se_out.ss, slen) == -1) {
		if (con->se_retry) {
			con->se_retry--;
			log_debug("%s: session %d: "
			    "forward failed: %s, %s", __func__,
			    con->se_id, strerror(errno),
			    con->se_retry ? "next retry" : "last retry");
			goto retry;
		}
		log_debug("%s: session %d: forward failed: %s", __func__,
		    con->se_id, strerror(errno));
		return (-1);
	}

	event_again(&con->se_ev, con->se_out.s, EV_TIMEOUT|EV_READ,
	    relay_udp_response, &con->se_tv_start, &env->sc_timeout, con);

	return (0);
}
static void mysleep(int msec)
{
  //printf("SLEEP %d ms\n", msec);

  struct timeval t1,t2;

  getmonotime(&t1,0);

  if( dbus_connection_read_write(connection, msec) )
  {
    do
    {
      puts("dbus dispatch");
    }
    while( dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS );
  }

  getmonotime(&t2,0);
  timersub(&t2,&t1,&t1);
  printf("SLEPT  %.3f / %.3f s\n", t1.tv_sec + t1.tv_usec * 1e-6, msec * 1e-3);
}
static int timeout_left(const struct timeval *tmo)
{
  int res = 0;
  struct timeval now;
  getmonotime(&now,0);
  if( timercmp(&now, tmo, <) )
  {
    timersub(tmo,&now,&now);
    res = now.tv_sec * 1000 + now.tv_usec / 1000;
  }
  return res;
}
Beispiel #7
0
void
show_status_msg(struct imsg *imsg)
{
	struct ctl_show_status	*cstatus;
	double			 clock_offset;
	struct timeval		 tv;

	if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(struct ctl_show_status))
		fatalx("invalid IMSG_CTL_SHOW_STATUS received");

	cstatus = (struct ctl_show_status *)imsg->data;

	if (cstatus->peercnt > 0)
		printf("%d/%d peers valid, ",
		    cstatus->valid_peers, cstatus->peercnt);

	if (cstatus->sensorcnt > 0)
		printf("%d/%d sensors valid, ",
		    cstatus->valid_sensors, cstatus->sensorcnt);

	if (cstatus->constraint_median) {
		tv.tv_sec = cstatus->constraint_median +
		    (getmonotime() - cstatus->constraint_last);
		tv.tv_usec = 0;
		d_to_tv(gettime_from_timeval(&tv) - gettime(), &tv);
		printf("constraint offset %llds", (long long)tv.tv_sec);
		if (cstatus->constraint_errors)
			printf(" (%d errors)",
			    cstatus->constraint_errors);
		printf(", ");
	}

	if (cstatus->peercnt + cstatus->sensorcnt == 0)
		printf("no peers and no sensors configured\n");

	if (cstatus->synced == 1)
		printf("clock synced, stratum %u\n", cstatus->stratum);
	else {
		printf("clock unsynced");
		clock_offset = cstatus->clock_offset < 0 ?
		    -1.0 * cstatus->clock_offset : cstatus->clock_offset;
		if (clock_offset > 5e-7)
			printf(", clock offset is %.3fms\n",
			    cstatus->clock_offset);
		else
			printf("\n");
	}
}
Beispiel #8
0
void
set_deadline(struct ntp_peer *p, time_t t)
{
    p->deadline = getmonotime() + t;
    p->next = 0;
}
Beispiel #9
0
int
client_dispatch(struct ntp_peer *p, u_int8_t settime)
{
    struct ntp_msg		 msg;
    struct msghdr		 somsg;
    struct iovec		 iov[1];
    struct timeval		 tv;
    char			 buf[NTP_MSGSIZE];
    union {
        struct cmsghdr	hdr;
        char		buf[CMSG_SPACE(sizeof(tv))];
    } cmsgbuf;
    struct cmsghdr		*cmsg;
    ssize_t			 size;
    double			 T1, T2, T3, T4;
    time_t			 interval;

    bzero(&somsg, sizeof(somsg));
    iov[0].iov_base = buf;
    iov[0].iov_len = sizeof(buf);
    somsg.msg_iov = iov;
    somsg.msg_iovlen = 1;
    somsg.msg_control = cmsgbuf.buf;
    somsg.msg_controllen = sizeof(cmsgbuf.buf);

    T4 = getoffset();
    if ((size = recvmsg(p->query->fd, &somsg, 0)) == -1) {
        if (errno == EHOSTUNREACH || errno == EHOSTDOWN ||
                errno == ENETUNREACH || errno == ENETDOWN ||
                errno == ECONNREFUSED || errno == EADDRNOTAVAIL ||
                errno == ENOPROTOOPT || errno == ENOENT) {
            client_log_error(p, "recvmsg", errno);
            set_next(p, error_interval());
            return (0);
        } else
            fatal("recvfrom");
    }

    if (somsg.msg_flags & MSG_TRUNC) {
        client_log_error(p, "recvmsg packet", EMSGSIZE);
        set_next(p, error_interval());
        return (0);
    }

    if (somsg.msg_flags & MSG_CTRUNC) {
        client_log_error(p, "recvmsg control data", E2BIG);
        set_next(p, error_interval());
        return (0);
    }

#ifdef HAVE_RTABLE
    if (p->rtable != -1 &&
            setsockopt(p->query->fd, SOL_SOCKET, SO_RTABLE, &p->rtable,
                       sizeof(p->rtable)) == -1)
        fatal("client_dispatch setsockopt SO_RTABLE");
#endif

    for (cmsg = CMSG_FIRSTHDR(&somsg); cmsg != NULL;
            cmsg = CMSG_NXTHDR(&somsg, cmsg)) {
        if (cmsg->cmsg_level == SOL_SOCKET &&
                cmsg->cmsg_type == SCM_TIMESTAMP) {
            memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv));
            T4 += tv.tv_sec + JAN_1970 + 1.0e-6 * tv.tv_usec;
            break;
        }
    }

    if (T4 < JAN_1970) {
        client_log_error(p, "recvmsg control format", EBADF);
        set_next(p, error_interval());
        return (0);
    }

    ntp_getmsg((struct sockaddr *)&p->addr->ss, buf, size, &msg);

    if (msg.orgtime.int_partl != p->query->msg.xmttime.int_partl ||
            msg.orgtime.fractionl != p->query->msg.xmttime.fractionl)
        return (0);

    if ((msg.status & LI_ALARM) == LI_ALARM || msg.stratum == 0 ||
            msg.stratum > NTP_MAXSTRATUM) {
        char s[16];

        if ((msg.status & LI_ALARM) == LI_ALARM) {
            strlcpy(s, "alarm", sizeof(s));
        } else if (msg.stratum == 0) {
            /* Kiss-o'-Death (KoD) packet */
            strlcpy(s, "KoD", sizeof(s));
        } else if (msg.stratum > NTP_MAXSTRATUM) {
            snprintf(s, sizeof(s), "stratum %d", msg.stratum);
        }
        interval = error_interval();
        set_next(p, interval);
        log_info("reply from %s: not synced (%s), next query %llds",
                 log_sockaddr((struct sockaddr *)&p->addr->ss), s,
                 (long long)interval);
        return (0);
    }

    /*
     * From RFC 2030 (with a correction to the delay math):
     *
     *     Timestamp Name          ID   When Generated
     *     ------------------------------------------------------------
     *     Originate Timestamp     T1   time request sent by client
     *     Receive Timestamp       T2   time request received by server
     *     Transmit Timestamp      T3   time reply sent by server
     *     Destination Timestamp   T4   time reply received by client
     *
     *  The roundtrip delay d and local clock offset t are defined as
     *
     *    d = (T4 - T1) - (T3 - T2)     t = ((T2 - T1) + (T3 - T4)) / 2.
     */

    T1 = p->query->xmttime;
    T2 = lfp_to_d(msg.rectime);
    T3 = lfp_to_d(msg.xmttime);

    /*
     * XXX workaround: time_t / tv_sec must never wrap.
     * around 2020 we will need a solution (64bit time_t / tv_sec).
     * consider every answer with a timestamp beyond january 2030 bogus.
     */
    if (T2 > JAN_2030 || T3 > JAN_2030) {
        set_next(p, error_interval());
        return (0);
    }

    p->reply[p->shift].offset = ((T2 - T1) + (T3 - T4)) / 2;
    p->reply[p->shift].delay = (T4 - T1) - (T3 - T2);
    p->reply[p->shift].status.stratum = msg.stratum;
    if (p->reply[p->shift].delay < 0) {
        interval = error_interval();
        set_next(p, interval);
        log_info("reply from %s: negative delay %fs, "
                 "next query %llds",
                 log_sockaddr((struct sockaddr *)&p->addr->ss),
                 p->reply[p->shift].delay, (long long)interval);
        return (0);
    }
    p->reply[p->shift].error = (T2 - T1) - (T3 - T4);
    p->reply[p->shift].rcvd = getmonotime();
    p->reply[p->shift].good = 1;

    p->reply[p->shift].status.leap = (msg.status & LIMASK);
    p->reply[p->shift].status.precision = msg.precision;
    p->reply[p->shift].status.rootdelay = sfp_to_d(msg.rootdelay);
    p->reply[p->shift].status.rootdispersion = sfp_to_d(msg.dispersion);
    p->reply[p->shift].status.refid = msg.refid;
    p->reply[p->shift].status.reftime = lfp_to_d(msg.reftime);
    p->reply[p->shift].status.poll = msg.ppoll;

    if (p->addr->ss.ss_family == AF_INET) {
        p->reply[p->shift].status.send_refid =
            ((struct sockaddr_in *)&p->addr->ss)->sin_addr.s_addr;
    } else if (p->addr->ss.ss_family == AF_INET6) {
        MD5_CTX		context;
        u_int8_t	digest[MD5_DIGEST_LENGTH];

        MD5_Init(&context);
        MD5_Update(&context, ((struct sockaddr_in6 *)&p->addr->ss)->
                   sin6_addr.s6_addr, sizeof(struct in6_addr));
        MD5_Final(digest, &context);
        memcpy((char *)&p->reply[p->shift].status.send_refid, digest,
               sizeof(u_int32_t));
    } else
        p->reply[p->shift].status.send_refid = msg.xmttime.fractionl;

    if (p->trustlevel < TRUSTLEVEL_PATHETIC)
        interval = scale_interval(INTERVAL_QUERY_PATHETIC);
    else if (p->trustlevel < TRUSTLEVEL_AGGRESSIVE)
        interval = scale_interval(INTERVAL_QUERY_AGGRESSIVE);
    else
        interval = scale_interval(INTERVAL_QUERY_NORMAL);

    set_next(p, interval);
    p->state = STATE_REPLY_RECEIVED;

    /* every received reply which we do not discard increases trust */
    if (p->trustlevel < TRUSTLEVEL_MAX) {
        if (p->trustlevel < TRUSTLEVEL_BADPEER &&
                p->trustlevel + 1 >= TRUSTLEVEL_BADPEER)
            log_info("peer %s now valid",
                     log_sockaddr((struct sockaddr *)&p->addr->ss));
        p->trustlevel++;
    }

    log_debug("reply from %s: offset %f delay %f, "
              "next query %llds %s",
              log_sockaddr((struct sockaddr *)&p->addr->ss),
              p->reply[p->shift].offset, p->reply[p->shift].delay,
              (long long)interval, print_rtable(p->rtable));

    client_update(p);
    if (settime)
        priv_settime(p->reply[p->shift].offset);

    if (++p->shift >= OFFSET_ARRAY_SIZE)
        p->shift = 0;

    return (0);
}
Beispiel #10
0
void
relay_udp_server(int fd, short sig, void *arg)
{
	struct relay *rlay = arg;
	struct protocol *proto = rlay->rl_proto;
	struct rsession *con = NULL;
	struct ctl_natlook *cnl = NULL;
	socklen_t slen;
	struct timeval tv;
	struct sockaddr_storage ss;
	u_int8_t buf[IBUF_READ_SIZE];
	void *priv = NULL;
	ssize_t len;

	if (relay_sessions >= RELAY_MAX_SESSIONS ||
	    rlay->rl_conf.flags & F_DISABLE)
		return;

	slen = sizeof(ss);
	if ((len = recvfrom(fd, buf, sizeof(buf), 0,
	    (struct sockaddr*)&ss, &slen)) < 1)
		return;

	if (proto->validate != NULL &&
	    (priv = (*proto->validate)(NULL, rlay, &ss, buf, len)) == NULL)
		return;

	if ((con = calloc(1, sizeof(*con))) == NULL) {
		free(priv);
		return;
	}

	/*
	 * Replace the DNS request Id with a random Id.
	 */
	con->se_priv = priv;
	con->se_in.s = -1;
	con->se_out.s = -1;
	con->se_in.dst = &con->se_out;
	con->se_out.dst = &con->se_in;
	con->se_in.con = con;
	con->se_out.con = con;
	con->se_relay = rlay;
	con->se_id = ++relay_conid;
	con->se_in.dir = RELAY_DIR_REQUEST;
	con->se_out.dir = RELAY_DIR_RESPONSE;
	con->se_retry = rlay->rl_conf.dstretry;
	con->se_out.port = rlay->rl_conf.dstport;
	switch (ss.ss_family) {
	case AF_INET:
		con->se_in.port = ((struct sockaddr_in *)&ss)->sin_port;
		break;
	case AF_INET6:
		con->se_in.port = ((struct sockaddr_in6 *)&ss)->sin6_port;
		break;
	}
	bcopy(&ss, &con->se_in.ss, sizeof(con->se_in.ss));

	getmonotime(&con->se_tv_start);
	bcopy(&con->se_tv_start, &con->se_tv_last, sizeof(con->se_tv_last));

	relay_sessions++;
	SPLAY_INSERT(session_tree, &rlay->rl_sessions, con);

	/* Increment the per-relay session counter */
	rlay->rl_stats[proc_id].last++;

	/* Pre-allocate output buffer */
	con->se_out.output = evbuffer_new();
	if (con->se_out.output == NULL) {
		relay_close(con, "failed to allocate output buffer");
		return;
	}

	/* Pre-allocate log buffer */
	con->se_log = evbuffer_new();
	if (con->se_log == NULL) {
		relay_close(con, "failed to allocate log buffer");
		return;
	}

	if (rlay->rl_conf.flags & F_NATLOOK) {
		if ((cnl = calloc(1, sizeof(*cnl))) == NULL) {
			relay_close(con, "failed to allocate natlookup");
			return;
		}
	}

	/* Save the received data */
	if (evbuffer_add(con->se_out.output, buf, len) == -1) {
		relay_close(con, "failed to store buffer");
		if (cnl != NULL)
			free(cnl);
		return;
	}

	if (cnl != NULL) {
		con->se_cnl = cnl;
		bzero(cnl, sizeof(*cnl));
		cnl->in = -1;
		cnl->id = con->se_id;
		cnl->proc = proc_id;
		cnl->proto = IPPROTO_UDP;
		bcopy(&con->se_in.ss, &cnl->src, sizeof(cnl->src));
		bcopy(&rlay->rl_conf.ss, &cnl->dst, sizeof(cnl->dst));
		proc_compose_imsg(env->sc_ps, PROC_PFE, -1,
		    IMSG_NATLOOK, -1, cnl, sizeof(*cnl));

		/* Schedule timeout */
		evtimer_set(&con->se_ev, relay_natlook, con);
		bcopy(&rlay->rl_conf.timeout, &tv, sizeof(tv));
		evtimer_add(&con->se_ev, &tv);
		return;
	}

	relay_session(con);
}