2 * Copyright (c) 1997-1999 Erez Zadok
3 * Copyright (c) 1990 Jan-Simon Pendry
4 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
5 * Copyright (c) 1990 The Regents of the University of California.
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgment:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 * $Id: transp_sockets.c,v 1.5 1999/08/22 21:12:31 ezk Exp $
43 * Socket specific utilities.
44 * -Erez Zadok <ezk@cs.columbia.edu>
49 #endif /* HAVE_CONFIG_H */
55 * find the IP address that can be used to connect to the local host
58 amu_get_myaddress(struct in_addr
*iap
)
60 struct sockaddr_in sin
;
62 memset((char *) &sin
, 0, sizeof(sin
));
64 iap
->s_addr
= sin
.sin_addr
.s_addr
;
69 * How to bind to reserved ports.
72 bind_resv_port(int so
, u_short
*pp
)
74 struct sockaddr_in sin
;
78 memset((voidp
) &sin
, 0, sizeof(sin
));
79 sin
.sin_family
= AF_INET
;
81 port
= IPPORT_RESERVED
;
85 sin
.sin_port
= htons(port
);
86 rc
= bind(so
, (struct sockaddr
*) &sin
, sizeof(sin
));
87 } while (rc
< 0 && (int) port
> IPPORT_RESERVED
/ 2);
97 * close a descriptor, Sockets style
107 * Create an rpc client attached to the mount daemon.
110 get_mount_client(char *unused_host
, struct sockaddr_in
*sin
, struct timeval
*tv
, int *sock
, u_long mnt_version
)
115 * First try a TCP socket
117 if ((*sock
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
)) > 0) {
119 * Bind to a privileged port
121 if (bind_resv_port(*sock
, (u_short
*) 0) < 0)
122 plog(XLOG_ERROR
, "can't bind privileged port");
125 * Find mountd port to connect to.
127 * Create a tcp client.
129 if ((sin
->sin_port
= htons(pmap_getport(sin
, MOUNTPROG
, mnt_version
, IPPROTO_TCP
))) != 0) {
130 if (connect(*sock
, (struct sockaddr
*) sin
, sizeof(*sin
)) >= 0
131 && ((client
= clnttcp_create(sin
, MOUNTPROG
, mnt_version
, sock
, 0, 0)) != NULL
))
135 * Failed so close socket
138 } /* tcp socket opened */
139 /* TCP failed so try UDP */
140 if ((*sock
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
141 plog(XLOG_ERROR
, "Can't create socket to connect to mountd: %m");
146 * Bind to a privileged port
148 if (bind_resv_port(*sock
, (u_short
*) 0) < 0)
149 plog(XLOG_ERROR
, "can't bind privileged port");
152 * Zero out the port - make sure we recompute
159 if ((client
= clntudp_create(sin
, MOUNTPROG
, mnt_version
, *tv
, sock
)) == NULL
) {
165 dlog("get_mount_client: Using udp, port %d", sin
->sin_port
);
172 * find the address of the caller of an RPC procedure.
175 amu_svc_getcaller(SVCXPRT
*xprt
)
177 return svc_getcaller(xprt
);
182 * Create the nfs service for amd
185 create_nfs_service(int *soNFSp
, u_short
*nfs_portp
, SVCXPRT
**nfs_xprtp
, void (*dispatch_fxn
)(struct svc_req
*rqstp
, SVCXPRT
*transp
))
188 *soNFSp
= socket(AF_INET
, SOCK_DGRAM
, 0);
190 if (*soNFSp
< 0 || bind_resv_port(*soNFSp
, NULL
) < 0) {
191 plog(XLOG_FATAL
, "Can't create privileged nfs port");
194 if ((*nfs_xprtp
= svcudp_create(*soNFSp
)) == NULL
) {
195 plog(XLOG_FATAL
, "cannot create rpc/udp service");
198 if ((*nfs_portp
= (*nfs_xprtp
)->xp_port
) >= IPPORT_RESERVED
) {
199 plog(XLOG_FATAL
, "Can't create privileged nfs port");
202 if (!svc_register(*nfs_xprtp
, NFS_PROGRAM
, NFS_VERSION
, dispatch_fxn
, 0)) {
203 plog(XLOG_FATAL
, "unable to register (NFS_PROGRAM, NFS_VERSION, 0)");
207 return 0; /* all is well */
212 * Create the amq service for amd (both TCP and UDP)
215 create_amq_service(int *udp_soAMQp
, SVCXPRT
**udp_amqpp
, int *tcp_soAMQp
, SVCXPRT
**tcp_amqpp
)
217 /* first create TCP service */
219 *tcp_soAMQp
= socket(AF_INET
, SOCK_STREAM
, 0);
220 if (*tcp_soAMQp
< 0) {
221 plog(XLOG_FATAL
, "cannot create tcp socket for amq service: %m");
225 /* now create RPC service handle for amq */
227 (*tcp_amqpp
= svctcp_create(*tcp_soAMQp
, AMQ_SIZE
, AMQ_SIZE
)) == NULL
) {
228 plog(XLOG_FATAL
, "cannot create tcp service for amq: soAMQp=%d", *tcp_soAMQp
);
233 /* next create UDP service */
235 *udp_soAMQp
= socket(AF_INET
, SOCK_DGRAM
, 0);
236 if (*udp_soAMQp
< 0) {
237 plog(XLOG_FATAL
, "cannot create udp socket for amq service: %m");
241 /* now create RPC service handle for amq */
243 (*udp_amqpp
= svcudp_bufcreate(*udp_soAMQp
, AMQ_SIZE
, AMQ_SIZE
)) == NULL
) {
244 plog(XLOG_FATAL
, "cannot create udp service for amq: soAMQp=%d", *udp_soAMQp
);
249 return 0; /* all is well */
254 * Ping the portmapper on a remote system by calling the nullproc
257 pmap_ping(struct sockaddr_in
*address
)
260 enum clnt_stat clnt_stat
= RPC_TIMEDOUT
; /* assume failure */
261 int socket
= RPC_ANYSOCK
;
262 struct timeval timeout
;
266 address
->sin_port
= htons(PMAPPORT
);
267 client
= clntudp_create(address
, PMAPPROG
, PMAPVERS
, timeout
, &socket
);
268 if (client
!= (CLIENT
*) NULL
) {
269 clnt_stat
= clnt_call(client
,
271 (XDRPROC_T_TYPE
) xdr_void
,
273 (XDRPROC_T_TYPE
) xdr_void
,
276 clnt_destroy(client
);
279 address
->sin_port
= 0;
286 * Find the best NFS version for a host and protocol.
289 get_nfs_version(char *host
, struct sockaddr_in
*sin
, u_long nfs_version
, const char *proto
)
293 enum clnt_stat clnt_stat
;
298 * If not set or set wrong, then try from NFS_VERS_MAX on down. If
299 * set, then try from nfs_version on down.
301 if (nfs_version
<= 0 || nfs_version
> NFS_VERS_MAX
) {
302 nfs_version
= NFS_VERS_MAX
;
305 tv
.tv_sec
= 3; /* retry every 3 seconds, but also timeout */
309 * First check if remote portmapper is up (verify if remote host is up).
311 clnt_stat
= pmap_ping(sin
);
312 if (clnt_stat
== RPC_TIMEDOUT
) {
313 plog(XLOG_ERROR
, "get_nfs_version: failed to contact portmapper on host \"%s\": %s", host
, clnt_sperrno(clnt_stat
));
319 #endif /* HAVE_FS_NFS3 */
322 if (STREQ(proto
, "tcp"))
323 clnt
= clnttcp_create(sin
, NFS_PROGRAM
, nfs_version
, &sock
, 0, 0);
324 else if (STREQ(proto
, "udp"))
325 clnt
= clntudp_create(sin
, NFS_PROGRAM
, nfs_version
, tv
, &sock
);
330 #ifdef HAVE_CLNT_SPCREATEERROR
331 plog(XLOG_INFO
, "get_nfs_version NFS(%d,%s) failed for %s :%s",
332 (int) nfs_version
, proto
, host
, clnt_spcreateerror(""));
333 #else /* not HAVE_CLNT_SPCREATEERROR */
334 plog(XLOG_INFO
, "get_nfs_version NFS(%d,%s) failed for %s",
335 (int) nfs_version
, proto
, host
);
336 #endif /* not HAVE_CLNT_SPCREATEERROR */
340 /* Try a couple times to verify the CLIENT handle. */
342 clnt_stat
= clnt_call(clnt
,
344 (XDRPROC_T_TYPE
) xdr_void
,
346 (XDRPROC_T_TYPE
) xdr_void
,
351 if (clnt_stat
!= RPC_SUCCESS
) {
354 if (nfs_version
== NFS_VERSION3
) {
355 plog(XLOG_INFO
, "get_nfs_version trying a lower version");
356 nfs_version
= NFS_VERSION
;
360 #endif /* HAVE_FS_NFS3 */
362 plog(XLOG_INFO
, "get_nfs_version NFS(%d,%s) failed for %s",
363 (int) nfs_version
, proto
, host
);
367 plog(XLOG_INFO
, "get_nfs_version: returning (%d,%s) on host %s",
368 (int) nfs_version
, proto
, host
);
374 * AUTOFS FUNCTIONS FOR SOCKETS:
376 #ifdef HAVE_FS_AUTOFS
378 * Create the nfs service for amd
381 create_autofs_service(int *soAUTOFSp
, u_short
*autofs_portp
, SVCXPRT
**autofs_xprtp
, void (*dispatch_fxn
)(struct svc_req
*rqstp
, SVCXPRT
*transp
))
383 /* NOT IMPLEMENTED! */
386 #endif /* HAVE_FS_AUTOFS */