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