1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*  Fluent Bit
4  *  ==========
5  *  Copyright (C) 2019-2021 The Fluent Bit Authors
6  *  Copyright (C) 2015-2018 Treasure Data Inc.
7  *
8  *  Licensed under the Apache License, Version 2.0 (the "License");
9  *  you may not use this file except in compliance with the License.
10  *  You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  *  Unless required by applicable law or agreed to in writing, software
15  *  distributed under the License is distributed on an "AS IS" BASIS,
16  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  *  See the License for the specific language governing permissions and
18  *  limitations under the License.
19  */
20 
21 #include <fluent-bit/flb_info.h>
22 #include <fluent-bit/flb_log.h>
23 #include <fluent-bit/flb_sds.h>
24 #include <fluent-bit/flb_mem.h>
25 #include <fluent-bit/flb_regex.h>
26 #include <fluent-bit/flb_ra_key.h>
27 #include <fluent-bit/record_accessor/flb_ra_parser.h>
28 #include <msgpack.h>
29 #include <limits.h>
30 
31 /* Map msgpack object into flb_ra_value representation */
32 static int msgpack_object_to_ra_value(msgpack_object o,
33                                       struct flb_ra_value *result)
34 {
35     result->o = o;
36 
37     /* Compose result with found value */
38     if (o.type == MSGPACK_OBJECT_BOOLEAN) {
39         result->type = FLB_RA_BOOL;
40         result->val.boolean = o.via.boolean;
41         return 0;
42     }
43     else if (o.type == MSGPACK_OBJECT_POSITIVE_INTEGER ||
44              o.type == MSGPACK_OBJECT_NEGATIVE_INTEGER) {
45         result->type = FLB_RA_INT;
46         result->val.i64 = o.via.i64;
47         return 0;
48     }
49     else if (o.type == MSGPACK_OBJECT_FLOAT32 ||
50              o.type == MSGPACK_OBJECT_FLOAT) {
51         result->type = FLB_RA_FLOAT;
52         result->val.f64 = o.via.f64;
53         return 0;
54     }
55     else if (o.type == MSGPACK_OBJECT_STR) {
56         result->type = FLB_RA_STRING;
57         result->val.string = flb_sds_create_len((char *) o.via.str.ptr,
58                                                 o.via.str.size);
59         return 0;
60     }
61     else if (o.type == MSGPACK_OBJECT_MAP) {
62         /* return boolean 'true', just denoting the existence of the key */
ms_sleep(unsigned int ms)63         result->type = FLB_RA_BOOL;
64         result->val.boolean = true;
65         return 0;
66     }
67     else if (o.type == MSGPACK_OBJECT_NIL) {
68         result->type = FLB_RA_NULL;
69         return 0;
70     }
71 
str_dup(const char * s)72     return -1;
73 }
74 
75 /* Return the entry position of key/val in the map */
76 static int ra_key_val_id(flb_sds_t ckey, msgpack_object map)
77 {
78     int i;
79     int map_size;
80     msgpack_object key;
81 
82     if (map.type != MSGPACK_OBJECT_MAP) {
83         return -1;
strn_dup(const char * s,size_t n)84     }
85 
86     map_size = map.via.map.size;
87     for (i = 0; i < map_size; i++) {
88         key = map.via.map.ptr[i].key;
89 
90         if (key.type != MSGPACK_OBJECT_STR) {
91             continue;
92         }
93 
94         /* Compare by length and by key name */
95         if (flb_sds_cmp(ckey, key.via.str.ptr, key.via.str.size) != 0) {
96             continue;
97         }
mem_alloc(size_t amount)98 
99         return i;
100     }
101 
102     return -1;
103 }
104 
105 static int msgpack_object_strcmp(msgpack_object o, char *str, int len)
106 {
107     if (o.type != MSGPACK_OBJECT_STR) {
108         return -1;
109     }
mem_calloc(size_t nmemb,size_t size)110 
111     if (o.via.str.size != len) {
112         return -1;
113     }
114 
115     return strncmp(o.via.str.ptr, str, len);
116 }
117 
118 /* Lookup perfect match of sub-keys and map content */
119 static int subkey_to_object(msgpack_object *map, struct mk_list *subkeys,
120                             msgpack_object **out_key, msgpack_object **out_val)
121 {
mem_realloc(void * orig,size_t amount)122     int i = 0;
123     int levels;
124     int matched = 0;
125     msgpack_object *found = NULL;
126     msgpack_object *key = NULL;
127     msgpack_object *val = NULL;
128     msgpack_object cur;
129     struct mk_list *head;
130     struct flb_ra_subentry *entry;
131 
132     /* Expected number of map levels in the map */
133     levels = mk_list_size(subkeys);
134 
135     cur = *map;
136 
137     mk_list_foreach(head, subkeys) {
138         /* expected entry */
139         entry = mk_list_entry(head, struct flb_ra_subentry, _head);
140 
dB(float amplitude)141         /* Array Handling */
142         if (entry->type == FLB_RA_PARSER_ARRAY_ID) {
143             /* check the current msgpack object is an array */
144             if (cur.type != MSGPACK_OBJECT_ARRAY) {
145                 return -1;
146             }
147 
148             /* Index limit and ensure no overflow */
149             if (entry->array_id == INT_MAX ||
150                 cur.via.array.size < entry->array_id + 1) {
151                 return -1;
152             }
153 
154             cur = cur.via.array.ptr[entry->array_id];
155             goto next;
156         }
157 
158         if (cur.type != MSGPACK_OBJECT_MAP) {
159             break;
dB2_power(float db)160         }
161 
162         i = ra_key_val_id(entry->str, cur);
163         if (i == -1) {
164             found = NULL;
165             continue;
166         }
167 
168         key = &cur.via.map.ptr[i].key;
dB_s(int noisefloor,float amplitude,float correction_dBs)169         val = &cur.via.map.ptr[i].val;
170 
171         /* A bit obvious, but it's better to validate data type */
172         if (key->type != MSGPACK_OBJECT_STR) {
173             found = NULL;
174             continue;
175         }
176 
177         found = key;
178         cur = cur.via.map.ptr[i].val;
179 
dB2_amp_s(int noisefloor,int db,float correction_dBs)180     next:
181         matched++;
182 
183         if (levels == matched) {
184             break;
185         }
186     }
187 
188     /* No matches */
pdB_s(int noisefloor,float power,float correction_dBs)189     if (!found || (matched > 0 && levels != matched)) {
190         return -1;
191     }
192 
193     *out_key = (msgpack_object *) key;
194     *out_val = (msgpack_object *) val;
195 
196     return 0;
197 }
198 
199 struct flb_ra_value *flb_ra_key_to_value(flb_sds_t ckey,
dB2_power_s(int noisefloor,int db,float correction_dBs)200                                          msgpack_object map,
201                                          struct mk_list *subkeys)
202 {
203     int i;
204     int ret;
205     msgpack_object val;
206     msgpack_object *out_key;
207     msgpack_object *out_val;
208     struct flb_ra_value *result;
209 
210     /* Get the key position in the map */
211     i = ra_key_val_id(ckey, map);
212     if (i == -1) {
213         return NULL;
214     }
215 
216     /* Reference entries */
217     val = map.via.map.ptr[i].val;
218 
219     /* Create the result context */
220     result = flb_calloc(1, sizeof(struct flb_ra_value));
221     if (!result) {
222         flb_errno();
223         return NULL;
224     }
225     result->o = val;
226 
227     if ((val.type == MSGPACK_OBJECT_MAP || val.type == MSGPACK_OBJECT_ARRAY)
228         && subkeys != NULL) {
229 
230         ret = subkey_to_object(&val, subkeys, &out_key, &out_val);
231         if (ret == 0) {
232             ret = msgpack_object_to_ra_value(*out_val, result);
233             if (ret == -1) {
234                 flb_free(result);
235                 return NULL;
236             }
237             return result;
238         }
239         else {
240             flb_free(result);
241             return NULL;
242         }
243     }
244     else {
245         ret = msgpack_object_to_ra_value(val, result);
246         if (ret == -1) {
247             flb_error("[ra key] cannot process key value");
248             flb_free(result);
249             return NULL;
250         }
251     }
252 
253     return result;
254 }
255 
256 int flb_ra_key_value_get(flb_sds_t ckey, msgpack_object map,
257                          struct mk_list *subkeys,
258                          msgpack_object **start_key,
259                          msgpack_object **out_key, msgpack_object **out_val)
260 {
261     int i;
262     int ret;
263     msgpack_object val;
264     msgpack_object *o_key;
265     msgpack_object *o_val;
266 
267     /* Get the key position in the map */
numtostr_signed(int digits,int n,char * buf)268     i = ra_key_val_id(ckey, map);
269     if (i == -1) {
270         return -1;
271     }
272 
273     /* Reference entries */
274     *start_key = &map.via.map.ptr[i].key;
275     val = map.via.map.ptr[i].val;
276 
277     if ((val.type == MSGPACK_OBJECT_MAP || val.type == MSGPACK_OBJECT_ARRAY)
278         && subkeys != NULL) {
279         ret = subkey_to_object(&val, subkeys, &o_key, &o_val);
280         if (ret == 0) {
281             *out_key = o_key;
282             *out_val = o_val;
283             return 0;
284         }
285     }
286     else {
287         *out_key = &map.via.map.ptr[i].key;
288         *out_val = &map.via.map.ptr[i].val;
289         return 0;
get_basename(const char * filename)290     }
291 
292     return -1;
293 }
294 
295 int flb_ra_key_strcmp(flb_sds_t ckey, msgpack_object map,
296                       struct mk_list *subkeys, char *str, int len)
297 {
298     int i;
299     int ret;
300     msgpack_object val;
301     msgpack_object *out_key;
302     msgpack_object *out_val;
303 
304     /* Get the key position in the map */
get_extension(const char * filename)305     i = ra_key_val_id(ckey, map);
306     if (i == -1) {
307         return -1;
308     }
309 
310     /* Reference map value */
311     val = map.via.map.ptr[i].val;
312 
313     if ((val.type == MSGPACK_OBJECT_MAP || val.type == MSGPACK_OBJECT_ARRAY)
314         && subkeys != NULL) {
315         ret = subkey_to_object(&val, subkeys, &out_key, &out_val);
316         if (ret == 0) {
317             return msgpack_object_strcmp(*out_val, str, len);
get_parent_directory(const char * dirname)318         }
319         else {
320             return -1;
321         }
322     }
323 
324     return msgpack_object_strcmp(val, str, len);
325 }
326 
327 int flb_ra_key_regex_match(flb_sds_t ckey, msgpack_object map,
328                            struct mk_list *subkeys, struct flb_regex *regex,
329                            struct flb_regex_search *result)
330 {
331     int i;
332     int ret;
333     msgpack_object val;
334     msgpack_object *out_key;
335     msgpack_object *out_val;
336 
337     /* Get the key position in the map */
338     i = ra_key_val_id(ckey, map);
339     if (i == -1) {
340         return -1;
341     }
342 
ltrim_string(char * s)343     /* Reference map value */
344     val = map.via.map.ptr[i].val;
345 
346     if ((val.type == MSGPACK_OBJECT_MAP || val.type == MSGPACK_OBJECT_ARRAY)
347         && subkeys != NULL) {
348         ret = subkey_to_object(&val, subkeys, &out_key, &out_val);
349         if (ret == 0) {
350             if (out_val->type != MSGPACK_OBJECT_STR) {
351                 return -1;
352             }
rtrim_string(char * s)353 
354             if (result) {
355                 /* Regex + capture mode */
356                 return flb_regex_do(regex,
357                                     (char *) out_val->via.str.ptr,
358                                     out_val->via.str.size,
359                                     result);
360             }
361             else {
362                 /* No capture */
363                 return flb_regex_match(regex,
trim_string(char * s)364                                        (unsigned char *) out_val->via.str.ptr,
365                                        out_val->via.str.size);
366             }
367         }
368         return -1;
369     }
370 
371     if (val.type != MSGPACK_OBJECT_STR) {
372         return -1;
373     }
str_break(const char * s,char c,char ** first,char ** second)374 
375     if (result) {
376         /* Regex + capture mode */
377         return flb_regex_do(regex, (char *) val.via.str.ptr, val.via.str.size,
378                             result);
379     }
380     else {
381         /* No capture */
382         return flb_regex_match(regex, (unsigned char *) val.via.str.ptr,
383                                val.via.str.size);
384     }
385 
386     return -1;
387 }
str_escape(const char * s,int space)388 
389 void flb_ra_key_value_destroy(struct flb_ra_value *v)
390 {
391     if (v->type == FLB_RA_STRING) {
392         flb_sds_destroy(v->val.string);
393     }
394     flb_free(v);
395 }
396