1 /* source: xio-vsock.c */
2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
3 /* Author: Stefano Garzarella <sgarzare@redhat.com */
4 /* Published under the GNU General Public License V.2, see file COPYING */
6 /* This file contains the source for opening addresses of VSOCK socket type */
8 #include "xiosysincludes.h"
12 #include "xio-listen.h"
13 #include "xio-socket.h"
14 #include "xio-vsock.h"
16 static int xioopen_vsock_connect(int argc
, const char *argv
[], struct opt
*opts
, int xioflags
, xiofile_t
*xxfd
, const struct addrdesc
*addrdesc
);
17 static int xioopen_vsock_listen(int argc
, const char *argv
[], struct opt
*opts
, int xioflags
, xiofile_t
*xxfd
, const struct addrdesc
*addrdesc
);
19 static void xiolog_vsock_cid(void);
21 const struct addrdesc xioaddr_vsock_connect
= { "VSOCK-CONNECT", 1+XIO_RDWR
, xioopen_vsock_connect
, GROUP_FD
|GROUP_SOCKET
|GROUP_CHILD
|GROUP_RETRY
, 0, 0, 0 HELP(":<cid>:<port>") };
23 const struct addrdesc xioaddr_vsock_listen
= { "VSOCK-LISTEN", 1+XIO_RDWR
, xioopen_vsock_listen
, GROUP_FD
|GROUP_SOCKET
|GROUP_LISTEN
|GROUP_CHILD
|GROUP_RETRY
, 0, 0, 0 HELP(":<port>") };
24 #endif /* WITH_LISTEN */
27 /* Initializes a sockaddr of type VSOCK */
28 static int vsock_addr_init(struct sockaddr_vm
*sa
, const char *cid_str
,
29 const char *port_str
, int pf
) {
32 memset(sa
, 0, sizeof(*sa
));
35 ret
= sockaddr_vm_parse(sa
, cid_str
, port_str
);
43 /* Performs a few steps during opening an address of type VSOCK */
44 static int vsock_init(struct opt
*opts
, struct single
*sfd
) {
46 if (sfd
->howtoend
== END_UNSPEC
)
47 sfd
->howtoend
= END_SHUTDOWN
;
49 if (applyopts_single(sfd
, opts
, PH_INIT
) < 0)
52 applyopts(sfd
, -1, opts
, PH_INIT
);
53 applyopts(sfd
, -1, opts
, PH_EARLY
);
55 sfd
->dtype
= XIODATA_STREAM
;
60 static int xioopen_vsock_connect(
66 const struct addrdesc
*addrdesc
)
68 /* we expect the form :cid:port */
69 struct single
*sfd
= &xxfd
->stream
;
70 struct sockaddr_vm sa
, sa_local
;
71 socklen_t sa_len
= sizeof(sa
);
72 bool needbind
= false;
73 int socktype
= SOCK_STREAM
;
79 xio_syntax(argv
[0], 2, argc
-1, addrdesc
->syntax
);
83 retropt_socket_pf(opts
, &pf
);
84 retropt_int(opts
, OPT_SO_TYPE
, &socktype
);
85 retropt_int(opts
, OPT_SO_PROTOTYPE
, &protocol
);
87 ret
= vsock_addr_init(&sa
, argv
[1], argv
[2], pf
);
92 ret
= vsock_init(opts
, sfd
);
99 ret
= retropt_bind(opts
, pf
, socktype
, protocol
,
100 (struct sockaddr
*)&sa_local
, &sa_len
, 3,
101 sfd
->para
.socket
.ip
.ai_flags
);
102 if (ret
== STAT_NORETRY
)
107 ret
= xioopen_connect(sfd
, needbind
? (union sockaddr_union
*)&sa_local
: NULL
,
108 sa_len
, (struct sockaddr
*)&sa
, sizeof(sa
),
109 opts
, pf
, socktype
, protocol
, false);
113 ret
= _xio_openlate(sfd
, opts
);
122 static int xioopen_vsock_listen(
128 const struct addrdesc
*addrdesc
)
130 /* we expect the form :port */
131 struct single
*sfd
= &xxfd
->stream
;
132 struct sockaddr_vm sa
, sa_bind
;
133 socklen_t sa_len
= sizeof(sa_bind
);
135 int socktype
= SOCK_STREAM
;
141 xio_syntax(argv
[0], 1, argc
-1, addrdesc
->syntax
);
145 retropt_socket_pf(opts
, &pf
);
146 retropt_int(opts
, OPT_SO_TYPE
, &socktype
);
147 retropt_int(opts
, OPT_SO_PROTOTYPE
, &protocol
);
149 ret
= vsock_addr_init(&sa
, NULL
, argv
[1], pf
);
154 ret
= vsock_init(opts
, sfd
);
159 opts0
= copyopts(opts
, GROUP_ALL
);
161 ret
= retropt_bind(opts
, pf
, socktype
, protocol
, (struct sockaddr
*)&sa_bind
,
163 sfd
->para
.socket
.ip
.ai_flags
);
164 if (ret
== STAT_NORETRY
)
167 sa
.svm_cid
= sa_bind
.svm_cid
;
171 /* this may fork() */
172 return xioopen_listen(sfd
, xioflags
, (struct sockaddr
*)&sa
, sizeof(sa
),
173 opts
, opts0
, pf
, socktype
, protocol
);
175 #endif /* WITH_LISTEN */
178 /* Just tries to query and log the VSOCK CID */
179 static void xiolog_vsock_cid(void) {
182 #ifdef IOCTL_VM_SOCKETS_GET_LOCAL_CID
183 if ((vsock
= Open("/dev/vsock", O_RDONLY
, 0)) < 0 ) {
184 Warn1("open(\"/dev/vsock\", ...): %s", strerror(errno
));
185 } else if (Ioctl(vsock
, IOCTL_VM_SOCKETS_GET_LOCAL_CID
, &cid
) < 0) {
186 Warn2("ioctl(%d, IOCTL_VM_SOCKETS_GET_LOCAL_CID, ...): %s",
187 vsock
, strerror(errno
));
189 Notice1("VSOCK CID=%u", cid
);
194 #endif /* IOCTL_VM_SOCKETS_GET_LOCAL_CID */
199 /* Returns information that can be used for constructing an environment
200 variable describing the socket address.
201 if idx is 0, this function writes "ADDR" into namebuff and the CID address
202 into valuebuff, and returns 1 (which means that one more info is there).
203 if idx is 1, it writes "PORT" into namebuff and the port number into
204 valuebuff, and returns 0 (no more info)
205 namelen and valuelen contain the max. allowed length of output chars in the
207 on error this function returns -1.
210 xiosetsockaddrenv_vsock(int idx
, char *namebuff
, size_t namelen
,
211 char *valuebuff
, size_t valuelen
,
212 struct sockaddr_vm
*sa
, int ipproto
) {
215 strcpy(namebuff
, "ADDR");
216 snprintf(valuebuff
, valuelen
, F_uint32_t
, sa
->svm_cid
);
219 strcpy(namebuff
, "PORT");
220 snprintf(valuebuff
, valuelen
, F_uint32_t
, sa
->svm_port
);
226 #endif /* WITH_VSOCK */