|
11 | 11 | #include <stdlib.h> |
12 | 12 | #include <string.h> |
13 | 13 | #include <sys/socket.h> |
| 14 | +#include <sys/time.h> |
14 | 15 | #include <sys/un.h> |
| 16 | +#include <linux/vm_sockets.h> |
15 | 17 | #include <libkrun.h> |
16 | 18 | #include <getopt.h> |
17 | 19 | #include <stdbool.h> |
|
23 | 25 | #define MAX_PATH 4096 |
24 | 26 | #endif |
25 | 27 |
|
26 | | -#define IPC_SOCK_PATH "/tmp/krun_nitro_example_ipc.sock" |
| 28 | +#define VMADDR_CID_HYPERVISOR 0 |
| 29 | +#define CID_TO_CONSOLE_PORT_OFFSET 10000 |
| 30 | + |
| 31 | +#define BUFSIZE 512 |
27 | 32 |
|
28 | 33 | static void print_help(char *const name) |
29 | 34 | { |
@@ -84,31 +89,56 @@ bool parse_cmdline(int argc, char *const argv[], struct cmdline *cmdline) |
84 | 89 |
|
85 | 90 | void *listen_enclave_output(void *opaque) |
86 | 91 | { |
87 | | - int ret, fd = (int) opaque, sock, len; |
88 | | - char buf[512]; |
89 | | - struct sockaddr_un client_sockaddr; |
| 92 | + socklen_t addr_sz = sizeof(struct sockaddr_vm); |
| 93 | + struct sockaddr_vm addr; |
| 94 | + int ret, sock_fd, cid; |
| 95 | + struct timeval timeval; |
| 96 | + char buf[BUFSIZE]; |
| 97 | + |
| 98 | + cid = (int) opaque; |
| 99 | + |
| 100 | + sock_fd = socket(AF_VSOCK, SOCK_STREAM, 0); |
| 101 | + if (sock_fd < 0) |
| 102 | + return (void *) -1; |
| 103 | + |
| 104 | + bzero((char *) &addr, sizeof(struct sockaddr_vm)); |
| 105 | + addr.svm_family = AF_VSOCK; |
| 106 | + addr.svm_cid = VMADDR_CID_HYPERVISOR; |
| 107 | + addr.svm_port = cid + CID_TO_CONSOLE_PORT_OFFSET; |
| 108 | + |
| 109 | + // Set vsock timeout limit to 5 seconds. |
| 110 | + memset(&timeval, 0, sizeof(struct timeval)); |
| 111 | + timeval.tv_sec = 5; |
| 112 | + |
| 113 | + ret = setsockopt(sock_fd, AF_VSOCK, SO_VM_SOCKETS_CONNECT_TIMEOUT, |
| 114 | + (void *) &timeval, sizeof(struct timeval)); |
| 115 | + if (ret < 0) { |
| 116 | + close(sock_fd); |
| 117 | + return (void *) -1; |
| 118 | + } |
90 | 119 |
|
91 | | - sock = accept(fd, (struct sockaddr *) &client_sockaddr, &len); |
92 | | - if (sock < 1) |
| 120 | + ret = connect(sock_fd, (struct sockaddr *) &addr, addr_sz); |
| 121 | + if (ret < 0) { |
| 122 | + close(sock_fd); |
93 | 123 | return (void *) -1; |
| 124 | + } |
94 | 125 |
|
| 126 | + bzero(buf, BUFSIZE); |
95 | 127 | for (;;) { |
96 | | - ret = read(sock, &buf, 512); |
| 128 | + ret = read(sock_fd, &buf, BUFSIZE); |
97 | 129 | if (ret <= 0) |
98 | 130 | break; |
99 | | - else if (ret < 512) { |
100 | | - buf[ret] = '\0'; |
101 | | - } |
| 131 | + |
| 132 | + buf[ret] = '\0'; |
102 | 133 |
|
103 | 134 | printf("%s", buf); |
104 | 135 | } |
105 | 136 | } |
106 | 137 |
|
107 | 138 | int main(int argc, char *const argv[]) |
108 | 139 | { |
109 | | - int ret, ctx_id, err, i, sock_fd, enable = 1; |
| 140 | + int ret, cid, ctx_id, err; |
110 | 141 | struct cmdline cmdline; |
111 | | - struct sockaddr_un addr; |
112 | 142 | pthread_t thread; |
113 | 143 |
|
114 | 144 | if (!parse_cmdline(argc, argv, &cmdline)) { |
@@ -161,62 +191,26 @@ int main(int argc, char *const argv[]) |
161 | 191 | return -1; |
162 | 192 | } |
163 | 193 |
|
164 | | - // Create and initialize UNIX IPC socket for reading enclave output. |
165 | | - sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); |
166 | | - if (sock_fd < 0) { |
167 | | - perror("Error creating UNIX IPC socket for enclave communication"); |
168 | | - return -1; |
169 | | - } |
170 | | - memset(&addr, 0, sizeof(struct sockaddr_un)); |
171 | | - addr.sun_family = AF_UNIX; |
172 | | - strcpy(addr.sun_path, IPC_SOCK_PATH); |
173 | | - |
174 | | - // Listen on the socket for enclave output. |
175 | | - unlink(IPC_SOCK_PATH); |
176 | | - ret = bind(sock_fd, (struct sockaddr *) &addr, sizeof(addr)); |
177 | | - if (ret < 0) { |
178 | | - perror("Error binding socket"); |
179 | | - close(sock_fd); |
180 | | - exit(1); |
181 | | - } |
182 | | - |
183 | | - ret = listen(sock_fd, 1); |
184 | | - if (ret < 0) { |
185 | | - perror("Error listening on socket"); |
186 | | - close(sock_fd); |
187 | | - exit(1); |
188 | | - } |
189 | | - |
190 | | - // Configure the IPC socket to read output from the enclave. The "port" |
191 | | - // argument is ignored. |
192 | | - if (err = krun_add_vsock_port(ctx_id, 0, IPC_SOCK_PATH)) { |
193 | | - close(sock_fd); |
| 194 | + /* |
| 195 | + * Start and enter the microVM. In the libkrun-nitro flavor, a positive |
| 196 | + * value returned by krun_start_enter() is the enclave's CID. |
| 197 | + */ |
| 198 | + cid = krun_start_enter(ctx_id); |
| 199 | + if (cid < 0) { |
194 | 200 | errno = -err; |
195 | | - perror("Error configuring enclave vsock"); |
| 201 | + perror("Error creating the microVM"); |
196 | 202 | return -1; |
197 | 203 | } |
198 | 204 |
|
199 | | - ret = pthread_create(&thread, NULL, listen_enclave_output, |
200 | | - (void *) sock_fd); |
| 205 | + ret = pthread_create(&thread, NULL, listen_enclave_output, (void *) cid); |
201 | 206 | if (ret < 0) { |
202 | 207 | perror("unable to create new listener thread"); |
203 | | - close(sock_fd); |
204 | 208 | exit(1); |
205 | 209 | } |
206 | 210 |
|
207 | | - // Start and enter the microVM. Unless there is some error while creating the microVM |
208 | | - // this function never returns. |
209 | | - if (err = krun_start_enter(ctx_id)) { |
210 | | - close(sock_fd); |
211 | | - errno = -err; |
212 | | - perror("Error creating the microVM"); |
213 | | - return -1; |
214 | | - } |
215 | | - |
216 | 211 | ret = pthread_join(thread, NULL); |
217 | 212 | if (ret < 0) { |
218 | 213 | perror("unable to join listener thread"); |
219 | | - close(sock_fd); |
220 | 214 | exit(1); |
221 | 215 | } |
222 | 216 |
|
|
0 commit comments