1*dec98d2aSGordon Ross /*
2*dec98d2aSGordon Ross * CDDL HEADER START
3*dec98d2aSGordon Ross *
4*dec98d2aSGordon Ross * The contents of this file are subject to the terms of the
5*dec98d2aSGordon Ross * Common Development and Distribution License (the "License").
6*dec98d2aSGordon Ross * You may not use this file except in compliance with the License.
7*dec98d2aSGordon Ross *
8*dec98d2aSGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*dec98d2aSGordon Ross * or http://www.opensolaris.org/os/licensing.
10*dec98d2aSGordon Ross * See the License for the specific language governing permissions
11*dec98d2aSGordon Ross * and limitations under the License.
12*dec98d2aSGordon Ross *
13*dec98d2aSGordon Ross * When distributing Covered Code, include this CDDL HEADER in each
14*dec98d2aSGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*dec98d2aSGordon Ross * If applicable, add the following below this CDDL HEADER, with the
16*dec98d2aSGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
17*dec98d2aSGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
18*dec98d2aSGordon Ross *
19*dec98d2aSGordon Ross * CDDL HEADER END
20*dec98d2aSGordon Ross */
21*dec98d2aSGordon Ross
22*dec98d2aSGordon Ross /*
23*dec98d2aSGordon Ross * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24*dec98d2aSGordon Ross * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
25*dec98d2aSGordon Ross * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
26*dec98d2aSGordon Ross */
27*dec98d2aSGordon Ross
28*dec98d2aSGordon Ross /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
29*dec98d2aSGordon Ross /* All Rights Reserved */
30*dec98d2aSGordon Ross
31*dec98d2aSGordon Ross /*
32*dec98d2aSGordon Ross * Portions of this source code were derived from Berkeley 4.3 BSD
33*dec98d2aSGordon Ross * under license from the Regents of the University of California.
34*dec98d2aSGordon Ross */
35*dec98d2aSGordon Ross
36*dec98d2aSGordon Ross #include <stdio.h>
37*dec98d2aSGordon Ross #include <stdlib.h>
38*dec98d2aSGordon Ross #include <ctype.h>
39*dec98d2aSGordon Ross #include <sys/types.h>
40*dec98d2aSGordon Ross #include <string.h>
41*dec98d2aSGordon Ross #include <syslog.h>
42*dec98d2aSGordon Ross #include <sys/param.h>
43*dec98d2aSGordon Ross #include <rpc/rpc.h>
44*dec98d2aSGordon Ross #include <sys/stat.h>
45*dec98d2aSGordon Ross #include <netconfig.h>
46*dec98d2aSGordon Ross #include <netdir.h>
47*dec98d2aSGordon Ross
48*dec98d2aSGordon Ross #include <sys/file.h>
49*dec98d2aSGordon Ross #include <sys/time.h>
50*dec98d2aSGordon Ross #include <sys/errno.h>
51*dec98d2aSGordon Ross #include <rpcsvc/mount.h>
52*dec98d2aSGordon Ross
53*dec98d2aSGordon Ross #include <signal.h>
54*dec98d2aSGordon Ross #include <locale.h>
55*dec98d2aSGordon Ross #include <unistd.h>
56*dec98d2aSGordon Ross #include <errno.h>
57*dec98d2aSGordon Ross #include <sys/socket.h>
58*dec98d2aSGordon Ross #include <netinet/in.h>
59*dec98d2aSGordon Ross #include <arpa/inet.h>
60*dec98d2aSGordon Ross #include <netdb.h>
61*dec98d2aSGordon Ross
62*dec98d2aSGordon Ross #include <thread.h>
63*dec98d2aSGordon Ross #include <assert.h>
64*dec98d2aSGordon Ross
65*dec98d2aSGordon Ross #include <limits.h>
66*dec98d2aSGordon Ross
67*dec98d2aSGordon Ross #define TESTPROG 987654
68*dec98d2aSGordon Ross
69*dec98d2aSGordon Ross uint32_t test_vers_max = 2;
70*dec98d2aSGordon Ross uint32_t test_vers_min = 1;
71*dec98d2aSGordon Ross
72*dec98d2aSGordon Ross int debug;
73*dec98d2aSGordon Ross int verbose;
74*dec98d2aSGordon Ross int testd_port;
75*dec98d2aSGordon Ross
76*dec98d2aSGordon Ross static void mysvc(struct svc_req *, SVCXPRT *);
77*dec98d2aSGordon Ross static void bind2(void);
78*dec98d2aSGordon Ross
79*dec98d2aSGordon Ross /*
80*dec98d2aSGordon Ross * This function is called for each configured network type to
81*dec98d2aSGordon Ross * bind and register our RPC service programs.
82*dec98d2aSGordon Ross *
83*dec98d2aSGordon Ross * On TCP or UDP, we want to bind TESTPROG on a specific port
84*dec98d2aSGordon Ross * (when testd_port is specified) in which case we'll use the
85*dec98d2aSGordon Ross * variant of svc_tp_create() that lets us pass a bind address.
86*dec98d2aSGordon Ross */
87*dec98d2aSGordon Ross static void
test_svc_tp_create(struct netconfig * nconf)88*dec98d2aSGordon Ross test_svc_tp_create(struct netconfig *nconf)
89*dec98d2aSGordon Ross {
90*dec98d2aSGordon Ross char port_str[8];
91*dec98d2aSGordon Ross struct nd_hostserv hs;
92*dec98d2aSGordon Ross struct nd_addrlist *al = NULL;
93*dec98d2aSGordon Ross SVCXPRT *xprt = NULL;
94*dec98d2aSGordon Ross rpcvers_t vers;
95*dec98d2aSGordon Ross
96*dec98d2aSGordon Ross vers = test_vers_max;
97*dec98d2aSGordon Ross
98*dec98d2aSGordon Ross /*
99*dec98d2aSGordon Ross * If testd_port is set and this is an inet transport,
100*dec98d2aSGordon Ross * bind this service on the specified port.
101*dec98d2aSGordon Ross */
102*dec98d2aSGordon Ross if (testd_port != 0 &&
103*dec98d2aSGordon Ross (strcmp(nconf->nc_protofmly, NC_INET) == 0 ||
104*dec98d2aSGordon Ross strcmp(nconf->nc_protofmly, NC_INET6) == 0)) {
105*dec98d2aSGordon Ross int err;
106*dec98d2aSGordon Ross
107*dec98d2aSGordon Ross snprintf(port_str, sizeof (port_str), "%u",
108*dec98d2aSGordon Ross (unsigned short)testd_port);
109*dec98d2aSGordon Ross
110*dec98d2aSGordon Ross hs.h_host = HOST_SELF_BIND;
111*dec98d2aSGordon Ross hs.h_serv = port_str;
112*dec98d2aSGordon Ross err = netdir_getbyname((struct netconfig *)nconf, &hs, &al);
113*dec98d2aSGordon Ross if (err == 0 && al != NULL) {
114*dec98d2aSGordon Ross xprt = svc_tp_create_addr(mysvc, TESTPROG, vers,
115*dec98d2aSGordon Ross nconf, al->n_addrs);
116*dec98d2aSGordon Ross netdir_free(al, ND_ADDRLIST);
117*dec98d2aSGordon Ross }
118*dec98d2aSGordon Ross if (xprt == NULL) {
119*dec98d2aSGordon Ross printf("testd: unable to create "
120*dec98d2aSGordon Ross "(TESTD,%d) on transport %s (port %d)\n",
121*dec98d2aSGordon Ross (int)vers, nconf->nc_netid, testd_port);
122*dec98d2aSGordon Ross }
123*dec98d2aSGordon Ross /* fall-back to default bind */
124*dec98d2aSGordon Ross }
125*dec98d2aSGordon Ross if (xprt == NULL) {
126*dec98d2aSGordon Ross /*
127*dec98d2aSGordon Ross * Had testd_port=0, or non-inet transport,
128*dec98d2aSGordon Ross * or the bind to a specific port failed.
129*dec98d2aSGordon Ross * Do a default bind.
130*dec98d2aSGordon Ross */
131*dec98d2aSGordon Ross xprt = svc_tp_create(mysvc, TESTPROG, vers, nconf);
132*dec98d2aSGordon Ross }
133*dec98d2aSGordon Ross if (xprt == NULL) {
134*dec98d2aSGordon Ross printf("testd: unable to create "
135*dec98d2aSGordon Ross "(TESTD,%d) on transport %s\n",
136*dec98d2aSGordon Ross (int)vers, nconf->nc_netid);
137*dec98d2aSGordon Ross return;
138*dec98d2aSGordon Ross }
139*dec98d2aSGordon Ross
140*dec98d2aSGordon Ross /*
141*dec98d2aSGordon Ross * Register additional versions on this transport.
142*dec98d2aSGordon Ross */
143*dec98d2aSGordon Ross while (--vers >= test_vers_min) {
144*dec98d2aSGordon Ross if (!svc_reg(xprt, TESTPROG, vers, mysvc, nconf)) {
145*dec98d2aSGordon Ross printf("testd: "
146*dec98d2aSGordon Ross "failed to register vers %d on %s\n",
147*dec98d2aSGordon Ross (int)vers, nconf->nc_netid);
148*dec98d2aSGordon Ross }
149*dec98d2aSGordon Ross }
150*dec98d2aSGordon Ross }
151*dec98d2aSGordon Ross
152*dec98d2aSGordon Ross static void
test_svc_unreg(void)153*dec98d2aSGordon Ross test_svc_unreg(void)
154*dec98d2aSGordon Ross {
155*dec98d2aSGordon Ross rpcvers_t vers;
156*dec98d2aSGordon Ross
157*dec98d2aSGordon Ross for (vers = test_vers_min; vers <= test_vers_max; vers++)
158*dec98d2aSGordon Ross svc_unreg(TESTPROG, vers);
159*dec98d2aSGordon Ross }
160*dec98d2aSGordon Ross
161*dec98d2aSGordon Ross int
main(int argc,char * argv[])162*dec98d2aSGordon Ross main(int argc, char *argv[])
163*dec98d2aSGordon Ross {
164*dec98d2aSGordon Ross int c;
165*dec98d2aSGordon Ross bool_t exclbind = TRUE;
166*dec98d2aSGordon Ross int tmp;
167*dec98d2aSGordon Ross struct netconfig *nconf;
168*dec98d2aSGordon Ross NCONF_HANDLE *nc;
169*dec98d2aSGordon Ross
170*dec98d2aSGordon Ross while ((c = getopt(argc, argv, "dvp:")) != EOF) {
171*dec98d2aSGordon Ross switch (c) {
172*dec98d2aSGordon Ross case 'd':
173*dec98d2aSGordon Ross debug++;
174*dec98d2aSGordon Ross break;
175*dec98d2aSGordon Ross case 'v':
176*dec98d2aSGordon Ross verbose++;
177*dec98d2aSGordon Ross break;
178*dec98d2aSGordon Ross case 'p':
179*dec98d2aSGordon Ross (void) sscanf(optarg, "%d", &tmp);
180*dec98d2aSGordon Ross if (tmp < 1 || tmp > UINT16_MAX) {
181*dec98d2aSGordon Ross (void) fprintf(stderr,
182*dec98d2aSGordon Ross "testd: -P port invalid.\n");
183*dec98d2aSGordon Ross return (1);
184*dec98d2aSGordon Ross }
185*dec98d2aSGordon Ross testd_port = tmp;
186*dec98d2aSGordon Ross break;
187*dec98d2aSGordon Ross default:
188*dec98d2aSGordon Ross fprintf(stderr, "usage: testd [-v] [-r]\n");
189*dec98d2aSGordon Ross exit(1);
190*dec98d2aSGordon Ross }
191*dec98d2aSGordon Ross }
192*dec98d2aSGordon Ross
193*dec98d2aSGordon Ross (void) setlocale(LC_ALL, "");
194*dec98d2aSGordon Ross
195*dec98d2aSGordon Ross #if !defined(TEXT_DOMAIN)
196*dec98d2aSGordon Ross #define TEXT_DOMAIN "SYS_TEST"
197*dec98d2aSGordon Ross #endif
198*dec98d2aSGordon Ross (void) textdomain(TEXT_DOMAIN);
199*dec98d2aSGordon Ross
200*dec98d2aSGordon Ross /*
201*dec98d2aSGordon Ross * Prevent our non-priv udp and tcp ports bound w/wildcard addr
202*dec98d2aSGordon Ross * from being hijacked by a bind to a more specific addr.
203*dec98d2aSGordon Ross */
204*dec98d2aSGordon Ross if (!rpc_control(__RPC_SVC_EXCLBIND_SET, &exclbind)) {
205*dec98d2aSGordon Ross fprintf(stderr, "warning: unable to set udp/tcp EXCLBIND\n");
206*dec98d2aSGordon Ross }
207*dec98d2aSGordon Ross
208*dec98d2aSGordon Ross if (testd_port < 0 || testd_port > UINT16_MAX) {
209*dec98d2aSGordon Ross fprintf(stderr, "unable to use specified port\n");
210*dec98d2aSGordon Ross exit(1);
211*dec98d2aSGordon Ross }
212*dec98d2aSGordon Ross
213*dec98d2aSGordon Ross /*
214*dec98d2aSGordon Ross * Make sure to unregister any previous versions in case the
215*dec98d2aSGordon Ross * user is reconfiguring the server in interesting ways.
216*dec98d2aSGordon Ross */
217*dec98d2aSGordon Ross test_svc_unreg();
218*dec98d2aSGordon Ross
219*dec98d2aSGordon Ross /*
220*dec98d2aSGordon Ross * Enumerate network transports and create service listeners
221*dec98d2aSGordon Ross * as appropriate for each.
222*dec98d2aSGordon Ross */
223*dec98d2aSGordon Ross if ((nc = setnetconfig()) == NULL) {
224*dec98d2aSGordon Ross perror("setnetconfig failed");
225*dec98d2aSGordon Ross return (-1);
226*dec98d2aSGordon Ross }
227*dec98d2aSGordon Ross while ((nconf = getnetconfig(nc)) != NULL) {
228*dec98d2aSGordon Ross /*
229*dec98d2aSGordon Ross * Skip things like tpi_raw, invisible...
230*dec98d2aSGordon Ross */
231*dec98d2aSGordon Ross if ((nconf->nc_flag & NC_VISIBLE) == 0)
232*dec98d2aSGordon Ross continue;
233*dec98d2aSGordon Ross if (nconf->nc_semantics != NC_TPI_CLTS &&
234*dec98d2aSGordon Ross nconf->nc_semantics != NC_TPI_COTS &&
235*dec98d2aSGordon Ross nconf->nc_semantics != NC_TPI_COTS_ORD)
236*dec98d2aSGordon Ross continue;
237*dec98d2aSGordon Ross
238*dec98d2aSGordon Ross test_svc_tp_create(nconf);
239*dec98d2aSGordon Ross }
240*dec98d2aSGordon Ross (void) endnetconfig(nc);
241*dec98d2aSGordon Ross
242*dec98d2aSGordon Ross /*
243*dec98d2aSGordon Ross * XXX: Normally would call svc_run() here, but
244*dec98d2aSGordon Ross * we just want to check our IP bindings.
245*dec98d2aSGordon Ross */
246*dec98d2aSGordon Ross if (testd_port != 0)
247*dec98d2aSGordon Ross bind2();
248*dec98d2aSGordon Ross
249*dec98d2aSGordon Ross if (debug) {
250*dec98d2aSGordon Ross char sysbuf[100];
251*dec98d2aSGordon Ross
252*dec98d2aSGordon Ross snprintf(sysbuf, sizeof (sysbuf),
253*dec98d2aSGordon Ross "rpcinfo -p |grep %u", TESTPROG);
254*dec98d2aSGordon Ross printf("x %s\n", sysbuf);
255*dec98d2aSGordon Ross fflush(stdout);
256*dec98d2aSGordon Ross system(sysbuf);
257*dec98d2aSGordon Ross
258*dec98d2aSGordon Ross if (testd_port) {
259*dec98d2aSGordon Ross snprintf(sysbuf, sizeof (sysbuf),
260*dec98d2aSGordon Ross "netstat -a -f inet -P udp |grep %u", testd_port);
261*dec98d2aSGordon Ross printf("x %s\n", sysbuf);
262*dec98d2aSGordon Ross fflush(stdout);
263*dec98d2aSGordon Ross system(sysbuf);
264*dec98d2aSGordon Ross
265*dec98d2aSGordon Ross snprintf(sysbuf, sizeof (sysbuf),
266*dec98d2aSGordon Ross "netstat -a -f inet -P tcp |grep %u", testd_port);
267*dec98d2aSGordon Ross printf("x %s\n", sysbuf);
268*dec98d2aSGordon Ross fflush(stdout);
269*dec98d2aSGordon Ross system(sysbuf);
270*dec98d2aSGordon Ross }
271*dec98d2aSGordon Ross }
272*dec98d2aSGordon Ross
273*dec98d2aSGordon Ross /* cleanup */
274*dec98d2aSGordon Ross test_svc_unreg();
275*dec98d2aSGordon Ross
276*dec98d2aSGordon Ross printf("%s complete\n", argv[0]);
277*dec98d2aSGordon Ross return (0);
278*dec98d2aSGordon Ross }
279*dec98d2aSGordon Ross
280*dec98d2aSGordon Ross /*
281*dec98d2aSGordon Ross * Server procedure switch routine
282*dec98d2aSGordon Ross */
283*dec98d2aSGordon Ross static void
mysvc(struct svc_req * rq,SVCXPRT * xprt)284*dec98d2aSGordon Ross mysvc(struct svc_req *rq, SVCXPRT *xprt)
285*dec98d2aSGordon Ross {
286*dec98d2aSGordon Ross
287*dec98d2aSGordon Ross switch (rq->rq_proc) {
288*dec98d2aSGordon Ross case NULLPROC:
289*dec98d2aSGordon Ross errno = 0;
290*dec98d2aSGordon Ross (void) svc_sendreply(xprt, xdr_void, (char *)0);
291*dec98d2aSGordon Ross return;
292*dec98d2aSGordon Ross
293*dec98d2aSGordon Ross default:
294*dec98d2aSGordon Ross svcerr_noproc(xprt);
295*dec98d2aSGordon Ross return;
296*dec98d2aSGordon Ross }
297*dec98d2aSGordon Ross }
298*dec98d2aSGordon Ross
299*dec98d2aSGordon Ross struct sockaddr_in addr;
300*dec98d2aSGordon Ross
301*dec98d2aSGordon Ross /*
302*dec98d2aSGordon Ross * The actual test: Try doing a 2nd bind with a specific IP.
303*dec98d2aSGordon Ross * The exclusive wildcard bind should prvent this.
304*dec98d2aSGordon Ross */
305*dec98d2aSGordon Ross static void
bind2(void)306*dec98d2aSGordon Ross bind2(void)
307*dec98d2aSGordon Ross {
308*dec98d2aSGordon Ross int ret;
309*dec98d2aSGordon Ross int sock;
310*dec98d2aSGordon Ross
311*dec98d2aSGordon Ross addr.sin_family = AF_INET;
312*dec98d2aSGordon Ross addr.sin_port = htons(testd_port);
313*dec98d2aSGordon Ross addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
314*dec98d2aSGordon Ross
315*dec98d2aSGordon Ross sock = socket(AF_INET, SOCK_STREAM, 0);
316*dec98d2aSGordon Ross if (sock == -1) {
317*dec98d2aSGordon Ross fprintf(stderr, "bind2 socket fail %s\n",
318*dec98d2aSGordon Ross strerror(errno));
319*dec98d2aSGordon Ross exit(1);
320*dec98d2aSGordon Ross }
321*dec98d2aSGordon Ross
322*dec98d2aSGordon Ross ret = bind(sock, (struct sockaddr *)&addr, sizeof (addr));
323*dec98d2aSGordon Ross if (ret == -1) {
324*dec98d2aSGordon Ross fprintf(stderr, "bind2 bind fail %s (expected) PASS\n",
325*dec98d2aSGordon Ross strerror(errno));
326*dec98d2aSGordon Ross close(sock);
327*dec98d2aSGordon Ross return;
328*dec98d2aSGordon Ross }
329*dec98d2aSGordon Ross
330*dec98d2aSGordon Ross printf("Oh no, bind2 worked! test FAILED\n");
331*dec98d2aSGordon Ross close(sock);
332*dec98d2aSGordon Ross }
333