Blame modules/parse_hesiod.c

Packit 8480eb
/*
Packit 8480eb
 * parse_hesiod.c
Packit 8480eb
 *
Packit 8480eb
 * Module for Linux automountd to parse a hesiod filesystem entry.
Packit 8480eb
 */
Packit 8480eb
Packit 8480eb
#include <sys/types.h>
Packit 8480eb
#include <ctype.h>
Packit 8480eb
#include <string.h>
Packit 8480eb
#include <stdlib.h>
Packit 8480eb
#include <netinet/in.h>
Packit 8480eb
#include <arpa/nameser.h>
Packit 8480eb
#include <resolv.h>
Packit 8480eb
Packit 8480eb
#define MODULE_PARSE
Packit 8480eb
#include "automount.h"
Packit 8480eb
Packit 8480eb
#define MODPREFIX "parse(hesiod): "
Packit 8480eb
Packit 8480eb
int parse_version = AUTOFS_PARSE_VERSION;	/* Required by protocol */
Packit 8480eb
Packit 8480eb
#define HESIOD_LEN 512
Packit 8480eb
Packit 8480eb
/* Break out the fields in an AFS record of the form:
Packit 8480eb
   "AFS /afs/athena/mit/tytso w /mit/tytso-afs" */
Packit 8480eb
static int parse_afs(struct autofs_point *ap,
Packit 8480eb
		     const char *filsysline, const char *name, int name_len,
Packit 8480eb
		     char *source, int source_len, char *options, int options_len)
