summaryrefslogtreecommitdiffstats
path: root/lib/stream.h
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2017-11-02 13:37:06 +0100
committerDonald Sharp <sharpd@cumulusnetworks.com>2017-11-13 20:15:24 +0100
commit051cc28c8f586eb3482e5fd9878b2307dbf98e38 (patch)
tree09f3c9e167bf48c72e7058e3c707ff4593d933d2 /lib/stream.h
parentMerge pull request #1436 from rtrlib/rpki (diff)
downloadfrr-051cc28c8f586eb3482e5fd9878b2307dbf98e38.tar.xz
frr-051cc28c8f586eb3482e5fd9878b2307dbf98e38.zip
lib: Add STREAM_GETX functions
Currently when stream reads fail, for any reason, we assert. While a *great* debugging tool, Asserting on production code is not a good thing. So this is the start of a conversion over to a series of STREAM_GETX functions that do not assert and allow the developer a way to program this gracefully and still clean up. Current code is something like this( taken from redistribute.c because this is dead simple ): afi = stream_getc(client->ibuf); type = stream_getc(client->ibuf); instance = stream_getw(client->ibuf); This code has several issues: 1) There is no failure mode for the stream read other than assert. if afi fails to be read the code stops. 2) stream_getX functions cannot be converted to a failure mode because it is impossible to tell a failure from good data with this api. So this new code will convert to this: STREAM_GETC(client->ibuf, afi); STREAM_GETC(client->ibuf, type); STREAM_GETW(client->ibuf, instance); .... stream_failure: return; We've created a stream_getc2( which does not assert ), but we need a way to allow clean failure mode handling. This is done by macro'ing stream_getX2 functions with the equivalent all uppercase STREAM_GETX functions that include a goto. Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Diffstat (limited to 'lib/stream.h')
-rw-r--r--lib/stream.h49
1 files changed, 49 insertions, 0 deletions
diff --git a/lib/stream.h b/lib/stream.h
index 7dcdca69f..1048180fa 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -181,14 +181,18 @@ extern int stream_put_prefix(struct stream *, struct prefix *);
extern int stream_put_labeled_prefix(struct stream *, struct prefix *,
mpls_label_t *);
extern void stream_get(void *, struct stream *, size_t);
+extern bool stream_get2(void *data, struct stream *s, size_t size);
extern void stream_get_from(void *, struct stream *, size_t, size_t);
extern u_char stream_getc(struct stream *);
+extern bool stream_getc2(struct stream *s, u_char *byte);
extern u_char stream_getc_from(struct stream *, size_t);
extern u_int16_t stream_getw(struct stream *);
+extern bool stream_getw2(struct stream *s, uint16_t *word);
extern u_int16_t stream_getw_from(struct stream *, size_t);
extern u_int32_t stream_get3(struct stream *);
extern u_int32_t stream_get3_from(struct stream *, size_t);
extern u_int32_t stream_getl(struct stream *);
+extern bool stream_getl2(struct stream *s, uint32_t *l);
extern u_int32_t stream_getl_from(struct stream *, size_t);
extern uint64_t stream_getq(struct stream *);
extern uint64_t stream_getq_from(struct stream *, size_t);
@@ -257,4 +261,49 @@ static inline uint8_t *ptr_get_be32(uint8_t *ptr, uint32_t *out)
return ptr + 4;
}
+/*
+ * so Normal stream_getX functions assert. Which is anathema
+ * to keeping a daemon up and running when something goes south
+ * Provide a stream_getX2 functions that do not assert.
+ * In addition provide these macro's that upon failure
+ * goto stream_failure. This is modeled upon some NL_XX
+ * macros in the linux kernel.
+ *
+ * This change allows for proper memory freeing
+ * after we've detected an error.
+ *
+ * In the future we will be removing the assert in
+ * the stream functions but we need a transition
+ * plan.
+ */
+#define STREAM_GETC(S, P) \
+ do { \
+ uint8_t _pval; \
+ if (!stream_getc2((S), &_pval)) \
+ goto stream_failure; \
+ (P) = _pval; \
+ } while (0)
+
+#define STREAM_GETW(S, P) \
+ do { \
+ uint16_t _pval; \
+ if (!stream_getw2((S), &_pval)) \
+ goto stream_failure; \
+ (P) = _pval; \
+ } while (0)
+
+#define STREAM_GETL(S, P) \
+ do { \
+ uint32_t _pval; \
+ if (!stream_getl2((S), &_pval)) \
+ goto stream_failure; \
+ (P) = _pval; \
+ } while (0)
+
+#define STREAM_GET(P, STR, SIZE) \
+ do { \
+ if (!stream_get2((P), (STR), (SIZE))) \
+ goto stream_failure; \
+ } while (0)
+
#endif /* _ZEBRA_STREAM_H */