4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
25 * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
32 * Portions of this source code were derived from Berkeley 4.3 BSD
33 * under license from the Regents of the University of California.
39 #include <sys/types.h>
42 #include <sys/param.h>
45 #include <netconfig.h>
50 #include <sys/errno.h>
51 #include <rpcsvc/mount.h>
57 #include <sys/socket.h>
58 #include <netinet/in.h>
59 #include <arpa/inet.h>
67 #define TESTPROG 987654
69 uint32_t test_vers_max
= 2;
70 uint32_t test_vers_min
= 1;
76 static void mysvc(struct svc_req
*, SVCXPRT
*);
77 static void bind2(void);
80 * This function is called for each configured network type to
81 * bind and register our RPC service programs.
83 * On TCP or UDP, we want to bind TESTPROG on a specific port
84 * (when testd_port is specified) in which case we'll use the
85 * variant of svc_tp_create() that lets us pass a bind address.
88 test_svc_tp_create(struct netconfig
*nconf
)
91 struct nd_hostserv hs
;
92 struct nd_addrlist
*al
= NULL
;
99 * If testd_port is set and this is an inet transport,
100 * bind this service on the specified port.
102 if (testd_port
!= 0 &&
103 (strcmp(nconf
->nc_protofmly
, NC_INET
) == 0 ||
104 strcmp(nconf
->nc_protofmly
, NC_INET6
) == 0)) {
107 snprintf(port_str
, sizeof (port_str
), "%u",
108 (unsigned short)testd_port
);
110 hs
.h_host
= HOST_SELF_BIND
;
111 hs
.h_serv
= port_str
;
112 err
= netdir_getbyname((struct netconfig
*)nconf
, &hs
, &al
);
113 if (err
== 0 && al
!= NULL
) {
114 xprt
= svc_tp_create_addr(mysvc
, TESTPROG
, vers
,
116 netdir_free(al
, ND_ADDRLIST
);
119 printf("testd: unable to create "
120 "(TESTD,%d) on transport %s (port %d)\n",
121 (int)vers
, nconf
->nc_netid
, testd_port
);
123 /* fall-back to default bind */
127 * Had testd_port=0, or non-inet transport,
128 * or the bind to a specific port failed.
131 xprt
= svc_tp_create(mysvc
, TESTPROG
, vers
, nconf
);
134 printf("testd: unable to create "
135 "(TESTD,%d) on transport %s\n",
136 (int)vers
, nconf
->nc_netid
);
141 * Register additional versions on this transport.
143 while (--vers
>= test_vers_min
) {
144 if (!svc_reg(xprt
, TESTPROG
, vers
, mysvc
, nconf
)) {
146 "failed to register vers %d on %s\n",
147 (int)vers
, nconf
->nc_netid
);
157 for (vers
= test_vers_min
; vers
<= test_vers_max
; vers
++)
158 svc_unreg(TESTPROG
, vers
);
162 main(int argc
, char *argv
[])
165 bool_t exclbind
= TRUE
;
167 struct netconfig
*nconf
;
170 while ((c
= getopt(argc
, argv
, "dvp:")) != EOF
) {
179 (void) sscanf(optarg
, "%d", &tmp
);
180 if (tmp
< 1 || tmp
> UINT16_MAX
) {
181 (void) fprintf(stderr
,
182 "testd: -P port invalid.\n");
188 fprintf(stderr
, "usage: testd [-v] [-r]\n");
193 (void) setlocale(LC_ALL
, "");
195 #if !defined(TEXT_DOMAIN)
196 #define TEXT_DOMAIN "SYS_TEST"
198 (void) textdomain(TEXT_DOMAIN
);
201 * Prevent our non-priv udp and tcp ports bound w/wildcard addr
202 * from being hijacked by a bind to a more specific addr.
204 if (!rpc_control(__RPC_SVC_EXCLBIND_SET
, &exclbind
)) {
205 fprintf(stderr
, "warning: unable to set udp/tcp EXCLBIND\n");
208 if (testd_port
< 0 || testd_port
> UINT16_MAX
) {
209 fprintf(stderr
, "unable to use specified port\n");
214 * Make sure to unregister any previous versions in case the
215 * user is reconfiguring the server in interesting ways.
220 * Enumerate network transports and create service listeners
221 * as appropriate for each.
223 if ((nc
= setnetconfig()) == NULL
) {
224 perror("setnetconfig failed");
227 while ((nconf
= getnetconfig(nc
)) != NULL
) {
229 * Skip things like tpi_raw, invisible...
231 if ((nconf
->nc_flag
& NC_VISIBLE
) == 0)
233 if (nconf
->nc_semantics
!= NC_TPI_CLTS
&&
234 nconf
->nc_semantics
!= NC_TPI_COTS
&&
235 nconf
->nc_semantics
!= NC_TPI_COTS_ORD
)
238 test_svc_tp_create(nconf
);
240 (void) endnetconfig(nc
);
243 * XXX: Normally would call svc_run() here, but
244 * we just want to check our IP bindings.
252 snprintf(sysbuf
, sizeof (sysbuf
),
253 "rpcinfo -p |grep %u", TESTPROG
);
254 printf("x %s\n", sysbuf
);
259 snprintf(sysbuf
, sizeof (sysbuf
),
260 "netstat -a -f inet -P udp |grep %u", testd_port
);
261 printf("x %s\n", sysbuf
);
265 snprintf(sysbuf
, sizeof (sysbuf
),
266 "netstat -a -f inet -P tcp |grep %u", testd_port
);
267 printf("x %s\n", sysbuf
);
276 printf("%s complete\n", argv
[0]);
281 * Server procedure switch routine
284 mysvc(struct svc_req
*rq
, SVCXPRT
*xprt
)
287 switch (rq
->rq_proc
) {
290 (void) svc_sendreply(xprt
, xdr_void
, (char *)0);
299 struct sockaddr_in addr
;
302 * The actual test: Try doing a 2nd bind with a specific IP.
303 * The exclusive wildcard bind should prvent this.
311 addr
.sin_family
= AF_INET
;
312 addr
.sin_port
= htons(testd_port
);
313 addr
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
315 sock
= socket(AF_INET
, SOCK_STREAM
, 0);
317 fprintf(stderr
, "bind2 socket fail %s\n",
322 ret
= bind(sock
, (struct sockaddr
*)&addr
, sizeof (addr
));
324 fprintf(stderr
, "bind2 bind fail %s (expected) PASS\n",
330 printf("Oh no, bind2 worked! test FAILED\n");