1 /* ------------------------------------------------
2 Copyright 2014 AT&T Intellectual Property
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
7 http://www.apache.org/licenses/LICENSE-2.0
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ------------------------------------------- */
16 #include <sys/types.h>
23 #include <stringhash.h>
31 #include <host_tuple.h>
37 #include <netinet/in.h>
39 #define MAX_PATTERN_LEN 1024
41 // Defined here to avoid link errors as this array is auto generated for the lfta and referenced in the clearinghouse library which gets linked against the hfta
42 extern "C" gs_sp_t fta_names[]={0};
45 // Only used to construct constant strings ...
46 gs_retval_t Vstring_Constructor(vstring *tmp, gs_csp_t str) {
47 tmp->length = strlen(str);
49 tmp->offset = (gs_p_t)strdup(str);
50 tmp->reserved = SHALLOW_COPY;
54 // Assume str is INTERNAL or SHALLOW_COPY.
55 void hfta_vstr_destroy(vstring * str) {
56 if (str->length && str->reserved == INTERNAL) {
57 free((gs_sp_t)str->offset);
62 // Make the vstring safe to destroy even if its never initialized
63 // (e.g. stack-allocated groups containing strings)
64 void hfta_vstr_init(vstring * str) {
68 gs_retval_t hfta_vstr_length(vstring *str) {
72 // Assume that SRC is either INTERNAL or SHALLOW_COPY
73 void hfta_vstr_assign_with_copy_in_tuple(vstring32 * target,
74 const vstring * src, gs_sp_t data_offset, gs_retval_t int_offset) {
75 target->length = src->length;
76 target->offset = int_offset;
77 target->reserved = PACKED;
79 memcpy(data_offset, (gs_sp_t)src->offset, src->length);
82 // Ted wrote the following function.
83 // make deep copy of src. Assume that dst is already empty.
84 // Assume that SRC is either INTERNAL or SHALLOW_COPY
85 void hfta_vstr_assign_with_copy(vstring *dst, const vstring *src){
86 dst->length=src->length;
88 dst->offset=(gs_p_t)malloc(dst->length);
89 memcpy((gs_sp_t)(dst->offset),(gs_sp_t)(src->offset),dst->length);
91 dst->reserved=INTERNAL;
94 // Ted wrote the following function.
95 // Make a deep copy of src. garbage collect dst if needed.
96 // Assume that SRC is either INTERNAL or SHALLOW_COPY
97 void hfta_vstr_replace(vstring *dst, const vstring *src){
98 hfta_vstr_destroy(dst);
99 hfta_vstr_assign_with_copy(dst,src);
102 #define HFTA_VSTR_LHASHFUNC_PRIME 12916008961267169387ull
103 gs_uint64_t hfta_vstr_long_hashfunc(const vstring *s) {
104 gs_uint64_t hash_code;
106 gs_int32_t substr_len;
108 gs_uint64_t sub_hash;
111 sv=(gs_sp_t)(s->offset);
113 n_steps = s->length / 4;
114 if(4*n_steps < s->length) n_steps++;
116 for (j = 0; j < n_steps; j++) {
117 if(4*(j+1) < s->length) substr_len = 4;
118 else substr_len = s->length - 4*j;
123 sub_hash = (sub_hash << 4) + *sv;
125 sub_hash = (sub_hash << 4);
129 hash_code = (sub_hash + hash_code * HFTA_VSTR_LHASHFUNC_PRIME);
135 #define HFTA_VSTR_HASHFUNC_PRIME 2995999
136 gs_uint32_t hfta_vstr_hashfunc(const vstring *s) {
137 gs_uint32_t hash_code;
139 gs_int32_t substr_len;
141 gs_uint32_t k, sub_hash;
144 sv=(gs_sp_t)(s->offset);
146 n_steps = s->length / 4;
147 if(4*n_steps < s->length) n_steps++;
149 for (j = 0; j < n_steps; j++) {
150 if(4*(j+1) < s->length) substr_len = 4;
151 else substr_len = s->length - 4*j;
156 sub_hash = (sub_hash << 4) + *sv;
158 sub_hash = (sub_hash << 4);
162 hash_code = (sub_hash + hash_code * HFTA_VSTR_HASHFUNC_PRIME);
169 // return negative if s1 < s2, 0 if s1==s2, positive if s1>s2
170 gs_retval_t hfta_vstr_compare(const vstring * s1, const vstring * s2) {
171 gs_int32_t minlen,cmp_ret;
172 minlen=(s1->length<s2->length?s1->length:s2->length);
173 cmp_ret=memcmp((void *)s1->offset,(void *)s2->offset,minlen);
175 if(cmp_ret) return cmp_ret;
176 return(s1->length - s2->length);
179 gs_retval_t hfta_vstr_equal(const vstring * s1, const vstring * s2) {
182 if(s1->length != s2->length)
185 // cmp_ret=memcmp((void *)s1->offset,(void *)s2->offset,s1->length);
186 for(x=0;x<s1->length;x++) {
187 if (((char *)(s1->offset))[x]!=((char *)(s2->offset))[x]) {
198 gs_param_handle_t register_handle_for_str_regex_match_slot_1(vstring* pattern) {
202 if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0) {
203 gslog(LOG_EMERG, "No memory for regular expression %s\n",
204 (gs_sp_t)(pattern->offset));
208 if (regcomp(reg,(char*)(pattern->offset), REG_NEWLINE|REG_EXTENDED|REG_NOSUB)!=0) {
209 gslog(LOG_EMERG, "Illegal regular expression %s\n",
210 (gs_sp_t)(pattern->offset));
213 return (gs_param_handle_t) reg;
216 gs_uint32_t str_regex_match(vstring* str, gs_param_handle_t pattern_handle) {
217 regex_t * reg = (regex_t *) pattern_handle ;
220 static gs_uint32_t dlen=0;
221 // grow our static buffer to the longest string we ever see
222 if ((str->length+1) >= dlen) {
223 if (d!=0) free((void*)d);
226 if ((d=(gs_sp_t)malloc(str->length+1))==0) return 0;
230 if (str->length==0) return 0;
232 // copy the string and 0 terminate it
233 memcpy((void *)d,(void *) str->offset, str->length);
237 res = regexec(reg, d, 0, NULL, 0);
238 return (res==REG_NOMATCH)?0:1;
241 gs_retval_t deregister_handle_for_str_regex_match_slot_1(gs_param_handle_t handle) {
242 regex_t * x = (regex_t *) handle;
248 gs_param_handle_t register_handle_for_str_partial_regex_match_slot_1(vstring* pattern) {
252 if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0) {
253 gslog(LOG_EMERG, "No memory for regular expression %s\n",
254 (gs_sp_t)(pattern->offset));
258 if (regcomp(reg,(gs_sp_t)(pattern->offset), REG_NEWLINE|REG_EXTENDED|REG_NOSUB)!=0) {
259 gslog(LOG_EMERG, "Illegal regular expression %s\n",
260 (gs_sp_t)(pattern->offset));
263 return (gs_param_handle_t) reg;
266 gs_uint32_t str_partial_regex_match(vstring* str, gs_param_handle_t pattern_handle,
268 regex_t * reg = (regex_t *) pattern_handle ;
272 static gs_uint32_t dlen=0;
273 // grow our static buffer to the longest string we ever see
274 if ((str->length+1) >= dlen) {
275 if (d!=0) free((void*)d);
278 if ((d=(gs_sp_t)malloc(str->length+1))==0) return 0;
282 if (str->length==0) return 0;
284 end=(maxlen>(str->length))?(str->length):maxlen;
286 // copy the string and 0 terminate it
287 memcpy((void *)d,(void *) str->offset, end);
291 res = regexec(reg, d,0, NULL, 0);
292 return (res==REG_NOMATCH)?0:1;
296 gs_retval_t deregister_handle_for_str_partial_regex_match_slot_1(
297 gs_param_handle_t handle) {
298 regex_t * x = (regex_t *) handle;
304 gs_param_handle_t register_handle_for_str_extract_regex_slot_1(vstring* pattern) {
307 if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0) {
308 gslog(LOG_EMERG, "No memory for regular expression %s\n",
309 (gs_sp_t)(pattern->offset));
312 if (regcomp(reg,(gs_sp_t)(pattern->offset), REG_EXTENDED)!=0) {
313 gslog(LOG_EMERG, "Illegal regular expression %s\n",
314 (gs_sp_t)(pattern->offset));
317 return (gs_param_handle_t) reg;
321 /* partial function return 0 if the value is valid */
322 gs_retval_t str_extract_regex( vstring * result, vstring * str, gs_param_handle_t handle) {
323 regex_t * reg = (regex_t *) handle ;
324 gs_sp_t source = (gs_sp_t)(str->offset);
328 static gs_uint32_t dlen=0;
329 // grow our static buffer to the longest string we ever see
330 if ((str->length+1) >= dlen) {
331 if (d!=0) free((void*)d);
334 if ((d=(gs_sp_t)malloc(str->length+1))==0) return 1;
338 if (str->length==0) return 1;
340 // copy the string and 0 terminate it
341 memcpy((void *)d,(void *) str->offset, str->length);
345 res = regexec(reg, d, 1, &match, 0);
346 if (res==REG_NOMATCH) return 1;
347 result->offset= (gs_p_t) &source[match.rm_so];
348 result->length=match.rm_eo-match.rm_so;
349 result->reserved = SHALLOW_COPY;
353 gs_retval_t deregister_handle_for_str_extract_regex_slot_1(gs_param_handle_t handle) {
354 regex_t * x = (regex_t *) handle;
360 // -------------------------------------------------
361 // More substring functions
363 // get last n bytes, if available
364 // getting the prefix is done by str_truncate, defined in the include file
365 gs_retval_t str_suffix(vstring *result, vstring *s, gs_uint32_t n){
366 register gs_p_t st = (gs_p_t)s->offset;
367 int prefix = (n > s->length) ? 0 : s->length-n;
368 result->offset = st + prefix;
369 result->length = s->length-prefix;
370 result->reserved = SHALLOW_COPY;
375 // Split the string on sep, get the i'th substring, if any
376 gs_retval_t get_list_entry(vstring *result, vstring *l, vstring *sep, gs_uint32_t pos){
380 result->offset = l->offset; // empty return string
381 result->reserved = SHALLOW_COPY;
384 if(sep->length > 0){ // get the sep char, ensure the string is nonempty
385 s = ((gs_sp_t)(sep->offset))[0];
390 for(c=0;c < l->length && pos>0; ++c){
391 if(((gs_sp_t)(l->offset))[c] == s){
396 if(pos>0 || c >= l->length-1){ // not enough seps, or final string is empty
400 result->offset = l->offset + c;
401 for(; c<l->length && ((gs_sp_t)(l->offset))[c] != s; ++c, ++result->length);
407 // -------------------------------------------------
409 static gs_uint32_t nextint(struct vstring *str , gs_uint32_t * offset, gs_uint32_t *res) {
410 gs_uint8_t * s = (gs_uint8_t *)(str->offset);
413 while(*offset<str->length) {
414 if ((s[*offset]>='0') && (s[*offset]<='9')) {
416 *res= (*res*10) + (gs_uint32_t) (s[*offset]-'0');
418 if (v!=0) { // got some valid result
420 } // otherwise skip leading grabage
428 gs_uint32_t strtoi(gs_uint32_t * r, struct vstring * s)
432 if (nextint(s,&offset,r)==0) return 1;
436 gs_param_handle_t register_handle_for_strtoi_c_slot_0(vstring* istr) {
437 gs_uint32_t offset,r;
439 if (nextint(istr,&offset,&r)!=0)
440 return (gs_param_handle_t) r;
441 return (gs_param_handle_t) 0;
443 gs_retval_t deregister_handle_for_strtoi_c_slot_0(gs_param_handle_t h) {
448 gs_uint32_t strtoip(gs_uint32_t * r, struct vstring * s)
450 gs_uint32_t ip1,ip2,ip3,ip4,offset;
452 if (nextint(s,&offset,&ip1)==0) return 1;
453 //fprintf (stderr, "1 %u %u\n",ip1,offset);
454 if (nextint(s,&offset,&ip2)==0) return 1;
455 //fprintf (stderr, "2 %u %u\n",ip2,offset);
456 if (nextint(s,&offset,&ip3)==0) return 1;
457 //fprintf (stderr, "3 %u %u\n",ip3,offset);
458 if (nextint(s,&offset,&ip4)==0) return 1;
459 //fprintf (stderr, "4 %u %u\n",ip4,offset);
460 *r=ip1<<24|ip2<<16|ip3<<8|ip4;
464 gs_param_handle_t register_handle_for_strtoip_c_slot_0(vstring* istr) {
465 gs_uint32_t ip1,ip2,ip3,ip4,offset,r;
467 if (nextint(istr,&offset,&ip1)==0) return (gs_param_handle_t)0;
468 if (nextint(istr,&offset,&ip2)==0) return (gs_param_handle_t)0;
469 if (nextint(istr,&offset,&ip3)==0) return (gs_param_handle_t)0;
470 if (nextint(istr,&offset,&ip4)==0) return (gs_param_handle_t)0;
471 r=ip1<<24|ip2<<16|ip3<<8|ip4;
472 return (gs_param_handle_t)r;
474 gs_retval_t deregister_handle_for_strtoip_c_slot_0(gs_param_handle_t h) {
478 gs_uint32_t partn_hash( gs_uint32_t ip1, gs_uint32_t ip2) {
482 gs_uint32_t rand_hash() {
486 ///////////////////////////////////////
488 // return negative if s1 < s2, 0 if s1==s2, positive if s1>s2
489 gs_retval_t hfta_ipv6_compare(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2) {
490 if(i1.v[0] > i2.v[0])
492 if(i1.v[0] < i2.v[0])
494 if(i1.v[1] > i2.v[1])
496 if(i1.v[1] < i2.v[1])
498 if(i1.v[2] > i2.v[2])
500 if(i1.v[2] < i2.v[2])
502 if(i1.v[3] > i2.v[3])
504 if(i1.v[3] < i2.v[3])
510 hfta_ipv6_str And_Ipv6(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2){
512 ret.v[0] = i1.v[0] & i2.v[0];
513 ret.v[1] = i1.v[1] & i2.v[1];
514 ret.v[2] = i1.v[2] & i2.v[2];
515 ret.v[3] = i1.v[3] & i2.v[3];
519 hfta_ipv6_str Or_Ipv6(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2){
521 ret.v[0] = i1.v[0] | i2.v[0];
522 ret.v[1] = i1.v[1] | i2.v[1];
523 ret.v[2] = i1.v[2] | i2.v[2];
524 ret.v[3] = i1.v[3] | i2.v[3];
528 gs_uint32_t hfta_ipv6_hashfunc(const hfta_ipv6_str *s) {
529 return s->v[0] ^ s->v[1] ^ s->v[2] ^ s->v[3];
532 hfta_ipv6_str hton_ipv6(hfta_ipv6_str s){
535 // ret.v[0] = htonl(s.v[0]);
536 // ret.v[1] = htonl(s.v[1]);
537 // ret.v[2] = htonl(s.v[2]);
538 // ret.v[3] = htonl(s.v[3]);
546 hfta_ipv6_str ntoh_ipv6(hfta_ipv6_str s){
548 // ret.v[0] = ntohl(s.v[0]);
549 // ret.v[1] = ntohl(s.v[1]);
550 // ret.v[2] = ntohl(s.v[2]);
551 // ret.v[3] = ntohl(s.v[3]);
559 int HFTA_Ipv6_Constructor(hfta_ipv6_str *s, gs_csp_t l) {
560 gs_uint32_t i0=0,i1=0,i2=0,i3=0,i4=0,i5=0,i6=0,i7=0;
561 sscanf(l,"%x:%x:%x:%x:%x:%x:%x:%x",&i0,&i1,&i2,&i3,&i4,&i5,&i6,&i7);
562 s->v[0] = ((i0 & 0xffff) << 16) | (i1 & 0xffff);
563 s->v[1] = ((i2 & 0xffff) << 16) | (i3 & 0xffff);
564 s->v[2] = ((i4 & 0xffff) << 16) | (i5 & 0xffff);
565 s->v[3] = ((i6 & 0xffff) << 16) | (i7 & 0xffff);
569 gs_retval_t str_exists_substr(vstring * s1,vstring * s2)
571 gs_uint8_t *st1 = (gs_uint8_t *)s1->offset;
572 gs_uint8_t *st2 = (gs_uint8_t *)s2->offset;
573 gs_uint8_t *s2f = (gs_uint8_t *)s2->offset;
574 gs_uint8_t len1 = s1->length-s2->length;
575 gs_uint8_t len2 = s2->length;
578 for (x=0; x<len1 ; x++)
582 for (y=0; y<len2 && st1[x+y]==st2[y];y++);
590 gs_retval_t str_compare(vstring *s1,vstring *s2)
592 return hfta_vstr_compare(s1,s2);
595 gs_uint32_t str_match_offset( gs_uint32_t offset, vstring *s1, vstring *s2)
597 gs_uint8_t *st1 = (gs_uint8_t *)s1->offset;
598 gs_uint8_t *st2 = &(((gs_uint8_t *)s2->offset)[offset]);
600 gs_int32_t len2 = s2->length-offset;
601 gs_int32_t len1 = s1->length;
606 for(x = 0; x < len1; x++)
608 if (st1[x] != st2[x])
614 gs_uint32_t byte_match_offset( gs_uint32_t offset, gs_uint32_t val,vstring *s2)
616 gs_uint8_t *st2 = (gs_uint8_t *)s2->offset;
617 gs_uint8_t v = (unsigned char) val;
619 // if ((s2->length <= offset)||(offset<0))
620 if (s2->length <= offset)
623 return (st2[offset]==v)?1:0;
627 // -------------------------------------------------------
628 // map_int_to_string and its support functions, structs
630 struct int_to_string_map_struct{
631 std::map<gs_int64_t, vstring> i2s_map;
633 vstring empty_string;
636 gs_param_handle_t register_handle_for_int_to_string_map_slot_1(vstring *filename){
637 int_to_string_map_struct *map_struct;
639 map_struct = new int_to_string_map_struct();
640 if(map_struct == NULL){
641 gslog(LOG_EMERG, "int_to_string_map:: Could not allocate handle memory\n");
645 map_struct->empty_string.offset = (gs_p_t)malloc(1);
646 map_struct->empty_string.reserved = INTERNAL;
647 map_struct->empty_string.length = 0;
650 filenamec = (gs_sp_t)alloca(filename->length+1);
652 gslog(LOG_EMERG, "int_to_string_map:: Could not allocate filename memory\n");
655 memcpy(filenamec,(gs_sp_t)filename->offset,filename->length);
656 filenamec[filename->length]=0;
657 map_struct->fname = filenamec;
659 FILE *fl = fopen(filenamec, "r");
661 gslog(LOG_EMERG, "int_to_string_map:: Could not open regex file %s \n",filename);
665 gs_int32_t buflen = 10000;
666 char buf[buflen], buf_str[buflen];
669 fret = fgets(buf, buflen, fl);
671 int nvals = sscanf(buf, "%lld,%s", &val, buf_str);
674 new_str.reserved = SHALLOW_COPY;
675 new_str.length = strlen(buf_str);
676 new_str.offset = (gs_p_t)malloc(new_str.length);
677 memcpy((char *)new_str.offset, buf_str, new_str.length);
678 map_struct->i2s_map[val] = new_str;
680 fret = fgets(buf, buflen, fl);
685 return (gs_param_handle_t) map_struct;
688 gs_retval_t int_to_string_map(vstring *result, gs_int64_t val, gs_param_handle_t handle){
689 int_to_string_map_struct *map_struct = (int_to_string_map_struct *)handle;
690 if(map_struct->i2s_map.count(val)>0){
691 vstring ret = map_struct->i2s_map[val];
692 result->offset = ret.offset;
693 result->reserved = ret.reserved;
694 result->length = ret.length;
696 result->offset = map_struct->empty_string.offset;
697 result->reserved = map_struct->empty_string.reserved;
698 result->length = map_struct->empty_string.length;
704 gs_param_handle_t deregister_handle_for_int_to_string_map_slot_1(gs_param_handle_t handle){
705 int_to_string_map_struct *map_struct = (int_to_string_map_struct *)handle;
706 for(std::map<gs_int64_t, vstring>::iterator i2si = map_struct->i2s_map.begin(); i2si!=map_struct->i2s_map.end(); ++i2si){
707 free((void *)((*i2si).second.offset));
709 free((void *)(map_struct->empty_string.offset));
713 // ---------------------------------------------------
714 // Return a (binary, non-ascii) string in its hex representation
716 static char hexmap[16] = {
717 '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
720 gs_retval_t to_hex_string(vstring *result, vstring *val){
721 result->length = 2*(val->length);
722 result->offset = (gs_p_t)malloc(result->length);
723 result->reserved = INTERNAL;
724 unsigned char *rs = (unsigned char *)(result->offset);
725 unsigned char *vs = (unsigned char *)(val->offset);
727 for(int c=0;c<val->length; ++c){
728 rs[2*c] = hexmap[vs[c] >> 4];
729 rs[2*c+1] = hexmap[vs[c] & 0x0f];
736 // ---------------------------------------------
737 // sum up unsigned integers expressed as a string with separators,
738 // e.g. on input '34|45|56' and sep '|', return 135.
739 // This kind of thing is common in Nokia PCMD data.
740 // gracefully handle empty entries, e.g. '|8|' should return 8
741 gs_int64_t sum_uint_in_list(struct vstring *list, struct vstring *sepchar){
748 if(sepchar->length < 1)
750 sep = ((char *)(sepchar->offset))[0];
752 for(c=0;c<list->length;++c){
753 v = ((char *)(list->offset))[c];
758 val = 10*val + (v>='0' && v<='9')*(v-'0');
765 // Convert an string to an integer
766 gs_int64_t to_llong(vstring *v){
774 d = ((char *)(v->offset))[0];
778 ret = (d>='0' && d<='9')*(d-'0');
781 for(c=1;c<v->length;++c){
782 d = ((char *)(v->offset))[c];
783 ret = 10*ret+(d>='0' && d<='9')*(d-'0');