1/*
2 * Copyright (c) 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1.  Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 * 2.  Redistributions in binary form must reproduce the above copyright
13 *     notice, this list of conditions and the following disclaimer in the
14 *     documentation and/or other materials provided with the distribution.
15 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
16 *     contributors may be used to endorse or promote products derived from
17 *     this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Portions of this software have been released under the following terms:
31 *
32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC.
33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY
34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION
35 *
36 * To anyone who acknowledges that this file is provided "AS IS"
37 * without any express or implied warranty:
38 * permission to use, copy, modify, and distribute this file for any
39 * purpose is hereby granted without fee, provided that the above
40 * copyright notices and this notice appears in all source code copies,
41 * and that none of the names of Open Software Foundation, Inc., Hewlett-
42 * Packard Company or Digital Equipment Corporation be used
43 * in advertising or publicity pertaining to distribution of the software
44 * without specific, written prior permission.  Neither Open Software
45 * Foundation, Inc., Hewlett-Packard Company nor Digital
46 * Equipment Corporation makes any representations about the suitability
47 * of this software for any purpose.
48 *
49 * Copyright (c) 2007, Novell, Inc. All rights reserved.
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 *
54 * 1.  Redistributions of source code must retain the above copyright
55 *     notice, this list of conditions and the following disclaimer.
56 * 2.  Redistributions in binary form must reproduce the above copyright
57 *     notice, this list of conditions and the following disclaimer in the
58 *     documentation and/or other materials provided with the distribution.
59 * 3.  Neither the name of Novell Inc. nor the names of its contributors
60 *     may be used to endorse or promote products derived from this
61 *     this software without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 *
74 * @APPLE_LICENSE_HEADER_END@
75 */
76
77/*
78**
79**  NAME
80**
81**      server.c
82**
83**  FACILITY:
84**
85**      Remote Procedure Call (RPC)
86**
87**  ABSTRACT:
88**
89**  Server main code for performance and system exerciser.
90**
91**
92*/
93
94#ifdef HAVE_CONFIG_H
95#include <config.h>
96#endif
97
98#include <string.h>
99#include <perf_c.h>
100#include <perf_p.h>
101#ifdef HAVE_GETOPT_H
102#include <getopt.h>
103#endif
104#include <stdlib.h>
105#include <unistd.h>
106
107#ifdef AUTH_KRB
108#include <dce/id_base.h>
109#endif /* AUTH_KRB */
110
111
112idl_boolean auth = false;       /* should we check authentication? */
113
114unsigned16 server_loops = 1;    /* # of times to loop on calls to rpc_server_listen */
115#define SERVER_LOOP_SLEEP_TIME 15   /* # of secs to sleep after return from " " " */
116
117idl_boolean use_reserved_threads = false;
118idl_boolean pool_active = false;
119static rpc_thread_pool_handle_t thread_poolh;
120static rpc_if_id_t perfg_if_id;
121static rpc_if_id_t perf_if_id;
122
123int verbose = 1;
124
125unsigned32 socket_buf_size = 0;  /* os default */
126
127rpc_binding_vector_p_t bv;
128
129static struct
130{
131    unsigned32      count;
132    uuid_p_t        uuid[2];
133} object_vec =
134{
135    2,
136    {
137        &NilObj,
138        &NilTypeObj,
139    }
140};
141
142
143/*
144 * M G M T _ A U T H _ F N
145 *
146 * Procedure called to determine whether server will be allowed to be shutdown
147 * remotely.
148 */
149
150idl_boolean shut_ok = true;
151
152static boolean32 mgmt_auth_fn (h, op, st)
153
154handle_t            h __attribute__(unused);
155unsigned32          op;
156unsigned32          *st;
157
158{
159    boolean32 b;
160
161    b = (op == rpc_c_mgmt_stop_server_listen) ? shut_ok : true;
162
163    VRprintf (1, ("+ In management authorization function: op=%lu, returning \"%s\"\n",
164                op, b ? "true" : "false"));
165
166    *st = b ? rpc_s_ok : rpc_s_mgmt_op_disallowed;
167
168    return (b);
169}
170
171/*
172 * I F _ I D _ I S _ E Q U A L
173 *
174 * return true iff the rpc_if_id_t's are identical.
175 */
176static idl_boolean if_id_is_equal(ifid1, ifid2)
177rpc_if_id_p_t ifid1, ifid2;
178{
179    unsigned32 st;
180
181    return (ifid1->vers_major == ifid2->vers_major
182        && ifid1->vers_minor == ifid2->vers_minor
183        && uuid_equal(&ifid1->uuid, &ifid2->uuid, &st));
184}
185
186/*
187 * T H R E A D _ P O O L _ F N
188 *
189 * Thread pool lookup function.  Manage the thread pool(s)
190 * based on a simple object uuid scheme:
191 *      for perfg.idl/perfg_op2 for non-nil object id use reserved pool threads
192 *      for perf.idl/perf_null_slow use reserved pool threads
193 *      otherwise use a default pool thread
194 */
195static void thread_pool_fn(obj_uuid, if_id, opnum, phandle, status)
196uuid_p_t                obj_uuid;
197rpc_if_id_p_t           if_id;
198unsigned32              opnum;
199rpc_thread_pool_handle_t *phandle;
200unsigned32              *status;
201{
202    unsigned32 st;
203    static int once = 1;
204
205    if (once == 1)
206    {
207        VRprintf (1, ("+ Thread pool selection function active\n"));
208        once = 0;
209    }
210
211    if (! use_reserved_threads)
212    {
213        fprintf(stderr, "Thread Pool FN called without being enabled\n");
214        fprintf(stderr, "Ignoring RPC\n");
215        *status = -1;
216    }
217
218    *phandle = NULL;
219    if ((opnum == 1 && if_id_is_equal(if_id, &perfg_if_id)
220            && obj_uuid != NULL && ! uuid_is_nil(obj_uuid, &st))
221      || (opnum == 15 && if_id_is_equal(if_id, &perf_if_id)))
222    {
223        *phandle = thread_poolh;
224    }
225    *status = 0;
226}
227
228/*
229 * S E T U P _ T H R E A D _ P O O L S
230 *
231 * Create a threads pool and register a pool lookup function.
232 * Create a thread pool for the specified interface.
233 * return 0 - ok
234 *       -1 - couldn't create pool
235 *        1 - couldn't set thread pool fn
236 */
237static int setup_thread_pools()
238{
239    unsigned32 st;
240
241    if (! use_reserved_threads)
242        return 0;
243
244    rpc_server_create_thread_pool(2, &thread_poolh, &st);
245    if (st != error_status_ok)
246    {
247        fprintf(stderr, "Cannot create thread pool - %s\n", error_text(st));
248        return -1;
249    }
250    pool_active = true;
251
252    rpc_server_set_thread_pool_fn(thread_pool_fn, &st);
253    if (st != error_status_ok)
254    {
255        fprintf(stderr, "Cannot set thread pool fn - %s\n", error_text(st));
256        return 1;
257    }
258
259    /*
260     * A little more setup for the thread_pool_fn().
261     */
262    rpc_if_inq_id(perfg_v1_0_s_ifspec, &perfg_if_id, &st);
263    rpc_if_inq_id(perf_v2_0_s_ifspec, &perf_if_id, &st);
264
265    return 0;
266}
267
268/*
269 * T E A R D O W N _ T H R E A D _ P O O L S
270 *
271 * Free our thread pools and unregister our lookup fn.
272 * return 0 - ok
273 *       -1 - couldn't free pool
274 *        1 - couldn't set thread pool fn NULL
275 */
276int teardown_thread_pools(wait_flg)
277idl_boolean wait_flg;
278{
279    unsigned32 st;
280
281    if (! use_reserved_threads)
282        return 0;
283
284    rpc_server_set_thread_pool_fn(NULL, &st);
285    if (st != error_status_ok)
286    {
287        fprintf(stderr, "Cannot thread pool fn NULL - %s\n", error_text(st));
288        return 1;
289    }
290
291    if (pool_active)
292    {
293        pool_active = false;
294        rpc_server_free_thread_pool(&thread_poolh, wait_flg, &st);
295        if (st != error_status_ok)
296        {
297            fprintf(stderr, "Cannot free thread pool - %s\n", error_text(st));
298            return -1;
299        }
300    }
301
302    return 0;
303}
304
305/*
306 * R E G I S T E R _ I F S
307 *
308 * Register the interfaces we export.
309 */
310
311static void register_ifs ()
312
313{
314    unsigned32          st;
315
316    rpc_server_register_if (perf_v2_0_s_ifspec, NULL,
317        (rpc_mgr_epv_t) &perf_epv, &st);
318
319    if (st != 0)
320    {
321        fprintf(stderr, "*** Can't register - %s\n", error_text(st));
322        exit(1);
323    }
324
325    rpc_server_register_if (perfg_v1_0_s_ifspec, (uuid_p_t) &FooType,
326        (rpc_mgr_epv_t) &foo_perfg_epv, &st);
327
328    if (st != 0)
329    {
330        fprintf(stderr, "*** Can't register Foo mgr - %s\n", error_text(st));
331        exit(1);
332    }
333
334    rpc_server_register_if (perfg_v1_0_s_ifspec, (uuid_p_t) &BarType,
335        (rpc_mgr_epv_t) &bar_perfg_epv, &st);
336
337    if (st != 0)
338    {
339        fprintf(stderr, "*** Can't register Bar mgr - %s\n", error_text(st));
340        exit(1);
341    }
342}
343
344/*
345 * R E G I S T E R _ O B J S
346 *
347 * Register the bogus objects we handle.
348 */
349
350static void register_objs ()
351
352{
353    unsigned32          st;
354
355    rpc_object_set_type ((uuid_p_t) &FooObj1, (uuid_p_t) &FooType, &st);
356
357    if (st != 0)
358    {
359        fprintf(stderr, "*** Can't register Foo1 object - %s\n", error_text(st));
360        exit(1);
361    }
362
363    rpc_object_set_type ((uuid_p_t) &BarObj1, (uuid_p_t) &BarType, &st);
364
365    if (st != 0)
366    {
367        fprintf(stderr, "*** Can't register Bar1 object - %s\n", error_text(st));
368        exit(1);
369    }
370
371    rpc_object_set_type ((uuid_p_t) &FooObj2, (uuid_p_t) &FooType, &st);
372
373    if (st != 0)
374    {
375        fprintf(stderr, "*** Can't register Foo1 object - %s\n", error_text(st));
376        exit(1);
377    }
378
379    rpc_object_set_type ((uuid_p_t) &BarObj2, (uuid_p_t) &BarType, &st);
380
381    if (st != 0)
382    {
383        fprintf(stderr, "*** Can't register Bar2 object - %s\n", error_text(st));
384        exit(1);
385    }
386
387    rpc_object_set_type ((uuid_p_t) &ZotObj, (uuid_p_t) &ZotType, &st);
388
389    if (st != 0)
390    {
391        fprintf(stderr, "*** Can't register Zot object - %s\n", error_text(st));
392        exit(1);
393    }
394}
395
396/*
397 * G E T _ S O C K E T S
398 *
399 * Create sockets to listen on.
400 */
401
402static void get_sockets (argc, argv, max_calls)
403
404int                 argc;
405char                *argv[];
406unsigned32          max_calls;
407
408{
409    unsigned32          st;
410    unsigned long       i;
411
412    i = 2;
413
414    while (i < (unsigned)argc)
415    {
416        if (strcmp(argv[i], "all") == 0)
417        {
418            rpc_server_use_all_protseqs (max_calls, &st);
419        }
420        else if (strcmp(argv[i], "allif") == 0)
421        {
422            rpc_server_use_all_protseqs_if (max_calls, perf_v2_0_s_ifspec, &st);
423        }
424        else if (strcmp(argv[i], "notif") == 0)
425        {
426            rpc_server_use_protseq
427                ((unsigned_char_p_t) argv[i + 1], max_calls, &st);
428            i += 1;
429        }
430        else if (strcmp(argv[i], "ep") == 0)
431        {
432            rpc_server_use_protseq_ep
433                ((unsigned_char_p_t) argv[i + 1], max_calls,
434                    (unsigned_char_p_t) argv[i + 2], &st);
435            i += 2;
436        }
437        else
438        {
439            rpc_server_use_protseq_if
440                ((unsigned_char_p_t) argv[i], max_calls, perf_v2_0_s_ifspec, &st);
441        }
442
443        if (st != rpc_s_ok)
444        {
445            fprintf(stderr, "*** Can't use_protseq - %s\n", error_text(st));
446            exit(1);
447        }
448
449        i += 1;
450    }
451
452    rpc_server_inq_bindings(&bv, &st);
453
454    if (st != rpc_s_ok)
455    {
456        fprintf(stderr, "*** Can't inq_bindings - %lx\n", st);
457        exit(1);
458    }
459
460    for (i = 0; i < bv->count; i++)
461    {
462        unsigned_char_p_t sb;
463
464        rpc_binding_to_string_binding (bv->binding_h[i], &sb, &st);
465
466        if (st != rpc_s_ok)
467        {
468            fprintf(stderr, "*** Can't get string binding - %lx\n", st);
469            exit(1);
470        }
471
472        VRprintf (1, ("Got binding: %s\n", sb));
473
474        rpc_string_free(&sb, &st);
475    }
476}
477
478/*
479 * U S A G E
480 */
481
482void usage(void)
483
484{
485    fprintf(stderr, "usage: server [-sD] [-S <server loops>] [-d <debug switches>]\n");
486    fprintf(stderr, "              [-p <authn proto>,<principal>[,<keytab file>]] [-v <verbose level>]\n");
487    fprintf(stderr, "              [-B <bufsize>\n");
488    fprintf(stderr, "              <max calls> <protseq spec> [<protseq spec> ...]\n");
489    fprintf(stderr, "  -d: Turns on NCK runtime debug output\n");
490    fprintf(stderr, "  -D: Turns on default NCK runtime debug output\n");
491    fprintf(stderr, "  -s: Disable remote shutdown\n");
492    fprintf(stderr, "  -S: Number of times to run listen loop (default = 1)\n");
493    fprintf(stderr, "  -p: Accept authentication using <authn proto> to <principal>\n");
494    fprintf(stderr, "  -r: Use reserved threads\n");
495    fprintf(stderr, "  -e: Register with endpoint map at startup\n");
496    fprintf(stderr, "  -B: Set CN TCP socket buffer size (bytes)\n");
497    fprintf(stderr, "  -b: Register B interface with endpoint map at startup\n");
498    fprintf(stderr, "  <protseq spec> is one of:\n");
499    fprintf(stderr, "     <protseq>         (rpc_server_use_protseq_if)\n");
500    fprintf(stderr, "     all               (rpc_server_use_all_protseqs)\n");
501    fprintf(stderr, "     allif             (rpc_server_use_all_protseqs_if)\n");
502    fprintf(stderr, "     ep <endpoint>     (rpc_server_use_protseq_ep)\n");
503    fprintf(stderr, "     notif <protseq>   (rpc_server_use_protseq)\n");
504
505    exit(1);
506}
507
508/*
509 * P R I N T _ B I N D I N G _ I N F O
510 *
511 * Print out binding info (location and auth info) for a server binding.  This
512 * routine is called (selectively) from manager routines.
513 */
514
515void print_binding_info(text, h)
516
517char        *text;
518handle_t    h;
519
520{
521    unsigned32          st;
522    unsigned32          authn_level, authn_protocol, authz_protocol;
523    unsigned_char_p_t   server_princ, client_princ;
524    unsigned_char_p_t   name;
525
526    if (h == NULL)
527    {
528        return;
529    }
530
531    rpc_binding_to_string_binding (h, &name, &st);
532    if (st != rpc_s_ok)
533    {
534        fprintf (stderr, "*** Can't convert binding to string binding - %s\n",
535            error_text (st));
536        exit(1);
537    }
538
539    VRprintf (1, ("+ %s: called from %s ", text, name));
540
541    rpc_string_free (&name, &st);
542
543    if (verbose <= 1)
544    {
545        VRprintf (1, ("\n"));
546        return;
547    }
548
549    rpc_binding_inq_auth_client
550        (h, (rpc_authz_handle_t *) &client_princ, &server_princ,
551        &authn_level, &authn_protocol, &authz_protocol, &st);
552
553    if (st == rpc_s_binding_has_no_auth)
554    {
555        printf ("(unauthenticated)\n");
556    }
557    else if (st != rpc_s_ok)
558    {
559        printf ("(can't get auth info - %s)\n", error_text (st));
560    }
561    else
562    {
563        printf("(authentication info follows)\n");
564
565        printf("    authn protocol: %s\n    authz protocol: %s\n    level: %s\n    server princ: \"%s\"\n",
566            authn_names[authn_protocol],
567            authz_names[authz_protocol],
568            authn_level_names[authn_level],
569            server_princ == NULL ? "(NULL)" : (char *) server_princ);
570
571        if (server_princ != NULL)
572        {
573            rpc_string_free (&server_princ, &st);
574        }
575
576        switch (authz_protocol)
577        {
578        case rpc_c_authz_name:
579            printf("    client princ: \"%s\"\n",
580                client_princ == NULL ? "(NULL)" : (char *) client_princ);
581            break;
582
583#ifdef AUTH_KRB
584        case rpc_c_authz_dce:
585        {
586            sec_id_pac_t    *pac = (sec_id_pac_t *) client_princ;
587            unsigned16      i;
588
589            printf("    PAC: uid %d, gid %d, ngroups %d:",
590                pac->principal.uuid.time_low,
591                pac->group.uuid.time_low,
592                pac->num_groups);
593            for (i = 0; i < pac->num_groups; i++)
594            {
595                printf (" %d", pac->groups[i].uuid.time_low);
596            }
597            printf ("\n");
598            break;
599        }
600#endif /* AUTH_KRB */
601        default:
602            printf("    unknown authorization protocol\n");
603            break;
604        }
605    }
606}
607
608/*
609 * M A I N
610 *
611 * Main program.
612 */
613extern void dump_stg_info(void);
614extern void rpc__dbg_set_switches    (
615        char            * /*s*/,
616        unsigned32      * /*st*/
617    );
618void rpc__cn_set_sock_buffsize (
619        unsigned32	  /* rsize */,
620        unsigned32	  /* ssize */,
621        unsigned32	* /* st */);
622void rpc__cn_inq_sock_buffsize (
623        unsigned32	* /* rsize */,
624        unsigned32	* /* ssize */,
625        unsigned32  * /* st */);
626
627extern int lookup_name(char *table[], char *s);
628
629int main (argc, argv)
630
631int                 argc;
632char                *argv[];
633
634{
635    unsigned32      st;
636    idl_boolean     debug = false;
637    idl_char        *auth_principal, *auth_principal_2;
638    char            *s;
639    int             c;
640    unsigned32      authn_protocol;
641    unsigned16      i;
642    extern int      optind;
643    extern char     *optarg;
644    unsigned32      max_calls;
645    idl_boolean     ep_reg = false;     /* should we rpc_ep_register() at startup? */
646    idl_boolean     b_reg = false;      /* ditto for perfb i/f */
647    idl_char        *keytab;
648    unsigned32      ssize,rsize;
649
650	 DO_NOT_CLOBBER(i);
651	 DO_NOT_CLOBBER(ep_reg);
652
653    while ((c = getopt(argc, argv, "beslrDB:d:p:S:v:")) != EOF)
654    {
655        switch (c)
656        {
657        case 'd':
658        case 'D':
659            rpc__dbg_set_switches(c == 'd' ? optarg : DEBUG_LEVEL, &st);
660            if (st != rpc_s_ok)
661            {
662                fprintf(stderr, "*** Error setting debug level - %s\n",
663                    error_text(st));
664                usage();
665            }
666
667            debug = true;
668            break;
669
670        case 'p':
671            if ((s = (char *)strtok(optarg, ",")) == NULL)
672                usage();
673            authn_protocol = strcmp(s, "default") == 0 ?
674                                rpc_c_authn_default : lookup_name(authn_names, s);
675
676            if ((auth_principal = (idl_char *) strtok(NULL, ",")) == NULL)
677                usage();
678
679            keytab = (idl_char *) strtok(NULL, " ");
680
681            VRprintf(2, ("+ Authentication params; authn_protocol: %s, auth_principal: %s, keytab: %s\n",
682                authn_protocol == (unsigned32)rpc_c_authn_default ?
683                    "default" : authn_names[authn_protocol],
684                auth_principal,
685                keytab == NULL ?
686                   (idl_char *) "<not specified>" : keytab
687                ));
688
689            rpc_server_register_auth_info
690                ((unsigned_char_p_t) auth_principal, authn_protocol, NULL, keytab, &st);
691            if (st != rpc_s_ok)
692            {
693                fprintf(stderr, "*** Error setting principal - %s\n", error_text(st));
694                exit(1);
695            }
696
697            rpc_mgmt_inq_server_princ_name
698                (NULL, authn_protocol, &auth_principal_2, &st);
699            if (st != rpc_s_ok)
700            {
701                fprintf(stderr, "*** Can't get my principal name %s\n", error_text(st));
702                exit(1);
703            }
704            VRprintf(2, ("+ Server principal name set to \"%s\"\n", auth_principal_2));
705
706            auth = true;
707            break;
708
709        case 's':
710            shut_ok = false;
711            break;
712
713        case 'S':
714            server_loops = atoi(optarg);
715            break;
716
717        case 'v':
718            verbose = atoi(optarg);
719            break;
720
721        case 'r':
722            use_reserved_threads = true;
723            if (setup_thread_pools() != 0)
724                exit(1);
725            break;
726
727        case 'e':
728            ep_reg = true;
729            break;
730
731        case 'b':
732            b_reg = true;
733            break;
734
735        case 'B':
736            socket_buf_size = atoi(optarg);
737            break;
738
739        default:
740            usage();
741        }
742    }
743
744    argc -= optind - 1;
745    argv = &argv[optind - 1];
746
747    if (argc < 3)
748    {
749        usage();
750    }
751
752    if (debug)
753    {
754        dump_stg_info();
755    }
756
757    rpc__cn_set_sock_buffsize(socket_buf_size, socket_buf_size, &st);
758    if (st != rpc_s_ok)
759    {
760	fprintf(stderr,"*** rpc__cn_set_sock_buffsize failed (0x%lx)\n", st);
761	exit(1);
762    }
763
764    rpc__cn_inq_sock_buffsize(&rsize, &ssize, &st);
765    if (st != rpc_s_ok)
766    {
767	fprintf(stderr,"*** rpc__cn_inq_sock_buffsize failed (0x%lx)\n", st);
768	exit(1);
769    }
770    if (socket_buf_size != rsize || socket_buf_size != ssize)
771    {
772        fprintf(stderr, "*** CN socket buffer sizes dont match:\n");
773        fprintf(stderr, "*** READ desired: %lu   actual: %lu\n", socket_buf_size, rsize);
774        fprintf(stderr, "*** WRITE desired: %lu  actual: %lu\n", socket_buf_size, ssize);
775	exit(1);
776    }
777
778    rpc_mgmt_set_authorization_fn(mgmt_auth_fn, &st);
779
780    max_calls = atoi(argv[1]);
781
782    get_sockets(argc, argv, max_calls);
783    register_ifs();
784    register_objs();
785
786    if (ep_reg)
787    {
788        rpc_ep_register(perf_v2_0_s_ifspec, bv, (uuid_vector_p_t) &object_vec,
789                (unsigned_char_p_t) "perf test", &st);
790        if (st != rpc_s_ok)
791        {
792            fprintf(stderr, "*** Can't register with endpoint map - %s\n",
793                    error_text(st));
794            exit(1);
795        }
796    }
797
798    if (b_reg)
799    {
800        perf_register_b(NULL, false, &st);
801        if (st != rpc_s_ok)
802        {
803            fprintf(stderr, "*** Can't register B interface with endpoint map - %s\n",
804                    error_text(st));
805            exit(1);
806        }
807    }
808
809    i = 0;
810
811    TRY
812    {
813        while (true)
814        {
815            VRprintf(1, ("+ Listening...\n"));
816
817            rpc_server_listen(max_calls, &st);
818            if (st != rpc_s_ok)
819            {
820                fprintf(stderr, "*** Listen returns - %s\n", error_text(st));
821                exit(1);
822            }
823
824            if (++i >= server_loops)
825            {
826                break;
827            }
828
829            /*
830             * Unreserve threads on the last server_loop iteration.
831             */
832            if (use_reserved_threads && i == (server_loops - 1))
833            {
834                VRprintf (1, ("+ Returned from listen; unreserving threads\n"));
835                teardown_thread_pools(true /* block */);
836            }
837
838            VRprintf (2, ("+ Returned from listen; sleeping for %d secs\n",
839                        SERVER_LOOP_SLEEP_TIME));
840            SLEEP (SERVER_LOOP_SLEEP_TIME);
841        }
842    }
843    FINALLY
844    {
845        if (ep_reg)
846        {
847            rpc_ep_unregister(perf_v2_0_s_ifspec, bv, (uuid_vector_p_t) &object_vec,
848                    &st);
849            if (st != rpc_s_ok)
850            {
851                fprintf(stderr, "*** Can't unregister from endpoint map - %s\n",
852                        error_text(st));
853            }
854        }
855    }
856    ENDTRY
857
858    VRprintf(1, ("Exiting\n"));
859	 return 0;
860}
861