2
* Copyright 2009 Oracle. All rights reserved.
4
* This file is part of nfs-utils.
6
* nfs-utils is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* nfs-utils is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with nfs-utils. If not, see <http://www.gnu.org/licenses/>.
32
#include <netinet/in.h>
34
#include <sys/socket.h>
35
#include <sys/resource.h>
40
#ifdef HAVE_TCP_WRAPPER
41
#include "tcpwrapper.h"
50
* Set up an appropriate bind address, given @port and @nconf.
52
* Returns getaddrinfo(3) results if successful. Caller must
53
* invoke freeaddrinfo(3) on these results.
55
* Otherwise NULL is returned if an error occurs.
58
static struct addrinfo *
59
svc_create_bindaddr(struct netconfig *nconf, const uint16_t port)
61
struct addrinfo *ai = NULL;
62
struct addrinfo hint = {
63
.ai_flags = AI_PASSIVE | AI_NUMERICSERV,
68
if (strcmp(nconf->nc_protofmly, NC_INET) == 0)
69
hint.ai_family = AF_INET;
71
else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0)
72
hint.ai_family = AF_INET6;
73
#endif /* IPV6_SUPPORTED */
75
xlog(D_GENERAL, "Unrecognized bind address family: %s",
80
if (strcmp(nconf->nc_proto, NC_UDP) == 0)
81
hint.ai_protocol = (int)IPPROTO_UDP;
82
else if (strcmp(nconf->nc_proto, NC_TCP) == 0)
83
hint.ai_protocol = (int)IPPROTO_TCP;
85
xlog(D_GENERAL, "Unrecognized bind address protocol: %s",
90
(void)snprintf(buf, sizeof(buf), "%u", port);
91
error = getaddrinfo(NULL, buf, &hint, &ai);
93
xlog(L_ERROR, "Failed to construct bind address: %s",
102
svc_create_nconf(const char *name, const rpcprog_t program,
103
const rpcvers_t version,
104
void (*dispatch)(struct svc_req *, SVCXPRT *),
105
const uint16_t port, struct netconfig *nconf)
107
struct t_bind bindaddr;
111
ai = svc_create_bindaddr(nconf, port);
115
bindaddr.addr.buf = ai->ai_addr;
116
bindaddr.qlen = SOMAXCONN;
118
xprt = svc_tli_create(RPC_ANYFD, nconf, &bindaddr, 0, 0);
121
xlog(D_GENERAL, "Failed to create listener xprt "
122
"(%s, %u, %s)", name, version, nconf->nc_netid);
126
if (!svc_reg(xprt, program, version, dispatch, nconf)) {
127
/* svc_reg(3) destroys @xprt in this case */
128
xlog(D_GENERAL, "Failed to register (%s, %u, %s)",
129
name, version, nconf->nc_netid);
137
* nfs_svc_create - start up RPC svc listeners
138
* @name: C string containing name of new service
139
* @program: RPC program number to register
140
* @version: RPC version number to register
141
* @dispatch: address of function that handles incoming RPC requests
142
* @port: if not zero, transport listens on this port
144
* Sets up network transports for receiving RPC requests, and starts
145
* the RPC dispatcher. Returns the number of started network transports.
148
nfs_svc_create(__attribute__((unused)) char *name,
149
const rpcprog_t program, const rpcvers_t version,
150
void (*dispatch)(struct svc_req *, SVCXPRT *),
153
const struct sigaction create_sigaction = {
154
.sa_handler = SIG_IGN,
156
unsigned int visible, up;
157
struct netconfig *nconf;
161
* Ignore SIGPIPE to avoid exiting sideways when peers
162
* close their TCP connection while we're trying to reply
165
(void)sigaction(SIGPIPE, &create_sigaction, NULL);
167
handlep = setnetconfig();
168
if (handlep == NULL) {
169
xlog(L_ERROR, "Failed to access local netconfig database: %s",
176
while ((nconf = getnetconfig(handlep)) != NULL) {
177
if (!(nconf->nc_flag & NC_VISIBLE))
180
up += svc_create_nconf(name, program, version, dispatch,
185
xlog(L_ERROR, "Failed to find any visible netconfig entries");
187
if (endnetconfig(handlep) == -1)
188
xlog(L_ERROR, "Failed to close local netconfig database: %s",
195
* nfs_svc_unregister - remove service registrations from local rpcbind database
196
* @program: RPC program number to unregister
197
* @version: RPC version number to unregister
199
* Removes all registrations for [ @program, @version ] .
202
nfs_svc_unregister(const rpcprog_t program, const rpcvers_t version)
204
if (rpcb_unset(program, version, NULL) == FALSE)
205
xlog(D_GENERAL, "Failed to unregister program %lu, version %lu",
206
(unsigned long)program, (unsigned long)version);
209
#else /* !HAVE_LIBTIRPC */
212
* nfs_svc_create - start up RPC svc listeners
213
* @name: C string containing name of new service
214
* @program: RPC program number to register
215
* @version: RPC version number to register
216
* @dispatch: address of function that handles incoming RPC requests
217
* @port: if not zero, transport listens on this port
219
* Sets up network transports for receiving RPC requests, and starts
220
* the RPC dispatcher. Returns the number of started network transports.
223
nfs_svc_create(char *name, const rpcprog_t program, const rpcvers_t version,
224
void (*dispatch)(struct svc_req *, SVCXPRT *),
227
rpc_init(name, (int)program, (int)version, dispatch, (int)port);
232
* nfs_svc_unregister - remove service registrations from local rpcbind database
233
* @program: RPC program number to unregister
234
* @version: RPC version number to unregister
236
* Removes all registrations for [ @program, @version ] .
239
nfs_svc_unregister(const rpcprog_t program, const rpcvers_t version)
241
if (pmap_unset((unsigned long)program, (unsigned long)version) == FALSE)
242
xlog(D_GENERAL, "Failed to unregister program %lu, version %lu",
243
(unsigned long)program, (unsigned long)version);
246
#endif /* !HAVE_LIBTIRPC */