Refactoring in preparation for handling more cases than client sending one packet.
[radsecproxy.git] / lib / err.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <assert.h>
4 #include "libradsec.h"
5 #include "libradsec-impl.h"
6
7 const char *_errtxt[] = {
8   "SUCCESS",                    /* 0 RSE_OK */
9   "NOMEM",                      /* 1 RSE_NOMEM */
10   "NYI -- not yet implemented", /* 2 RSE_NOSYS */
11   "invalid handle"              /* 3 RSE_INVALID_CTX */
12   "invalid connection"          /* 4 RSE_INVALID_CONN */
13   "connection type mismatch"    /* 5 RSE_CONN_TYPE_MISMATCH */
14   "FreeRadius error"            /* 6 RSE_FR */
15   "bad hostname or port"        /* 7 RSE_BADADDR */
16   "no peer configured"          /* 8 RSE_NOPEER */
17   "libevent error"              /* 9 RSE_EVENT */
18   "connection error"            /* 10 RSE_CONNERR */
19   "ERR 11"                      /*  RSE_ */
20   "ERR 12"                      /*  RSE_ */
21   "ERR 13"                      /*  RSE_ */
22   "ERR "                        /*  RSE_ */
23   "ERR "                        /*  RSE_ */
24   "ERR "                        /*  RSE_ */
25   "ERR "                        /*  RSE_ */
26   "ERR "                        /*  RSE_ */
27   "ERR "                        /*  RSE_ */
28   "ERR "                        /*  RSE_ */
29   "some error"                  /* 21 RSE_SOME_ERROR */
30 };
31 #define ERRTXT_SIZE (sizeof(_errtxt) / sizeof(*_errtxt))
32
33 static struct rs_error *
34 _err_new (unsigned int code, const char *file, int line, const char *fmt, va_list args)
35 {
36   struct rs_error *err;
37
38   err = malloc (sizeof(struct rs_error));
39   if (err)
40     {
41       int n;
42       memset (err, 0, sizeof(struct rs_error));
43       err->code = code;
44       if (fmt)
45         n = vsnprintf (err->buf, sizeof(err->buf), fmt, args);
46       else
47         {
48           strncpy (err->buf,
49                    err->code < ERRTXT_SIZE ? _errtxt[err->code] : "",
50                    sizeof(err->buf));
51           n = strlen (err->buf);
52         }
53       if (n >= 0)
54         {
55           char *sep = strrchr (file, '/');
56           if (sep)
57             file = sep + 1;
58           snprintf (err->buf + n, sizeof(err->buf) - n, " (%s: %d)", file,
59                     line);
60         }
61     }
62   return err;
63 }
64
65 static int
66 _ctx_err_vpush_fl (struct rs_handle *ctx, int code, const char *file, int line, const char *fmt, va_list args)
67 {
68   struct rs_error *err = _err_new (code, file, line, fmt, args);
69
70   if (err)
71     ctx->err = err;
72   return code;
73 }
74
75 int
76 rs_ctx_err_push (struct rs_handle *ctx, int code, const char *fmt, ...)
77 {
78   va_list args;
79   va_start (args, fmt);
80   _ctx_err_vpush_fl (ctx, code, NULL, 0, fmt, args);
81   va_end (args);
82   return code;
83 }
84
85 int
86 rs_ctx_err_push_fl (struct rs_handle *ctx, int code, const char *file, int line, const char *fmt, ...)
87 {
88   va_list args;
89   va_start (args, fmt);
90   _ctx_err_vpush_fl (ctx, code, file, line, fmt, args);
91   va_end (args);
92   return code;
93 }
94
95 static int
96 _conn_err_vpush_fl (struct rs_connection *conn, int code, const char *file, int line, const char *fmt, va_list args)
97 {
98   struct rs_error *err = _err_new (code, file, line, fmt, args);
99
100   if (err)
101     conn->err = err;
102   return code;
103 }
104
105 int
106 rs_conn_err_push (struct rs_connection *conn, int code, const char *fmt, ...)
107 {
108   va_list args;
109   va_start (args, fmt);
110   _conn_err_vpush_fl (conn, code, NULL, 0, fmt, args);
111   va_end (args);
112   return code;
113 }
114
115 int
116 rs_conn_err_push_fl (struct rs_connection *conn, int code, const char *file, int line, const char *fmt, ...)
117 {
118   va_list args;
119   va_start (args, fmt);
120   _conn_err_vpush_fl (conn, code, file, line, fmt, args);
121   va_end (args);
122   return code;
123 }
124
125 struct rs_error *
126 rs_ctx_err_pop (struct rs_handle *ctx)
127 {
128   struct rs_error *err;
129
130   if (!ctx)
131     return NULL;                /* FIXME: RSE_INVALID_CTX.  */
132   err = ctx->err;
133   ctx->err = NULL;
134   return err;
135 }
136
137 struct rs_error *
138 rs_conn_err_pop (struct rs_connection *conn)
139 {
140   struct rs_error *err;
141
142   if (!conn)
143     return NULL;                /* FIXME: RSE_INVALID_CONN */
144   err = conn->err;
145   conn->err = NULL;
146   return err;
147 }
148
149 void
150 rs_err_free (struct rs_error *err)
151 {
152   assert (err);
153   if (err->msg)
154     free (err->msg);
155   free (err);
156 }
157
158 char *
159 rs_err_msg (struct rs_error *err, int dofree_flag)
160 {
161   char *msg;
162
163   if (!err)
164     return NULL;
165   if (err->msg)
166     msg = err->msg;
167   else
168     msg = strdup (err->buf);
169
170   if (dofree_flag)
171     rs_err_free (err);
172   return msg;
173 }
174
175 int
176 rs_err_code (struct rs_error *err, int dofree_flag)
177 {
178   int code;
179
180   if (!err)
181     return -1;
182   code = err->code;
183
184   if (dofree_flag)
185     rs_err_free(err);
186   return code;
187 }