1*8bae5d40Schristos /* $NetBSD: nfs_start.c,v 1.1.1.3 2015/01/17 16:34:15 christos Exp $ */
2a53f50b9Schristos
3a53f50b9Schristos /*
4*8bae5d40Schristos * Copyright (c) 1997-2014 Erez Zadok
5a53f50b9Schristos * Copyright (c) 1990 Jan-Simon Pendry
6a53f50b9Schristos * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
7a53f50b9Schristos * Copyright (c) 1990 The Regents of the University of California.
8a53f50b9Schristos * All rights reserved.
9a53f50b9Schristos *
10a53f50b9Schristos * This code is derived from software contributed to Berkeley by
11a53f50b9Schristos * Jan-Simon Pendry at Imperial College, London.
12a53f50b9Schristos *
13a53f50b9Schristos * Redistribution and use in source and binary forms, with or without
14a53f50b9Schristos * modification, are permitted provided that the following conditions
15a53f50b9Schristos * are met:
16a53f50b9Schristos * 1. Redistributions of source code must retain the above copyright
17a53f50b9Schristos * notice, this list of conditions and the following disclaimer.
18a53f50b9Schristos * 2. Redistributions in binary form must reproduce the above copyright
19a53f50b9Schristos * notice, this list of conditions and the following disclaimer in the
20a53f50b9Schristos * documentation and/or other materials provided with the distribution.
21*8bae5d40Schristos * 3. Neither the name of the University nor the names of its contributors
22a53f50b9Schristos * may be used to endorse or promote products derived from this software
23a53f50b9Schristos * without specific prior written permission.
24a53f50b9Schristos *
25a53f50b9Schristos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26a53f50b9Schristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27a53f50b9Schristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28a53f50b9Schristos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29a53f50b9Schristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30a53f50b9Schristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31a53f50b9Schristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32a53f50b9Schristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33a53f50b9Schristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34a53f50b9Schristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35a53f50b9Schristos * SUCH DAMAGE.
36a53f50b9Schristos *
37a53f50b9Schristos *
38a53f50b9Schristos * File: am-utils/amd/nfs_start.c
39a53f50b9Schristos *
40a53f50b9Schristos */
41a53f50b9Schristos
42a53f50b9Schristos #ifdef HAVE_CONFIG_H
43a53f50b9Schristos # include <config.h>
44a53f50b9Schristos #endif /* HAVE_CONFIG_H */
45a53f50b9Schristos #include <am_defs.h>
46a53f50b9Schristos #include <amd.h>
47a53f50b9Schristos
48a53f50b9Schristos #ifndef SELECT_MAXWAIT
49a53f50b9Schristos # define SELECT_MAXWAIT 16
50a53f50b9Schristos #endif /* not SELECT_MAXWAIT */
51a53f50b9Schristos
52a53f50b9Schristos SVCXPRT *nfsxprt = NULL;
53a53f50b9Schristos u_short nfs_port = 0;
54a53f50b9Schristos
55a53f50b9Schristos #ifndef HAVE_SIGACTION
56a53f50b9Schristos # define MASKED_SIGS (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGCHLD)|sigmask(SIGHUP))
57a53f50b9Schristos #endif /* not HAVE_SIGACTION */
58a53f50b9Schristos
59a53f50b9Schristos #ifdef DEBUG
60a53f50b9Schristos /*
61a53f50b9Schristos * Check that we are not burning resources
62a53f50b9Schristos */
63a53f50b9Schristos static void
checkup(void)64a53f50b9Schristos checkup(void)
65a53f50b9Schristos {
66a53f50b9Schristos static int max_fd = 0;
67a53f50b9Schristos static char *max_mem = NULL;
68a53f50b9Schristos int next_fd = dup(0);
69a53f50b9Schristos caddr_t next_mem = sbrk(0);
70a53f50b9Schristos
71a53f50b9Schristos close(next_fd);
72a53f50b9Schristos
73a53f50b9Schristos if (max_fd < next_fd) {
74a53f50b9Schristos dlog("%d new fds allocated; total is %d",
75a53f50b9Schristos next_fd - max_fd, next_fd);
76a53f50b9Schristos max_fd = next_fd;
77a53f50b9Schristos }
78a53f50b9Schristos if (max_mem < next_mem) {
79a53f50b9Schristos #ifdef HAVE_GETPAGESIZE
80a53f50b9Schristos dlog("%#lx bytes of memory allocated; total is %#lx (%ld pages)",
81a53f50b9Schristos (long) (next_mem - max_mem), (unsigned long) next_mem,
82a53f50b9Schristos ((long) next_mem + getpagesize() - 1) / (long) getpagesize());
83a53f50b9Schristos #else /* not HAVE_GETPAGESIZE */
84a53f50b9Schristos dlog("%#lx bytes of memory allocated; total is %#lx",
85a53f50b9Schristos (long) (next_mem - max_mem), (unsigned long) next_mem);
86a53f50b9Schristos #endif /* not HAVE_GETPAGESIZE */
87a53f50b9Schristos max_mem = next_mem;
88a53f50b9Schristos
89a53f50b9Schristos }
90a53f50b9Schristos }
91a53f50b9Schristos #else /* not DEBUG */
92a53f50b9Schristos #define checkup()
93a53f50b9Schristos #endif /* not DEBUG */
94a53f50b9Schristos
95a53f50b9Schristos
96a53f50b9Schristos static int
97a53f50b9Schristos #ifdef HAVE_SIGACTION
do_select(sigset_t smask,int fds,fd_set * fdp,struct timeval * tvp)98a53f50b9Schristos do_select(sigset_t smask, int fds, fd_set *fdp, struct timeval *tvp)
99a53f50b9Schristos #else /* not HAVE_SIGACTION */
100a53f50b9Schristos do_select(int smask, int fds, fd_set *fdp, struct timeval *tvp)
101a53f50b9Schristos #endif /* not HAVE_SIGACTION */
102a53f50b9Schristos {
103a53f50b9Schristos
104a53f50b9Schristos int sig;
105a53f50b9Schristos int nsel;
106a53f50b9Schristos
107a53f50b9Schristos if ((sig = setjmp(select_intr))) {
108a53f50b9Schristos select_intr_valid = 0;
109a53f50b9Schristos /* Got a signal */
110a53f50b9Schristos switch (sig) {
111a53f50b9Schristos case SIGINT:
112a53f50b9Schristos case SIGTERM:
113a53f50b9Schristos amd_state = Finishing;
114a53f50b9Schristos reschedule_timeout_mp();
115a53f50b9Schristos break;
116a53f50b9Schristos }
117a53f50b9Schristos nsel = -1;
118a53f50b9Schristos errno = EINTR;
119a53f50b9Schristos } else {
120a53f50b9Schristos select_intr_valid = 1;
121a53f50b9Schristos /*
122a53f50b9Schristos * Allow interrupts. If a signal
123a53f50b9Schristos * occurs, then it will cause a longjmp
124a53f50b9Schristos * up above.
125a53f50b9Schristos */
126a53f50b9Schristos #ifdef HAVE_SIGACTION
127a53f50b9Schristos sigprocmask(SIG_SETMASK, &smask, NULL);
128a53f50b9Schristos #else /* not HAVE_SIGACTION */
129a53f50b9Schristos (void) sigsetmask(smask);
130a53f50b9Schristos #endif /* not HAVE_SIGACTION */
131a53f50b9Schristos
132a53f50b9Schristos /*
133a53f50b9Schristos * Wait for input
134a53f50b9Schristos */
135a53f50b9Schristos nsel = select(fds, fdp, (fd_set *) NULL, (fd_set *) NULL,
136a53f50b9Schristos tvp->tv_sec ? tvp : (struct timeval *) NULL);
137a53f50b9Schristos }
138a53f50b9Schristos
139a53f50b9Schristos #ifdef HAVE_SIGACTION
140a53f50b9Schristos sigprocmask(SIG_BLOCK, &masked_sigs, NULL);
141a53f50b9Schristos #else /* not HAVE_SIGACTION */
142a53f50b9Schristos (void) sigblock(MASKED_SIGS);
143a53f50b9Schristos #endif /* not HAVE_SIGACTION */
144a53f50b9Schristos
145a53f50b9Schristos /*
146a53f50b9Schristos * Perhaps reload the cache?
147a53f50b9Schristos */
148a53f50b9Schristos if (do_mapc_reload < clocktime(NULL)) {
149a53f50b9Schristos mapc_reload();
150a53f50b9Schristos do_mapc_reload = clocktime(NULL) + gopt.map_reload_interval;
151a53f50b9Schristos }
152a53f50b9Schristos return nsel;
153a53f50b9Schristos }
154a53f50b9Schristos
155a53f50b9Schristos
156a53f50b9Schristos /*
157a53f50b9Schristos * Determine whether anything is left in
158a53f50b9Schristos * the RPC input queue.
159a53f50b9Schristos */
160a53f50b9Schristos static int
rpc_pending_now(void)161a53f50b9Schristos rpc_pending_now(void)
162a53f50b9Schristos {
163a53f50b9Schristos struct timeval tvv;
164a53f50b9Schristos int nsel;
165a53f50b9Schristos fd_set readfds;
166a53f50b9Schristos
167a53f50b9Schristos FD_ZERO(&readfds);
168a53f50b9Schristos FD_SET(fwd_sock, &readfds);
169a53f50b9Schristos
170a53f50b9Schristos tvv.tv_sec = tvv.tv_usec = 0;
171a53f50b9Schristos nsel = select(FD_SETSIZE, &readfds, (fd_set *) NULL, (fd_set *) NULL, &tvv);
172a53f50b9Schristos if (nsel < 1)
173a53f50b9Schristos return (0);
174a53f50b9Schristos if (FD_ISSET(fwd_sock, &readfds))
175a53f50b9Schristos return (1);
176a53f50b9Schristos
177a53f50b9Schristos return (0);
178a53f50b9Schristos }
179a53f50b9Schristos
180a53f50b9Schristos
181a53f50b9Schristos static serv_state
run_rpc(void)182a53f50b9Schristos run_rpc(void)
183a53f50b9Schristos {
184a53f50b9Schristos #ifdef HAVE_SIGACTION
185a53f50b9Schristos sigset_t smask;
186a53f50b9Schristos sigprocmask(SIG_BLOCK, &masked_sigs, &smask);
187a53f50b9Schristos #else /* not HAVE_SIGACTION */
188a53f50b9Schristos int smask = sigblock(MASKED_SIGS);
189a53f50b9Schristos #endif /* not HAVE_SIGACTION */
190a53f50b9Schristos
191a53f50b9Schristos next_softclock = clocktime(NULL);
192a53f50b9Schristos
193a53f50b9Schristos amd_state = Run;
194a53f50b9Schristos
195a53f50b9Schristos /*
196a53f50b9Schristos * Keep on trucking while we are in Run mode. This state
197a53f50b9Schristos * is switched to Quit after all the file systems have
198a53f50b9Schristos * been unmounted.
199a53f50b9Schristos */
200a53f50b9Schristos while ((int) amd_state <= (int) Finishing) {
201a53f50b9Schristos struct timeval tvv;
202a53f50b9Schristos int nsel;
203a53f50b9Schristos time_t now;
204a53f50b9Schristos fd_set readfds;
205a53f50b9Schristos
206a53f50b9Schristos #ifdef HAVE_SVC_GETREQSET
207a53f50b9Schristos memmove(&readfds, &svc_fdset, sizeof(svc_fdset));
208a53f50b9Schristos #else /* not HAVE_SVC_GETREQSET */
209a53f50b9Schristos FD_ZERO(&readfds);
210a53f50b9Schristos # ifdef HAVE_FD_SET_FDS_BITS
211a53f50b9Schristos readfds.fds_bits[0] = svc_fds;
212a53f50b9Schristos # else /* not HAVE_FD_SET_FDS_BITS */
213a53f50b9Schristos readfds = svc_fds;
214a53f50b9Schristos # endif /* not HAVE_FD_SET_FDS_BITS */
215a53f50b9Schristos #endif /* not HAVE_SVC_GETREQSET */
216a53f50b9Schristos FD_SET(fwd_sock, &readfds);
217a53f50b9Schristos
218a53f50b9Schristos checkup();
219a53f50b9Schristos
220a53f50b9Schristos /*
221a53f50b9Schristos * If the full timeout code is not called,
222a53f50b9Schristos * then recompute the time delta manually.
223a53f50b9Schristos */
224a53f50b9Schristos now = clocktime(NULL);
225a53f50b9Schristos
226a53f50b9Schristos if (next_softclock <= now) {
227a53f50b9Schristos if (amd_state == Finishing)
228a53f50b9Schristos umount_exported();
229a53f50b9Schristos tvv.tv_sec = softclock();
230a53f50b9Schristos } else {
231a53f50b9Schristos tvv.tv_sec = next_softclock - now;
232a53f50b9Schristos }
233a53f50b9Schristos tvv.tv_usec = 0;
234a53f50b9Schristos
235a53f50b9Schristos if (amd_state == Finishing && get_exported_ap(0) == NULL) {
236a53f50b9Schristos flush_mntfs();
237a53f50b9Schristos amd_state = Quit;
238a53f50b9Schristos break;
239a53f50b9Schristos }
240a53f50b9Schristos
241a53f50b9Schristos #ifdef HAVE_FS_AUTOFS
242a53f50b9Schristos autofs_add_fdset(&readfds);
243a53f50b9Schristos #endif /* HAVE_FS_AUTOFS */
244a53f50b9Schristos
245a53f50b9Schristos if (tvv.tv_sec <= 0)
246a53f50b9Schristos tvv.tv_sec = SELECT_MAXWAIT;
247a53f50b9Schristos if (tvv.tv_sec) {
248a53f50b9Schristos dlog("Select waits for %ds", (int) tvv.tv_sec);
249a53f50b9Schristos } else {
250a53f50b9Schristos dlog("Select waits for Godot");
251a53f50b9Schristos }
252a53f50b9Schristos
253a53f50b9Schristos nsel = do_select(smask, FD_SETSIZE, &readfds, &tvv);
254a53f50b9Schristos
255a53f50b9Schristos switch (nsel) {
256a53f50b9Schristos case -1:
257a53f50b9Schristos if (errno == EINTR) {
258a53f50b9Schristos dlog("select interrupted");
259a53f50b9Schristos continue;
260a53f50b9Schristos }
261a53f50b9Schristos plog(XLOG_ERROR, "select: %m");
262a53f50b9Schristos break;
263a53f50b9Schristos
264a53f50b9Schristos case 0:
265a53f50b9Schristos break;
266a53f50b9Schristos
267a53f50b9Schristos default:
268a53f50b9Schristos /*
269a53f50b9Schristos * Read all pending NFS responses at once to avoid having responses
270a53f50b9Schristos * queue up as a consequence of retransmissions.
271a53f50b9Schristos */
272a53f50b9Schristos if (FD_ISSET(fwd_sock, &readfds)) {
273a53f50b9Schristos FD_CLR(fwd_sock, &readfds);
274a53f50b9Schristos --nsel;
275a53f50b9Schristos do {
276a53f50b9Schristos fwd_reply();
277a53f50b9Schristos } while (rpc_pending_now() > 0);
278a53f50b9Schristos }
279a53f50b9Schristos
280a53f50b9Schristos #ifdef HAVE_FS_AUTOFS
281a53f50b9Schristos if (nsel)
282a53f50b9Schristos nsel = autofs_handle_fdset(&readfds, nsel);
283a53f50b9Schristos #endif /* HAVE_FS_AUTOFS */
284a53f50b9Schristos
285a53f50b9Schristos if (nsel) {
286a53f50b9Schristos /*
287a53f50b9Schristos * Anything left must be a normal
288a53f50b9Schristos * RPC request.
289a53f50b9Schristos */
290a53f50b9Schristos #ifdef HAVE_SVC_GETREQSET
291a53f50b9Schristos svc_getreqset(&readfds);
292a53f50b9Schristos #else /* not HAVE_SVC_GETREQSET */
293a53f50b9Schristos # ifdef HAVE_FD_SET_FDS_BITS
294a53f50b9Schristos svc_getreq(readfds.fds_bits[0]);
295a53f50b9Schristos # else /* not HAVE_FD_SET_FDS_BITS */
296a53f50b9Schristos svc_getreq(readfds);
297a53f50b9Schristos # endif /* not HAVE_FD_SET_FDS_BITS */
298a53f50b9Schristos #endif /* not HAVE_SVC_GETREQSET */
299a53f50b9Schristos }
300a53f50b9Schristos break;
301a53f50b9Schristos }
302a53f50b9Schristos }
303a53f50b9Schristos
304a53f50b9Schristos #ifdef HAVE_SIGACTION
305a53f50b9Schristos sigprocmask(SIG_SETMASK, &smask, NULL);
306a53f50b9Schristos #else /* not HAVE_SIGACTION */
307a53f50b9Schristos (void) sigsetmask(smask);
308a53f50b9Schristos #endif /* not HAVE_SIGACTION */
309a53f50b9Schristos
310a53f50b9Schristos if (amd_state == Quit)
311a53f50b9Schristos amd_state = Done;
312a53f50b9Schristos
313a53f50b9Schristos return amd_state;
314a53f50b9Schristos }
315a53f50b9Schristos
316a53f50b9Schristos
317a53f50b9Schristos int
mount_automounter(int ppid)318a53f50b9Schristos mount_automounter(int ppid)
319a53f50b9Schristos {
320a53f50b9Schristos /*
321a53f50b9Schristos * Old code replaced by rpc-trash patch.
322a53f50b9Schristos * Erez Zadok <ezk@cs.columbia.edu>
323a53f50b9Schristos int so = socket(AF_INET, SOCK_DGRAM, 0);
324a53f50b9Schristos */
325a53f50b9Schristos SVCXPRT *udp_amqp = NULL, *tcp_amqp = NULL;
326a53f50b9Schristos int nmount, ret;
327a53f50b9Schristos int soNFS;
328a53f50b9Schristos int udp_soAMQ, tcp_soAMQ;
329a53f50b9Schristos struct netconfig *udp_amqncp, *tcp_amqncp;
330a53f50b9Schristos
331a53f50b9Schristos /*
332a53f50b9Schristos * This must be done first, because it attempts to bind
333a53f50b9Schristos * to various UDP ports and we don't want anything else
334a53f50b9Schristos * potentially taking over those ports before we get a chance
335a53f50b9Schristos * to reserve them.
336a53f50b9Schristos */
337a53f50b9Schristos if (gopt.flags & CFM_RESTART_EXISTING_MOUNTS)
338a53f50b9Schristos restart_automounter_nodes();
339a53f50b9Schristos
340a53f50b9Schristos /*
341a53f50b9Schristos * Start RPC forwarding
342a53f50b9Schristos */
343a53f50b9Schristos if (fwd_init() != 0)
344a53f50b9Schristos return 3;
345a53f50b9Schristos
346a53f50b9Schristos /*
347a53f50b9Schristos * Construct the root automount node
348a53f50b9Schristos */
349a53f50b9Schristos make_root_node();
350a53f50b9Schristos
351a53f50b9Schristos /*
352a53f50b9Schristos * Pick up the pieces from a previous run
353a53f50b9Schristos * This is likely to (indirectly) need the rpc_fwd package
354a53f50b9Schristos * so it *must* come after the call to fwd_init().
355a53f50b9Schristos */
356a53f50b9Schristos if (gopt.flags & CFM_RESTART_EXISTING_MOUNTS)
357a53f50b9Schristos restart();
358a53f50b9Schristos
359a53f50b9Schristos /*
360a53f50b9Schristos * Create the nfs service for amd
361a53f50b9Schristos * If nfs_port is already initialized, it means we
362a53f50b9Schristos * already created the service during restart_automounter_nodes().
363a53f50b9Schristos */
364a53f50b9Schristos if (nfs_port == 0) {
365*8bae5d40Schristos ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_dispatcher,
366*8bae5d40Schristos get_nfs_dispatcher_version(nfs_dispatcher));
367a53f50b9Schristos if (ret != 0)
368a53f50b9Schristos return ret;
369a53f50b9Schristos }
370a53f50b9Schristos xsnprintf(pid_fsname, sizeof(pid_fsname), "%s:(pid%ld,port%u)",
371a53f50b9Schristos am_get_hostname(), (long) am_mypid, nfs_port);
372a53f50b9Schristos
373a53f50b9Schristos /* security: if user sets -D noamq, don't even create listening socket */
374a53f50b9Schristos if (amuDebug(D_AMQ)) {
375a53f50b9Schristos ret = create_amq_service(&udp_soAMQ,
376a53f50b9Schristos &udp_amqp,
377a53f50b9Schristos &udp_amqncp,
378a53f50b9Schristos &tcp_soAMQ,
379a53f50b9Schristos &tcp_amqp,
380a53f50b9Schristos &tcp_amqncp,
381a53f50b9Schristos gopt.preferred_amq_port);
382a53f50b9Schristos if (ret != 0)
383a53f50b9Schristos return ret;
384a53f50b9Schristos }
385a53f50b9Schristos
386a53f50b9Schristos #ifdef HAVE_FS_AUTOFS
387a53f50b9Schristos if (amd_use_autofs) {
388a53f50b9Schristos /*
389a53f50b9Schristos * Create the autofs service for amd.
390a53f50b9Schristos */
391a53f50b9Schristos ret = create_autofs_service();
392a53f50b9Schristos /* if autofs service fails it is OK if using a test amd */
393a53f50b9Schristos if (ret != 0) {
394a53f50b9Schristos plog(XLOG_WARNING, "autofs service registration failed, turning off autofs support");
395a53f50b9Schristos amd_use_autofs = 0;
396a53f50b9Schristos }
397a53f50b9Schristos }
398a53f50b9Schristos #endif /* HAVE_FS_AUTOFS */
399a53f50b9Schristos
400a53f50b9Schristos /*
401a53f50b9Schristos * Mount the top-level auto-mountpoints
402a53f50b9Schristos */
403a53f50b9Schristos nmount = mount_exported();
404a53f50b9Schristos
405a53f50b9Schristos /*
406a53f50b9Schristos * Now safe to tell parent that we are up and running
407a53f50b9Schristos */
408a53f50b9Schristos if (ppid)
409a53f50b9Schristos kill(ppid, SIGQUIT);
410a53f50b9Schristos
411a53f50b9Schristos if (nmount == 0) {
412a53f50b9Schristos plog(XLOG_FATAL, "No work to do - quitting");
413a53f50b9Schristos amd_state = Done;
414a53f50b9Schristos return 0;
415a53f50b9Schristos }
416a53f50b9Schristos
417a53f50b9Schristos if (amuDebug(D_AMQ)) {
418a53f50b9Schristos /*
419a53f50b9Schristos * Complete registration of amq (first TCP service then UDP)
420a53f50b9Schristos */
421a53f50b9Schristos int tcp_ok = 0, udp_ok = 0;
422a53f50b9Schristos
423a53f50b9Schristos unregister_amq(); /* unregister leftover Amd, if any, just in case */
424a53f50b9Schristos
425a53f50b9Schristos tcp_ok = amu_svc_register(tcp_amqp, get_amd_program_number(), AMQ_VERSION,
426a53f50b9Schristos amq_program_1, IPPROTO_TCP, tcp_amqncp);
427a53f50b9Schristos if (!tcp_ok)
428a53f50b9Schristos plog(XLOG_FATAL,
429a53f50b9Schristos "unable to register (AMQ_PROGRAM=%lu, AMQ_VERSION, tcp)",
430a53f50b9Schristos get_amd_program_number());
431a53f50b9Schristos
432a53f50b9Schristos udp_ok = amu_svc_register(udp_amqp, get_amd_program_number(), AMQ_VERSION,
433a53f50b9Schristos amq_program_1, IPPROTO_UDP, udp_amqncp);
434a53f50b9Schristos if (!udp_ok)
435a53f50b9Schristos plog(XLOG_FATAL,
436a53f50b9Schristos "unable to register (AMQ_PROGRAM=%lu, AMQ_VERSION, udp)",
437a53f50b9Schristos get_amd_program_number());
438a53f50b9Schristos
439a53f50b9Schristos /* return error only if both failed */
440a53f50b9Schristos if (!tcp_ok && !udp_ok) {
441a53f50b9Schristos amd_state = Done;
442a53f50b9Schristos return 3;
443a53f50b9Schristos }
444a53f50b9Schristos }
445a53f50b9Schristos
446a53f50b9Schristos /*
447a53f50b9Schristos * Start timeout_mp rolling
448a53f50b9Schristos */
449a53f50b9Schristos reschedule_timeout_mp();
450a53f50b9Schristos
451a53f50b9Schristos /*
452a53f50b9Schristos * Start the server
453a53f50b9Schristos */
454a53f50b9Schristos if (run_rpc() != Done) {
455a53f50b9Schristos plog(XLOG_FATAL, "run_rpc failed");
456a53f50b9Schristos amd_state = Done;
457a53f50b9Schristos }
458a53f50b9Schristos return 0;
459a53f50b9Schristos }
460