4a90019e916e9aaad75c3541b43e500549a6ec87
[libradsec.git] / lib / err.c
1 /* Copyright 2010, 2011 NORDUnet A/S. All rights reserved.
2    See the file COPYING for licensing information.  */
3
4 #if defined HAVE_CONFIG_H
5 #include <config.h>
6 #endif
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <assert.h>
11 #include <radsec/radsec.h>
12 #include <radsec/radsec-impl.h>
13
14 static const char *_errtxt[] = {
15   "SUCCESS",                    /* 0 RSE_OK */
16   "out of memory",              /* 1 RSE_NOMEM */
17   "not yet implemented",        /* 2 RSE_NOSYS */
18   "invalid handle",             /* 3 RSE_INVALID_CTX */
19   "invalid connection",         /* 4 RSE_INVALID_CONN */
20   "connection type mismatch",   /* 5 RSE_CONN_TYPE_MISMATCH */
21   "FreeRadius error",           /* 6 RSE_FR */
22   "bad hostname or port",       /* 7 RSE_BADADDR */
23   "no peer configured",         /* 8 RSE_NOPEER */
24   "libevent error",             /* 9 RSE_EVENT */
25   "socket error",               /* 10 RSE_SOCKERR */
26   "invalid configuration file", /* 11 RSE_CONFIG */
27   "authentication failed",      /* 12 RSE_BADAUTH */
28   "internal error",             /* 13 RSE_INTERNAL */
29   "SSL error",                  /* 14 RSE_SSLERR */
30   "invalid packet",             /* 15 RSE_INVALID_PKT */
31   "connect timeout",            /* 16 RSE_TIMEOUT_CONN */
32   "invalid argument",           /* 17 RSE_INVAL */
33   "I/O timeout",                /* 18 RSE_TIMEOUT_IO */
34   "timeout",                    /* 19 RSE_TIMEOUT */
35   "peer disconnected",          /* 20 RSE_DISCO */
36 };
37 #define ERRTXT_SIZE (sizeof(_errtxt) / sizeof(*_errtxt))
38
39 static struct rs_error *
40 _err_vcreate (unsigned int code, const char *file, int line, const char *fmt,
41               va_list args)
42 {
43   struct rs_error *err = NULL;
44
45   err = malloc (sizeof(struct rs_error));
46   if (err)
47     {
48       int n;
49       memset (err, 0, sizeof(struct rs_error));
50       err->code = code;
51       if (fmt)
52         n = vsnprintf (err->buf, sizeof(err->buf), fmt, args);
53       else
54         {
55           strncpy (err->buf,
56                    err->code < ERRTXT_SIZE ? _errtxt[err->code] : "",
57                    sizeof(err->buf));
58           n = strlen (err->buf);
59         }
60       if (n >= 0 && file)
61         {
62           char *sep = strrchr (file, '/');
63           if (sep)
64             file = sep + 1;
65           snprintf (err->buf + n, sizeof(err->buf) - n, " (%s:%d)", file,
66                     line);
67         }
68     }
69   return err;
70 }
71
72 struct rs_error *
73 err_create (unsigned int code,
74             const char *file,
75             int line,
76             const char *fmt,
77             ...)
78 {
79   struct rs_error *err = NULL;
80
81   va_list args;
82   va_start (args, fmt);
83   err = _err_vcreate (code, file, line, fmt, args);
84   va_end (args);
85
86   return err;
87 }
88
89 static int
90 _ctx_err_vpush_fl (struct rs_context *ctx, int code, const char *file,
91                    int line, const char *fmt, va_list args)
92 {
93   struct rs_error *err = _err_vcreate (code, file, line, fmt, args);
94
95   if (!err)
96     return RSE_NOMEM;
97
98   /* TODO: Implement a stack.  */
99   if (ctx->err)
100     rs_err_free (ctx->err);
101   ctx->err = err;
102
103   return err->code;
104 }
105
106 int
107 rs_err_ctx_push (struct rs_context *ctx, int code, const char *fmt, ...)
108 {
109   int r = 0;
110   va_list args;
111
112   va_start (args, fmt);
113   r = _ctx_err_vpush_fl (ctx, code, NULL, 0, fmt, args);
114   va_end (args);
115
116   return r;
117 }
118
119 int
120 rs_err_ctx_push_fl (struct rs_context *ctx, int code, const char *file,
121                     int line, const char *fmt, ...)
122 {
123   int r = 0;
124   va_list args;
125
126   va_start (args, fmt);
127   r = _ctx_err_vpush_fl (ctx, code, file, line, fmt, args);
128   va_end (args);
129
130   return r;
131 }
132
133 int
134 err_conn_push_err (struct rs_connection *conn, struct rs_error *err)
135 {
136
137   if (conn->err)
138     rs_err_free (conn->err);
139   conn->err = err;              /* FIXME: use a stack */
140
141   return err->code;
142 }
143
144 static int
145 _conn_err_vpush_fl (struct rs_connection *conn, int code, const char *file,
146                     int line, const char *fmt, va_list args)
147 {
148   struct rs_error *err = _err_vcreate (code, file, line, fmt, args);
149
150   if (!err)
151     return RSE_NOMEM;
152
153   return err_conn_push_err (conn, err);
154 }
155
156 int
157 rs_err_conn_push (struct rs_connection *conn, int code, const char *fmt, ...)
158 {
159   int r = 0;
160
161   va_list args;
162   va_start (args, fmt);
163   r = _conn_err_vpush_fl (conn, code, NULL, 0, fmt, args);
164   va_end (args);
165
166   return r;
167 }
168
169 int
170 rs_err_conn_push_fl (struct rs_connection *conn, int code, const char *file,
171                      int line, const char *fmt, ...)
172 {
173   int r = 0;
174
175   va_list args;
176   va_start (args, fmt);
177   r = _conn_err_vpush_fl (conn, code, file, line, fmt, args);
178   va_end (args);
179
180   return r;
181 }
182
183 struct rs_error *
184 rs_err_ctx_pop (struct rs_context *ctx)
185 {
186   struct rs_error *err;
187
188   if (!ctx)
189     return NULL;                /* FIXME: RSE_INVALID_CTX.  */
190   err = ctx->err;
191   ctx->err = NULL;
192
193   return err;
194 }
195
196 struct rs_error *
197 rs_err_conn_pop (struct rs_connection *conn)
198 {
199   struct rs_error *err;
200
201   if (!conn)
202     return NULL;                /* FIXME: RSE_INVALID_CONN */
203   err = conn->err;
204   conn->err = NULL;
205
206   return err;
207 }
208
209 int
210 rs_err_conn_peek_code (struct rs_connection *conn)
211 {
212   if (!conn)
213     return -1;                  /* FIXME: RSE_INVALID_CONN */
214   if (conn->err)
215     return conn->err->code;
216
217   return RSE_OK;
218 }
219
220 void
221 rs_err_free (struct rs_error *err)
222 {
223   assert (err);
224   free (err);
225 }
226
227 char *
228 rs_err_msg (struct rs_error *err)
229 {
230   if (!err)
231     return NULL;
232
233   return err->buf;
234 }
235
236 int
237 rs_err_code (struct rs_error *err, int dofree_flag)
238 {
239   int code;
240
241   if (!err)
242     return -1;
243   code = err->code;
244
245   if (dofree_flag)
246     rs_err_free (err);
247
248   return code;
249 }