Packit 8480eb
{
Packit 8480eb
	const char *p;
Packit 8480eb
	int i;
Packit 8480eb
Packit 8480eb
	p = filsysline;
Packit 8480eb
Packit 8480eb
	/* Skip whitespace. */
Packit 8480eb
	while (isspace(*p))
Packit 8480eb
		p++;
Packit 8480eb
Packit 8480eb
	/* Skip the filesystem type. */
Packit 8480eb
	while (!isspace(*p))
Packit 8480eb
		p++;
Packit 8480eb
Packit 8480eb
	/* Skip whitespace. */
Packit 8480eb
	while (isspace(*p))
Packit 8480eb
		p++;
Packit 8480eb
Packit 8480eb
	/* Isolate the source for this AFS fs. */
Packit 8480eb
	for (i = 0; (!isspace(p[i]) && i < source_len); i++) {
Packit 8480eb
		if (!p[i]) {
Packit 8480eb
			error(ap->logopt, MODPREFIX
Packit 8480eb
			      "unexpeced end of input looking for AFS "
Packit 8480eb
			      "source: %s", p);
Packit 8480eb
			return 1;
Packit 8480eb
		}
Packit 8480eb
		source[i] = p[i];
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	source[i] = 0;
Packit 8480eb
	p += i;
Packit 8480eb
Packit 8480eb
	/* Skip whitespace. */
Packit 8480eb
	while ((*p) && (isspace(*p)))
Packit 8480eb
		p++;
Packit 8480eb
Packit 8480eb
	/* Isolate the options for this AFS fs. */
Packit 8480eb
	for (i = 0; (!isspace(p[i]) && i < options_len); i++) {
Packit 8480eb
		if (!p[i]) {
Packit 8480eb
			error(ap->logopt, MODPREFIX
Packit 8480eb
			      "unexpeced end of input looking for AFS "
Packit 8480eb
			      "options: %s", p);
Packit 8480eb
			return 1;
Packit 8480eb
		}
Packit 8480eb
		options[i] = p[i];
Packit 8480eb
	}
Packit 8480eb
	options[i] = 0;
Packit 8480eb
Packit 8480eb
	/* Hack for "r" or "w" options. */
Packit 8480eb
	if (!strcmp(options, "r"))
Packit 8480eb
		strcpy(options, "ro");
Packit 8480eb
Packit 8480eb
	if (!strcmp(options, "w"))
Packit 8480eb
		strcpy(options, "rw");
Packit 8480eb
Packit 8480eb
	debug(ap->logopt,
Packit 8480eb
	      MODPREFIX
Packit 8480eb
	      "parsing AFS record gives '%s'->'%s' with options" " '%s'",
Packit 8480eb
	      name, source, options);
Packit 8480eb
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
/*
Packit 8480eb
 * Break out the fields in an NFS record of the form:
Packit 8480eb
 * "NFS /export/src nelson.tx.ncsu.edu w /ncsu/tx-src"
Packit 8480eb
 */
Packit 8480eb
static int parse_nfs(struct autofs_point *ap,
Packit 8480eb
		     const char *filsysline, const char *name,
Packit 8480eb
		     int name_len, char *source, int source_len,
Packit 8480eb
		     char *options, int options_len)
Packit 8480eb
{
Packit 8480eb
	const char *p;
Packit 8480eb
	char mount[HESIOD_LEN + 1];
Packit 8480eb
	int i;
Packit 8480eb
Packit 8480eb
	p = filsysline;
Packit 8480eb
Packit 8480eb
	/* Skip whitespace. */
Packit 8480eb
	while (isspace(*p))
Packit 8480eb
		p++;
Packit 8480eb
Packit 8480eb
	/* Skip the filesystem type. */
Packit 8480eb
	while (!isspace(*p))
Packit 8480eb
		p++;
Packit 8480eb
Packit 8480eb
	/* Skip whitespace. */
Packit 8480eb
	while (isspace(*p))
Packit 8480eb
		p++;
Packit 8480eb
Packit 8480eb
	/* Isolate the remote mountpoint for this NFS fs. */
Packit 8480eb
	for (i = 0; (!isspace(p[i]) && i < ((int) sizeof(mount) - 1)); i++) {
Packit 8480eb
		if (!p[i]) {
Packit 8480eb
			error(ap->logopt, MODPREFIX
Packit 8480eb
			      "unexpeced end of input looking for NFS "
Packit 8480eb
			      "mountpoint: %s", p);
Packit 8480eb
			return 1;
Packit 8480eb
		}
Packit 8480eb
		mount[i] = p[i];
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	mount[i] = 0;
Packit 8480eb
	p += i;
Packit 8480eb
Packit 8480eb
	/* Skip whitespace. */
Packit 8480eb
	while ((*p) && (isspace(*p)))
Packit 8480eb
		p++;
Packit 8480eb
Packit 8480eb
	/* Isolate the remote host. */
Packit 8480eb
	for (i = 0; (!isspace(p[i]) && i < source_len); i++) {
Packit 8480eb
		if (!p[i]) {
Packit 8480eb
			error(ap->logopt, MODPREFIX
Packit 8480eb
			      "unexpeced end of input looking for NFS "
Packit 8480eb
			      "host: %s", p);
Packit 8480eb
			return 1;
Packit 8480eb
		}
Packit 8480eb
		source[i] = p[i];
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	source[i] = 0;
Packit 8480eb
	p += i;
Packit 8480eb
Packit 8480eb
	if (strlen(source) + strlen(mount) + 2 > source_len) {
Packit 8480eb
		error(ap->logopt, MODPREFIX "entry too log for mount source");
Packit 8480eb
		return 1;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/* Append ":mountpoint" to the source to get "host:mountpoint". */
Packit 8480eb
	strcat(source, ":");
Packit 8480eb
	strcat(source, mount);
Packit 8480eb
Packit 8480eb
	/* Skip whitespace. */
Packit 8480eb
	while ((*p) && (isspace(*p)))
Packit 8480eb
		p++;
Packit 8480eb
Packit 8480eb
	/* Isolate the mount options. */
Packit 8480eb
	for (i = 0; (!isspace(p[i]) && i < options_len); i++) {
Packit 8480eb
		if (!p[i]) {
Packit 8480eb
			error(ap->logopt, MODPREFIX
Packit 8480eb
			      "unexpeced end of input looking for NFS "
Packit 8480eb
			      "mount options: %s", p);
Packit 8480eb
			return 1;
Packit 8480eb
		}
Packit 8480eb
		options[i] = p[i];
Packit 8480eb
	}
Packit 8480eb
	options[i] = 0;
Packit 8480eb
Packit 8480eb
	/* Hack for "r" or "w" options. */
Packit 8480eb
	if (!strcmp(options, "r"))
Packit 8480eb
		strcpy(options, "ro");
Packit 8480eb
Packit 8480eb
	if (!strcmp(options, "w"))
Packit 8480eb
		strcpy(options, "rw");
Packit 8480eb
Packit 8480eb
	debug(ap->logopt,
Packit 8480eb
	      MODPREFIX
Packit 8480eb
	      "parsing NFS record gives '%s'->'%s' with options" "'%s'",
Packit 8480eb
	      name, source, options);
Packit 8480eb
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
/* Break out the fields in a generic record of the form:
Packit 8480eb
   "UFS /dev/ra0g w /site" */
Packit 8480eb
static int parse_generic(struct autofs_point *ap,
Packit 8480eb
			 const char *filsysline, const char *name, int name_len,
Packit 8480eb
			 char *source, int source_len, char *options, int options_len)
Packit 8480eb
{
Packit 8480eb
	const char *p;
Packit 8480eb
	int i;
Packit 8480eb
Packit 8480eb
	p = filsysline;
Packit 8480eb
Packit 8480eb
	/* Skip whitespace. */
Packit 8480eb
	while (isspace(*p))
Packit 8480eb
		p++;
Packit 8480eb
Packit 8480eb
	/* Skip the filesystem type. */
Packit 8480eb
	while (!isspace(*p))
Packit 8480eb
		p++;
Packit 8480eb
Packit 8480eb
	/* Skip whitespace. */
Packit 8480eb
	while (isspace(*p))
Packit 8480eb
		p++;
Packit 8480eb
Packit 8480eb
	/* Isolate the source for this fs. */
Packit 8480eb
	for (i = 0; (!isspace(p[i]) && i < source_len); i++) {
Packit 8480eb
		if (!p[i]) {
Packit 8480eb
			error(ap->logopt, MODPREFIX
Packit 8480eb
			      "unexpeced end of input looking for generic "
Packit 8480eb
			      "mount source: %s", p);
Packit 8480eb
			return 1;
Packit 8480eb
		}
Packit 8480eb
		source[i] = p[i];
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	source[i] = 0;
Packit 8480eb
	p += i;
Packit 8480eb
Packit 8480eb
	/* Skip whitespace. */
Packit 8480eb
	while ((*p) && (isspace(*p)))
Packit 8480eb
		p++;
Packit 8480eb
Packit 8480eb
	/* Isolate the mount options. */
Packit 8480eb
	for (i = 0; (!isspace(p[i]) && i < options_len); i++) {
Packit 8480eb
		if (!p[i]) {
Packit 8480eb
			error(ap->logopt, MODPREFIX
Packit 8480eb
			      "unexpeced end of input looking for generic "
Packit 8480eb
			      "mount options: %s", p);
Packit 8480eb
			return 1;
Packit 8480eb
		}
Packit 8480eb
		options[i] = p[i];
Packit 8480eb
	}
Packit 8480eb
	options[i] = 0;
Packit 8480eb
Packit 8480eb
	/* Hack for "r" or "w" options. */
Packit 8480eb
	if (!strcmp(options, "r"))
Packit 8480eb
		strcpy(options, "ro");
Packit 8480eb
Packit 8480eb
	if (!strcmp(options, "w"))
Packit 8480eb
		strcpy(options, "rw");
Packit 8480eb
Packit 8480eb
	debug(ap->logopt,
Packit 8480eb
	      MODPREFIX
Packit 8480eb
	      "parsing generic record gives '%s'->'%s' with options '%s'",
Packit 8480eb
	      name, source, options);
Packit 8480eb
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int parse_init(int argc, const char *const *argv, void **context)
Packit 8480eb
{
Packit 8480eb
	*context = NULL;
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int parse_reinit(int argc, const char *const *argv, void **context)
Packit 8480eb
{
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int parse_done(void *context)
Packit 8480eb
{
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int parse_mount(struct autofs_point *ap, const char *name,
Packit 8480eb
		int name_len, const char *mapent, void *context)
Packit 8480eb
{
Packit 8480eb
	char source[HESIOD_LEN + 1];
Packit 8480eb
	char fstype[HESIOD_LEN + 1];
Packit 8480eb
	char options[HESIOD_LEN + 1];
Packit 8480eb
	char *q;
Packit 8480eb
	const char *p;
Packit 8480eb
	int ret;
Packit 8480eb
Packit 8480eb
	ap->entry->current = NULL;
Packit 8480eb
	master_source_current_signal(ap->entry);
Packit 8480eb
Packit 8480eb
	p = mapent;
Packit 8480eb
	q = fstype;
Packit 8480eb
Packit 8480eb
	/* Skip any initial whitespace... */
Packit 8480eb
	while (isspace(*p))
Packit 8480eb
		p++;
Packit 8480eb
Packit 8480eb
	/* Isolate the filesystem type... */
Packit 8480eb
	while (!isspace(*p)) {
Packit 8480eb
		*q++ = tolower(*p++);
Packit 8480eb
	}
Packit 8480eb
	*q = 0;
Packit 8480eb
Packit 8480eb
	/* If it's an error message... */
Packit 8480eb
	if (!strcasecmp(fstype, "err")) {
Packit 8480eb
		error(ap->logopt, MODPREFIX "%s", mapent);
Packit 8480eb
		return 1;
Packit 8480eb
	/* If it's an AFS fs... */
Packit 8480eb
	} else if (!strcasecmp(fstype, "afs"))
Packit 8480eb
		ret = parse_afs(ap, mapent, name, name_len,
Packit 8480eb
				source, sizeof(source), options,
Packit 8480eb
				sizeof(options));
Packit 8480eb
	/* If it's NFS... */
Packit 8480eb
	else if (!strcasecmp(fstype, "nfs"))
Packit 8480eb
		ret = parse_nfs(ap, mapent, name, name_len,
Packit 8480eb
				source, sizeof(source), options,
Packit 8480eb
				sizeof(options));
Packit 8480eb
	/* Punt. */
Packit 8480eb
	else
Packit 8480eb
		ret = parse_generic(ap, mapent, name, name_len,
Packit 8480eb
				    source, sizeof(source), options,
Packit 8480eb
				    sizeof(options));
Packit 8480eb
Packit 8480eb
	if (ret) {
Packit 8480eb
		error(ap->logopt, MODPREFIX "failed to parse entry");
Packit 8480eb
		return 1;
Packit 8480eb
	} else {
Packit 8480eb
		debug(ap->logopt,
Packit 8480eb
		      MODPREFIX "mount %s is type %s from %s",
Packit 8480eb
		      name, fstype, source);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return do_mount(ap, ap->path, name, name_len, source, fstype, options);
Packit 8480eb
}