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);
63 gs_retval_t hfta_vstr_length(vstring *str) {
67 // Assume that SRC is either INTERNAL or SHALLOW_COPY
68 void hfta_vstr_assign_with_copy_in_tuple(vstring32 * target, vstring * src,
69 gs_sp_t data_offset, gs_retval_t int_offset) {
70 target->length = src->length;
71 target->offset = int_offset;
72 target->reserved = PACKED;
74 memcpy(data_offset, (gs_sp_t)src->offset, src->length);
77 // Ted wrote the following function.
78 // make deep copy of src. Assume that dst is already empty.
79 // Assume that SRC is either INTERNAL or SHALLOW_COPY
80 void hfta_vstr_assign_with_copy(vstring *dst, vstring *src){
81 dst->length=src->length;
83 dst->offset=(gs_p_t)malloc(dst->length);
84 memcpy((gs_sp_t)(dst->offset),(gs_sp_t)(src->offset),dst->length);
86 dst->reserved=INTERNAL;
89 // Ted wrote the following function.
90 // Make a deep copy of src. garbage collect dst if needed.
91 // Assume that SRC is either INTERNAL or SHALLOW_COPY
92 void hfta_vstr_replace(vstring *dst, vstring *src){
93 hfta_vstr_destroy(dst);
94 hfta_vstr_assign_with_copy(dst,src);
97 #define HFTA_VSTR_LHASHFUNC_PRIME 12916008961267169387ull
98 gs_uint64_t hfta_vstr_long_hashfunc(const vstring *s) {
99 gs_uint64_t hash_code;
101 gs_int32_t substr_len;
103 gs_uint64_t sub_hash;
106 sv=(gs_sp_t)(s->offset);
108 n_steps = s->length / 4;
109 if(4*n_steps < s->length) n_steps++;
111 for (j = 0; j < n_steps; j++) {
112 if(4*(j+1) < s->length) substr_len = 4;
113 else substr_len = s->length - 4*j;
118 sub_hash = (sub_hash << 4) + *sv;
120 sub_hash = (sub_hash << 4);
124 hash_code = (sub_hash + hash_code * HFTA_VSTR_LHASHFUNC_PRIME);
130 #define HFTA_VSTR_HASHFUNC_PRIME 2995999
131 gs_uint32_t hfta_vstr_hashfunc(const vstring *s) {
132 gs_uint32_t hash_code;
134 gs_int32_t substr_len;
136 gs_uint32_t k, sub_hash;
139 sv=(gs_sp_t)(s->offset);
141 n_steps = s->length / 4;
142 if(4*n_steps < s->length) n_steps++;
144 for (j = 0; j < n_steps; j++) {
145 if(4*(j+1) < s->length) substr_len = 4;
146 else substr_len = s->length - 4*j;
151 sub_hash = (sub_hash << 4) + *sv;
153 sub_hash = (sub_hash << 4);
157 hash_code = (sub_hash + hash_code * HFTA_VSTR_HASHFUNC_PRIME);
164 // return negative if s1 < s2, 0 if s1==s2, positive if s1>s2
165 gs_retval_t hfta_vstr_compare(const vstring * s1, const vstring * s2) {
166 gs_int32_t minlen,cmp_ret;
167 minlen=(s1->length<s2->length?s1->length:s2->length);
168 cmp_ret=memcmp((void *)s1->offset,(void *)s2->offset,minlen);
170 if(cmp_ret) return cmp_ret;
171 return(s1->length - s2->length);
176 gs_param_handle_t register_handle_for_str_regex_match_slot_1(vstring* pattern) {
180 if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0) {
181 gslog(LOG_EMERG, "No memory for regular expression %s\n",
182 (gs_sp_t)(pattern->offset));
186 if (regcomp(reg,(char*)(pattern->offset), REG_NEWLINE|REG_EXTENDED|REG_NOSUB)!=0) {
187 gslog(LOG_EMERG, "Illegal regular expression %s\n",
188 (gs_sp_t)(pattern->offset));
191 return (gs_param_handle_t) reg;
194 gs_uint32_t str_regex_match(vstring* str, gs_param_handle_t pattern_handle) {
195 regex_t * reg = (regex_t *) pattern_handle ;
198 static gs_uint32_t dlen=0;
199 // grow our static buffer to the longest string we ever see
200 if ((str->length+1) >= dlen) {
201 if (d!=0) free((void*)d);
204 if ((d=(gs_sp_t)malloc(str->length+1))==0) return 0;
208 if (str->length==0) return 0;
210 // copy the string and 0 terminate it
211 memcpy((void *)d,(void *) str->offset, str->length);
215 res = regexec(reg, d, 0, NULL, 0);
216 return (res==REG_NOMATCH)?0:1;
219 gs_retval_t deregister_handle_for_str_regex_match_slot_1(gs_param_handle_t handle) {
220 regex_t * x = (regex_t *) handle;
226 gs_param_handle_t register_handle_for_str_partial_regex_match_slot_1(vstring* pattern) {
230 if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0) {
231 gslog(LOG_EMERG, "No memory for regular expression %s\n",
232 (gs_sp_t)(pattern->offset));
236 if (regcomp(reg,(gs_sp_t)(pattern->offset), REG_NEWLINE|REG_EXTENDED|REG_NOSUB)!=0) {
237 gslog(LOG_EMERG, "Illegal regular expression %s\n",
238 (gs_sp_t)(pattern->offset));
241 return (gs_param_handle_t) reg;
244 gs_uint32_t str_partial_regex_match(vstring* str, gs_param_handle_t pattern_handle,
246 regex_t * reg = (regex_t *) pattern_handle ;
250 static gs_uint32_t dlen=0;
251 // grow our static buffer to the longest string we ever see
252 if ((str->length+1) >= dlen) {
253 if (d!=0) free((void*)d);
256 if ((d=(gs_sp_t)malloc(str->length+1))==0) return 0;
260 if (str->length==0) return 0;
262 end=(maxlen>(str->length))?(str->length):maxlen;
264 // copy the string and 0 terminate it
265 memcpy((void *)d,(void *) str->offset, end);
269 res = regexec(reg, d,0, NULL, 0);
270 return (res==REG_NOMATCH)?0:1;
274 gs_retval_t deregister_handle_for_str_partial_regex_match_slot_1(
275 gs_param_handle_t handle) {
276 regex_t * x = (regex_t *) handle;
282 gs_param_handle_t register_handle_for_str_extract_regex_slot_1(vstring* pattern) {
285 if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0) {
286 gslog(LOG_EMERG, "No memory for regular expression %s\n",
287 (gs_sp_t)(pattern->offset));
290 if (regcomp(reg,(gs_sp_t)(pattern->offset), REG_EXTENDED)!=0) {
291 gslog(LOG_EMERG, "Illegal regular expression %s\n",
292 (gs_sp_t)(pattern->offset));
295 return (gs_param_handle_t) reg;
299 /* partial function return 0 if the value is valid */
300 gs_retval_t str_extract_regex( vstring * result, vstring * str, gs_param_handle_t handle) {
301 regex_t * reg = (regex_t *) handle ;
302 gs_sp_t source = (gs_sp_t)(str->offset);
306 static gs_uint32_t dlen=0;
307 // grow our static buffer to the longest string we ever see
308 if ((str->length+1) >= dlen) {
309 if (d!=0) free((void*)d);
312 if ((d=(gs_sp_t)malloc(str->length+1))==0) return 1;
316 if (str->length==0) return 1;
318 // copy the string and 0 terminate it
319 memcpy((void *)d,(void *) str->offset, str->length);
323 res = regexec(reg, d, 1, &match, 0);
324 if (res==REG_NOMATCH) return 1;
325 result->offset= (gs_p_t) &source[match.rm_so];
326 result->length=match.rm_eo-match.rm_so;
327 result->reserved = SHALLOW_COPY;
331 gs_retval_t deregister_handle_for_str_extract_regex_slot_1(gs_param_handle_t handle) {
332 regex_t * x = (regex_t *) handle;
339 static gs_uint32_t nextint(struct vstring *str , gs_uint32_t * offset, gs_uint32_t *res) {
340 gs_uint8_t * s = (gs_uint8_t *)(str->offset);
343 while(*offset<str->length) {
344 if ((s[*offset]>='0') && (s[*offset]<='9')) {
346 *res= (*res*10) + (gs_uint32_t) (s[*offset]-'0');
348 if (v!=0) { // got some valid result
350 } // otherwise skip leading grabage
357 gs_uint32_t strtoi(gs_uint32_t * r, struct vstring * s)
361 if (nextint(s,&offset,r)==0) return 1;
365 gs_param_handle_t register_handle_for_strtoi_c_slot_0(vstring* istr) {
366 gs_uint32_t offset,r;
368 if (nextint(istr,&offset,&r)!=0)
369 return (gs_param_handle_t) r;
370 return (gs_param_handle_t) 0;
372 gs_retval_t deregister_handle_for_strtoi_c_slot_0(gs_param_handle_t h) {
377 gs_uint32_t strtoip(gs_uint32_t * r, struct vstring * s)
379 gs_uint32_t ip1,ip2,ip3,ip4,offset;
381 if (nextint(s,&offset,&ip1)==0) return 1;
382 //fprintf (stderr, "1 %u %u\n",ip1,offset);
383 if (nextint(s,&offset,&ip2)==0) return 1;
384 //fprintf (stderr, "2 %u %u\n",ip2,offset);
385 if (nextint(s,&offset,&ip3)==0) return 1;
386 //fprintf (stderr, "3 %u %u\n",ip3,offset);
387 if (nextint(s,&offset,&ip4)==0) return 1;
388 //fprintf (stderr, "4 %u %u\n",ip4,offset);
389 *r=ip1<<24|ip2<<16|ip3<<8|ip4;
393 gs_param_handle_t register_handle_for_strtoip_c_slot_0(vstring* istr) {
394 gs_uint32_t ip1,ip2,ip3,ip4,offset,r;
396 if (nextint(istr,&offset,&ip1)==0) return (gs_param_handle_t)0;
397 if (nextint(istr,&offset,&ip2)==0) return (gs_param_handle_t)0;
398 if (nextint(istr,&offset,&ip3)==0) return (gs_param_handle_t)0;
399 if (nextint(istr,&offset,&ip4)==0) return (gs_param_handle_t)0;
400 r=ip1<<24|ip2<<16|ip3<<8|ip4;
401 return (gs_param_handle_t)r;
403 gs_retval_t deregister_handle_for_strtoip_c_slot_0(gs_param_handle_t h) {
407 gs_uint32_t partn_hash( gs_uint32_t ip1, gs_uint32_t ip2) {
411 gs_uint32_t rand_hash() {
415 ///////////////////////////////////////
417 // return negative if s1 < s2, 0 if s1==s2, positive if s1>s2
418 gs_retval_t hfta_ipv6_compare(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2) {
419 if(i1.v[0] > i2.v[0])
421 if(i1.v[0] < i2.v[0])
423 if(i1.v[1] > i2.v[1])
425 if(i1.v[1] < i2.v[1])
427 if(i1.v[2] > i2.v[2])
429 if(i1.v[2] < i2.v[2])
431 if(i1.v[3] > i2.v[3])
433 if(i1.v[3] < i2.v[3])
439 hfta_ipv6_str And_Ipv6(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2){
441 ret.v[0] = i1.v[0] & i2.v[0];
442 ret.v[1] = i1.v[1] & i2.v[1];
443 ret.v[2] = i1.v[2] & i2.v[2];
444 ret.v[3] = i1.v[3] & i2.v[3];
448 hfta_ipv6_str Or_Ipv6(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2){
450 ret.v[0] = i1.v[0] | i2.v[0];
451 ret.v[1] = i1.v[1] | i2.v[1];
452 ret.v[2] = i1.v[2] | i2.v[2];
453 ret.v[3] = i1.v[3] | i2.v[3];
457 gs_uint32_t hfta_ipv6_hashfunc(const hfta_ipv6_str *s) {
458 return s->v[0] ^ s->v[1] ^ s->v[2] ^ s->v[3];
461 hfta_ipv6_str hton_ipv6(hfta_ipv6_str s){
464 // ret.v[0] = htonl(s.v[0]);
465 // ret.v[1] = htonl(s.v[1]);
466 // ret.v[2] = htonl(s.v[2]);
467 // ret.v[3] = htonl(s.v[3]);
475 hfta_ipv6_str ntoh_ipv6(hfta_ipv6_str s){
477 // ret.v[0] = ntohl(s.v[0]);
478 // ret.v[1] = ntohl(s.v[1]);
479 // ret.v[2] = ntohl(s.v[2]);
480 // ret.v[3] = ntohl(s.v[3]);
488 int HFTA_Ipv6_Constructor(hfta_ipv6_str *s, gs_csp_t l) {
489 gs_uint32_t i0=0,i1=0,i2=0,i3=0,i4=0,i5=0,i6=0,i7=0;
490 sscanf(l,"%x:%x:%x:%x:%x:%x:%x:%x",&i0,&i1,&i2,&i3,&i4,&i5,&i6,&i7);
491 s->v[0] = ((i0 & 0xffff) << 16) | (i1 & 0xffff);
492 s->v[1] = ((i2 & 0xffff) << 16) | (i3 & 0xffff);
493 s->v[2] = ((i4 & 0xffff) << 16) | (i5 & 0xffff);
494 s->v[3] = ((i6 & 0xffff) << 16) | (i7 & 0xffff);
498 gs_retval_t str_exists_substr(vstring * s1,vstring * s2)
500 gs_uint8_t *st1 = (gs_uint8_t *)s1->offset;
501 gs_uint8_t *st2 = (gs_uint8_t *)s2->offset;
502 gs_uint8_t *s2f = (gs_uint8_t *)s2->offset;
503 gs_uint8_t len1 = s1->length-s2->length;
504 gs_uint8_t len2 = s2->length;
507 for (x=0; x<len1 ; x++)
511 for (y=0; y<len2 && st1[x+y]==st2[y];y++);
519 gs_retval_t str_compare(vstring *s1,vstring *s2)
521 return hfta_vstr_compare(s1,s2);
524 gs_uint32_t str_match_offset( gs_uint32_t offset, vstring *s1, vstring *s2)
526 gs_uint8_t *st1 = (gs_uint8_t *)s1->offset;
527 gs_uint8_t *st2 = &(((gs_uint8_t *)s2->offset)[offset]);
529 gs_int32_t len2 = s2->length-offset;
530 gs_int32_t len1 = s1->length;
535 for(x = 0; x < len1; x++)
537 if (st1[x] != st2[x])
543 gs_uint32_t byte_match_offset( gs_uint32_t offset, gs_uint32_t val,vstring *s2)
545 gs_uint8_t *st2 = (gs_uint8_t *)s2->offset;
546 gs_uint8_t v = (unsigned char) val;
548 // if ((s2->length <= offset)||(offset<0))
549 if (s2->length <= offset)
552 return (st2[offset]==v)?1:0;
556 // -------------------------------------------------------
557 // map_int_to_string and its support functions, structs
559 struct int_to_string_map_struct{
560 std::map<gs_int64_t, vstring> i2s_map;
562 vstring empty_string;
565 gs_param_handle_t register_handle_for_int_to_string_map_slot_1(vstring *filename){
566 int_to_string_map_struct *map_struct;
568 map_struct = new int_to_string_map_struct();
569 if(map_struct == NULL){
570 gslog(LOG_EMERG, "int_to_string_map:: Could not allocate handle memory\n");
574 map_struct->empty_string.offset = (gs_p_t)malloc(1);
575 map_struct->empty_string.reserved = INTERNAL;
576 map_struct->empty_string.length = 0;
579 filenamec = (gs_sp_t)alloca(filename->length+1);
581 gslog(LOG_EMERG, "int_to_string_map:: Could not allocate filename memory\n");
584 memcpy(filenamec,(gs_sp_t)filename->offset,filename->length);
585 filenamec[filename->length]=0;
586 map_struct->fname = filenamec;
588 FILE *fl = fopen(filenamec, "r");
590 gslog(LOG_EMERG, "int_to_string_map:: Could not open regex file %s \n",filename);
594 gs_int32_t buflen = 10000;
595 char buf[buflen], buf_str[buflen];
598 fret = fgets(buf, buflen, fl);
600 int nvals = sscanf(buf, "%lld,%s", &val, buf_str);
603 new_str.reserved = SHALLOW_COPY;
604 new_str.length = strlen(buf_str);
605 new_str.offset = (gs_p_t)malloc(new_str.length);
606 memcpy((char *)new_str.offset, buf_str, new_str.length);
607 map_struct->i2s_map[val] = new_str;
609 fret = fgets(buf, buflen, fl);
614 return (gs_param_handle_t) map_struct;
617 gs_retval_t int_to_string_map(vstring *result, gs_int64_t val, gs_param_handle_t handle){
618 int_to_string_map_struct *map_struct = (int_to_string_map_struct *)handle;
619 if(map_struct->i2s_map.count(val)>0){
620 vstring ret = map_struct->i2s_map[val];
621 result->offset = ret.offset;
622 result->reserved = ret.reserved;
623 result->length = ret.length;
625 result->offset = map_struct->empty_string.offset;
626 result->reserved = map_struct->empty_string.reserved;
627 result->length = map_struct->empty_string.length;
633 gs_param_handle_t deregister_handle_for_int_to_string_map_slot_1(gs_param_handle_t handle){
634 int_to_string_map_struct *map_struct = (int_to_string_map_struct *)handle;
635 for(std::map<gs_int64_t, vstring>::iterator i2si = map_struct->i2s_map.begin(); i2si!=map_struct->i2s_map.end(); ++i2si){
636 free((void *)((*i2si).second.offset));
638 free((void *)(map_struct->empty_string.offset));