+ return ret;
+}
+
+int lxc_unix_sockaddr(struct sockaddr_un *ret, const char *path)
+{
+ size_t len;
+
+ len = strlen(path);
+ if (len == 0)
+ return minus_one_set_errno(EINVAL);
+ if (path[0] != '/' && path[0] != '@')
+ return minus_one_set_errno(EINVAL);
+ if (path[1] == '\0')
+ return minus_one_set_errno(EINVAL);
+
+ if (len + 1 > sizeof(ret->sun_path))
+ return minus_one_set_errno(EINVAL);
+
+ *ret = (struct sockaddr_un){
+ .sun_family = AF_UNIX,
+ };
+
+ if (path[0] == '@') {
+ memcpy(ret->sun_path + 1, path + 1, len);
+ return (int)(offsetof(struct sockaddr_un, sun_path) + len);
+ }
+
+ memcpy(ret->sun_path, path, len + 1);
+ return (int)(offsetof(struct sockaddr_un, sun_path) + len + 1);
+}
+
+int lxc_unix_connect_type(struct sockaddr_un *addr, int type)
+{
+ __do_close_prot_errno int fd = -EBADF;
+ int ret;
+ ssize_t len;
+
+ fd = socket(AF_UNIX, type | SOCK_CLOEXEC, 0);
+ if (fd < 0) {
+ SYSERROR("Failed to open new AF_UNIX socket");
+ return -1;
+ }
+
+ if (addr->sun_path[0] == '\0')
+ len = strlen(&addr->sun_path[1]);
+ else
+ len = strlen(&addr->sun_path[0]);
+
+ ret = connect(fd, (struct sockaddr *)addr,
+ offsetof(struct sockaddr_un, sun_path) + len);
+ if (ret < 0) {
+ SYSERROR("Failed to bind new AF_UNIX socket");
+ return -1;
+ }
+
+ return move_fd(fd);
+}
+
+int lxc_unix_connect(struct sockaddr_un *addr, int type)
+{
+ return lxc_unix_connect_type(addr, SOCK_STREAM);
+}
+
+int lxc_socket_set_timeout(int fd, int rcv_timeout, int snd_timeout)
+{
+ struct timeval out = {0};
+ int ret;
+
+ out.tv_sec = snd_timeout;
+ ret = setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (const void *)&out,
+ sizeof(out));
+ if (ret < 0)
+ return -1;
+
+ out.tv_sec = rcv_timeout;
+ ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const void *)&out,
+ sizeof(out));
+ if (ret < 0)
+ return -1;
+
+ return 0;