Mac OSX Port - Lightly tested

This commit is contained in:
Joseph Henry 2016-01-25 12:55:29 -08:00
parent 935f00ad4c
commit 95d28494f6
6 changed files with 101 additions and 19 deletions

View File

@ -79,6 +79,18 @@ one: $(OBJS) service/OneService.o one.o
$(CODESIGN) -f -s $(CODESIGN_APP_CERT) zerotier-one $(CODESIGN) -f -s $(CODESIGN_APP_CERT) zerotier-one
$(CODESIGN) -vvv zerotier-one $(CODESIGN) -vvv zerotier-one
netcon: $(OBJS)
rm -f *.o
# Need to selectively rebuild one.cpp and OneService.cpp with ZT_SERVICE_NETCON and ZT_ONE_NO_ROOT_CHECK defined, and also NetconEthernetTap
$(CXX) $(CXXFLAGS) $(LDFLAGS) -DZT_SERVICE_NETCON -DZT_ONE_NO_ROOT_CHECK -Iext/lwip/src/include -Iext/lwip/src/include/ipv4 -Iext/lwip/src/include/ipv6 -o zerotier-netcon-service $(OBJS) service/OneService.cpp netcon/NetconEthernetTap.cpp one.cpp -x c netcon/RPC.c $(LDLIBS) -ldl
# Build netcon/liblwip.so which must be placed in ZT home for zerotier-netcon-service to work
cd netcon ; make -f make-liblwip.mk
# Use gcc not clang to build standalone intercept library since gcc is typically used for libc and we want to ensure maximal ABI compatibility
cd netcon ; gcc -O2 -Wall -std=c99 -fPIC -fno-common -dynamiclib -flat_namespace -DVERBOSE -D_GNU_SOURCE -DNETCON_INTERCEPT -I. -nostdlib -shared -o libzerotierintercept.so Intercept.c RPC.c -ldl
cp netcon/libzerotierintercept.so libzerotierintercept.so
ln -sf zerotier-netcon-service zerotier-cli
ln -sf zerotier-netcon-service zerotier-idtool
selftest: $(OBJS) selftest.o selftest: $(OBJS) selftest.o
$(CXX) $(CXXFLAGS) -o zerotier-selftest selftest.o $(OBJS) $(LIBS) $(CXX) $(CXXFLAGS) -o zerotier-selftest selftest.o $(OBJS) $(LIBS)
$(STRIP) zerotier-selftest $(STRIP) zerotier-selftest
@ -97,7 +109,7 @@ official: FORCE
make ZT_OFFICIAL_RELEASE=1 mac-dist-pkg make ZT_OFFICIAL_RELEASE=1 mac-dist-pkg
clean: clean:
rm -rf *.dSYM build-* *.pkg *.dmg *.o node/*.o controller/*.o service/*.o osdep/*.o ext/http-parser/*.o ext/lz4/*.o ext/json-parser/*.o $(OBJS) zerotier-one zerotier-idtool zerotier-selftest zerotier-cli ZeroTierOneInstaller-* mkworld rm -rf netcon/*.so *.dSYM build-* *.pkg *.dmg *.o node/*.o controller/*.o service/*.o osdep/*.o ext/http-parser/*.o ext/lz4/*.o ext/json-parser/*.o $(OBJS) zerotier-one zerotier-idtool zerotier-selftest zerotier-cli ZeroTierOneInstaller-* mkworld
# For those building from source -- installs signed binary tap driver in system ZT home # For those building from source -- installs signed binary tap driver in system ZT home
install-mac-tap: FORCE install-mac-tap: FORCE

View File

@ -38,20 +38,25 @@
#include <sys/time.h> #include <sys/time.h>
#include <pwd.h> #include <pwd.h>
#include <errno.h> #include <errno.h>
#include <linux/errno.h>
#include <stdarg.h> #include <stdarg.h>
#include <netdb.h> #include <netdb.h>
#include <string.h> #include <string.h>
#include <sys/syscall.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/poll.h> #include <sys/poll.h>
#include <sys/un.h> #include <sys/un.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <linux/net.h> /* for NPROTO */
#define SOCK_MAX (SOCK_PACKET + 1) #if defined(__linux__)
#include <linux/errno.h>
#include <sys/syscall.h>
#include <linux/net.h> /* for NPROTO */
#endif
#if defined(__linux__)
#define SOCK_MAX (SOCK_PACKET + 1)
#endif
#define SOCK_TYPE_MASK 0xf #define SOCK_TYPE_MASK 0xf
#include "Intercept.h" #include "Intercept.h"
@ -92,6 +97,11 @@ static int connected_to_service(int sockfd)
static int set_up_intercept() static int set_up_intercept()
{ {
if (!realconnect) { if (!realconnect) {
#if defined(__linux__)
realaccept4 = dlsym(RTLD_NEXT, "accept4");
realsyscall = dlsym(RTLD_NEXT, "syscall");
#endif
realconnect = dlsym(RTLD_NEXT, "connect"); realconnect = dlsym(RTLD_NEXT, "connect");
realbind = dlsym(RTLD_NEXT, "bind"); realbind = dlsym(RTLD_NEXT, "bind");
realaccept = dlsym(RTLD_NEXT, "accept"); realaccept = dlsym(RTLD_NEXT, "accept");
@ -100,9 +110,7 @@ static int set_up_intercept()
realbind = dlsym(RTLD_NEXT, "bind"); realbind = dlsym(RTLD_NEXT, "bind");
realsetsockopt = dlsym(RTLD_NEXT, "setsockopt"); realsetsockopt = dlsym(RTLD_NEXT, "setsockopt");
realgetsockopt = dlsym(RTLD_NEXT, "getsockopt"); realgetsockopt = dlsym(RTLD_NEXT, "getsockopt");
realaccept4 = dlsym(RTLD_NEXT, "accept4");
realclose = dlsym(RTLD_NEXT, "close"); realclose = dlsym(RTLD_NEXT, "close");
realsyscall = dlsym(RTLD_NEXT, "syscall");
realgetsockname = dlsym(RTLD_NEXT, "getsockname"); realgetsockname = dlsym(RTLD_NEXT, "getsockname");
} }
if (!netpath) { if (!netpath) {
@ -127,10 +135,12 @@ int setsockopt(SETSOCKOPT_SIG)
return realsetsockopt(socket, level, option_name, option_value, option_len); return realsetsockopt(socket, level, option_name, option_value, option_len);
dwr(MSG_DEBUG,"setsockopt(%d)\n", socket); dwr(MSG_DEBUG,"setsockopt(%d)\n", socket);
#if defined(__linux__)
if(level == SOL_IPV6 && option_name == IPV6_V6ONLY) if(level == SOL_IPV6 && option_name == IPV6_V6ONLY)
return 0; return 0;
if(level == SOL_IP && (option_name == IP_TTL || option_name == IP_TOS)) if(level == SOL_IP && (option_name == IP_TTL || option_name == IP_TOS))
return 0; return 0;
#endif
if(level == IPPROTO_TCP || (level == SOL_SOCKET && option_name == SO_KEEPALIVE)) if(level == IPPROTO_TCP || (level == SOL_SOCKET && option_name == SO_KEEPALIVE))
return 0; return 0;
if(realsetsockopt(socket, level, option_name, option_value, option_len) < 0) if(realsetsockopt(socket, level, option_name, option_value, option_len) < 0)
@ -169,13 +179,16 @@ int socket(SOCKET_SIG)
dwr(MSG_DEBUG,"socket():\n"); dwr(MSG_DEBUG,"socket():\n");
/* Check that type makes sense */ /* Check that type makes sense */
#if defined(__linux__)
int flags = socket_type & ~SOCK_TYPE_MASK; int flags = socket_type & ~SOCK_TYPE_MASK;
if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) { if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
#endif
socket_type &= SOCK_TYPE_MASK; socket_type &= SOCK_TYPE_MASK;
/* Check protocol is in range */ /* Check protocol is in range */
#if defined(__linux__)
if (socket_family < 0 || socket_family >= NPROTO){ if (socket_family < 0 || socket_family >= NPROTO){
errno = EAFNOSUPPORT; errno = EAFNOSUPPORT;
return -1; return -1;
@ -184,9 +197,12 @@ int socket(SOCKET_SIG)
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
#endif
/* TODO: detect ENFILE condition */ /* TODO: detect ENFILE condition */
if(socket_family == AF_LOCAL if(socket_family == AF_LOCAL
#if defined(__linux__)
|| socket_family == AF_NETLINK || socket_family == AF_NETLINK
#endif
|| socket_family == AF_UNIX) { || socket_family == AF_UNIX) {
int err = realsocket(socket_family, socket_type, protocol); int err = realsocket(socket_family, socket_type, protocol);
dwr(MSG_DEBUG,"realsocket() = %d\n", err); dwr(MSG_DEBUG,"realsocket() = %d\n", err);
@ -244,24 +260,30 @@ int connect(CONNECT_SIG)
errno = ENOTSOCK; errno = ENOTSOCK;
return -1; return -1;
} }
#if defined(__linux__)
/* Check family */ /* Check family */
if (connaddr->sin_family < 0 || connaddr->sin_family >= NPROTO){ if (connaddr->sin_family < 0 || connaddr->sin_family >= NPROTO){
errno = EAFNOSUPPORT; errno = EAFNOSUPPORT;
return -1; return -1;
} }
#endif
/* make sure we don't touch any standard outputs */ /* make sure we don't touch any standard outputs */
if(__fd == STDIN_FILENO || __fd == STDOUT_FILENO || __fd == STDERR_FILENO) if(__fd == STDIN_FILENO || __fd == STDOUT_FILENO || __fd == STDERR_FILENO)
return(realconnect(__fd, __addr, __len)); return(realconnect(__fd, __addr, __len));
if(__addr != NULL && (connaddr->sin_family == AF_LOCAL if(__addr != NULL && (connaddr->sin_family == AF_LOCAL
#if defined(__linux__)
|| connaddr->sin_family == PF_NETLINK || connaddr->sin_family == PF_NETLINK
|| connaddr->sin_family == AF_NETLINK || connaddr->sin_family == AF_NETLINK
#endif
|| connaddr->sin_family == AF_UNIX)) { || connaddr->sin_family == AF_UNIX)) {
return realconnect(__fd, __addr, __len); return realconnect(__fd, __addr, __len);
} }
/* Assemble and send RPC */ /* Assemble and send RPC */
struct connect_st rpc_st; struct connect_st rpc_st;
#if defined(__linux__)
rpc_st.__tid = syscall(SYS_gettid); rpc_st.__tid = syscall(SYS_gettid);
#endif
rpc_st.__fd = __fd; rpc_st.__fd = __fd;
memcpy(&rpc_st.__addr, __addr, sizeof(struct sockaddr_storage)); memcpy(&rpc_st.__addr, __addr, sizeof(struct sockaddr_storage));
memcpy(&rpc_st.__len, &__len, sizeof(socklen_t)); memcpy(&rpc_st.__len, &__len, sizeof(socklen_t));
@ -300,7 +322,9 @@ int bind(BIND_SIG)
connaddr = (struct sockaddr_in *)addr; connaddr = (struct sockaddr_in *)addr;
if(connaddr->sin_family == AF_LOCAL if(connaddr->sin_family == AF_LOCAL
#if defined(__linux__)
|| connaddr->sin_family == AF_NETLINK || connaddr->sin_family == AF_NETLINK
#endif
|| connaddr->sin_family == AF_UNIX) { || connaddr->sin_family == AF_UNIX) {
int err = realbind(sockfd, addr, addrlen); int err = realbind(sockfd, addr, addrlen);
dwr(MSG_DEBUG,"realbind, err = %d\n", err); dwr(MSG_DEBUG,"realbind, err = %d\n", err);
@ -317,7 +341,9 @@ int bind(BIND_SIG)
/* Assemble and send RPC */ /* Assemble and send RPC */
struct bind_st rpc_st; struct bind_st rpc_st;
rpc_st.sockfd = sockfd; rpc_st.sockfd = sockfd;
#if defined(__linux__)
rpc_st.__tid = syscall(SYS_gettid); rpc_st.__tid = syscall(SYS_gettid);
#endif
memcpy(&rpc_st.addr, addr, sizeof(struct sockaddr_storage)); memcpy(&rpc_st.addr, addr, sizeof(struct sockaddr_storage));
memcpy(&rpc_st.addrlen, &addrlen, sizeof(socklen_t)); memcpy(&rpc_st.addrlen, &addrlen, sizeof(socklen_t));
return rpc_send_command(netpath, RPC_BIND, sockfd, &rpc_st, sizeof(struct bind_st)); return rpc_send_command(netpath, RPC_BIND, sockfd, &rpc_st, sizeof(struct bind_st));
@ -328,6 +354,7 @@ int bind(BIND_SIG)
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
/* int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags */ /* int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags */
#if defined(__linux__)
int accept4(ACCEPT4_SIG) int accept4(ACCEPT4_SIG)
{ {
dwr(MSG_DEBUG,"accept4(%d):\n", sockfd); dwr(MSG_DEBUG,"accept4(%d):\n", sockfd);
@ -337,6 +364,7 @@ int accept4(ACCEPT4_SIG)
fcntl(sockfd, F_SETFL, O_NONBLOCK); fcntl(sockfd, F_SETFL, O_NONBLOCK);
return accept(sockfd, addr, addrlen); return accept(sockfd, addr, addrlen);
} }
#endif
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
----------------------------------- accept() ----------------------------------- ----------------------------------- accept() -----------------------------------
@ -442,7 +470,9 @@ int listen(LISTEN_SIG)
struct listen_st rpc_st; struct listen_st rpc_st;
rpc_st.sockfd = sockfd; rpc_st.sockfd = sockfd;
rpc_st.backlog = backlog; rpc_st.backlog = backlog;
#if defined(__linux__)
rpc_st.__tid = syscall(SYS_gettid); rpc_st.__tid = syscall(SYS_gettid);
#endif
return rpc_send_command(netpath, RPC_LISTEN, sockfd, &rpc_st, sizeof(struct listen_st)); return rpc_send_command(netpath, RPC_LISTEN, sockfd, &rpc_st, sizeof(struct listen_st));
} }
@ -502,6 +532,7 @@ int getsockname(GETSOCKNAME_SIG)
------------------------------------ syscall() --------------------------------- ------------------------------------ syscall() ---------------------------------
------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------*/
#if defined(__linux__)
long syscall(SYSCALL_SIG) long syscall(SYSCALL_SIG)
{ {
va_list ap; va_list ap;
@ -542,3 +573,4 @@ long syscall(SYSCALL_SIG)
#endif #endif
return realsyscall(number,a,b,c,d,e,f); return realsyscall(number,a,b,c,d,e,f);
} }
#endif

View File

@ -25,12 +25,17 @@
* LLC. Start here: http://www.zerotier.com/ * LLC. Start here: http://www.zerotier.com/
*/ */
#ifndef _INTERCEPT_H #ifndef _INTERCEPT_H
#define _INTERCEPT_H 1 #define _INTERCEPT_H 1
#include <sys/socket.h> #include <sys/socket.h>
#if defined(__linux__)
#define ACCEPT4_SIG int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags
#define SYSCALL_SIG long number, ...
#endif
#define CLOSE_SIG int fd #define CLOSE_SIG int fd
#define READ_SIG int __fd, void *__buf, size_t __nbytes #define READ_SIG int __fd, void *__buf, size_t __nbytes
#define BIND_SIG int sockfd, const struct sockaddr *addr, socklen_t addrlen #define BIND_SIG int sockfd, const struct sockaddr *addr, socklen_t addrlen
@ -38,7 +43,6 @@
#define WRITE_SIG int __fd, const void *__buf, size_t __n #define WRITE_SIG int __fd, const void *__buf, size_t __n
#define LISTEN_SIG int sockfd, int backlog #define LISTEN_SIG int sockfd, int backlog
#define SOCKET_SIG int socket_family, int socket_type, int protocol #define SOCKET_SIG int socket_family, int socket_type, int protocol
#define ACCEPT4_SIG int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags
#define ACCEPT_SIG int sockfd, struct sockaddr *addr, socklen_t *addrlen #define ACCEPT_SIG int sockfd, struct sockaddr *addr, socklen_t *addrlen
#define SHUTDOWN_SIG int socket, int how #define SHUTDOWN_SIG int socket, int how
#define CONNECT_SOCKARG struct sockaddr * #define CONNECT_SOCKARG struct sockaddr *
@ -47,12 +51,17 @@
#define DAEMON_SIG int nochdir, int noclose #define DAEMON_SIG int nochdir, int noclose
#define SETSOCKOPT_SIG int socket, int level, int option_name, const void *option_value, socklen_t option_len #define SETSOCKOPT_SIG int socket, int level, int option_name, const void *option_value, socklen_t option_len
#define GETSOCKOPT_SIG int sockfd, int level, int optname, void *optval, socklen_t *optlen #define GETSOCKOPT_SIG int sockfd, int level, int optname, void *optval, socklen_t *optlen
#define SYSCALL_SIG long number, ...
#define CLONE_SIG int (*fn)(void *), void *child_stack, int flags, void *arg, ... #define CLONE_SIG int (*fn)(void *), void *child_stack, int flags, void *arg, ...
#define GETSOCKNAME_SIG int sockfd, struct sockaddr *addr, socklen_t *addrlen #define GETSOCKNAME_SIG int sockfd, struct sockaddr *addr, socklen_t *addrlen
#define DUP2_SIG int oldfd, int newfd #define DUP2_SIG int oldfd, int newfd
#define DUP3_SIG int oldfd, int newfd, int flags #define DUP3_SIG int oldfd, int newfd, int flags
#if defined(__linux__)
int accept4(ACCEPT4_SIG);
long syscall(SYSCALL_SIG);
#endif
void my_init(void); void my_init(void);
int connect(CONNECT_SIG); int connect(CONNECT_SIG);
int bind(BIND_SIG); int bind(BIND_SIG);
@ -61,14 +70,17 @@ int listen(LISTEN_SIG);
int socket(SOCKET_SIG); int socket(SOCKET_SIG);
int setsockopt(SETSOCKOPT_SIG); int setsockopt(SETSOCKOPT_SIG);
int getsockopt(GETSOCKOPT_SIG); int getsockopt(GETSOCKOPT_SIG);
int accept4(ACCEPT4_SIG);
long syscall(SYSCALL_SIG);
int close(CLOSE_SIG); int close(CLOSE_SIG);
int clone(CLONE_SIG); int clone(CLONE_SIG);
int dup2(DUP2_SIG); int dup2(DUP2_SIG);
int dup3(DUP3_SIG); int dup3(DUP3_SIG);
int getsockname(GETSOCKNAME_SIG); int getsockname(GETSOCKNAME_SIG);
#if defined(__linux__)
static int (*realaccept4)(ACCEPT4_SIG) = 0;
static long (*realsyscall)(SYSCALL_SIG) = 0;
#endif
static int (*realconnect)(CONNECT_SIG) = 0; static int (*realconnect)(CONNECT_SIG) = 0;
static int (*realbind)(BIND_SIG) = 0; static int (*realbind)(BIND_SIG) = 0;
static int (*realaccept)(ACCEPT_SIG) = 0; static int (*realaccept)(ACCEPT_SIG) = 0;
@ -76,8 +88,6 @@ static int (*reallisten)(LISTEN_SIG) = 0;
static int (*realsocket)(SOCKET_SIG) = 0; static int (*realsocket)(SOCKET_SIG) = 0;
static int (*realsetsockopt)(SETSOCKOPT_SIG) = 0; static int (*realsetsockopt)(SETSOCKOPT_SIG) = 0;
static int (*realgetsockopt)(GETSOCKOPT_SIG) = 0; static int (*realgetsockopt)(GETSOCKOPT_SIG) = 0;
static int (*realaccept4)(ACCEPT4_SIG) = 0;
static long (*realsyscall)(SYSCALL_SIG) = 0;
static int (*realclose)(CLOSE_SIG) = 0; static int (*realclose)(CLOSE_SIG) = 0;
static int (*realgetsockname)(GETSOCKNAME_SIG) = 0; static int (*realgetsockname)(GETSOCKNAME_SIG) = 0;

View File

@ -132,7 +132,13 @@ public:
LWIPStack(const char* path) : LWIPStack(const char* path) :
_libref(NULL) _libref(NULL)
{ {
#if defined(__linux__)
_libref = dlmopen(LM_ID_NEWLM, path, RTLD_NOW); _libref = dlmopen(LM_ID_NEWLM, path, RTLD_NOW);
#elif defined(__APPLE__)
_libref = dlopen(path, RTLD_NOW);
#endif
if(_libref == NULL) if(_libref == NULL)
printf("dlerror(): %s\n", dlerror()); printf("dlerror(): %s\n", dlerror());

View File

@ -70,6 +70,22 @@ The intercept library does nothing unless the *ZT\_NC\_NETWORK* environment vari
Unlike *zerotier-one*, *zerotier-netcon-service* does not need to be run with root privileges and will not modify the host's network configuration in any way. It can be run alongside *zerotier-one* on the same host with no ill effect, though this can be confusing since you'll have to remember the difference between "real" host interfaces (tun/tap) and network containerized endpoints. The latter are completely unknown to the kernel and will not show up in *ifconfig*. Unlike *zerotier-one*, *zerotier-netcon-service* does not need to be run with root privileges and will not modify the host's network configuration in any way. It can be run alongside *zerotier-one* on the same host with no ill effect, though this can be confusing since you'll have to remember the difference between "real" host interfaces (tun/tap) and network containerized endpoints. The latter are completely unknown to the kernel and will not show up in *ifconfig*.
# Linking into an application on Mac OSX
Example:
gcc myapp.c -o myapp libzerotierintercept.so
export ZT_NC_NETWORK=/tmp/netcon-test-home/nc_8056c2e21c000001
Start service
./zerotier-netcon-service -d -p8000 /tmp/netcon-test-home
Run application
./myapp
# Starting the Network Containers Service # Starting the Network Containers Service
You don't need Docker or any other container engine to try Network Containers. A simple test can be performed in user space (no root) in your own home directory. You don't need Docker or any other container engine to try Network Containers. A simple test can be performed in user space (no root) in your own home directory.

View File

@ -3,7 +3,10 @@
#include <sys/un.h> #include <sys/un.h>
#include <pthread.h> #include <pthread.h>
#include <errno.h> #include <errno.h>
#if defined(__linux__)
#include <sys/syscall.h> #include <sys/syscall.h>
#endif
#include <fcntl.h> #include <fcntl.h>
#include <dlfcn.h> #include <dlfcn.h>
@ -70,12 +73,12 @@ int get_retval(int rpc_sock)
int load_symbols_rpc() int load_symbols_rpc()
{ {
#ifdef NETCON_INTERCEPT #ifdef NETCON_INTERCEPT
realsocket = dlsym(RTLD_NEXT, "socket"); realsocket = dlsym(RTLD_NEXT, "socket");
realconnect = dlsym(RTLD_NEXT, "connect"); realconnect = dlsym(RTLD_NEXT, "connect");
if(!realconnect || !realsocket) if(!realconnect || !realsocket)
return -1; return -1;
#endif #endif
return 1; return 1;
} }
@ -131,19 +134,22 @@ int rpc_send_command(char *path, int cmd, int forfd, void *data, int len)
memcpy(&cmdbuf[CANARY_IDX], &canary_num, CANARY_SZ); memcpy(&cmdbuf[CANARY_IDX], &canary_num, CANARY_SZ);
memcpy(&cmdbuf[STRUCT_IDX], data, len); memcpy(&cmdbuf[STRUCT_IDX], data, len);
#ifdef VERBOSE #if defined(VERBOSE)
rpc_count++;
memset(metabuf, 0, BUF_SZ); memset(metabuf, 0, BUF_SZ);
#if defined(__linux__)
pid_t pid = syscall(SYS_getpid); pid_t pid = syscall(SYS_getpid);
pid_t tid = syscall(SYS_gettid); pid_t tid = syscall(SYS_gettid);
rpc_count++; #endif
char timestring[20]; char timestring[20];
time_t timestamp; time_t timestamp;
timestamp = time(NULL); timestamp = time(NULL);
strftime(timestring, sizeof(timestring), "%H:%M:%S", localtime(&timestamp)); strftime(timestring, sizeof(timestring), "%H:%M:%S", localtime(&timestamp));
memcpy(metabuf, RPC_PHRASE, RPC_PHRASE_SZ); // Write signal phrase memcpy(metabuf, RPC_PHRASE, RPC_PHRASE_SZ); // Write signal phrase
#if defined(__linux__)
memcpy(&metabuf[IDX_PID], &pid, sizeof(pid_t) ); /* pid */ memcpy(&metabuf[IDX_PID], &pid, sizeof(pid_t) ); /* pid */
memcpy(&metabuf[IDX_TID], &tid, sizeof(pid_t) ); /* tid */ memcpy(&metabuf[IDX_TID], &tid, sizeof(pid_t) ); /* tid */
#endif
memcpy(&metabuf[IDX_COUNT], &rpc_count, sizeof(rpc_count) ); /* rpc_count */ memcpy(&metabuf[IDX_COUNT], &rpc_count, sizeof(rpc_count) ); /* rpc_count */
memcpy(&metabuf[IDX_TIME], &timestring, 20 ); /* timestamp */ memcpy(&metabuf[IDX_TIME], &timestring, 20 ); /* timestamp */
#endif #endif