+++ /dev/null
-#ifndef _MINI_SAMPLE_H
-#define _MINI_SAMPLE_H
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-
-/* input and output sample types */
-enum {
- SMP_T_ANY = 0, /* any type */
- SMP_T_BOOL, /* boolean */
- SMP_T_SINT, /* signed 64bits integer type */
- SMP_T_ADDR, /* ipv4 or ipv6, only used for input type compatibility */
- SMP_T_IPV4, /* ipv4 type */
- SMP_T_IPV6, /* ipv6 type */
- SMP_T_STR, /* char string type */
- SMP_T_BIN, /* buffer type */
- SMP_T_METH, /* contain method */
- SMP_TYPES /* number of types, must always be last */
-};
-
-/* describes a chunk of string */
-struct chunk {
- char *str; /* beginning of the string itself. Might not be 0-terminated */
- int size; /* total size of the buffer, 0 if the *str is read-only */
- int len; /* current size of the string from first to last char. <0 = uninit. */
-};
-
-union sample_value {
- long long int sint; /* used for signed 64bits integers */
- struct in_addr ipv4; /* used for ipv4 addresses */
- struct in6_addr ipv6; /* used for ipv6 addresses */
- struct chunk str; /* used for char strings or buffers */
- //struct meth meth; /* used for http method */
-};
-
-/* Used to store sample constant */
-struct sample_data {
- int type; /* SMP_T_* */
- union sample_value u; /* sample data */
-};
-
-/* a sample is a typed data extracted from a stream. It has a type, contents,
- * validity constraints, a context for use in iterative calls.
- */
-struct sample {
- struct sample_data data;
-};
-#endif
-
#include <stdint.h>
#include <string.h>
#include <spoe_types.h>
-#include <mini-sample.h>
#ifndef MIN
return sz;
}
-/* Encode a typed data using value in <smp>. On success, it returns the number
- * of copied bytes and <*buf> is moved after the encoded value. If an error
- * occured, it returns -1.
+/* Encode a typed data using value in <data> and type <type>. On success, it
+ * returns the number of copied bytes and <*buf> is moved after the encoded
+ * value. If an error occured, it returns -1.
*
* If the value is too big to be encoded, depending on its type, then encoding
* failed or the value is partially encoded. Only strings and binaries can be
* many bytes has been encoded. If <*off> is zero at the end, it means that all
* data has been encoded. */
static inline int
-spoe_encode_data(struct sample *smp, unsigned int *off, char **buf, char *end)
+spoe_encode_data(union spoe_data *data, enum spoe_data_type type, unsigned int *off, char **buf, char *end)
{
char *p = *buf;
int ret;
if (p >= end)
return -1;
- if (smp == NULL) {
+ if (data == NULL) {
*p++ = SPOE_DATA_T_NULL;
goto end;
}
- switch (smp->data.type) {
- case SMP_T_BOOL:
- *p = SPOE_DATA_T_BOOL;
- *p++ |= ((!smp->data.u.sint) ? SPOE_DATA_FL_FALSE : SPOE_DATA_FL_TRUE);
+ *p++ = type;
+ switch (type) {
+ case SPOE_DATA_T_BOOL:
+ p[-1] |= (data->boolean ? SPOE_DATA_FL_TRUE : SPOE_DATA_FL_FALSE);
+ break;
+
+ case SPOE_DATA_T_INT32:
+ if (encode_varint(data->int32, &p, end) == -1)
+ return -1;
break;
- case SMP_T_SINT:
- *p++ = SPOE_DATA_T_INT64;
- if (encode_varint(smp->data.u.sint, &p, end) == -1)
+ case SPOE_DATA_T_UINT32:
+ if (encode_varint(data->uint32, &p, end) == -1)
return -1;
break;
- case SMP_T_IPV4:
- if (p + 5 > end)
+ case SPOE_DATA_T_INT64:
+ if (encode_varint(data->int64, &p, end) == -1)
+ return -1;
+ break;
+
+ case SPOE_DATA_T_UINT64:
+ if (encode_varint(data->uint64, &p, end) == -1)
+ return -1;
+ break;
+
+ case SPOE_DATA_T_IPV4:
+ if (p + 4 > end)
return -1;
- *p++ = SPOE_DATA_T_IPV4;
- memcpy(p, &smp->data.u.ipv4, 4);
+ memcpy(p, &data->ipv4, 4);
p += 4;
break;
- case SMP_T_IPV6:
- if (p + 17 > end)
+ case SPOE_DATA_T_IPV6:
+ if (p + 16 > end)
return -1;
- *p++ = SPOE_DATA_T_IPV6;
- memcpy(p, &smp->data.u.ipv6, 16);
+ memcpy(p, &data->ipv6, 16);
p += 16;
break;
- case SMP_T_STR:
- case SMP_T_BIN: {
- struct chunk *chk = &smp->data.u.str;
-
+ case SPOE_DATA_T_STR:
+ case SPOE_DATA_T_BIN: {
/* Here, we need to know if the sample has already been
* partially encoded. If yes, we only need to encode the
* remaining, <*off> reprensenting the number of bytes
* type (string or binary), the buffer length
* (as a varint) and at least 1 byte of the
* buffer. */
- struct chunk *chk = &smp->data.u.str;
-
- *p++ = (smp->data.type == SMP_T_STR)
- ? SPOE_DATA_T_STR
- : SPOE_DATA_T_BIN;
- ret = spoe_encode_frag_buffer(chk->str, chk->len, &p, end);
+ ret = spoe_encode_frag_buffer(data->chk.ptr, data->chk.len, &p, end);
if (ret == -1)
return -1;
}
else {
/* The sample has been fragmented, encode remaining data */
- ret = MIN(chk->len - *off, end - p);
- memcpy(p, chk->str + *off, ret);
+ ret = MIN(data->chk.len - *off, end - p);
+ memcpy(p, data->chk.ptr + *off, ret);
p += ret;
}
/* Now update <*off> */
- if (ret + *off != chk->len)
+ if (ret + *off != data->chk.len)
*off += ret;
else
*off = 0;
*/
default:
- *p++ = SPOE_DATA_T_NULL;
+ /* send type NULL for unknown types */
+ p[-1] = SPOE_DATA_T_NULL;
break;
}
* otherwise the number of read bytes is returned and <*buf> is moved after the
* decoded data. See spoe_skip_data for details. */
static inline int
-spoe_decode_data(char **buf, char *end, struct sample *smp)
+spoe_decode_data(char **buf, char *end, union spoe_data *data, enum spoe_data_type *type)
{
char *str, *p = *buf;
- int type, r = 0;
+ int v, r = 0;
uint64_t sz;
if (p >= end)
return -1;
- type = *p++;
- switch (type & SPOE_DATA_T_MASK) {
+ v = *p++;
+ *type = v & SPOE_DATA_T_MASK;
+
+ switch (*type) {
case SPOE_DATA_T_BOOL:
- smp->data.u.sint = ((type & SPOE_DATA_FL_MASK) == SPOE_DATA_FL_TRUE);
- smp->data.type = SMP_T_BOOL;
+ data->boolean = ((v & SPOE_DATA_FL_MASK) == SPOE_DATA_FL_TRUE);
break;
case SPOE_DATA_T_INT32:
+ if (decode_varint(&p, end, &sz) == -1)
+ return -1;
+ data->int32 = sz;
+ break;
case SPOE_DATA_T_INT64:
+ if (decode_varint(&p, end, &sz) == -1)
+ return -1;
+ data->int64 = sz;
+ break;
case SPOE_DATA_T_UINT32:
+ if (decode_varint(&p, end, &sz) == -1)
+ return -1;
+ data->uint32 = sz;
+ break;
case SPOE_DATA_T_UINT64:
- if (decode_varint(&p, end, (uint64_t *)&smp->data.u.sint) == -1)
+ if (decode_varint(&p, end, &sz) == -1)
return -1;
- smp->data.type = SMP_T_SINT;
+ data->uint64 = sz;
break;
case SPOE_DATA_T_IPV4:
if (p+4 > end)
return -1;
- smp->data.type = SMP_T_IPV4;
- memcpy(&smp->data.u.ipv4, p, 4);
+ memcpy(&data->ipv4, p, 4);
p += 4;
break;
case SPOE_DATA_T_IPV6:
if (p+16 > end)
return -1;
- memcpy(&smp->data.u.ipv6, p, 16);
- smp->data.type = SMP_T_IPV6;
+ memcpy(&data->ipv6, p, 16);
p += 16;
break;
case SPOE_DATA_T_STR:
/* All the buffer must be decoded */
if (spoe_decode_buffer(&p, end, &str, &sz) == -1)
return -1;
- smp->data.u.str.str = str;
- smp->data.u.str.len = sz;
- smp->data.type = (type == SPOE_DATA_T_STR) ? SMP_T_STR : SMP_T_BIN;
+ data->chk.ptr = str;
+ data->chk.len = sz;
+ break;
+ default: /* SPOE_DATA_T_NULL, unknown */
break;
}
nbargs = *p++; /* Get the number of arguments */
frame->offset = (p - frame->buf); /* Save index to handle errors and skip args */
if (!memcmp(str, "check-client-ip", sz)) {
- struct sample smp;
-
- memset(&smp, 0, sizeof(smp));
+ union spoe_data data;
+ enum spoe_data_type type;
if (nbargs != 1)
goto skip_message;
if (spoe_decode_buffer(&p, end, &str, &sz) == -1)
goto stop_processing;
- if (spoe_decode_data(&p, end, &smp) == -1)
+ if (spoe_decode_data(&p, end, &data, &type) == -1)
goto skip_message;
- if (smp.data.type == SMP_T_IPV4)
- check_ipv4_reputation(frame, &smp.data.u.ipv4);
- if (smp.data.type == SMP_T_IPV6)
- check_ipv6_reputation(frame, &smp.data.u.ipv6);
+ if (type == SPOE_DATA_T_IPV4)
+ check_ipv4_reputation(frame, &data.ipv4);
+ if (type == SPOE_DATA_T_IPV6)
+ check_ipv6_reputation(frame, &data.ipv6);
}
else {
skip_message: