/** send fastd pid to Android GUI for later signal sending (HUP, TERM etc) */ void fastd_android_send_pid(void) { char pid[20]; snprintf(pid, sizeof(pid), "%u", (unsigned)getpid()); if (write(ctx.android_ctrl_sock_fd, pid, strlen(pid)) != strlen(pid)) { exit_errno("send pid"); } }
/** report \e fd to Android GUI to be protected (i.e. not to be routed via TUN) */ bool fastd_android_protect_socket(int fd) { if (!conf.android_integration) { /* rooted/non-GUI mode */ return true; } pr_debug("sending fd to protect"); if (ancil_send_fd(ctx.android_ctrl_sock_fd, fd) == -1) { exit_errno("could not send handle to Android for protecting"); } char buf[20]; if (read(ctx.android_ctrl_sock_fd, buf, sizeof(buf)) == -1) { exit_errno("read ack"); } return buf[0] == PROTECT_OK; }
/** establish the unix domain socket with Android GUI */ static void init_ctrl_sock(void) { /* Must keep consistent with FastdVpnService */ struct sockaddr_un addr; if ((ctx.android_ctrl_sock_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { exit_errno("could not create unix domain socket"); } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; addr.sun_path[0] = 0; /* Linux's abstract unix domain socket name */ strncpy(addr.sun_path + 1, CTRL_SOCK_NAME, sizeof(addr.sun_path) - 2); int socklen = offsetof(struct sockaddr_un, sun_path) + strlen(CTRL_SOCK_NAME) + 1; if (connect(ctx.android_ctrl_sock_fd, (struct sockaddr*)&addr, socklen) == -1) { exit_errno("could not connect to Android LocalServerSocket"); } }
/** Provides a given amount of cryptographic random data */ void fastd_random_bytes(void *buffer, size_t len, bool secure) { int fd; size_t read_bytes = 0; if (secure) fd = open("/dev/random", O_RDONLY); else fd = open("/dev/urandom", O_RDONLY); if (fd < 0) exit_errno("unable to open random device"); while (read_bytes < len) { ssize_t ret = read(fd, ((char *)buffer)+read_bytes, len-read_bytes); if (ret < 0) exit_errno("unable to read from random device"); read_bytes += ret; } close(fd); }
static void read_psched(void) { uint32_t clock_res; uint32_t t2us; uint32_t us2t; FILE *f = fopen("/proc/net/psched", "r"); if (!f || fscanf(f, "%08x %08x %08x", &t2us, &us2t, &clock_res) != 3) exit_errno("error reading /proc/net/psched"); fclose(f); /* compatibility hack from iproute... */ if (clock_res == 1000000000) t2us = us2t; ticks = (double)t2us / us2t * clock_res; }
static struct nl_msg * prepare_tcmsg(int type, int flags, uint32_t parent, uint32_t handle, uint32_t info) { struct nl_msg *msg = nlmsg_alloc_simple(type, flags); if (!msg) exit_errno("nlmsg_alloc_simple"); struct tcmsg tcmsg; memset(&tcmsg, 0, sizeof(tcmsg)); tcmsg.tcm_family = AF_UNSPEC; tcmsg.tcm_ifindex = ifindex; tcmsg.tcm_parent = parent; tcmsg.tcm_handle = handle; tcmsg.tcm_info = info; nlmsg_append(msg, &tcmsg, sizeof(tcmsg), NLMSG_ALIGNTO); return msg; }
/** Resizes a vector Vector allocations are always powers of 2. Internal function, use VECTOR_RESIZE() instead. */ void _fastd_vector_resize(fastd_vector_desc_t *desc, void **data, size_t n, size_t elemsize) { desc->length = n; size_t alloc = desc->allocated; if (!alloc) { alloc = MIN_VECTOR_ALLOC; n = n*3/2; } while (alloc < n) { alloc <<= 1; if (!alloc) { errno = EOVERFLOW; exit_errno("memory allocation error"); } } if (alloc != desc->allocated) { desc->allocated = alloc; *data = fastd_realloc_array(*data, alloc, elemsize); } }