1/*	$NetBSD: am_glue.c,v 1.3 2010/02/26 22:44:17 christos Exp $	*/
2
3/*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30#ifndef lint
31__RCSID("$NetBSD: am_glue.c,v 1.3 2010/02/26 22:44:17 christos Exp $");
32#endif /* not lint */
33
34#ifdef HAVE_CONFIG_H
35# include <config.h>
36#endif /* HAVE_CONFIG_H */
37#include <am_defs.h>
38#include <amu.h>
39#include <rpc/pmap_prot.h>
40#include <rpc/pmap_clnt.h>
41
42#include <stdbool.h>
43
44#include "am_glue.h"
45
46static CLIENT *clnt;
47
48static struct timeval tv = { 5, 0 };
49/*
50 * Appease lint: Properly typecast some numbers defined in
51 * src/extern/bsd/am-utils/dist/include/amq_defs.h.
52 */
53#define	xAMQ_PROGRAM		(rpcprog_t)AMQ_PROGRAM
54#define xAMQ_VERSION		(rpcvers_t)AMQ_VERSION
55#define xAMQPROC_SYNC_UMNT	(rpcproc_t)AMQPROC_SYNC_UMNT
56
57static int
58ping_pmap(void)
59{
60	u_short port = 0;
61	CLIENT *cl;
62	struct pmap parms;
63	struct sockaddr_in si;
64	int s = -1, rv;
65	static struct timeval pingtv = { 1, 0 };
66
67	(void)memset(&si, 0, sizeof(si));
68	si.sin_family = AF_INET;
69	si.sin_len = sizeof(si);
70	si.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
71	si.sin_port = htons(PMAPPORT);
72
73	if ((cl = clntudp_bufcreate(&si, PMAPPROG, PMAPVERS, pingtv,
74	    &s, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE)) == NULL)
75		return -1;
76
77	parms.pm_prog = PMAPPROG;
78	parms.pm_vers = PMAPVERS;
79	parms.pm_prot = IPPROTO_UDP;
80	parms.pm_port = 0;  /* not needed or used */
81
82	rv = CLNT_CALL(cl, (rpcproc_t)PMAPPROC_GETPORT,
83	    (xdrproc_t)xdr_pmap, &parms,
84	    (xdrproc_t)xdr_u_short, &port, pingtv) == RPC_SUCCESS ? 0 : -1;
85
86	CLNT_DESTROY(cl);
87	return rv;
88}
89
90static void
91am_init(void)
92{
93	static const char *server = "localhost";
94	static bool called;
95
96	if (called)
97		return;
98	called = true;
99
100	if (ping_pmap() == -1)
101		return;
102	/*
103	 * Create RPC endpoint
104	 */
105	/* try tcp first */
106	clnt = clnt_create(server, xAMQ_PROGRAM, xAMQ_VERSION, "tcp");
107	if (clnt != NULL)
108		return;
109
110	/* try udp next */
111	clnt = clnt_create(server, xAMQ_PROGRAM, xAMQ_VERSION, "udp");
112	if (clnt != NULL)	/* set udp timeout */
113		(void)clnt_control(clnt, CLSET_RETRY_TIMEOUT, (void *)&tv);
114}
115
116int
117am_unmount(const char *dirname)
118{
119	static struct timeval timeout = { ALLOWED_MOUNT_TIME, 0 };
120	amq_sync_umnt result;
121
122	am_init();
123
124	if (clnt == NULL)
125		return AMQ_UMNT_FAILED;
126
127	if (clnt_call(clnt, xAMQPROC_SYNC_UMNT, xdr_amq_string, &dirname,
128	    xdr_amq_sync_umnt, (void *)&result, timeout) != RPC_SUCCESS)
129		return AMQ_UMNT_SERVER;
130
131	return result.au_etype;
132}
133