1 /* SPDX-License-Identifier: GPL-2.0-only */
11 #include <linux/sockios.h>
12 #include <libmnl/libmnl.h>
13 #include <linux/if_link.h>
14 #include <linux/rtnetlink.h>
17 void die(const char *fmt, ...)
24 ret = vasprintf(&str, fmt, argp);
26 if (ret < 0) { /* give up */
30 m7a_log(LL_EMERG, "%s\n", str);
34 void die_errno(const char *fmt, ...)
38 int ret, save_errno = errno;
41 ret = vasprintf(&str, fmt, argp);
47 m7a_log(LL_EMERG, "%s: %s\n", str, strerror(save_errno));
51 void *xrealloc(void *p, size_t size)
54 assert((p = realloc(p, size)));
58 void *xmalloc(size_t size)
60 return xrealloc(NULL, size);
63 void *xzmalloc(size_t size)
65 void *p = xrealloc(NULL, size);
70 void *xstrdup(const char *s)
72 char *ret = strdup(s? s: "");
78 char *msg(const char *fmt, ...)
88 /* Try to print in the allocated space. */
90 n = vsnprintf(m, size, fmt, ap);
92 /* If that worked, return the string. */
95 /* Else try again with more space. */
96 size = n + 1; /* precisely what is needed */
97 m = xrealloc(m, size);
101 char *xstrcat(char *a, const char *b)
109 tmp = msg("%s%s", a, b);
114 void die_empty_arg(const char *opt)
116 die("argument to --%s must not be empty", opt);
119 __attribute__ ((noreturn))
120 static void die_range(const char *opt)
122 die("argument to --%s is out of range", opt);
125 void check_range(uint32_t val, uint32_t min, uint32_t max, const char *opt)
127 if (val < min || val > max)
131 bool fd2buf(int fd, const struct iovec *iov)
133 ssize_t ret, nread = 0, max;
134 char *buf = iov->iov_base;
136 assert(iov->iov_len > 1);
137 max = iov->iov_len - 1;
139 ret = read(fd, buf + nread, max - nread);
141 if (errno == EAGAIN || errno == EINTR)
143 ERROR_LOG("read error: %s\n", strerror(errno));
148 DEBUG_LOG("read %zd bytes\n", nread);
153 ERROR_LOG("cmd output truncated\n");
159 bool xexec(char * const argv[], const struct iovec *iov)
162 int pipefd[2] = {-1, -1};
165 for (n = 0; argv[n]; n++)
166 DEBUG_LOG("argv[%u]=%s\n", n, argv[n]);
168 if (pipe(pipefd) < 0)
171 if ((pid = fork()) < 0)
173 if (pid > 0) { /* parent */
178 success = fd2buf(pipefd[0], iov);
181 if (waitpid(pid, &wstatus, 0) < 0)
185 if (!WIFEXITED(wstatus))
187 if (WEXITSTATUS(wstatus) != EXIT_SUCCESS)
193 if (pipefd[1] >= 0 && pipefd[1] != STDOUT_FILENO) {
194 if (dup2(pipefd[1], STDOUT_FILENO) < 0)
198 execvp(argv[0], argv);
199 EMERG_LOG("execvp error: %s\n", strerror(errno));
203 void valid_fd012(void)
205 /* Ensure that file descriptors 0, 1, and 2 are valid. */
207 int fd = open("/dev/null", O_RDWR);
217 void check_name(const char *arg)
226 die("name too long: %s", arg);
227 for (m = 0; m < len; m++) {
231 if (!isalnum(c) && c != '-')
236 die("invalid character '%c' in name %s", c, arg);
239 /* allocates two new strings that should be freed by the caller */
240 void parse_compound_arg(const char *arg, const char *opt, char **name, char **val)
247 p = strchr(copy, ':');
249 die("could not parse argument to --%s", opt);
257 char *parse_cgroup_acl(const char *arg)
259 if (!strncmp(arg, "allow ", 6))
260 return msg("a%s", arg + 6);
261 if (!strncmp(arg, "deny ", 5))
262 return msg("d%s", arg + 5);
263 die("invalid cgroup access specifier: %s", arg);
266 void parse_ifspec(const char *arg, char **bridge, uint8_t *hwaddr)
268 const char *colon = strchr(arg, ':');
274 *bridge = xmalloc(len + 1);
275 memcpy(*bridge, arg, len);
276 (*bridge)[len] = '\0';
278 *bridge = xstrdup(arg);
281 memset(hwaddr, 0, 6);
284 if (sscanf(colon + 1, "%02x:%02x:%02x:%02x:%02x:%02x",
285 x, x + 1, x + 2, x + 3, x + 4, x + 5) != 6)
286 die("invalid hwaddress for ifspec %s", arg);
287 if (colon[1 + 6 * 2 + 5] != '\0')
288 die("trailing garbage at the end of ifspec %s", arg);
289 for (n = 0; n < 6; n++)
293 uint32_t atou32(const char *str, const char *opt)
298 errno = 0; /* To distinguish success/failure after call */
299 tmp = strtoll(str, &endptr, 10);
300 if (errno == ERANGE && (tmp == LLONG_MAX || tmp == LLONG_MIN))
302 if (tmp < 0 || tmp > (uint32_t)-1)
305 * If there were no digits at all, strtoll() stores the original value
311 * The implementation may also set errno and return 0 in case no
312 * conversion was performed.
314 if (errno != 0 && tmp == 0)
316 if (*endptr != '\0') /* Further characters after number */
317 die("--%s: trailing characters after number", opt);
321 bool remove_subdirs_recursively(const char *path)
323 DIR *d = opendir(path);
324 struct dirent *entry;
329 ERROR_LOG("opendir %s: %m\n", path);
334 while ((entry = readdir(d))) {
336 if (!strcmp(entry->d_name, "."))
338 if (!strcmp(entry->d_name, ".."))
340 if (fstatat(dfd, entry->d_name, &stat, 0) == -1) {
341 WARNING_LOG("%s/%s: %m", path, entry->d_name);
344 if (!S_ISDIR(stat.st_mode))
346 subpath = msg("%s/%s", path, entry->d_name);
347 remove_subdirs_recursively(subpath);
348 DEBUG_LOG("removing %s\n", subpath);
349 if (rmdir(subpath) < 0) {
350 ERROR_LOG("rmdir %s: %m\n", subpath);
359 void daemonize(const char *logfile)
364 if ((pid = fork()) < 0)
366 if (pid) /* parent exits */
369 /* become session leader */
372 if ((nullfd = open("/dev/null", O_RDWR)) < 0)
373 die_errno("open /dev/null");
374 logfile = logfile? logfile : "/dev/null";
375 if ((logfd = open(logfile, O_WRONLY | O_APPEND | O_CREAT, 0666)) < 0)
376 die_errno("open %s", logfile);
377 NOTICE_LOG("subsequent log messages go to %s\n", logfile);
378 if (dup2(nullfd, STDIN_FILENO) < 0)
381 if (dup2(logfd, STDOUT_FILENO) < 0)
383 if (dup2(logfd, STDERR_FILENO) < 0)
390 static int super_dull_hash(const char *input)
392 const uint8_t *x = (typeof(x))input;
393 const unsigned p1 = 16777619, p2 = 2971215073;
394 unsigned n, m, h, result = 0;
396 for (n = 0; n < 4; n++) {
398 for (m = 1; x[m] != 0; m++)
400 result = (result << 8) | (h % 256);
406 * We use a semaphore set with two semaphores. The first semaphore is modified
407 * in all locking related functions while the second semaphore is modified only
408 * in try_lock() and aquire_lock(). This allows us to obtain the PID of the
409 * lock holder by querying the PID that last performed an operation on the
410 * second semaphore. This is achieved by passing GETPID as the control
411 * operation to semctl().
414 static bool get_lock(const char *string, pid_t *pid, bool wait)
417 struct sembuf sops[4];
418 key_t key = super_dull_hash(string);
420 short sem_flg = SEM_UNDO;
423 sem_flg |= IPC_NOWAIT;
424 ret = semget(key, 2, IPC_CREAT | 0600);
426 ERROR_LOG("semget: %m\n");
430 DEBUG_LOG("key: 0x%0x, semid: %d\n", (unsigned)key, semid);
431 ret = semctl(semid, 1, GETPID);
438 sops[0].sem_flg = sem_flg;
442 sops[1].sem_flg = sem_flg;
446 sops[2].sem_flg = sem_flg;
450 sops[3].sem_flg = sem_flg;
452 success = semop(semid, sops, 4) >= 0;
454 INFO_LOG("semop: %m\n");
458 bool try_lock(const char *string, pid_t *pid)
460 return get_lock(string, pid, false /* don't wait */);
463 bool acquire_lock(const char *string)
465 return get_lock(string, NULL /* don't need pid */, true /* do wait */);
468 bool release_lock(const char *string)
471 struct sembuf sops[2];
472 key_t key = super_dull_hash(string);
475 ret = semget(key, 2, IPC_CREAT | 0600);
477 ERROR_LOG("semget: %m\n");
481 DEBUG_LOG("key: 0x%0x, semid: %d\n", (unsigned)key, semid);
484 sops[0].sem_flg = SEM_UNDO;
487 sops[1].sem_flg = SEM_UNDO;
488 success = semop(semid, sops, 2) >= 0;
490 INFO_LOG("semop: %m\n");
494 bool is_locked(const char *string, pid_t *pid)
497 struct sembuf sops = {
500 .sem_flg = SEM_UNDO | IPC_NOWAIT
502 key_t key = super_dull_hash(string);
506 ret = semget(key, 2, 0);
510 DEBUG_LOG("key: 0x%0x, semid: %d\n", (unsigned)key, semid);
511 if (semop(semid, &sops, 1) >= 0)
513 ret = semctl(semid, 1, GETPID);
521 bool attach_to_bridge(const char *iface, const char *bridge)
527 INFO_LOG("adding interface %s to bridge %s\n", iface, bridge);
528 if (!(idx = if_nametoindex(iface))) {
529 ERROR_LOG("no index for %s: %m\n", iface);
532 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
533 ERROR_LOG("socket: %m\n");
536 strncpy(ifr.ifr_name, bridge, IFNAMSIZ - 1);
537 ifr.ifr_name[IFNAMSIZ - 1] = '\0';
538 ifr.ifr_ifindex = idx;
539 success = ioctl(fd, SIOCBRADDIF, &ifr) == 0;
541 ERROR_LOG("interface %s, bridge %s: ioctl SIOCBRADDIF: %m\n",
548 #define NLMSG_TAIL(nmsg) \
549 ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
551 static void addattr_l(struct nlmsghdr *nlh, int type, const void *data,
554 int len = RTA_LENGTH(alen);
557 rta = NLMSG_TAIL(nlh);
558 rta->rta_type = type;
561 memcpy(RTA_DATA(rta), data, alen);
562 nlh->nlmsg_len = NLMSG_ALIGN(nlh->nlmsg_len) + RTA_ALIGN(len);
565 static struct rtattr *addattr_nest(struct nlmsghdr *n, int type)
567 struct rtattr *nest = NLMSG_TAIL(n);
568 addattr_l(n, type, NULL, 0);
572 static void end_nest(struct nlmsghdr *nlh, struct rtattr *attr)
574 attr->rta_len = (void *)NLMSG_TAIL(nlh) - (void *)attr;
577 static struct mnl_socket *get_and_bind_netlink_socket(void)
579 struct mnl_socket *nl = mnl_socket_open(NETLINK_ROUTE);
582 ERROR_LOG("mnl_socket_open error\n");
585 if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
586 ERROR_LOG("mnl_socket_bind\n");
587 mnl_socket_close(nl);
593 static struct nlmsghdr *prepare_netlink_msg_header(char *buf)
595 struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
596 nlh->nlmsg_flags = NLM_F_REQUEST;
597 nlh->nlmsg_seq = time(NULL);
601 bool rename_interface(const char *before, const char *after)
604 struct mnl_socket *nl;
605 char buf[MNL_SOCKET_BUFFER_SIZE];
606 struct nlmsghdr *nlh;
607 struct ifinfomsg *ifm;
610 INFO_LOG("%s -> %s\n", before, after);
611 if (!(idx = if_nametoindex(before))) {
612 ERROR_LOG("no index for %s\n", before);
615 if (!(nl = get_and_bind_netlink_socket()))
618 nlh = prepare_netlink_msg_header(buf);
619 nlh->nlmsg_type = RTM_NEWLINK;
621 ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
622 ifm->ifi_family = AF_UNSPEC;
623 ifm->ifi_index = idx;
624 addattr_l(nlh, IFLA_IFNAME, after, strlen(after) + 1);
625 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
626 ERROR_LOG("mnl_socket_sendto failed\n");
632 mnl_socket_close(nl);
636 void pretty_print_hwaddr(const uint8_t *hwaddr, char *result)
638 sprintf(result, "%02x:%02x:%02x:%02x:%02x:%02x", hwaddr[0], hwaddr[1],
639 hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
642 bool set_hwaddr(const char *iface, const uint8_t *hwaddr)
644 struct mnl_socket *nl;
645 char buf[MNL_SOCKET_BUFFER_SIZE];
646 struct nlmsghdr *nlh;
647 struct ifinfomsg *ifm;
649 const uint8_t zero[6] = {0};
650 char pretty_hwaddr[18];
652 if (!memcmp(hwaddr, zero, 6))
653 return true; /* no hwaddr specified, nothing to do */
654 pretty_print_hwaddr(hwaddr, pretty_hwaddr);
655 INFO_LOG("hardware address of %s: %s\n", iface, pretty_hwaddr);
656 if (!(nl = get_and_bind_netlink_socket()))
659 nlh = prepare_netlink_msg_header(buf);
660 nlh->nlmsg_type = RTM_NEWLINK;
662 ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
663 ifm->ifi_family = AF_UNSPEC;
664 addattr_l(nlh, IFLA_ADDRESS, hwaddr, 6);
665 addattr_l(nlh, IFLA_IFNAME, iface, strlen(iface) + 1);
666 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
667 ERROR_LOG("%s: mnl_socket_sendto failed\n", iface);
673 mnl_socket_close(nl);
677 bool link_del(const char *iface)
679 struct mnl_socket *nl;
680 char buf[MNL_SOCKET_BUFFER_SIZE];
681 struct nlmsghdr *nlh;
682 struct ifinfomsg *ifm;
685 INFO_LOG("removing interface %s\n", iface);
686 if (!(nl = get_and_bind_netlink_socket()))
689 nlh = prepare_netlink_msg_header(buf);
690 nlh->nlmsg_type = RTM_DELLINK;
692 ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
693 ifm->ifi_family = AF_UNSPEC;
694 ifm->ifi_change = IFF_UP;
695 ifm->ifi_flags = IFF_UP;
696 addattr_l(nlh, IFLA_IFNAME, iface, strlen(iface) + 1);
697 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
698 ERROR_LOG("%s: mnl_socket_sendto failed\n", iface);
704 mnl_socket_close(nl);
708 bool link_up(const char *iface)
710 struct mnl_socket *nl;
711 char buf[MNL_SOCKET_BUFFER_SIZE];
712 struct nlmsghdr *nlh;
713 struct ifinfomsg *ifm;
716 INFO_LOG("activating interface %s\n", iface);
717 if (!(nl = get_and_bind_netlink_socket()))
719 nlh = prepare_netlink_msg_header(buf);
720 nlh->nlmsg_type = RTM_NEWLINK;
722 ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
723 ifm->ifi_family = AF_UNSPEC;
724 ifm->ifi_change = IFF_UP;
725 ifm->ifi_flags = IFF_UP;
726 addattr_l(nlh, IFLA_IFNAME, iface, strlen(iface) + 1);
727 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
728 ERROR_LOG("%s: mnl_socket_sendto failed\n", iface);
734 mnl_socket_close(nl);
738 #ifndef VETH_INFO_PEER
739 #define VETH_INFO_PEER 1
742 bool create_veth_device_pair(const char *name, char *peer)
744 struct mnl_socket *nl;
745 char buf[MNL_SOCKET_BUFFER_SIZE];
746 struct rtattr *n1, *n2, *n3;
747 struct nlmsghdr *nlh;
748 struct ifinfomsg *ifm;
751 INFO_LOG("new pair: %s <-> %s\n", name, peer);
752 if (!(nl = get_and_bind_netlink_socket()))
755 nlh = prepare_netlink_msg_header(buf);
756 nlh->nlmsg_type = RTM_NEWLINK;
757 nlh->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
759 ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
760 ifm->ifi_family = AF_UNSPEC;
761 n1 = addattr_nest(nlh, IFLA_LINKINFO);
762 addattr_l(nlh, IFLA_INFO_KIND, "veth", 5);
763 n2 = addattr_nest(nlh, IFLA_INFO_DATA);
764 n3 = addattr_nest(nlh, VETH_INFO_PEER);
765 ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
766 ifm->ifi_family = AF_UNSPEC;
767 addattr_l(nlh, IFLA_IFNAME, peer, strlen(peer) + 1);
771 addattr_l(nlh, IFLA_IFNAME, name, strlen(name) + 1);
772 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
773 ERROR_LOG("%s: mnl_socket_sendto\n", name);
779 mnl_socket_close(nl);
783 bool set_netns(const char *iface, pid_t pid)
785 struct mnl_socket *nl;
786 char buf[MNL_SOCKET_BUFFER_SIZE];
787 struct nlmsghdr *nlh;
788 struct ifinfomsg *ifm;
790 INFO_LOG("changing net namespace of interface %s to pid %d\n",
792 if (!(nl = get_and_bind_netlink_socket()))
795 nlh = prepare_netlink_msg_header(buf);
796 nlh->nlmsg_type = RTM_NEWLINK;
798 ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
799 ifm->ifi_family = AF_UNSPEC;
802 addattr_l(nlh, IFLA_NET_NS_PID, &pid, sizeof(pid));
803 mnl_attr_put_str(nlh, IFLA_IFNAME, iface);
805 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
806 ERROR_LOG("%s: mnl_socket_sendto failed\n", iface);
809 mnl_socket_close(nl);
813 #ifndef UNIX_PATH_MAX
814 #define UNIX_PATH_MAX (sizeof(((struct sockaddr_un *)0)->sun_path))
817 static bool init_unix_socket(const char *socket_path, int *socketfd,
818 struct sockaddr_un *sau)
823 if (strlen(socket_path) + 1 >= UNIX_PATH_MAX) {
824 ERROR_LOG("socket path to long: %s\n", socket_path);
827 memset(sau, 0, sizeof(struct sockaddr_un));
828 sau->sun_family = PF_UNIX;
829 sau->sun_path[0] = '\0'; /* use the abstract socket namespace */
830 strcpy(sau->sun_path + 1, socket_path);
831 fd = socket(PF_UNIX, SOCK_STREAM, 0);
833 ERROR_LOG("socket: %m\n");
840 bool listen_on_unix_socket(const char *socket_path, int *result)
842 struct sockaddr_un sau;
844 bool success = false;
846 if (!init_unix_socket(socket_path, &fd, &sau))
848 flags = fcntl(fd, F_GETFL);
850 ERROR_LOG("fcntl (F_GETFL): %m\n");
853 flags = fcntl(fd, F_SETFL, ((long)flags) | O_NONBLOCK);
855 ERROR_LOG("fcntl (F_SETFL): %m\n");
858 if (bind(fd, (struct sockaddr *)&sau, sizeof(sau)) < 0) {
859 ERROR_LOG("bind: %m\n");
862 if (listen(fd , 5) < 0) {
863 ERROR_LOG("listen: %m\n");
867 NOTICE_LOG("listening on fd %d\n", fd);
874 * Send a buffer and the credentials of the current process to a socket.
876 * buf must be zero-terminated.
877 * return the return value of the underlying call to sendmsg().
879 static bool send_cred_buffer(int sock, char *buf)
881 char control[255] __attribute__((__aligned__(8)));
883 struct cmsghdr *cmsg;
884 static struct iovec iov;
889 iov.iov_len = strlen(buf) + 1;
893 /* compose the message */
894 memset(&msg, 0, sizeof(msg));
897 msg.msg_control = control;
898 msg.msg_controllen = sizeof(control);
899 /* attach the ucred struct */
900 cmsg = CMSG_FIRSTHDR(&msg);
901 cmsg->cmsg_level = SOL_SOCKET;
902 cmsg->cmsg_type = SCM_CREDENTIALS;
903 cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
904 *(struct ucred *)CMSG_DATA(cmsg) = c;
905 msg.msg_controllen = cmsg->cmsg_len;
906 if (sendmsg(sock, &msg, 0) < 0) {
907 ERROR_LOG("sendmsg: %m\n");
913 static void dispose_fds(int *fds, unsigned num)
917 for (i = 0; i < num; i++)
921 /* Receive a buffer and the Unix credentials of the sending process. */
922 bool recv_cred_buffer(int socketfd, char *buf, size_t size,
923 int *clientfd, uid_t *uid)
925 char control[255] __attribute__((__aligned__(8)));
927 struct cmsghdr *cmsg;
929 int yes = 1, cfd, ret;
931 struct sockaddr_un sau;
932 socklen_t sizeof_sau = sizeof(sau);
934 ret = accept(socketfd, (struct sockaddr *)&sau, &sizeof_sau);
936 ERROR_LOG("accept: %m\n");
940 setsockopt(cfd, SOL_SOCKET, SO_PASSCRED, &yes, sizeof(int));
941 memset(&msg, 0, sizeof(msg));
946 msg.msg_control = control;
947 msg.msg_controllen = sizeof(control);
948 if (recvmsg(cfd, &msg, 0) < 0) {
949 ERROR_LOG("recvmsg: %m\n");
952 cmsg = CMSG_FIRSTHDR(&msg);
954 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type
955 == SCM_CREDENTIALS) {
956 memcpy(&cred, CMSG_DATA(cmsg), sizeof(struct ucred));
961 if (cmsg->cmsg_level == SOL_SOCKET
962 && cmsg->cmsg_type == SCM_RIGHTS) {
963 dispose_fds((int *)CMSG_DATA(cmsg),
964 (cmsg->cmsg_len - CMSG_LEN(0))
967 cmsg = CMSG_NXTHDR(&msg, cmsg);
975 bool pass_fd(int passfd, int socketfd)
977 struct msghdr msg = {.msg_iov = NULL};
978 struct cmsghdr *cmsg;
979 char control[255] __attribute__((__aligned__(8)));
984 iov.iov_len = sizeof(buf);
989 msg.msg_control = control;
990 msg.msg_controllen = sizeof(control);
992 cmsg = CMSG_FIRSTHDR(&msg);
993 cmsg->cmsg_level = SOL_SOCKET;
994 cmsg->cmsg_type = SCM_RIGHTS;
995 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
996 *(int *)CMSG_DATA(cmsg) = passfd;
998 /* Sum of the length of all control messages in the buffer */
999 msg.msg_controllen = cmsg->cmsg_len;
1000 DEBUG_LOG("passing %s and fd %d\n", buf, passfd);
1001 if (sendmsg(socketfd, &msg, 0) < 0) {
1002 ERROR_LOG("sendmsg: %m\n");
1008 static bool recv_fd(int socketfd, int *recvfd)
1010 char control[255] __attribute__((__aligned__(8)));
1011 struct msghdr msg = {.msg_iov = NULL};
1012 struct cmsghdr *cmsg;
1015 ssize_t sz = sizeof(buf), ssz;
1019 iov.iov_len = sz - 1;
1022 msg.msg_control = control;
1023 msg.msg_controllen = sizeof(control);
1025 ssz = recvmsg(socketfd, &msg, 0);
1027 ERROR_LOG("recvmsg: %m\n");
1031 INFO_LOG("server response: %u (%s)\n", (unsigned)buf[0], buf + 1);
1032 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1033 if (cmsg->cmsg_level != SOL_SOCKET
1034 || cmsg->cmsg_type != SCM_RIGHTS)
1036 if ((cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int) != 1)
1038 *recvfd = *(int *)CMSG_DATA(cmsg);
1044 int request_fd(const char *socket_path, char *msg, int *result)
1046 struct sockaddr_un sau;
1047 int socketfd, receivefd;
1049 if (!init_unix_socket(socket_path, &socketfd, &sau))
1050 die("could not init socket");
1051 if (connect(socketfd, (struct sockaddr *)&sau, sizeof(sau)) < 0)
1052 die_errno("connect");
1053 if (!send_cred_buffer(socketfd, msg))
1054 die("could not send cred buffer");
1055 if (!recv_fd(socketfd, &receivefd))
1056 die("did not receive tty fd");
1057 NOTICE_LOG("received fd %d\n", receivefd);
1058 *result = receivefd;
1062 bool request_int(const char *socket_path, char *msg, int *result)
1064 struct sockaddr_un sau;
1066 bool success = false;
1071 if (!init_unix_socket(socket_path, &socketfd, &sau))
1073 if (connect(socketfd, (struct sockaddr *)&sau, sizeof(sau)) < 0) {
1074 ERROR_LOG("connect: %m\n");
1077 if (!send_cred_buffer(socketfd, msg)) {
1078 ERROR_LOG("could not send cred msg \"%s\"\n", msg);
1081 ssz = read(socketfd, buf, sizeof(buf) - 1);
1083 ERROR_LOG("did not receive integer: %m\n");
1087 ERROR_LOG("did not receive integer: %s\n", buf + 1);
1090 if (ssz != sizeof(int) + 1) {
1091 ERROR_LOG("protocol mismatch, server msg: %s\n", buf + 1);
1094 memcpy(result, buf + 1, sizeof(int));
1095 DEBUG_LOG("received integer: %d\n", *result);
1104 static void signal_handler(int signum)
1107 int save_errno = errno;
1108 assert(signum > 0 && signum < 256);
1109 if (write(signal_pipe[1], &u, 1) < 0)
1110 ERROR_LOG("write to signal pipe: %m\n");
1114 void init_signal_handling(void)
1116 struct sigaction act;
1118 if (pipe(signal_pipe) < 0)
1119 die_errno("signal pipe");
1120 act.sa_handler = signal_handler;
1121 sigemptyset(&act.sa_mask);
1122 act.sa_flags = SA_RESTART;
1123 if (sigaction(SIGINT, &act, NULL) < 0)
1124 die_errno("sigaction");
1125 if (sigaction(SIGTERM, &act, NULL) < 0)
1126 die_errno("sigaction");
1127 if (sigaction(SIGCHLD, &act, NULL) < 0)
1128 die_errno("sigaction");
1131 int next_signal(void)
1135 if (read(signal_pipe[0], &u, 1) < 0) {
1140 DEBUG_LOG("process %d received signal %u\n", getpid(), u);