]> git.proxmox.com Git - mirror_frr.git/blame - lib/ferr.h
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / lib / ferr.h
CommitLineData
acddc0ed 1// SPDX-License-Identifier: ISC
3155489a
DL
2/*
3 * Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc.
3155489a
DL
4 */
5
6#ifndef _FRR_FERR_H
7#define _FRR_FERR_H
8
9/***********************************************************
10 * scroll down to the end of this file for a full example! *
11 ***********************************************************/
12
13#include <stdint.h>
14#include <limits.h>
15#include <errno.h>
16
7b526b61
QY
17#include "vty.h"
18
5e244469
RW
19#ifdef __cplusplus
20extern "C" {
21#endif
22
3155489a
DL
23/* return type when this error indication stuff is used.
24 *
25 * guaranteed to have boolean evaluation to "false" when OK, "true" when error
214d8a60 26 * (i.e. can be changed to pointer in the future if necessary)
3155489a
DL
27 *
28 * For checking, always use "if (value)", nothing else.
29 * Do _NOT_ use any integer constant (!= 0), or sign check (< 0).
30 */
31typedef int ferr_r;
32
33/* rough category of error indication */
34enum ferr_kind {
35 /* no error */
36 FERR_OK = 0,
37
38 /* something isn't the way it's supposed to be.
39 * (things that might otherwise be asserts, really)
40 */
41 FERR_CODE_BUG,
42
43 /* user-supplied parameters don't make sense or is inconsistent
44 * if you can express a rule for it (e.g. "holdtime > 2 * keepalive"),
45 * it's this category.
46 */
47 FERR_CONFIG_INVALID,
48
49 /* user-supplied parameters don't line up with reality
50 * (IP address or interface not available, etc.)
51 * NB: these are really TODOs where the code needs to be fixed to
52 * respond to future changes!
53 */
54 FERR_CONFIG_REALITY,
55
56 /* out of some system resource (probably memory)
57 * aka "you didn't spend enough money error" */
58 FERR_RESOURCE,
59
60 /* system error (permission denied, etc.) */
61 FERR_SYSTEM,
62
63 /* error return from some external library
64 * (FERR_SYSTEM and FERR_LIBRARY are not strongly distinct) */
65 FERR_LIBRARY,
66};
67
68struct ferr {
69 /* code location */
70 const char *file;
71 const char *func;
72 int line;
73
74 enum ferr_kind kind;
75
76 /* unique_id is calculated as a checksum of source filename and error
77 * message format (*before* calling vsnprintf). Line number and
78 * function name are not used; this keeps the number reasonably static
79 * across changes.
80 */
81 uint32_t unique_id;
82
83 char message[384];
84
85 /* valid if != 0. note "errno" might be preprocessor foobar. */
86 int errno_val;
87 /* valid if pathname[0] != '\0' */
88 char pathname[PATH_MAX];
89};
90
7b526b61 91/* Numeric ranges assigned to daemons for use as error codes. */
0f41a262
DS
92#define BABEL_FERR_START 0x01000001
93#define BABEL_FRRR_END 0x01FFFFFF
94#define BGP_FERR_START 0x02000001
95#define BGP_FERR_END 0x02FFFFFF
96#define EIGRP_FERR_START 0x03000001
97#define EIGRP_FERR_END 0x03FFFFFF
98#define ISIS_FERR_START 0x04000001
99#define ISIS_FERR_END 0x04FFFFFF
100#define LDP_FERR_START 0x05000001
101#define LDP_FERR_END 0x05FFFFFF
102#define LIB_FERR_START 0x06000001
103#define LIB_FERR_END 0x06FFFFFF
104#define NHRP_FERR_START 0x07000001
105#define NHRP_FERR_END 0x07FFFFFF
106#define OSPF_FERR_START 0x08000001
107#define OSPF_FERR_END 0x08FFFFFF
108#define OSPFV3_FERR_START 0x09000001
109#define OSPFV3_FERR_END 0x09FFFFFF
110#define PBR_FERR_START 0x0A000001
111#define PBR_FERR_END 0x0AFFFFFF
112#define PIM_FERR_START 0x0B000001
113#define PIM_FERR_STOP 0x0BFFFFFF
114#define RIP_FERR_START 0x0C000001
115#define RIP_FERR_STOP 0x0CFFFFFF
116#define RIPNG_FERR_START 0x0D000001
117#define RIPNG_FERR_STOP 0x0DFFFFFF
118#define SHARP_FERR_START 0x0E000001
119#define SHARP_FERR_END 0x0EFFFFFF
120#define VTYSH_FERR_START 0x0F000001
121#define VTYSH_FRR_END 0x0FFFFFFF
122#define WATCHFRR_FERR_START 0x10000001
123#define WATCHFRR_FERR_END 0x10FFFFFF
4d7b695d
SM
124#define PATH_FERR_START 0x11000001
125#define PATH_FERR_END 0x11FFFFFF
0f41a262
DS
126#define ZEBRA_FERR_START 0xF1000001
127#define ZEBRA_FERR_END 0xF1FFFFFF
128#define END_FERR 0xFFFFFFFF
7b526b61 129
85cd2f9f 130struct log_ref {
7b526b61
QY
131 /* Unique error code displayed to end user as a reference. -1 means
132 * this is an uncoded error that does not have reference material. */
133 uint32_t code;
134 /* Ultra brief title */
135 const char *title;
136 /* Brief description of error */
137 const char *description;
138 /* Remedial suggestion */
139 const char *suggestion;
140};
141
85cd2f9f
QY
142void log_ref_add(struct log_ref *ref);
143struct log_ref *log_ref_get(uint32_t code);
144void log_ref_display(struct vty *vty, uint32_t code, bool json);
b66d022e
DS
145
146/*
147 * This function should be called by the
148 * code in libfrr.c
149 */
85cd2f9f
QY
150void log_ref_init(void);
151void log_ref_fini(void);
1f9128d6 152void log_ref_vty_init(void);
7b526b61 153
3155489a
DL
154/* get error details.
155 *
156 * NB: errval/ferr_r does NOT carry the full error information. It's only
157 * passed around for future API flexibility. ferr_get_last always returns
158 * the last error set in the current thread.
159 */
160const struct ferr *ferr_get_last(ferr_r errval);
161
af4d3437
QY
162/*
163 * Can optionally be called at strategic locations.
164 * Always returns 0.
165 */
3155489a
DL
166ferr_r ferr_clear(void);
167
168/* do NOT call these functions directly. only for macro use! */
169ferr_r ferr_set_internal(const char *file, int line, const char *func,
0f9de11a
DL
170 enum ferr_kind kind, const char *text, ...)
171 PRINTFRR(5, 6);
3155489a 172ferr_r ferr_set_internal_ext(const char *file, int line, const char *func,
996c9314 173 enum ferr_kind kind, const char *pathname,
0f9de11a
DL
174 int errno_val, const char *text, ...)
175 PRINTFRR(7, 8);
3155489a 176
996c9314 177#define ferr_ok() 0
3155489a
DL
178
179/* Report an error.
180 *
181 * If you need to do cleanup (free memory, etc.), save the return value in a
182 * variable of type ferr_r.
183 *
184 * Don't put a \n at the end of the error message.
185 */
996c9314
LB
186#define ferr_code_bug(...) \
187 ferr_set_internal(__FILE__, __LINE__, __func__, FERR_CODE_BUG, \
188 __VA_ARGS__)
189#define ferr_cfg_invalid(...) \
190 ferr_set_internal(__FILE__, __LINE__, __func__, FERR_CONFIG_INVALID, \
191 __VA_ARGS__)
192#define ferr_cfg_reality(...) \
193 ferr_set_internal(__FILE__, __LINE__, __func__, FERR_CONFIG_REALITY, \
194 __VA_ARGS__)
195#define ferr_cfg_resource(...) \
196 ferr_set_internal(__FILE__, __LINE__, __func__, FERR_RESOURCE, \
197 __VA_ARGS__)
198#define ferr_system(...) \
199 ferr_set_internal(__FILE__, __LINE__, __func__, FERR_SYSTEM, \
200 __VA_ARGS__)
201#define ferr_library(...) \
202 ferr_set_internal(__FILE__, __LINE__, __func__, FERR_LIBRARY, \
203 __VA_ARGS__)
3155489a
DL
204
205/* extended information variants */
996c9314
LB
206#define ferr_system_errno(...) \
207 ferr_set_internal_ext(__FILE__, __LINE__, __func__, FERR_SYSTEM, NULL, \
208 errno, __VA_ARGS__)
209#define ferr_system_path_errno(path, ...) \
210 ferr_set_internal_ext(__FILE__, __LINE__, __func__, FERR_SYSTEM, path, \
211 errno, __VA_ARGS__)
3155489a
DL
212
213#include "vty.h"
214/* print error message to vty; $ERR is replaced by the error's message */
0f9de11a
DL
215void vty_print_error(struct vty *vty, ferr_r err, const char *msg, ...)
216 PRINTFRR(3, 4);
3155489a 217
996c9314
LB
218#define CMD_FERR_DO(func, action, ...) \
219 do { \
220 ferr_r cmd_retval = func; \
221 if (cmd_retval) { \
222 vty_print_error(vty, cmd_retval, __VA_ARGS__); \
223 action; \
224 } \
3155489a
DL
225 } while (0)
226
996c9314 227#define CMD_FERR_RETURN(func, ...) \
7eb09438 228 CMD_FERR_DO(func, return CMD_WARNING_CONFIG_FAILED, __VA_ARGS__)
996c9314 229#define CMD_FERR_GOTO(func, label, ...) \
3155489a
DL
230 CMD_FERR_DO(func, goto label, __VA_ARGS__)
231
e894f9fd
LB
232/* example: uses bogus #define to keep indent.py happy */
233#ifdef THIS_IS_AN_EXAMPLE
3155489a
DL
234ferr_r foo_bar_set(struct object *obj, int bar)
235{
236 if (bar < 1 || bar >= 100)
e894f9fd
LB
237 return ferr_config_invalid("bar setting (%d) must be 0<x<100",
238 bar);
3155489a 239 obj->bar = bar;
e894f9fd 240 if (ioctl(obj->fd, bar))
3155489a
DL
241 return ferr_system_errno("couldn't set bar to %d", bar);
242
243 return ferr_ok();
244}
245
246DEFUN("bla")
247{
248 CMD_FERR_RETURN(foo_bar_set(obj, atoi(argv[1])),
996c9314 249 "command failed: $ERR\n");
3155489a
DL
250 return CMD_SUCCESS;
251}
252
e894f9fd 253#endif /* THIS_IS_AN_EXAMPLE */
3155489a 254
5e244469
RW
255#ifdef __cplusplus
256}
257#endif
258
3155489a 259#endif /* _FERR_H */