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