diff options
| author | git commit -m first <[email protected]> | 2019-06-12 15:06:20 +0800 |
|---|---|---|
| committer | git commit -m first <[email protected]> | 2019-06-12 15:06:20 +0800 |
| commit | 10e810b629148dcc96159d96045edccb94af600a (patch) | |
| tree | d8e4724d2f1ea208f05fa6d96be8ad6413b6df3b | |
add source code
| -rw-r--r-- | Makefile | 47 | ||||
| -rw-r--r-- | comm_zip_py/interval_zip.py | 94 | ||||
| -rw-r--r-- | comm_zip_py/run | 2 | ||||
| -rw-r--r-- | comm_zip_py/run_comm_interval_zip | 12 | ||||
| -rw-r--r-- | conf/comm_audit.inf | 13 | ||||
| -rw-r--r-- | conf/net_log_upload_pz.txt | 1 | ||||
| -rw-r--r-- | djconf/comm_audit.conf | 19 | ||||
| -rw-r--r-- | inc/cJSON.h | 149 | ||||
| -rw-r--r-- | inc/comm_audit.h | 489 | ||||
| -rw-r--r-- | inc/identify.h | 35 | ||||
| -rw-r--r-- | inc/maxminddb.h | 241 | ||||
| -rw-r--r-- | inc/project_requirement.h | 112 | ||||
| -rwxr-xr-x | lib/comm_audit.so | bin | 0 -> 200288 bytes | |||
| -rw-r--r-- | libmaxminddb.a | bin | 0 -> 178110 bytes | |||
| -rw-r--r-- | src/.comm_audit.cpp.swp | bin | 0 -> 16384 bytes | |||
| -rw-r--r-- | src/cJSON.c | 763 | ||||
| -rw-r--r-- | src/comm_audit.cpp | 968 |
17 files changed, 2945 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fffe8fe --- /dev/null +++ b/Makefile @@ -0,0 +1,47 @@ +CC = g++ +CCC = g++ +CFLAGS += -g -Wall -fPIC -std=c++11 +#CFLAGS += $(OPTFLAGS) +SRCS += $(wildcard ./src/*.cpp) $(wildcard ./src/*.c) +OBJECTS := $(patsubst %.cpp, %.o, $(SRCS)) +LDFLAGS = -L/usr/local/lib +#OBJECTS := $(patsubst %.cpp, %.o) +TARGET := comm_audit.so + +INCS := -I./inc -I./. +LIBS = -lMESA_handle_logger -lMESA_prof_load +STATICLIB = ./libmaxminddb.a + +# LIBPATH += -L./lib +LIBPATH := ./lib +vpath %.cpp src +vpath %.c src +vpath %.h inc:MESA + +%.o:%.cpp + $(CCC) $(CFLAGS) $(INCS) -o $@ -c $< +%.o:%.c + $(CC) $(CFLAGS) $(INCS) -o $@ -c $< + +all:$(TARGET) $(SUPPORT) + +$(TARGET):$(OBJECTS) + $(CC) -o $(TARGET) $^ $(INCS) $(STATICLIB) $(LIBS) -shared -fPIC + rm -f src/*.o + mv $(TARGET) $(LIBPATH) + +.PHONY: clean + +clean: +# rm -f $(OBJECTS) *.o ./lib/* + rm -f ./lib/* + +install: + cp -ru ./lib/$(TARGET) /home/jcq/bin/sapp_se/plug/business/comm_audit/ + cp -ru ./djconf/* /home/jcq/bin/sapp_se/djconf/ + cp -ru ./comm_zip_py /usr/local/bin/ + chmod +x /usr/local/bin/comm_zip_py/interval_zip.py + chmod +x /usr/local/bin/comm_zip_py/run + chmod +x /usr/local/bin/comm_zip_py/run_comm_interval_zip +# echo "cd /usr/local/bin/comm_zip_py;./run" >> /etc/rc.local + diff --git a/comm_zip_py/interval_zip.py b/comm_zip_py/interval_zip.py new file mode 100644 index 0000000..4ea9578 --- /dev/null +++ b/comm_zip_py/interval_zip.py @@ -0,0 +1,94 @@ +#!/usr/bin/python +# encoding: utf8 + +# Author: zhangxi +# Last modified: 2017/11/24 + +import os +import json +import time +import datetime +import pprint +import pdb +from optparse import OptionParser + + +def interval_zip(interval, conf_file): + + dest_path = "" + tmp_path = "" + # interval = 1 + + with open(conf_file) as f: + for line in f.readlines(): + if line.startswith("upload_log_path"): + dest_path = line[line.find("=")+1:].strip() + if not dest_path.endswith('/'): + dest_path+='/' + elif line.startswith("tmp_log_path"): + tmp_path = line[line.find("=")+1:].strip() + else: + pass + + while True: + try: + ''' + try: + with open(upload_pz) as f: + for line in f.readlines(): + start = line.find('interval":')+10 + end = line.find(',"num') + interval = int(line[start:end]) + except Exception, e: + pass + #raise e + # print interval + ''' + + time_remaining = interval-time.time()%interval + # print time_remaining + time.sleep(time_remaining) + + # today = time.strftime('%Y-%m-%d',time.localtime(time.time())) + # now_path = dest_path+today + # now_path+="/" + # cmd = 'mkdir -p %s; cd %s; gzip -q *; mv %s/* %s'%(now_path, tmp_path, tmp_path, now_path) + # # print cmd + # os.system(cmd) + + + # l = os.listdir(tmp_path) + l = tmp_path + if len(l)>1: + # st = l.sort(key=lambda fn: os.path.getmtime(tmp_path+"/"+fn) if not os.path.isdir(tmp_path+"/"+fn) else 0) + latest = sorted([(x, os.path.getmtime(os.path.join(l,x))) for x in os.listdir(l) if os.path.isfile(os.path.join(l,x))], \ + key=lambda i: i[1])[-1] + # print ('last file is '+l[-1]) + + today = time.strftime('%Y-%m-%d',time.localtime(time.time())) + now_path = dest_path+today + now_path+="/" + now_time = time.strftime('%H%M%S',time.localtime(time.time())) + # print now_time + # cmd = 'mkdir -p %s; cd %s; tar zcf %s/%s.tar.gz * --exclude=%s; rm `ls *|egrep -v %s`'\ + # %(now_path, tmp_path, now_path, now_time, l[-1], l[-1]) + #pdb.set_trace() + cmd = 'mkdir -p %s; cd %s; count=`ls|grep .txt|wc -l`; if [[ $count -gt 1 ]]; then tar zcf %s/%s.tar.gz * --exclude=%s; rm `ls *|egrep -v %s`;fi;'\ + %(now_path, tmp_path, now_path, now_time, latest[0], latest[0]) + # print cmd + os.system(cmd) + + except Exception, e: + pass + # print e + + +if __name__ == '__main__': + usage_info ="python %prog [options arg] \n" + parser =OptionParser(usage=usage_info,version="version verifiy 1.0") + parser.add_option("-i","--interval",dest="interval",default=5,help="interval of scanning upload file. Default is 5 seconds.") + # parser.add_option("-u","--upload_pz",dest="upload_pz",default="/tmp/upload_pz/net_log_upload_pz.txt",help="upload_pz_path. Default file is /tmp/upload_pz/net_log_upload_pz.txt") + parser.add_option("-c","--conf_file",dest="conf_file",default="/home/jcq/bin/sapp_se/djconf/comm_audit.conf",help="conf_path. Default file is /home/jcq/bin/sapp_se/djconf/comm_audit.conf") + (options,args) =parser.parse_args() + interval_zip(options.interval, options.conf_file) + diff --git a/comm_zip_py/run b/comm_zip_py/run new file mode 100644 index 0000000..8dd112c --- /dev/null +++ b/comm_zip_py/run @@ -0,0 +1,2 @@ +killall interval_zip.py run_comm_interval_zip +./run_comm_interval_zip & > /dev/null & diff --git a/comm_zip_py/run_comm_interval_zip b/comm_zip_py/run_comm_interval_zip new file mode 100644 index 0000000..4c005f4 --- /dev/null +++ b/comm_zip_py/run_comm_interval_zip @@ -0,0 +1,12 @@ +#!/bin/sh + +while [ 1 ]; do + count=`ps aux | grep interval_zip.py | grep -v grep | wc -l` + if [ $count -lt 1 ] + then + ./interval_zip.py > /dev/null & + echo program crashed, restart at `date +"%w %Y/%m/%d, %H:%M:%S"` >> RESTART.log + sleep 10 + fi + sleep 10 +done diff --git a/conf/comm_audit.inf b/conf/comm_audit.inf new file mode 100644 index 0000000..bf8707a --- /dev/null +++ b/conf/comm_audit.inf @@ -0,0 +1,13 @@ +[PLUGINFO]
+PLUGNAME=COMM_AUDIT
+SO_PATH=./plug/business/comm_audit/comm_audit.so
+INIT_FUNC=COMM_AUDIT_INIT
+DESTROY_FUNC=COMM_AUDIT_DESTROY
+
+[UDP]
+FUNC_FLAG=ALL
+FUNC_NAME=COMM_AUDIT_ENTRY
+
+[TCP_ALL]
+FUNC_FLAG=ALL
+FUNC_NAME=COMM_AUDIT_ENTRY
diff --git a/conf/net_log_upload_pz.txt b/conf/net_log_upload_pz.txt new file mode 100644 index 0000000..084b081 --- /dev/null +++ b/conf/net_log_upload_pz.txt @@ -0,0 +1 @@ +[{"interval":15,"num":100}]
\ No newline at end of file diff --git a/djconf/comm_audit.conf b/djconf/comm_audit.conf new file mode 100644 index 0000000..71aa9ff --- /dev/null +++ b/djconf/comm_audit.conf @@ -0,0 +1,19 @@ +[DEFAULT]
+htable_size = 100000
+sleep = 2
+log_level = 10
+log_path = ./log/comm_audit_log
+
+[UPLOAD_LOG]
+upload_log_path = /tmp/comm_upload_log
+tmp_log_path = /tmp/comm_log
+
+[UPLOAD_PZ]
+upload_pz_path = /tmp/upload_pz
+read_upload_pz_interval = 60
+default_upload_interval = 2
+defailt_upload_max_num = 100000
+
+[IPDB_PZ]
+flag = 0
+mmdb_path = ./db/all_ip_only_coun_v4.mmdb
diff --git a/inc/cJSON.h b/inc/cJSON.h new file mode 100644 index 0000000..466d10d --- /dev/null +++ b/inc/cJSON.h @@ -0,0 +1,149 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef cJSON__h +#define cJSON__h + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* cJSON Types: */ +#define cJSON_False 0 +#define cJSON_True 1 +#define cJSON_NULL 2 +#define cJSON_Number 3 +#define cJSON_String 4 +#define cJSON_Array 5 +#define cJSON_Object 6 + +#define cJSON_IsReference 256 +#define cJSON_StringIsConst 512 + +/* The cJSON structure: */ +typedef struct cJSON { + struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + + int type; /* The type of the item, as above. */ + + char *valuestring; /* The item's string, if type==cJSON_String */ + int valueint; /* The item's number, if type==cJSON_Number */ + double valuedouble; /* The item's number, if type==cJSON_Number */ + + char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ +} cJSON; + +typedef struct cJSON_Hooks { + void *(*malloc_fn)(size_t sz); + void (*free_fn)(void *ptr); +} cJSON_Hooks; + +/* Supply malloc, realloc and free functions to cJSON */ +extern void cJSON_InitHooks(cJSON_Hooks* hooks); + + +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ +extern cJSON *cJSON_Parse(const char *value); +/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ +extern char *cJSON_Print(cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ +extern char *cJSON_PrintUnformatted(cJSON *item); +/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ +extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt); +/* Delete a cJSON entity and all subentities. */ +extern void cJSON_Delete(cJSON *c); + +/* Returns the number of items in an array (or object). */ +extern int cJSON_GetArraySize(cJSON *array); +/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ +extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); +/* Get item "string" from object. Case insensitive. */ +extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); + +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +extern const char *cJSON_GetErrorPtr(void); + +/* These calls create a cJSON item of the appropriate type. */ +extern cJSON *cJSON_CreateNull(void); +extern cJSON *cJSON_CreateTrue(void); +extern cJSON *cJSON_CreateFalse(void); +extern cJSON *cJSON_CreateBool(int b); +extern cJSON *cJSON_CreateNumber(double num); +extern cJSON *cJSON_CreateString(const char *string); +extern cJSON *cJSON_CreateArray(void); +extern cJSON *cJSON_CreateObject(void); + +/* These utilities create an Array of count items. */ +extern cJSON *cJSON_CreateIntArray(const int *numbers,int count); +extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count); +extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); +extern cJSON *cJSON_CreateStringArray(const char **strings,int count); + +/* Append item to the specified array/object. */ +extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); +extern void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */ +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ +extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); + +/* Remove/Detatch items from Arrays/Objects. */ +extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); +extern void cJSON_DeleteItemFromArray(cJSON *array,int which); +extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); +extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); + +/* Update array items. */ +extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem); /* Shifts pre-existing items to the right. */ +extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); +extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); + +/* Duplicate a cJSON item */ +extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); +/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will +need to be released. With recurse!=0, it will duplicate any children connected to the item. +The item->next and ->prev pointers are always zero on return from Duplicate. */ + +/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ +extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); + +extern void cJSON_Minify(char *json); + +/* Macros for creating things quickly. */ +#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) +#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) +#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) +#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) +#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) +#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) + +/* When assigning an integer value, it needs to be propagated to valuedouble too. */ +#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) +#define cJSON_SetNumberValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/inc/comm_audit.h b/inc/comm_audit.h new file mode 100644 index 0000000..be9038d --- /dev/null +++ b/inc/comm_audit.h @@ -0,0 +1,489 @@ +/*
+ * COMM_AUDIT.h
+ *
+ * Created on: 2017-8-14
+ * Last Modified: 2017-11-23
+ * Author: zhangxi
+ */
+
+#ifndef _COMM_AUDIT_H_
+#define _COMM_AUDIT_H_
+
+#include <sys/types.h>
+#include <time.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <dirent.h>
+#include <assert.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#include <MESA/stream.h>
+#include <MESA/MESA_handle_logger.h>
+#include <MESA/MESA_htable.h>
+#include <MESA/MESA_prof_load.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define IPLEN (16)
+#define MACLEN (60)
+#define MB (1024 * 1024)
+#define MAX_LEN (1024)
+
+#define STREAM_TYPE(num)\
+({\
+ string type;\
+ switch(num)\
+ {\
+ case 0:\
+ type="NON";\
+ break;\
+ case 1:\
+ type="TCP";\
+ break;\
+ case 2:\
+ type="UDP";\
+ break;\
+ case 3:\
+ type="VLAN";\
+ break;\
+ case 4:\
+ type="SOCKS4";\
+ break;\
+ case 5:\
+ type="SOCKS5";\
+ break;\
+ case 6:\
+ type="HTTP_PROXY";\
+ break;\
+ case 7:\
+ type="PPPOE";\
+ break;\
+ case 8:\
+ type="L2TP";\
+ break;\
+ case 9:\
+ type="OPENVPN";\
+ break;\
+ case 10:\
+ type="PPTP";\
+ break;\
+ case 11:\
+ type="ISAKMP";\
+ break;\
+ }\
+ (type);\
+})
+
+
+#define APP_TYPE(num)\
+({\
+ string type;\
+ switch(num)\
+ {\
+ case 227:\
+ type="HTTP";\
+ break;\
+ case 256:\
+ type="DNS";\
+ break;\
+ case 314:\
+ type="SSL";\
+ break;\
+ case 229:\
+ type="FTP";\
+ break;\
+ case 243:\
+ type="SMTP";\
+ break;\
+ case 242:\
+ type="POP3";\
+ break;\
+ case 244:\
+ type="IMAP";\
+ break;\
+ case 1:\
+ type="BT";\
+ break;\
+ case 145:\
+ type="RTSP";\
+ break;\
+ case 1054:\
+ type="SSH";\
+ break;\
+ case 1058:\
+ type="telnet";\
+ break;\
+ case 312:\
+ type="socks4";\
+ break;\
+ case 313:\
+ type="socks5";\
+ break;\
+ case 15:\
+ type="fasttrack";\
+ break;\
+ case 17:\
+ type="filetopia";\
+ break;\
+ case 18:\
+ type="flashget";\
+ break;\
+ case 954:\
+ type="oracle";\
+ break;\
+ case 1002:\
+ type="skinny";\
+ break;\
+ case 1023:\
+ type="yyvoice";\
+ break;\
+ case 28:\
+ type="imesh";\
+ break;\
+ case 975:\
+ type="iax";\
+ break;\
+ case 986:\
+ type="mgcp";\
+ break;\
+ case 997:\
+ type="rtcp";\
+ break;\
+ case 998:\
+ type="rtp";\
+ break;\
+ case 1042:\
+ type="citrix";\
+ break;\
+ case 1043:\
+ type="corba";\
+ break;\
+ case 1044:\
+ type="dameware";\
+ break;\
+ case 1050:\
+ type="pcanywhere";\
+ break;\
+ case 1051:\
+ type="qq_rdp";\
+ break;\
+ case 1056:\
+ type="teamview";\
+ break;\
+ case 1060:\
+ type="vnc";\
+ break;\
+ case 1063:\
+ type="xdmcp";\
+ break;\
+ case 1068:\
+ type="rdp";\
+ break;\
+ case 4:\
+ type="aimini";\
+ break;\
+ case 41:\
+ type="poco";\
+ break;\
+ case 46:\
+ type="qqdownload";\
+ break;\
+ case 5:\
+ type="applejuice";\
+ break;\
+ case 55:\
+ type="stealthnet";\
+ break;\
+ case 59:\
+ type="winmx";\
+ break;\
+ case 66:\
+ type="emule";\
+ break;\
+ case 72:\
+ type="kuwo";\
+ break;\
+ case 80:\
+ type="thunder";\
+ break;\
+ case 138:\
+ type="qvod";\
+ break;\
+ case 953:\
+ type="mysql";\
+ break;\
+ case 101:\
+ type="icecast";\
+ break;\
+ case 113:\
+ type="mms";\
+ break;\
+ case 127:\
+ type="pplive";\
+ break;\
+ case 129:\
+ type="ppstream";\
+ break;\
+ case 151:\
+ type="sopcast";\
+ break;\
+ case 153:\
+ type="steam";\
+ break;\
+ case 157:\
+ type="tvants";\
+ break;\
+ case 199:\
+ type="iqiyi";\
+ break;\
+ case 208:\
+ type="sohutv";\
+ break;\
+ case 223:\
+ type="iku";\
+ break;\
+ case 228:\
+ type="cvs";\
+ break;\
+ case 232:\
+ type="ipp";\
+ break;\
+ case 235:\
+ type="nfs";\
+ break;\
+ case 236:\
+ type="rsync";\
+ break;\
+ case 237:\
+ type="smb";\
+ break;\
+ case 239:\
+ type="tftp";\
+ break;\
+ case 247:\
+ type="lotus_notes";\
+ break;\
+ case 251:\
+ type="bgp";\
+ break;\
+ case 254:\
+ type="dhcp";\
+ break;\
+ case 259:\
+ type="finger";\
+ break;\
+ case 264:\
+ type="kerberos";\
+ break;\
+ case 265:\
+ type="ldap";\
+ break;\
+ case 266:\
+ type="mdns";\
+ break;\
+ case 268:\
+ type="nntp";\
+ break;\
+ case 276:\
+ type="snmp";\
+ break;\
+ case 277:\
+ type="ssdp";\
+ break;\
+ case 278:\
+ type="syslog";\
+ break;\
+ case 281:\
+ type="whois";\
+ break;\
+ case 288:\
+ type="radius";\
+ break;\
+ case 1150:\
+ type="quic";\
+ break;\
+ case 295:\
+ type="ikev1";\
+ break;\
+ case 296:\
+ type="ikev2";\
+ break;\
+ case 304:\
+ type="l2tp";\
+ break;\
+ case 307:\
+ type="openvpn";\
+ break;\
+ case 309:\
+ type="pptp";\
+ break;\
+ case 315:\
+ type="stun";\
+ break;\
+ case 317:\
+ type="teredo";\
+ break;\
+ case 318:\
+ type="tor";\
+ break;\
+ case 328:\
+ type="xunyou_speedup";\
+ break;\
+ case 360:\
+ type="msn";\
+ break;\
+ case 368:\
+ type="popo";\
+ break;\
+ case 404:\
+ type="qq";\
+ break;\
+ case 410:\
+ type="sinauc";\
+ break;\
+ case 467:\
+ type="qqbattle";\
+ break;\
+ case 484:\
+ type="quake";\
+ break;\
+ case 507:\
+ type="xbox";\
+ break;\
+ case 690:\
+ type="wow";\
+ break;\
+ case 1074:\
+ type="gtp";\
+ break;\
+ default:\
+ type="unknown";\
+ break;\
+ }\
+ (type);\
+})
+
+#define TCP_FLAG(num)\
+({\
+ string flag;\
+ int n = num;\
+ if(n >= 32)\
+ {\
+ flag += "U";\
+ n -= 32;\
+ }\
+ if(n >= 16)\
+ {\
+ flag += "A";\
+ n -= 16;\
+ }\
+ if(n >= 8)\
+ {\
+ flag += "P";\
+ n -= 8;\
+ }\
+ if(n >= 4)\
+ {\
+ flag += "R";\
+ n -= 4;\
+ }\
+ if(n >= 2)\
+ {\
+ flag += "S";\
+ n -= 2;\
+ }\
+ if(n >= 1)\
+ {\
+ flag += "F";\
+ n -= 1;\
+ }\
+ (flag);\
+})
+
+
+typedef struct _htable_data_t
+{
+
+ unsigned int inner_ip;
+ unsigned int ext_ip;
+ unsigned short inner_port;
+ unsigned short ext_port;
+ char inner_mac[MACLEN];
+ char ext_mac[MACLEN];
+ unsigned char protocol;
+ unsigned short app;
+
+ unsigned short tcp_flag;
+ unsigned long long in_bytes;
+ unsigned long long out_bytes;
+ unsigned long long in_pkts;
+ unsigned long long out_pkts;
+ long long start_time;
+ long long end_time;
+
+}htable_data_t;
+
+
+typedef struct htable_search_arg
+{
+ struct streaminfo * stream;
+ void * packet;
+ int is_end;
+}htable_search_arg;
+
+
+typedef struct comm_prog_configure_t
+{
+ int htable_size;
+ int sleep;
+ int read_interval;
+ int write_interval;
+ int write_max_num;
+ int flag; //0:use mmd filter;1:no filter;2:no have any data
+ // char * log_path;
+ char * tmp_log_path;
+ char * upload_pz_path;
+ char * mmdb_path;
+}comm_prog_configure_t;
+
+typedef struct comm_prog_runtime_parameter_t
+{
+ int project_id_pro;
+ int thread_num;
+ void* log_handle;
+ long long last_send_time;
+ pthread_mutex_t mutex;
+ MESA_htable_handle **htable_handle;
+ // MESA_htable_handle htable_handle1;
+ // MESA_htable_handle htable_handle2;
+ // MESA_htable_handle wtable;
+ // MESA_htable_handle rtable;
+
+}comm_prog_runtime_parameter_t;
+
+typedef struct del_para_t
+{
+ char * writetime;
+ int thread_seq;
+}del_para_t;
+
+int COMM_AUDIT_INIT();
+char COMM_AUDIT_ENTRY(struct streaminfo *, void **, int , void *);
+void COMM_AUDIT_DESTROY();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/inc/identify.h b/inc/identify.h new file mode 100644 index 0000000..2912b8d --- /dev/null +++ b/inc/identify.h @@ -0,0 +1,35 @@ +#ifndef _IDENTIFY_PROC_H_
+#define _IDENTIFY_PROC_H_
+
+
+#define DNTY_PPROJECT_TYPE "struct"
+
+#define DNTY_PPROJECT_AREA "PPROJECT_AREA"
+#define DNTY_PPROJECT_PRO "PPROJECT_PRO"
+
+
+#define DNTY_AREA_OUTSIDE 700000
+#define DNTY_AREA_UNKONW 0
+
+
+typedef struct _dnty_area_info
+{
+ unsigned int client_area;
+ unsigned int server_area;
+}stDntyAreaInfo;
+
+
+typedef struct _dnty_protocol_info
+{
+ unsigned char trans_proto;
+ unsigned char communicate_mode:7;
+ unsigned char v6:1;
+ unsigned short protocol_type;
+ unsigned short application_class;
+ unsigned char cmd_type;
+ unsigned char reserved;
+}stDntyProInfo;
+
+
+#endif
+
diff --git a/inc/maxminddb.h b/inc/maxminddb.h new file mode 100644 index 0000000..de1fdf8 --- /dev/null +++ b/inc/maxminddb.h @@ -0,0 +1,241 @@ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAXMINDDB_H +#define MAXMINDDB_H + +/* Request POSIX.1-2008. However, we want to remain compatible with + * POSIX.1-2001 (since we have been historically and see no reason to drop + * compatibility). By requesting POSIX.1-2008, we can conditionally use + * features provided by that standard if the implementation provides it. We can + * check for what the implementation provides by checking the _POSIX_VERSION + * macro after including unistd.h. If a feature is in POSIX.1-2008 but not + * POSIX.1-2001, check that macro before using the feature (or check for the + * feature directly if possible). */ +#ifndef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200809L +#endif + +#include "maxminddb_config.h" +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <sys/types.h> + +#ifdef _WIN32 +#include <winsock2.h> +#include <ws2tcpip.h> +/* libmaxminddb package version from configure */ +#define PACKAGE_VERSION "1.3.2" + +typedef ADDRESS_FAMILY sa_family_t; + +#if defined(_MSC_VER) +/* MSVC doesn't define signed size_t, copy it from configure */ +#define ssize_t SSIZE_T + +/* MSVC doesn't support restricted pointers */ +#define restrict +#endif +#else +#include <netdb.h> +#include <netinet/in.h> +#include <sys/socket.h> +#endif + +#define MMDB_DATA_TYPE_EXTENDED (0) +#define MMDB_DATA_TYPE_POINTER (1) +#define MMDB_DATA_TYPE_UTF8_STRING (2) +#define MMDB_DATA_TYPE_DOUBLE (3) +#define MMDB_DATA_TYPE_BYTES (4) +#define MMDB_DATA_TYPE_UINT16 (5) +#define MMDB_DATA_TYPE_UINT32 (6) +#define MMDB_DATA_TYPE_MAP (7) +#define MMDB_DATA_TYPE_INT32 (8) +#define MMDB_DATA_TYPE_UINT64 (9) +#define MMDB_DATA_TYPE_UINT128 (10) +#define MMDB_DATA_TYPE_ARRAY (11) +#define MMDB_DATA_TYPE_CONTAINER (12) +#define MMDB_DATA_TYPE_END_MARKER (13) +#define MMDB_DATA_TYPE_BOOLEAN (14) +#define MMDB_DATA_TYPE_FLOAT (15) + +#define MMDB_RECORD_TYPE_SEARCH_NODE (0) +#define MMDB_RECORD_TYPE_EMPTY (1) +#define MMDB_RECORD_TYPE_DATA (2) +#define MMDB_RECORD_TYPE_INVALID (3) + +/* flags for open */ +#define MMDB_MODE_MMAP (1) +#define MMDB_MODE_MASK (7) + +/* error codes */ +#define MMDB_SUCCESS (0) +#define MMDB_FILE_OPEN_ERROR (1) +#define MMDB_CORRUPT_SEARCH_TREE_ERROR (2) +#define MMDB_INVALID_METADATA_ERROR (3) +#define MMDB_IO_ERROR (4) +#define MMDB_OUT_OF_MEMORY_ERROR (5) +#define MMDB_UNKNOWN_DATABASE_FORMAT_ERROR (6) +#define MMDB_INVALID_DATA_ERROR (7) +#define MMDB_INVALID_LOOKUP_PATH_ERROR (8) +#define MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR (9) +#define MMDB_INVALID_NODE_NUMBER_ERROR (10) +#define MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR (11) + +#if !(MMDB_UINT128_IS_BYTE_ARRAY) +#if MMDB_UINT128_USING_MODE +typedef unsigned int mmdb_uint128_t __attribute__ ((__mode__(TI))); +#else +typedef unsigned __int128 mmdb_uint128_t; +#endif +#endif + +/* This is a pointer into the data section for a given IP address lookup */ +typedef struct MMDB_entry_s { + struct MMDB_s *mmdb; + uint32_t offset; +} MMDB_entry_s; + +typedef struct MMDB_lookup_result_s { + bool found_entry; + MMDB_entry_s entry; + uint16_t netmask; +} MMDB_lookup_result_s; + +typedef struct MMDB_entry_data_s { + bool has_data; + union { + uint32_t pointer; + const char *utf8_string; + double double_value; + const uint8_t *bytes; + uint16_t uint16; + uint32_t uint32; + int32_t int32; + uint64_t uint64; +#if MMDB_UINT128_IS_BYTE_ARRAY + uint8_t uint128[16]; +#else + mmdb_uint128_t uint128; +#endif + bool boolean; + float float_value; + }; + /* This is a 0 if a given entry cannot be found. This can only happen + * when a call to MMDB_(v)get_value() asks for hash keys or array + * indices that don't exist. */ + uint32_t offset; + /* This is the next entry in the data section, but it's really only + * relevant for entries that part of a larger map or array + * struct. There's no good reason for an end user to look at this + * directly. */ + uint32_t offset_to_next; + /* This is only valid for strings, utf8_strings or binary data */ + uint32_t data_size; + /* This is an MMDB_DATA_TYPE_* constant */ + uint32_t type; +} MMDB_entry_data_s; + +/* This is the return type when someone asks for all the entry data in a map or array */ +typedef struct MMDB_entry_data_list_s { + MMDB_entry_data_s entry_data; + struct MMDB_entry_data_list_s *next; + void *pool; +} MMDB_entry_data_list_s; + +typedef struct MMDB_description_s { + const char *language; + const char *description; +} MMDB_description_s; + +typedef struct MMDB_metadata_s { + uint32_t node_count; + uint16_t record_size; + uint16_t ip_version; + const char *database_type; + struct { + size_t count; + const char **names; + } languages; + uint16_t binary_format_major_version; + uint16_t binary_format_minor_version; + uint64_t build_epoch; + struct { + size_t count; + MMDB_description_s **descriptions; + } description; +} MMDB_metadata_s; + +typedef struct MMDB_ipv4_start_node_s { + uint16_t netmask; + uint32_t node_value; +} MMDB_ipv4_start_node_s; + +typedef struct MMDB_s { + uint32_t flags; + const char *filename; + ssize_t file_size; + const uint8_t *file_content; + const uint8_t *data_section; + uint32_t data_section_size; + const uint8_t *metadata_section; + uint32_t metadata_section_size; + uint16_t full_record_byte_size; + uint16_t depth; + MMDB_ipv4_start_node_s ipv4_start_node; + MMDB_metadata_s metadata; +} MMDB_s; + +typedef struct MMDB_search_node_s { + uint64_t left_record; + uint64_t right_record; + uint8_t left_record_type; + uint8_t right_record_type; + MMDB_entry_s left_record_entry; + MMDB_entry_s right_record_entry; +} MMDB_search_node_s; + + /* *INDENT-OFF* */ + /* --prototypes automatically generated by dev-bin/regen-prototypes.pl - don't remove this comment */ + extern int MMDB_open(const char *const filename, uint32_t flags, MMDB_s *const mmdb); + extern MMDB_lookup_result_s MMDB_lookup_string(MMDB_s *const mmdb, + const char *const ipstr, + int *const gai_error, + int *const mmdb_error); + extern MMDB_lookup_result_s MMDB_lookup_sockaddr( + MMDB_s *const mmdb, + const struct sockaddr *const sockaddr, + int *const mmdb_error); + extern int MMDB_read_node(MMDB_s *const mmdb, uint32_t node_number, + MMDB_search_node_s *const node); + extern int MMDB_get_value(MMDB_entry_s *const start, + MMDB_entry_data_s *const entry_data, + ...); + extern int MMDB_vget_value(MMDB_entry_s *const start, + MMDB_entry_data_s *const entry_data, + va_list va_path); + extern int MMDB_aget_value(MMDB_entry_s *const start, + MMDB_entry_data_s *const entry_data, + const char *const *const path); + extern int MMDB_get_metadata_as_entry_data_list( + MMDB_s *const mmdb, MMDB_entry_data_list_s **const entry_data_list); + extern int MMDB_get_entry_data_list( + MMDB_entry_s *start, MMDB_entry_data_list_s **const entry_data_list); + extern void MMDB_free_entry_data_list(MMDB_entry_data_list_s *const entry_data_list); + extern void MMDB_close(MMDB_s *const mmdb); + extern const char *MMDB_lib_version(void); + extern int MMDB_dump_entry_data_list(FILE *const stream, + MMDB_entry_data_list_s *const entry_data_list, + int indent); + extern const char *MMDB_strerror(int error_code); + /* --prototypes end - don't remove this comment-- */ + /* *INDENT-ON* */ + +#endif /* MAXMINDDB_H */ + +#ifdef __cplusplus +} +#endif diff --git a/inc/project_requirement.h b/inc/project_requirement.h new file mode 100644 index 0000000..3159b36 --- /dev/null +++ b/inc/project_requirement.h @@ -0,0 +1,112 @@ +#ifndef _PROJECT_REQUIREMENT_H_
+#define _PROJECT_REQUIREMENT_H_
+
+#include <MESA/stream.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define PROJECT_REQ_NAME_MAX_LEN (64)
+
+typedef void (project_req_free_t)(int thread_seq, void *project_req_value);
+
+#define PROJECT_VAL_TYPE_CHAR "char"
+#define PROJECT_VAL_TYPE_SHORT "short"
+#define PROJECT_VAL_TYPE_INT "int"
+#define PROJECT_VAL_TYPE_LONG "long"
+#define PROJECT_VAL_TYPE_STRUCT "struct"
+
+
+int project_requirement_global_init(void);
+
+/*
+ must call this function in initialization, only one times,
+ the 'free_cb' should be NULL if 'project_req_val_type' is simple type,
+ otherwise please implement it by youself.
+
+ args:
+ project_req_name: for example, "terminal_tag", "stream_id".
+ project_req_val_type: support "char","short","int","long","struct".
+ free_cb: used to free resource when 'project_req_val_type' is "struct".
+
+
+ return value: 'project_req_id' of this project_req_name, must use this id in following functions.
+ >= 0 : success;
+ -1 : error.
+*/
+int project_producer_register(const char *project_req_name, const char *project_req_val_type, project_req_free_t *free_cb);
+
+/* args and return value same with project_producer_register() */
+int project_customer_register(const char *project_req_name, const char *project_req_val_type);
+
+/*
+ Function project_req_add_struct: 'project_req_value' must be a pointer to heap memory(obtain by malloc).
+
+ return value:
+ 0 : success;
+ -1: error.
+*/
+int project_req_add_char(struct streaminfo *stream, int project_req_id, char project_req_value);
+int project_req_add_short(struct streaminfo *stream, int project_req_id, short project_req_value);
+int project_req_add_int(struct streaminfo *stream, int project_req_id, int project_req_value);
+int project_req_add_long(struct streaminfo *stream, int project_req_id, long project_req_value);
+
+int project_req_add_uchar(struct streaminfo *stream, int project_req_id, unsigned char project_req_value);
+int project_req_add_ushort(struct streaminfo *stream, int project_req_id, unsigned short project_req_value);
+int project_req_add_uint(struct streaminfo *stream, int project_req_id, unsigned int project_req_value);
+int project_req_add_ulong(struct streaminfo *stream, int project_req_id, unsigned long project_req_value);
+
+
+int project_req_add_struct(struct streaminfo *stream, int project_req_id, const void *project_req_value);
+
+
+/*
+ return value:
+ -1(or all bit is '1' in Hex mode, 0xFF, 0xFFFF):
+ maybe error, maybe the actual project_req_value is -1 indeed,
+ must check tht 'errno' in this case,
+ the 'errno' will be set to 'ERANGE' indicate an error.
+ others: success.
+
+ for example:
+ int value = project_req_get_int(stream, req_id);
+ if((-1 == value) && (ERANGE == errno)){
+ error_handle();
+ }else{
+ do_somgthing();
+ }
+
+ for example2:
+ unsigned short value = project_req_get_ushort(stream, req_id);
+ if((0xFF == value) && (ERANGE == errno)){
+ error_handle();
+ }else{
+ do_somgthing();
+ }
+
+*/
+char project_req_get_char(const struct streaminfo *stream, int project_req_id);
+short project_req_get_short(const struct streaminfo *stream, int project_req_id);
+int project_req_get_int(const struct streaminfo *stream, int project_req_id);
+long project_req_get_long(const struct streaminfo *stream, int project_req_id);
+
+unsigned char project_req_get_uchar(const struct streaminfo *stream, int project_req_id);
+unsigned short project_req_get_ushort(const struct streaminfo *stream, int project_req_id);
+unsigned int project_req_get_uint(const struct streaminfo *stream, int project_req_id);
+unsigned long project_req_get_ulong(const struct streaminfo *stream, int project_req_id);
+
+/*
+ return value:
+ NULL : error;
+ others: success.
+*/
+const void *project_req_get_struct(const struct streaminfo *stream, int project_req_id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/lib/comm_audit.so b/lib/comm_audit.so Binary files differnew file mode 100755 index 0000000..518b585 --- /dev/null +++ b/lib/comm_audit.so diff --git a/libmaxminddb.a b/libmaxminddb.a Binary files differnew file mode 100644 index 0000000..77a550b --- /dev/null +++ b/libmaxminddb.a diff --git a/src/.comm_audit.cpp.swp b/src/.comm_audit.cpp.swp Binary files differnew file mode 100644 index 0000000..499ead6 --- /dev/null +++ b/src/.comm_audit.cpp.swp diff --git a/src/cJSON.c b/src/cJSON.c new file mode 100644 index 0000000..772f9af --- /dev/null +++ b/src/cJSON.c @@ -0,0 +1,763 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +#include <string.h> +#include <stdio.h> +#include <math.h> +#include <stdlib.h> +#include <float.h> +#include <limits.h> +#include <ctype.h> +#include "cJSON.h" + +static const char *ep; + +const char *cJSON_GetErrorPtr(void) {return ep;} + +static int cJSON_strcasecmp(const char *s1,const char *s2) +{ + if (!s1) return (s1==s2)?0:1;if (!s2) return 1; + for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; + return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); +} + +// static void *(*cJSON_malloc)(size_t sz) = rt_malloc; +// static void (*cJSON_free)(void *ptr) = rt_free; +static void *(*cJSON_malloc)(size_t sz) = malloc; +static void (*cJSON_free)(void *ptr) = free; + +static char* cJSON_strdup(const char* str) +{ + size_t len; + char* copy; + + len = strlen(str) + 1; + if (!(copy = (char*)cJSON_malloc(len))) return 0; + memcpy(copy,str,len); + return copy; +} + +// void cJSON_InitHooks(cJSON_Hooks* hooks) +// { +// if (!hooks) { /* Reset hooks */ +// cJSON_malloc = rt_malloc; +// cJSON_free = rt_free; +// return; +// } + +// cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:rt_malloc; +// cJSON_free = (hooks->free_fn)?hooks->free_fn:rt_free; +// } +void cJSON_InitHooks(cJSON_Hooks* hooks) +{ + if (!hooks) { /* Reset hooks */ + cJSON_malloc = malloc; + cJSON_free = free; + return; + } + + cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; + cJSON_free = (hooks->free_fn)?hooks->free_fn:free; +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(void) +{ + cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); + if (node) memset(node,0,sizeof(cJSON)); + return node; +} + +/* Delete a cJSON structure. */ +void cJSON_Delete(cJSON *c) +{ + cJSON *next; + while (c) + { + next=c->next; + if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); + if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); + if (!(c->type&cJSON_StringIsConst) && c->string) cJSON_free(c->string); + cJSON_free(c); + c=next; + } +} + +/* Parse the input text to generate a number, and populate the result into item. */ +static const char *parse_number(cJSON *item,const char *num) +{ + double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; + + if (*num=='-') sign=-1,num++; /* Has sign? */ + if (*num=='0') num++; /* is zero */ + if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ + if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ + if (*num=='e' || *num=='E') /* Exponent? */ + { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ + while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ + } + + n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ + + item->valuedouble=n; + item->valueint=(int)n; + item->type=cJSON_Number; + return num; +} + +static int pow2gt (int x) { --x; x|=x>>1; x|=x>>2; x|=x>>4; x|=x>>8; x|=x>>16; return x+1; } + +typedef struct {char *buffer; int length; int offset; } printbuffer; + +static char* ensure(printbuffer *p,int needed) +{ + char *newbuffer;int newsize; + if (!p || !p->buffer) return 0; + needed+=p->offset; + if (needed<=p->length) return p->buffer+p->offset; + + newsize=pow2gt(needed); + newbuffer=(char*)cJSON_malloc(newsize); + if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;} + if (newbuffer) memcpy(newbuffer,p->buffer,p->length); + cJSON_free(p->buffer); + p->length=newsize; + p->buffer=newbuffer; + return newbuffer+p->offset; +} + +static int update(printbuffer *p) +{ + char *str; + if (!p || !p->buffer) return 0; + str=p->buffer+p->offset; + return p->offset+strlen(str); +} + +/* Render the number nicely from the given item into a string. */ +static char *print_number(cJSON *item,printbuffer *p) +{ + char *str=0; + double d=item->valuedouble; + if (d==0) + { + if (p) str=ensure(p,2); + else str=(char*)cJSON_malloc(2); /* special case for 0. */ + if (str) strcpy(str,"0"); + } + else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) + { + if (p) str=ensure(p,21); + else str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ + if (str) sprintf(str,"%d",item->valueint); + } + else + { + if (p) str=ensure(p,64); + else str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ + if (str) + { + if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d); + else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); + else sprintf(str,"%f",d); + } + } + return str; +} + +static unsigned parse_hex4(const char *str) +{ + unsigned h=0; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + h=h<<4;str++; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + h=h<<4;str++; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + h=h<<4;str++; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + return h; +} + +/* Parse the input text into an unescaped cstring, and populate item. */ +static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; +static const char *parse_string(cJSON *item,const char *str) +{ + const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; + if (*str!='\"') {ep=str;return 0;} /* not a string! */ + + while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ + + out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ + if (!out) return 0; + + ptr=str+1;ptr2=out; + while (*ptr!='\"' && *ptr) + { + if (*ptr!='\\') *ptr2++=*ptr++; + else + { + ptr++; + switch (*ptr) + { + case 'b': *ptr2++='\b'; break; + case 'f': *ptr2++='\f'; break; + case 'n': *ptr2++='\n'; break; + case 'r': *ptr2++='\r'; break; + case 't': *ptr2++='\t'; break; + case 'u': /* transcode utf16 to utf8. */ + uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */ + + if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */ + + if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */ + { + if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */ + uc2=parse_hex4(ptr+3);ptr+=6; + if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */ + uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); + } + + len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; + + switch (len) { + case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 1: *--ptr2 =(uc | firstByteMark[len]); + } + ptr2+=len; + break; + default: *ptr2++=*ptr; break; + } + ptr++; + } + } + *ptr2=0; + if (*ptr=='\"') ptr++; + item->valuestring=out; + item->type=cJSON_String; + return ptr; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static char *print_string_ptr(const char *str,printbuffer *p) +{ + const char *ptr;char *ptr2,*out;int len=0,flag=0;unsigned char token; + + for (ptr=str;*ptr;ptr++) flag|=((*ptr>0 && *ptr<32)||(*ptr=='\"')||(*ptr=='\\'))?1:0; + if (!flag) + { + len=ptr-str; + if (p) out=ensure(p,len+3); + else out=(char*)cJSON_malloc(len+3); + if (!out) return 0; + ptr2=out;*ptr2++='\"'; + strcpy(ptr2,str); + ptr2[len]='\"'; + ptr2[len+1]=0; + return out; + } + + if (!str) + { + if (p) out=ensure(p,3); + else out=(char*)cJSON_malloc(3); + if (!out) return 0; + strcpy(out,"\"\""); + return out; + } + ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;} + + if (p) out=ensure(p,len+3); + else out=(char*)cJSON_malloc(len+3); + if (!out) return 0; + + ptr2=out;ptr=str; + *ptr2++='\"'; + while (*ptr) + { + if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; + else + { + *ptr2++='\\'; + switch (token=*ptr++) + { + case '\\': *ptr2++='\\'; break; + case '\"': *ptr2++='\"'; break; + case '\b': *ptr2++='b'; break; + case '\f': *ptr2++='f'; break; + case '\n': *ptr2++='n'; break; + case '\r': *ptr2++='r'; break; + case '\t': *ptr2++='t'; break; + default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ + } + } + } + *ptr2++='\"';*ptr2++=0; + return out; +} +/* Invote print_string_ptr (which is useful) on an item. */ +static char *print_string(cJSON *item,printbuffer *p) {return print_string_ptr(item->valuestring,p);} + +/* Predeclare these prototypes. */ +static const char *parse_value(cJSON *item,const char *value); +static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p); +static const char *parse_array(cJSON *item,const char *value); +static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p); +static const char *parse_object(cJSON *item,const char *value); +static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p); + +/* Utility to jump whitespace and cr/lf */ +static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} + +/* Parse an object - create a new root, and populate. */ +cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated) +{ + const char *end=0; + cJSON *c=cJSON_New_Item(); + ep=0; + if (!c) return 0; /* memory fail */ + + end=parse_value(c,skip(value)); + if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */ + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}} + if (return_parse_end) *return_parse_end=end; + return c; +} +/* Default options for cJSON_Parse */ +cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);} + +/* Render a cJSON item/entity/structure to text. */ +char *cJSON_Print(cJSON *item) {return print_value(item,0,1,0);} +char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0,0);} + +char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt) +{ + printbuffer p; + p.buffer=(char*)cJSON_malloc(prebuffer); + p.length=prebuffer; + p.offset=0; + return print_value(item,0,fmt,&p); + return p.buffer; +} + + +/* Parser core - when encountering text, process appropriately. */ +static const char *parse_value(cJSON *item,const char *value) +{ + if (!value) return 0; /* Fail on null. */ + if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } + if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } + if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } + if (*value=='\"') { return parse_string(item,value); } + if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } + if (*value=='[') { return parse_array(item,value); } + if (*value=='{') { return parse_object(item,value); } + + ep=value;return 0; /* failure. */ +} + +/* Render a value to text. */ +static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p) +{ + char *out=0; + if (!item) return 0; + if (p) + { + switch ((item->type)&255) + { + case cJSON_NULL: {out=ensure(p,5); if (out) strcpy(out,"null"); break;} + case cJSON_False: {out=ensure(p,6); if (out) strcpy(out,"false"); break;} + case cJSON_True: {out=ensure(p,5); if (out) strcpy(out,"true"); break;} + case cJSON_Number: out=print_number(item,p);break; + case cJSON_String: out=print_string(item,p);break; + case cJSON_Array: out=print_array(item,depth,fmt,p);break; + case cJSON_Object: out=print_object(item,depth,fmt,p);break; + } + } + else + { + switch ((item->type)&255) + { + case cJSON_NULL: out=cJSON_strdup("null"); break; + case cJSON_False: out=cJSON_strdup("false");break; + case cJSON_True: out=cJSON_strdup("true"); break; + case cJSON_Number: out=print_number(item,0);break; + case cJSON_String: out=print_string(item,0);break; + case cJSON_Array: out=print_array(item,depth,fmt,0);break; + case cJSON_Object: out=print_object(item,depth,fmt,0);break; + } + } + return out; +} + +/* Build an array from input text. */ +static const char *parse_array(cJSON *item,const char *value) +{ + cJSON *child; + if (*value!='[') {ep=value;return 0;} /* not an array! */ + + item->type=cJSON_Array; + value=skip(value+1); + if (*value==']') return value+1; /* empty array. */ + + item->child=child=cJSON_New_Item(); + if (!item->child) return 0; /* memory fail */ + value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ + if (!value) return 0; + + while (*value==',') + { + cJSON *new_item; + if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ + child->next=new_item;new_item->prev=child;child=new_item; + value=skip(parse_value(child,skip(value+1))); + if (!value) return 0; /* memory fail */ + } + + if (*value==']') return value+1; /* end of array */ + ep=value;return 0; /* malformed. */ +} + +/* Render an array to text */ +static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p) +{ + char **entries; + char *out=0,*ptr,*ret;int len=5; + cJSON *child=item->child; + int numentries=0,i=0,fail=0; + size_t tmplen=0; + + /* How many entries in the array? */ + while (child) numentries++,child=child->next; + /* Explicitly handle numentries==0 */ + if (!numentries) + { + if (p) out=ensure(p,3); + else out=(char*)cJSON_malloc(3); + if (out) strcpy(out,"[]"); + return out; + } + + if (p) + { + /* Compose the output array. */ + i=p->offset; + ptr=ensure(p,1);if (!ptr) return 0; *ptr='['; p->offset++; + child=item->child; + while (child && !fail) + { + print_value(child,depth+1,fmt,p); + p->offset=update(p); + if (child->next) {len=fmt?2:1;ptr=ensure(p,len+1);if (!ptr) return 0;*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;p->offset+=len;} + child=child->next; + } + ptr=ensure(p,2);if (!ptr) return 0; *ptr++=']';*ptr=0; + out=(p->buffer)+i; + } + else + { + /* Allocate an array to hold the values for each */ + entries=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!entries) return 0; + memset(entries,0,numentries*sizeof(char*)); + /* Retrieve all the results: */ + child=item->child; + while (child && !fail) + { + ret=print_value(child,depth+1,fmt,0); + entries[i++]=ret; + if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1; + child=child->next; + } + + /* If we didn't fail, try to malloc the output string */ + if (!fail) out=(char*)cJSON_malloc(len); + /* If that fails, we fail. */ + if (!out) fail=1; + + /* Handle failure. */ + if (fail) + { + for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]); + cJSON_free(entries); + return 0; + } + + /* Compose the output array. */ + *out='['; + ptr=out+1;*ptr=0; + for (i=0;i<numentries;i++) + { + tmplen=strlen(entries[i]);memcpy(ptr,entries[i],tmplen);ptr+=tmplen; + if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;} + cJSON_free(entries[i]); + } + cJSON_free(entries); + *ptr++=']';*ptr++=0; + } + return out; +} + +/* Build an object from the text. */ +static const char *parse_object(cJSON *item,const char *value) +{ + cJSON *child; + if (*value!='{') {ep=value;return 0;} /* not an object! */ + + item->type=cJSON_Object; + value=skip(value+1); + if (*value=='}') return value+1; /* empty array. */ + + item->child=child=cJSON_New_Item(); + if (!item->child) return 0; + value=skip(parse_string(child,skip(value))); + if (!value) return 0; + child->string=child->valuestring;child->valuestring=0; + if (*value!=':') {ep=value;return 0;} /* fail! */ + value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ + if (!value) return 0; + + while (*value==',') + { + cJSON *new_item; + if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ + child->next=new_item;new_item->prev=child;child=new_item; + value=skip(parse_string(child,skip(value+1))); + if (!value) return 0; + child->string=child->valuestring;child->valuestring=0; + if (*value!=':') {ep=value;return 0;} /* fail! */ + value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ + if (!value) return 0; + } + + if (*value=='}') return value+1; /* end of array */ + ep=value;return 0; /* malformed. */ +} + +/* Render an object to text. */ +static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p) +{ + char **entries=0,**names=0; + char *out=0,*ptr,*ret,*str;int len=7,i=0,j; + cJSON *child=item->child; + int numentries=0,fail=0; + size_t tmplen=0; + /* Count the number of entries. */ + while (child) numentries++,child=child->next; + /* Explicitly handle empty object case */ + if (!numentries) + { + if (p) out=ensure(p,fmt?depth+4:3); + else out=(char*)cJSON_malloc(fmt?depth+4:3); + if (!out) return 0; + ptr=out;*ptr++='{'; + if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';} + *ptr++='}';*ptr++=0; + return out; + } + if (p) + { + /* Compose the output: */ + i=p->offset; + len=fmt?2:1; ptr=ensure(p,len+1); if (!ptr) return 0; + *ptr++='{'; if (fmt) *ptr++='\n'; *ptr=0; p->offset+=len; + child=item->child;depth++; + while (child) + { + if (fmt) + { + ptr=ensure(p,depth); if (!ptr) return 0; + for (j=0;j<depth;j++) *ptr++='\t'; + p->offset+=depth; + } + print_string_ptr(child->string,p); + p->offset=update(p); + + len=fmt?2:1; + ptr=ensure(p,len); if (!ptr) return 0; + *ptr++=':';if (fmt) *ptr++='\t'; + p->offset+=len; + + print_value(child,depth,fmt,p); + p->offset=update(p); + + len=(fmt?1:0)+(child->next?1:0); + ptr=ensure(p,len+1); if (!ptr) return 0; + if (child->next) *ptr++=','; + if (fmt) *ptr++='\n';*ptr=0; + p->offset+=len; + child=child->next; + } + ptr=ensure(p,fmt?(depth+1):2); if (!ptr) return 0; + if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t'; + *ptr++='}';*ptr=0; + out=(p->buffer)+i; + } + else + { + /* Allocate space for the names and the objects */ + entries=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!entries) return 0; + names=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!names) {cJSON_free(entries);return 0;} + memset(entries,0,sizeof(char*)*numentries); + memset(names,0,sizeof(char*)*numentries); + + /* Collect all the results into our arrays: */ + child=item->child;depth++;if (fmt) len+=depth; + while (child) + { + names[i]=str=print_string_ptr(child->string,0); + entries[i++]=ret=print_value(child,depth,fmt,0); + if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1; + child=child->next; + } + + /* Try to allocate the output string */ + if (!fail) out=(char*)cJSON_malloc(len); + if (!out) fail=1; + + /* Handle failure */ + if (fail) + { + for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);} + cJSON_free(names);cJSON_free(entries); + return 0; + } + + /* Compose the output: */ + *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0; + for (i=0;i<numentries;i++) + { + if (fmt) for (j=0;j<depth;j++) *ptr++='\t'; + tmplen=strlen(names[i]);memcpy(ptr,names[i],tmplen);ptr+=tmplen; + *ptr++=':';if (fmt) *ptr++='\t'; + strcpy(ptr,entries[i]);ptr+=strlen(entries[i]); + if (i!=numentries-1) *ptr++=','; + if (fmt) *ptr++='\n';*ptr=0; + cJSON_free(names[i]);cJSON_free(entries[i]); + } + + cJSON_free(names);cJSON_free(entries); + if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t'; + *ptr++='}';*ptr++=0; + } + return out; +} + +/* Get Array size/item / object item. */ +int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;} +cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} +cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} +/* Utility for handling references. */ +static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} + +/* Add item to array/object. */ +void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} +void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} +void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (!(item->type&cJSON_StringIsConst) && item->string) cJSON_free(item->string);item->string=(char*)string;item->type|=cJSON_StringIsConst;cJSON_AddItemToArray(object,item);} +void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} +void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} + +cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; + if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} +void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} +cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;} +void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} + +/* Replace array/object items with new ones. */ +void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) {cJSON_AddItemToArray(array,newitem);return;} + newitem->next=c;newitem->prev=c->prev;c->prev=newitem;if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;} +void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; + newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; + if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} +void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} + +/* Create basic types: */ +cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} +cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} +cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} +cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} +cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} +cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} +cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} +cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} + +/* Create Arrays: */ +cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} + +/* Duplication */ +cJSON *cJSON_Duplicate(cJSON *item,int recurse) +{ + cJSON *newitem,*cptr,*nptr=0,*newchild; + /* Bail on bad ptr */ + if (!item) return 0; + /* Create new item */ + newitem=cJSON_New_Item(); + if (!newitem) return 0; + /* Copy over all vars */ + newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble; + if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}} + if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}} + /* If non-recursive, then we're done! */ + if (!recurse) return newitem; + /* Walk the ->next chain for the child. */ + cptr=item->child; + while (cptr) + { + newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) {cJSON_Delete(newitem);return 0;} + if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */ + cptr=cptr->next; + } + return newitem; +} + +void cJSON_Minify(char *json) +{ + char *into=json; + while (*json) + { + if (*json==' ') json++; + else if (*json=='\t') json++; /* Whitespace characters. */ + else if (*json=='\r') json++; + else if (*json=='\n') json++; + else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; /* double-slash comments, to end of line. */ + else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} /* multiline comments. */ + else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} /* string literals, which are \" sensitive. */ + else *into++=*json++; /* All other characters. */ + } + *into=0; /* and null-terminate. */ +} diff --git a/src/comm_audit.cpp b/src/comm_audit.cpp new file mode 100644 index 0000000..5ffaa05 --- /dev/null +++ b/src/comm_audit.cpp @@ -0,0 +1,968 @@ +/*
+ * comm_audit.cpp
+ *
+ * Created on: 2017-8-14
+ * Last Modified: 2017-11-24
+ * Author: zhangxi
+ */
+
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <atomic>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include "project_requirement.h"
+#include "identify.h"
+#include "cJSON.h"
+#include "comm_audit.h"
+#include "maxminddb.h"
+//#define LOG_DEBUG 0
+
+using namespace std;
+
+int COMM_AUDIT_VERSION_20171124 = 0;
+
+comm_prog_configure_t g_comm_prog_configure;
+comm_prog_runtime_parameter_t g_comm_prog_para;
+atomic_flag lock = ATOMIC_FLAG_INIT;
+
+static int log_nums;
+static int times = 0;
+static int log = 0;
+static int now = 0;
+// static char FDIR[12]={0};
+
+
+//获取IP归属地
+int get_ip_coun(char * filename, char *ip_address, char ** name_en)
+{
+ MMDB_s mmdb;
+ int status = MMDB_open(filename, MMDB_MODE_MMAP, &mmdb);
+
+ if(MMDB_SUCCESS != status)
+ {
+ //fprintf(stderr, "\n Can't open %s - %s\n",filename, MMDB_strerror(status));
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "ERROR", "Can't open %s - %s\n",filename, MMDB_strerror(status));
+ if(MMDB_IO_ERROR == status)
+ {
+ //fprintf(stderr, "IO error: %s\n", strerror(errno));
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "ERROR","IO error: %s\n", strerror(errno));
+ }
+ return 1; //error
+ }
+
+ int gai_error, mmdb_error;
+
+ MMDB_lookup_result_s result =
+ MMDB_lookup_string(&mmdb, ip_address, &gai_error, &mmdb_error);
+
+ if (0 != gai_error)
+ {
+ fprintf(stderr, "\n Error from getaddrinfo for %s - %s\n\n", ip_address, gai_strerror(gai_error));
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "ERROR","Error from getaddrinfo for %s - %s", ip_address, gai_strerror(gai_error));
+ return 2; //error
+ }
+
+ if (MMDB_SUCCESS != mmdb_error)
+ {
+ fprintf(stderr,"\n Got an error from libmaxminddb: %s\n\n", MMDB_strerror(mmdb_error));
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "ERROR","Got an error from libmaxminddb: %s", MMDB_strerror(mmdb_error));
+ return 3; //error
+ }
+
+ MMDB_entry_data_s entry_data;
+
+ int exit_code = 0;
+ if (result.found_entry)
+ {
+
+ int status = MMDB_get_value(&result.entry, &entry_data, "COUNTRY", NULL);
+
+ if (MMDB_SUCCESS != status)
+ {
+ fprintf(stderr,"Got an error looking up the entry data - %s\n", MMDB_strerror(status));
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "ERROR","Got an error looking up the entry data - %s\n", MMDB_strerror(status));
+ exit_code = 4;
+ goto end;
+ }
+
+ if (entry_data.has_data)
+ {
+ *name_en = (char *)malloc(sizeof(entry_data.data_size + 1));
+ memset(*name_en, '\0', sizeof(entry_data.data_size + 1));
+ memcpy(*name_en, entry_data.utf8_string, entry_data.data_size);
+ //printf ("%s\n", name_en);
+ }
+ }
+ else
+ {
+ //fprintf(stderr,"\n No entry for this IP address (%s) was found\n\n", ip_address);
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "ERROR","No entry for this IP address (%s) was found", ip_address);
+ exit_code = 5;
+ }
+
+end:
+ MMDB_close(&mmdb);
+ //exit(exit_code);
+ return exit_code;
+}
+
+
+//读取json格式文件
+void parseJson(char * buf)
+{
+ if(NULL == buf)
+ {
+ return;
+ }
+ cJSON * json = cJSON_Parse(buf);
+ if (!json)
+ {
+ printf("JSON FILE READ FAIL! PLEASE CHECK net_log_upload_pz.txt's FORMAT.\n");
+ printf("USE LAST UPLOAD_PZ NOW.\n");
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "UPLOAD_PZ JSON FILE READ FAIL!ERROR NUM IS %s.", strerror(errno));
+ }
+ else
+ {
+ int size = cJSON_GetArraySize(json);
+ cJSON *object;
+ for(int i = 0; i < size; i++)
+ {
+ object = cJSON_GetArrayItem(json,i);
+ int interval = cJSON_GetObjectItem(object, "interval")->valueint;
+ int max_num = cJSON_GetObjectItem(object, "num")->valueint;
+ if(interval != g_comm_prog_configure.write_interval || max_num != g_comm_prog_configure.write_max_num)
+ {
+ g_comm_prog_configure.write_interval = interval;
+ g_comm_prog_configure.write_max_num = max_num;
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "INFO", "UPLOAD_PZ JSON FILE READ SUCC! interval is %d, num is %d.", g_comm_prog_configure.write_interval, g_comm_prog_configure.write_max_num);
+ }
+ }
+ }
+
+ cJSON_Delete(json);
+}
+
+
+void read_json_file(int num)
+{
+
+ string read_path = g_comm_prog_configure.upload_pz_path;
+ if (read_path[read_path.size() - 1] != '/')
+ read_path+='/';
+
+ fstream handle;
+ string in_file_name = read_path + "net_log_upload_pz.txt";
+ handle.open(in_file_name.c_str(), ios::binary|ios::in);
+ if(handle.is_open())
+ {
+ char *buf = new char[MAX_LEN];
+ handle.read(buf, MAX_LEN);
+ parseJson(buf);
+ handle.close();
+
+ delete buf;
+ }
+
+}
+
+// 定时读取json线程
+void *set_timer(void * pParam)
+{
+ signal(SIGALRM, read_json_file);
+
+ struct itimerval tick;
+ tick.it_value.tv_sec = 1; //1秒钟后将启动定时器
+ tick.it_value.tv_usec = 0;
+ tick.it_interval.tv_sec = g_comm_prog_configure.read_interval; //定时器启动后,每隔指定秒数将执行相应的函数
+ tick.it_interval.tv_usec = 0;
+
+ //setitimer将触发SIGALRM信号
+ int ret = setitimer(ITIMER_REAL, &tick, NULL);
+
+ if ( ret != 0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "SET TIMER ERROR! ERROR NUM IS %s.", strerror(errno));
+ return NULL;
+ }
+
+ while(1){sleep(1);}
+
+}
+
+// 写数据
+int send_data(htable_data_t* send_data, FILE *fp)
+{
+ log = 1;
+ long long EndTime;
+ EndTime = time(NULL);
+
+ char stime[24];
+ struct tm stm;
+ time_t sTime = (time_t)send_data->start_time;
+ localtime_r(&sTime, &stm);
+ sprintf(stime, "%d-%02d-%02d %d:%d:%d", stm.tm_year+1900, stm.tm_mon+1, stm.tm_mday, stm.tm_hour, stm.tm_min, stm.tm_sec);
+
+ char etime[24];
+ struct tm ptm;
+ time_t eTime;
+ if(send_data->end_time == 0)
+ eTime = (time_t)EndTime;
+ else
+ eTime = (time_t)send_data->end_time;
+ localtime_r(&eTime, &ptm);
+ sprintf(etime, "%d-%02d-%02d %d:%d:%d", ptm.tm_year+1900, ptm.tm_mon+1, ptm.tm_mday, ptm.tm_hour, ptm.tm_min, ptm.tm_sec);
+ // memcpy(stat_info->time_data.end_time, etime, 24);
+
+ char sendInnerIP[IPLEN]={0};
+ inet_ntop(AF_INET, &send_data->inner_ip, sendInnerIP ,IPLEN);
+ // sprintf(sendInnerIP, "%s", inet_ntop(AF_INET, &send_data->inner_ip, sendInnerIP ,IPLEN));
+ char sendExtIP[IPLEN]={0};
+ inet_ntop(AF_INET, &send_data->ext_ip, sendExtIP ,IPLEN);
+ // sprintf(sendExtIP, "%s", inet_ntop(AF_INET, &send_data->ext_ip, sendExtIP ,IPLEN));
+
+ string app = APP_TYPE(send_data->app);
+ string protocol = STREAM_TYPE(send_data->protocol);
+ string tcp_flag = TCP_FLAG(send_data->tcp_flag);
+
+ fprintf(fp, "%s#%u#%s#%s#%u#%s#%s#%s#%s#%llu#%llu#%llu#%llu#%s#%s\n",
+ sendInnerIP,
+ ntohs(send_data->inner_port),
+ send_data->inner_mac,
+ sendExtIP,
+ ntohs(send_data->ext_port),
+ send_data->ext_mac,
+ protocol.c_str(),
+ app.c_str(),
+ tcp_flag.c_str(),
+ send_data->in_bytes,
+ send_data->out_bytes,
+ send_data->in_pkts,
+ send_data->out_pkts,
+ stime,
+ etime
+ );
+ // log_nums条记录写入一个txt
+ if(log_nums < g_comm_prog_configure.write_max_num-1)
+ log_nums++;
+ else
+ {
+ log_nums = 0;
+ times++;
+ }
+
+ return 0;
+}
+
+// 遍历哈希表写文件
+void iterate_cb(const uchar * key, uint size, void * data, void *arg)
+{
+ htable_data_t* info = (htable_data_t*)data;
+ char * writetime = ((del_para_t*)arg)->writetime;
+ int thread_seq = ((del_para_t*)arg)->thread_seq;
+ char writefile[50];
+ writefile[0]='\0';
+
+ // string write_path = g_comm_prog_configure.upload_log_path;
+ // if (write_path[write_path.size() - 1] != '/')
+ // write_path+='/';
+ // #ifdef LOG_DEBUG
+ // cout<<"write_path:"<<write_path<<endl;
+ // #endif
+
+ string tmp_log_path = g_comm_prog_configure.tmp_log_path;
+ if (tmp_log_path[tmp_log_path.size() - 1] != '/')
+ tmp_log_path+='/';
+#ifdef LOG_DEBUG
+ cout<<"tmp_log_path:"<<tmp_log_path<<endl;
+#endif
+
+ sprintf(writefile, "%s%s-%d.txt", tmp_log_path.c_str(), writetime, times);
+#ifdef LOG_DEBUG
+ cout<<"writefile:"<<writefile<<endl;
+#endif
+
+ FILE *fp = fopen(writefile, "a+");
+ if(fp != NULL)
+ {
+ send_data(info, fp);
+ }
+ else
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "FOPEN ERROR! ERROR NUM IS %s.", strerror(errno));
+ }
+ fclose(fp);
+ fp = NULL;
+
+ /*
+ if(log_nums == 0 && log == 1)
+ {
+ g_comm_prog_para.last_send_time = time(NULL);
+
+ char cmd[200] = {0};
+ sprintf(cmd, "cd %s; gzip -q %s-%d.txt; mv *.gz %s%s", g_comm_prog_configure.tmp_log_path, writetime, times-1, write_path.c_str(), FDIR);
+ // system(cmd);
+ FILE * ret = popen(cmd, "w");
+ if(!ret)
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "%s IS FAILED! ERROR NUM IS %s",cmd, strerror(errno));
+ else
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_INFO, "INFO", "Pack %s/%s.gz is submit.", FDIR, writetime);
+ pclose(ret);
+ }
+ */
+
+ if(MESA_htable_del(g_comm_prog_para.htable_handle[thread_seq][1], key, size, NULL) < 0)
+ {
+ perror("MESA_htable_del()");
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "MESA_htable_del error!");
+ }
+}
+
+// 写日志线程
+void * thread_time(void * pParam)
+{
+ while(1)
+ {
+
+ int last;
+ if(g_comm_prog_configure.write_interval <= 0)
+ {
+ g_comm_prog_configure.write_interval = 1;
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_INFO, "INFO", "write_interval arg is not more than 0! reset interval to 1.");
+ }
+
+ time_t sTime = (time_t)g_comm_prog_para.last_send_time;
+ struct tm stm;
+ localtime_r(&sTime, &stm);
+ last = stm.tm_hour * 10000 + stm.tm_min * 100 + stm.tm_sec;
+
+ // sprintf(FDIR, "%d-%02d-%02d", stm.tm_year+1900, stm.tm_mon+1, stm.tm_mday);
+ // char mkdir[50]={0};
+ // sprintf(mkdir, "mkdir -p %s/%s", g_comm_prog_configure.upload_log_path, FDIR);
+ // FILE * ret = popen(mkdir, "w");
+ // if(!ret)
+ // MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "%s FAILED! ERROR IS %s",mkdir, strerror(errno));
+ // pclose(ret);
+
+ char FNAME[10];
+ char TXT[8];
+ sprintf(FNAME, "%d-%d-%d", stm.tm_hour, stm.tm_min, stm.tm_sec);
+ //sprintf(TXT, "%d-%d-%d", stm.tm_hour, stm.tm_min, stm.tm_sec);
+ sprintf(TXT, "%d%02d%02d", stm.tm_year+1900, stm.tm_mon+1, stm.tm_mday);
+ //sprintf(etime, "%d-%d-%d %d:%d:%d", ptm.tm_year+1900, ptm.tm_mon+1, ptm.tm_mday, ptm.tm_hour, ptm.tm_min, ptm.tm_sec);
+
+ // times = 1;
+ log_nums = 0;
+ if(g_comm_prog_configure.write_max_num <= 0)
+ {
+ g_comm_prog_configure.write_max_num = 1000;
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_INFO, "INFO", "write_interval arg is not more than 0! reset interval to 1000.");
+ }
+
+ sleep(g_comm_prog_configure.sleep);
+
+ // pthread_mutex_lock(&g_comm_prog_para.mutex);
+ while (lock.test_and_set(std::memory_order_acquire)); // spin
+ for(int i = 0; i < g_comm_prog_para.thread_num; i++)
+ {
+ MESA_htable_handle tmp = g_comm_prog_para.htable_handle[i][0];
+ g_comm_prog_para.htable_handle[i][0] = g_comm_prog_para.htable_handle[i][1];
+ g_comm_prog_para.htable_handle[i][1] = tmp;
+ }
+ lock.clear(std::memory_order_release); // release lock
+ // pthread_mutex_unlock(&g_comm_prog_para.mutex);
+
+ for(int i = 0; i < g_comm_prog_para.thread_num; i++)
+ {
+ del_para_t arg;
+ arg.writetime = TXT;
+ arg.thread_seq = i;
+ MESA_htable_iterate(g_comm_prog_para.htable_handle[i][1], iterate_cb, (void *)&arg);
+ }
+
+ sTime = (time_t)g_comm_prog_para.last_send_time;
+ localtime_r(&sTime, &stm);
+ last = stm.tm_hour * 10000 + stm.tm_min * 100 + stm.tm_sec;
+
+ long long NowTime = time(NULL);
+ time_t eTime = (time_t)NowTime;
+ struct tm ptm;
+ localtime_r(&eTime, &ptm);
+ now = ptm.tm_hour * 10000 + ptm.tm_min * 100 + ptm.tm_sec;
+
+
+ if(log == 1)
+ {
+ if(now - last >= g_comm_prog_configure.write_interval * 100)
+ {
+ /*
+ char cmd[200] = {0};
+ string log_path = g_comm_prog_configure.upload_log_path;
+ if (log_path[log_path.size() - 1] != '/')
+ log_path+='/';
+#ifdef LOG_DEBUG
+cout<<"log_path:"<<log_path<<endl;
+#endif
+
+sprintf(cmd, "cd %s; count=`ls|grep .txt|wc -l`; if [[ $count -gt 0 ]]; then tar -zcf %s%s/%s.tar.gz *.txt; rm -f *.txt; fi;", \
+g_comm_prog_configure.tmp_log_path, log_path.c_str(), FDIR, FNAME);
+#ifdef LOG_DEBUG
+cout<<cmd<<endl;
+#endif
+
+FILE * ret = popen(cmd, "w");
+if(!ret)
+MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "MKDIR IS FAILED! ERROR IS %s",strerror(errno));
+else
+MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_INFO, "INFO", "Pack %s/%s.tar.gz is submit.", FDIR, FNAME);
+pclose(ret);
+*/
+ times++;
+ g_comm_prog_para.last_send_time = time(NULL);
+ }
+ else if(now < last)
+ {
+ times = 1;
+ g_comm_prog_para.last_send_time = time(NULL);
+ }
+ }
+ }
+ return NULL;
+
+}
+
+
+static long search_cb(void* data, const uchar* key, uint size, void* arg)
+{
+ if(data == NULL)
+ return -1;
+
+ struct streaminfo * a_stream = (struct streaminfo *)((htable_search_arg *)arg)->stream;
+ void * a_packet = (void *)((htable_search_arg *)arg)->packet;
+ int is_end = ((htable_search_arg *)arg)->is_end;
+ htable_data_t * info = (htable_data_t *)data;
+
+ if(a_stream->type == STREAM_TYPE_TCP)
+ {
+ struct tcpdetail* a_tcp = (struct tcpdetail*)(a_stream->ptcpdetail);
+ if(a_stream->curdir == DIR_C2S)//C2S:INNER TO EXTERN
+ {
+ info->out_bytes += a_tcp->datalen;
+ info->out_pkts++;
+ }
+ else
+ {
+ info->in_bytes += a_tcp->datalen;
+ info->in_pkts++;
+ }
+ // struct tcpdetail* a_tcp = (struct tcpdetail*)(a_stream->ptcpdetail);
+ // info->tcp_flag = info->tcp_flag & a_stream->stream_state;
+ if(a_packet != NULL)
+ {
+ struct tcphdr* tcp_header = (struct tcphdr*)(a_packet + sizeof(struct iphdr));
+ info->tcp_flag = 32*tcp_header->urg + 16*tcp_header->ack + 8*tcp_header->psh + 4*tcp_header->rst + \
+ 2*tcp_header->syn + tcp_header->fin;
+ }
+ }
+ else
+ {
+ struct udpdetail* a_udp = (struct udpdetail*)(a_stream->pudpdetail);
+ if(a_stream->curdir == DIR_C2S)//C2S:INNER TO EXTERN
+ {
+ info->out_bytes += a_udp->datalen;
+ info->out_pkts++;
+ }
+ else
+ {
+ info->in_bytes += a_udp->datalen;
+ info->in_pkts++;
+ }
+ info->tcp_flag = 0;
+ }
+ if(is_end)
+ info->end_time = time(NULL);
+
+ return 0;
+}
+
+
+
+int judge_ip_location(unsigned int inner_ip, char ** inner_name_en, unsigned int ext_ip, char ** ext_name_en)
+{
+ char innerIP[IPLEN] = {0};
+ char extIP[IPLEN] = {0};
+ int res1 = 0;
+ int res2 = 0;
+ //char * inner_name_en = NULL;
+ //char * ext_name_en = NULL;
+ inet_ntop(AF_INET, &inner_ip, innerIP ,IPLEN);
+ inet_ntop(AF_INET, &ext_ip, extIP ,IPLEN);
+ res1 = get_ip_coun(g_comm_prog_configure.mmdb_path, innerIP, inner_name_en);
+ res2 = get_ip_coun(g_comm_prog_configure.mmdb_path, extIP, ext_name_en);
+ if(0 != res1 && 0 != res2)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_INFO, "JUDGE_IP", "judge_innerip_location INNER[%s] EXT[%s] error!", innerIP, extIP);
+ return 0;
+ }
+ if ((NULL!=*inner_name_en && 0!=strncmp(*inner_name_en, "China", 5)) || (NULL!=*ext_name_en && 0 != strncmp(*ext_name_en, "China", 5))) //有境外IP
+ {
+ return 1;
+ }
+ else //全部都是境内IP
+ {
+ return 2;
+ }
+}
+
+
+void time_mode_op(struct streaminfo* a_stream, int thread_seq, void * a_packet, int state, int is_end)
+{
+ stDntyProInfo * pro_info = (stDntyProInfo *)project_req_get_struct(a_stream,g_comm_prog_para.project_id_pro);
+ if(pro_info == NULL)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "project_req_get_struct is NULL. LACK OF IDENTIFY'S CONF!");
+ return ;
+ }
+
+ long ret;
+ int judge_res = 0;
+
+ htable_search_arg arg;
+ arg.stream = a_stream;
+ arg.packet = a_packet;
+
+ // pthread_mutex_lock(&g_comm_prog_para.mutex);
+ if(NULL == MESA_htable_search_cb(g_comm_prog_para.htable_handle[thread_seq][0], (unsigned char*)&a_stream->addr, sizeof(a_stream->addr), search_cb, (void *)&arg, &ret))
+ {
+ htable_data_t * value = (htable_data_t*)calloc(1, sizeof(htable_data_t));
+ if(a_stream->addr.addrtype == ADDR_TYPE_IPV4)
+ {
+ value->inner_ip = a_stream->addr.tuple4_v4->saddr;
+ value->inner_port = a_stream->addr.tuple4_v4->source;
+ value->ext_ip = a_stream->addr.tuple4_v4->daddr;
+ value->ext_port = a_stream->addr.tuple4_v4->dest;
+ if(g_comm_prog_configure.flag == 0) //flag == 0, 只记录包含境外IP的通联数据
+ {
+ char * inner_name_en = NULL;
+ char * ext_name_en = NULL;
+ judge_res = judge_ip_location(value->inner_ip, &inner_name_en, value->ext_ip, &ext_name_en);
+ if(judge_res == 0) //查找IP归属失败,仍然记录
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "find IP[%u or %u] location error!.", value->inner_ip, value->ext_ip);
+ }
+ else if(judge_res == 1) //有境外IP,需要记录
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "find IP1[%u:%s] IP2[%u:%s].", value->inner_ip,inner_name_en, value->ext_ip, ext_name_en);
+ }
+ else if(judge_res == 2) //全都是境内IP,不做记录,直接返回
+ {
+ return ;
+ }
+ }
+ }
+ if(a_stream->type == STREAM_TYPE_TCP)
+ {
+ struct tcpdetail* a_tcp = (struct tcpdetail*)(a_stream->ptcpdetail);
+ if(a_stream->routedir == DIR_C2S)//C2S:INNER TO EXTERN
+ {
+ value->in_bytes = 0;
+ value->in_pkts = 0;
+ value->out_bytes = a_tcp->datalen;
+ value->out_pkts = 1;
+ }
+ else
+ {
+ value->in_bytes = a_tcp->datalen;
+ value->in_pkts = 1;
+ value->out_bytes = 0;
+ value->out_pkts = 0;
+ }
+ if(a_packet != NULL)
+ {
+ struct tcphdr* tcp_header = (struct tcphdr*)(a_packet + sizeof(struct iphdr));
+ value->tcp_flag = 32*tcp_header->urg + 16*tcp_header->ack + 8*tcp_header->psh + 4*tcp_header->rst + 2*tcp_header->syn + tcp_header->fin;
+ }
+ }
+ else
+ {
+ struct udpdetail* a_udp = (struct udpdetail*)(a_stream->pudpdetail);
+ if(a_stream->routedir == DIR_C2S)//C2S:INNER TO EXTERN
+ {
+ value->in_bytes = 0;
+ value->in_pkts = 0;
+ value->out_bytes = a_udp->datalen;
+ value->out_pkts = 1;
+ }
+ else
+ {
+ value->in_bytes = a_udp->datalen;
+ value->in_pkts = 1;
+ value->out_bytes = 0;
+ value->out_pkts = 0;
+ }
+ value->tcp_flag = 0;
+ }
+
+ value->protocol = a_stream->type;
+ value->app = pro_info->protocol_type;
+
+ struct streaminfo *father = a_stream->pfather;
+ while(father)
+ {
+ if(father->addr.addrtype != ADDR_TYPE_MAC)
+ {
+ father = father->pfather;
+ continue;
+ }
+ else
+ {
+ memset(value->inner_mac, 0, 60);
+ sprintf(value->inner_mac, "%02x-%02x-%02x-%02x-%02x-%02x", father->addr.mac->src_mac[0], father->addr.mac->src_mac[1],\
+ father->addr.mac->src_mac[2], father->addr.mac->src_mac[3], father->addr.mac->src_mac[4], father->addr.mac->src_mac[5]);
+ memset(value->ext_mac, 0, 60);
+ sprintf(value->ext_mac, "%02x-%02x-%02x-%02x-%02x-%02x", father->addr.mac->dst_mac[0], father->addr.mac->dst_mac[1],\
+ father->addr.mac->dst_mac[2], father->addr.mac->dst_mac[3], father->addr.mac->dst_mac[4], father->addr.mac->dst_mac[5]);
+ break;
+ }
+ }
+
+ value->start_time = time(NULL);
+ value->end_time = 0;
+
+ if(MESA_htable_add(g_comm_prog_para.htable_handle[thread_seq][0], (const unsigned char *)&a_stream->addr, \
+ sizeof(a_stream->addr), (void *)value) < 0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "htable_add error.ERROR IS %s.", strerror(errno));
+ free(value);
+ value = NULL;
+ }
+ }
+ // pthread_mutex_unlock(&g_comm_prog_para.mutex);
+ // free(arg);
+ // arg = NULL;
+}
+
+
+char op_state_data(struct streaminfo *a_stream, void **pme, int thread_seq, void *a_packet, int state, int is_end)
+{
+ // struct tcpdetail *pdetail = (struct tcpdetail*)a_stream->ptcpdetail;
+ // comm_audit_t* stat_info = (comm_audit_t*)(*pme);
+ // assert(stat_info != NULL);
+
+ if(a_packet == NULL && state != OP_STATE_CLOSE)
+ return APP_STATE_GIVEME;
+
+ time_mode_op(a_stream, thread_seq, a_packet, state, is_end);
+
+ return APP_STATE_GIVEME;
+}
+
+// char op_state_pending(struct streaminfo *a_stream, void **pme, int thread_seq,void *a_packet, int state, int is_end)
+// {
+// // init_pme_info(pme);
+
+// op_state_data(a_stream, pme, thread_seq, a_packet, state, is_end);
+
+// return APP_STATE_GIVEME;
+// }
+
+
+char op_state_close(struct streaminfo *a_stream, void **pme, int thread_seq,void *a_packet, int state, int is_end)
+{
+ op_state_data(a_stream, pme, thread_seq, a_packet, state, is_end);
+
+ // free_pme_info(pme);
+
+ return APP_STATE_DROPME;
+}
+
+
+char COMM_AUDIT_ENTRY(struct streaminfo *a_stream, void **pme, int thread_seq, void *a_packet)
+{
+ if(g_comm_prog_configure.flag == 2) //flag == 2,不记录任何通联数据,直接返回
+ {
+ return APP_STATE_DROPME;
+ }
+ char ret = APP_STATE_GIVEME;
+ int state;
+ if(a_stream->type == STREAM_TYPE_TCP)
+ state = a_stream->pktstate;
+ else
+ state = a_stream->opstate;
+ int is_end = 0;
+ switch(state)
+ {
+ case OP_STATE_PENDING:
+ case OP_STATE_DATA:
+ ret = op_state_data(a_stream, pme, thread_seq, a_packet, state, is_end);
+ break;
+
+ case OP_STATE_CLOSE:
+ is_end=1;
+ ret = op_state_close(a_stream, pme, thread_seq, a_packet, state, is_end);
+ break;
+
+ default:
+ ret = APP_STATE_DROPME;
+ break;
+ }
+
+ return ret;
+}
+
+void htable_del1(const uchar * key, uint size, void * data, void * arg)
+{
+ int thread_seq = *(int*)arg;
+ if(MESA_htable_del(g_comm_prog_para.htable_handle[thread_seq][0], key, size, NULL) < 0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "MESA_htable_del error!");
+ }
+}
+
+void htable_del2(const uchar * key, uint size, void * data, void * arg)
+{
+ int thread_seq = *(int*)arg;
+ if(MESA_htable_del(g_comm_prog_para.htable_handle[thread_seq][1], key, size, NULL) < 0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "MESA_htable_del error!");
+ }
+}
+
+void COMM_AUDIT_DESTROY()
+{
+
+ // free(g_comm_prog_configure.upload_log_path);
+ free(g_comm_prog_configure.tmp_log_path);
+ free(g_comm_prog_configure.upload_pz_path);
+
+ for(int i = 0; i < g_comm_prog_para.thread_num; i++)
+ {
+ if(MESA_htable_iterate(g_comm_prog_para.htable_handle[i][0], htable_del1, (void*)&i) < 0)
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "COMM_AUDIT_DESTROY. MESA_htable_iterate error!");
+ // printf("iterate error!\n");
+ if(MESA_htable_destroy(g_comm_prog_para.htable_handle[i][0], NULL) < 0)
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "COMM_AUDIT_DESTROY. MESA_htable_destroy error!");
+ // printf("destroy error!\n");
+
+ if(MESA_htable_iterate(g_comm_prog_para.htable_handle[i][1], htable_del2, (void*)&i) < 0)
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "COMM_AUDIT_DESTROY. MESA_htable_iterate error!");
+ // printf("iterate error!\n");
+ if(MESA_htable_destroy(g_comm_prog_para.htable_handle[i][1], NULL) < 0)
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "COMM_AUDIT_DESTROY. MESA_htable_destroy error!");
+ // printf("destroy error!\n");
+ }
+ for(int i = 0; i < g_comm_prog_para.thread_num; i++)
+ free(g_comm_prog_para.htable_handle[i]);
+ free(g_comm_prog_para.htable_handle);
+
+ pthread_exit(NULL);
+ //printf("destroy COMM_AUDIT_DESTROY success!\n");
+
+}
+
+void htable_free(void * data)
+{
+ htable_data_t * info = (htable_data_t *)data;
+ free(info);
+ data = NULL;
+}
+
+int init_hash_table()
+{
+ MESA_htable_handle ** handle = (MESA_htable_handle**)malloc(g_comm_prog_para.thread_num*sizeof(MESA_htable_handle*));
+ for(int i = 0; i < g_comm_prog_para.thread_num; i++)
+ handle[i] = (MESA_htable_handle*)malloc(2 * sizeof(MESA_htable_handle));
+ for(int i = 0; i < g_comm_prog_para.thread_num; i++)
+ {
+ MESA_htable_create_args_t htable_args1;
+ memset(&htable_args1, 0, sizeof(htable_args1));
+ htable_args1.recursive = 1;
+ htable_args1.thread_safe = 0;
+ htable_args1.hash_slot_size = 4096*4096;
+ htable_args1.max_elem_num = g_comm_prog_configure.htable_size;
+ htable_args1.data_free = htable_free;
+ htable_args1.data_expire_with_condition = NULL;
+ htable_args1.eliminate_type = HASH_ELIMINATE_ALGO_LRU;
+ htable_args1.expire_time = 0;
+ handle[i][0] = MESA_htable_create(&htable_args1, sizeof(htable_args1));
+ if(handle[i][0] == NULL)
+ return -1;
+
+ MESA_htable_create_args_t htable_args2;
+ memset(&htable_args2, 0, sizeof(htable_args2));
+ htable_args2.recursive = 1;
+ htable_args2.thread_safe = 0;
+ htable_args2.hash_slot_size = 4096*4096;
+ htable_args2.max_elem_num = g_comm_prog_configure.htable_size;
+ htable_args2.data_free = htable_free;
+ htable_args2.data_expire_with_condition = NULL;
+ htable_args2.eliminate_type = HASH_ELIMINATE_ALGO_LRU;
+ htable_args2.expire_time = 0;
+ handle[i][1] = MESA_htable_create(&htable_args2, sizeof(htable_args2));
+ if(handle[i][1] == NULL)
+ return -1;
+ }
+
+ g_comm_prog_para.htable_handle = handle;
+ return 0;
+}
+
+int comm_read_conf(const char *file_name)
+{
+ short log_level = 30;
+ char log_filename[256];
+ log_filename[0]='\0';
+ int ret;
+
+ if(MESA_load_profile_short_nodef(file_name, "DEFAULT", "log_level", (short*)&log_level)<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [DEFAULT] log_level error!");
+ return -1;
+ }
+ if(MESA_load_profile_string_nodef(file_name, "DEFAULT", "log_path", log_filename, sizeof(log_filename))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [DEFAULT] log_path error!");
+ return -1;
+ }
+ g_comm_prog_para.log_handle = MESA_create_runtime_log_handle(log_filename, log_level);
+ if(g_comm_prog_para.log_handle == NULL)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "Create log_handle error!");
+ return -1;
+ }
+
+ if((ret=MESA_load_profile_int_nodef(file_name, "DEFAULT", "htable_size", (int*)&g_comm_prog_configure.htable_size))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [DEFAULT] htable_size error!");
+ return -1;
+ }
+ if((ret=MESA_load_profile_int_nodef(file_name, "DEFAULT", "sleep", (int*)&g_comm_prog_configure.sleep))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [DEFAULT] sleep error!");
+ return -1;
+ }
+ if(g_comm_prog_configure.sleep <= 0)
+ {
+ g_comm_prog_configure.sleep = 10;
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_INFO, "comm_read_conf",\
+ "conf [DEFAULT] sleep is not more than 0! Reset interval to 10.");
+ }
+
+
+ // g_comm_prog_configure.upload_log_path = (char *)calloc(1, 256*sizeof(char));
+ // if((ret=MESA_load_profile_string_nodef(file_name, "UPLOAD_LOG", "upload_log_path", g_comm_prog_configure.upload_log_path, 256*sizeof(char)))<0)
+ // {
+ // MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [UPLOAD_LOG] upload_log_path error!");
+ // return -1;
+ // }
+ // char upload_log_path[50]={0};
+ // sprintf(upload_log_path, "mkdir -p %s", g_comm_prog_configure.upload_log_path);
+ // FILE * pret = popen(upload_log_path, "w");
+ // if(!pret)
+ // MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "%s IS FAILED! ERROR IS %s",upload_log_path, strerror(errno));
+ // pclose(pret);
+
+ g_comm_prog_configure.tmp_log_path = (char *)calloc(1, 256*sizeof(char));
+ if((ret=MESA_load_profile_string_nodef(file_name, "UPLOAD_LOG", "tmp_log_path", g_comm_prog_configure.tmp_log_path, 256*sizeof(char)))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [UPLOAD_LOG] tmp_log_path error!");
+ return -1;
+ }
+ char tmp_log_path[50]={0};
+ sprintf(tmp_log_path, "mkdir -p %s", g_comm_prog_configure.tmp_log_path);
+ FILE * pret = popen(tmp_log_path, "w");
+ if(!pret)
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "%s IS FAILED! ERROR IS %s",tmp_log_path, strerror(errno));
+ pclose(pret);
+
+
+ g_comm_prog_configure.upload_pz_path = (char *)calloc(1, 256*sizeof(char));
+ if((ret=MESA_load_profile_string_nodef(file_name, "UPLOAD_PZ", "upload_pz_path", g_comm_prog_configure.upload_pz_path,256*sizeof(char)))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [UPLOAD_PZ] upload_pz_path error!");
+ return -1;
+ }
+
+ if((ret=MESA_load_profile_int_nodef(file_name,"UPLOAD_PZ","read_upload_pz_interval",&g_comm_prog_configure.read_interval))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [UPLOAD_PZ] read_upload_pz_interval error!");
+ return -1;
+ }
+
+ if((ret=MESA_load_profile_int_nodef(file_name,"UPLOAD_PZ","default_upload_interval",&g_comm_prog_configure.write_interval))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [UPLOAD_PZ] default_upload_interval error!");
+ return -1;
+ }
+
+ if((ret=MESA_load_profile_int_nodef(file_name,"UPLOAD_PZ","defailt_upload_max_num",&g_comm_prog_configure.write_max_num))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [UPLOAD_PZ] defailt_upload_max_num error!");
+ return -1;
+ }
+
+ if((ret=MESA_load_profile_int_nodef(file_name,"IPDB_PZ","flag",&g_comm_prog_configure.flag))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [IPDB_PZ] flag error!");
+ return -1;
+ }
+
+ g_comm_prog_configure.mmdb_path = (char *)calloc(1, 256*sizeof(char));
+ if((ret=MESA_load_profile_string_nodef(file_name, "IPDB_PZ", "mmdb_path", g_comm_prog_configure.mmdb_path, 256*sizeof(char)))<0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "comm_read_conf", "conf [IPDB_PZ] mmdb_path error!");
+ return -1;
+ }
+ return 0;
+}
+
+int COMM_AUDIT_INIT()
+{
+ int ret;
+ if(-1 == comm_read_conf("./djconf/comm_audit.conf"))
+ return -1;
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_INFO, "COMM_AUDIT_INIT", "COMM_AUDIT_INIT conf read over!");
+
+ g_comm_prog_para.project_id_pro = project_customer_register(DNTY_PPROJECT_PRO, DNTY_PPROJECT_TYPE);
+ if(g_comm_prog_para.project_id_pro < 0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "COMM_AUDIT_INIT. project_req_register error. LACK OF IDENTIFY'S CONF!");
+ return -1;
+ }
+
+
+ int thread_num = get_thread_count();
+ g_comm_prog_para.thread_num = thread_num;
+#ifdef LOG_DEBUG
+ printf("thread_num:%d\n", g_comm_prog_para.thread_num);
+#endif
+ ret = init_hash_table();
+ if(ret < 0)
+ {
+ MESA_handle_runtime_log(g_comm_prog_para.log_handle, RLOG_LV_FATAL, "FATAL", "COMM_AUDIT_INIT. init_hash_table error!");
+ //printf("init_hash_table() error!\n");
+ return -1;
+ }
+
+ g_comm_prog_para.last_send_time = time(NULL);
+ // pthread_mutex_init(&g_comm_prog_para.mutex, NULL);
+
+
+ //创建写文件线程
+ pthread_t hd_write;
+ pthread_create(&hd_write, NULL, thread_time, NULL);
+
+ //创建读json配置线程
+ pthread_t hd_read;
+ pthread_create(&hd_read, NULL, set_timer, NULL);
+
+ // printf("init COMM_AUDIT_INIT success!\n");
+
+ return 0;
+}
+
|
