1 /*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library. If not, see
14 * <http://www.gnu.org/licenses/>.
15 *
16 */
17
18 #include <config.h>
19
20 #ifdef WITH_SYS_IOCTL_H
21 # include <sys/ioctl.h>
22 #endif
23
24 #if WITH_DECL_VHOST_VSOCK_SET_GUEST_CID
25 # include <linux/vhost.h>
26 #endif
27
28 #include "virvsock.h"
29
30 #include "virerror.h"
31 #include "virlog.h"
32
33
34 #define VIR_FROM_THIS VIR_FROM_NONE
35
36 VIR_LOG_INIT("util.vsock");
37
38 #if WITH_DECL_VHOST_VSOCK_SET_GUEST_CID
39 static int
virVsockSetGuestCidQuiet(int fd,unsigned int guest_cid)40 virVsockSetGuestCidQuiet(int fd,
41 unsigned int guest_cid)
42 {
43 uint64_t val = guest_cid;
44
45 return ioctl(fd, VHOST_VSOCK_SET_GUEST_CID, &val);
46 }
47
48 #else
49 static int
virVsockSetGuestCidQuiet(int fd G_GNUC_UNUSED,unsigned int guest_cid G_GNUC_UNUSED)50 virVsockSetGuestCidQuiet(int fd G_GNUC_UNUSED,
51 unsigned int guest_cid G_GNUC_UNUSED)
52 {
53 errno = ENOSYS;
54 return -1;
55 }
56 #endif
57
58
59 /**
60 * virVsockSetGuestCid:
61 * @fd: file descriptor of a vsock interface
62 * @guest_cid: guest CID to be set
63 *
64 * Wrapper for VHOST_VSOCK_SET_GUEST_CID ioctl.
65 * Returns: 0 on success, -1 on error.
66 */
67 int
virVsockSetGuestCid(int fd,unsigned int guest_cid)68 virVsockSetGuestCid(int fd,
69 unsigned int guest_cid)
70 {
71 if (virVsockSetGuestCidQuiet(fd, guest_cid) < 0) {
72 virReportSystemError(errno, "%s",
73 _("failed to set guest cid"));
74 return -1;
75 }
76
77 return 0;
78 }
79
80 #define VIR_VSOCK_GUEST_CID_MIN 3
81
82 /**
83 * virVsockAcquireGuestCid:
84 * @fd: file descriptor of a vsock interface
85 * @guest_cid: where to store the guest CID
86 *
87 * Iterates over usable CIDs until a free one is found.
88 * Returns: 0 on success, with the acquired CID stored in guest_cid
89 * -1 on error.
90 */
91 int
virVsockAcquireGuestCid(int fd,unsigned int * guest_cid)92 virVsockAcquireGuestCid(int fd,
93 unsigned int *guest_cid)
94 {
95 unsigned int cid = VIR_VSOCK_GUEST_CID_MIN;
96
97 for (; virVsockSetGuestCidQuiet(fd, cid) < 0; cid++) {
98 if (errno != EADDRINUSE) {
99 virReportSystemError(errno, "%s",
100 _("failed to acquire guest cid"));
101 return -1;
102 }
103 }
104 *guest_cid = cid;
105
106 return 0;
107 }
108