summaryrefslogtreecommitdiffstats
path: root/sbin/mount_nfs
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2001-05-13 00:07:03 +0000
committeriedowse <iedowse@FreeBSD.org>2001-05-13 00:07:03 +0000
commit0ed7ba54b3471331d3d3726dc8089f9fb2658d87 (patch)
tree9085bc6a50d6fb1878aaf41061be21aac2c461db /sbin/mount_nfs
parentf4c99b3d8ebdf658215a72230dd543f62e5f5d5f (diff)
downloadFreeBSD-src-0ed7ba54b3471331d3d3726dc8089f9fb2658d87.zip
FreeBSD-src-0ed7ba54b3471331d3d3726dc8089f9fb2658d87.tar.gz
- Split out the {family,socktype}->netid conversion into a separate
function; we now handle unknown protocols more gracefully. - Cache the return from getnetconfigent() so that we don't have to remember to call freenetconfigent() each time. This fixes a memory leak that would cause retrying background mount_nfs processes to slowly increase their memory usage.
Diffstat (limited to 'sbin/mount_nfs')
-rw-r--r--sbin/mount_nfs/mount_nfs.c90
1 files changed, 79 insertions, 11 deletions
diff --git a/sbin/mount_nfs/mount_nfs.c b/sbin/mount_nfs/mount_nfs.c
index a026c71..1be9944 100644
--- a/sbin/mount_nfs/mount_nfs.c
+++ b/sbin/mount_nfs/mount_nfs.c
@@ -158,6 +158,19 @@ struct nfs_args nfsdefargs = {
NFS_MAXDIRATTRTIMO,
};
+/* Table for af,sotype -> netid conversions. */
+struct nc_protos {
+ char *netid;
+ int af;
+ int sotype;
+} nc_protos[] = {
+ {"udp", AF_INET, SOCK_DGRAM},
+ {"tcp", AF_INET, SOCK_STREAM},
+ {"udp6", AF_INET6, SOCK_DGRAM},
+ {"tcp6", AF_INET6, SOCK_STREAM},
+ {NULL}
+};
+
struct nfhret {
u_long stat;
long vers;
@@ -204,6 +217,8 @@ enum tryret {
int getnfsargs __P((char *, struct nfs_args *));
/* void set_rpc_maxgrouplist __P((int)); */
+struct netconfig *getnetconf_cached(const char *netid);
+char *netidbytype(int af, int sotype);
void usage __P((void)) __dead2;
int xdr_dir __P((XDR *, char *));
int xdr_fh __P((XDR *, struct nfhret *));
@@ -757,15 +772,13 @@ nfs_tryproto(struct nfs_args *nfsargsp, struct addrinfo *ai, char *hostp,
errbuf[0] = '\0';
*errstr = errbuf;
- /*
- * XXX. Nead a generic (family, type, proto) -> nconf interface.
- * __rpc_*2nconf exist, maybe they should be exported.
- */
- if (nfsargsp->sotype == SOCK_STREAM)
- netid = (ai->ai_family == AF_INET6) ? "tcp6" : "tcp";
- else
- netid = (ai->ai_family == AF_INET6) ? "udp6" : "udp";
- if ((nconf = getnetconfigent(netid)) == NULL) {
+ if ((netid = netidbytype(ai->ai_family, nfsargsp->sotype)) == NULL) {
+ snprintf(errbuf, sizeof errbuf,
+ "af %d sotype %d not supported", ai->ai_family,
+ nfsargsp->sotype);
+ return (TRYRET_LOCALERR);
+ }
+ if ((nconf = getnetconf_cached(netid)) == NULL) {
snprintf(errbuf, sizeof errbuf, "%s: %s", netid, nc_sperror());
return (TRYRET_LOCALERR);
}
@@ -774,8 +787,14 @@ nfs_tryproto(struct nfs_args *nfsargsp, struct addrinfo *ai, char *hostp,
netid_mnt = netid;
nconf_mnt = nconf;
} else {
- netid_mnt = (ai->ai_family == AF_INET6) ? "udp6" : "udp";
- if ((nconf_mnt = getnetconfigent(netid_mnt)) == NULL) {
+ if ((netid_mnt = netidbytype(ai->ai_family, SOCK_DGRAM))
+ == NULL) {
+ snprintf(errbuf, sizeof errbuf,
+ "af %d sotype SOCK_DGRAM not supported",
+ ai->ai_family);
+ return (TRYRET_LOCALERR);
+ }
+ if ((nconf_mnt = getnetconf_cached(netid_mnt)) == NULL) {
snprintf(errbuf, sizeof errbuf, "%s: %s", netid_mnt,
nc_sperror());
return (TRYRET_LOCALERR);
@@ -934,6 +953,55 @@ returncode(enum clnt_stat stat, struct rpc_err *rpcerr)
}
/*
+ * Look up a netid based on an address family and socket type.
+ * `af' is the address family, and `sotype' is SOCK_DGRAM or SOCK_STREAM.
+ *
+ * XXX there should be a library function for this.
+ */
+char *
+netidbytype(int af, int sotype) {
+ struct nc_protos *p;
+
+ for (p = nc_protos; p->netid != NULL; p++) {
+ if (af != p->af || sotype != p->sotype)
+ continue;
+ return (p->netid);
+ }
+ return (NULL);
+}
+
+/*
+ * Look up a netconfig entry based on a netid, and cache the result so
+ * that we don't need to remember to call freenetconfigent().
+ *
+ * Otherwise it behaves just like getnetconfigent(), so nc_*error()
+ * work on failure.
+ */
+struct netconfig *
+getnetconf_cached(const char *netid) {
+ static struct nc_entry {
+ struct netconfig *nconf;
+ struct nc_entry *next;
+ } *head;
+ struct nc_entry *p;
+ struct netconfig *nconf;
+
+ for (p = head; p != NULL; p = p->next)
+ if (strcmp(netid, p->nconf->nc_netid) == 0)
+ return (p->nconf);
+
+ if ((nconf = getnetconfigent(netid)) == NULL)
+ return (NULL);
+ if ((p = malloc(sizeof(*p))) == NULL)
+ err(1, "malloc");
+ p->nconf = nconf;
+ p->next = head;
+ head = p;
+
+ return (p->nconf);
+}
+
+/*
* xdr routines for mount rpc's
*/
int
OpenPOWER on IntegriCloud