Check which getprotobynumber_r() variant to use
[socat.git] / xio-vsock.c
blob5078e9c99f283e22be24ea7158f03efbcdba4da2
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"
10 #ifdef WITH_VSOCK
11 #include "xioopen.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,
17 int xioflags, xiofile_t *xxfd, unsigned groups, int abstract,
18 int dummy2, int dummy3);
19 static int xioopen_vsock_listen(int argc, const char *argv[], struct opt *opts,
20 int xioflags, xiofile_t *xxfd, unsigned groups, int abstract,
21 int dummy2, int dummy3);
23 const struct addrdesc addr_vsock_connect = { "vsock-connect", 1 + XIO_RDWR,
24 xioopen_vsock_connect,
25 GROUP_FD|GROUP_SOCKET|GROUP_CHILD|GROUP_RETRY,
26 0, 0, 0 HELP(":<cid>:<port>") };
27 #if WITH_LISTEN
28 const struct addrdesc addr_vsock_listen = { "vsock-listen", 1 + XIO_RDWR,
29 xioopen_vsock_listen,
30 GROUP_FD|GROUP_SOCKET|GROUP_LISTEN|GROUP_CHILD|GROUP_RETRY,
31 0, 0, 0 HELP(":<port>") };
32 #endif /* WITH_LISTEN */
34 static int vsock_addr_init(struct sockaddr_vm *sa, const char *cid_str,
35 const char *port_str) {
36 int ret;
38 memset(sa, 0, sizeof(*sa));
40 sa->svm_family = AF_VSOCK;
41 ret = sockaddr_vm_parse(sa, cid_str, port_str);
42 if (ret < 0)
43 return STAT_NORETRY;
45 return STAT_OK;
48 static int vsock_init(struct opt *opts, struct single *xfd) {
50 xfd->howtoend = END_SHUTDOWN;
52 if (applyopts_single(xfd, opts, PH_INIT) < 0)
53 return STAT_NORETRY;
55 applyopts(-1, opts, PH_INIT);
56 applyopts(-1, opts, PH_EARLY);
58 xfd->dtype = XIODATA_STREAM;
60 return STAT_OK;
63 static int xioopen_vsock_connect(int argc, const char *argv[], struct opt *opts,
64 int xioflags, xiofile_t *xxfd, unsigned groups,
65 int abstract, int dummy2, int dummy3) {
66 /* we expect the form :cid:port */
67 struct single *xfd = &xxfd->stream;
68 struct sockaddr_vm sa, sa_local;
69 socklen_t sa_len = sizeof(sa);
70 bool needbind = false;
71 int socktype = SOCK_STREAM;
72 int pf = PF_VSOCK;
73 int protocol = 0;
74 int ret;
76 if (argc != 3) {
77 Error2("%s: wrong number of parameters (%d instead of 2)",
78 argv[0], argc-1);
79 return STAT_NORETRY;
82 ret = vsock_addr_init(&sa, argv[1], argv[2]);
83 if (ret) {
84 return ret;
87 ret = vsock_init(opts, xfd);
88 if (ret) {
89 return ret;
92 ret = retropt_bind(opts, pf, socktype, protocol,
93 (struct sockaddr *)&sa_local, &sa_len, 3, 0, 0);
94 if (ret == STAT_NORETRY)
95 return ret;
96 if (ret == STAT_OK)
97 needbind = true;
99 ret = xioopen_connect(xfd, needbind ? (union sockaddr_union *)&sa_local : NULL,
100 sa_len, (struct sockaddr *)&sa, sizeof(sa),
101 opts, pf, socktype, protocol, false);
102 if (ret)
103 return ret;
105 ret = _xio_openlate(xfd, opts);
106 if (ret < 0)
107 return ret;
109 return STAT_OK;
112 #if WITH_LISTEN
113 static int xioopen_vsock_listen(int argc, const char *argv[], struct opt *opts,
114 int xioflags, xiofile_t *xxfd, unsigned groups, int abstract,
115 int dummy2, int dummy3) {
116 /* we expect the form :port */
117 struct single *xfd = &xxfd->stream;
118 struct sockaddr_vm sa, sa_bind;
119 socklen_t sa_len = sizeof(sa_bind);
120 struct opt *opts0;
121 int socktype = SOCK_STREAM;
122 int pf = PF_VSOCK;
123 int protocol = 0;
124 int ret;
126 if (argc != 2) {
127 Error2("%s: wrong number of parameters (%d instead of 1)",
128 argv[0], argc-1);
129 return STAT_NORETRY;
132 ret = vsock_addr_init(&sa, NULL, argv[1]);
133 if (ret) {
134 return ret;
137 ret = vsock_init(opts, xfd);
138 if (ret) {
139 return ret;
143 unsigned int cid;
144 if (Ioctl(xfd->fd, IOCTL_VM_SOCKETS_GET_LOCAL_CID, &cid) < 0) {
145 Warn2("ioctl(%d, IOCTL_VM_SOCKETS_GET_LOCAL_CID, ...): %s",
146 xfd->fd, strerror(errno));
147 } else {
148 Notice1("VSOCK CID=%u", cid);
152 opts0 = copyopts(opts, GROUP_ALL);
154 ret = retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&sa_bind,
155 &sa_len, 1, 0, 0);
156 if (ret == STAT_NORETRY)
157 return ret;
158 if (ret == STAT_OK)
159 sa.svm_cid = sa_bind.svm_cid;
161 /* this may fork() */
162 return xioopen_listen(xfd, xioflags, (struct sockaddr *)&sa, sizeof(sa),
163 opts, opts0, pf, socktype, protocol);
166 #endif /* WITH_LISTEN */
167 #endif /* WITH_VSOCK */