ab94a0137d85cbd7b101787b2b51783f779fc089
[com/gs-lite.git] / src / lib / gscphftaaux / hfta_runtime_library.cc
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
6
7      http://www.apache.org/licenses/LICENSE-2.0
8
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  ------------------------------------------- */
15
16 #include <sys/types.h>
17 #include <iostream>
18 extern "C" {
19 #include "gsconfig.h"
20 #include "gstypes.h"
21 #include <regex.h>
22 #include <rdtsc.h>
23 #include <stringhash.h>
24 #include <errno.h>
25 #include <unistd.h>
26 }
27 #include <stdio.h>
28 #include <string.h>
29
30 #include <vstring.h>
31 #include <host_tuple.h>
32 #include <fta.h>
33
34 // for htonl,ntohl
35 #include <netinet/in.h>
36
37 #define MAX_PATTERN_LEN 1024
38
39 // 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
40 extern "C" gs_sp_t fta_names[]={0};
41
42
43 //              Only used to construct constant strings ...
44 gs_retval_t Vstring_Constructor(vstring *tmp, gs_csp_t str) {
45         tmp->length = strlen(str);
46         if(tmp->length)
47                 tmp->offset = (gs_p_t)strdup(str);
48         tmp->reserved = SHALLOW_COPY;
49         return 0;
50 }
51
52 //              Assume str is INTERNAL or SHALLOW_COPY.
53 void hfta_vstr_destroy(vstring * str) {
54         if (str->length && str->reserved == INTERNAL) {
55                 free((gs_sp_t)str->offset);
56         }
57         str->length = 0;
58 }
59
60
61 gs_retval_t hfta_vstr_length(vstring *str) {
62         return str->length;
63 }
64
65 //              Assume that SRC is either INTERNAL or SHALLOW_COPY
66 void hfta_vstr_assign_with_copy_in_tuple(vstring32 * target, vstring * src,
67         gs_sp_t data_offset,  gs_retval_t int_offset) {
68         target->length = src->length;
69         target->offset = int_offset;
70         target->reserved = PACKED;
71         if ( src->length)
72                 memcpy(data_offset, (gs_sp_t)src->offset, src->length);
73 }
74
75 //              Ted wrote the following function.
76 //              make deep copy of src.  Assume that dst is already empty.
77 //              Assume that SRC is either INTERNAL or SHALLOW_COPY
78 void hfta_vstr_assign_with_copy(vstring *dst, vstring *src){
79         dst->length=src->length;
80         if(src->length){
81                 dst->offset=(gs_p_t)malloc(dst->length);
82                 memcpy((gs_sp_t)(dst->offset),(gs_sp_t)(src->offset),dst->length);
83         }
84         dst->reserved=INTERNAL;
85 }
86
87 //              Ted wrote the following function.
88 //              Make a deep copy of src.  garbage collect dst if needed.
89 //              Assume that SRC is either INTERNAL or SHALLOW_COPY
90 void hfta_vstr_replace(vstring *dst, vstring *src){
91         hfta_vstr_destroy(dst);
92         hfta_vstr_assign_with_copy(dst,src);
93 }
94
95 #define HFTA_VSTR_HASHFUNC_PRIME 2995999
96 gs_uint32_t hfta_vstr_hashfunc(const vstring *s) {
97         gs_uint32_t hash_code;
98         gs_int32_t n_steps;
99         gs_int32_t substr_len;
100         gs_int32_t j;
101         gs_uint32_t k, sub_hash;
102         gs_sp_t sv;
103
104
105         sv=(gs_sp_t)(s->offset);
106         hash_code = 0;
107         n_steps = s->length / 4;
108         if(4*n_steps < s->length) n_steps++;
109
110         for (j = 0; j <  n_steps; j++) {
111                 if(4*(j+1) < s->length) substr_len = 4;
112                 else                  substr_len = s->length - 4*j;
113
114                 sub_hash = 0;
115                 for(k=0;k<4;k++){
116                   if(k < substr_len)
117                         sub_hash = (sub_hash << 4) + *sv;
118                   else
119                         sub_hash = (sub_hash << 4);
120                   sv++;
121                 }
122
123                 hash_code = (sub_hash + hash_code * HFTA_VSTR_HASHFUNC_PRIME);
124         }
125
126         return(hash_code);
127 }
128
129 //      return negative if s1 < s2, 0 if s1==s2, positive if s1>s2
130 gs_retval_t hfta_vstr_compare(const vstring * s1, const vstring * s2) {
131         gs_int32_t minlen,cmp_ret;
132         minlen=(s1->length<s2->length?s1->length:s2->length);
133         cmp_ret=memcmp((void *)s1->offset,(void *)s2->offset,minlen);
134
135         if(cmp_ret) return cmp_ret;
136         return(s1->length - s2->length);
137 }
138
139
140
141 gs_param_handle_t register_handle_for_str_regex_match_slot_1(vstring* pattern) {
142     regex_t * reg;
143     gs_int32_t res;
144
145     if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0)  {
146         gslog(LOG_EMERG, "No memory for regular expression %s\n",
147                 (gs_sp_t)(pattern->offset));
148         return 0;
149     }
150
151     if (regcomp(reg,(char*)(pattern->offset), REG_NEWLINE|REG_EXTENDED|REG_NOSUB)!=0) {
152         gslog(LOG_EMERG, "Illegal regular expression %s\n",
153                 (gs_sp_t)(pattern->offset));
154         return 0;
155     }
156     return (gs_param_handle_t) reg;
157 }
158
159 gs_uint32_t str_regex_match(vstring* str, gs_param_handle_t pattern_handle) {
160     regex_t * reg = (regex_t *) pattern_handle ;
161     gs_int32_t res;
162     static gs_sp_t d=0;
163     static gs_uint32_t dlen=0;
164     // grow our static buffer to the longest string we ever see
165     if ((str->length+1) >= dlen) {
166         if (d!=0) free((void*)d);
167         dlen=0;
168         d=0;
169         if ((d=(gs_sp_t)malloc(str->length+1))==0) return 0;
170         dlen=str->length+1;
171     }
172     
173     if (str->length==0) return 0;
174     
175     // copy the string and 0 terminate it
176     memcpy((void *)d,(void *) str->offset, str->length);
177     d[str->length]=0;
178     
179     res = REG_NOMATCH;
180     res = regexec(reg, d, 0, NULL, 0);
181     return (res==REG_NOMATCH)?0:1;
182 }
183
184 gs_retval_t deregister_handle_for_str_regex_match_slot_1(gs_param_handle_t handle) {
185     regex_t * x = (regex_t *) handle;
186     regfree(x);
187     if (x!=0) free(x);
188     return 0;
189 }
190
191 gs_param_handle_t register_handle_for_str_partial_regex_match_slot_1(vstring* pattern) {
192     regex_t * reg;
193     gs_int32_t res;
194
195     if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0)  {
196         gslog(LOG_EMERG, "No memory for regular expression %s\n",
197                 (gs_sp_t)(pattern->offset));
198         return 0;
199     }
200
201     if (regcomp(reg,(gs_sp_t)(pattern->offset), REG_NEWLINE|REG_EXTENDED|REG_NOSUB)!=0) {
202         gslog(LOG_EMERG, "Illegal regular expression %s\n",
203                 (gs_sp_t)(pattern->offset));
204         return 0;
205     }
206     return (gs_param_handle_t) reg;
207 }
208
209 gs_uint32_t str_partial_regex_match(vstring* str, gs_param_handle_t pattern_handle,
210                              uint maxlen) {
211     regex_t * reg = (regex_t *) pattern_handle ;
212     gs_int32_t res;
213     gs_int32_t end;
214     static gs_sp_t d=0;
215     static gs_uint32_t dlen=0;
216     // grow our static buffer to the longest string we ever see
217     if ((str->length+1) >= dlen) {
218         if (d!=0) free((void*)d);
219         dlen=0;
220         d=0;
221         if ((d=(gs_sp_t)malloc(str->length+1))==0) return 0;
222         dlen=str->length+1;
223     }
224     
225     if (str->length==0) return 0;
226     
227     end=(maxlen>(str->length))?(str->length):maxlen;
228     
229     // copy the string and 0 terminate it
230     memcpy((void *)d,(void *) str->offset, end);
231     d[end]=0;
232  
233     res = REG_NOMATCH;
234     res = regexec(reg, d,0, NULL, 0);
235     return (res==REG_NOMATCH)?0:1;
236 }
237
238
239 gs_retval_t deregister_handle_for_str_partial_regex_match_slot_1(
240                                              gs_param_handle_t handle) {
241     regex_t * x = (regex_t *) handle;
242     regfree(x);
243     if (x!=0) free(x);
244     return 0;
245 }
246
247 gs_param_handle_t register_handle_for_str_extract_regex_slot_1(vstring* pattern) {
248     regex_t * reg;
249     
250     if ((reg=(regex_t *) malloc(sizeof(regex_t)))==0)  {
251         gslog(LOG_EMERG, "No memory for regular expression %s\n",
252               (gs_sp_t)(pattern->offset));
253         return 0;
254     }
255     if (regcomp(reg,(gs_sp_t)(pattern->offset), REG_EXTENDED)!=0) {
256         gslog(LOG_EMERG, "Illegal regular expression %s\n",
257               (gs_sp_t)(pattern->offset));
258         return 0;
259     }
260     return (gs_param_handle_t) reg;
261 }
262
263
264 /* partial function return 0 if the value is valid */
265 gs_retval_t str_extract_regex( vstring * result, vstring * str, gs_param_handle_t handle) {
266     regex_t * reg = (regex_t *) handle ;
267     gs_sp_t source = (gs_sp_t)(str->offset);
268     gs_retval_t res;
269     regmatch_t match;
270     static gs_sp_t d=0;
271     static gs_uint32_t dlen=0;
272     // grow our static buffer to the longest string we ever see
273     if ((str->length+1) >= dlen) {
274         if (d!=0) free((void*)d);
275         dlen=0;
276         d=0;
277         if ((d=(gs_sp_t)malloc(str->length+1))==0) return 1;
278         dlen=str->length+1;
279     }
280     
281     if (str->length==0) return 1;
282     
283     // copy the string and 0 terminate it
284     memcpy((void *)d,(void *) str->offset, str->length);
285     d[str->length]=0;
286
287     res = REG_NOMATCH;
288     res = regexec(reg, d, 1, &match, 0);
289     if (res==REG_NOMATCH) return 1;
290     result->offset= (gs_p_t) &source[match.rm_so];
291     result->length=match.rm_eo-match.rm_so;
292     result->reserved = SHALLOW_COPY;
293     return 0;
294 }
295
296 gs_retval_t deregister_handle_for_str_extract_regex_slot_1(gs_param_handle_t handle) {
297     regex_t * x = (regex_t *) handle;
298     regfree(x);
299     if (x!=0) free(x);
300     return 0;
301 }
302
303
304 static gs_uint32_t nextint(struct vstring *str , gs_uint32_t * offset, gs_uint32_t *res) {
305         gs_uint8_t * s = (gs_uint8_t *)(str->offset);
306         int v = 0;
307         *res = 0;
308         while(*offset<str->length) {
309                 if ((s[*offset]>='0') && (s[*offset]<='9')) {
310                         v=1;
311                         *res= (*res*10) + (gs_uint32_t) (s[*offset]-'0');
312                 } else {
313                         if (v!=0) { // got some valid result
314                                 return 1;
315                         } // otherwise skip leading grabage
316                 }
317                 (*offset)++;
318         }
319         return v;
320 }
321
322 gs_uint32_t strtoi(gs_uint32_t * r, struct vstring * s)
323 {
324         gs_uint32_t offset;
325         offset=0;
326         if (nextint(s,&offset,r)==0) return 1;
327         return 0;
328 }
329
330 gs_param_handle_t register_handle_for_strtoi_c_slot_0(vstring* istr) {
331         gs_uint32_t offset,r;
332         offset=0;
333         if (nextint(istr,&offset,&r)!=0)
334                 return (gs_param_handle_t) r;
335         return (gs_param_handle_t) 0;
336 }
337 gs_retval_t deregister_handle_for_strtoi_c_slot_0(gs_param_handle_t h) {
338         return 0;
339 }
340
341
342 gs_uint32_t strtoip(gs_uint32_t * r, struct vstring * s)
343 {
344         gs_uint32_t ip1,ip2,ip3,ip4,offset;
345         offset=0;
346         if (nextint(s,&offset,&ip1)==0) return 1;
347         //fprintf (stderr, "1 %u %u\n",ip1,offset);
348         if (nextint(s,&offset,&ip2)==0) return 1;
349         //fprintf (stderr, "2 %u %u\n",ip2,offset);
350         if (nextint(s,&offset,&ip3)==0) return 1;
351         //fprintf (stderr, "3 %u %u\n",ip3,offset);
352         if (nextint(s,&offset,&ip4)==0) return 1;
353         //fprintf (stderr, "4 %u %u\n",ip4,offset);
354         *r=ip1<<24|ip2<<16|ip3<<8|ip4;
355         return 0;
356 }
357
358 gs_param_handle_t register_handle_for_strtoip_c_slot_0(vstring* istr) {
359         gs_uint32_t ip1,ip2,ip3,ip4,offset,r;
360         offset=0;
361         if (nextint(istr,&offset,&ip1)==0) return (gs_param_handle_t)0;
362         if (nextint(istr,&offset,&ip2)==0) return (gs_param_handle_t)0;
363         if (nextint(istr,&offset,&ip3)==0) return (gs_param_handle_t)0;
364         if (nextint(istr,&offset,&ip4)==0) return (gs_param_handle_t)0;
365         r=ip1<<24|ip2<<16|ip3<<8|ip4;
366                 return (gs_param_handle_t)r;
367 }
368 gs_retval_t deregister_handle_for_strtoip_c_slot_0(gs_param_handle_t h) {
369         return 0;
370 }
371
372 gs_uint32_t partn_hash(  gs_uint32_t ip1, gs_uint32_t ip2) {
373     return (ip1^ip2);
374 }
375
376 gs_uint32_t rand_hash() {
377     return rand();
378 }
379
380 ///////////////////////////////////////
381 //              IPv6 fcns.
382 //      return negative if s1 < s2, 0 if s1==s2, positive if s1>s2
383 gs_retval_t hfta_ipv6_compare(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2) {
384     if(i1.v[0] > i2.v[0])
385         return 1;
386     if(i1.v[0] < i2.v[0])
387         return -1;
388     if(i1.v[1] > i2.v[1])
389         return 1;
390     if(i1.v[1] < i2.v[1])
391         return -1;
392     if(i1.v[2] > i2.v[2])
393         return 1;
394     if(i1.v[2] < i2.v[2])
395         return -1;
396     if(i1.v[3] > i2.v[3])
397         return 1;
398     if(i1.v[3] < i2.v[3])
399         return -1;
400
401     return 0;
402 }
403
404 hfta_ipv6_str And_Ipv6(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2){
405         hfta_ipv6_str ret;
406         ret.v[0] = i1.v[0] & i2.v[0];
407         ret.v[1] = i1.v[1] & i2.v[1];
408         ret.v[2] = i1.v[2] & i2.v[2];
409         ret.v[3] = i1.v[3] & i2.v[3];
410         return ret;
411 }
412
413 hfta_ipv6_str Or_Ipv6(const hfta_ipv6_str &i1, const hfta_ipv6_str &i2){
414         hfta_ipv6_str ret;
415         ret.v[0] = i1.v[0] | i2.v[0];
416         ret.v[1] = i1.v[1] | i2.v[1];
417         ret.v[2] = i1.v[2] | i2.v[2];
418         ret.v[3] = i1.v[3] | i2.v[3];
419         return ret;
420 }
421
422 gs_uint32_t hfta_ipv6_hashfunc(const hfta_ipv6_str *s) {
423         return s->v[0] ^ s->v[1] ^ s->v[2] ^ s->v[3];
424 }
425
426 hfta_ipv6_str hton_ipv6(hfta_ipv6_str s){
427         hfta_ipv6_str ret;
428
429 //      ret.v[0] = htonl(s.v[0]);
430 //      ret.v[1] = htonl(s.v[1]);
431 //      ret.v[2] = htonl(s.v[2]);
432 //      ret.v[3] = htonl(s.v[3]);
433         ret.v[0] = s.v[0];
434         ret.v[1] = s.v[1];
435         ret.v[2] = s.v[2];
436         ret.v[3] = s.v[3];
437         return ret;
438 }
439
440 hfta_ipv6_str ntoh_ipv6(hfta_ipv6_str s){
441         hfta_ipv6_str ret;
442 //      ret.v[0] = ntohl(s.v[0]);
443 //      ret.v[1] = ntohl(s.v[1]);
444 //      ret.v[2] = ntohl(s.v[2]);
445 //      ret.v[3] = ntohl(s.v[3]);
446         ret.v[0] = s.v[0];
447         ret.v[1] = s.v[1];
448         ret.v[2] = s.v[2];
449         ret.v[3] = s.v[3];
450         return ret;
451 }
452
453 int HFTA_Ipv6_Constructor(hfta_ipv6_str *s, gs_csp_t l) {
454         gs_uint32_t i0=0,i1=0,i2=0,i3=0,i4=0,i5=0,i6=0,i7=0;
455         sscanf(l,"%x:%x:%x:%x:%x:%x:%x:%x",&i0,&i1,&i2,&i3,&i4,&i5,&i6,&i7);
456         s->v[0] = ((i0 & 0xffff) << 16) | (i1 & 0xffff);
457         s->v[1] = ((i2 & 0xffff) << 16) | (i3 & 0xffff);
458         s->v[2] = ((i4 & 0xffff) << 16) | (i5 & 0xffff);
459         s->v[3] = ((i6 & 0xffff) << 16) | (i7 & 0xffff);
460     return(0);
461 }
462
463 gs_retval_t str_exists_substr(vstring * s1,vstring * s2)
464 {
465   gs_uint8_t *st1 = (gs_uint8_t *)s1->offset;
466   gs_uint8_t *st2 = (gs_uint8_t *)s2->offset;
467   gs_uint8_t *s2f = (gs_uint8_t *)s2->offset;
468   gs_uint8_t len1 = s1->length-s2->length;
469   gs_uint8_t len2 = s2->length;
470   gs_uint8_t x,y;
471
472   for (x=0; x<len1 ; x++)
473   {
474       if (st1[x]== *s2f)
475         {
476           for (y=0; y<len2 && st1[x+y]==st2[y];y++);
477           if (y==len2)
478               return 1;
479         }
480   }
481   return 0;
482 }
483
484 gs_retval_t str_compare(vstring *s1,vstring *s2)
485 {
486   return hfta_vstr_compare(s1,s2);
487 }
488
489 gs_uint32_t str_match_offset( gs_uint32_t offset, vstring *s1, vstring *s2)
490 {
491   gs_uint8_t *st1 = (gs_uint8_t *)s1->offset;
492   gs_uint8_t *st2 = &(((gs_uint8_t *)s2->offset)[offset]);
493   gs_int32_t x;
494   gs_int32_t len2 = s2->length-offset;
495   gs_int32_t len1 = s1->length;
496
497   if (len2 < len1)
498     return 0;
499
500   for(x = 0; x < len1; x++)
501     {
502       if (st1[x] != st2[x])
503         return 0;
504     }
505   return 1;
506 }
507
508 gs_uint32_t byte_match_offset( gs_uint32_t offset, gs_uint32_t val,vstring *s2)
509 {
510   gs_uint8_t *st2 = (gs_uint8_t *)s2->offset;
511   gs_uint8_t v = (unsigned char) val;
512
513 //  if ((s2->length <= offset)||(offset<0))
514   if (s2->length <= offset)
515       return 0;
516
517   return (st2[offset]==v)?1:0;
518 }
519
520