Blame testsuite/clknetsim/client.c

Packit 9c3e7e
/*
Packit 9c3e7e
 * Copyright (C) 2010  Miroslav Lichvar <mlichvar@redhat.com>
Packit 9c3e7e
 * 
Packit 9c3e7e
 * This program is free software; you can redistribute it and/or modify
Packit 9c3e7e
 * it under the terms of the GNU General Public License as published by
Packit 9c3e7e
 * the Free Software Foundation; either version 2 of the License, or
Packit 9c3e7e
 * (at your option) any later version.
Packit 9c3e7e
 * 
Packit 9c3e7e
 * This program is distributed in the hope that it will be useful,
Packit 9c3e7e
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 9c3e7e
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 9c3e7e
 * GNU General Public License for more details.
Packit 9c3e7e
 * 
Packit 9c3e7e
 * You should have received a copy of the GNU General Public License
Packit 9c3e7e
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit 9c3e7e
 */
Packit 9c3e7e
Packit 9c3e7e
#define _GNU_SOURCE
Packit 9c3e7e
#include <sys/utsname.h>
Packit 9c3e7e
#include <sys/time.h>
Packit 9c3e7e
#include <sys/timex.h>
Packit 9c3e7e
#include <sys/types.h>
Packit 9c3e7e
#include <sys/socket.h>
Packit 9c3e7e
#include <sys/syscall.h>
Packit 9c3e7e
#include <sys/timerfd.h>
Packit 9c3e7e
#include <sys/ipc.h>
Packit 9c3e7e
#include <sys/shm.h>
Packit 9c3e7e
#include <netinet/in.h>
Packit 9c3e7e
#include <arpa/inet.h>
Packit 9c3e7e
#include <time.h>
Packit 9c3e7e
#include <stdio.h>
Packit 9c3e7e
#include <dlfcn.h>
Packit 9c3e7e
#include <sys/un.h>
Packit 9c3e7e
#include <unistd.h>
Packit 9c3e7e
#include <assert.h>
Packit 9c3e7e
#include <stddef.h>
Packit 9c3e7e
#include <stdlib.h>
Packit 9c3e7e
#include <errno.h>
Packit 9c3e7e
#include <sys/ioctl.h>
Packit 9c3e7e
#include <net/if.h>
Packit 9c3e7e
#include <pwd.h>
Packit 9c3e7e
#include <stdarg.h>
Packit 9c3e7e
#include <signal.h>
Packit 9c3e7e
#include <ifaddrs.h>
Packit 9c3e7e
#include <linux/types.h>
Packit 9c3e7e
#include <linux/ethtool.h>
Packit 9c3e7e
#include <linux/sockios.h>
Packit 9c3e7e
#ifdef SO_TIMESTAMPING
Packit 9c3e7e
#include <linux/ptp_clock.h>
Packit 9c3e7e
#include <linux/net_tstamp.h>
Packit 9c3e7e
#endif
Packit 9c3e7e
Packit 9c3e7e
#include "protocol.h"
Packit 9c3e7e
Packit 9c3e7e
#include "client_fuzz.c"
Packit 9c3e7e
Packit 9c3e7e
/* first node in first subnet is 192.168.123.1 */
Packit 9c3e7e
#define BASE_ADDR 0xc0a87b00
Packit 9c3e7e
#define NETMASK 0xffffff00
Packit 9c3e7e
#define NODE_ADDR(subnet, node) (BASE_ADDR + 0x100 * (subnet) + (node) + 1)
Packit 9c3e7e
#define BROADCAST_ADDR(subnet) (NODE_ADDR(subnet, 0) | 0xff)
Packit 9c3e7e
#define NODE_FROM_ADDR(addr) (((addr) & ~NETMASK) - 1)
Packit 9c3e7e
#define SUBNET_FROM_ADDR(addr) ((((addr) & NETMASK) - BASE_ADDR) / 0x100)
Packit 9c3e7e
Packit 9c3e7e
#define PTP_PRIMARY_MCAST_ADDR 0xe0000181 /* 224.0.1.129 */
Packit 9c3e7e
#define PTP_PDELAY_MCAST_ADDR 0xe000006b /* 224.0.0.107 */
Packit 9c3e7e
Packit 9c3e7e
#define REFCLK_FD 1000
Packit 9c3e7e
#define REFCLK_ID ((~(clockid_t)REFCLK_FD << 3) | 3)
Packit 9c3e7e
#define REFCLK_PHC_INDEX 0
Packit 9c3e7e
#define SYSCLK_FD 1001
Packit 9c3e7e
#define SYSCLK_CLOCKID ((~(clockid_t)SYSCLK_FD << 3) | 3)
Packit 9c3e7e
#define SYSCLK_PHC_INDEX 1
Packit 9c3e7e
Packit 9c3e7e
#define MAX_SOCKETS 20
Packit 9c3e7e
#define BASE_SOCKET_FD 100
Packit 9c3e7e
#define BASE_SOCKET_DEFAULT_PORT 60000
Packit 9c3e7e
Packit 9c3e7e
#define MAX_TIMERS 40
Packit 9c3e7e
#define BASE_TIMER_ID 0xC1230123
Packit 9c3e7e
#define BASE_TIMER_FD 200
Packit 9c3e7e
Packit 9c3e7e
#define URANDOM_FILE (void *)0xD1230123
Packit 9c3e7e
Packit 9c3e7e
static FILE *(*_fopen)(const char *path, const char *mode);
Packit 9c3e7e
static size_t (*_fread)(void *ptr, size_t size, size_t nmemb, FILE *stream);
Packit 9c3e7e
static int (*_fileno)(FILE *stream);
Packit 9c3e7e
static int (*_fclose)(FILE *fp);
Packit 9c3e7e
static int (*_open)(const char *pathname, int flags);
Packit 9c3e7e
static int (*_close)(int fd);
Packit 9c3e7e
static int (*_socket)(int domain, int type, int protocol);
Packit 9c3e7e
static int (*_connect)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
Packit 9c3e7e
static ssize_t (*_recvmsg)(int sockfd, struct msghdr *msg, int flags);
Packit 9c3e7e
static ssize_t (*_send)(int sockfd, const void *buf, size_t len, int flags);
Packit 9c3e7e
static int (*_usleep)(useconds_t usec);
Packit 9c3e7e
static void (*_srandom)(unsigned int seed);
Packit 9c3e7e
static int (*_shmget)(key_t key, size_t size, int shmflg);
Packit 9c3e7e
static void *(*_shmat)(int shmid, const void *shmaddr, int shmflg);
Packit 9c3e7e
Packit 9c3e7e
static unsigned int node;
Packit 9c3e7e
static int initialized = 0;
Packit 9c3e7e
static int clknetsim_fd;
Packit 9c3e7e
static int precision_hack = 1;
Packit 9c3e7e
static unsigned int random_seed = 0;
Packit 9c3e7e
static int recv_multiply = 1;
Packit 9c3e7e
static int timestamping = 1;
Packit 9c3e7e
Packit 9c3e7e
enum {
Packit 9c3e7e
	IFACE_NONE = 0,
Packit 9c3e7e
	IFACE_LO,
Packit 9c3e7e
	IFACE_ALL,
Packit 9c3e7e
	IFACE_ETH0,
Packit 9c3e7e
};
Packit 9c3e7e
Packit 9c3e7e
struct ts_message {
Packit 9c3e7e
	char data[MAX_PACKET_SIZE];
Packit 9c3e7e
	unsigned int len;
Packit 9c3e7e
	unsigned int subnet;
Packit 9c3e7e
	unsigned int to;
Packit 9c3e7e
	unsigned int port;
Packit 9c3e7e
};
Packit 9c3e7e
Packit 9c3e7e
struct socket {
Packit 9c3e7e
	int used;
Packit 9c3e7e
	int type;
Packit 9c3e7e
	int port;
Packit 9c3e7e
	int iface;
Packit 9c3e7e
	int remote_node;
Packit 9c3e7e
	int remote_port;
Packit 9c3e7e
	int broadcast;
Packit 9c3e7e
	int pkt_info;
Packit 9c3e7e
	int time_stamping;
Packit 9c3e7e
	struct ts_message last_ts_msg;
Packit 9c3e7e
};
Packit 9c3e7e
Packit 9c3e7e
static struct socket sockets[MAX_SOCKETS];
Packit 9c3e7e
static int subnets;
Packit 9c3e7e
Packit 9c3e7e
static double real_time = 0.0;
Packit 9c3e7e
static double monotonic_time = 0.0;
Packit 9c3e7e
static double network_time = 0.0;
Packit 9c3e7e
static int local_time_valid = 0;
Packit 9c3e7e
Packit 9c3e7e
static time_t system_time_offset = 1262304000; /* 2010-01-01 0:00 UTC */
Packit 9c3e7e
Packit 9c3e7e
#define TIMER_TYPE_SIGNAL 1
Packit 9c3e7e
#define TIMER_TYPE_FD 2
Packit 9c3e7e
Packit 9c3e7e
struct timer {
Packit 9c3e7e
	int used;
Packit 9c3e7e
	int armed;
Packit 9c3e7e
	int type;
Packit 9c3e7e
	clockid_t clock_id;
Packit 9c3e7e
	double timeout;
Packit 9c3e7e
	double interval;
Packit 9c3e7e
};
Packit 9c3e7e
Packit 9c3e7e
static struct timer timers[MAX_TIMERS];
Packit 9c3e7e
Packit 9c3e7e
static timer_t itimer_real_id;
Packit 9c3e7e
Packit 9c3e7e
#define SHM_KEY 0x4e545030
Packit 9c3e7e
#define SHM_REFCLOCKS 4
Packit 9c3e7e
Packit 9c3e7e
static struct shmTime {
Packit 9c3e7e
  int    mode;
Packit 9c3e7e
  int    count;
Packit 9c3e7e
  time_t clockTimeStampSec;
Packit 9c3e7e
  int    clockTimeStampUSec;
Packit 9c3e7e
  time_t receiveTimeStampSec;
Packit 9c3e7e
  int    receiveTimeStampUSec;
Packit 9c3e7e
  int    leap;
Packit 9c3e7e
  int    precision;
Packit 9c3e7e
  int    nsamples;
Packit 9c3e7e
  int    valid;
Packit 9c3e7e
  int    clockTimeStampNSec;
Packit 9c3e7e
  int    receiveTimeStampNSec;
Packit 9c3e7e
  int    dummy[8]; 
Packit 9c3e7e
} shm_time[SHM_REFCLOCKS];
Packit 9c3e7e
Packit 9c3e7e
static int shm_refclocks = 0;
Packit 9c3e7e
static double shm_refclock_time = 0.0;
Packit 9c3e7e
static struct Reply_getrefoffsets refclock_offsets;
Packit 9c3e7e
static int refclock_offsets_used = REPLY_GETREFOFFSETS_SIZE;
Packit 9c3e7e
Packit 9c3e7e
static void make_request(int request_id, const void *request_data, int reqlen, void *reply, int replylen);
Packit 9c3e7e
Packit 9c3e7e
__attribute__((constructor))
Packit 9c3e7e
static void init(void) {
Packit 9c3e7e
	struct Request_register req;
Packit 9c3e7e
	struct Reply_register rep;
Packit 9c3e7e
	struct sockaddr_un s = {AF_UNIX, "clknetsim.sock"};
Packit 9c3e7e
	const char *env;
Packit 9c3e7e
	unsigned int connect_retries = 100; /* 10 seconds */
Packit 9c3e7e
Packit 9c3e7e
	if (initialized)
Packit 9c3e7e
		return;
Packit 9c3e7e
Packit 9c3e7e
	_fopen = (FILE *(*)(const char *path, const char *mode))dlsym(RTLD_NEXT, "fopen");
Packit 9c3e7e
	_fread = (size_t (*)(void *ptr, size_t size, size_t nmemb, FILE *stream))dlsym(RTLD_NEXT, "fread");
Packit 9c3e7e
	_fileno = (int (*)(FILE *stream))dlsym(RTLD_NEXT, "fileno");
Packit 9c3e7e
	_fclose = (int (*)(FILE *fp))dlsym(RTLD_NEXT, "fclose");
Packit 9c3e7e
	_open = (int (*)(const char *pathname, int flags))dlsym(RTLD_NEXT, "open");
Packit 9c3e7e
	_close = (int (*)(int fd))dlsym(RTLD_NEXT, "close");
Packit 9c3e7e
	_socket = (int (*)(int domain, int type, int protocol))dlsym(RTLD_NEXT, "socket");
Packit 9c3e7e
	_connect = (int (*)(int sockfd, const struct sockaddr *addr, socklen_t addrlen))dlsym(RTLD_NEXT, "connect");
Packit 9c3e7e
	_recvmsg = (ssize_t (*)(int sockfd, struct msghdr *msg, int flags))dlsym(RTLD_NEXT, "recvmsg");
Packit 9c3e7e
	_send = (ssize_t (*)(int sockfd, const void *buf, size_t len, int flags))dlsym(RTLD_NEXT, "send");
Packit 9c3e7e
	_usleep = (int (*)(useconds_t usec))dlsym(RTLD_NEXT, "usleep");
Packit 9c3e7e
	_srandom = (void (*)(unsigned int seed))dlsym(RTLD_NEXT, "srandom");
Packit 9c3e7e
	_shmget = (int (*)(key_t key, size_t size, int shmflg))dlsym(RTLD_NEXT, "shmget");
Packit 9c3e7e
	_shmat = (void *(*)(int shmid, const void *shmaddr, int shmflg))dlsym(RTLD_NEXT, "shmat");
Packit 9c3e7e
Packit 9c3e7e
	env = getenv("CLKNETSIM_START_DATE");
Packit 9c3e7e
	if (env)
Packit 9c3e7e
		system_time_offset = atol(env);
Packit 9c3e7e
Packit 9c3e7e
	env = getenv("CLKNETSIM_RANDOM_SEED");
Packit 9c3e7e
	if (env)
Packit 9c3e7e
		random_seed = atoi(env);
Packit 9c3e7e
Packit 9c3e7e
	env = getenv("CLKNETSIM_RECV_MULTIPLY");
Packit 9c3e7e
	if (env)
Packit 9c3e7e
		recv_multiply = atoi(env);
Packit 9c3e7e
Packit 9c3e7e
	env = getenv("CLKNETSIM_TIMESTAMPING");
Packit 9c3e7e
	if (env)
Packit 9c3e7e
		timestamping = atoi(env);
Packit 9c3e7e
Packit 9c3e7e
	if (fuzz_init()) {
Packit 9c3e7e
		node = 0;
Packit 9c3e7e
		subnets = 1;
Packit 9c3e7e
		initialized = 1;
Packit 9c3e7e
		return;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	env = getenv("CLKNETSIM_NODE");
Packit 9c3e7e
	if (!env) {
Packit 9c3e7e
		fprintf(stderr, "clknetsim: CLKNETSIM_NODE variable not set.\n");
Packit 9c3e7e
		exit(1);
Packit 9c3e7e
	}
Packit 9c3e7e
	node = atoi(env) - 1;
Packit 9c3e7e
Packit 9c3e7e
	env = getenv("CLKNETSIM_SOCKET");
Packit 9c3e7e
	if (env)
Packit 9c3e7e
		snprintf(s.sun_path, sizeof (s.sun_path), "%s", env);
Packit 9c3e7e
Packit 9c3e7e
	env = getenv("CLKNETSIM_CONNECT_TIMEOUT");
Packit 9c3e7e
	if (env)
Packit 9c3e7e
		connect_retries = 10 * atoi(env);
Packit 9c3e7e
Packit 9c3e7e
	clknetsim_fd = _socket(AF_UNIX, SOCK_SEQPACKET, 0);
Packit 9c3e7e
Packit 9c3e7e
	assert(clknetsim_fd >= 0);
Packit 9c3e7e
Packit 9c3e7e
	while (_connect(clknetsim_fd, (struct sockaddr *)&s, sizeof (s)) < 0) {
Packit 9c3e7e
		if (!--connect_retries) {
Packit 9c3e7e
			fprintf(stderr, "clknetsim: could not connect to server.\n");
Packit 9c3e7e
			exit(1);
Packit 9c3e7e
		}
Packit 9c3e7e
		_usleep(100000);
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	/* this requires the node variable to be already set */
Packit 9c3e7e
	srandom(0);
Packit 9c3e7e
Packit 9c3e7e
	initialized = 1;
Packit 9c3e7e
Packit 9c3e7e
	req.node = node;
Packit 9c3e7e
	make_request(REQ_REGISTER, &req, sizeof (req), &rep, sizeof (rep));
Packit 9c3e7e
Packit 9c3e7e
	subnets = rep.subnets;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
__attribute__((destructor))
Packit 9c3e7e
static void fini(void) {
Packit 9c3e7e
	if (initialized)
Packit 9c3e7e
		make_request(REQ_DEREGISTER, NULL, 0, NULL, 0);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static void make_request(int request_id, const void *request_data, int reqlen, void *reply, int replylen) {
Packit 9c3e7e
	struct Request_packet request;
Packit 9c3e7e
	int sent, received = 0;
Packit 9c3e7e
Packit 9c3e7e
	assert(initialized);
Packit 9c3e7e
Packit 9c3e7e
	if (fuzz_mode) {
Packit 9c3e7e
		fuzz_process_reply(request_id, request_data, reply, replylen);
Packit 9c3e7e
		return;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	request.header.request = request_id;
Packit 9c3e7e
	request.header._pad = 0;
Packit 9c3e7e
Packit 9c3e7e
	assert(offsetof(struct Request_packet, data) + reqlen <= sizeof (request));
Packit 9c3e7e
Packit 9c3e7e
	if (request_data)
Packit 9c3e7e
		memcpy(&request.data, request_data, reqlen);
Packit 9c3e7e
	reqlen += offsetof(struct Request_packet, data);
Packit 9c3e7e
Packit 9c3e7e
	if ((sent = _send(clknetsim_fd, &request, reqlen, 0)) <= 0 ||
Packit 9c3e7e
			(reply && (received = recv(clknetsim_fd, reply, replylen, 0)) <= 0)) {
Packit 9c3e7e
		fprintf(stderr, "clknetsim: server connection closed.\n");
Packit 9c3e7e
		initialized = 0;
Packit 9c3e7e
		exit(1);
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	assert(sent == reqlen);
Packit 9c3e7e
Packit 9c3e7e
	if (!reply)
Packit 9c3e7e
		return;
Packit 9c3e7e
Packit 9c3e7e
	/* check reply length */
Packit 9c3e7e
	switch (request_id) {
Packit 9c3e7e
		case REQ_RECV:
Packit 9c3e7e
			/* reply with variable length */
Packit 9c3e7e
			assert(received >= offsetof(struct Reply_recv, data));
Packit 9c3e7e
			assert(offsetof(struct Reply_recv, data) +
Packit 9c3e7e
				((struct Reply_recv *)reply)->len <= received);
Packit 9c3e7e
			break;
Packit 9c3e7e
		default:
Packit 9c3e7e
			assert(received == replylen);
Packit 9c3e7e
	}
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static void fetch_time(void) {
Packit 9c3e7e
	struct Reply_gettime r;
Packit 9c3e7e
Packit 9c3e7e
	if (!local_time_valid) {
Packit 9c3e7e
		make_request(REQ_GETTIME, NULL, 0, &r, sizeof (r));
Packit 9c3e7e
		real_time = r.real_time;
Packit 9c3e7e
		monotonic_time = r.monotonic_time;
Packit 9c3e7e
		network_time = r.network_time;
Packit 9c3e7e
		local_time_valid = 1;
Packit 9c3e7e
	}
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static double get_real_time(void) {
Packit 9c3e7e
	fetch_time();
Packit 9c3e7e
	return real_time;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static double get_monotonic_time(void) {
Packit 9c3e7e
	fetch_time();
Packit 9c3e7e
	return monotonic_time;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static double get_refclock_offset(void) {
Packit 9c3e7e
	if (refclock_offsets_used >= REPLY_GETREFOFFSETS_SIZE) {
Packit 9c3e7e
		make_request(REQ_GETREFOFFSETS, NULL, 0, &refclock_offsets, sizeof (refclock_offsets));
Packit 9c3e7e
		refclock_offsets_used = 0;
Packit 9c3e7e
	}
Packit 9c3e7e
	return refclock_offsets.offsets[refclock_offsets_used++];
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static double get_refclock_time(void) {
Packit 9c3e7e
	fetch_time();
Packit 9c3e7e
	return network_time - get_refclock_offset();
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static void settime(double time) {
Packit 9c3e7e
	struct Request_settime req;
Packit 9c3e7e
Packit 9c3e7e
	req.time = time;
Packit 9c3e7e
	make_request(REQ_SETTIME, &req, sizeof (req), NULL, 0);
Packit 9c3e7e
Packit 9c3e7e
	local_time_valid = 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static void fill_refclock_sample(void) {
Packit 9c3e7e
	struct Reply_getrefsample r;
Packit 9c3e7e
	double clock_time, receive_time, round_corr;
Packit 9c3e7e
	int i;
Packit 9c3e7e
Packit 9c3e7e
	if (!shm_refclocks)
Packit 9c3e7e
		return;
Packit 9c3e7e
Packit 9c3e7e
	make_request(REQ_GETREFSAMPLE, NULL, 0, &r, sizeof (r));
Packit 9c3e7e
Packit 9c3e7e
	if (r.time == shm_refclock_time || !r.valid)
Packit 9c3e7e
		return;
Packit 9c3e7e
	shm_refclock_time = r.time;
Packit 9c3e7e
Packit 9c3e7e
	for (i = 0; i < shm_refclocks; i++) {
Packit 9c3e7e
		if (shm_refclocks == 1) {
Packit 9c3e7e
			clock_time = r.time - r.offset;
Packit 9c3e7e
			receive_time = r.time;
Packit 9c3e7e
		} else {
Packit 9c3e7e
			clock_time = get_refclock_time();
Packit 9c3e7e
			receive_time = get_real_time();
Packit 9c3e7e
		}
Packit 9c3e7e
Packit 9c3e7e
		round_corr = (clock_time * 1e6 - floor(clock_time * 1e6) + 0.5) / 1e6;
Packit 9c3e7e
		clock_time -= round_corr;
Packit 9c3e7e
		receive_time -= round_corr;
Packit 9c3e7e
Packit 9c3e7e
		shm_time[i].count++;
Packit 9c3e7e
		shm_time[i].clockTimeStampSec = floor(clock_time);
Packit 9c3e7e
		shm_time[i].clockTimeStampUSec = (clock_time - shm_time[i].clockTimeStampSec) * 1e6;
Packit 9c3e7e
		shm_time[i].clockTimeStampNSec = (clock_time - shm_time[i].clockTimeStampSec) * 1e9;
Packit 9c3e7e
		shm_time[i].clockTimeStampSec += system_time_offset;
Packit 9c3e7e
		shm_time[i].receiveTimeStampSec = floor(receive_time);
Packit 9c3e7e
		shm_time[i].receiveTimeStampUSec = (receive_time - shm_time[i].receiveTimeStampSec) * 1e6;
Packit 9c3e7e
		shm_time[i].receiveTimeStampNSec = (receive_time - shm_time[i].receiveTimeStampSec) * 1e9;
Packit 9c3e7e
		shm_time[i].receiveTimeStampSec += system_time_offset;
Packit 9c3e7e
		shm_time[i].leap = 0;
Packit 9c3e7e
		shm_time[i].valid = 1;
Packit 9c3e7e
	}
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static int socket_in_subnet(int socket, int subnet) {
Packit 9c3e7e
	switch (sockets[socket].iface) {
Packit 9c3e7e
		case IFACE_LO:
Packit 9c3e7e
			return 0;
Packit 9c3e7e
		case IFACE_NONE:
Packit 9c3e7e
		case IFACE_ALL:
Packit 9c3e7e
			return 1;
Packit 9c3e7e
		default:
Packit 9c3e7e
			return sockets[socket].iface - IFACE_ETH0 == subnet;
Packit 9c3e7e
	}
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static void get_target(int socket, uint32_t addr, unsigned int *subnet, unsigned int *node) {
Packit 9c3e7e
	if (addr == PTP_PRIMARY_MCAST_ADDR || addr == PTP_PDELAY_MCAST_ADDR) {
Packit 9c3e7e
		assert(sockets[socket].iface >= IFACE_ETH0);
Packit 9c3e7e
		*subnet = sockets[socket].iface - IFACE_ETH0;
Packit 9c3e7e
		*node = -1; /* multicast as broadcast */
Packit 9c3e7e
	} else {
Packit 9c3e7e
		*subnet = SUBNET_FROM_ADDR(addr);
Packit 9c3e7e
		assert(*subnet >= 0 && *subnet < subnets);
Packit 9c3e7e
		assert(socket_in_subnet(socket, *subnet));
Packit 9c3e7e
Packit 9c3e7e
		if (addr == BROADCAST_ADDR(*subnet))
Packit 9c3e7e
			*node = -1; /* broadcast */
Packit 9c3e7e
		else
Packit 9c3e7e
			*node = NODE_FROM_ADDR(addr);
Packit 9c3e7e
	}
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static int get_network_from_iface(const char *iface) {
Packit 9c3e7e
	if (strncmp(iface, "eth", 3))
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	return atoi(iface + 3);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static int get_free_socket(void) {
Packit 9c3e7e
	int i;
Packit 9c3e7e
Packit 9c3e7e
	for (i = 0; i < MAX_SOCKETS; i++) {
Packit 9c3e7e
		if (!sockets[i].used)
Packit 9c3e7e
			return i;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	return -1;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static int get_socket_from_fd(int fd) {
Packit 9c3e7e
	int s = fd - BASE_SOCKET_FD;
Packit 9c3e7e
Packit 9c3e7e
	if (s >= 0 && s < MAX_SOCKETS && sockets[s].used)
Packit 9c3e7e
		return s;
Packit 9c3e7e
	return -1;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static int get_socket_fd(int s) {
Packit 9c3e7e
	return s + BASE_SOCKET_FD;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static int find_recv_socket(int subnet, int port, int broadcast) {
Packit 9c3e7e
	int i, s = -1;
Packit 9c3e7e
Packit 9c3e7e
	for (i = 0; i < MAX_SOCKETS; i++) {
Packit 9c3e7e
		if (!sockets[i].used ||
Packit 9c3e7e
				!socket_in_subnet(i, subnet) ||
Packit 9c3e7e
				sockets[i].type != SOCK_DGRAM ||
Packit 9c3e7e
				(port && sockets[i].port != port))
Packit 9c3e7e
			continue;
Packit 9c3e7e
		if (s < 0 || sockets[s].iface < sockets[i].iface ||
Packit 9c3e7e
				(broadcast && sockets[i].broadcast) ||
Packit 9c3e7e
				(!broadcast && sockets[s].broadcast &&
Packit 9c3e7e
				 !sockets[i].broadcast))
Packit 9c3e7e
			s = i;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	return s;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static int get_free_timer(void) {
Packit 9c3e7e
	int i;
Packit 9c3e7e
Packit 9c3e7e
	for (i = 0; i < MAX_TIMERS; i++) {
Packit 9c3e7e
		if (!timers[i].used)
Packit 9c3e7e
			return i;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	return -1;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static timer_t get_timerid(int timer) {
Packit 9c3e7e
	return (timer_t)((long)timer + BASE_TIMER_ID);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static int get_timer_from_id(timer_t timerid) {
Packit 9c3e7e
	int t = (long)timerid - BASE_TIMER_ID;
Packit 9c3e7e
Packit 9c3e7e
	if (t >= 0 && t < MAX_TIMERS && timers[t].used)
Packit 9c3e7e
		return t;
Packit 9c3e7e
	return -1;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static int get_timerfd(int timer) {
Packit 9c3e7e
	return timer + BASE_TIMER_FD;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static int get_timer_from_fd(int fd) {
Packit 9c3e7e
	int t = fd - BASE_TIMER_FD;
Packit 9c3e7e
Packit 9c3e7e
	if (t >= 0 && t < MAX_TIMERS && timers[t].used)
Packit 9c3e7e
		return t;
Packit 9c3e7e
	return -1;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static int get_first_timer(fd_set *timerfds) {
Packit 9c3e7e
	int i, r = -1;
Packit 9c3e7e
Packit 9c3e7e
	for (i = 0; i < MAX_TIMERS; i++) {
Packit 9c3e7e
		if (!timers[i].used || !timers[i].armed)
Packit 9c3e7e
			continue;
Packit 9c3e7e
		if (timers[i].type == TIMER_TYPE_FD &&
Packit 9c3e7e
				!(timerfds && FD_ISSET(get_timerfd(i), timerfds)))
Packit 9c3e7e
			continue;
Packit 9c3e7e
		if (r < 0 || timers[r].timeout > timers[i].timeout)
Packit 9c3e7e
			r = i;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	return r;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static void rearm_timer(int timer)
Packit 9c3e7e
{
Packit 9c3e7e
	assert(timers[timer].armed);
Packit 9c3e7e
	if (timers[timer].interval > 0.0)
Packit 9c3e7e
		timers[timer].timeout += timers[timer].interval;
Packit 9c3e7e
	else
Packit 9c3e7e
		timers[timer].armed = 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static void time_to_timeval(double d, struct timeval *tv) {
Packit 9c3e7e
	tv->tv_sec = floor(d);
Packit 9c3e7e
	tv->tv_usec = (d - tv->tv_sec) * 1e6;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static void time_to_timespec(double d, struct timespec *tp) {
Packit 9c3e7e
	tp->tv_sec = floor(d);
Packit 9c3e7e
	tp->tv_nsec = (d - tp->tv_sec) * 1e9;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static double timeval_to_time(const struct timeval *tv, time_t offset) {
Packit 9c3e7e
	return tv->tv_sec + offset + tv->tv_usec / 1e6;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static double timespec_to_time(const struct timespec *tp, time_t offset) {
Packit 9c3e7e
	return tp->tv_sec + offset + tp->tv_nsec / 1e9;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int gettimeofday(struct timeval *tv, struct timezone *tz) {
Packit 9c3e7e
	double time;
Packit 9c3e7e
Packit 9c3e7e
	time = get_real_time() + 0.5e-6;
Packit 9c3e7e
Packit 9c3e7e
	time_to_timeval(time, tv);
Packit 9c3e7e
	tv->tv_sec += system_time_offset;
Packit 9c3e7e
Packit 9c3e7e
	/* chrony clock precision routine hack */
Packit 9c3e7e
	if (precision_hack)
Packit 9c3e7e
		tv->tv_usec += random() % 2;
Packit 9c3e7e
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int clock_gettime(clockid_t which_clock, struct timespec *tp) {
Packit 9c3e7e
	double time;
Packit 9c3e7e
Packit 9c3e7e
	switch (which_clock) {
Packit 9c3e7e
		case CLOCK_REALTIME:
Packit 9c3e7e
		case SYSCLK_CLOCKID:
Packit 9c3e7e
			time = get_real_time();
Packit 9c3e7e
			break;
Packit 9c3e7e
		case CLOCK_MONOTONIC:
Packit 9c3e7e
			time = get_monotonic_time();
Packit 9c3e7e
			break;
Packit 9c3e7e
		case REFCLK_ID:
Packit 9c3e7e
			time = get_refclock_time();
Packit 9c3e7e
			break;
Packit 9c3e7e
		default:
Packit 9c3e7e
			assert(0);
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	time += 0.5e-9;
Packit 9c3e7e
	time_to_timespec(time, tp);
Packit 9c3e7e
	
Packit 9c3e7e
	if (which_clock == CLOCK_REALTIME || which_clock == REFCLK_ID)
Packit 9c3e7e
		tp->tv_sec += system_time_offset;
Packit 9c3e7e
Packit 9c3e7e
	/* ntpd clock precision routine hack */
Packit 9c3e7e
	if (precision_hack) {
Packit 9c3e7e
		static int x = 0;
Packit 9c3e7e
		tp->tv_nsec += x++ * 101;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
time_t time(time_t *t) {
Packit 9c3e7e
	time_t time;
Packit 9c3e7e
Packit 9c3e7e
	time = floor(get_real_time());
Packit 9c3e7e
	time += system_time_offset;
Packit 9c3e7e
	if (t)
Packit 9c3e7e
		*t = time;
Packit 9c3e7e
	return time;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int settimeofday(const struct timeval *tv, const struct timezone *tz) {
Packit 9c3e7e
	assert(tv);
Packit 9c3e7e
	settime(timeval_to_time(tv, -system_time_offset));
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int clock_settime(clockid_t which_clock, const struct timespec *tp) {
Packit 9c3e7e
	assert(tp && which_clock == CLOCK_REALTIME);
Packit 9c3e7e
	settime(timespec_to_time(tp, -system_time_offset));
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int adjtimex(struct timex *buf) {
Packit 9c3e7e
	struct Request_adjtimex req;
Packit 9c3e7e
	struct Reply_adjtimex rep;
Packit 9c3e7e
Packit 9c3e7e
	if (buf->modes & ADJ_SETOFFSET)
Packit 9c3e7e
		local_time_valid = 0;
Packit 9c3e7e
Packit 9c3e7e
	req.timex = *buf;
Packit 9c3e7e
	make_request(REQ_ADJTIMEX, &req, sizeof (req), &rep, sizeof (rep));
Packit 9c3e7e
	*buf = rep.timex;
Packit 9c3e7e
	
Packit 9c3e7e
	if (rep.ret < 0)
Packit 9c3e7e
		errno = EINVAL;
Packit 9c3e7e
Packit 9c3e7e
	return rep.ret;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int ntp_adjtime(struct timex *buf) {
Packit 9c3e7e
	return adjtimex(buf);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int clock_adjtime(clockid_t id, struct timex *tx) {
Packit 9c3e7e
	assert(id == CLOCK_REALTIME || id == SYSCLK_CLOCKID || id == REFCLK_ID);
Packit 9c3e7e
Packit 9c3e7e
	if (id == SYSCLK_CLOCKID) {
Packit 9c3e7e
		/* allow large frequency adjustment by setting ticks */
Packit 9c3e7e
Packit 9c3e7e
		long hz, base_tick, scaled_ppm_per_tick;
Packit 9c3e7e
		int r;
Packit 9c3e7e
Packit 9c3e7e
		hz = sysconf(_SC_CLK_TCK);
Packit 9c3e7e
		assert(hz > 0);
Packit 9c3e7e
		base_tick = (1000000 + hz / 2) / hz;
Packit 9c3e7e
		scaled_ppm_per_tick = 65536 * hz;
Packit 9c3e7e
Packit 9c3e7e
		if (tx->modes & ADJ_FREQUENCY && !(tx->modes & ADJ_TICK))
Packit 9c3e7e
			tx->tick = base_tick, tx->modes |= ADJ_TICK;
Packit 9c3e7e
Packit 9c3e7e
		tx->tick += tx->freq / scaled_ppm_per_tick;
Packit 9c3e7e
		tx->freq = tx->freq % scaled_ppm_per_tick;
Packit 9c3e7e
Packit 9c3e7e
		r = adjtimex(tx);
Packit 9c3e7e
Packit 9c3e7e
		tx->freq += (tx->tick - base_tick) * scaled_ppm_per_tick;
Packit 9c3e7e
		tx->tick = base_tick;
Packit 9c3e7e
Packit 9c3e7e
		return r;
Packit 9c3e7e
	} else if (id == REFCLK_ID) {
Packit 9c3e7e
		if (tx->modes) {
Packit 9c3e7e
			errno = EINVAL;
Packit 9c3e7e
			return -1;
Packit 9c3e7e
		}
Packit 9c3e7e
Packit 9c3e7e
		memset(tx, 0, sizeof (*tx));
Packit 9c3e7e
		return 0;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	return adjtimex(tx);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int adjtime(const struct timeval *delta, struct timeval *olddelta) {
Packit 9c3e7e
	struct Request_adjtime req;
Packit 9c3e7e
	struct Reply_adjtime rep;
Packit 9c3e7e
Packit 9c3e7e
	if (delta)
Packit 9c3e7e
		req.tv = *delta;
Packit 9c3e7e
	else
Packit 9c3e7e
		time_to_timeval(0.0, &req.tv);
Packit 9c3e7e
Packit 9c3e7e
	make_request(REQ_ADJTIME, &req, sizeof (req), &rep, sizeof (rep));
Packit 9c3e7e
	if (olddelta)
Packit 9c3e7e
		*olddelta = rep.tv;
Packit 9c3e7e
Packit 9c3e7e
	if (!delta) {
Packit 9c3e7e
		req.tv = rep.tv;
Packit 9c3e7e
		make_request(REQ_ADJTIME, &req, sizeof (req), &rep, sizeof (rep));
Packit 9c3e7e
	}
Packit 9c3e7e
	
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) {
Packit 9c3e7e
	struct Request_select req;
Packit 9c3e7e
	struct Reply_select rep;
Packit 9c3e7e
	int i, timer, s, recv_fd = -1;
Packit 9c3e7e
	double elapsed = 0.0;
Packit 9c3e7e
Packit 9c3e7e
	if (writefds)
Packit 9c3e7e
		FD_ZERO(writefds);
Packit 9c3e7e
Packit 9c3e7e
	if (exceptfds) {
Packit 9c3e7e
		/* chronyd waiting for TX timestamp from the error queue */
Packit 9c3e7e
		for (i = 0; i < nfds; i++) {
Packit 9c3e7e
			if (!FD_ISSET(i, exceptfds) || get_socket_from_fd(i) < 0 ||
Packit 9c3e7e
					!sockets[get_socket_from_fd(i)].last_ts_msg.len)
Packit 9c3e7e
				continue;
Packit 9c3e7e
			if (readfds)
Packit 9c3e7e
				FD_ZERO(readfds);
Packit 9c3e7e
			FD_ZERO(exceptfds);
Packit 9c3e7e
			FD_SET(i, exceptfds);
Packit 9c3e7e
			return 1;
Packit 9c3e7e
		}
Packit 9c3e7e
Packit 9c3e7e
		FD_ZERO(exceptfds);
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	req.read = 0;
Packit 9c3e7e
	req._pad = 0;
Packit 9c3e7e
Packit 9c3e7e
	/* unknown reading fds are always ready (e.g. chronyd waiting
Packit 9c3e7e
	   for name resolving notification, or OpenSSL waiting for
Packit 9c3e7e
	   /dev/urandom) */
Packit 9c3e7e
	if (readfds) {
Packit 9c3e7e
		for (i = 0; i < nfds; i++) {
Packit 9c3e7e
			if (!FD_ISSET(i, readfds))
Packit 9c3e7e
				continue;
Packit 9c3e7e
			if (get_socket_from_fd(i) < 0 &&
Packit 9c3e7e
					get_timer_from_fd(i) < 0) {
Packit 9c3e7e
				FD_ZERO(readfds);
Packit 9c3e7e
				FD_SET(i, readfds);
Packit 9c3e7e
				return 1;
Packit 9c3e7e
			}
Packit 9c3e7e
			req.read = 1;
Packit 9c3e7e
		}
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	timer = get_first_timer(readfds);
Packit 9c3e7e
Packit 9c3e7e
	assert((timeout && (timeout->tv_sec > 0 || timeout->tv_usec > 0)) ||
Packit 9c3e7e
			timer >= 0 || find_recv_socket(0, 0, 0) >= 0);
Packit 9c3e7e
Packit 9c3e7e
	fetch_time();
Packit 9c3e7e
Packit 9c3e7e
	if (timeout)
Packit 9c3e7e
		req.timeout = timeout->tv_sec + (timeout->tv_usec + 1) / 1e6;
Packit 9c3e7e
	else
Packit 9c3e7e
		req.timeout = 1e20;
Packit 9c3e7e
Packit 9c3e7e
try_again:
Packit 9c3e7e
	if (timer >= 0 && timers[timer].timeout <= monotonic_time) {
Packit 9c3e7e
		/* avoid unnecessary requests */
Packit 9c3e7e
		rep.ret = REPLY_SELECT_TIMEOUT;
Packit 9c3e7e
	} else {
Packit 9c3e7e
		if (timer >= 0 && monotonic_time + req.timeout > timers[timer].timeout)
Packit 9c3e7e
			req.timeout = timers[timer].timeout - monotonic_time;
Packit 9c3e7e
Packit 9c3e7e
		make_request(REQ_SELECT, &req, sizeof (req), &rep, sizeof (rep));
Packit 9c3e7e
Packit 9c3e7e
		elapsed += rep.time.monotonic_time - monotonic_time;
Packit 9c3e7e
		req.timeout -= rep.time.monotonic_time - monotonic_time;
Packit 9c3e7e
Packit 9c3e7e
		real_time = rep.time.real_time;
Packit 9c3e7e
		monotonic_time = rep.time.monotonic_time;
Packit 9c3e7e
		network_time = rep.time.network_time;
Packit 9c3e7e
		local_time_valid = 1;
Packit 9c3e7e
Packit 9c3e7e
		fill_refclock_sample();
Packit 9c3e7e
Packit 9c3e7e
		if (monotonic_time >= 0.1 || timer >= 0 || rep.ret != REPLY_SELECT_TIMEOUT)
Packit 9c3e7e
			precision_hack = 0;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	switch (rep.ret) {
Packit 9c3e7e
		case REPLY_SELECT_TERMINATE:
Packit 9c3e7e
			kill(getpid(), SIGTERM);
Packit 9c3e7e
			errno = EINTR;
Packit 9c3e7e
			return -1;
Packit 9c3e7e
Packit 9c3e7e
		case REPLY_SELECT_TIMEOUT:
Packit 9c3e7e
			if (timer >= 0 && monotonic_time >= timers[timer].timeout) {
Packit 9c3e7e
				rearm_timer(timer);
Packit 9c3e7e
				switch (timers[timer].type) {
Packit 9c3e7e
					case TIMER_TYPE_SIGNAL:
Packit 9c3e7e
						kill(getpid(), SIGALRM);
Packit 9c3e7e
						errno = EINTR;
Packit 9c3e7e
						return -1;
Packit 9c3e7e
					case TIMER_TYPE_FD:
Packit 9c3e7e
						recv_fd = get_timerfd(timer);
Packit 9c3e7e
						break;
Packit 9c3e7e
					default:
Packit 9c3e7e
						assert(0);
Packit 9c3e7e
				}
Packit 9c3e7e
			} else
Packit 9c3e7e
				recv_fd = 0;
Packit 9c3e7e
			break;
Packit 9c3e7e
Packit 9c3e7e
		case REPLY_SELECT_NORMAL:
Packit 9c3e7e
		case REPLY_SELECT_BROADCAST:
Packit 9c3e7e
			s = find_recv_socket(rep.subnet, rep.dst_port,
Packit 9c3e7e
					rep.ret == REPLY_SELECT_BROADCAST);
Packit 9c3e7e
			recv_fd = s >= 0 ? get_socket_fd(s) : 0;
Packit 9c3e7e
Packit 9c3e7e
			/* fetch and drop the packet if no fd is waiting for it */
Packit 9c3e7e
			if (!readfds || !recv_fd || !FD_ISSET(recv_fd, readfds)) {
Packit 9c3e7e
				struct Reply_recv recv_rep;
Packit 9c3e7e
Packit 9c3e7e
				make_request(REQ_RECV, NULL, 0, &recv_rep, sizeof (recv_rep));
Packit 9c3e7e
				if (rep.ret != REPLY_SELECT_BROADCAST)
Packit 9c3e7e
					fprintf(stderr, "clknetsim: dropped packet from "
Packit 9c3e7e
							"node %d on port %d in subnet %d\n",
Packit 9c3e7e
							recv_rep.from + 1, recv_rep.dst_port,
Packit 9c3e7e
							recv_rep.subnet + 1);
Packit 9c3e7e
Packit 9c3e7e
				goto try_again;
Packit 9c3e7e
			}
Packit 9c3e7e
			break;
Packit 9c3e7e
Packit 9c3e7e
		default:
Packit 9c3e7e
			assert(0);
Packit 9c3e7e
			return 0;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	assert(!recv_fd || (readfds && FD_ISSET(recv_fd, readfds)));
Packit 9c3e7e
	assert(!recv_fd || (recv_fd >= BASE_SOCKET_FD && recv_fd < BASE_SOCKET_FD + MAX_SOCKETS) ||
Packit 9c3e7e
			(recv_fd >= BASE_TIMER_FD && recv_fd < BASE_TIMER_FD + MAX_TIMERS));
Packit 9c3e7e
Packit 9c3e7e
	if (readfds) {
Packit 9c3e7e
		FD_ZERO(readfds);
Packit 9c3e7e
		if (recv_fd)
Packit 9c3e7e
			FD_SET(recv_fd, readfds);
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	if (timeout) {
Packit 9c3e7e
		time_to_timeval(timeval_to_time(timeout, 0) - elapsed, timeout);
Packit 9c3e7e
		if (timeout->tv_sec < 0) {
Packit 9c3e7e
			timeout->tv_sec = 0;
Packit 9c3e7e
			timeout->tv_usec = 0;
Packit 9c3e7e
		}
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	return recv_fd ? 1 : 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
#ifndef CLKNETSIM_DISABLE_POLL
Packit 9c3e7e
int poll(struct pollfd *fds, nfds_t nfds, int timeout) {
Packit 9c3e7e
	struct timeval tv, *ptv = NULL;
Packit 9c3e7e
	int r, maxfd = 0;
Packit 9c3e7e
	nfds_t i;
Packit 9c3e7e
	fd_set rfds;
Packit 9c3e7e
Packit 9c3e7e
	/* ptp4l waiting for tx SO_TIMESTAMPING */
Packit 9c3e7e
	if (nfds == 1 && fds[0].events != POLLOUT && get_socket_from_fd(fds[0].fd) >= 0 &&
Packit 9c3e7e
	    sockets[get_socket_from_fd(fds[0].fd)].time_stamping &
Packit 9c3e7e
	    (SOF_TIMESTAMPING_TX_SOFTWARE | SOF_TIMESTAMPING_TX_HARDWARE)) {
Packit 9c3e7e
		if (!fds[0].events) {
Packit 9c3e7e
			fds[0].revents = POLLERR;
Packit 9c3e7e
			return 1;
Packit 9c3e7e
		} else if (fds[0].events == POLLPRI) {
Packit 9c3e7e
			/* SO_SELECT_ERR_QUEUE option enabled */
Packit 9c3e7e
			fds[0].revents = POLLPRI;
Packit 9c3e7e
			return 1;
Packit 9c3e7e
		}
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	/* pmc waiting to send packet */
Packit 9c3e7e
	if (nfds == 2 && (fds[1].events & POLLOUT) && get_socket_from_fd(fds[1].fd) >= 0) {
Packit 9c3e7e
		fds[0].revents = 0;
Packit 9c3e7e
		fds[1].revents = POLLOUT;
Packit 9c3e7e
		return 1;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	FD_ZERO(&rfds);
Packit 9c3e7e
Packit 9c3e7e
	for (i = 0; i < nfds; i++)
Packit 9c3e7e
		if (fds[i].fd >= 0 && fds[i].events & POLLIN) {
Packit 9c3e7e
			FD_SET(fds[i].fd, &rfds);
Packit 9c3e7e
			if (maxfd < fds[i].fd)
Packit 9c3e7e
				maxfd = fds[i].fd;
Packit 9c3e7e
		}
Packit 9c3e7e
Packit 9c3e7e
	if (timeout >= 0) {
Packit 9c3e7e
		tv.tv_sec = timeout / 1000;
Packit 9c3e7e
		tv.tv_usec = (timeout % 1000) * 1000;
Packit 9c3e7e
		ptv = &tv;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	r = select(maxfd + 1, &rfds, NULL, NULL, ptv);
Packit 9c3e7e
Packit 9c3e7e
	for (i = 0; i < nfds; i++)
Packit 9c3e7e
		fds[i].revents = r > 0 && fds[i].fd >= 0 &&
Packit 9c3e7e
			FD_ISSET(fds[i].fd, &rfds) ? POLLIN : 0;
Packit 9c3e7e
Packit 9c3e7e
	return r;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int __poll_chk(struct pollfd *fds, nfds_t nfds, int timeout, size_t fdslen) {
Packit 9c3e7e
	return poll(fds, nfds, timeout);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
#endif
Packit 9c3e7e
Packit 9c3e7e
int usleep(useconds_t usec) {
Packit 9c3e7e
	struct timeval tv;
Packit 9c3e7e
	int r;
Packit 9c3e7e
Packit 9c3e7e
	tv.tv_sec = usec / 1000000;
Packit 9c3e7e
	tv.tv_usec = usec % 1000000;
Packit 9c3e7e
Packit 9c3e7e
	r = select(0, NULL, NULL, NULL, &tv;;
Packit 9c3e7e
	assert(r == 0);
Packit 9c3e7e
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int nanosleep(const struct timespec *req, struct timespec *rem) {
Packit 9c3e7e
	struct timeval tv;
Packit 9c3e7e
	int r;
Packit 9c3e7e
Packit 9c3e7e
	tv.tv_sec = req->tv_sec;
Packit 9c3e7e
	tv.tv_usec = req->tv_nsec / 1000 + 1;
Packit 9c3e7e
Packit 9c3e7e
	r = select(0, NULL, NULL, NULL, &tv;;
Packit 9c3e7e
	assert(r <= 0);
Packit 9c3e7e
Packit 9c3e7e
	if (r < 0) {
Packit 9c3e7e
		assert(!rem);
Packit 9c3e7e
		return r;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	if (rem)
Packit 9c3e7e
		rem->tv_sec = rem->tv_nsec = 0;
Packit 9c3e7e
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int clock_nanosleep(clockid_t clock_id, int flags,
Packit 9c3e7e
		const struct timespec *request,
Packit 9c3e7e
		struct timespec *remain) {
Packit 9c3e7e
	assert(clock_id == CLOCK_MONOTONIC || clock_id == CLOCK_REALTIME);
Packit 9c3e7e
	return nanosleep(request, remain);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
FILE *fopen(const char *path, const char *mode) {
Packit 9c3e7e
	if (!strcmp(path, "/proc/net/if_inet6")) {
Packit 9c3e7e
		errno = ENOENT;
Packit 9c3e7e
		return NULL;
Packit 9c3e7e
	} else if (!strcmp(path, "/dev/urandom")) {
Packit 9c3e7e
		return URANDOM_FILE;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	/* make sure _fopen is initialized in case it is called from another
Packit 9c3e7e
	   constructor (e.g. OpenSSL's libcrypto) */
Packit 9c3e7e
	init();
Packit 9c3e7e
Packit 9c3e7e
	return _fopen(path, mode);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) {
Packit 9c3e7e
	if (stream == URANDOM_FILE) {
Packit 9c3e7e
		size_t i, l = size * nmemb;
Packit 9c3e7e
		long r;
Packit 9c3e7e
Packit 9c3e7e
		assert(RAND_MAX >= 0xffffff);
Packit 9c3e7e
		for (i = r = 0; i < l; i++) {
Packit 9c3e7e
			if (i % 3)
Packit 9c3e7e
				r >>= 8;
Packit 9c3e7e
			else
Packit 9c3e7e
				r = random();
Packit 9c3e7e
			((unsigned char *)ptr)[i] = r;
Packit 9c3e7e
		}
Packit 9c3e7e
Packit 9c3e7e
		return nmemb;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	return _fread(ptr, size, nmemb, stream);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int fileno(FILE *stream) {
Packit 9c3e7e
	if (stream == URANDOM_FILE)
Packit 9c3e7e
		return -1;
Packit 9c3e7e
Packit 9c3e7e
	return _fileno(stream);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int fclose(FILE *fp) {
Packit 9c3e7e
	if (fp == URANDOM_FILE)
Packit 9c3e7e
		return 0;
Packit 9c3e7e
	return _fclose(fp);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int open(const char *pathname, int flags) {
Packit 9c3e7e
	int r;
Packit 9c3e7e
Packit 9c3e7e
	assert(REFCLK_PHC_INDEX == 0 && SYSCLK_PHC_INDEX == 1);
Packit 9c3e7e
	if (!strcmp(pathname, "/dev/ptp0"))
Packit 9c3e7e
		return REFCLK_FD;
Packit 9c3e7e
	else if (!strcmp(pathname, "/dev/ptp1"))
Packit 9c3e7e
		return SYSCLK_FD;
Packit 9c3e7e
Packit 9c3e7e
	r = _open(pathname, flags);
Packit 9c3e7e
	assert(r < 0 || (r < BASE_SOCKET_FD && r < BASE_TIMER_FD));
Packit 9c3e7e
Packit 9c3e7e
	return r;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int close(int fd) {
Packit 9c3e7e
	int t, s;
Packit 9c3e7e
Packit 9c3e7e
	if (fd == REFCLK_FD || fd == SYSCLK_FD) {
Packit 9c3e7e
		return 0;
Packit 9c3e7e
	} else if ((t = get_timer_from_fd(fd)) >= 0) {
Packit 9c3e7e
		return timer_delete(get_timerid(t));
Packit 9c3e7e
	} else if ((s = get_socket_from_fd(fd)) >= 0) {
Packit 9c3e7e
		sockets[s].used = 0;
Packit 9c3e7e
		return 0;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	return _close(fd);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int socket(int domain, int type, int protocol) {
Packit 9c3e7e
	int s;
Packit 9c3e7e
Packit 9c3e7e
	if (domain != AF_INET || (type != SOCK_DGRAM && type != SOCK_STREAM)) {
Packit 9c3e7e
		errno = EINVAL;
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	s = get_free_socket();
Packit 9c3e7e
	if (s < 0) {
Packit 9c3e7e
		assert(0);
Packit 9c3e7e
		errno = ENOMEM;
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	memset(sockets + s, 0, sizeof (struct socket));
Packit 9c3e7e
	sockets[s].used = 1;
Packit 9c3e7e
	sockets[s].type = type;
Packit 9c3e7e
	sockets[s].port = BASE_SOCKET_DEFAULT_PORT + s;
Packit 9c3e7e
	sockets[s].remote_node = -1;
Packit 9c3e7e
Packit 9c3e7e
	return get_socket_fd(s);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
Packit 9c3e7e
	/* ntpd uses connect() and getsockname() to find the interface
Packit 9c3e7e
	   which will be used to send packets to an address */
Packit 9c3e7e
	int s = get_socket_from_fd(sockfd), port;
Packit 9c3e7e
	unsigned int node, subnet;
Packit 9c3e7e
	uint32_t a;
Packit 9c3e7e
Packit 9c3e7e
	if (s < 0 || addr->sa_family != AF_INET) {
Packit 9c3e7e
		errno = EINVAL;
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	port = ntohs(((const struct sockaddr_in *)addr)->sin_port);
Packit 9c3e7e
	a = ntohl(((const struct sockaddr_in *)addr)->sin_addr.s_addr);
Packit 9c3e7e
Packit 9c3e7e
	get_target(s, a, &subnet, &node);
Packit 9c3e7e
Packit 9c3e7e
	sockets[s].iface = IFACE_ETH0 + subnet;
Packit 9c3e7e
	sockets[s].remote_node = node;
Packit 9c3e7e
	sockets[s].remote_port = port;
Packit 9c3e7e
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
Packit 9c3e7e
	int s = get_socket_from_fd(sockfd), port;
Packit 9c3e7e
	uint32_t a;
Packit 9c3e7e
Packit 9c3e7e
	if (s < 0 || addr->sa_family != AF_INET) {
Packit 9c3e7e
		errno = EINVAL;
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	port = ntohs(((struct sockaddr_in *)addr)->sin_port);
Packit 9c3e7e
	a = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
Packit 9c3e7e
Packit 9c3e7e
	if (port)
Packit 9c3e7e
		sockets[s].port = port;
Packit 9c3e7e
Packit 9c3e7e
	if (a == INADDR_ANY)
Packit 9c3e7e
		sockets[s].iface = IFACE_ALL;
Packit 9c3e7e
	else if (a == INADDR_LOOPBACK)
Packit 9c3e7e
		sockets[s].iface = IFACE_LO;
Packit 9c3e7e
	else {
Packit 9c3e7e
		int subnet = SUBNET_FROM_ADDR(a);
Packit 9c3e7e
		assert(subnet >= 0 && subnet < subnets);
Packit 9c3e7e
		if (a == NODE_ADDR(subnet, node))
Packit 9c3e7e
			sockets[s].iface = IFACE_ETH0 + subnet;
Packit 9c3e7e
		else if (a == BROADCAST_ADDR(subnet)) {
Packit 9c3e7e
			sockets[s].iface = IFACE_ETH0 + subnet;
Packit 9c3e7e
			sockets[s].broadcast = 1;
Packit 9c3e7e
		} else
Packit 9c3e7e
			assert(0);
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
Packit 9c3e7e
	int s = get_socket_from_fd(sockfd);
Packit 9c3e7e
	uint32_t a;
Packit 9c3e7e
Packit 9c3e7e
	if (s < 0) {
Packit 9c3e7e
		errno = EINVAL;
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	struct sockaddr_in *in;
Packit 9c3e7e
	in = (struct sockaddr_in *)addr;
Packit 9c3e7e
	assert(*addrlen >= sizeof (*in));
Packit 9c3e7e
	*addrlen = sizeof (*in);
Packit 9c3e7e
	in->sin_family = AF_INET;
Packit 9c3e7e
	in->sin_port = htons(sockets[s].port);
Packit 9c3e7e
Packit 9c3e7e
	switch (sockets[s].iface) {
Packit 9c3e7e
		case IFACE_NONE:
Packit 9c3e7e
		case IFACE_ALL:
Packit 9c3e7e
			a = INADDR_ANY;
Packit 9c3e7e
			break;
Packit 9c3e7e
		case IFACE_LO:
Packit 9c3e7e
			a = INADDR_LOOPBACK;
Packit 9c3e7e
			break;
Packit 9c3e7e
		default:
Packit 9c3e7e
			assert(sockets[s].iface - IFACE_ETH0 < subnets);
Packit 9c3e7e
			a = sockets[s].broadcast ?
Packit 9c3e7e
				BROADCAST_ADDR(sockets[s].iface - IFACE_ETH0) :
Packit 9c3e7e
				NODE_ADDR(sockets[s].iface - IFACE_ETH0, node);
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	in->sin_addr.s_addr = htonl(a);
Packit 9c3e7e
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) {
Packit 9c3e7e
	int subnet, s = get_socket_from_fd(sockfd);
Packit 9c3e7e
Packit 9c3e7e
	if (s < 0) {
Packit 9c3e7e
		errno = EINVAL;
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	if (level == SOL_SOCKET && optname == SO_BINDTODEVICE) {
Packit 9c3e7e
		if (!strcmp(optval, "lo"))
Packit 9c3e7e
			sockets[s].iface = IFACE_LO;
Packit 9c3e7e
		else if ((subnet = get_network_from_iface(optval)) >= 0)
Packit 9c3e7e
			sockets[s].iface = IFACE_ETH0 + subnet;
Packit 9c3e7e
		else {
Packit 9c3e7e
			errno = EINVAL;
Packit 9c3e7e
			return -1;
Packit 9c3e7e
		}
Packit 9c3e7e
	}
Packit 9c3e7e
	else if (level == IPPROTO_IP && optname == IP_PKTINFO && optlen == sizeof (int))
Packit 9c3e7e
		sockets[s].pkt_info = !!(int *)optval;
Packit 9c3e7e
#ifdef SO_TIMESTAMPING
Packit 9c3e7e
	else if (level == SOL_SOCKET && optname == SO_TIMESTAMPING && optlen == sizeof (int)) {
Packit 9c3e7e
		if (!timestamping) {
Packit 9c3e7e
			errno = EINVAL;
Packit 9c3e7e
			return -1;
Packit 9c3e7e
		}
Packit 9c3e7e
		sockets[s].time_stamping = *(int *)optval;
Packit 9c3e7e
	}
Packit 9c3e7e
#endif
Packit 9c3e7e
Packit 9c3e7e
	/* unhandled options succeed too */
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int fcntl(int fd, int cmd, ...) {
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int ioctl(int fd, unsigned long request, ...) {
Packit 9c3e7e
	va_list ap;
Packit 9c3e7e
	struct ifconf *conf;
Packit 9c3e7e
	struct ifreq *req;
Packit 9c3e7e
	int i, subnet, ret = 0, s = get_socket_from_fd(fd);
Packit 9c3e7e
Packit 9c3e7e
	va_start(ap, request);
Packit 9c3e7e
Packit 9c3e7e
	if (request == SIOCGIFCONF) {
Packit 9c3e7e
		conf = va_arg(ap, struct ifconf *);
Packit 9c3e7e
		assert(conf->ifc_len >= sizeof (struct ifreq) * (1 + subnets));
Packit 9c3e7e
		conf->ifc_len = sizeof (struct ifreq) * (1 + subnets);
Packit 9c3e7e
		sprintf(conf->ifc_req[0].ifr_name, "lo");
Packit 9c3e7e
		((struct sockaddr_in*)&conf->ifc_req[0].ifr_addr)->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
Packit 9c3e7e
		conf->ifc_req[0].ifr_addr.sa_family = AF_INET;
Packit 9c3e7e
Packit 9c3e7e
		for (i = 0; i < subnets; i++) {
Packit 9c3e7e
			sprintf(conf->ifc_req[i + 1].ifr_name, "eth%d", i);
Packit 9c3e7e
			((struct sockaddr_in*)&conf->ifc_req[i + 1].ifr_addr)->sin_addr.s_addr = htonl(NODE_ADDR(i, node));
Packit 9c3e7e
			conf->ifc_req[i + 1].ifr_addr.sa_family = AF_INET;
Packit 9c3e7e
		}
Packit 9c3e7e
	} else if (request == SIOCGIFINDEX) {
Packit 9c3e7e
		req = va_arg(ap, struct ifreq *);
Packit 9c3e7e
		if (!strcmp(req->ifr_name, "lo"))
Packit 9c3e7e
			req->ifr_ifindex = 0;
Packit 9c3e7e
		else if ((subnet = get_network_from_iface(req->ifr_name)) >= 0)
Packit 9c3e7e
			req->ifr_ifindex = subnet + 1;
Packit 9c3e7e
		else
Packit 9c3e7e
			ret = -1, errno = EINVAL;
Packit 9c3e7e
	} else if (request == SIOCGIFFLAGS) {
Packit 9c3e7e
		req = va_arg(ap, struct ifreq *);
Packit 9c3e7e
		if (!strcmp(req->ifr_name, "lo"))
Packit 9c3e7e
			req->ifr_flags = IFF_UP | IFF_LOOPBACK;
Packit 9c3e7e
		else if (get_network_from_iface(req->ifr_name) >= 0)
Packit 9c3e7e
			req->ifr_flags = IFF_UP | IFF_BROADCAST;
Packit 9c3e7e
		else
Packit 9c3e7e
			ret = -1, errno = EINVAL;
Packit 9c3e7e
	} else if (request == SIOCGIFBRDADDR) {
Packit 9c3e7e
		req = va_arg(ap, struct ifreq *);
Packit 9c3e7e
		if ((subnet = get_network_from_iface(req->ifr_name)) >= 0)
Packit 9c3e7e
			((struct sockaddr_in*)&req->ifr_broadaddr)->sin_addr.s_addr = htonl(BROADCAST_ADDR(subnet));
Packit 9c3e7e
		else
Packit 9c3e7e
			ret = -1, errno = EINVAL;
Packit 9c3e7e
		req->ifr_broadaddr.sa_family = AF_INET;
Packit 9c3e7e
	} else if (request == SIOCGIFNETMASK) {
Packit 9c3e7e
		req = va_arg(ap, struct ifreq *);
Packit 9c3e7e
		if (!strcmp(req->ifr_name, "lo"))
Packit 9c3e7e
			((struct sockaddr_in*)&req->ifr_netmask)->sin_addr.s_addr = htonl(0xff000000);
Packit 9c3e7e
		else if (get_network_from_iface(req->ifr_name) >= 0)
Packit 9c3e7e
			((struct sockaddr_in*)&req->ifr_netmask)->sin_addr.s_addr = htonl(NETMASK);
Packit 9c3e7e
		else
Packit 9c3e7e
			ret = -1, errno = EINVAL;
Packit 9c3e7e
		req->ifr_netmask.sa_family = AF_INET;
Packit 9c3e7e
	} else if (request == SIOCGIFHWADDR) {
Packit 9c3e7e
		req = va_arg(ap, struct ifreq *);
Packit 9c3e7e
		if (!strcmp(req->ifr_name, "lo"))
Packit 9c3e7e
			memset((&req->ifr_hwaddr)->sa_data, 0, IFHWADDRLEN);
Packit 9c3e7e
		else if ((subnet = get_network_from_iface(req->ifr_name)) >= 0) {
Packit 9c3e7e
			char mac[IFHWADDRLEN] = {0x12, 0x34, 0x56, 0x78, subnet + 1, node + 1};
Packit 9c3e7e
			memcpy((&req->ifr_hwaddr)->sa_data, mac, sizeof (mac));
Packit 9c3e7e
		} else
Packit 9c3e7e
			ret = -1, errno = EINVAL;
Packit 9c3e7e
		req->ifr_netmask.sa_family = AF_UNSPEC;
Packit 9c3e7e
#ifdef ETHTOOL_GET_TS_INFO
Packit 9c3e7e
	} else if (request == SIOCETHTOOL) {
Packit 9c3e7e
		struct ethtool_ts_info *info;
Packit 9c3e7e
		req = va_arg(ap, struct ifreq *);
Packit 9c3e7e
		info = (struct ethtool_ts_info *)req->ifr_data;
Packit 9c3e7e
		memset(info, 0, sizeof (*info));
Packit 9c3e7e
		if (get_network_from_iface(req->ifr_name) >= 0) {
Packit 9c3e7e
			info->phc_index = timestamping > 1 ? REFCLK_PHC_INDEX : SYSCLK_PHC_INDEX;
Packit 9c3e7e
			info->so_timestamping = SOF_TIMESTAMPING_SOFTWARE |
Packit 9c3e7e
				SOF_TIMESTAMPING_TX_SOFTWARE | SOF_TIMESTAMPING_RX_SOFTWARE |
Packit 9c3e7e
				SOF_TIMESTAMPING_RAW_HARDWARE |
Packit 9c3e7e
				SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE;
Packit 9c3e7e
			info->tx_types = HWTSTAMP_TX_ON;
Packit 9c3e7e
			info->rx_filters = 1 << HWTSTAMP_FILTER_NONE | 1 << HWTSTAMP_FILTER_ALL;
Packit 9c3e7e
		} else
Packit 9c3e7e
			ret = -1, errno = EINVAL;
Packit 9c3e7e
#endif
Packit 9c3e7e
#ifdef PTP_CLOCK_GETCAPS
Packit 9c3e7e
	} else if (request == PTP_CLOCK_GETCAPS && (fd == REFCLK_FD || fd == SYSCLK_FD)) {
Packit 9c3e7e
		struct ptp_clock_caps *caps = va_arg(ap, struct ptp_clock_caps *);
Packit 9c3e7e
		memset(caps, 0, sizeof (*caps));
Packit 9c3e7e
		/* maximum frequency in 32-bit timex.freq */
Packit 9c3e7e
		caps->max_adj = 32767999;
Packit 9c3e7e
#endif
Packit 9c3e7e
#ifdef PTP_SYS_OFFSET
Packit 9c3e7e
	} else if (request == PTP_SYS_OFFSET && fd == REFCLK_FD) {
Packit 9c3e7e
		struct ptp_sys_offset *sys_off = va_arg(ap, struct ptp_sys_offset *);
Packit 9c3e7e
		struct timespec ts;
Packit 9c3e7e
		int i;
Packit 9c3e7e
Packit 9c3e7e
		if (sys_off->n_samples > PTP_MAX_SAMPLES)
Packit 9c3e7e
			sys_off->n_samples = PTP_MAX_SAMPLES;
Packit 9c3e7e
Packit 9c3e7e
		clock_gettime(REFCLK_ID, &ts);
Packit 9c3e7e
		for (i = 0; i < sys_off->n_samples; i++) {
Packit 9c3e7e
			sys_off->ts[2 * i + 1].sec = ts.tv_sec;
Packit 9c3e7e
			sys_off->ts[2 * i + 1].nsec = ts.tv_nsec;
Packit 9c3e7e
		}
Packit 9c3e7e
Packit 9c3e7e
		clock_gettime(CLOCK_REALTIME, &ts);
Packit 9c3e7e
		for (i = 0; i < sys_off->n_samples + 1; i++) {
Packit 9c3e7e
			sys_off->ts[2 * i].sec = ts.tv_sec;
Packit 9c3e7e
			sys_off->ts[2 * i].nsec = ts.tv_nsec;
Packit 9c3e7e
		}
Packit 9c3e7e
#endif
Packit 9c3e7e
#ifdef PTP_SYS_OFFSET_PRECISE
Packit 9c3e7e
	} else if (request == PTP_SYS_OFFSET_PRECISE && fd == REFCLK_FD) {
Packit 9c3e7e
		struct ptp_sys_offset_precise *sys_off = va_arg(ap, struct ptp_sys_offset_precise *);
Packit 9c3e7e
		struct timespec ts;
Packit 9c3e7e
Packit 9c3e7e
		clock_gettime(REFCLK_ID, &ts);
Packit 9c3e7e
		sys_off->device.sec = ts.tv_sec;
Packit 9c3e7e
		sys_off->device.nsec = ts.tv_nsec;
Packit 9c3e7e
Packit 9c3e7e
		clock_gettime(CLOCK_REALTIME, &ts);
Packit 9c3e7e
		sys_off->sys_realtime.sec = ts.tv_sec;
Packit 9c3e7e
		sys_off->sys_realtime.nsec = ts.tv_nsec;
Packit 9c3e7e
#endif
Packit 9c3e7e
#ifdef SIOCSHWTSTAMP
Packit 9c3e7e
	} else if (request == SIOCSHWTSTAMP && s >= 0) {
Packit 9c3e7e
#endif
Packit 9c3e7e
	} else {
Packit 9c3e7e
		ret = -1;
Packit 9c3e7e
		errno = EINVAL;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	va_end(ap);
Packit 9c3e7e
	return ret;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int getifaddrs(struct ifaddrs **ifap) {
Packit 9c3e7e
	struct iface {
Packit 9c3e7e
		struct ifaddrs ifaddrs;
Packit 9c3e7e
		struct sockaddr_in addr, netmask, broadaddr;
Packit 9c3e7e
		char name[11];
Packit 9c3e7e
	} *ifaces;
Packit 9c3e7e
	int i;
Packit 9c3e7e
       
Packit 9c3e7e
	ifaces = malloc(sizeof (struct iface) * (1 + subnets));
Packit 9c3e7e
Packit 9c3e7e
	ifaces[0].ifaddrs = (struct ifaddrs){
Packit 9c3e7e
		.ifa_next = &ifaces[1].ifaddrs,
Packit 9c3e7e
		.ifa_name = "lo",
Packit 9c3e7e
		.ifa_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING,
Packit 9c3e7e
		.ifa_addr = (struct sockaddr *)&ifaces[0].addr,
Packit 9c3e7e
		.ifa_netmask = (struct sockaddr *)&ifaces[0].netmask,
Packit 9c3e7e
		.ifa_broadaddr = (struct sockaddr *)&ifaces[0].broadaddr
Packit 9c3e7e
	};
Packit 9c3e7e
	ifaces[0].addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
Packit 9c3e7e
	ifaces[0].netmask.sin_addr.s_addr = htonl(0xff000000);
Packit 9c3e7e
	ifaces[0].broadaddr.sin_addr.s_addr = 0;
Packit 9c3e7e
Packit 9c3e7e
	for (i = 0; i < subnets; i++) {
Packit 9c3e7e
		ifaces[i + 1].ifaddrs = (struct ifaddrs){
Packit 9c3e7e
			.ifa_next = &ifaces[i + 2].ifaddrs,
Packit 9c3e7e
			.ifa_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING,
Packit 9c3e7e
			.ifa_addr = (struct sockaddr *)&ifaces[i + 1].addr,
Packit 9c3e7e
			.ifa_netmask = (struct sockaddr *)&ifaces[i + 1].netmask,
Packit 9c3e7e
			.ifa_broadaddr = (struct sockaddr *)&ifaces[i + 1].broadaddr
Packit 9c3e7e
		};
Packit 9c3e7e
		ifaces[i + 1].ifaddrs.ifa_name = ifaces[i + 1].name;
Packit 9c3e7e
		snprintf(ifaces[i + 1].name, sizeof (ifaces[i + 1].name), "eth%d", i);
Packit 9c3e7e
		ifaces[i + 1].addr.sin_addr.s_addr = htonl(NODE_ADDR(i, node));
Packit 9c3e7e
		ifaces[i + 1].netmask.sin_addr.s_addr = htonl(NETMASK);
Packit 9c3e7e
		ifaces[i + 1].broadaddr.sin_addr.s_addr = htonl(BROADCAST_ADDR(i));
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	ifaces[i].ifaddrs.ifa_next = NULL;
Packit 9c3e7e
Packit 9c3e7e
	for (i = 0; i < 1 + subnets; i++) {
Packit 9c3e7e
		ifaces[i].addr.sin_family = AF_INET;
Packit 9c3e7e
		ifaces[i].netmask.sin_family = AF_INET;
Packit 9c3e7e
		ifaces[i].broadaddr.sin_family = AF_INET;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	*ifap = (struct ifaddrs *)ifaces;
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
void freeifaddrs(struct ifaddrs *ifa) {
Packit 9c3e7e
	free(ifa);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) {
Packit 9c3e7e
	struct Request_send req;
Packit 9c3e7e
	struct sockaddr_in connected_sa, *sa;
Packit 9c3e7e
	int s = get_socket_from_fd(sockfd);
Packit 9c3e7e
Packit 9c3e7e
	if (s < 0 || sockets[s].type != SOCK_DGRAM) {
Packit 9c3e7e
		assert(0);
Packit 9c3e7e
		errno = EINVAL;
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	if (sockets[s].remote_node >= 0) {
Packit 9c3e7e
		if (msg->msg_name) {
Packit 9c3e7e
			errno = EISCONN;
Packit 9c3e7e
			return -1;
Packit 9c3e7e
		}
Packit 9c3e7e
		sa = &connected_sa;
Packit 9c3e7e
		sa->sin_family = AF_INET;
Packit 9c3e7e
		sa->sin_port = htons(sockets[s].remote_port);
Packit 9c3e7e
		sa->sin_addr.s_addr = htonl(NODE_ADDR(sockets[s].iface - IFACE_ETH0,
Packit 9c3e7e
					sockets[s].remote_node));
Packit 9c3e7e
	} else {
Packit 9c3e7e
		sa = msg->msg_name;
Packit 9c3e7e
		assert(sa && msg->msg_namelen >= sizeof (struct sockaddr_in));
Packit 9c3e7e
		assert(sa->sin_family == AF_INET);
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	assert(msg->msg_iovlen == 1);
Packit 9c3e7e
	assert(msg->msg_iov[0].iov_len <= sizeof (req.data));
Packit 9c3e7e
Packit 9c3e7e
	get_target(s, ntohl(sa->sin_addr.s_addr), &req.subnet, &req.to);
Packit 9c3e7e
	req.src_port = sockets[s].port;
Packit 9c3e7e
	req.dst_port = ntohs(sa->sin_port);
Packit 9c3e7e
	assert(req.src_port && req.dst_port);
Packit 9c3e7e
Packit 9c3e7e
	req.len = msg->msg_iov[0].iov_len;
Packit 9c3e7e
	memcpy(req.data, msg->msg_iov[0].iov_base, req.len);
Packit 9c3e7e
Packit 9c3e7e
	make_request(REQ_SEND, &req, offsetof(struct Request_send, data) + req.len, NULL, 0);
Packit 9c3e7e
Packit 9c3e7e
	if (sockets[s].time_stamping & (SOF_TIMESTAMPING_TX_SOFTWARE | SOF_TIMESTAMPING_TX_HARDWARE)) {
Packit 9c3e7e
		struct ts_message *last_ts_msg = &sockets[s].last_ts_msg;
Packit 9c3e7e
Packit 9c3e7e
		assert(req.len <= sizeof (last_ts_msg->data));
Packit 9c3e7e
		memcpy(last_ts_msg->data, req.data, req.len);
Packit 9c3e7e
		last_ts_msg->len = req.len;
Packit 9c3e7e
		last_ts_msg->subnet = req.subnet;
Packit 9c3e7e
		last_ts_msg->to = req.to;
Packit 9c3e7e
		last_ts_msg->port = req.dst_port;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	return req.len;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) {
Packit 9c3e7e
	struct msghdr msg;
Packit 9c3e7e
	struct iovec iov;
Packit 9c3e7e
Packit 9c3e7e
	iov.iov_base = (void *)buf;
Packit 9c3e7e
	iov.iov_len = len;
Packit 9c3e7e
Packit 9c3e7e
	msg.msg_name = (void *)dest_addr;
Packit 9c3e7e
	msg.msg_namelen = addrlen;
Packit 9c3e7e
	msg.msg_iov = &iov;
Packit 9c3e7e
	msg.msg_iovlen = 1;
Packit 9c3e7e
	msg.msg_control = NULL;
Packit 9c3e7e
	msg.msg_controllen = 0;
Packit 9c3e7e
	msg.msg_flags = 0;
Packit 9c3e7e
	return sendmsg(sockfd, &msg, flags);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
ssize_t send(int sockfd, const void *buf, size_t len, int flags) {
Packit 9c3e7e
	return sendto(sockfd, buf, len, flags, NULL, 0);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,
Packit 9c3e7e
#if !defined(__GLIBC_PREREQ) || !(__GLIBC_PREREQ(2, 20))
Packit 9c3e7e
		const
Packit 9c3e7e
#endif
Packit 9c3e7e
		struct timespec *timeout) {
Packit 9c3e7e
	ssize_t len;
Packit 9c3e7e
	int i, n;
Packit 9c3e7e
Packit 9c3e7e
	assert(vlen > 0);
Packit 9c3e7e
	len = recvmsg(sockfd, &msgvec[0].msg_hdr, flags);
Packit 9c3e7e
	if (len < 0)
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	msgvec[0].msg_len = len;
Packit 9c3e7e
Packit 9c3e7e
	if (recv_multiply <= 1 || vlen <= 1)
Packit 9c3e7e
		return 1;
Packit 9c3e7e
Packit 9c3e7e
	n = random() % recv_multiply + 1;
Packit 9c3e7e
	if (n > vlen)
Packit 9c3e7e
		n = vlen;
Packit 9c3e7e
Packit 9c3e7e
	for (i = 1; i < n; i++) {
Packit 9c3e7e
		struct msghdr *src = &msgvec[0].msg_hdr, *dst = &msgvec[i].msg_hdr;
Packit 9c3e7e
		if (dst->msg_name) {
Packit 9c3e7e
			memcpy(dst->msg_name, src->msg_name, src->msg_namelen);
Packit 9c3e7e
			dst->msg_namelen = src->msg_namelen;
Packit 9c3e7e
		}
Packit 9c3e7e
		assert(dst->msg_iovlen == 1 && dst->msg_iov[0].iov_len >= len);
Packit 9c3e7e
		memcpy(dst->msg_iov[0].iov_base, src->msg_iov[0].iov_base, len);
Packit 9c3e7e
		if (dst->msg_control) {
Packit 9c3e7e
			assert(dst->msg_controllen >= src->msg_controllen);
Packit 9c3e7e
			memcpy(dst->msg_control, src->msg_control, src->msg_controllen);
Packit 9c3e7e
			dst->msg_controllen = src->msg_controllen;
Packit 9c3e7e
		}
Packit 9c3e7e
		dst->msg_flags = src->msg_flags;
Packit 9c3e7e
		msgvec[i].msg_len = msgvec[0].msg_len;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	return n;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags) {
Packit 9c3e7e
	struct Reply_recv rep;
Packit 9c3e7e
	struct sockaddr_in *sa;
Packit 9c3e7e
	struct cmsghdr *cmsg;
Packit 9c3e7e
	int msglen, cmsglen, s = get_socket_from_fd(sockfd);
Packit 9c3e7e
Packit 9c3e7e
	if (sockfd == clknetsim_fd)
Packit 9c3e7e
		return _recvmsg(sockfd, msg, flags);
Packit 9c3e7e
Packit 9c3e7e
	assert(s >= 0 && sockets[s].type == SOCK_DGRAM);
Packit 9c3e7e
Packit 9c3e7e
	if (sockets[s].time_stamping & (SOF_TIMESTAMPING_TX_SOFTWARE | SOF_TIMESTAMPING_TX_HARDWARE) &&
Packit 9c3e7e
	    flags & MSG_ERRQUEUE) {
Packit 9c3e7e
		struct ts_message *last_ts_msg;
Packit 9c3e7e
		uint32_t addr;
Packit 9c3e7e
		uint16_t port;
Packit 9c3e7e
Packit 9c3e7e
		/* last message looped back to the error queue */
Packit 9c3e7e
Packit 9c3e7e
		last_ts_msg = &sockets[s].last_ts_msg;
Packit 9c3e7e
		assert(last_ts_msg->len);
Packit 9c3e7e
Packit 9c3e7e
		msg->msg_flags = MSG_ERRQUEUE;
Packit 9c3e7e
Packit 9c3e7e
		rep.subnet = last_ts_msg->subnet;
Packit 9c3e7e
		rep.from = last_ts_msg->to;
Packit 9c3e7e
		rep.src_port = last_ts_msg->port;
Packit 9c3e7e
		rep.dst_port = sockets[s].port;
Packit 9c3e7e
Packit 9c3e7e
		addr = htonl(NODE_ADDR(rep.subnet, rep.from));
Packit 9c3e7e
		port = htons(rep.src_port);
Packit 9c3e7e
Packit 9c3e7e
		/* put the message in an Ethernet frame */
Packit 9c3e7e
		memset(rep.data, 0, 42);
Packit 9c3e7e
		rep.data[12] = 0x08;
Packit 9c3e7e
		rep.data[14] = 0x45;
Packit 9c3e7e
		rep.data[23] = 17;
Packit 9c3e7e
		memcpy(rep.data + 30, &addr, sizeof (addr));
Packit 9c3e7e
		memcpy(rep.data + 36, &port, sizeof (port));
Packit 9c3e7e
Packit 9c3e7e
		assert(last_ts_msg->len + 42 <= sizeof (rep.data));
Packit 9c3e7e
		memcpy(rep.data + 42, last_ts_msg->data, last_ts_msg->len);
Packit 9c3e7e
Packit 9c3e7e
		rep.len = 42 + last_ts_msg->len;
Packit 9c3e7e
Packit 9c3e7e
		last_ts_msg->len = 0;
Packit 9c3e7e
	} else
Packit 9c3e7e
		make_request(REQ_RECV, NULL, 0, &rep, sizeof (rep));
Packit 9c3e7e
Packit 9c3e7e
	if (rep.len == 0) {
Packit 9c3e7e
		errno = EWOULDBLOCK;
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	assert(socket_in_subnet(s, rep.subnet));
Packit 9c3e7e
	assert(sockets[s].port == rep.dst_port);
Packit 9c3e7e
	assert(!sockets[s].remote_port || sockets[s].remote_port == rep.src_port);
Packit 9c3e7e
Packit 9c3e7e
	if (msg->msg_name) {
Packit 9c3e7e
		assert(msg->msg_namelen >= sizeof (struct sockaddr_in));
Packit 9c3e7e
Packit 9c3e7e
		sa = msg->msg_name;
Packit 9c3e7e
		sa->sin_family = AF_INET;
Packit 9c3e7e
		sa->sin_port = htons(rep.src_port);
Packit 9c3e7e
		sa->sin_addr.s_addr = htonl(NODE_ADDR(rep.subnet, rep.from));
Packit 9c3e7e
		msg->msg_namelen = sizeof (struct sockaddr_in);
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	assert(msg->msg_iovlen == 1);
Packit 9c3e7e
	msglen = msg->msg_iov[0].iov_len < rep.len ? msg->msg_iov[0].iov_len : rep.len;
Packit 9c3e7e
	memcpy(msg->msg_iov[0].iov_base, rep.data, msglen);
Packit 9c3e7e
Packit 9c3e7e
	cmsglen = 0;
Packit 9c3e7e
Packit 9c3e7e
	if (sockets[s].pkt_info) {
Packit 9c3e7e
		struct in_pktinfo ipi;
Packit 9c3e7e
Packit 9c3e7e
		cmsglen = CMSG_SPACE(sizeof (ipi));
Packit 9c3e7e
		assert(msg->msg_control && msg->msg_controllen >= cmsglen);
Packit 9c3e7e
Packit 9c3e7e
		cmsg = CMSG_FIRSTHDR(msg);
Packit 9c3e7e
		memset(cmsg, 0, sizeof (*cmsg));
Packit 9c3e7e
		cmsg->cmsg_level = IPPROTO_IP;
Packit 9c3e7e
		cmsg->cmsg_type = IP_PKTINFO;
Packit 9c3e7e
		cmsg->cmsg_len = CMSG_LEN(sizeof (ipi));
Packit 9c3e7e
Packit 9c3e7e
		memset(&ipi, 0, sizeof (ipi));
Packit 9c3e7e
		ipi.ipi_spec_dst.s_addr = htonl(NODE_ADDR(rep.subnet, node));
Packit 9c3e7e
		ipi.ipi_addr.s_addr = ipi.ipi_spec_dst.s_addr;
Packit 9c3e7e
		ipi.ipi_ifindex = rep.subnet + 1;
Packit 9c3e7e
Packit 9c3e7e
		memcpy(CMSG_DATA(cmsg), &ipi, sizeof (ipi));
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
#ifdef SO_TIMESTAMPING
Packit 9c3e7e
	if ((sockets[s].time_stamping & (SOF_TIMESTAMPING_TX_SOFTWARE | SOF_TIMESTAMPING_TX_HARDWARE) &&
Packit 9c3e7e
	     flags & MSG_ERRQUEUE) ||
Packit 9c3e7e
	    (sockets[s].time_stamping & (SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_RX_HARDWARE) &&
Packit 9c3e7e
	     !(flags & MSG_ERRQUEUE))) {
Packit 9c3e7e
		struct timespec ts;
Packit 9c3e7e
Packit 9c3e7e
		/* don't use CMSG_NXTHDR as it's buggy in glibc */
Packit 9c3e7e
		cmsg = (struct cmsghdr *)((char *)CMSG_FIRSTHDR(msg) + cmsglen);
Packit 9c3e7e
		cmsglen += CMSG_SPACE(3 * sizeof (ts));
Packit 9c3e7e
		assert(msg->msg_control && msg->msg_controllen >= cmsglen);
Packit 9c3e7e
Packit 9c3e7e
		memset(cmsg, 0, CMSG_SPACE(3 * sizeof (ts)));
Packit 9c3e7e
		cmsg->cmsg_level = SOL_SOCKET;
Packit 9c3e7e
		cmsg->cmsg_type = SO_TIMESTAMPING;
Packit 9c3e7e
		cmsg->cmsg_len = CMSG_LEN(3 * sizeof (ts));
Packit 9c3e7e
Packit 9c3e7e
		if (sockets[s].time_stamping & SOF_TIMESTAMPING_SOFTWARE) {
Packit 9c3e7e
			clock_gettime(CLOCK_REALTIME, &ts);
Packit 9c3e7e
			memcpy((struct timespec *)CMSG_DATA(cmsg), &ts, sizeof (ts));
Packit 9c3e7e
		}
Packit 9c3e7e
		if (sockets[s].time_stamping & SOF_TIMESTAMPING_RAW_HARDWARE) {
Packit 9c3e7e
			clock_gettime(timestamping > 1 ? REFCLK_ID : CLOCK_REALTIME, &ts);
Packit 9c3e7e
			memcpy((struct timespec *)CMSG_DATA(cmsg) + 2, &ts, sizeof (ts));
Packit 9c3e7e
		}
Packit 9c3e7e
	}
Packit 9c3e7e
#endif
Packit 9c3e7e
	msg->msg_controllen = cmsglen;
Packit 9c3e7e
Packit 9c3e7e
	return msglen;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) {
Packit 9c3e7e
	ssize_t ret;
Packit 9c3e7e
	struct msghdr msg;
Packit 9c3e7e
	struct iovec iov;
Packit 9c3e7e
Packit 9c3e7e
	iov.iov_base = (void *)buf;
Packit 9c3e7e
	iov.iov_len = len;
Packit 9c3e7e
Packit 9c3e7e
	/* needed for compatibility with old glibc recvmsg() */
Packit 9c3e7e
	memset(&msg, 0, sizeof (msg));
Packit 9c3e7e
Packit 9c3e7e
	msg.msg_name = (void *)src_addr;
Packit 9c3e7e
	msg.msg_namelen = *addrlen;
Packit 9c3e7e
	msg.msg_iov = &iov;
Packit 9c3e7e
	msg.msg_iovlen = 1;
Packit 9c3e7e
	msg.msg_control = NULL;
Packit 9c3e7e
	msg.msg_controllen = 0;
Packit 9c3e7e
	msg.msg_flags = 0;
Packit 9c3e7e
Packit 9c3e7e
	ret = recvmsg(sockfd, &msg, flags);
Packit 9c3e7e
	*addrlen = msg.msg_namelen;
Packit 9c3e7e
Packit 9c3e7e
	return ret;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
ssize_t recv(int sockfd, void *buf, size_t len, int flags) {
Packit 9c3e7e
	struct sockaddr_in sa;
Packit 9c3e7e
	socklen_t addrlen = sizeof (sa);
Packit 9c3e7e
Packit 9c3e7e
	return recvfrom(sockfd, buf, len, flags, (struct sockaddr *)&sa, &addrlen);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int timer_create(clockid_t which_clock, struct sigevent *timer_event_spec, timer_t *created_timer_id) {
Packit 9c3e7e
	int t;
Packit 9c3e7e
Packit 9c3e7e
	assert(which_clock == CLOCK_REALTIME && timer_event_spec == NULL);
Packit 9c3e7e
Packit 9c3e7e
	t = get_free_timer();
Packit 9c3e7e
	if (t < 0) {
Packit 9c3e7e
		assert(0);
Packit 9c3e7e
		errno = ENOMEM;
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	timers[t].used = 1;
Packit 9c3e7e
	timers[t].armed = 0;
Packit 9c3e7e
	timers[t].type = TIMER_TYPE_SIGNAL;
Packit 9c3e7e
	timers[t].clock_id = which_clock;
Packit 9c3e7e
	*created_timer_id = get_timerid(t);
Packit 9c3e7e
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int timer_delete(timer_t timerid) {
Packit 9c3e7e
	int t = get_timer_from_id(timerid);
Packit 9c3e7e
Packit 9c3e7e
	if (t < 0) {
Packit 9c3e7e
		errno = EINVAL;
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	timers[t].used = 0;
Packit 9c3e7e
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue) {
Packit 9c3e7e
	int t = get_timer_from_id(timerid);
Packit 9c3e7e
Packit 9c3e7e
	if (t < 0) {
Packit 9c3e7e
		errno = EINVAL;
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	assert(value && ovalue == NULL &&
Packit 9c3e7e
	       (flags == 0 || (flags == TIMER_ABSTIME && timers[t].clock_id == CLOCK_MONOTONIC)));
Packit 9c3e7e
Packit 9c3e7e
	if (value->it_value.tv_sec || value->it_value.tv_nsec) {
Packit 9c3e7e
		timers[t].armed = 1;
Packit 9c3e7e
		timers[t].timeout = timespec_to_time(&value->it_value, 0);
Packit 9c3e7e
		if (!(flags & TIMER_ABSTIME))
Packit 9c3e7e
			timers[t].timeout += get_monotonic_time();
Packit 9c3e7e
		timers[t].interval = timespec_to_time(&value->it_interval, 0);
Packit 9c3e7e
	} else {
Packit 9c3e7e
		timers[t].armed = 0;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int timer_gettime(timer_t timerid, struct itimerspec *value) {
Packit 9c3e7e
	double timeout;
Packit 9c3e7e
	int t = get_timer_from_id(timerid);
Packit 9c3e7e
Packit 9c3e7e
	if (t < 0) {
Packit 9c3e7e
		errno = EINVAL;
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	if (timers[t].armed) {
Packit 9c3e7e
		timeout = timers[t].timeout - get_monotonic_time();
Packit 9c3e7e
		time_to_timespec(timeout, &value->it_value);
Packit 9c3e7e
	} else {
Packit 9c3e7e
		value->it_value.tv_sec = 0;
Packit 9c3e7e
		value->it_value.tv_nsec = 0;
Packit 9c3e7e
	}
Packit 9c3e7e
	time_to_timespec(timers[t].interval, &value->it_interval);
Packit 9c3e7e
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
#ifndef CLKNETSIM_DISABLE_ITIMER
Packit 9c3e7e
int setitimer(__itimer_which_t which, const struct itimerval *new_value, struct itimerval *old_value) {
Packit 9c3e7e
	struct itimerspec timerspec;
Packit 9c3e7e
Packit 9c3e7e
	assert(which == ITIMER_REAL && old_value == NULL);
Packit 9c3e7e
Packit 9c3e7e
	if (get_timer_from_id(itimer_real_id) < 0)
Packit 9c3e7e
		timer_create(CLOCK_REALTIME, NULL, &itimer_real_id);
Packit 9c3e7e
Packit 9c3e7e
	timerspec.it_interval.tv_sec = new_value->it_interval.tv_sec;
Packit 9c3e7e
	timerspec.it_interval.tv_nsec = new_value->it_interval.tv_usec * 1000;
Packit 9c3e7e
	timerspec.it_value.tv_sec = new_value->it_value.tv_sec;
Packit 9c3e7e
	timerspec.it_value.tv_nsec = new_value->it_value.tv_usec * 1000;
Packit 9c3e7e
Packit 9c3e7e
	return timer_settime(itimer_real_id, 0, &timerspec, NULL);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int getitimer(__itimer_which_t which, struct itimerval *curr_value) {
Packit 9c3e7e
	struct itimerspec timerspec;
Packit 9c3e7e
Packit 9c3e7e
	assert(which == ITIMER_REAL);
Packit 9c3e7e
Packit 9c3e7e
	if (timer_gettime(itimer_real_id, &timerspec))
Packit 9c3e7e
		return -1;
Packit 9c3e7e
Packit 9c3e7e
	curr_value->it_interval.tv_sec = timerspec.it_interval.tv_sec;
Packit 9c3e7e
	curr_value->it_interval.tv_usec = timerspec.it_interval.tv_nsec / 1000;
Packit 9c3e7e
	curr_value->it_value.tv_sec = timerspec.it_value.tv_sec;
Packit 9c3e7e
	curr_value->it_value.tv_usec = timerspec.it_value.tv_nsec / 1000;
Packit 9c3e7e
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
#endif
Packit 9c3e7e
Packit 9c3e7e
int timerfd_create(int clockid, int flags) {
Packit 9c3e7e
	int t;
Packit 9c3e7e
Packit 9c3e7e
	assert((clockid == CLOCK_REALTIME || clockid == CLOCK_MONOTONIC) && !flags);
Packit 9c3e7e
Packit 9c3e7e
	t = get_free_timer();
Packit 9c3e7e
	if (t < 0) {
Packit 9c3e7e
		assert(0);
Packit 9c3e7e
		errno = ENOMEM;
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	timers[t].used = 1;
Packit 9c3e7e
	timers[t].armed = 0;
Packit 9c3e7e
	timers[t].type = TIMER_TYPE_FD;
Packit 9c3e7e
	timers[t].clock_id = clockid;
Packit 9c3e7e
Packit 9c3e7e
	return get_timerfd(t);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value) {
Packit 9c3e7e
	if (flags == TFD_TIMER_ABSTIME)
Packit 9c3e7e
		flags = TIMER_ABSTIME;
Packit 9c3e7e
	else
Packit 9c3e7e
		assert(!flags);
Packit 9c3e7e
Packit 9c3e7e
	return timer_settime(get_timerid(get_timer_from_fd(fd)), flags, new_value, old_value);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int timerfd_gettime(int fd, struct itimerspec *curr_value) {
Packit 9c3e7e
	return timer_gettime(get_timerid(get_timer_from_fd(fd)), curr_value);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int shmget(key_t key, size_t size, int shmflg) {
Packit 9c3e7e
	if (fuzz_mode)
Packit 9c3e7e
		return _shmget(key, size, shmflg);
Packit 9c3e7e
Packit 9c3e7e
	if (key >= SHM_KEY && key < SHM_KEY + SHM_REFCLOCKS)
Packit 9c3e7e
		return key;
Packit 9c3e7e
Packit 9c3e7e
	return -1;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
void *shmat(int shmid, const void *shmaddr, int shmflg) {
Packit 9c3e7e
	if (fuzz_mode)
Packit 9c3e7e
		return _shmat(shmid, shmaddr, shmflg);
Packit 9c3e7e
Packit 9c3e7e
	assert(shmid >= SHM_KEY && shmid < SHM_KEY + SHM_REFCLOCKS);
Packit 9c3e7e
Packit 9c3e7e
	if (shm_refclocks < shmid - SHM_KEY + 1)
Packit 9c3e7e
		shm_refclocks = shmid - SHM_KEY + 1;
Packit 9c3e7e
	memset(&shm_time[shmid - SHM_KEY], 0, sizeof (shm_time[0]));
Packit 9c3e7e
	shm_time[shmid - SHM_KEY].mode = 1;
Packit 9c3e7e
	shm_time[shmid - SHM_KEY].precision = -20;
Packit 9c3e7e
Packit 9c3e7e
	/* don't wait for select() with starting of the refclock generator */
Packit 9c3e7e
	fill_refclock_sample();
Packit 9c3e7e
Packit 9c3e7e
	return &shm_time[shmid - SHM_KEY];
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int shmdt(const void *shmaddr) {
Packit 9c3e7e
	assert(shmaddr >= (void *)&shm_time[0] && shmaddr < (void *)&shm_time[SHM_REFCLOCKS]);
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
uid_t getuid(void) {
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int uname(struct utsname *buf) {
Packit 9c3e7e
	memset(buf, 0, sizeof (*buf));
Packit 9c3e7e
	sprintf(buf->sysname, "Linux (clknetsim)");
Packit 9c3e7e
	sprintf(buf->release, "4.19");
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int gethostname(char *name, size_t len) {
Packit 9c3e7e
	snprintf(name, len, "clknetsim-node%d", node + 1);
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
void openlog(const char *ident, int option, int facility) {
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
void __syslog_chk(int priority, int flag, const char *format, ...) {
Packit 9c3e7e
	va_list ap;
Packit 9c3e7e
Packit 9c3e7e
	va_start(ap, format);
Packit 9c3e7e
	vfprintf(stderr, format, ap);
Packit 9c3e7e
	va_end(ap);
Packit 9c3e7e
	fprintf(stderr, "\n");
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
void syslog(int priority, const char *format, ...) {
Packit 9c3e7e
	va_list ap;
Packit 9c3e7e
Packit 9c3e7e
	va_start(ap, format);
Packit 9c3e7e
	vfprintf(stderr, format, ap);
Packit 9c3e7e
	va_end(ap);
Packit 9c3e7e
	fprintf(stderr, "\n");
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
void closelog(void) {
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
#ifndef CLKNETSIM_DISABLE_SYSCALL
Packit 9c3e7e
long syscall(long number, ...) {
Packit 9c3e7e
	va_list ap;
Packit 9c3e7e
	long r;
Packit 9c3e7e
	struct timex *timex;
Packit 9c3e7e
	clockid_t clock_id;
Packit 9c3e7e
Packit 9c3e7e
	va_start(ap, number);
Packit 9c3e7e
	switch (number) {
Packit 9c3e7e
#ifdef __NR_clock_adjtime
Packit 9c3e7e
		case __NR_clock_adjtime:
Packit 9c3e7e
			clock_id = va_arg(ap, clockid_t);
Packit 9c3e7e
			timex = va_arg(ap, struct timex *);
Packit 9c3e7e
			r = clock_adjtime(clock_id, timex);
Packit 9c3e7e
			break;
Packit 9c3e7e
#endif
Packit 9c3e7e
		default:
Packit 9c3e7e
			assert(0);
Packit 9c3e7e
	}
Packit 9c3e7e
	va_end(ap);
Packit 9c3e7e
Packit 9c3e7e
	return r;
Packit 9c3e7e
}
Packit 9c3e7e
#endif
Packit 9c3e7e
Packit 9c3e7e
ssize_t getrandom(void *buf, size_t length, unsigned int flags) {
Packit 9c3e7e
	errno = ENOTSUP;
Packit 9c3e7e
	return -1;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
void srandom(unsigned int seed) {
Packit 9c3e7e
	FILE *f;
Packit 9c3e7e
Packit 9c3e7e
	/* override the seed to the fixed seed if set or make it truly
Packit 9c3e7e
	   random in case it's based on the simulated time */
Packit 9c3e7e
	if (random_seed) {
Packit 9c3e7e
		seed = random_seed + node;
Packit 9c3e7e
	} else if ((f = _fopen("/dev/urandom", "r"))) {
Packit 9c3e7e
		if (fread(&seed, sizeof (seed), 1, f) != 1)
Packit 9c3e7e
			;
Packit 9c3e7e
		fclose(f);
Packit 9c3e7e
	}
Packit 9c3e7e
	_srandom(seed);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
struct passwd *getpwnam(const char *name) {
Packit 9c3e7e
	static struct passwd pw = {
Packit 9c3e7e
		.pw_name = "",
Packit 9c3e7e
		.pw_passwd = "",
Packit 9c3e7e
		.pw_uid = 0,
Packit 9c3e7e
		.pw_gid = 0,
Packit 9c3e7e
		.pw_gecos = "",
Packit 9c3e7e
		.pw_dir = "",
Packit 9c3e7e
		.pw_shell = ""
Packit 9c3e7e
	};
Packit 9c3e7e
Packit 9c3e7e
	return &pw;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int initgroups(const char *user, gid_t group) {
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int setgroups(size_t size, const gid_t *list) {
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int setegid(gid_t gid) {
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int setgid(gid_t gid) {
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int seteuid(uid_t uid) {
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int setuid(uid_t uid) {
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int cap_set_proc() {
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}