From d24a3f265ec4344b5502ec57df3cf8358f6f1499 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 5 Jan 2004 22:24:10 +0000 Subject: many changes git-svn-id: file:///home/lennart/svn/public/ivam2/trunk@14 dbf6933d-3bce-0310-9bcc-ed052ba35b35 --- src/msntab.c | 303 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 300 insertions(+), 3 deletions(-) (limited to 'src/msntab.c') diff --git a/src/msntab.c b/src/msntab.c index bcd3030..09709cc 100644 --- a/src/msntab.c +++ b/src/msntab.c @@ -1,12 +1,39 @@ #include #include +#include +#include +#include +#include +#include + +#include + #include "msntab.h" +#define MAX_ENTRIES 100 +#define MAX_INCLUDES 10 + +static struct tabentry *first = NULL; +static struct tabentry *last = NULL; +static int n_entries = 0; + +static int n_includes = 0; + struct tabentry* msntab_check_call(const char *callee, const char *caller) { - static char *args[] = { "/bin/cat", NULL }; - static struct tabentry ca = { CALL_ACTION_ACCEPT, 1, args }; + struct tabentry *l = first; - return msntab_ref(&ca); + while (l) { + assert(l->local && l->remote); + + if (!fnmatch(l->local, callee, 0) && !fnmatch(l->remote, caller, 0)) { + daemon_log(LOG_INFO, "MSN table entry from '%s:%u' matched.", l->filename, l->line); + return msntab_ref(l); + } + + l = l->next; + } + + return NULL; } @@ -19,5 +46,275 @@ struct tabentry* msntab_ref(struct tabentry *t) { void msntab_unref(struct tabentry *t) { assert(t && t->ref_counter >= 1); t->ref_counter--; + + if (t->ref_counter == 0) { + + if (t->args) { + char **a = t->args; + while (*a) { + free(*a); + a++; + } + free(t->args); + } + + free(t->local); + free(t->remote); + free(t->filename); + + free(t); + } +} + +void msntab_flush(void) { + while (first) { + struct tabentry *l = first; + first = first->next; + + if (first) + first->prev = NULL; + + if (last == l) + last = NULL; + + msntab_unref(l); + } + + n_entries = 0; + n_includes++; +} + +#define MAX_ARGS 16 + +static char** parse_args(const char *s) { + char *o, **a; + char *c = (char*) s; + int i = 0; + + a = malloc(sizeof(char *)*MAX_ARGS); + memset(a, 0, sizeof(char *)*MAX_ARGS); + + while ((o = strsep(&c, " \t"))) { + a[i++] = strdup(o); + + if (i >= MAX_ARGS-1) + break; + } + + return a; +} + + +static int parse_options(const char *s, struct tabentry *t) { + char *o; + char *c = (char*) s; + + assert(s && t); + + while ((o = strsep(&c, ","))) { + + if (!strcmp(o, "defaults")) + continue; + else if (!strcmp(o, "shbuf")) { + t->shbuf = 1; + continue; + } else if (!strncmp(o, "rings=", 6)) { + t->rings = atoi(o+6); + continue; + } + + daemon_log(LOG_INFO, "Unknown option '%s'", o); + return -1; + } + + return 0; } + +int msntab_load(const char *fn) { + int n; + struct tabentry *t = NULL; + FILE *f = NULL; + + daemon_log(LOG_INFO, "Loading MSN table '%s'.", fn); + if (!(f = fopen(fn, "r"))) { + daemon_log(LOG_ERR, "Failed to open MSN table '%s'.", fn); + goto fail; + } + + n = 0; + while (!feof(f)) { + char l[256], *c, *e, *local, *remote, *options, *action; + + n++; + + if (!fgets(l, sizeof(l), f)) + break; + + c = l+strspn(l, " \t"); + if ((e = strchr(c, '\r'))) + *e = 0; + if ((e = strchr(c, '\n'))) + *e = 0; + e = strchr(c, 0); + + if (*c == '#' || *c == 0) + continue; + + if (!(local = strsep(&c, " \t"))) { + daemon_log(LOG_ERR, "Parse failure on local MSN field in '%s:%i'.", fn, n); + goto fail; + } + + if (c) + c+=strspn(c, " \t"); + + if (!strcmp(local, "@include")) { + char *include; + + if (n_includes ++ >= MAX_INCLUDES) { + daemon_log(LOG_ERR, "Recursive include directive detected."); + goto fail; + } + + if (!(include = strsep(&c, ""))) { + daemon_log(LOG_ERR, "Parse failure on include field in '%s:%i'.", fn, n); + goto fail; + } + + if (msntab_load(include) < 0) + goto fail; + + continue; + } + + if (!(remote = strsep(&c, " \t"))) { + daemon_log(LOG_ERR, "Parse failure on remote MSN field in '%s:%i'.", fn, n); + goto fail; + } + + if (c) + c+=strspn(c, " \t"); + + if (!(options = strsep(&c, " \t"))) { + daemon_log(LOG_ERR, "Parse failure on options field in '%s:%i'.", fn, n); + goto fail; + } + + if (c) + c+=strspn(c, " \t"); + + if (!(action = strsep(&c, ""))) { + daemon_log(LOG_ERR, "Parse failure on action field in '%s:%i'.", fn, n); + goto fail; + } + + t = malloc(sizeof(struct tabentry)); + assert(t); + memset(t, 0, sizeof(struct tabentry)); + + t->line = n; + t->filename = strdup(fn); + + t->ref_counter = 1; + + t->local = strdup(local); + assert(t->local); + + t->remote = strdup(remote); + assert(t->remote); + + if (action[0] == '@') { + if (!strcmp(action, "@hangup")) + t->action = CALL_ACTION_HANGUP; + else if (!strcmp(action, "@ignore")) + t->action = CALL_ACTION_IGNORE; + else { + daemon_log(LOG_ERR, "Unknown action command '%s' in '%s:%i'.", action, fn, n); + goto fail; + } + } else { + t->action = CALL_ACTION_ACCEPT; + t->args = parse_args(action); + } + + if (parse_options(options, t) < 0) { + daemon_log(LOG_ERR, "Parse failure on options field in '%s:%i'.", fn, n); + goto fail; + } + + if (last) { + t->prev = last; + last->next = t; + last = t; + } else + last = first = t; + + n_entries ++; + + t = NULL; + + if (n_entries > MAX_ENTRIES) { + daemon_log(LOG_INFO, "Too many MSN table entries"); + goto fail; + } + } + + fclose(f); + daemon_log(LOG_INFO, "MSN table '%s' successfully read.", fn); + + return 0; + +fail: + + if (t) + msntab_unref(t); + + if (f) + fclose(f); + + return -1; +} + + +static void dump_entry(struct tabentry *t) { + char s[256]; + assert(t); + + s[0] = 0; + + if (t->args) { + char **a = t->args; + + while (*a) { + char *p = strchr(s, 0); + snprintf(p, sizeof(s)-(p-s), a == t->args ? "%s" : " %s", *a); + a++; + } + } else + strncpy(s, "NOARGS", sizeof(s)); + + daemon_log(LOG_INFO, "[%s:%02u] %-12s -> %-12s; shbuf=%-3s; rings=%u; action=%s; args=<%s>", + t->filename, + t->line, + t->local, + t->remote, + t->shbuf ? "yes" : "no", + t->rings, + t->action == CALL_ACTION_ACCEPT ? "ACCEPT" : (t->action == CALL_ACTION_HANGUP ? "HANGUP" : "IGNORE"), + s); +} + +void msntab_dump(void) { + struct tabentry *l; + + daemon_log(LOG_INFO, "=== Dumping MSN table ==="); + + l = first; + while (l) { + dump_entry(l); + l = l->next; + } + + daemon_log(LOG_INFO, "=== MSN table dump complete ==="); +} -- cgit