1 /*
2 * virnetserverservice.c: generic network RPC server service
3 *
4 * Copyright (C) 2006-2012, 2014 Red Hat, Inc.
5 * Copyright (C) 2006 Daniel P. Berrange
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see
19 * <http://www.gnu.org/licenses/>.
20 */
21
22 #include <config.h>
23
24 #include "virnetserverservice.h"
25
26 #include <unistd.h>
27
28 #include "viralloc.h"
29 #include "virerror.h"
30 #include "virthread.h"
31 #include "virlog.h"
32
33 #define VIR_FROM_THIS VIR_FROM_RPC
34
35 VIR_LOG_INIT("rpc.netserverservice");
36
37 struct _virNetServerService {
38 virObject parent;
39
40 size_t nsocks;
41 virNetSocket **socks;
42
43 int auth;
44 bool readonly;
45 size_t nrequests_client_max;
46 int timer;
47 bool timerActive;
48
49 virNetTLSContext *tls;
50
51 virNetServerServiceDispatchFunc dispatchFunc;
52 void *dispatchOpaque;
53 };
54
55
56 static virClass *virNetServerServiceClass;
57 static void virNetServerServiceDispose(void *obj);
58
virNetServerServiceOnceInit(void)59 static int virNetServerServiceOnceInit(void)
60 {
61 if (!VIR_CLASS_NEW(virNetServerService, virClassForObject()))
62 return -1;
63
64 return 0;
65 }
66
67 VIR_ONCE_GLOBAL_INIT(virNetServerService);
68
69
virNetServerServiceAccept(virNetSocket * sock,int events G_GNUC_UNUSED,void * opaque)70 static void virNetServerServiceAccept(virNetSocket *sock,
71 int events G_GNUC_UNUSED,
72 void *opaque)
73 {
74 virNetServerService *svc = opaque;
75 virNetSocket *clientsock = NULL;
76 int rc;
77
78 rc = virNetSocketAccept(sock, &clientsock);
79 if (rc < 0) {
80 if (rc == -2) {
81 /* Could not accept new client due to EMFILE. Suspend listening on
82 * the socket and set up a timer to enable it later. Hopefully,
83 * some FDs will be closed meanwhile. */
84 VIR_DEBUG("Temporarily suspending listening on svc=%p because accept() on sock=%p failed (errno=%d)",
85 svc, sock, errno);
86
87 virNetServerServiceToggle(svc, false);
88
89 svc->timerActive = true;
90 /* Retry in 5 seconds. */
91 virEventUpdateTimeout(svc->timer, 5 * 1000);
92 }
93 goto cleanup;
94 }
95
96 if (!clientsock) /* Connection already went away */
97 goto cleanup;
98
99 if (!svc->dispatchFunc)
100 goto cleanup;
101
102 svc->dispatchFunc(svc, clientsock, svc->dispatchOpaque);
103
104 cleanup:
105 virObjectUnref(clientsock);
106 }
107
108
109 static void
virNetServerServiceTimerFunc(int timer,void * opaque)110 virNetServerServiceTimerFunc(int timer,
111 void *opaque)
112 {
113 virNetServerService *svc = opaque;
114
115 VIR_DEBUG("Resuming listening on service svc=%p after previous suspend", svc);
116
117 virNetServerServiceToggle(svc, true);
118
119 virEventUpdateTimeout(timer, -1);
120 svc->timerActive = false;
121 }
122
123
124 static virNetServerService *
virNetServerServiceNewSocket(virNetSocket ** socks,size_t nsocks,int auth,virNetTLSContext * tls,bool readonly,size_t max_queued_clients,size_t nrequests_client_max)125 virNetServerServiceNewSocket(virNetSocket **socks,
126 size_t nsocks,
127 int auth,
128 virNetTLSContext *tls,
129 bool readonly,
130 size_t max_queued_clients,
131 size_t nrequests_client_max)
132 {
133 virNetServerService *svc;
134 size_t i;
135
136 if (virNetServerServiceInitialize() < 0)
137 return NULL;
138
139 if (!(svc = virObjectNew(virNetServerServiceClass)))
140 return NULL;
141
142 svc->socks = g_new0(virNetSocket *, nsocks);
143 svc->nsocks = nsocks;
144 for (i = 0; i < svc->nsocks; i++) {
145 svc->socks[i] = socks[i];
146 virObjectRef(svc->socks[i]);
147 }
148 svc->auth = auth;
149 svc->readonly = readonly;
150 svc->nrequests_client_max = nrequests_client_max;
151 svc->tls = virObjectRef(tls);
152
153 virObjectRef(svc);
154 svc->timer = virEventAddTimeout(-1, virNetServerServiceTimerFunc,
155 svc, virObjectFreeCallback);
156 if (svc->timer < 0) {
157 virObjectUnref(svc);
158 goto error;
159 }
160
161 for (i = 0; i < svc->nsocks; i++) {
162 if (virNetSocketListen(svc->socks[i], max_queued_clients) < 0)
163 goto error;
164
165 /* IO callback is initially disabled, until we're ready
166 * to deal with incoming clients */
167 virObjectRef(svc);
168 if (virNetSocketAddIOCallback(svc->socks[i],
169 0,
170 virNetServerServiceAccept,
171 svc,
172 virObjectFreeCallback) < 0) {
173 virObjectUnref(svc);
174 goto error;
175 }
176 }
177
178
179 return svc;
180
181 error:
182 virObjectUnref(svc);
183 return NULL;
184 }
185
186
virNetServerServiceNewTCP(const char * nodename,const char * service,int family,int auth,virNetTLSContext * tls,bool readonly,size_t max_queued_clients,size_t nrequests_client_max)187 virNetServerService *virNetServerServiceNewTCP(const char *nodename,
188 const char *service,
189 int family,
190 int auth,
191 virNetTLSContext *tls,
192 bool readonly,
193 size_t max_queued_clients,
194 size_t nrequests_client_max)
195 {
196 virNetServerService *svc;
197 size_t i;
198 virNetSocket **socks;
199 size_t nsocks;
200
201 VIR_DEBUG("Creating new TCP server nodename='%s' service='%s'",
202 NULLSTR(nodename), NULLSTR(service));
203 if (virNetSocketNewListenTCP(nodename,
204 service,
205 family,
206 &socks,
207 &nsocks) < 0)
208 return NULL;
209
210 svc = virNetServerServiceNewSocket(socks,
211 nsocks,
212 auth,
213 tls,
214 readonly,
215 max_queued_clients,
216 nrequests_client_max);
217
218 for (i = 0; i < nsocks; i++)
219 virObjectUnref(socks[i]);
220 VIR_FREE(socks);
221
222 return svc;
223 }
224
225
virNetServerServiceNewUNIX(const char * path,mode_t mask,gid_t grp,int auth,virNetTLSContext * tls,bool readonly,size_t max_queued_clients,size_t nrequests_client_max)226 virNetServerService *virNetServerServiceNewUNIX(const char *path,
227 mode_t mask,
228 gid_t grp,
229 int auth,
230 virNetTLSContext *tls,
231 bool readonly,
232 size_t max_queued_clients,
233 size_t nrequests_client_max)
234 {
235 virNetServerService *svc;
236 virNetSocket *sock;
237
238 VIR_DEBUG("Creating new UNIX server path='%s' mask=%o gid=%u",
239 path, mask, grp);
240 if (virNetSocketNewListenUNIX(path,
241 mask,
242 -1,
243 grp,
244 &sock) < 0)
245 return NULL;
246
247 svc = virNetServerServiceNewSocket(&sock,
248 1,
249 auth,
250 tls,
251 readonly,
252 max_queued_clients,
253 nrequests_client_max);
254
255 virObjectUnref(sock);
256
257 return svc;
258 }
259
virNetServerServiceNewFDs(int * fds,size_t nfds,bool unlinkUNIX,int auth,virNetTLSContext * tls,bool readonly,size_t max_queued_clients,size_t nrequests_client_max)260 virNetServerService *virNetServerServiceNewFDs(int *fds,
261 size_t nfds,
262 bool unlinkUNIX,
263 int auth,
264 virNetTLSContext *tls,
265 bool readonly,
266 size_t max_queued_clients,
267 size_t nrequests_client_max)
268 {
269 virNetServerService *svc = NULL;
270 virNetSocket **socks;
271 size_t i;
272
273 socks = g_new0(virNetSocket *, nfds);
274
275 for (i = 0; i < nfds; i++) {
276 if (virNetSocketNewListenFD(fds[i],
277 unlinkUNIX,
278 &socks[i]) < 0)
279 goto cleanup;
280 }
281
282 svc = virNetServerServiceNewSocket(socks,
283 nfds,
284 auth,
285 tls,
286 readonly,
287 max_queued_clients,
288 nrequests_client_max);
289
290 cleanup:
291 for (i = 0; i < nfds && socks; i++)
292 virObjectUnref(socks[i]);
293 VIR_FREE(socks);
294 return svc;
295 }
296
297
virNetServerServiceNewPostExecRestart(virJSONValue * object)298 virNetServerService *virNetServerServiceNewPostExecRestart(virJSONValue *object)
299 {
300 virNetServerService *svc;
301 virJSONValue *socks;
302 size_t i;
303 size_t n;
304 unsigned int max;
305
306 if (virNetServerServiceInitialize() < 0)
307 return NULL;
308
309 if (!(svc = virObjectNew(virNetServerServiceClass)))
310 return NULL;
311
312 if (virJSONValueObjectGetNumberInt(object, "auth", &svc->auth) < 0) {
313 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
314 _("Missing auth field in JSON state document"));
315 goto error;
316 }
317 if (virJSONValueObjectGetBoolean(object, "readonly", &svc->readonly) < 0) {
318 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
319 _("Missing readonly field in JSON state document"));
320 goto error;
321 }
322 if (virJSONValueObjectGetNumberUint(object, "nrequests_client_max",
323 &max) < 0) {
324 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
325 _("Missing nrequests_client_max field in JSON state document"));
326 goto error;
327 }
328 svc->nrequests_client_max = max;
329
330 if (!(socks = virJSONValueObjectGet(object, "socks"))) {
331 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
332 _("Missing socks field in JSON state document"));
333 goto error;
334 }
335
336 if (!virJSONValueIsArray(socks)) {
337 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
338 _("Malformed socks array"));
339 goto error;
340 }
341
342 n = virJSONValueArraySize(socks);
343 svc->socks = g_new0(virNetSocket *, n);
344 svc->nsocks = n;
345
346 for (i = 0; i < svc->nsocks; i++) {
347 virJSONValue *child = virJSONValueArrayGet(socks, i);
348 virNetSocket *sock;
349
350 if (!(sock = virNetSocketNewPostExecRestart(child))) {
351 virObjectUnref(sock);
352 goto error;
353 }
354
355 svc->socks[i] = sock;
356
357 /* IO callback is initially disabled, until we're ready
358 * to deal with incoming clients */
359 virObjectRef(svc);
360 if (virNetSocketAddIOCallback(sock,
361 0,
362 virNetServerServiceAccept,
363 svc,
364 virObjectFreeCallback) < 0) {
365 virObjectUnref(svc);
366 goto error;
367 }
368 }
369
370 return svc;
371
372 error:
373 virObjectUnref(svc);
374 return NULL;
375 }
376
377
virNetServerServicePreExecRestart(virNetServerService * svc)378 virJSONValue *virNetServerServicePreExecRestart(virNetServerService *svc)
379 {
380 g_autoptr(virJSONValue) object = virJSONValueNewObject();
381 g_autoptr(virJSONValue) socks = virJSONValueNewArray();
382 size_t i;
383
384 if (virJSONValueObjectAppendNumberInt(object, "auth", svc->auth) < 0)
385 return NULL;
386 if (virJSONValueObjectAppendBoolean(object, "readonly", svc->readonly) < 0)
387 return NULL;
388 if (virJSONValueObjectAppendNumberUint(object, "nrequests_client_max", svc->nrequests_client_max) < 0)
389 return NULL;
390
391 for (i = 0; i < svc->nsocks; i++) {
392 g_autoptr(virJSONValue) child = NULL;
393 if (!(child = virNetSocketPreExecRestart(svc->socks[i])))
394 return NULL;
395
396 if (virJSONValueArrayAppend(socks, &child) < 0)
397 return NULL;
398 }
399
400 if (virJSONValueObjectAppend(object, "socks", &socks) < 0)
401 return NULL;
402
403 return g_steal_pointer(&object);
404 }
405
406
virNetServerServiceGetPort(virNetServerService * svc)407 int virNetServerServiceGetPort(virNetServerService *svc)
408 {
409 /* We're assuming if there are multiple sockets
410 * for IPv4 & 6, then they are all on same port */
411 return virNetSocketGetPort(svc->socks[0]);
412 }
413
414
virNetServerServiceGetAuth(virNetServerService * svc)415 int virNetServerServiceGetAuth(virNetServerService *svc)
416 {
417 return svc->auth;
418 }
419
420
virNetServerServiceIsReadonly(virNetServerService * svc)421 bool virNetServerServiceIsReadonly(virNetServerService *svc)
422 {
423 return svc->readonly;
424 }
425
426
virNetServerServiceGetMaxRequests(virNetServerService * svc)427 size_t virNetServerServiceGetMaxRequests(virNetServerService *svc)
428 {
429 return svc->nrequests_client_max;
430 }
431
virNetServerServiceGetTLSContext(virNetServerService * svc)432 virNetTLSContext *virNetServerServiceGetTLSContext(virNetServerService *svc)
433 {
434 return svc->tls;
435 }
436
virNetServerServiceSetDispatcher(virNetServerService * svc,virNetServerServiceDispatchFunc func,void * opaque)437 void virNetServerServiceSetDispatcher(virNetServerService *svc,
438 virNetServerServiceDispatchFunc func,
439 void *opaque)
440 {
441 svc->dispatchFunc = func;
442 svc->dispatchOpaque = opaque;
443 }
444
445
virNetServerServiceDispose(void * obj)446 void virNetServerServiceDispose(void *obj)
447 {
448 virNetServerService *svc = obj;
449 size_t i;
450
451 if (svc->timer >= 0)
452 virEventRemoveTimeout(svc->timer);
453
454 for (i = 0; i < svc->nsocks; i++)
455 virObjectUnref(svc->socks[i]);
456 g_free(svc->socks);
457
458 virObjectUnref(svc->tls);
459 }
460
virNetServerServiceToggle(virNetServerService * svc,bool enabled)461 void virNetServerServiceToggle(virNetServerService *svc,
462 bool enabled)
463 {
464 size_t i;
465
466 for (i = 0; i < svc->nsocks; i++)
467 virNetSocketUpdateIOCallback(svc->socks[i],
468 enabled ?
469 VIR_EVENT_HANDLE_READABLE :
470 0);
471 }
472
virNetServerServiceClose(virNetServerService * svc)473 void virNetServerServiceClose(virNetServerService *svc)
474 {
475 size_t i;
476
477 if (!svc)
478 return;
479
480 for (i = 0; i < svc->nsocks; i++) {
481 virNetSocketRemoveIOCallback(svc->socks[i]);
482 virNetSocketClose(svc->socks[i]);
483 }
484 }
485
486
487 bool
virNetServerServiceTimerActive(virNetServerService * svc)488 virNetServerServiceTimerActive(virNetServerService *svc)
489 {
490 return svc->timerActive;
491 }
492