2 * support/export/export.c
4 * Maintain list of exported file systems.
6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
14 #include <sys/types.h>
15 #include <sys/param.h>
16 #include <netinet/in.h>
22 exp_hash_table exportlist[MCL_MAXTYPES] = {{NULL, {{NULL,NULL}, }}, };
23 static int export_hash(char *);
25 static void export_init(nfs_export *exp, nfs_client *clp,
26 struct exportent *nep);
27 static void export_add(nfs_export *exp);
28 static int export_check(const nfs_export *exp, const struct addrinfo *ai,
31 export_allowed_internal(const struct addrinfo *ai,
35 export_free(nfs_export *exp)
37 xfree(exp->m_export.e_squids);
38 xfree(exp->m_export.e_sqgids);
39 free(exp->m_export.e_mountpoint);
40 free(exp->m_export.e_fslocdata);
41 free(exp->m_export.e_uuid);
43 xfree(exp->m_export.e_hostname);
47 static void warn_duplicated_exports(nfs_export *exp, struct exportent *eep)
49 if (exp->m_export.e_flags != eep->e_flags) {
50 xlog(L_ERROR, "incompatible duplicated export entries:");
51 xlog(L_ERROR, "\t%s:%s (0x%x) [IGNORED]", eep->e_hostname,
52 eep->e_path, eep->e_flags);
53 xlog(L_ERROR, "\t%s:%s (0x%x)", exp->m_export.e_hostname,
54 exp->m_export.e_path, exp->m_export.e_flags);
56 xlog(L_ERROR, "duplicated export entries:");
57 xlog(L_ERROR, "\t%s:%s", eep->e_hostname, eep->e_path);
58 xlog(L_ERROR, "\t%s:%s", exp->m_export.e_hostname,
59 exp->m_export.e_path);
64 * export_read - read entries from /etc/exports
65 * @fname: name of file to read from
69 export_read(char *fname)
71 struct exportent *eep;
74 setexportent(fname, "r");
75 while ((eep = getexportent(0,1)) != NULL) {
76 exp = export_lookup(eep->e_hostname, eep->e_path, 0);
78 export_create(eep, 0);
80 warn_duplicated_exports(exp, eep);
86 * export_create - create an in-core nfs_export record from an export entry
87 * @xep: export entry to lookup
88 * @canonical: if set, e_hostname is known to be canonical DNS name
90 * Returns a freshly instantiated export record, or NULL if
94 export_create(struct exportent *xep, int canonical)
99 if (!(clp = client_lookup(xep->e_hostname, canonical))) {
100 /* bad export entry; complaint already logged */
103 exp = (nfs_export *) xmalloc(sizeof(*exp));
104 export_init(exp, clp, xep);
111 export_init(nfs_export *exp, nfs_client *clp, struct exportent *nep)
113 struct exportent *e = &exp->m_export;
115 dupexportent(e, nep);
117 e->e_hostname = xstrdup(nep->e_hostname);
121 exp->m_mayexport = 0;
129 * Duplicate exports data. The in-core export struct retains the
130 * original hostname from /etc/exports, while the in-core client struct
131 * gets the newly found FQDN.
134 export_dup(nfs_export *exp, const struct addrinfo *ai)
139 new = (nfs_export *) xmalloc(sizeof(*new));
140 memcpy(new, exp, sizeof(*new));
141 dupexportent(&new->m_export, &exp->m_export);
142 if (exp->m_export.e_hostname)
143 new->m_export.e_hostname = xstrdup(exp->m_export.e_hostname);
144 clp = client_dup(exp->m_client, ai);
151 new->m_mayexport = exp->m_mayexport;
162 export_add(nfs_export *exp)
164 exp_hash_table *p_tbl;
165 exp_hash_entry *p_hen;
168 int type = exp->m_client->m_type;
171 pos = export_hash(exp->m_export.e_path);
172 p_tbl = &(exportlist[type]); /* pointer to hash table */
173 p_hen = &(p_tbl->entries[pos]); /* pointer to hash table entry */
175 if (!(p_hen->p_first)) { /* hash table entry is empty */
176 p_hen->p_first = exp;
179 exp->m_next = p_tbl->p_head;
181 } else { /* hash table entry is NOT empty */
182 p_next = p_hen->p_last->m_next;
183 p_hen->p_last->m_next = exp;
184 exp->m_next = p_next;
190 * export_find - find or create a suitable nfs_export for @ai and @path
191 * @ai: pointer to addrinfo for client
192 * @path: '\0'-terminated ASCII string containing export path
194 * Returns a pointer to nfs_export data matching @ai and @path,
195 * or NULL if an error occurs.
198 export_find(const struct addrinfo *ai, const char *path)
203 for (i = 0; i < MCL_MAXTYPES; i++) {
204 for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
205 if (!export_check(exp, ai, path))
207 if (exp->m_client->m_type == MCL_FQDN)
209 return export_dup(exp, ai);
217 export_allowed_internal(const struct addrinfo *ai, const char *path)
222 for (i = 0; i < MCL_MAXTYPES; i++) {
223 for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
224 if (!exp->m_mayexport ||
225 !export_check(exp, ai, path))
235 * export_allowed - determine if this export is allowed
236 * @ai: pointer to addrinfo for client
237 * @path: '\0'-terminated ASCII string containing export path
239 * Returns a pointer to nfs_export data matching @ai and @path,
240 * or NULL if the export is not allowed.
243 export_allowed(const struct addrinfo *ai, const char *path)
246 char epath[MAXPATHLEN+1];
249 if (path [0] != '/') return NULL;
251 strncpy(epath, path, sizeof (epath) - 1);
252 epath[sizeof (epath) - 1] = '\0';
254 /* Try the longest matching exported pathname. */
256 exp = export_allowed_internal(ai, epath);
259 /* We have to treat the root, "/", specially. */
260 if (p == &epath[1]) break;
261 p = strrchr(epath, '/');
270 * export_lookup - search hash table for export entry
271 * @hname: '\0'-terminated ASCII string containing client hostname to look for
272 * @path: '\0'-terminated ASCII string containing export path to look for
273 * @canonical: if set, @hname is known to be canonical DNS name
275 * Returns a pointer to nfs_export record matching @hname and @path,
276 * or NULL if the export was not found.
279 export_lookup(char *hname, char *path, int canonical)
283 exp_hash_entry *p_hen;
287 clp = client_lookup(hname, canonical);
291 pos = export_hash(path);
292 p_hen = &(exportlist[clp->m_type].entries[pos]);
293 for(exp = p_hen->p_first; exp && (exp != p_hen->p_last->m_next);
295 if (exp->m_client == clp && !strcmp(exp->m_export.e_path, path)) {
303 export_check(const nfs_export *exp, const struct addrinfo *ai, const char *path)
305 if (strcmp(path, exp->m_export.e_path))
308 return client_check(exp->m_client, ai);
312 * export_freeall - deallocate all nfs_export records
318 nfs_export *exp, *nxt;
321 for (i = 0; i < MCL_MAXTYPES; i++) {
322 for (exp = exportlist[i].p_head; exp; exp = nxt) {
324 client_release(exp->m_client);
327 for (j = 0; j < HASH_TABLE_SIZE; j++) {
328 exportlist[i].entries[j].p_first = NULL;
329 exportlist[i].entries[j].p_last = NULL;
331 exportlist[i].p_head = NULL;
337 * Compute and returns integer from string.
338 * Note: Its understood the smae integers can be same for
339 * different strings, but it should not matter.
347 while ( str[i] != '\0') {
358 export_hash(char *str)
360 int num = strtoint(str);
362 return num % HASH_TABLE_SIZE;