diff options
| author | Linus Nordberg <linus@nordu.net> | 2010-10-04 01:31:01 +0200 | 
|---|---|---|
| committer | Linus Nordberg <linus@nordu.net> | 2010-10-04 01:31:01 +0200 | 
| commit | 0065f2622cc3bdf1e5cfd322fbb890a25afef8d8 (patch) | |
| tree | 078425b00c8cd28eef9d9dd5ab9ef2d714a4ae01 /lib | |
| parent | dcfb8bca7400c5db4fafbed7aa9395e5f3277d9b (diff) | |
WIP -- reading configuration.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/conf.c | 104 | ||||
| -rw-r--r-- | lib/err.c | 45 | ||||
| -rw-r--r-- | lib/examples/Makefile | 4 | ||||
| -rw-r--r-- | lib/examples/client-blocking.c | 29 | ||||
| -rw-r--r-- | lib/examples/client.conf | 10 | ||||
| -rw-r--r-- | lib/include/radsec/radsec-impl.h | 8 | ||||
| -rw-r--r-- | lib/include/radsec/radsec.h | 3 | ||||
| -rw-r--r-- | lib/radsec.c | 70 | 
8 files changed, 211 insertions, 62 deletions
| diff --git a/lib/conf.c b/lib/conf.c new file mode 100644 index 0000000..9acf4d4 --- /dev/null +++ b/lib/conf.c @@ -0,0 +1,104 @@ +#include <confuse.h> +#include <string.h> +#include <radsec/radsec.h> +#include <radsec/radsec-impl.h> + +#if 0 +  realm NAME { +      type = STRING +      server { +          hostname = STRING +	  service = STRING +	  secret = STRING +	  timeout = INT         /* optional */ +	  tries = INT		/* optional */ +      } +  } +#endif + +int +rs_context_read_config(struct rs_handle *ctx, const char *config_file) +{ +#warning "Missing some error handling in rs_context_config_read()" +  cfg_opt_t server_opts[] = +    { +      CFG_STR ("hostname", NULL, CFGF_NONE), +      CFG_STR ("service", "radius", CFGF_NONE), +      CFG_STR ("secret", NULL, CFGF_NONE), +      CFG_INT ("timeout", 3, CFGF_NONE), +      CFG_INT ("tries", 1, CFGF_NONE), +      CFG_END () +    }; +  cfg_opt_t realm_opts[] = +    { +      CFG_STR ("type", "UDP", CFGF_NONE), +      CFG_SEC ("server", server_opts, CFGF_MULTI), +      CFG_END () +    }; +  cfg_opt_t opts[] = +    { +      CFG_SEC ("realm", realm_opts, CFGF_TITLE | CFGF_MULTI), +      CFG_END () +    }; +  cfg_t *cfg, *cfg_realm, *cfg_server; +  int i, j; + +  cfg = cfg_init (opts, CFGF_NONE); +  if (cfg_parse (cfg, config_file) == CFG_PARSE_ERROR) +    return rs_err_ctx_push (ctx, RSE_CONFIG, "%s: invalid configuration file", +			    config_file); +  for (i = 0; i < cfg_size (cfg, "realm"); i++) +    { +      struct rs_realm *r = rs_malloc (ctx, sizeof(*r)); +      const char *typestr; +      enum rs_conn_type type; + +      if (!r) +	return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__, NULL); +      memset (r, 0, sizeof(*r)); +      if (ctx->realms) +	ctx->realms->next = r; +      else +	ctx->realms = r; +      cfg_realm = cfg_getnsec (cfg, "realm", i); +      r->name = strdup (cfg_title (cfg_realm)); +      typestr = cfg_getstr (cfg_realm, "type"); +      if (!strcmp (typestr, "UDP")) +	type = RS_CONN_TYPE_UDP; +      else if (!strcmp (typestr, "TCP")) +	type = RS_CONN_TYPE_TCP; +      else if (!strcmp (typestr, "TLS")) +	type = RS_CONN_TYPE_TLS; +      else if (!strcmp (typestr, "DTLS")) +	type = RS_CONN_TYPE_DTLS; +      else +	return rs_err_ctx_push_fl (ctx, RSE_CONFIG, __FILE__, __LINE__, +				   "%s: invalid connection type", typestr); +      for (j = 0; j < cfg_size (cfg_realm, "server"); j++) +	{ +	  struct rs_peer *p = _rs_peer_create (ctx, &r->peers); +	  if (!p) +	    return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__, +				       NULL); + +	  cfg_server = cfg_getnsec (cfg_realm, "server", j); +	  _rs_resolv (&p->addr, type, cfg_getstr (cfg_server, "hostname"), +		      cfg_getstr (cfg_server, "service")); +	  p->secret = strdup (cfg_getstr (cfg_server, "secret")); +	  p->timeout = cfg_getint (cfg_server, "timeout"); +	  p->tries = cfg_getint (cfg_server, "tries"); +	} +    } +  return RSE_OK; +} + +struct rs_realm +*rs_conf_find_realm(struct rs_handle *ctx, const char *name) +{ +  struct rs_realm *r; + +  for (r = ctx->realms; r; r = r->next) +    if (!strcmp (r->name, name)) +	return r; +  return NULL; +} @@ -18,22 +18,23 @@ const char *_errtxt[] = {    "no peer configured"		/* 8 RSE_NOPEER */    "libevent error"		/* 9 RSE_EVENT */    "connection error"		/* 10 RSE_CONNERR */ -  "ERR 11"			/*  RSE_ */ +  "invalid configuration file"	/* 11 RSE_CONFIG */    "ERR 12"			/*  RSE_ */    "ERR 13"			/*  RSE_ */ -  "ERR "			/*  RSE_ */ -  "ERR "			/*  RSE_ */ -  "ERR "			/*  RSE_ */ -  "ERR "			/*  RSE_ */ -  "ERR "			/*  RSE_ */ -  "ERR "			/*  RSE_ */ -  "ERR "			/*  RSE_ */ +  "ERR 14"			/*  RSE_ */ +  "ERR 15"			/*  RSE_ */ +  "ERR 16"			/*  RSE_ */ +  "ERR 17"			/*  RSE_ */ +  "ERR 18"			/*  RSE_ */ +  "ERR 19"			/*  RSE_ */ +  "ERR 20"			/*  RSE_ */    "some error"			/* 21 RSE_SOME_ERROR */  };  #define ERRTXT_SIZE (sizeof(_errtxt) / sizeof(*_errtxt))  static struct rs_error * -_err_new (unsigned int code, const char *file, int line, const char *fmt, va_list args) +_err_vcreate (unsigned int code, const char *file, int line, const char *fmt, +	      va_list args)  {    struct rs_error *err; @@ -64,10 +65,23 @@ _err_new (unsigned int code, const char *file, int line, const char *fmt, va_lis    return err;  } +struct rs_error * +_rs_err_create (unsigned int code, const char *file, int line, const char *fmt, +		...) +{ +  struct rs_error *err; + +  va_list args; +  va_start (args, fmt); +  err = _err_vcreate (code, file, line, fmt, args); +  va_end (args); +  return err; +} +  static int  _ctx_err_vpush_fl (struct rs_handle *ctx, int code, const char *file, int line, const char *fmt, va_list args)  { -  struct rs_error *err = _err_new (code, file, line, fmt, args); +  struct rs_error *err = _err_vcreate (code, file, line, fmt, args);    if (err)      ctx->err = err; @@ -94,13 +108,20 @@ rs_err_ctx_push_fl (struct rs_handle *ctx, int code, const char *file, int line,    return code;  } +int +_rs_err_conn_push_err (struct rs_connection *conn, struct rs_error *err) +{ +  conn->err = err;		/* FIXME: use a stack */ +  return err->code; +} +  static int  _conn_err_vpush_fl (struct rs_connection *conn, int code, const char *file, int line, const char *fmt, va_list args)  { -  struct rs_error *err = _err_new (code, file, line, fmt, args); +  struct rs_error *err = _err_vcreate (code, file, line, fmt, args);    if (err) -    conn->err = err; +    _rs_err_conn_push_err (conn, err);    return code;  } diff --git a/lib/examples/Makefile b/lib/examples/Makefile index 4802c4b..cf3441b 100644 --- a/lib/examples/Makefile +++ b/lib/examples/Makefile @@ -1,6 +1,6 @@  SPECIAL =   #SPECIAL += -DUSE_REQUEST_OBJECT -#SPECIAL += -DUSE_CONFIG_FILE +SPECIAL += -DUSE_CONFIG_FILE  CFLAGS = -Wall -g -I ../include $(SPECIAL) @@ -9,7 +9,7 @@ HFILES = ../include/radsec/radsec.h ../include/radsec/radsec-impl.h  all: client-blocking  client-blocking: client-blocking.c ../libradsec.a $(HFILES) -	$(CC) $(CFLAGS) -o $@ $< -L /usr/lib/freeradius -lfreeradius-radius -L .. -lradsec -L /usr/local/lib -levent_core +	$(CC) $(CFLAGS) -o $@ $< -lconfuse -L /usr/lib/freeradius -lfreeradius-radius -L .. -lradsec -L /usr/local/lib -levent_core  clean:  	-rm *.o *.gch client-blocking diff --git a/lib/examples/client-blocking.c b/lib/examples/client-blocking.c index 0e6ad39..8cd9968 100644 --- a/lib/examples/client-blocking.c +++ b/lib/examples/client-blocking.c @@ -20,7 +20,6 @@ blocking_client (const char *av1, const char *av2)  {    struct rs_handle *h;    struct rs_connection *conn; -  struct rs_peer *server;    struct rs_packet *req, *resp;    RADIUS_PACKET *fr_pkt;    VALUE_PAIR *fr_vp; @@ -29,19 +28,23 @@ blocking_client (const char *av1, const char *av2)      return NULL;  #if !defined (USE_CONFIG_FILE) -  if (rs_conn_create (h, &conn, NULL)) -    return rs_err_conn_pop (conn); -  rs_conn_set_type (conn, RS_CONN_TYPE_UDP); -  if (rs_server_create (conn, &server)) -    return rs_err_conn_pop (conn); -  if (rs_server_set_address (server, av1, atoi (av2))) -    return rs_err_conn_pop (conn); -  rs_server_set_timeout (server, 1); -  rs_server_set_tries (server, 3); -  if (rs_server_set_secret (server, SECRET)) -    return rs_err_conn_pop (conn); +  { +    struct rs_peer *server; + +    if (rs_conn_create (h, &conn, NULL)) +      return rs_err_conn_pop (conn); +    rs_conn_set_type (conn, RS_CONN_TYPE_UDP); +    if (rs_server_create (conn, &server)) +      return rs_err_conn_pop (conn); +    if (rs_server_set_address (server, av1, av2)) +      return rs_err_conn_pop (conn); +    rs_server_set_timeout (server, 1); +    rs_server_set_tries (server, 3); +    if (rs_server_set_secret (server, SECRET)) +      return rs_err_conn_pop (conn); +  }  #else -  if (rs_context_config_read (h, av1)) +  if (rs_context_read_config (h, av1))      return rs_err_ctx_pop (h);    if (rs_conn_create (h, &conn, av2))      return rs_err_conn_pop (conn); diff --git a/lib/examples/client.conf b/lib/examples/client.conf new file mode 100644 index 0000000..5f9536f --- /dev/null +++ b/lib/examples/client.conf @@ -0,0 +1,10 @@ +realm blocking { +    type = "UDP" +    server { +        hostname = "localhost" +	service = "1820" +	secret = "sikrit" +	timeout = 1         /* optional */ +	tries = 10	      /* optional */ +    } +} diff --git a/lib/include/radsec/radsec-impl.h b/lib/include/radsec/radsec-impl.h index 503b2e5..9421fd6 100644 --- a/lib/include/radsec/radsec-impl.h +++ b/lib/include/radsec/radsec-impl.h @@ -46,6 +46,7 @@ struct rs_realm {      char *name;      enum rs_conn_type type;      struct rs_peer *peers; +    struct rs_realm *next;  };  struct rs_handle { @@ -79,6 +80,13 @@ struct rs_attr {      VALUE_PAIR *vp;  }; +/* Nonpublic functions.  */ +struct rs_error *_rs_resolv (struct evutil_addrinfo **addr, rs_conn_type_t type, const char *hostname, const char *service); +struct rs_peer *_rs_peer_create (struct rs_handle *ctx, struct rs_peer **rootp); +struct rs_error *_rs_err_create (unsigned int code, const char *file, int line, const char *fmt, ...); +int _rs_err_conn_push_err (struct rs_connection *conn, struct rs_error *err); + +  /* Convenience macros.  */  #define rs_calloc(h, nmemb, size) \      (h->alloc_scheme.calloc ? h->alloc_scheme.calloc : calloc)(nmemb, size) diff --git a/lib/include/radsec/radsec.h b/lib/include/radsec/radsec.h index c108d8a..982c430 100644 --- a/lib/include/radsec/radsec.h +++ b/lib/include/radsec/radsec.h @@ -16,6 +16,7 @@ enum rs_err_code {      RSE_NOPEER = 8,      RSE_EVENT = 9,      RSE_CONNERR = 10, +    RSE_CONFIG = 11,      RSE_SOME_ERROR = 21,  }; @@ -89,7 +90,7 @@ int rs_conn_receive_packet(struct rs_connection *conn, struct rs_packet **pkt_ou  /* Server and client.  */  int rs_server_create(struct rs_connection *conn, struct rs_peer **server); -int rs_server_set_address(struct rs_peer *server, const char *hostname, int port); +int rs_server_set_address(struct rs_peer *server, const char *hostname, const char *service);  int rs_server_set_secret(struct rs_peer *server, const char *secret);  void rs_server_set_timeout(struct rs_peer *server, int timeout);  void rs_server_set_tries(struct rs_peer *server, int tries); diff --git a/lib/radsec.c b/lib/radsec.c index adf5576..96182a6 100644 --- a/lib/radsec.c +++ b/lib/radsec.c @@ -73,12 +73,6 @@ int rs_context_set_alloc_scheme(struct rs_handle *ctx, struct rs_alloc_scheme *s  			     "%s: NYI", __func__);  } -int rs_context_config_read(struct rs_handle *ctx, const char *config_file) -{ -  return rs_err_ctx_push_fl (ctx, RSE_NOSYS, __FILE__, __LINE__, -			     "%s: NYI", __func__); -} -  int  rs_conn_create(struct rs_handle *ctx, struct rs_connection **conn,  	       const char *config) @@ -95,8 +89,12 @@ rs_conn_create(struct rs_handle *ctx, struct rs_connection **conn,  	  struct rs_realm *r = rs_conf_find_realm (ctx, config);  	  if (r)  	    { +	      struct rs_peer *p; +  	      c->type = r->type; -	      c->peers = r->peers; /* FIXME: Copy?  */ +	      c->peers = r->peers; /* FIXME: Copy instead?  */ +	      for (p = c->peers; p; p = p->next) +		p->conn = c;  	    }  	}      } @@ -111,22 +109,21 @@ rs_conn_set_type(struct rs_connection *conn, rs_conn_type_t type)    conn->type = type;  } -struct addrinfo * -_resolv (struct rs_connection *conn, const char *hostname, int port) + +struct rs_error * +_rs_resolv (struct evutil_addrinfo **addr, rs_conn_type_t type, +	    const char *hostname, const char *service)  {    int err; -  char portstr[6];    struct evutil_addrinfo hints, *res = NULL; -  snprintf (portstr, sizeof(portstr), "%d", port);    memset (&hints, 0, sizeof(struct evutil_addrinfo));    hints.ai_family = AF_UNSPEC;	/* v4 or v6.  */    hints.ai_flags = AI_ADDRCONFIG; -  switch (conn->type) +  switch (type)      {      case RS_CONN_TYPE_NONE: -      rs_err_conn_push_fl (conn, RSE_INVALID_CONN, __FILE__, __LINE__, NULL); -      return NULL; +      return _rs_err_create (RSE_INVALID_CONN, __FILE__, __LINE__, NULL, NULL);      case RS_CONN_TYPE_TCP:        /* Fall through.  */      case RS_CONN_TYPE_TLS: @@ -140,33 +137,30 @@ _resolv (struct rs_connection *conn, const char *hostname, int port)        hints.ai_protocol = IPPROTO_UDP;        break;      } -  err = evutil_getaddrinfo (hostname, portstr, &hints, &res); +  err = evutil_getaddrinfo (hostname, service, &hints, &res);    if (err) -    rs_err_conn_push_fl (conn, RSE_BADADDR, __FILE__, __LINE__, -			 "%s:%d: bad host name or port (%s)", -			 hostname, port, evutil_gai_strerror(err)); -  return res;			/* Simply use first result.  */ +    return _rs_err_create (RSE_BADADDR, __FILE__, __LINE__, +			   "%s:%s: bad host name or service name (%s)", +			   hostname, service, evutil_gai_strerror(err)); +  *addr = res;			/* Simply use first result.  */ +  return NULL;  } -static struct rs_peer * -_peer_new (struct rs_connection *conn) +struct rs_peer * +_rs_peer_create (struct rs_handle *ctx, struct rs_peer **rootp)  {    struct rs_peer *p; -  p = (struct rs_peer *) malloc (sizeof(*p)); +  p = (struct rs_peer *) rs_malloc (ctx, sizeof(*p));    if (p)      {        memset (p, 0, sizeof(struct rs_peer)); -      p->conn = conn;        p->fd = -1; -      p->next = conn->peers; -      if (conn->peers) -	conn->peers->next = p; +      if (*rootp) +	(*rootp)->next = p;        else -	conn->peers = p; +	*rootp = p;      } -  else -    rs_err_conn_push_fl (conn, RSE_NOMEM, __FILE__, __LINE__, NULL);    return p;  } @@ -175,22 +169,30 @@ rs_server_create (struct rs_connection *conn, struct rs_peer **server)  {    struct rs_peer *srv; -  srv = _peer_new (conn); +  srv = _rs_peer_create (conn->ctx, &conn->peers);    if (srv)      { +      srv->conn = conn;        srv->timeout = 1;        srv->tries = 3;      } +  else +    return rs_err_conn_push_fl (conn, RSE_NOMEM, __FILE__, __LINE__, NULL);    if (*server)      *server = srv; -  return srv ? RSE_OK : -1; +  return RSE_OK;  }  int -rs_server_set_address (struct rs_peer *server, const char *hostname, int port) +rs_server_set_address (struct rs_peer *server, const char *hostname, +		       const char *service)  { -  server->addr = _resolv (server->conn, hostname, port); -  return server->addr ? RSE_OK : -1; +  struct rs_error *err; + +  err = _rs_resolv (&server->addr, server->conn->type, hostname, service); +  if (err) +    return _rs_err_conn_push_err (server->conn, err); +  return RSE_OK;  }  void | 
