summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorliuxueli <[email protected]>2021-11-10 11:55:22 +0300
committerliuxueli <[email protected]>2021-11-10 11:55:22 +0300
commit11c3aa538a3d7e73e1f1f29269ffdf2900d20803 (patch)
tree871d5da2e2f0de3aa6fa6318e0824bca60377884
parentfa5af896903efb7dc2c73c26c555167f5eed7a0e (diff)
TSG-8364: 重构代码,只解QUIC链接的第一个数据包
-rw-r--r--CMakeLists.txt2
-rw-r--r--README.md10
-rw-r--r--demo/demo.cpp275
-rw-r--r--inc/gquic.h96
-rw-r--r--include/quic.h55
-rw-r--r--src/gquic_process.cpp1558
-rw-r--r--src/quic_deprotection.cpp (renamed from src/parser_quic.cpp)11
-rw-r--r--src/quic_deprotection.h (renamed from src/parser_quic.h)2
-rw-r--r--src/quic_deprotection_utils.cpp (renamed from src/utils.cpp)4
-rw-r--r--src/quic_deprotection_utils.h (renamed from src/utils.h)0
-rw-r--r--src/quic_deprotection_wsgcrypt.cpp (renamed from src/wsgcrypt.cpp)2
-rw-r--r--src/quic_deprotection_wsgcrypt.h (renamed from src/wsgcrypt.h)0
-rw-r--r--src/quic_entry.cpp (renamed from src/quic_analysis.cpp)193
-rw-r--r--src/quic_entry.h (renamed from src/quic_analysis.h)11
-rw-r--r--src/quic_process.cpp871
-rw-r--r--src/quic_process.h (renamed from src/gquic_process.h)150
-rw-r--r--src/quic_version.cpp4
-rw-r--r--test/pcap/airport/quic_result.json68
-rw-r--r--test/pcap/gquic/43/quic_result.json8
-rw-r--r--test/pcap/gquic/44/quic_result.json4
-rw-r--r--test/pcap/iquic/29/quic_result.json6
-rw-r--r--test/pcap/tquic/quic_result.json42
-rw-r--r--test/quic_test_plug.cpp29
23 files changed, 1141 insertions, 2260 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 24da4c2..7ad2ca3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -30,7 +30,7 @@ endif()
set(CMAKE_INSTALL_PREFIX /home/mesasoft/sapp_run)
-include_directories(inc)
+include_directories(include)
include_directories(/opt/MESA/include/MESA/)
include_directories(/usr/include/glib-2.0/)
#include_directories(/usr/include/glib-2.0/include/)
diff --git a/README.md b/README.md
index d592b56..90fd4b4 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,3 @@
-# gquic
-
-gquic protocol parse plugin
-
-
-
-Chromium currently support two kinds of QUIC versions, GoogleQUIC and IETF QUIC.
-
+quic
+https://www.chromium.org/quic
https://quiche.googlesource.com/quiche/+/refs/heads/master/quic/core/quic_versions.h \ No newline at end of file
diff --git a/demo/demo.cpp b/demo/demo.cpp
deleted file mode 100644
index f69e594..0000000
--- a/demo/demo.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <pwd.h>
-#include <grp.h>
-#include <time.h>
-#include <locale.h>
-#include <langinfo.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <arpa/inet.h>
-
-#include "gquic_process.h"
-#include "quic_analysis.h"
-#include "parser_quic.h"
-
-static int check_length(int last_len, int field_len)
-{
- return ((last_len-field_len>0) ? 1 : 0);
-}
-
-
-int get_quic_tlv(char *start_pos, quic_tlv_t *tlv, int len, int type, int thread_seq)
-{
- if(tlv->value==NULL && len>0)
- {
- tlv->value=(char *)calloc(1, len+1);
- memset(tlv->value, 0, len+1);
- tlv->length=len;
- tlv->type=type;
- memcpy(tlv->value, start_pos, tlv->length);
- }
-
- return 0;
-}
-
-static int get_value(unsigned char *payload, int *offset, int len)
-{
- switch(len)
- {
- case 1:
- return (int)(payload[(*offset)++]);
- break;
- case 2:
- (*offset)+=len;
- return (int)ntohs(*(unsigned short *)(payload+*offset-len));
- break;
- case 3:
- (*offset)+=len;
- return ((int)*(payload-2+*offset)<<16|
- (int)*(payload-1+*offset)<<8|
- (int)*(payload+*offset)<<0);
- break;
- case 4:
- (*offset)+=len;
- return (int)ntohl(*(unsigned int *)(payload+*offset-len));
- break;
- case 32:
- (*offset)+=len;
- return 0;
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-int parse_encrypt_parameter(struct _quic_stream *quic_stream, unsigned char *payload, int payload_len, int thread_seq)
-{
- int used_len=0,length=0;
- while(payload_len>used_len)
- {
- if(payload[used_len]> 0x00 && payload[used_len]<=0x20)
- {
- get_value(payload, &used_len, 1); //type=1
- length=get_value(payload, &used_len, 1); // length=1
- used_len+=length;
-
- continue;
- }
-
- if((*(unsigned short *)(payload+used_len)) == htons(EXT_QUIC_PARAM_USER_AGENT))
- {
- quic_stream->ua_idx=quic_stream->ext_tag_num++;
- get_value(payload, &used_len, 2); //type=2
- length=get_value(payload, &used_len, 1); // length=1
- get_quic_tlv((char *)payload+used_len, &(quic_stream->ext_tags[quic_stream->ua_idx]), length, EXT_QUIC_PARAM_USER_AGENT, thread_seq);
- used_len+=length;
-
- continue;
- }
-
- if(*(unsigned int *)(payload+used_len) == htonl(EXT_QUIC_PARAM_QUIC_VERSION))
- {
- quic_stream->ver_idx=quic_stream->ext_tag_num++;
- get_value(payload, &used_len, 4); //type=4
- length=get_value(payload, &used_len, 1); // length=1
- get_quic_tlv((char *)payload+used_len, &(quic_stream->ext_tags[quic_stream->ver_idx]), length, EXT_QUIC_PARAM_QUIC_VERSION, thread_seq);
- *(unsigned int *)quic_stream->ext_tags[quic_stream->ver_idx].value=(unsigned int)htonl(*(unsigned int *)quic_stream->ext_tags[quic_stream->ver_idx].value);
- used_len+=length;
-
- continue;
- }
-
- if((*(unsigned int *)(payload+used_len))== htonl(EXT_QUIC_PARAM_GREASE_HIGH4) && (*(unsigned int *)(payload+used_len+4))== htonl(EXT_QUIC_PARAM_GREASE_LOW4))
- {
- used_len+=8; //type=8
- length=get_value(payload, &used_len, 1); // length=1
- used_len+=length;
-
- continue;
- }
-
- break;
- }
-
- return 0;
-}
-
-int parse_encrypt_server_name(struct _quic_stream *quic_stream, unsigned char *payload, int payload_len, int thread_seq)
-{
- int ext_len=0,used_len=0;
-
- ext_len=get_value(payload, &used_len, 2); //Server Name List length
- if(ext_len>0 && ext_len>payload_len)
- {
- return 0;
- }
-
- if(get_value(payload, &used_len, 1)==0) //Server Name type
- {
- ext_len=get_value(payload, &used_len, 2); //Server Name length
- if(ext_len<0 || ext_len>payload_len)
- {
- return 0;
- }
-
- quic_stream->sni_idx=quic_stream->ext_tag_num++;
- get_quic_tlv((char *)payload+used_len, &(quic_stream->ext_tags[quic_stream->sni_idx]), ext_len, EXTENSION_SERVER_NAME, thread_seq);
- }
- else
- {
- return 0;
- }
-
- return 1;
-}
-
-int parse_encrypt_client_hello(void *pstream, struct _quic_stream *quic_stream, void *a_packet, unsigned char *payload, int payload_len)
-{
- int used_len=0;
- int flags=0,ret=0;
- int skip_len=0,client_hello_len=0;
- int ext_type=0, extension_total_len=0;
-
- get_value(payload, &used_len, 1); //handshake type
- client_hello_len=get_value(payload, &used_len, 3); //client hello length
- get_value(payload, &used_len, 2); //ssl_version
-
- get_value(payload, &used_len, 32); //Random
-
- skip_len=(int)get_value(payload, &used_len, 1); //Session ID length
- if(!check_length(payload_len-used_len, skip_len))
- {
- return flags;
- }
- used_len+=skip_len;
-
- skip_len=(int)get_value(payload, &used_len, 2); //Ciper Suites length
- if(!check_length(payload_len-used_len, skip_len))
- {
- return flags;
- }
- used_len+=skip_len;
-
- skip_len=(int)get_value(payload, &used_len, 1); //Compression Methods
- if(!check_length(payload_len-used_len, skip_len))
- {
- return flags;
- }
- used_len+=skip_len;
-
- extension_total_len=(int)get_value(payload, &used_len, 2); //Extension length
- if(!check_length(payload_len-used_len, extension_total_len) && (extension_total_len!=payload_len-used_len))
- {
- return flags;
- }
-
- quic_stream->ext_tags=(quic_tlv_t *)calloc(1, sizeof(quic_tlv_t)*3);
- memset(quic_stream->ext_tags, 0, sizeof(quic_tlv_t)*3);
-
- while(extension_total_len>used_len)
- {
- ext_type=get_value(payload, &used_len, 2); //Extension type
- skip_len=get_value(payload, &used_len, 2); //length
- if(!check_length(payload_len-used_len, skip_len) || skip_len==0)
- {
- return flags;
- }
-
- switch(ext_type)
- {
- case EXTENSION_SERVER_NAME:
- ret=parse_encrypt_server_name(quic_stream, payload+used_len, skip_len, 0);
- if(ret==0)
- {
- break;
- }
- flags=1;
- break;
- case EXTENSION_QUIC_PARAM:
- parse_encrypt_parameter(quic_stream, payload+used_len, skip_len, 0);
- break;
- case EXTENSION_SUPPORT_GROUP:
- case EXTENSION_APP_PROT_NEGO:
- case EXTENSION_SIG_ALGORITHM:
- case EXTENSION_KEY_SHARE:
- case EXTENSION_PSK_EXCHANGE:
- case EXTENSION_SUPP_SSL_VER:
- case EXTENSION_COMPRESS_CERT:
- break;
- default:
- break;
- }
-
- used_len+=skip_len;
- }
-
- return flags;
-}
-
-
-int main(int argc, char *argv[])
-{
- if(argc<1)
- {
- return -1;
- }
-
- struct stat statbuf;
- if (stat(argv[1], &statbuf) == -1)
- {
- return -1;
- }
-
- unsigned char *payload=(unsigned char *)calloc(1, statbuf.st_size);
- FILE *fp=fopen(argv[1], "rb");
- if(fp)
- {
- int size=fread(payload, 1, 1315, fp);
- assert(size==1315);
- //assert(size==statbuf.st_size);
-
- struct _quic_stream * quic_stream=(struct _quic_stream *)calloc(1, sizeof(struct _quic_stream));
- parse_encrypt_client_hello(NULL, quic_stream, NULL, payload+4, 1314)-4;
-
- fclose(fp);
- fp=NULL;
-
- free(quic_stream);
- quic_stream=NULL;
-
- free(payload);
- payload=NULL;
-
- }
-
- return 0;
-}
diff --git a/inc/gquic.h b/inc/gquic.h
deleted file mode 100644
index 133912c..0000000
--- a/inc/gquic.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * quic.h
- *
- * Created on: 2019-4-4
- * Author: root
- */
-
-#ifndef _GQUIC_H_
-#define _GQUIC_H_
-
-#define QUIC_INTEREST_KEY (1<<QUIC_INTEREST_KEY_MASK)
-#define QUIC_CLIENT_HELLO (1<<QUIC_CLIENT_HELLO_MASK)
-#define QUIC_SERVER_HELLO (1<<QUIC_SERVER_HELLO_MASK)
-#define QUIC_CACHED_CERT (1<<QUIC_CACHED_CERT_MASK)
-#define QUIC_COMM_CERT (1<<QUIC_COMM_CERT_MASK)
-#define QUIC_CERT_CHAIN (1<<QUIC_CERT_CHAIN_MASK)
-#define QUIC_APPLICATION_DATA (1<<QUIC_APPLICATION_DATA_MASK)
-#define QUIC_USEING_VERSION (1<<QUIC_USEING_VERSION_MASK)
-#define QUIC_NEGOTIATION_VERSION (1<<QUIC_NEGOTIATION_VERSION_MASK)
-#define QUIC_REJECTION (1<<QUIC_REJECTION_MASK)
-
-
-enum quic_interested_region
-{
- QUIC_INTEREST_KEY_MASK = 0,
- QUIC_CLIENT_HELLO_MASK,
- QUIC_SERVER_HELLO_MASK,
- QUIC_CACHED_CERT_MASK,
- QUIC_COMM_CERT_MASK,
- QUIC_CERT_CHAIN_MASK,
- QUIC_APPLICATION_DATA_MASK,
- QUIC_USEING_VERSION_MASK,
- QUIC_NEGOTIATION_VERSION_MASK,
- QUIC_REJECTION_MASK
-};
-
-typedef struct _quic_tlv
-{
- unsigned int type;
- unsigned int length;
- void *value;
-}quic_tlv_t;
-
-#define MAX_CONNECT_ID_LEN 18
-
-struct _quic_public_header
-{
- unsigned char public_flags;
- unsigned char is_reset;
- unsigned char is_sepcial_packet; // special Packets
- unsigned char is_version_negotiation;
- unsigned char server_CID_len;
- unsigned char client_CID_len;
- unsigned char negotiation_version_num;
- unsigned int quic_version;
- unsigned long long packet_number;
- unsigned char server_CID[MAX_CONNECT_ID_LEN]; ////use first 8 bytes if GQUIC version 1~43
- unsigned char client_CID[MAX_CONNECT_ID_LEN]; // no used if GQUIC version 1~43
- unsigned int *negotiation_version_list;
-};
-struct _gquic_frame_header
-{
- unsigned char frame_type;
- unsigned char fin_state;
- unsigned short data_len;
- unsigned int stream_id;
- unsigned long long offset;
-};
-
-
-struct _quic_stream
-{
- unsigned char count;
- unsigned char sni_idx;
- unsigned char ua_idx;
- unsigned char ver_idx;
- unsigned int ext_tag_num; //number of extensions or tags
- quic_tlv_t *ext_tags; //extensions or tags
-};
-
-struct _quic_info
-{
- struct _quic_stream *rejection;
- struct _quic_stream *client_hello;
- struct _quic_stream *server_hello;
- struct _gquic_frame_header frame_hdr;
- struct _quic_public_header quic_hdr;
-};
-
-
-//buff_len minimun 32bytes
-int quic_version_int2string(unsigned int version, char *buff, int buff_len);
-//ret: 0: not quic, >0: quic version
-unsigned int quic_protocol_identify(struct streaminfo *a_stream, void *a_packet, char *out_sni, int *out_sni_len, char *out_ua, int *out_ua_len);
-
-#endif /* SRC_GQUIC_H_ */
diff --git a/include/quic.h b/include/quic.h
new file mode 100644
index 0000000..33181cd
--- /dev/null
+++ b/include/quic.h
@@ -0,0 +1,55 @@
+/*
+ * quic.h
+ *
+ * Created on: 2021-11-08
+ * Author: liuxueli
+ */
+
+#ifndef __QUIC_H__
+#define __QUIC_H__
+
+#define QUIC_INTEREST_KEY (1<<QUIC_INTEREST_KEY_MASK)
+#define QUIC_CLIENT_HELLO (1<<QUIC_CLIENT_HELLO_MASK)
+#define QUIC_SERVER_HELLO (1<<QUIC_SERVER_HELLO_MASK)
+#define QUIC_CACHED_CERT (1<<QUIC_CACHED_CERT_MASK)
+#define QUIC_COMM_CERT (1<<QUIC_COMM_CERT_MASK)
+#define QUIC_CERT_CHAIN (1<<QUIC_CERT_CHAIN_MASK)
+#define QUIC_APPLICATION_DATA (1<<QUIC_APPLICATION_DATA_MASK)
+#define QUIC_USEING_VERSION (1<<QUIC_USEING_VERSION_MASK)
+#define QUIC_NEGOTIATION_VERSION (1<<QUIC_NEGOTIATION_VERSION_MASK)
+#define QUIC_REJECTION (1<<QUIC_REJECTION_MASK)
+
+
+enum quic_interested_region
+{
+ QUIC_INTEREST_KEY_MASK = 0,
+ QUIC_CLIENT_HELLO_MASK,
+ QUIC_SERVER_HELLO_MASK,
+ QUIC_CACHED_CERT_MASK,
+ QUIC_COMM_CERT_MASK,
+ QUIC_CERT_CHAIN_MASK,
+ QUIC_APPLICATION_DATA_MASK,
+ QUIC_USEING_VERSION_MASK,
+ QUIC_NEGOTIATION_VERSION_MASK,
+ QUIC_REJECTION_MASK
+};
+
+struct quic_client_hello
+{
+ char *sni;
+ char *user_agent;
+};
+
+struct quic_info
+{
+ unsigned int quic_version;
+ struct quic_client_hello *client_hello;
+};
+
+
+//buff_len minimun 32bytes
+int quic_version_int2string(unsigned int version, char *buff, int buff_len);
+//ret: 0: not quic, >0: quic version
+unsigned int quic_protocol_identify(struct streaminfo *a_stream, void *a_packet, char *out_sni, int *out_sni_len, char *out_ua, int *out_ua_len);
+
+#endif /* SRC__QUIC_H__ */
diff --git a/src/gquic_process.cpp b/src/gquic_process.cpp
deleted file mode 100644
index e1e5002..0000000
--- a/src/gquic_process.cpp
+++ /dev/null
@@ -1,1558 +0,0 @@
-/*
- * quic_process.c
- *
- * Created on: 2019��4��2��
- * Author: root
- */
-
-#include <stdio.h>
-#include <assert.h>
-#include <stdbool.h>
-#include <sys/time.h>
-#include <MESA/stream.h>
-#include <MESA/MESA_handle_logger.h>
-
-#include "gquic_process.h"
-#include "quic_analysis.h"
-#include "parser_quic.h"
-
-#ifndef PRINTADDR
-#define PRINTADDR(a, b) ((b)<RLOG_LV_FATAL ? printaddr(&(a->addr), a->threadnum) : "")
-#endif
-
-#ifndef MIN
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#endif
-
-const unsigned char PCAP_FILE_HEAD[24] = {0xD4, 0xC3, 0xB2, 0xA1, 0x02, 0x00, 0x04, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00};
-
-struct pcap_hdr
-{
- unsigned int tv_sec;
- unsigned int tv_usec;
- unsigned int len;
- unsigned int caplen;
-};
-
-int dump_packet(struct streaminfo *pstream)
-{
- int ret=0;
- char buff[2048]={0};
- char filename[512]={0};
- void *p_eth_rawpkt=NULL;
- int eth_rawpkt_len=0;
- struct pcap_hdr pcap_hdr;
- struct timeval current_time;
-
- if(g_quic_param.dump_packet_switch==0)
- {
- return 0;
- }
-
- ret=get_rawpkt_opt_from_streaminfo(pstream, RAW_PKT_GET_DATA, &p_eth_rawpkt);
- if(ret==0)
- {
- ret=get_rawpkt_opt_from_streaminfo(pstream, RAW_PKT_GET_TOT_LEN, &eth_rawpkt_len);
- if(ret<0)
- {
- return -1;
- }
- snprintf(filename, sizeof(filename), "%s-%s.pcap", g_quic_param.log_path, printaddr(&(pstream->addr), pstream->threadnum));
- FILE *fp=fopen(filename, "a+");
- if(fp)
- {
- gettimeofday(&current_time, NULL);
- pcap_hdr.tv_sec = current_time.tv_sec;
- pcap_hdr.tv_usec = current_time.tv_usec;
- pcap_hdr.caplen = eth_rawpkt_len;
- pcap_hdr.len = pcap_hdr.caplen;
-
- memcpy(buff, PCAP_FILE_HEAD, 24);
- memcpy(buff+24, &pcap_hdr, sizeof(pcap_hdr));
- memcpy(buff+24+sizeof(pcap_hdr), p_eth_rawpkt, eth_rawpkt_len);
- fwrite(buff, eth_rawpkt_len+24+sizeof(pcap_hdr), 1, fp);
-
- fclose(fp);
- fp=NULL;
- }
- }
-
- return 0;
-}
-
-int is_iquic(enum _QUIC_VERSION quic_version)
-{
- switch(quic_version)
- {
- case IQUIC_VERSION_I001:
- case IQUIC_VERSION_I002:
- case IQUIC_VERSION_I003:
- case IQUIC_VERSION_I004:
- case IQUIC_VERSION_I005:
- case IQUIC_VERSION_I006:
- case IQUIC_VERSION_I007:
- case IQUIC_VERSION_I008:
- case IQUIC_VERSION_I009:
- case IQUIC_VERSION_I010:
- case IQUIC_VERSION_I011:
- case IQUIC_VERSION_I012:
- case IQUIC_VERSION_I013:
- case IQUIC_VERSION_I014:
- case IQUIC_VERSION_I015:
- case IQUIC_VERSION_I016:
- case IQUIC_VERSION_I017:
- case IQUIC_VERSION_I018:
- case IQUIC_VERSION_I019:
- case IQUIC_VERSION_I020:
- case IQUIC_VERSION_I021:
- case IQUIC_VERSION_I022:
- case IQUIC_VERSION_I023:
- case IQUIC_VERSION_I024:
- case IQUIC_VERSION_I025:
- case IQUIC_VERSION_I026:
- case IQUIC_VERSION_I027:
- case IQUIC_VERSION_I028:
- case IQUIC_VERSION_I029:
- case IQUIC_VERSION_I030:
- case IQUIC_VERSION_I031:
- case IQUIC_VERSION_I032:
- return TRUE;
- break;
- default:
- break;
- }
-
- return FALSE;
-}
-
-int check_port(unsigned short port)
-{
- int i=0;
- for(i=0; i< g_quic_param.quic_port_num; i++)
- {
- if(g_quic_param.quic_port_list[i]==port)
- {
- return 1;
- }
- }
-
- return 0;
-}
-
-int is_quic_port(struct streaminfo *pstream)
-{
- unsigned short source=0, dest=0;
-
- switch(pstream->addr.addrtype)
- {
- case ADDR_TYPE_IPV4:
- case __ADDR_TYPE_IP_PAIR_V4:
- source=(unsigned short)ntohs(pstream->addr.ipv4->source);
- dest=(unsigned short)ntohs(pstream->addr.ipv4->dest);
- break;
- case ADDR_TYPE_IPV6:
- case __ADDR_TYPE_IP_PAIR_V6:
- source=(unsigned short)ntohs(pstream->addr.ipv6->source);
- dest=(unsigned short)ntohs(pstream->addr.ipv6->dest);
- break;
- default:
- return 0;
- break;
- }
-
- if(check_port(source) || check_port(dest))
- {
- return 1;
- }
-
- return 0;
-}
-
-static long get_value(unsigned char *payload, int *offset, int len)
-{
- switch(len)
- {
- case 1:
- return (long)(payload[(*offset)++]);
- break;
- case 2:
- (*offset)+=len;
- return (long)ntohs(*(unsigned short *)(payload+*offset-len));
- break;
- case 3:
- (*offset)+=len;
- return ((long)*(payload-2+*offset)<<16|
- (long)*(payload-1+*offset)<<8|
- (long)*(payload+*offset)<<0);
- break;
- case 4:
- (*offset)+=len;
- return (long)ntohl(*(unsigned int *)(payload+*offset-len));
- break;
- case 8:
- (*offset)+=len;
- return ((long)*(payload-7+*offset)<<56|
- (long)*(payload-6+*offset)<<48|
- (long)*(payload-5+*offset)<<40|
- (long)*(payload-4+*offset)<<32|
- (long)*(payload-3+*offset)<<24|
- (long)*(payload-2+*offset)<<16|
- (long)*(payload-1+*offset)<<8|
- (long)*(payload+*offset)<<0);
- break;
- case 32:
- (*offset)+=len;
- return 0;
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-
-static int check_length(int last_len, int field_len)
-{
- return ((last_len-field_len>0) ? 1 : 0);
-}
-
-int quic_getLinkState(struct _quic_context *_context)
-{
- UCHAR state = 0;
-
- if(0==_context->link_state)
- {
- state=SESSION_STATE_PENDING|SESSION_STATE_DATA;
- _context->link_state=1;
- }
- else
- {
- state=SESSION_STATE_DATA;
- }
-
- return state;
-}
-
-char quic_callPlugins(struct streaminfo *pstream, struct _quic_context *_context, void *buff, int buff_len, enum quic_interested_region region_mask, void *a_packet)
-{
- char state=PROT_STATE_GIVEME;
- char app_state=APP_STATE_GIVEME;
- stSessionInfo session_info={0};
-
- if(region_mask==QUIC_INTEREST_KEY_MASK)
- {
- session_info.plugid=g_quic_param.quic_plugid;
- session_info.prot_flag=0;
- session_info.session_state=SESSION_STATE_CLOSE;
- session_info.app_info=NULL;
- session_info.buf=NULL;
- session_info.buflen=0;
- }
- else
- {
- session_info.plugid=g_quic_param.quic_plugid;
- session_info.prot_flag=(((unsigned long long)1)<<region_mask);
- session_info.session_state=quic_getLinkState(_context) ;
- session_info.app_info=(void*)(&_context->quic_info);
- session_info.buf=buff;
- session_info.buflen=buff_len;
- }
- state=PROT_PROCESS(&session_info, &(_context->business_pme), pstream->threadnum, pstream, a_packet);
-
- if(state&PROT_STATE_DROPPKT)
- {
- app_state=APP_STATE_DROPPKT;
- }
-
- return app_state;
-}
-
-
-unsigned long long get_variable_length(char *p, int offset, int v_len)
-{
- switch(v_len)
- {
- case 1:
- return (unsigned long long)(p[offset]);
- break;
- case 2:
- return (unsigned long long)ntohs(*(unsigned short *)((char *)p+offset));
- break;
- case 3:
- return (unsigned long long)*(p+0+offset)<<16|
- (unsigned long long)*(p+1+offset)<<8|
- (unsigned long long)*(p+2+offset)<<0;
- break;
- case 4:
- return (unsigned long long)ntohl(*(unsigned int *)(p+offset));
- break;
- case 5:
- return (unsigned long long)*((unsigned char *)(p)+0+offset)<<32|
- (unsigned long long)*((unsigned char *)(p)+1+offset)<<24|
- (unsigned long long)*((unsigned char *)(p)+2+offset)<<16|
- (unsigned long long)*((unsigned char *)(p)+3+offset)<<8|
- (unsigned long long)*((unsigned char *)(p)+4+offset)<<0;
- break;
- case 6:
- return (unsigned long long)*((unsigned char *)(p)+0+offset)<<40|
- (unsigned long long)*((unsigned char *)(p)+1+offset)<<32|
- (unsigned long long)*((unsigned char *)(p)+2+offset)<<24|
- (unsigned long long)*((unsigned char *)(p)+3+offset)<<16|
- (unsigned long long)*((unsigned char *)(p)+4+offset)<<8|
- (unsigned long long)*((unsigned char *)(p)+5+offset)<<0;
- break;
- case 7:
- return (unsigned long long)*((unsigned char *)(p)+0+offset)<<56|
- (unsigned long long)*((unsigned char *)(p)+1+offset)<<40|
- (unsigned long long)*((unsigned char *)(p)+2+offset)<<32|
- (unsigned long long)*((unsigned char *)(p)+3+offset)<<24|
- (unsigned long long)*((unsigned char *)(p)+4+offset)<<16|
- (unsigned long long)*((unsigned char *)(p)+5+offset)<<8|
- (unsigned long long)*((unsigned char *)(p)+6+offset)<<0;
- break;
- case 8:
- return (unsigned long long)*((unsigned char *)(p)+0+offset)<<56|
- (unsigned long long)*((unsigned char *)(p)+1+offset)<<48|
- (unsigned long long)*((unsigned char *)(p)+2+offset)<<40|
- (unsigned long long)*((unsigned char *)(p)+3+offset)<<32|
- (unsigned long long)*((unsigned char *)(p)+4+offset)<<24|
- (unsigned long long)*((unsigned char *)(p)+5+offset)<<16|
- (unsigned long long)*((unsigned char *)(p)+6+offset)<<8|
- (unsigned long long)*((unsigned char *)(p)+7+offset)<<0;
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-long long bit_to_value(char *payload, int payload_len, unsigned char flags, unsigned long long *out_value, int *used_len)
-{
- switch(flags&0x3) // packet number
- {
- case 0x3: // 6 bytes
- if(!check_length(payload_len-*used_len, 6))
- {
- return -1;
- }
- *out_value=get_variable_length(payload, *used_len, 6);
- *used_len+=6;
- break;
- case 0x2: // 4 bytes
- if(!check_length(payload_len-*used_len, sizeof(unsigned int)))
- {
- return -1;
- }
- *out_value=(unsigned long long)ntohl(*(unsigned int *)(payload+*used_len));
- *used_len+=4;
- break;
- case 0x1: // 2bytes
- if(!check_length(payload_len-*used_len, sizeof(unsigned short)))
- {
- return -1;
- }
- *out_value=(unsigned long long)ntohs(*(unsigned short *)(payload+*used_len));
- *used_len+=2;
- break;
- default: // 1 byte
- if(!check_length(payload_len-*used_len, sizeof(unsigned char)))
- {
- return -1;
- }
- *out_value=payload[*used_len];
- *used_len+=1;
- break;
- }
-
- return 0;
-}
-
-int get_quic_tlv(char *start_pos, quic_tlv_t *tlv, int len, int type, int thread_seq)
-{
- if(tlv->value==NULL && len>0)
- {
- tlv->value=(char *)dictator_malloc(thread_seq, len+1);
- memset(tlv->value, 0, len+1);
- tlv->length=len;
- tlv->type=type;
- memcpy(tlv->value, start_pos, tlv->length);
- }
-
- return 0;
-}
-
-int get_stream_id(struct streaminfo *pstream, struct _quic_context* _context, char* payload, int payload_len, unsigned char frame_type, int *used_len)
-{
- int stream_len=0,offset_len=0;
-
- _context->quic_info.frame_hdr.frame_type=frame_type;
-
- stream_len=(frame_type&GQUIC_SPECIAL_FRAME_STREAM_ID)+1;
- if(!check_length(payload_len-*used_len, stream_len))
- {
- return -1;
- }
-
- _context->quic_info.frame_hdr.stream_id=(unsigned int)get_variable_length(payload, *used_len, stream_len);
- *used_len+=stream_len; // stream ID length
-
- if(frame_type&GQUIC_SPECIAL_FRAME_STREAM_DLEN)
- {
- if(!check_length(payload_len-*used_len, 2))
- {
- return -1;
- }
- _context->quic_info.frame_hdr.data_len=ntohs(*(unsigned short *)(payload+*used_len));
- *used_len+=2; //data length
- }
-
- offset_len=(frame_type&GQUIC_SPECIAL_FRAME_STREAM_OFFSET) ? (((frame_type&GQUIC_SPECIAL_FRAME_STREAM_OFFSET))>>2)+1 : 0;
- if(!check_length(payload_len-*used_len, offset_len))
- {
- return -1;
- }
-
- _context->quic_info.frame_hdr.offset=get_variable_length(payload, *used_len, offset_len);
- *used_len+=offset_len;
-
- MESA_handle_runtime_log(g_quic_param.logger,
- RLOG_LV_DEBUG,
- "QUIC_FRAME",
- "frame_type: 0X%02X stream_id: %u data length: %u offset length: %u addr: %s",
- frame_type,
- _context->quic_info.frame_hdr.stream_id,
- _context->quic_info.frame_hdr.data_len,
- offset_len,
- PRINTADDR(pstream, g_quic_param.level)
- );
-
- return _context->quic_info.frame_hdr.stream_id;
-}
-
-unsigned long long get_packet_number(char* data, int offset, char pkn_len)
-{
- switch(pkn_len)
- {
- case 1:
- return (unsigned long long)data[offset];
- break;
- case 2:
- return (unsigned long long)ntohs(*(unsigned short *)(data+offset));
- break;
- case 4:
- return (unsigned long long)ntohl(*(unsigned int *)(data+offset));
- break;
- case 8:
- return get_variable_length(data, offset, 8);;
- break;
- }
-
- return 0;
-}
-
-// GQUIC version from 0 to 43
-static enum _QUIC_VERSION parse_q0to43_header(struct streaminfo *pstream, struct _quic_context* _context, char *payload, int payload_len, int *used_len)
-{
- int ret=0;
- char public_flags=0;
-
- struct _quic_public_header *gquic_hdr=&(_context->quic_info.quic_hdr);
-
- public_flags=payload[*used_len];
- *used_len+=1;
- gquic_hdr->public_flags=public_flags;
-
- if((public_flags&GQUIC_PUBLIC_FLAG_RST) && _context->is_quic==TRUE)
- {
- gquic_hdr->is_reset=TRUE; //Public Reset Packet
- return QUIC_VERSION_UNKNOWN;
-
- }
-
- if(pstream->curdir==DIR_S2C && gquic_hdr->public_flags&GQUIC_PUBLIC_FLAG_VERSION)
- {
- return QUIC_VERSION_UNKNOWN;
- }
-
- //For Public Reset and Version Negotiation Packets (sent by the server) which don't have a packet number
- if(!public_flags&GQUIC_PUBLIC_FLAG_PKT_NUM)
- {
- if(public_flags&GQUIC_PUBLIC_FLAG_VERSION) //Public Reset Packet
- {
- return QUIC_VERSION_UNKNOWN;// todo
- }
- else // Version Negotiation Packet
- {
- return QUIC_VERSION_UNKNOWN;
- }
- }
-
- if(gquic_hdr->public_flags&GQUIC_PUBLIC_FLAG_CID)
- {
- *(unsigned long long *)gquic_hdr->server_CID=get_variable_length(payload, *used_len, sizeof(gquic_hdr->server_CID));
- *used_len+=sizeof(unsigned long long); // CID length
-
- _context->is_quic=TRUE;
- }
-
- if(gquic_hdr->public_flags&GQUIC_PUBLIC_FLAG_VERSION && (*(unsigned char *)(payload+*used_len)==0x51))
- {
- gquic_hdr->quic_version=(unsigned int)ntohl(*(unsigned int *)(payload+*used_len));
- *used_len+=sizeof(int); // skip version
-
- _context->is_quic=TRUE;
- }
-
- if(_context->is_quic==FALSE || gquic_hdr->quic_version<GQUIC_VERSION_Q001 || gquic_hdr->quic_version>GQUIC_VERSION_Q043)
- {
- _context->is_quic=FALSE;
- return QUIC_VERSION_UNKNOWN;
- }
-
- ret=bit_to_value(payload, payload_len, gquic_hdr->public_flags>>4, &gquic_hdr->packet_number, used_len);
- if(ret<0)
- {
- return (enum _QUIC_VERSION)gquic_hdr->quic_version;
- }
-
- if(gquic_hdr->public_flags==GQUIC_PUBLIC_FLAG_NONCE)
- {
- *used_len+=32; //diversification nonce
- }
-
- // Version 11 reduced the length of null encryption authentication tag from 16 to 12 bytes
- if(gquic_hdr->quic_version > GQUIC_VERSION_Q010)
- {
- *used_len+=12;
- }
- else
- {
- *used_len+=16;
- }
-
- // Version 34 removed entropy bits from packets and ACK frames,
- // removed private flag from packet header and changed the ACK format to specify ranges of packets acknowledged rather than missing ranges.
- if(gquic_hdr->quic_version < GQUIC_VERSION_Q034)
- {
- *used_len+=1; //private flags
- }
-
- _context->is_quic=TRUE;
-
- MESA_handle_runtime_log(g_quic_param.logger,
- RLOG_LV_DEBUG,
- "QUIC_IDETIFY",
- "pub_flags: 0X%02X conection ID:[ destination: %llu ] version: Q%03u packet number: %llu dir(1: C2S;2: S2C): %d addr: %s",
- gquic_hdr->public_flags,
- *(unsigned long long *)gquic_hdr->server_CID,
- (((gquic_hdr->quic_version>>8)&0x0000000F)*10) + ((gquic_hdr->quic_version)&0x0000000F),
- gquic_hdr->packet_number,
- pstream->curdir,
- PRINTADDR(pstream, g_quic_param.level)
- );
-
- return (enum _QUIC_VERSION)gquic_hdr->quic_version;
-}
-
-enum _QUIC_VERSION parse_quic_header(struct streaminfo *pstream, struct _quic_context* _context, char *payload, int payload_len, int *used_len)
-{
- int i=0,len=0;
- char client_CID[MAX_CONNECT_ID_LEN*2]={0};
- char server_CID[MAX_CONNECT_ID_LEN*2]={0};
-
- struct _quic_public_header *long_hdr=&(_context->quic_info.quic_hdr);
-
- long_hdr->public_flags=payload[*used_len];
- *used_len+=1; //skip public flags
-
- if(long_hdr->public_flags&0x80)
- {
- long_hdr->quic_version=(unsigned int)ntohl(*(unsigned int *)(payload+*used_len));
- *used_len+=sizeof(int); // skip version
-
- long_hdr->client_CID_len=(payload[*used_len]&0xF) ? (payload[*used_len]&0xF)+3 : 0;
- long_hdr->server_CID_len=((payload[*used_len]>>4)&0xF) ? ((payload[*used_len]>>4)&0xF)+3 : 0;
- *used_len+=sizeof(char); // both connection_id length
-
- memcpy(long_hdr->server_CID, (void *)(payload+*used_len), long_hdr->server_CID_len);
- *used_len+=long_hdr->server_CID_len; // Destination connection_id length
- memcpy(long_hdr->client_CID, (void *)(payload+*used_len), long_hdr->client_CID_len);
- *used_len+=long_hdr->client_CID_len; // source connection_id length
- }
- else
- {
- if(pstream->curdir==DIR_C2S)// short header only destination connection ID
- {
- *used_len+=long_hdr->server_CID_len; // every packet destination connection ID is same
- }
- }
-
- len=(long_hdr->public_flags&0x03)+1;
- long_hdr->packet_number=get_packet_number(payload, *used_len, len);
- *used_len+=len;
-
- *used_len+=12; //message authentication hash
-
- _context->is_quic=TRUE;
-
- for(i=0,len=0;i<long_hdr->server_CID_len; i++)
- {
- len+=snprintf(server_CID+len, sizeof(server_CID)-len, "%02X", long_hdr->server_CID[i]);
- }
-
- for(i=0,len=0;i<long_hdr->client_CID_len; i++)
- {
- len+=snprintf(client_CID+len, sizeof(client_CID)-len, "%02X", long_hdr->client_CID[i]);
- }
-
- MESA_handle_runtime_log(g_quic_param.logger,
- RLOG_LV_DEBUG,
- "QUIC_IDETIFY",
- "pub_flags: 0X%02X conection ID:[ destination: %s source: %s ] version: Q%03u packet number: %llu dir(1: C2S;2: S2C): %d addr: %s",
- long_hdr->public_flags,
- server_CID,
- client_CID,
- (((long_hdr->quic_version>>8)&0x0000000F)*10) + ((long_hdr->quic_version)&0x0000000F),
- long_hdr->packet_number,
- pstream->curdir,
- PRINTADDR(pstream, g_quic_param.level)
- );
-
- return (enum _QUIC_VERSION)long_hdr->quic_version;
-}
-
-enum _QUIC_VERSION is_quic_protocol(struct streaminfo *pstream, struct _quic_context* _context, char *payload, int payload_len, int *used_len)
-{
- enum _QUIC_VERSION quic_version=QUIC_VERSION_UNKNOWN;
-
- if(_context->quic_info.quic_hdr.quic_version!=QUIC_VERSION_UNKNOWN)
- {
- if(is_iquic((enum _QUIC_VERSION)(_context->quic_info.quic_hdr.quic_version)))
- {
- return (enum _QUIC_VERSION)(_context->quic_info.quic_hdr.quic_version);
- }
-
- quic_version=(enum _QUIC_VERSION)(_context->quic_info.quic_hdr.quic_version);
- }
- else
- {
- // The most significant bit (0x80) of byte 0 (the first byte) is set to 1 for long headers
- (payload[*used_len]&0x80) ? (quic_version=(enum _QUIC_VERSION)ntohl(*(unsigned int *)(payload+(*used_len+1)))) : QUIC_VERSION_UNKNOWN;
- }
-
- switch(quic_version) // +1 meaning: skip public flags
- {
- case GQUIC_VERSION_Q044:
- case GQUIC_VERSION_Q045:
- case GQUIC_VERSION_Q046:
- case GQUIC_VERSION_Q047:
- case GQUIC_VERSION_Q048:
- quic_version=parse_quic_header(pstream, _context, payload, payload_len, used_len);
- return quic_version;
- break;
- default:
- if(
- (quic_version==GQUIC_VERSION_Q099) ||
- (quic_version==PICOQUIC_VERSION_30) ||
- (quic_version==PQUIC_VERSION_PROX) ||
- (quic_version==GQUIC_VERSION_T099) ||
- (quic_version>=GQUIC_VERSION_Q049 && quic_version<=GQUIC_VERSION_Q050) ||
- (quic_version>=GQUIC_VERSION_Q051 && quic_version<=GQUIC_VERSION_Q059) ||
- (quic_version>=GQUIC_VERSION_T048 && quic_version<=GQUIC_VERSION_T049) ||
- (quic_version>=GQUIC_VERSION_T050 && quic_version<=GQUIC_VERSION_T059) ||
- (quic_version>=QUANT_VERSION_00 && quic_version<=QUANT_VERSION_FF) ||
- (quic_version>=QUIC_GO_VERSION_00 && quic_version<=QUIC_GO_VERSION_FF) ||
- (quic_version>=QUICLY_VERSION_00 && quic_version<=QUICLY_VERSION_FF) ||
- (quic_version>=MSQUIC_VERSION_00 && quic_version<=MSQUIC_VERSION_0F) ||
- (quic_version>=MOZQUIC_VERSION_00 && quic_version<=MOZQUIC_VERSION_0F) ||
- (quic_version>=MVFST_VERSION_00 && quic_version<=MVFST_VERSION_0F) ||
- (quic_version>=IQUIC_VERSION_I001 && quic_version<=IQUIC_VERSION_I032) ||
- (quic_version==IQUIC_VERSION_RFC9000)
- )
- {
- MESA_handle_runtime_log(g_quic_param.logger,
- RLOG_LV_DEBUG,
- "QUIC",
- "version: 0x%x addr: %s",
- quic_version, PRINTADDR(pstream, g_quic_param.level)
- );
-
- _context->is_quic=TRUE;
- _context->quic_info.quic_hdr.quic_version=quic_version;
- return quic_version;
- }
- break;
- }
-
- // Q001~Q043: 0x80 is currently unused, and must be set to 0
- if(payload[*used_len]>0x80)
- {
- return QUIC_VERSION_UNKNOWN;
- }
-
- return parse_q0to43_header(pstream, _context, payload, payload_len, used_len);
-}
-
-int parse_extension_tag(struct streaminfo *pstream, struct _quic_stream **quic_stream, void *a_packet, char *payload, int payload_len, int *used_len, int tag_num)
-{
- int tag_used_num=0;
- int tag_type=0;
- int total_tag_len=0,tag_len=0;
- int tag_offset_end=0,pre_tag_offset_end=0;
-
- if(tag_num>64 || tag_num<0)
- {
- (*used_len)=payload_len;
-
- dump_packet(pstream);
- MESA_handle_runtime_log(g_quic_param.logger, RLOG_LV_FATAL, "QUIC_TAG_NUM", "QUIC_TAG_NUM:%d addr: %s", tag_num, printaddr(&pstream->addr, pstream->threadnum));
- return -1;
- }
-
- struct _quic_stream *stream=*quic_stream;
- int tag_value_start=tag_num*4*2+(*used_len); // skip length of type and offset, type(offset)=szieof(int)
-
- if(stream==NULL)
- {
- stream=(struct _quic_stream *)dictator_malloc(pstream->threadnum, sizeof(struct _quic_stream));
- memset(stream, 0, sizeof(struct _quic_stream));
- stream->ext_tags=(quic_tlv_t *)dictator_malloc(pstream->threadnum, tag_num*sizeof(quic_tlv_t));
- memset(stream->ext_tags, 0, tag_num*sizeof(quic_tlv_t));
- *quic_stream=stream;
- stream->sni_idx=0xFF;
- stream->ver_idx=0xFF;
- stream->ua_idx=0xFF;
- }
- else
- {
- quic_release_exts(pstream->threadnum, stream->ext_tags, stream->ext_tag_num);
- stream->ext_tags=(quic_tlv_t *)dictator_malloc(pstream->threadnum, tag_num*sizeof(quic_tlv_t));
- memset(stream->ext_tags, 0, tag_num*sizeof(quic_tlv_t));
- *quic_stream=stream;
- stream->ext_tag_num=0;
- stream->count++;
- stream->sni_idx=0xFF;
- stream->ver_idx=0xFF;
- stream->ua_idx=0xFF;
- }
-
- while(tag_num>tag_used_num)
- {
- tag_type=ntohl(*(unsigned int *)(payload+*used_len));
- *used_len+=sizeof(int);
-
- tag_offset_end=*(unsigned int *)(payload+*used_len);
- *used_len+=sizeof(int);
-
- tag_len=tag_offset_end-pre_tag_offset_end;
- if(tag_len<0 || (tag_offset_end>=payload_len) || (tag_len>payload_len-tag_value_start))
- {
- return -1;
- }
-
- switch(tag_type)
- {
- case TAG_PAD:
- break;
- case TAG_VER:
- stream->ver_idx=stream->ext_tag_num;
- get_quic_tlv(payload+tag_value_start, &stream->ext_tags[stream->ext_tag_num], tag_len, tag_type, pstream->threadnum);
- *(unsigned int *)(stream->ext_tags[stream->ext_tag_num].value)=(unsigned int)ntohl(*(unsigned int *)(stream->ext_tags[stream->ext_tag_num].value));
- MESA_handle_runtime_log(g_quic_param.logger,
- RLOG_LV_DEBUG,
- "QUIC_VERSION",
- "Quic version: 0X%X addr: %s",
- *(unsigned int *)(stream->ext_tags[stream->ext_tag_num].value),
- PRINTADDR(pstream, g_quic_param.level)
- );
- break;
- case TAG_UAID:
- stream->ua_idx=stream->ext_tag_num;
- get_quic_tlv(payload+tag_value_start, &stream->ext_tags[stream->ext_tag_num], tag_len, tag_type, pstream->threadnum);
- MESA_handle_runtime_log(g_quic_param.logger,
- RLOG_LV_DEBUG,
- "QUIC_UA",
- "User Agent: %s addr: %s",
- stream->ext_tags[stream->ext_tag_num].value,
- PRINTADDR(pstream, g_quic_param.level)
- );
- stream->ext_tag_num++;
- break;
- case TAG_SNI:
- stream->sni_idx=stream->ext_tag_num;
- get_quic_tlv(payload+tag_value_start, &stream->ext_tags[stream->ext_tag_num], tag_len, tag_type, pstream->threadnum);
- MESA_handle_runtime_log(g_quic_param.logger,
- RLOG_LV_DEBUG,
- "QUIC_SNI",
- "SNI: %s addr: %s",
- stream->ext_tags[stream->ext_tag_num].value,
- PRINTADDR(pstream, g_quic_param.level)
- );
- stream->ext_tag_num++;
- break;
- default:
- get_quic_tlv(payload+tag_value_start, &stream->ext_tags[stream->ext_tag_num], tag_len, tag_type, pstream->threadnum);
- stream->ext_tag_num++;
- break;
- }
-
- tag_used_num++;
- tag_value_start+=tag_len;
- total_tag_len+=tag_len;
- pre_tag_offset_end=tag_offset_end;
- }
-
- *used_len += total_tag_len;
-
- return 0;
-}
-
-int gquic_frame_type_stream(struct streaminfo *pstream, struct _quic_context* _context, char *payload, int payload_len, int *used_len, void *a_packet)
-{
- int ret=0;
- char state=APP_STATE_GIVEME;
- int tag_num = 0;
- unsigned int message_tag;
-
- if(!check_length(payload_len-*used_len, 8))
- {
- return state;
- }
-
- switch(_context->quic_info.quic_hdr.quic_version)
- {
- case GQUIC_VERSION_Q041:
- *used_len+=1; // unknown
- case GQUIC_VERSION_Q044:
- message_tag=(unsigned int)ntohl(*(unsigned int *)(payload+*used_len));
- *used_len+=4;
-
- tag_num=*(int *)(payload+*used_len);
- *used_len+=4; //tag_num
- break;
- default:
- message_tag=(unsigned int)ntohl(*(unsigned int *)(payload+*used_len));
- *used_len+=4;
-
- tag_num=*(unsigned short *)(payload+*used_len);
- *used_len+=2; //tag_num
- *used_len+=2; //padding
- break;
- }
-
- switch(message_tag)
- {
- case CHLO: //MTAG_CHLO;
- ret=parse_extension_tag(pstream, &(_context->quic_info.client_hello), a_packet, payload, payload_len, used_len, tag_num);
- if(ret>=0 && _context->call_business)
- {
- state=quic_callPlugins(pstream, _context, (void *)(_context->quic_info.client_hello), sizeof(void *), QUIC_CLIENT_HELLO_MASK, a_packet);
- }
- break;
- case SHLO: //MTAG_SHLO;
- ret=parse_extension_tag(pstream, &(_context->quic_info.server_hello), a_packet, payload, payload_len, used_len, tag_num);
- if(ret>=0 && _context->call_business)
- {
- state=quic_callPlugins(pstream, _context, (void *)(_context->quic_info.server_hello), sizeof(void *), QUIC_SERVER_HELLO_MASK, a_packet);
- }
- break;
- case REJ: //MTAG_REJ;
- ret=parse_extension_tag(pstream, &(_context->quic_info.rejection), a_packet, payload, payload_len, used_len, tag_num);
- if(ret>=0 && _context->call_business)
- {
- state=quic_callPlugins(pstream, _context, (void *)(_context->quic_info.rejection), sizeof(void *), QUIC_REJECTION_MASK, a_packet);
- }
- break;
- default:
- break;
- }
-
- return state;
-}
-
-//frame type->stream->offset->data length
-int gquic_proc_unencrypt(struct streaminfo *pstream, struct _quic_context* _context, void *a_packet, char * payload, int payload_len, int *used_len)
-{
- int ret=0;
- unsigned char frame_type=0;
- unsigned int stream_id=0;
- unsigned int error_code=0;
- unsigned short reason_phrase_length=0;
- unsigned long long byte_offset=0;
- unsigned long long least_unacked_delta=0;
-
- while(*used_len<payload_len)
- {
- frame_type=payload[*used_len];
- *used_len+=1; //skip frame_type
-
- switch(frame_type)
- {
- case GQUIC_REGULAR_FRAME_PADDING:
- return APP_STATE_GIVEME; // PADDING frame
- break;
- case GQUIC_REGULAR_FRAME_RST_STREAM:
- if(!check_length(payload_len-*used_len, sizeof(unsigned int)+sizeof(unsigned long long)+sizeof(unsigned int)))
- {
- return APP_STATE_GIVEME;
- }
- stream_id=(unsigned int)get_variable_length(payload, *used_len, sizeof(unsigned int));
- *used_len+=sizeof(unsigned int);
-
- byte_offset=get_variable_length(payload, *used_len, sizeof(unsigned long long));
- *used_len+=sizeof(unsigned long long);
-
- error_code=(unsigned int)get_variable_length(payload, *used_len, sizeof(unsigned int));
- *used_len+=sizeof(unsigned int);
-
- MESA_handle_runtime_log(g_quic_param.logger,
- RLOG_LV_DEBUG,
- "QUIC_RST_STREAM",
- "stream_id: %u byte_offset: %llu error_code: %u addr: %s",
- stream_id,
- byte_offset,
- error_code,
- printaddr(&pstream->addr, pstream->threadnum));
-
- return quic_callPlugins(pstream, _context, NULL, 0, QUIC_INTEREST_KEY_MASK, a_packet);
- break;
- case GQUIC_REGULAR_FRAME_CONNECTION_CLOSE:
- if(!check_length(payload_len-*used_len, sizeof(unsigned int)+sizeof(unsigned short)))
- {
- return APP_STATE_GIVEME;
- }
- error_code=(unsigned int)get_variable_length(payload, *used_len, sizeof(unsigned int));
- *used_len+=sizeof(unsigned int);
-
- reason_phrase_length=(unsigned short)get_variable_length(payload, *used_len, sizeof(unsigned short));
- *used_len+=sizeof(unsigned short);
-
- if(!check_length(payload_len-*used_len, reason_phrase_length))
- {
- return APP_STATE_GIVEME;
- }
-
- *used_len+=reason_phrase_length; // skip Reason Phrase
-
- MESA_handle_runtime_log(g_quic_param.logger,
- RLOG_LV_DEBUG,
- "QUIC_CONNECTION_CLOSE",
- "error_code: %u reason_phrase_length: %d addr: %s",
- error_code,
- reason_phrase_length,
- printaddr(&pstream->addr, pstream->threadnum));
-
- return quic_callPlugins(pstream, _context, NULL, 0, QUIC_INTEREST_KEY_MASK, a_packet);
- break;
- case GQUIC_REGULAR_FRAME_GOAWAY:
- if(!check_length(payload_len-*used_len, sizeof(unsigned int)+sizeof(unsigned int)+sizeof(unsigned short)))
- {
- return APP_STATE_GIVEME;
- }
- error_code=(unsigned int)get_variable_length(payload, *used_len, sizeof(unsigned int));
- *used_len+=sizeof(unsigned int);
-
- //Last Good Stream ID
- stream_id=(unsigned int)get_variable_length(payload, *used_len, sizeof(unsigned int));
- *used_len+=sizeof(unsigned int);
-
- reason_phrase_length=(unsigned short)get_variable_length(payload, *used_len, sizeof(unsigned short));
- *used_len+=sizeof(unsigned short);
-
- if(!check_length(payload_len-*used_len, reason_phrase_length))
- {
- return APP_STATE_GIVEME;
- }
- *used_len+=reason_phrase_length; // skip Reason Phrase
-
- MESA_handle_runtime_log(g_quic_param.logger,
- RLOG_LV_DEBUG,
- "QUIC_GOAWAY",
- "error_code: %u Last Good Stream ID: %u reason_phrase_length: %d addr: %s",
- error_code,
- stream_id,
- reason_phrase_length,
- printaddr(&pstream->addr, pstream->threadnum));
- break;
- case GQUIC_REGULAR_FRAME_WINDOW_UPDATE:
- if(!check_length(payload_len-*used_len, sizeof(unsigned int)+sizeof(unsigned long long)))
- {
- return APP_STATE_GIVEME;
- }
- stream_id=(unsigned int)get_variable_length(payload, *used_len, sizeof(unsigned int));
- *used_len+=sizeof(unsigned int);
-
- byte_offset=get_variable_length(payload, *used_len, sizeof(unsigned long long));
- *used_len+=sizeof(unsigned long long);
-
- MESA_handle_runtime_log(g_quic_param.logger,
- RLOG_LV_DEBUG,
- "QUIC_WINDOW_UPDATE",
- "stream_id: %u byte_offset: %llu addr: %s",
- stream_id,
- byte_offset,
- printaddr(&pstream->addr, pstream->threadnum));
- break;
- case GQUIC_REGULAR_FRAME_BLOCKED:
- if(!check_length(payload_len-*used_len, sizeof(unsigned int)))
- {
- return APP_STATE_GIVEME;
- }
- stream_id=(unsigned int)get_variable_length(payload, *used_len, sizeof(unsigned int));
- *used_len+=sizeof(unsigned int);
-
- MESA_handle_runtime_log(g_quic_param.logger,
- RLOG_LV_DEBUG,
- "QUIC_STOP_WAITING",
- "stream_id: %u addr: %s",
- stream_id,
- printaddr(&pstream->addr, pstream->threadnum));
- break;
- case GQUIC_REGULAR_FRAME_STOP_WAITING:
- ret=bit_to_value(payload, payload_len, _context->quic_info.quic_hdr.public_flags>>4, &least_unacked_delta, used_len);
- if(ret<0)
- {
- return APP_STATE_GIVEME;
- }
-
- MESA_handle_runtime_log(g_quic_param.logger,
- RLOG_LV_DEBUG,
- "QUIC_STOP_WAITING",
- "least_unacked_delta: %llu addr: %s",
- least_unacked_delta,
- printaddr(&pstream->addr, pstream->threadnum));
- break;
- case GQUIC_REGULAR_FRAME_PING:
- //The PING frame contains no payload.
- //The receiver of a PING frame simply needs to ACK the packet containing this frame
- break;
- default: //Regular Frame Types
- if(frame_type&GQUIC_SPECIAL_FRAME_STREAM || (frame_type&0xC0)==GQUIC_SPECIAL_FRAME_ACK)
- {
- stream_id=get_stream_id(pstream, _context, payload, payload_len, frame_type, used_len);
- if(stream_id<0)
- {
- return APP_STATE_GIVEME;
- }
- ret=gquic_frame_type_stream(pstream, _context, payload, payload_len, used_len, a_packet);
- }
- else if((frame_type&0xE0)==GQUIC_SPECIAL_FRAME_CONGEST_FB) // high two bits set 0; (frame_type: 01nullmmB)
- {
- //not used
- }
- else
- {
- return APP_STATE_GIVEME;
- }
- break;
- }
-
- if(ret&APP_STATE_DROPME || ret&APP_STATE_DROPPKT)
- {
- return ret;
- }
- }
-
- return APP_STATE_GIVEME;
-}
-
-
-//QUIC_DATA:is quic data pcap;QUIC_TRUE:is handshake pcap;QUIC_RETURN_DROPME:not quic protocol;
-int parse_gquic_Q046(struct streaminfo *pstream, struct _quic_context* _context, void *a_packet, char * payload, int payload_len, int *used_len)
-{
- int stream_id=0;
- int ret=APP_STATE_GIVEME;
- unsigned char frame_type;
-
- while(*used_len < payload_len)
- {
- frame_type=payload[*used_len];
- *used_len+=1; //skip frame_type
-
- if((frame_type>>4)&IQUIC_FRAME_STREAM_HEX08) //0x08=Q048
- {
- stream_id=get_stream_id(pstream, _context, payload, payload_len, frame_type, used_len);
- if(stream_id<0)
- {
- return APP_STATE_GIVEME;
- }
- ret=gquic_frame_type_stream(pstream, _context, payload, payload_len, used_len, a_packet);
- }
- else
- {
- return APP_STATE_GIVEME; //todo
- }
-
- if(ret&APP_STATE_DROPME || ret&APP_STATE_DROPPKT)
- {
- return ret;
- }
- }
-
- return APP_STATE_GIVEME;
-}
-
-int parameter_type_len(unsigned char flags)
-{
- switch(flags)
- {
- case 0:
- return 1;
- break;
- case 1:
- return 2;
- break;
- case 2:
- return 4;
- break;
- case 3:
- return 8;
- break;
- default:
- break;
- }
-
- return 1;
-}
-
-int parse_encrypt_parameter(struct _quic_stream *quic_stream, unsigned char *payload, int payload_len, int thread_seq)
-{
- int used_len=0,length=0;
- int para_type_len=0;
- unsigned long para_type=0;
-
- while(payload_len>used_len)
- {
- para_type_len=parameter_type_len(payload[used_len]>>6);
- para_type=get_value(payload, &used_len, para_type_len); //type=
- switch(para_type&0xFFFF)
- {
- case EXT_QUIC_PARAM_USER_AGENT: // 2021-10-20 deprecated
- quic_stream->ua_idx=quic_stream->ext_tag_num++;
- length=get_value(payload, &used_len, 1); // length=1
- if(length+used_len>payload_len)
- {
- return 0;
- }
- get_quic_tlv((char *)payload+used_len, &(quic_stream->ext_tags[quic_stream->ua_idx]), length, EXT_QUIC_PARAM_USER_AGENT, thread_seq);
- used_len+=length;
- break;
- case EXT_QUIC_PARAM_QUIC_VERSION:
- quic_stream->ver_idx=quic_stream->ext_tag_num++;
- length=get_value(payload, &used_len, 1); // length=1
- if(length+used_len>payload_len)
- {
- return 0;
- }
- get_quic_tlv((char *)payload+used_len, &(quic_stream->ext_tags[quic_stream->ver_idx]), length, EXT_QUIC_PARAM_QUIC_VERSION, thread_seq);
- *(unsigned int *)quic_stream->ext_tags[quic_stream->ver_idx].value=(unsigned int)htonl(*(unsigned int *)quic_stream->ext_tags[quic_stream->ver_idx].value);
- used_len+=length;
- break;
- case EXT_QUIC_PARAM_INIT_RTT:
- case EXT_QUIC_PARAM_GOOGLE_CONN_OPTIONS:
- case EXT_QUIC_PARAM_ORIGINAL_DST_CONN_ID:
- case EXT_QUIC_PARAM_MAX_IDLE_TIMEOUT:
- case EXT_QUIC_PARAM_STATELESS_RST_TOKEN:
- case EXT_QUIC_PARAM_MAX_UDP_PAYLOAD:
- case EXT_QUIC_PARAM_MAX_INIT_DATA:
- case EXT_QUIC_PARAM_MAX_STREAM_BIDI_LOCAL:
- case EXT_QUIC_PARAM_MAX_STREAM_BIDI_REMOTE:
- case EXT_QUIC_PARAM_MAX_STREAM_UNI:
- case EXT_QUIC_PARAM_MAX_STREAMS_BIDI:
- case EXT_QUIC_PARAM_MAX_STREAMS_UNI:
- case EXT_QUIC_PARAM_ACK_DELAY_EXPONENT:
- case EXT_QUIC_PARAM_MAX_ACK_DELAY:
- case EXT_QUIC_PARAM_DISABLE_ACTIVE_MIGRATION:
- case EXT_QUIC_PARAM_PREFERRED_ADDRESS:
- case EXT_QUIC_PARAM_ACTIVE_CONN_ID_LINIT:
- case EXT_QUIC_PARAM_INIT_SRC_CONN_ID:
- case EXT_QUIC_PARAM_RETRY_SRC_CONN_ID:
- case EXT_QUIC_PARAM_MAX_DATAGRAM_FRAME_SIZE:
- default:
- length=get_value(payload, &used_len, 1); // length=1
- used_len+=length;
- break;
- }
- }
-
- return 0;
-}
-int parse_encrypt_server_name(struct _quic_stream *quic_stream, unsigned char *payload, int payload_len, int thread_seq)
-{
- int ext_len=0,used_len=0;
-
- ext_len=get_value(payload, &used_len, 2); //Server Name List length
- if(ext_len<=0 || ext_len>payload_len)
- {
- return 0;
- }
-
- if(get_value(payload, &used_len, 1)==0) //Server Name type
- {
- ext_len=get_value(payload, &used_len, 2); //Server Name length
- if(ext_len<=0 || ext_len>payload_len)
- {
- return 0;
- }
-
- quic_stream->sni_idx=quic_stream->ext_tag_num++;
- get_quic_tlv((char *)payload+used_len, &(quic_stream->ext_tags[quic_stream->sni_idx]), ext_len, EXTENSION_SERVER_NAME, thread_seq);
- }
-
- return 1;
-}
-
-int parse_encrypt_client_hello(struct streaminfo *pstream, struct _quic_stream *quic_stream, void *a_packet, unsigned char *payload, int payload_len)
-{
- int skip_len=0;
- int used_len=0;
- int flags=0,ret=0;
- int ext_type=0, extension_total_len=0;
-
- get_value(payload, &used_len, 1); //handshake type
- get_value(payload, &used_len, 3); //client hello length
- get_value(payload, &used_len, 2); //ssl_version
-
- get_value(payload, &used_len, 32); //Random
-
- skip_len=(int)get_value(payload, &used_len, 1); //Session ID length
- if(!check_length(payload_len-used_len, skip_len))
- {
- return flags;
- }
- used_len+=skip_len;
-
- skip_len=(int)get_value(payload, &used_len, 2); //Ciper Suites length
- if(!check_length(payload_len-used_len, skip_len))
- {
- return flags;
- }
- used_len+=skip_len;
-
- skip_len=(int)get_value(payload, &used_len, 1); //Compression Methods
- if(!check_length(payload_len-used_len, skip_len))
- {
- return flags;
- }
- used_len+=skip_len;
-
- extension_total_len=(int)get_value(payload, &used_len, 2); //Extension length
- if(!check_length(payload_len-used_len, extension_total_len) && (payload_len-used_len!=extension_total_len))
- {
- return flags;
- }
-
- quic_stream->ext_tags=(quic_tlv_t *)dictator_malloc(pstream->threadnum, sizeof(quic_tlv_t)*3);
- memset(quic_stream->ext_tags, 0, sizeof(quic_tlv_t)*3);
- quic_stream->sni_idx=0xFF;
- quic_stream->ua_idx=0xFF;
- quic_stream->ver_idx=0xFF;
-
- while(extension_total_len>used_len)
- {
- ext_type=get_value(payload, &used_len, 2); //Extension type
- skip_len=get_value(payload, &used_len, 2); //length
- if(!check_length(payload_len-used_len, skip_len))
- {
- return flags;
- }
-
- switch(ext_type)
- {
- case EXTENSION_SERVER_NAME:
- ret=parse_encrypt_server_name(quic_stream, payload+used_len, skip_len, pstream->threadnum);
- if(ret<=0)
- {
- break;
- }
- flags=1;
- break;
- case EXTENSION_QUIC_PARAM_TLS_13:
- case EXTENSION_QUIC_PARAM_TLS_33:
- parse_encrypt_parameter(quic_stream, payload+used_len, skip_len, pstream->threadnum);
- break;
- case EXTENSION_SUPPORT_GROUP:
- case EXTENSION_APP_PROT_NEGO:
- case EXTENSION_SIG_ALGORITHM:
- case EXTENSION_KEY_SHARE:
- case EXTENSION_PSK_EXCHANGE:
- case EXTENSION_SUPP_SSL_VER:
- case EXTENSION_COMPRESS_CERT:
- break;
- default:
- break;
- }
-
- used_len+=skip_len;
- }
-
- return flags;
-}
-
-static int get_decrypt_payload(unsigned char * payload, int payload_len, unsigned char *join_payload, int *join_payload_len, int *used_len)
-{
- int join_length=0;
- unsigned char frame_type=0;
- unsigned short offset=0;
- unsigned short length=0;
-
- for(; *used_len<payload_len; )
- {
- frame_type=get_value(payload, used_len, 1); // Frame Type=1
- if(frame_type==IQUIC_FRAME_PADDING || frame_type==IQUIC_FRAME_PING)
- {
- continue;
- }
-
- if((payload+(*used_len))[0]&0x40)
- {
- offset=(get_value(payload, used_len, 2))&0x0FFF; // offset=12bit
- }
- else
- {
- offset=get_value(payload, used_len, 1); // offset=8bit
- }
-
- if((payload+(*used_len))[0]&0x40)
- {
- length=(get_value(payload, used_len, 2))&0x0FFF; // length=12bit
- }
- else
- {
- length=get_value(payload, used_len, 1); // length=8bit
- }
-
- if((*join_payload_len)<join_length+length || offset<0 || offset>payload_len)
- {
- break;
- }
-
- #if 0
- if(frame_type==IQUIC_FRAME_CRYPTO && offset==0 && join_length==0)
- {
- memcpy(join_payload, payload+(*used_len), length);
- join_length+=length;
- break;
- }
-#endif
- memcpy(join_payload+offset, payload+(*used_len), length);
- join_length+=length;
- *used_len+=length;
- }
-
- (*join_payload_len)=join_length;
-
- return join_length;
-}
-
-int parse_decrypt_quic(struct streaminfo *pstream, struct _quic_context* _context, void *a_packet, unsigned char * payload, int payload_len, int *used_len)
-{
- unsigned char join_payload[2048]={0};
- int join_payload_len=sizeof(join_payload);
-
- int ret=0,state=APP_STATE_GIVEME;
- unsigned int quic_version=_context->quic_info.quic_hdr.quic_version;
-
-
- if( (quic_version>=MVFST_VERSION_00 && quic_version<=MVFST_VERSION_0F) ||
- (quic_version>=GQUIC_VERSION_T050 && quic_version<=GQUIC_VERSION_T059) ||
- (quic_version>=IQUIC_VERSION_I022 && quic_version<=IQUIC_VERSION_I029) ||
- (quic_version==IQUIC_VERSION_RFC9000)
- )
- {
- join_payload_len=get_decrypt_payload(payload, payload_len, join_payload, &join_payload_len, used_len);
- if(join_payload_len<=0)
- {
- return state;
- }
- if(join_payload[0] == 0x01)
- {
- if(_context->quic_info.client_hello==NULL)
- {
- _context->quic_info.client_hello=(struct _quic_stream *)dictator_malloc(pstream->threadnum, sizeof(struct _quic_stream));
- memset(_context->quic_info.client_hello, 0, sizeof(struct _quic_stream));
- _context->quic_info.client_hello->sni_idx=0xFF;
- _context->quic_info.client_hello->ua_idx=0xFF;
- _context->quic_info.client_hello->ver_idx=0xFF;
- }
- ret=parse_encrypt_client_hello(pstream, _context->quic_info.client_hello, a_packet, join_payload, join_payload_len);
- if(ret>0 && _context->call_business)
- {
- state=quic_callPlugins(pstream, _context, (void *)(_context->quic_info.client_hello), sizeof(void *), QUIC_CLIENT_HELLO_MASK, a_packet);
- }
- }
- }
- else if(quic_version>=GQUIC_VERSION_Q047 && quic_version<=GQUIC_VERSION_Q059)
- {
- get_value(payload, used_len, 4); // Frame type=1,offset=1,length=2
- state=gquic_frame_type_stream(pstream, _context, (char *)payload, payload_len, used_len, a_packet);
- }
- else
- {
- state=APP_STATE_DROPME;
- }
-
- return state;
-}
-
-//cid->version->nounce->pkt num->ahn hash(12)
-int quic_process(struct streaminfo *pstream, struct _quic_context* _context, int thread_seq, void* a_packet)
-{
- int used_len=0;
- int ret=APP_STATE_GIVEME;
- unsigned char decrypt_payload[1500]={0};
- unsigned int decrypt_payload_len=sizeof(decrypt_payload);
-
- enum _QUIC_VERSION is_gquic=QUIC_VERSION_UNKNOWN;
- struct udpdetail *udp_detail=pstream->pudpdetail;
-
- if(udp_detail->pdata==NULL || udp_detail->datalen<=0)
- {
- return APP_STATE_GIVEME;
- }
-
- is_gquic=is_quic_protocol(pstream, _context, (char *)udp_detail->pdata, udp_detail->datalen, &used_len);
- if(is_gquic!=QUIC_VERSION_UNKNOWN)
- {
- if(_context->cb_version==0 && _context->call_business)
- {
- _context->cb_version=1;
- ret=quic_callPlugins(pstream, _context, &(_context->quic_info.quic_hdr.quic_version), sizeof(_context->quic_info.quic_hdr.quic_version), QUIC_USEING_VERSION_MASK, a_packet);
- if((ret&APP_STATE_DROPME) || (ret&APP_STATE_DROPPKT))
- {
- return ret;
- }
- }
-
- switch(is_gquic)
- {
- case GQUIC_VERSION_Q044:
- case GQUIC_VERSION_Q045:
- case GQUIC_VERSION_Q046:
- case GQUIC_VERSION_Q047:
- case GQUIC_VERSION_Q048:
- ret=parse_gquic_Q046(pstream, _context, a_packet, (char *)udp_detail->pdata, udp_detail->datalen, &used_len);
- break;
- default:
- if(is_gquic>=GQUIC_VERSION_Q001 && is_gquic<=GQUIC_VERSION_Q046)
- {
- ret=gquic_proc_unencrypt(pstream, _context, a_packet, (char *)udp_detail->pdata, udp_detail->datalen, &used_len);
- break;
- }
-
- if( ((is_gquic>=MVFST_VERSION_00 && is_gquic<=MVFST_VERSION_0F) ||
- (is_gquic>=GQUIC_VERSION_Q049 && is_gquic<=GQUIC_VERSION_Q059) ||
- (is_gquic>=GQUIC_VERSION_T050 && is_gquic<=GQUIC_VERSION_T059) ||
- (is_gquic>=GQUIC_VERSION_T050 && is_gquic<=GQUIC_VERSION_T059) ||
- (is_gquic>=IQUIC_VERSION_I022 && is_gquic<=IQUIC_VERSION_I029) ||
- (is_gquic==IQUIC_VERSION_RFC9000)
- )
- && _context->is_decrypt==0
- )
- {
- _context->is_decrypt=1;
- ret=dissect_quic((char *)udp_detail->pdata, udp_detail->datalen, decrypt_payload, &decrypt_payload_len);
- if(ret!=1 || decrypt_payload_len>2048 || decrypt_payload_len<=0)
- {
- return APP_STATE_GIVEME;
- }
- ret=parse_decrypt_quic(pstream, _context, a_packet, decrypt_payload, decrypt_payload_len, &used_len);
- break;
- }
-
- if(_context->call_business)
- {
- ret=quic_callPlugins(pstream, _context, (char *)udp_detail->pdata, udp_detail->datalen, QUIC_APPLICATION_DATA_MASK, a_packet);
- if((ret&APP_STATE_DROPME) || (ret&APP_STATE_DROPPKT))
- {
- return ret;
- }
- }
- break;
- }
-
- if((ret&APP_STATE_DROPME) || (ret&APP_STATE_DROPPKT))
- {
- return ret;
- }
- }
-
- if(_context->is_quic==TRUE)
- {
- if(_context->quic_info.quic_hdr.is_reset && _context->call_business)
- {
- return quic_callPlugins(pstream, _context, NULL, 0, QUIC_INTEREST_KEY_MASK, a_packet);
- }
-
- if(_context->quic_info.quic_hdr.is_version_negotiation && _context->call_business)
- {
- return quic_callPlugins(pstream, _context, NULL, 0, QUIC_NEGOTIATION_VERSION_MASK, a_packet);
- }
- return APP_STATE_GIVEME;
- }
-
- return APP_STATE_DROPME;;
-}
-
-unsigned int quic_protocol_identify(struct streaminfo *a_stream, void *a_packet, char *out_sni, int *out_sni_len, char *out_ua, int *out_ua_len)
-{
- int ret=APP_STATE_GIVEME;
- int len=0;
- void *pme=NULL;
- struct _quic_context *_context=NULL;
- unsigned int quic_version=QUIC_VERSION_UNKNOWN;
-
- if(!is_quic_port(a_stream))
- {
- return quic_version;
- }
-
- quic_init_stream(&pme, a_stream->threadnum);
- _context=(struct _quic_context *)pme;
-
- ret=quic_process(a_stream, _context, a_stream->threadnum, a_packet);
- if(ret!=PROT_STATE_DROPME && _context->is_quic!=QUIC_VERSION_UNKNOWN)
- {
- if(_context->quic_info.client_hello!=NULL && _context->quic_info.client_hello->ext_tags!=NULL)
- {
- if(_context->quic_info.client_hello->sni_idx!=0xFF)
- {
- len=MIN((int)_context->quic_info.client_hello->ext_tags[_context->quic_info.client_hello->sni_idx].length, (*out_sni_len)-1);
- memcpy(out_sni, _context->quic_info.client_hello->ext_tags[_context->quic_info.client_hello->sni_idx].value, len);
- (*out_sni_len)=len;
- }
- else
- {
- (*out_sni_len)=0;
- }
-
- if(_context->quic_info.client_hello->ua_idx!=0xFF)
- {
- len=MIN((int)_context->quic_info.client_hello->ext_tags[_context->quic_info.client_hello->ua_idx].length, (*out_ua_len)-1);
- memcpy(out_ua, _context->quic_info.client_hello->ext_tags[_context->quic_info.client_hello->ua_idx].value, len);
- (*out_ua_len)=len;
- }
- else
- {
- (*out_ua_len)=0;
- }
-
- quic_version=_context->quic_info.quic_hdr.quic_version;
- }
- else
- {
- if(_context->is_quic==TRUE)
- {
- quic_version=_context->quic_info.quic_hdr.quic_version;
- }
- }
- }
-
- quic_release_stream(&pme, a_stream->threadnum);
-
- return quic_version;
-}
diff --git a/src/parser_quic.cpp b/src/quic_deprotection.cpp
index 448935f..58565d1 100644
--- a/src/parser_quic.cpp
+++ b/src/quic_deprotection.cpp
@@ -10,11 +10,11 @@
#include <stdlib.h>
#include <string.h>
-#include "parser_quic.h"
-#include "wsgcrypt.h"
-#include "utils.h"
#include "pint.h"
#include "gcrypt.h"
+#include "quic_deprotection.h"
+#include "quic_deprotection_wsgcrypt.h"
+#include "quic_deprotection_utils.h"
// #define DEBUG_PARSER_QUIC
@@ -163,8 +163,9 @@ static void quic_decrypt_message(quic_pp_cipher *pp_cipher, const char *payload,
header[0] = first_byte;
guint i;
for (i = 0; i < pkn_len; i++)
+ {
header[header_length - 1 - i] = (guint8)(packet_number >> (8 * i));
-
+ }
// Input is "header || ciphertext (buffer) || auth tag (16 bytes)"
// buffer_length = length - (header_length + 16);
// buffer_length = 297 - (2 + 16);
@@ -752,7 +753,7 @@ static void free_quic_cipher(quic_ciphers *initial_ciphers)
}
-int dissect_quic(const char *payload, unsigned int length, unsigned char *out, unsigned int *out_length)
+int quic_deprotection(const char *payload, unsigned int length, unsigned char *out, unsigned int *out_length)
{
guint offset = 0;
quic_packet_info_t quic_packet;
diff --git a/src/parser_quic.h b/src/quic_deprotection.h
index a295bb5..d7d5b67 100644
--- a/src/parser_quic.h
+++ b/src/quic_deprotection.h
@@ -14,7 +14,7 @@ extern "C" {
#endif
/*ret: 1 sucess*/
-int dissect_quic(const char *payload, unsigned int length, unsigned char *out, unsigned int *out_length);
+int quic_deprotection(const char *payload, unsigned int length, unsigned char *out, unsigned int *out_length);
int gcry_init();
#ifdef __cplusplus
diff --git a/src/utils.cpp b/src/quic_deprotection_utils.cpp
index 9af0ffa..f032303 100644
--- a/src/utils.cpp
+++ b/src/quic_deprotection_utils.cpp
@@ -10,9 +10,9 @@
#include <stdlib.h>
#include <string.h>
-#include "utils.h"
-#include "wsgcrypt.h"
#include "pint.h"
+#include "quic_deprotection_utils.h"
+#include "quic_deprotection_wsgcrypt.h"
/*
* Computes HKDF-Expand-Label(Secret, Label, Hash(context_value), Length) with a
diff --git a/src/utils.h b/src/quic_deprotection_utils.h
index 58c8955..58c8955 100644
--- a/src/utils.h
+++ b/src/quic_deprotection_utils.h
diff --git a/src/wsgcrypt.cpp b/src/quic_deprotection_wsgcrypt.cpp
index c6b89a5..369f7f5 100644
--- a/src/wsgcrypt.cpp
+++ b/src/quic_deprotection_wsgcrypt.cpp
@@ -10,7 +10,7 @@
#include <stdlib.h>
#include <string.h>
-#include "wsgcrypt.h"
+#include "quic_deprotection_wsgcrypt.h"
gcry_error_t ws_hmac_buffer(int algo, void *digest, const void *buffer, size_t length, const void *key, size_t keylen)
{
diff --git a/src/wsgcrypt.h b/src/quic_deprotection_wsgcrypt.h
index 1dc7416..1dc7416 100644
--- a/src/wsgcrypt.h
+++ b/src/quic_deprotection_wsgcrypt.h
diff --git a/src/quic_analysis.cpp b/src/quic_entry.cpp
index 639be64..5881c2a 100644
--- a/src/quic_analysis.cpp
+++ b/src/quic_entry.cpp
@@ -1,20 +1,20 @@
/*
- * quic_analysis.c
+ * quic_entry.cpp
*
- * Created on: 2019��4��2��
- * Author: root
+ * Created on: 2021-11-09
+ * Author: liuxueli
*/
-#include "gquic.h"
-#include "quic_analysis.h"
-#include "gquic_process.h"
-#include "parser_quic.h"
-
+
#include <stdio.h>
#include <MESA/stream_inc/stream_base.h>
#include <MESA/MESA_handle_logger.h>
#include <MESA/MESA_prof_load.h>
+#include "quic.h"
+#include "quic_entry.h"
+#include "quic_process.h"
+#include "quic_deprotection.h"
-struct _quic_param_t g_quic_param;
+struct quic_param g_quic_param;
const char *g_quic_proto_conffile="./conf/quic/main.conf";
const char *g_quic_regionname_conffile="./conf/quic/quic.conf";
@@ -106,69 +106,98 @@ static int parse_quic_port(char *port_list, unsigned short *quic_port, int quic_
}
-int quic_init_stream(void **pme, int thread_seq)
+int quic_init_context(void **pme, int thread_seq)
{
- struct _quic_context *_context=(struct _quic_context *)dictator_malloc(thread_seq, sizeof(struct _quic_context));
- memset(_context, 0, sizeof(struct _quic_context));
+ struct quic_context *context=(struct quic_context *)dictator_malloc(thread_seq, sizeof(struct quic_context));
+ memset(context, 0, sizeof(struct quic_context));
- *pme=(void*)_context;
+ *pme=(void*)context;
return 0;
}
-void quic_release_exts(int thread_seq, quic_tlv_t *ext_tags, int ext_tag_num)
+void quic_free_client_hello(struct quic_client_hello *client_hello, int thread_seq)
{
- int i=0;
+ if(client_hello==NULL)
+ {
+ return ;
+ }
- if(ext_tags!=NULL)
+ if(client_hello->sni)
{
- for(i=0; i<ext_tag_num; i++)
- {
- if(ext_tags[i].value!=NULL)
- {
- dictator_free(thread_seq, ext_tags[i].value);
- ext_tags[i].value=NULL;
- }
- }
+ dictator_free(thread_seq, client_hello->sni);
+ client_hello->sni=NULL;
+ }
- dictator_free(thread_seq, ext_tags);
- ext_tags=NULL;
+ if(client_hello->user_agent)
+ {
+ dictator_free(thread_seq, client_hello->user_agent);
+ client_hello->user_agent=NULL;
}
+
+ dictator_free(thread_seq, client_hello);
+ client_hello=NULL;
+
+ return ;
+}
+void quic_free_context(void** pme, int thread_seq)
+{
+ if(NULL==*pme)
+ {
+ return ;
+ }
+
+ struct quic_context *context = (struct quic_context *)*pme;
+ quic_free_client_hello(context->quic_info.client_hello, thread_seq);
+
+ dictator_free(thread_seq, *pme);
+ *pme=NULL;
+
+ return;
}
-void quic_release_stream(void** pme, int thread_seq)
+extern "C" unsigned char QUIC_ENTRY(struct streaminfo *pstream, void**pme, int thread_seq, void *a_packet)
{
- struct _quic_context *_context = (struct _quic_context *)*pme;
- if(NULL!=_context)
- {
- if(_context->quic_info.client_hello!=NULL)
- {
- quic_release_exts(thread_seq, _context->quic_info.client_hello->ext_tags, _context->quic_info.client_hello->ext_tag_num);
- dictator_free(thread_seq, _context->quic_info.client_hello);
- _context->quic_info.client_hello=NULL;
- }
+ unsigned char state=0;
+ struct quic_context *context=(struct quic_context *)*pme;
- if(_context->quic_info.server_hello!=NULL)
- {
- quic_release_exts(thread_seq, _context->quic_info.server_hello->ext_tags, _context->quic_info.server_hello->ext_tag_num);
- dictator_free(thread_seq, _context->quic_info.server_hello);
- _context->quic_info.server_hello=NULL;
- }
-
- if(_context->quic_info.rejection!=NULL)
- {
- quic_release_exts(thread_seq, _context->quic_info.rejection->ext_tags, _context->quic_info.rejection->ext_tag_num);
- dictator_free(thread_seq, _context->quic_info.rejection);
- _context->quic_info.rejection=NULL;
- }
+ if((g_quic_param.quic_interested_region_flag<QUIC_KEY) || (!is_quic_port(pstream)))
+ {
+ return APP_STATE_DROPME;
+ }
- dictator_free(thread_seq, _context);
- _context=NULL;
- *pme=NULL;
+ if(*pme==NULL)
+ {
+ quic_init_context(pme, thread_seq);
+ context=(struct quic_context *)*pme;
+ }
+
+ switch(pstream->opstate)
+ {
+ case OP_STATE_PENDING:
+ state=quic_analyze_entry(pstream, context, thread_seq, a_packet);
+ break;
+ case OP_STATE_DATA:
+ state=quic_call_business_plug(pstream, context, (char *)pstream->pudpdetail->pdata, pstream->pudpdetail->datalen, QUIC_APPLICATION_DATA_MASK, a_packet);
+ break;
+ case OP_STATE_CLOSE:
+ if(pstream->pudpdetail->pdata!=NULL && pstream->pudpdetail->datalen>0)
+ {
+ state=quic_call_business_plug(pstream, context, (char *)pstream->pudpdetail->pdata, pstream->pudpdetail->datalen, QUIC_APPLICATION_DATA_MASK, a_packet);
+ }
+ state=quic_call_business_plug(pstream, context, NULL, 0, QUIC_INTEREST_KEY_MASK, a_packet);
+ break;
}
- return;
+ if(state&APP_STATE_DROPME || state&APP_STATE_DROPPKT || pstream->opstate==OP_STATE_CLOSE)
+ {
+ quic_free_context(pme, thread_seq);
+ *pme=NULL;
+ return state;
+ }
+
+ return APP_STATE_GIVEME;
}
extern "C" int QUIC_INIT(void)
@@ -179,12 +208,12 @@ extern "C" int QUIC_INIT(void)
int region_id=0;
char region_name[REGION_NAME_LEN]={0};
- memset(&g_quic_param,0,sizeof(struct _quic_param_t));
+ memset(&g_quic_param,0,sizeof(struct quic_param));
MESA_load_profile_int_def(g_quic_proto_conffile, "QUIC", "LOG_LEVEL", &g_quic_param.level, RLOG_LV_FATAL);
MESA_load_profile_string_def(g_quic_proto_conffile, "QUIC", "LOG_PATH", g_quic_param.log_path, sizeof(g_quic_param.log_path), "./log/quic/quic");
- MESA_load_profile_int_def(g_quic_proto_conffile, "QUIC", "DUMP_PCAKET_SWITCH", &g_quic_param.dump_packet_switch, 0);
+ MESA_load_profile_int_def(g_quic_proto_conffile, "QUIC", "DECRYPTED_SWITCH", &g_quic_param.decrypted_switch, 2);
MESA_load_profile_string_def(g_quic_proto_conffile, "QUIC", "QUIC_PORT_LIST", buff, sizeof(buff), "443;8443;");
g_quic_param.quic_port_num=parse_quic_port(buff, g_quic_param.quic_port_list, SUPPORT_QUIC_PORT_NUM);
@@ -230,12 +259,7 @@ extern "C" int QUIC_INIT(void)
gcry_init();
return 0;
-}/*QUICINIT*/
-
-extern "C" void QUIC_DESTROY(void)
-{
- return ;
-}/*QUICDESTROY*/
+}
extern "C" void QUIC_GETPLUGID(unsigned short plugid)
{
@@ -251,7 +275,7 @@ extern "C" void QUIC_PROT_FUNSTAT(unsigned long long protflag)
g_quic_param.quic_interested_region_flag=protflag;
MESA_handle_runtime_log(g_quic_param.logger, RLOG_LV_FATAL, "QUIC_PROT_FUNSTAT", "interested_region_flag: %llu", g_quic_param.quic_interested_region_flag);
return;
-}/*PROT_FUNSTAT*/
+}
extern "C" unsigned long long quic_getRegionID(char *string, int str_len,const char g_string[MAX_REGION_NUM][REGION_NAME_LEN])
{
@@ -305,49 +329,8 @@ extern "C" long long QUIC_FLAG_CHANGE(char* flag_str)
return protflag;
}
-extern "C" char QUIC_ENTRY(struct streaminfo *pstream, void**pme, int thread_seq, void *a_packet)
+extern "C" void QUIC_DESTROY(void)
{
- int ret=0;
- struct _quic_context *_context=(struct _quic_context *)*pme;
-
- if(g_quic_param.quic_interested_region_flag<QUIC_KEY)
- {
- return APP_STATE_DROPME;
- }
-
- if(!is_quic_port(pstream))
- {
- return APP_STATE_DROPME;
- }
-
- if(*pme==NULL)
- {
- quic_init_stream(pme, thread_seq);
- _context=(struct _quic_context *)*pme;
- _context->call_business=TRUE;
- }
-
- switch(pstream->opstate)
- {
- case OP_STATE_PENDING:
- case OP_STATE_DATA:
- ret=quic_process(pstream, _context, thread_seq, a_packet);
- break;
- case OP_STATE_CLOSE:
- ret=quic_process(pstream, _context, thread_seq, a_packet);
- quic_callPlugins(pstream, _context, NULL, 0, QUIC_INTEREST_KEY_MASK, a_packet);
- break;
- default:
- break;
- }
-
- if(ret&APP_STATE_DROPME || ret&APP_STATE_DROPPKT || pstream->opstate==OP_STATE_CLOSE)
- {
- quic_release_stream(pme, thread_seq);
- *pme=NULL;
- return ret;
- }
-
- return APP_STATE_GIVEME;
+ return ;
}
diff --git a/src/quic_analysis.h b/src/quic_entry.h
index a3b3cd2..96bd3ae 100644
--- a/src/quic_analysis.h
+++ b/src/quic_entry.h
@@ -1,7 +1,7 @@
#ifndef _QUIC_ANALYSIS_H_
#define _QUIC_ANALYSIS_H_
-#include "gquic.h"
+#include "quic.h"
#define FALSE 0x00
#define TRUE 0x01
@@ -20,14 +20,14 @@
#define MAX_REGION_NUM 15
#define REGION_NAME_LEN 32
-struct _quic_param_t
+struct quic_param
{
unsigned long long quic_interested_region_flag;
unsigned long long quic_region_cnt;
unsigned short quic_plugid;
int level;
int quic_port_num;
- int dump_packet_switch;
+ int decrypted_switch;
unsigned short quic_port_list[SUPPORT_QUIC_PORT_NUM];
char quic_conf_regionname[MAX_REGION_NUM][REGION_NAME_LEN];
char log_path[128];
@@ -45,10 +45,9 @@ enum quic_mes_type{
MSG_UNKNOWN = 255
};
-extern struct _quic_param_t g_quic_param;
-
+extern struct quic_param g_quic_param;
int is_quic_port(struct streaminfo *pstream);
-void quic_release_exts(int thread_seq, quic_tlv_t *ext_tags, int ext_tag_num);
+void quic_free_client_hello(struct quic_client_hello *client_hello, int thread_seq);
#endif /* SRC_QUIC_ANALYSIS_H_ */
diff --git a/src/quic_process.cpp b/src/quic_process.cpp
new file mode 100644
index 0000000..97793ae
--- /dev/null
+++ b/src/quic_process.cpp
@@ -0,0 +1,871 @@
+/*
+ * quic_analyze_entry.cpp
+ *
+ * Created on: 2021-11-09
+ * Author: liuxueli
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/time.h>
+#include <arpa/inet.h>
+#include <MESA/stream.h>
+#include <MESA/MESA_handle_logger.h>
+
+#include "quic_entry.h"
+#include "quic_process.h"
+#include "quic_deprotection.h"
+
+#define PARSE_RESULT_UNKNOWN 0
+#define PARSE_RESULT_VERSION 1
+#define PARSE_RESULT_CLIENT_HELLO 2
+
+#ifndef PRINTADDR
+#define PRINTADDR(a, b) ((b)<RLOG_LV_FATAL ? printaddr(&(a->addr), a->threadnum) : "")
+#endif
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+struct quic_client_hello_msg_hdr
+{
+ uint8_t handshake_type;
+ uint8_t client_hello_len[3];
+ uint16_t tls_version;
+ uint8_t random[32];
+};
+
+int check_port(unsigned short port)
+{
+ int i=0;
+ for(i=0; i< g_quic_param.quic_port_num; i++)
+ {
+ if(g_quic_param.quic_port_list[i]==port)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int is_quic_port(struct streaminfo *pstream)
+{
+ unsigned short source=0, dest=0;
+
+ switch(pstream->addr.addrtype)
+ {
+ case ADDR_TYPE_IPV4:
+ case __ADDR_TYPE_IP_PAIR_V4:
+ source=(unsigned short)ntohs(pstream->addr.ipv4->source);
+ dest=(unsigned short)ntohs(pstream->addr.ipv4->dest);
+ break;
+ case ADDR_TYPE_IPV6:
+ case __ADDR_TYPE_IP_PAIR_V6:
+ source=(unsigned short)ntohs(pstream->addr.ipv6->source);
+ dest=(unsigned short)ntohs(pstream->addr.ipv6->dest);
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ if(check_port(source) || check_port(dest))
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+static int gquic_pkn_bit2length(unsigned char bit_value)
+{
+ switch(bit_value)
+ {
+ case 0x30: return 6;
+ case 0x20: return 4;
+ case 0x10: return 2;
+ default:
+ return 1;
+ }
+
+ return 1;
+}
+
+static int copy_extension_tag(const char *tag_start_pos, int tag_len, char **out, int thread_seq)
+{
+ if(tag_start_pos!=NULL && tag_len>0)
+ {
+ (*out)=(char *)dictator_malloc(thread_seq, tag_len+1);
+ memcpy(*out, tag_start_pos, tag_len);
+ (*out)[tag_len]='\0';
+
+ return tag_len;
+ }
+
+ return 0;
+}
+
+//Source: https://wise2.ipac.caltech.edu/staff/slw/docs/html/varint_8h_source.html
+static int msb2_varint_decode(const unsigned char *buf, long *out)
+{
+ unsigned long val = buf[0] & 0x3f;
+ unsigned int nfollow = 1<<(buf[0]>>6);
+ switch (nfollow-1)
+ {
+ case 7: val = (val << 8) | buf[nfollow - 7]; /*fail through*/
+ case 6: val = (val << 8) | buf[nfollow - 6]; /*fail through*/
+ case 5: val = (val << 8) | buf[nfollow - 5]; /*fail through*/
+ case 4: val = (val << 8) | buf[nfollow - 4]; /*fail through*/
+ case 3: val = (val << 8) | buf[nfollow - 3]; /*fail through*/
+ case 2: val = (val << 8) | buf[nfollow - 2]; /*fail through*/
+ case 1: val = (val << 8) | buf[nfollow-1];
+ case 0: break;
+ }
+ *out=val;
+
+ return nfollow;
+}
+
+int quic_call_business_state(struct quic_context *context)
+{
+ UCHAR state = 0;
+
+ if(0==context->link_state)
+ {
+ state=SESSION_STATE_PENDING|SESSION_STATE_DATA;
+ context->link_state=1;
+ }
+ else
+ {
+ state=SESSION_STATE_DATA;
+ }
+
+ return state;
+}
+
+unsigned char quic_call_business_plug(struct streaminfo *pstream, struct quic_context *context, void *buff, int buff_len, enum quic_interested_region region_mask, void *a_packet)
+{
+ char state=PROT_STATE_GIVEME;
+ char app_state=APP_STATE_GIVEME;
+ stSessionInfo session_info={0};
+
+ if(region_mask==QUIC_INTEREST_KEY_MASK)
+ {
+ session_info.plugid=g_quic_param.quic_plugid;
+ session_info.prot_flag=0;
+ session_info.session_state=SESSION_STATE_CLOSE;
+ session_info.app_info=NULL;
+ session_info.buf=NULL;
+ session_info.buflen=0;
+ }
+ else
+ {
+ session_info.plugid=g_quic_param.quic_plugid;
+ session_info.prot_flag=(((unsigned long long)1)<<region_mask);
+ session_info.session_state=quic_call_business_state(context) ;
+ session_info.app_info=(void*)(&context->quic_info);
+ session_info.buf=buff;
+ session_info.buflen=buff_len;
+ }
+ state=PROT_PROCESS(&session_info, &(context->business_pme), pstream->threadnum, pstream, a_packet);
+
+ if(state&PROT_STATE_DROPPKT)
+ {
+ app_state=APP_STATE_DROPPKT;
+ }
+
+ return app_state;
+}
+
+/*
+
+//https://docs.google.com/document/d/1FcpCJGTDEMblAs-Bm5TYuqhHyUqeWpqrItw2vkMFsdY/edit
+
+Long Header (used for packets that are sent prior to the completion of version negotiation and establishment of 1-RTT keys):
++-+-+-+-+-+-+-+-+
+|1|1|T|T|R|R|P|P|
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Version (32) |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|DCIL(4)|SCIL(4)|
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Destination Connection ID (0/64) ...
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Source Connection ID (0/64) ...
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Packet Number (8/16/24/32) ...
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+*/
+
+
+static int join_client_hello_frames(const char *payload, int payload_len, char *join_payload, int *join_payload_len)
+{
+ int joined_length=0;
+ int payload_offset=0;
+ long frame_type=0, frame_offset=0, frame_length=0;
+
+ for(; payload_offset<payload_len; )
+ {
+ frame_type=payload[payload_offset++]; // Frame Type=1
+ if(frame_type==IQUIC_FRAME_PADDING || frame_type==IQUIC_FRAME_PING)
+ {
+ continue;
+ }
+
+ payload_offset+=msb2_varint_decode((const unsigned char *)(payload+payload_offset), &frame_offset);
+ payload_offset+=msb2_varint_decode((const unsigned char *)(payload+payload_offset), &frame_length);
+
+ if(joined_length+frame_length>(*join_payload_len) || frame_offset<0 || frame_offset+frame_length>payload_len)
+ {
+ return -1;
+ }
+ memcpy(join_payload+frame_offset, payload+payload_offset, frame_length);
+ joined_length+=frame_length;
+ payload_offset+=frame_length;
+ }
+
+ (*join_payload_len)=joined_length;
+
+ return joined_length;
+}
+
+static int parse_gquic_version_44to48_header(const char *payload, int payload_len, int *payload_offset)
+{
+ unsigned pkn_length=0;
+ unsigned char client_CID_len=0;
+ unsigned char server_CID_len=0;
+ unsigned char public_flags=payload[*payload_offset];
+ *payload_offset+=1; //skip public flags
+
+ *payload_offset+=sizeof(int); // skip version
+
+ if((payload[*payload_offset])&GQUIC_VERSION_44to48_CID_MASK)
+ {
+ client_CID_len=(payload[*payload_offset]&GQUIC_VERSION_44to48_CID_MASK) + 3;
+ }
+
+ if((payload[*payload_offset]>>4)&GQUIC_VERSION_44to48_CID_MASK)
+ {
+ server_CID_len=((payload[*payload_offset]>>4)&GQUIC_VERSION_44to48_CID_MASK) + 3;
+ }
+
+ *payload_offset+=1; // both connection_id length
+ *payload_offset+=server_CID_len; // Destination connection id length
+ *payload_offset+=client_CID_len; // source connection id length
+
+ pkn_length=(public_flags&GQUIC_VERSION_44to48_PKN_LEN_MASK)+1;
+ *payload_offset+=pkn_length;
+
+ *payload_offset+=12; //message authentication hash
+
+ return 1;
+}
+
+int parse_special_frame_stream(struct quic_info* quic_info, const char *payload, int payload_len, int thread_seq)
+{
+ int tag_num = 0;
+ int payload_offset=0;
+ unsigned int message_tag;
+ int pass_tag_num=0;
+ int ext_tag_type=0;
+ int tag_value_start_offset=0;
+ int total_tag_len=0,one_tag_len=0;
+ int parse_result=PARSE_RESULT_VERSION;
+ int one_tag_offset_end=0,pre_one_tag_offset_end=0;
+
+ if(payload_len-payload_offset<=8)
+ {
+ return PARSE_RESULT_VERSION;
+ }
+
+ switch(quic_info->quic_version)
+ {
+ case GQUIC_VERSION_Q041:
+ payload_offset+=1; // unknown
+ case GQUIC_VERSION_Q044:
+ message_tag=(unsigned int)ntohl(*(unsigned int *)(payload+payload_offset));
+ payload_offset+=4;
+
+ tag_num=*(int *)(payload+payload_offset);
+ payload_offset+=4; //tag_num
+ break;
+ default:
+ message_tag=(unsigned int)ntohl(*(unsigned int *)(payload+payload_offset));
+ payload_offset+=4;
+
+ tag_num=*(unsigned short *)(payload+payload_offset);
+ payload_offset+=2; //tag_num
+ payload_offset+=2; //padding
+ break;
+ }
+
+ if(message_tag!=CHLO || tag_num>64 || tag_num<=0)
+ {
+ return PARSE_RESULT_VERSION;
+ }
+
+ quic_info->client_hello=(struct quic_client_hello *)dictator_malloc(thread_seq, sizeof(struct quic_client_hello));
+ memset(quic_info->client_hello, 0, sizeof(struct quic_client_hello));
+
+ tag_value_start_offset=payload_offset+tag_num*4*2; // skip length of type and offset, type(offset)=szieof(int)
+
+ while(tag_num>pass_tag_num)
+ {
+ ext_tag_type=ntohl(*(unsigned int *)(payload+payload_offset));
+ payload_offset+=sizeof(int);
+
+ one_tag_offset_end=*(unsigned int *)(payload+payload_offset);
+ payload_offset+=sizeof(int);
+
+ one_tag_len=one_tag_offset_end-pre_one_tag_offset_end;
+ if(one_tag_len<=0 || (one_tag_offset_end>=payload_len) || (one_tag_len+tag_value_start_offset)>payload_len)
+ {
+ break;
+ }
+
+ switch(ext_tag_type)
+ {
+ case TAG_UAID:
+ copy_extension_tag(payload+tag_value_start_offset, one_tag_len, &quic_info->client_hello->user_agent, thread_seq);
+ parse_result=PARSE_RESULT_CLIENT_HELLO;
+ break;
+ case TAG_SNI:
+ copy_extension_tag(payload+tag_value_start_offset, one_tag_len, &quic_info->client_hello->sni, thread_seq);
+ parse_result=PARSE_RESULT_CLIENT_HELLO;
+ break;
+ default:
+ break;
+ }
+
+ pass_tag_num++;
+ tag_value_start_offset+=one_tag_len;
+ total_tag_len+=one_tag_len;
+ pre_one_tag_offset_end=one_tag_offset_end;
+ }
+
+ return parse_result;
+}
+
+int parse_quic_transport_parameter(struct quic_client_hello *client_hello, const char *quic_para, int quic_para_len, int thread_seq)
+{
+ int one_para_length=0;
+ int para_offset=0;
+ long one_para_type=0;
+
+ while(quic_para_len > para_offset)
+ {
+ para_offset+=msb2_varint_decode((const unsigned char *)(quic_para+para_offset), &one_para_type);
+ switch(one_para_type)
+ {
+ case EXT_QUIC_PARAM_USER_AGENT: // 2021-10-20 deprecated
+ one_para_length=quic_para[para_offset++]; // length=1
+ if(one_para_length+para_offset>quic_para_len)
+ {
+ return 0;
+ }
+ para_offset+=copy_extension_tag(quic_para+para_offset, one_para_length, &client_hello->user_agent, thread_seq);
+ return 1;
+ default:
+ one_para_length=quic_para[para_offset++]; // length=1
+ para_offset+=one_para_length;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int parse_extension_server_name(struct quic_client_hello *client_hello, const char *ext_server_name, int ext_server_name_length, int thread_seq)
+{
+ unsigned short sni_type=0;
+ unsigned short sni_length=0;
+ unsigned short extension_offset=0;
+ unsigned short server_name_list_len=0;
+
+ server_name_list_len=ntohs(*(unsigned short *)(ext_server_name+extension_offset)); //Server Name List length
+ if(server_name_list_len<=0 || server_name_list_len>ext_server_name_length)
+ {
+ return 0;
+ }
+ extension_offset+=2; //Server Name List length
+
+ sni_type=ext_server_name[extension_offset++]; //Server Name type
+ if(sni_type!=EXTENSION_SERVER_NAME)
+ {
+ return 0;
+ }
+
+ sni_length=ntohs(*(unsigned short*)(ext_server_name+extension_offset)); //Server Name length
+ if(sni_length<=0 || sni_length>ext_server_name_length)
+ {
+ return 0;
+ }
+ extension_offset+=2;
+
+ copy_extension_tag(ext_server_name+extension_offset, sni_length, &client_hello->sni, thread_seq);
+
+ return 1;
+}
+
+int parse_tls_client_hello(struct quic_client_hello **client_hello, const char *payload, int payload_len, int thread_seq)
+{
+ int ret=0,skip_len=0;
+ int payload_offset=0;
+ int extension_offset=0;
+ const char *extension_start_pos=NULL;
+ int parse_result=PARSE_RESULT_VERSION;
+ unsigned short one_ext_type=0, one_ext_len=0, extension_total_len=0;
+
+ if(payload_len-payload_offset<=sizeof(struct quic_client_hello_msg_hdr))
+ {
+ return PARSE_RESULT_VERSION;
+ }
+
+ // handshake type(1), client hello length(3), ssl_version(2), Random(32)
+ payload_offset+=sizeof(struct quic_client_hello_msg_hdr);
+
+ skip_len=payload[payload_offset++]; //Session ID length
+ if(payload_len-payload_offset<=skip_len)
+ {
+ return PARSE_RESULT_VERSION;
+ }
+ payload_offset+=skip_len;
+
+ skip_len=ntohs(*(unsigned short *)(payload+payload_offset)); //Ciper Suites length
+ if(payload_len-payload_offset<=skip_len+2)
+ {
+ return PARSE_RESULT_VERSION;
+ }
+ payload_offset+=skip_len+2;
+
+ skip_len=payload[payload_offset++]; //Compression Methods
+ if(payload_len-payload_offset<skip_len)
+ {
+ return PARSE_RESULT_VERSION;
+ }
+ payload_offset+=skip_len;
+
+ extension_total_len=ntohs(*(unsigned short *)(payload+payload_offset)); //Extension length
+ if(payload_len-payload_offset<extension_total_len)
+ {
+ return PARSE_RESULT_VERSION;
+ }
+
+ payload_offset+=2;
+
+ if(*client_hello==NULL)
+ {
+ *client_hello=(struct quic_client_hello *)dictator_malloc(thread_seq, sizeof(struct quic_client_hello));
+ memset(*client_hello, 0, sizeof(struct quic_client_hello));
+ }
+
+ extension_start_pos=payload+payload_offset;
+
+ while(extension_total_len > extension_offset)
+ {
+ one_ext_type=ntohs(*(unsigned short *)(extension_start_pos+extension_offset)); //Extension type
+ extension_offset+=2;
+
+ one_ext_len=ntohs(*(unsigned short *)(extension_start_pos+extension_offset)); //length
+ extension_offset+=2;
+
+ if(extension_total_len-extension_offset<one_ext_len)
+ {
+ break;
+ }
+
+ switch(one_ext_type)
+ {
+ case EXTENSION_SERVER_NAME:
+ ret=parse_extension_server_name(*client_hello, extension_start_pos+extension_offset, one_ext_len, thread_seq);
+ break;
+ case EXTENSION_QUIC_PARAM_TLS_13:
+ case EXTENSION_QUIC_PARAM_TLS_33:
+ ret=parse_quic_transport_parameter(*client_hello, extension_start_pos+extension_offset, one_ext_len, thread_seq);
+ break;
+ default:
+ break;
+ }
+
+ if(ret==1)
+ {
+ ret=0;
+ parse_result=PARSE_RESULT_CLIENT_HELLO;
+ }
+
+ extension_offset+=one_ext_len;
+ }
+
+ return parse_result;
+}
+
+int parse_quic_decrypted_payload(struct quic_info *quic_info, const char * payload, int payload_len, int thread_seq)
+{
+ char join_payload[2048]={0};
+ int join_payload_len=sizeof(join_payload);
+ unsigned int quic_version=quic_info->quic_version;
+
+ if( (quic_version>=MVFST_VERSION_00 && quic_version<=MVFST_VERSION_0F) ||
+ (quic_version>=GQUIC_VERSION_T050 && quic_version<=GQUIC_VERSION_T059) ||
+ (quic_version>=IQUIC_VERSION_I022 && quic_version<=IQUIC_VERSION_I029) ||
+ (quic_version==IQUIC_VERSION_RFC9000)
+ )
+ {
+ join_payload_len=join_client_hello_frames(payload, payload_len, join_payload, &join_payload_len);
+ if(join_payload_len<=0)
+ {
+ return PARSE_RESULT_VERSION;
+ }
+
+ if(join_payload[0] == QUIC_HANDSHAKE_TYPE_CLIENTHELLO)
+ {
+ return parse_tls_client_hello(&(quic_info->client_hello), join_payload, join_payload_len, thread_seq);
+ }
+ }
+ else //if(quic_version>=GQUIC_VERSION_Q047 && quic_version<=GQUIC_VERSION_Q059)
+ {
+ return parse_special_frame_stream(quic_info, (char *)payload+4, payload_len-4, thread_seq); // Frame type=1,offset=1,length=2
+ }
+
+ return PARSE_RESULT_VERSION;
+}
+
+int parse_quic_uncryption_payload(struct quic_info *quic_info, const char * payload, int payload_len, int thread_seq)
+{
+ int stream_id_len=0;
+ int offset_len=0;
+ unsigned char frame_type;
+ int payload_offset=0;
+
+ frame_type=payload[payload_offset];
+ payload_offset+=1; //skip frame_type
+
+ //https://docs.google.com/document/d/1WJvyZflAO2pq77yOLbp9NsGjC1CHetAXV8I0fQe-B_U/edit#
+ //Frame Type: The Frame Type byte is an 8-bit value containing various flags (1fdooossB):
+ if(frame_type&GQUIC_SPECIAL_FRAME_STREAM || (frame_type&0xC0)==GQUIC_SPECIAL_FRAME_ACK)
+ {
+ stream_id_len=(frame_type&GQUIC_SPECIAL_FRAME_STREAM_ID)+1;
+ if(payload_len-payload_offset<=stream_id_len)
+ {
+ return PARSE_RESULT_VERSION;
+ }
+
+ payload_offset+=stream_id_len; // stream ID length
+
+ if(frame_type&GQUIC_SPECIAL_FRAME_STREAM_DLEN)
+ {
+ if(payload_len-payload_offset<2)
+ {
+ return PARSE_RESULT_VERSION;
+ }
+ payload_offset+=2; //data length
+ }
+
+ if(frame_type&GQUIC_SPECIAL_FRAME_STREAM_OFFSET)
+ {//The next three 'ooo' bits encode the length of the Offset header field as 0, 16, 24, 32, 40, 48, 56, or 64 bits long.
+ offset_len= (((frame_type&GQUIC_SPECIAL_FRAME_STREAM_OFFSET))>>2)+1;
+ if(payload_len-payload_offset<=offset_len)
+ {
+ return PARSE_RESULT_VERSION;
+ }
+ payload_offset+=offset_len; //data length
+ }
+
+ return parse_special_frame_stream(quic_info, payload+payload_offset, payload_len-payload_offset, thread_seq);
+ }
+
+ return PARSE_RESULT_VERSION;
+}
+
+/*
+//https://docs.google.com/document/d/1WJvyZflAO2pq77yOLbp9NsGjC1CHetAXV8I0fQe-B_U/edit
+
+--- src
+ 0 1 2 3 4 8
++--------+--------+--------+--------+--------+--- ---+
+| Public | Connection ID (64) ... | ->
+|Flags(8)| (optional) |
++--------+--------+--------+--------+--------+--- ---+
+
+ 9 10 11 12
++--------+--------+--------+--------+
+| QUIC Version (32) | ->
+| (optional) |
++--------+--------+--------+--------+
+
+
+ 13 14 15 16 17 18 19 20
++--------+--------+--------+--------+--------+--------+--------+--------+
+| Diversification Nonce | ->
+| (optional) |
++--------+--------+--------+--------+--------+--------+--------+--------+
+
+ 21 22 23 24 25 26 27 28
++--------+--------+--------+--------+--------+--------+--------+--------+
+| Diversification Nonce Continued | ->
+| (optional) |
++--------+--------+--------+--------+--------+--------+--------+--------+
+
+ 29 30 31 32 33 34 35 36
++--------+--------+--------+--------+--------+--------+--------+--------+
+| Diversification Nonce Continued | ->
+| (optional) |
++--------+--------+--------+--------+--------+--------+--------+--------+
+
+ 37 38 39 40 41 42 43 44
++--------+--------+--------+--------+--------+--------+--------+--------+
+| Diversification Nonce Continued | ->
+| (optional) |
++--------+--------+--------+--------+--------+--------+--------+--------+
+
+
+ 45 46 47 48 49 50
++--------+--------+--------+--------+--------+--------+
+| Packet Number (8, 16, 32, or 48) |
+| (variable length) |
++--------+--------+--------+--------+--------+--------+
+
+*/
+enum QUIC_VERSION identify_gquic_version0to43(const char *payload, int payload_len, int *payload_offset)
+{
+ unsigned char pkn_length=0;
+ unsigned char public_flags=0;
+ enum QUIC_VERSION quic_version=QUIC_VERSION_UNKNOWN;
+
+ public_flags=payload[*payload_offset];
+ *payload_offset+=1;
+
+ if(!(public_flags&GQUIC_PUBLIC_FLAG_VERSION))
+ {
+ return QUIC_VERSION_UNKNOWN;
+ }
+
+ /*
+ 0x08 = Indicates the full 8 byte Connection ID is present in the packet.
+ This must be set in all packets until negotiated to a different value for a given direction
+ (e.g., client may request fewer bytes of the Connection ID be presented)
+ */
+ if(public_flags&GQUIC_PUBLIC_FLAG_CID)
+ {
+ *payload_offset+=8; // CID length
+ }
+
+ if(public_flags&GQUIC_PUBLIC_FLAG_VERSION && (*(unsigned char *)(payload+*payload_offset)==0x51))
+ {
+ quic_version=(enum QUIC_VERSION)ntohl(*(unsigned int *)(payload+*payload_offset));
+ *payload_offset+=sizeof(int); // skip version
+ }
+
+ if(quic_version<GQUIC_VERSION_Q001 || quic_version>GQUIC_VERSION_Q043)
+ {
+ return QUIC_VERSION_UNKNOWN;
+ }
+
+ pkn_length=gquic_pkn_bit2length(public_flags&GQUIC_VERSION_0to43_PKN_LEN_MASK);
+ *payload_offset+=pkn_length; // packet number length
+
+ if(public_flags==GQUIC_PUBLIC_FLAG_NONCE)
+ {
+ *payload_offset+=32; //diversification nonce
+ }
+
+ // Version 11 reduced the length of null encryption authentication tag from 16 to 12 bytes
+ if(quic_version > GQUIC_VERSION_Q010)
+ {
+ *payload_offset+=12;
+ }
+ else
+ {
+ *payload_offset+=16;
+ }
+
+ // Version 34 removed entropy bits from packets and ACK frames,
+ // removed private flag from packet header and changed the ACK format to specify ranges of packets acknowledged rather than missing ranges.
+ if(quic_version < GQUIC_VERSION_Q034)
+ {
+ *payload_offset+=1; //private flags
+ }
+
+ return quic_version;
+}
+
+enum QUIC_VERSION identify_quic_version(const char *payload, int payload_len, int *payload_offset)
+{
+ enum QUIC_VERSION quic_version=(enum QUIC_VERSION)ntohl(*(unsigned int *)(payload+(*payload_offset+1)));
+ if(quic_version>=GQUIC_VERSION_Q044 && quic_version<=GQUIC_VERSION_Q048)
+ {
+ parse_gquic_version_44to48_header(payload, payload_len, payload_offset);
+ return quic_version;
+ }
+ else if(
+ (quic_version==GQUIC_VERSION_Q099) ||
+ (quic_version==PICOQUIC_VERSION_30) ||
+ (quic_version==PQUIC_VERSION_PROX) ||
+ (quic_version==GQUIC_VERSION_T099) ||
+ (quic_version>=GQUIC_VERSION_Q049 && quic_version<=GQUIC_VERSION_Q050) ||
+ (quic_version>=GQUIC_VERSION_Q051 && quic_version<=GQUIC_VERSION_Q059) ||
+ (quic_version>=GQUIC_VERSION_T048 && quic_version<=GQUIC_VERSION_T049) ||
+ (quic_version>=GQUIC_VERSION_T050 && quic_version<=GQUIC_VERSION_T059) ||
+ (quic_version>=QUANT_VERSION_00 && quic_version<=QUANT_VERSION_FF) ||
+ (quic_version>=QUIC_GO_VERSION_00 && quic_version<=QUIC_GO_VERSION_FF) ||
+ (quic_version>=QUICLY_VERSION_00 && quic_version<=QUICLY_VERSION_FF) ||
+ (quic_version>=MSQUIC_VERSION_00 && quic_version<=MSQUIC_VERSION_0F) ||
+ (quic_version>=MOZQUIC_VERSION_00 && quic_version<=MOZQUIC_VERSION_0F) ||
+ (quic_version>=MVFST_VERSION_00 && quic_version<=MVFST_VERSION_0F) ||
+ (quic_version>=IQUIC_VERSION_I001 && quic_version<=IQUIC_VERSION_I032) ||
+ (quic_version==IQUIC_VERSION_RFC9000)
+ )
+ {
+ return quic_version;
+ }
+
+ return QUIC_VERSION_UNKNOWN;
+}
+
+enum QUIC_VERSION is_quic_protocol(const char *payload, int payload_len, int *payload_offset)
+{
+ enum QUIC_VERSION quic_version=QUIC_VERSION_UNKNOWN;
+ unsigned char frame_type=(unsigned char)(payload[0]);
+
+ if(frame_type&QUIC_LONG_HEADER_MASK)
+ {
+ quic_version=identify_quic_version(payload, payload_len, payload_offset);
+ }
+ else if(frame_type<QUIC_LONG_HEADER_MASK)
+ {
+ quic_version=identify_gquic_version0to43(payload, payload_len, payload_offset);
+ }
+ else
+ {
+ return QUIC_VERSION_UNKNOWN;
+ }
+
+ return quic_version;
+}
+
+int parse_quic_all_version(struct quic_info *quic_info, const char *payload, int payload_len, int thread_seq)
+{
+ int ret=0, payload_offset=0;
+ unsigned char decrypt_payload[2048]={0};
+ unsigned int decrypt_payload_len=sizeof(decrypt_payload);
+ enum QUIC_VERSION quic_version=QUIC_VERSION_UNKNOWN;
+
+ if(payload==NULL || payload_len<=0)
+ {
+ return PARSE_RESULT_UNKNOWN;
+ }
+
+ quic_version=is_quic_protocol(payload, payload_len, &payload_offset);
+ if(quic_version==QUIC_VERSION_UNKNOWN)
+ {
+ return PARSE_RESULT_UNKNOWN;
+ }
+
+ quic_info->quic_version=quic_version;
+
+ if(quic_version>=GQUIC_VERSION_Q001 && quic_version<=GQUIC_VERSION_Q048)
+ {
+ return parse_quic_uncryption_payload(quic_info, payload+payload_offset, payload_len-payload_offset, thread_seq);
+ }
+ else if(((quic_version>=MVFST_VERSION_00 && quic_version<=MVFST_VERSION_0F) ||
+ (quic_version>=GQUIC_VERSION_Q049 && quic_version<=GQUIC_VERSION_Q059) ||
+ (quic_version>=GQUIC_VERSION_T050 && quic_version<=GQUIC_VERSION_T059) ||
+ (quic_version>=GQUIC_VERSION_T050 && quic_version<=GQUIC_VERSION_T059) ||
+ (quic_version>=IQUIC_VERSION_I022 && quic_version<=IQUIC_VERSION_I029) ||
+ (quic_version==IQUIC_VERSION_RFC9000))
+ && g_quic_param.decrypted_switch>0
+ )
+ {
+ ret=quic_deprotection(payload, payload_len, decrypt_payload, &decrypt_payload_len);
+ if(ret!=1 || decrypt_payload_len<=0)
+ {
+ return PARSE_RESULT_VERSION;
+ }
+
+ if(g_quic_param.decrypted_switch==2)
+ {
+ return parse_quic_decrypted_payload(quic_info, (const char *)decrypt_payload, decrypt_payload_len, thread_seq);
+ }
+ }
+ else
+ {
+ return PARSE_RESULT_VERSION;
+ }
+
+ return PARSE_RESULT_VERSION;
+}
+
+
+unsigned char quic_analyze_entry(struct streaminfo *pstream, struct quic_context* context, int thread_seq, void* a_packet)
+{
+ int ret=PARSE_RESULT_UNKNOWN;
+ if(pstream==NULL || pstream->pudpdetail==NULL)
+ {
+ return APP_STATE_DROPME;
+ }
+ struct udpdetail *udp_detail=pstream->pudpdetail;
+ ret=parse_quic_all_version(&(context->quic_info), (const char *)udp_detail->pdata, udp_detail->datalen, thread_seq);
+ switch(ret)
+ {
+ case PARSE_RESULT_VERSION:
+ return quic_call_business_plug(pstream, context, (void *)&(context->quic_info.quic_version), sizeof(unsigned int), QUIC_USEING_VERSION_MASK, a_packet);
+ case PARSE_RESULT_CLIENT_HELLO:
+ return quic_call_business_plug(pstream, context, (void *)&(context->quic_info), sizeof(void *), QUIC_CLIENT_HELLO_MASK, a_packet);
+ default:
+ break;
+ }
+
+ return APP_STATE_DROPME;
+}
+
+static int copy_client_hello_extension(char *src, char *dest, int d_len)
+{
+ if(src==NULL || dest==NULL || d_len<=0)
+ {
+ return 0;
+ }
+
+ int len=MIN((int)strlen(src), d_len-1);
+ memcpy(dest, src, len);
+ dest[len]='\0';
+
+ return len;
+}
+
+unsigned int quic_protocol_identify(struct streaminfo *a_stream, void *a_packet, char *out_sni, int *out_sni_len, char *out_ua, int *out_ua_len)
+{
+ int ret=APP_STATE_GIVEME;
+ struct quic_info quic_info={0, NULL};
+ unsigned int quic_version=QUIC_VERSION_UNKNOWN;
+
+ if(!is_quic_port(a_stream) || a_stream==NULL || a_stream->pudpdetail==NULL)
+ {
+ return quic_version;
+ }
+
+ ret=parse_quic_all_version(&quic_info, (const char *)a_stream->pudpdetail->pdata, a_stream->pudpdetail->datalen, a_stream->threadnum);
+ if(ret!=PARSE_RESULT_UNKNOWN)
+ {
+ if(quic_info.client_hello!=NULL)
+ {
+ *out_sni_len=copy_client_hello_extension(quic_info.client_hello->sni, out_sni, *out_sni_len);
+ *out_ua_len=copy_client_hello_extension(quic_info.client_hello->user_agent, out_ua, *out_ua_len);
+ quic_free_client_hello(quic_info.client_hello, a_stream->threadnum);
+ }
+ else
+ {
+ *out_sni_len=0;
+ *out_ua_len=0;
+ }
+
+ quic_version=quic_info.quic_version;
+ }
+
+ return quic_version;
+}
+
diff --git a/src/gquic_process.h b/src/quic_process.h
index 2188a7c..6a77769 100644
--- a/src/gquic_process.h
+++ b/src/quic_process.h
@@ -1,5 +1,5 @@
/*
- * quic_process.h
+ * quic_analyze_entry.h
*
* Created on: 2019��4��2��
* Author: root
@@ -12,10 +12,13 @@
#include <stdint.h>
#include <stdbool.h>
-#include "gquic.h"
+#include "quic.h"
-//#define VERSION_LEN 4
-//#define VER_Q046
+#define QUIC_LONG_HEADER_MASK 0x80
+
+#define GQUIC_VERSION_44to48_CID_MASK 0x0F
+#define GQUIC_VERSION_44to48_PKN_LEN_MASK 0x03
+#define GQUIC_VERSION_0to43_PKN_LEN_MASK 0x30
#define GQUIC_PUBLIC_FLAG_VERSION 0x01
#define GQUIC_PUBLIC_FLAG_RST 0x02
@@ -41,60 +44,15 @@
#define GQUIC_REGULAR_FRAME_WINDOW_UPDATE 0x04
#define GQUIC_REGULAR_FRAME_BLOCKED 0x05
#define GQUIC_REGULAR_FRAME_STOP_WAITING 0x06
-#define GQUIC_REGULAR_FRAME_PING 0x07
-
-#define GQUIC_SPECIAL_FRAME_FLAG 0xE0 // Special Frame Types
-#define GQUIC_SPECIAL_FRAME_STREAM 0x80
-#define GQUIC_SPECIAL_FRAME_ACK 0x40
-#define GQUIC_SPECIAL_FRAME_CONGEST_FB 0x20
-
-#define GQUIC_SPECIAL_FRAME_STREAM_FIN 0x40 // FIN
-#define GQUIC_SPECIAL_FRAME_STREAM_DLEN 0x20 //stream length
-#define GQUIC_SPECIAL_FRAME_STREAM_OFFSET 0x1C //offset header field
-#define GQUIC_SPECIAL_FRAME_STREAM_ID 0x03 //offset header field
-
-#define GQUIC_REGULAR_FRAME_PADDING 0x00
-#define GQUIC_REGULAR_FRAME_RST_STREAM 0x01
-#define GQUIC_REGULAR_FRAME_CONNECTION_CLOSE 0x02
-#define GQUIC_REGULAR_FRAME_GOAWAY 0x03
-#define GQUIC_REGULAR_FRAME_WINDOW_UPDATE 0x04
-#define GQUIC_REGULAR_FRAME_BLOCKED 0x05
-#define GQUIC_REGULAR_FRAME_STOP_WAITING 0x06
#define GQUIC_REGULAR_FRAME_PING 0x07
+#define IQUIC_FRAME_PADDING 0x00
+#define IQUIC_FRAME_PING 0x01
+
+#define QUIC_HANDSHAKE_TYPE_CLIENTHELLO 0x01
//https://datatracker.ietf.org/doc/html/draft-ietf-quic-transport-27#section-12.4
//IQIIC Frame type (GQUIC_Q046 is iQUIC 17)
-#define IQUIC_FRAME_PADDING 0x00
-#define IQUIC_FRAME_PING 0x01
-#define IQUIC_FRAME_ACK_HEX02 0x02
-#define IQUIC_FRAME_ACK_HEX03 0x03
-#define IQUIC_FRAME_RESET_STREAM 0x04
-#define IQUIC_FRAME_STOP_SENDING 0x05
-#define IQUIC_FRAME_CRYPTO 0x06
-#define IQUIC_FRAME_NEW_TOKEN 0x07
-#define IQUIC_FRAME_STREAM_HEX08 0x08
-#define IQUIC_FRAME_STREAM_HEX09 0x09
-#define IQUIC_FRAME_STREAM_HEX0A 0x0A
-#define IQUIC_FRAME_STREAM_HEX0B 0x0B
-#define IQUIC_FRAME_STREAM_HEX0C 0x0C
-#define IQUIC_FRAME_STREAM_HEX0D 0x0D
-#define IQUIC_FRAME_STREAM_HEX0E 0x0E
-#define IQUIC_FRAME_STREAM_HEX0F 0x0F
-#define IQUIC_FRAME_MAX_DATA 0x10
-#define IQUIC_FRAME_MAX_STREAM_DATA 0x11
-#define IQUIC_FRAME_MAX_STREAMS_HEX12 0x12
-#define IQUIC_FRAME_MAX_STREAMS_HEX13 0x13
-#define IQUIC_FRAME_DATA_BLOCKED 0x14
-#define IQUIC_FRAME_STREAM_DATA_BLOCKED 0x15
-#define IQUIC_FRAME_STREAMS_BLOCKED_HEX16 0x16
-#define IQUIC_FRAME_STREAMS_BLOCKED_HEX17 0x17
-#define IQUIC_FRAME_NEW_CONNECTION_ID 0x18
-#define IQUIC_FRAME_RETIRE_CONNECTION_ID 0x19
-#define IQUIC_FRAME_PATH_CHALLENGE 0x1A
-#define IQUIC_FRAME_PATH_RESPONSE 0x1B
-#define IQUIC_FRAME_CONNECTION_CLOSE_HEX1C 0x1C
-#define IQUIC_FRAME_CONNECTION_CLOSE_HEX1D 0x1D
/**************************************************************************/
@@ -109,50 +67,10 @@
/**************************************************************************/
/* Tag */
/**************************************************************************/
-#define TAG_PAD 0x50414400
#define TAG_SNI 0x534E4900
#define TAG_VER 0x56455200
-#define TAG_CCS 0x43435300
#define TAG_UAID 0x55414944
-#define TAG_PDMD 0x50444d44
-#define TAG_STK 0x53544b00
-#define TAG_SNO 0x534E4F00
-#define TAG_PROF 0x50524F46
-#define TAG_SCFG 0x53434647
-#define TAG_RREJ 0x5252454A
-#define TAG_CRT 0x435254FF
-#define TAG_AEAD 0x41454144
-#define TAG_SCID 0x53434944
-#define TAG_PUBS 0x50554253
-#define TAG_KEXS 0x4B455853
-#define TAG_OBIT 0x4F424954
-#define TAG_EXPY 0x45585059
-#define TAG_NONC 0x4E4F4E43
-#define TAG_MSPC 0x4D535043
-#define TAG_TCID 0x54434944
-#define TAG_SRBF 0x53524246
-#define TAG_ICSL 0x4943534C
-#define TAG_SCLS 0x53434C53
-#define TAG_COPT 0x434F5054
-#define TAG_CCRT 0x43435254
-#define TAG_IRTT 0x49525454
-#define TAG_CFCW 0x43464357
-#define TAG_SFCW 0x53464357
-#define TAG_CETV 0x43455456
-#define TAG_XLCT 0x584C4354
-#define TAG_NONP 0x4E4F4E50
-#define TAG_CSCT 0x43534354
-#define TAG_CTIM 0x4354494D
-#define TAG_MIDS 0x4D494453
-#define TAG_FHOL 0x46484F4C
-#define TAG_STTL 0x5354544C
-#define TAG_SMHL 0x534D484C
-#define TAG_TBKP 0x54424B50
-
-/* Public Reset Tag */
-#define TAG_RNON 0x524E4F4E
-#define TAG_RSEQ 0x52534551
-#define TAG_CADR 0x43414452
+
#define EXTENSION_SERVER_NAME 0x0000
#define EXTENSION_SUPPORT_GROUP 0x000A
@@ -185,13 +103,13 @@
#define EXT_QUIC_PARAM_INIT_SRC_CONN_ID 0x0F
#define EXT_QUIC_PARAM_RETRY_SRC_CONN_ID 0x10
#define EXT_QUIC_PARAM_MAX_DATAGRAM_FRAME_SIZE 0x20
-#define EXT_QUIC_PARAM_INIT_RTT 0x7127
-#define EXT_QUIC_PARAM_GOOGLE_CONN_OPTIONS 0x7128
-#define EXT_QUIC_PARAM_USER_AGENT 0x7129 // 2021-10-20 deprecated
+#define EXT_QUIC_PARAM_INIT_RTT 0x3127
+#define EXT_QUIC_PARAM_GOOGLE_CONN_OPTIONS 0x3128
+#define EXT_QUIC_PARAM_USER_AGENT 0x3129 // 2021-10-20 deprecated
#define EXT_QUIC_PARAM_QUIC_VERSION 0x4752
//https://github.com/quicwg/base-drafts/wiki/QUIC-Versions
-enum _QUIC_VERSION
+enum QUIC_VERSION
{
QUIC_VERSION_UNKNOWN=0,
//NetApp
@@ -361,39 +279,17 @@ enum _QUIC_VERSION
IQUIC_VERSION_I032=0xFF000020
};
-struct _quic_context
+struct quic_context
{
- int is_quic;
- int is_decrypt;
- int cb_version;
- int link_state;
- int call_business;
+ unsigned char link_state;
+ unsigned char padding[7];
void *business_pme;
- struct _quic_info quic_info;
-};
-
-int quic_process(struct streaminfo *pstream, struct _quic_context* _context, int thread_seq, void* a_packet);
-
-int quic_init_stream(void **pme, int thread_seq); // **pme=(struct _quic_context* )
-void quic_release_stream(void **pme, int thread_seq);
-enum _QUIC_VERSION is_quic_protocol(struct streaminfo *pstream, struct _quic_context* _context, char *payload, int payload_len, int *used_len);
-
-
-struct _gquic_reset_public_header
-{
- unsigned char public_flags;
- unsigned long long connection_id;
- unsigned int tag;
-};
-
-struct _gquic_ack_frame_header
-{
- unsigned long long largest_acked;
- unsigned short largest_acked_delta_time;
- unsigned int tag;
+ struct quic_info quic_info;
};
-char quic_callPlugins(struct streaminfo *pstream, struct _quic_context *_context, void *buff, int buff_len, enum quic_interested_region region_mask, void *a_packet);
+int parse_quic_all_version(struct quic_info* quic_info, const char *payload, int payload_len, int thread_seq);
+unsigned char quic_analyze_entry(struct streaminfo *pstream, struct quic_context* context, int thread_seq, void* a_packet);
+unsigned char quic_call_business_plug(struct streaminfo *pstream, struct quic_context *context, void *buff, int buff_len, enum quic_interested_region region_mask, void *a_packet);
#endif
diff --git a/src/quic_version.cpp b/src/quic_version.cpp
index 7fc9eb0..fb83d08 100644
--- a/src/quic_version.cpp
+++ b/src/quic_version.cpp
@@ -1,8 +1,8 @@
#include <stdio.h>
#include <string.h>
-#include "gquic.h"
-#include "gquic_process.h"
+#include "quic.h"
+#include "quic_process.h"
int quic_version_int2string(unsigned int version, char *buff, int buff_len)
{
diff --git a/test/pcap/airport/quic_result.json b/test/pcap/airport/quic_result.json
index 49530b9..94b48cc 100644
--- a/test/pcap/airport/quic_result.json
+++ b/test/pcap/airport/quic_result.json
@@ -1,94 +1,94 @@
[{
+ "Tuple4": "10.56.160.76.44417>216.58.209.132.443",
+ "SNI": "www.google.com",
+ "UA": "com.google.android.googlequicksearchbox Cronet/96.0.4664.17",
+ "VERSION": "IETF QUIC RFC9000",
+ "name": "QUIC_RESULT_1"
+ }, {
"Tuple4": "10.56.160.76.47427>213.55.110.12.443",
- "VERSION": "Google QUIC 43",
"SNI": "r1---sn-xuj-5qqz.googlevideo.com",
"UA": "com.google.android.youtube Cronet/96.0.4655.4",
- "name": "QUIC_RESULT_1"
- }, {
- "Tuple4": "10.56.160.76.38866>197.156.74.141.443",
"VERSION": "Google QUIC 43",
- "SNI": "r2---sn-xuj-5qqs.googlevideo.com",
- "UA": "com.google.android.youtube Cronet/96.0.4655.4",
"name": "QUIC_RESULT_2"
}, {
- "Tuple4": "10.56.160.76.44417>216.58.209.132.443",
- "VERSION": "IETF QUIC RFC9000",
- "SNI": "www.google.com",
- "UA": "com.google.android.googlequicksearchbox Cronet/96.0.4664.17",
- "name": "QUIC_RESULT_3"
- }, {
"Tuple4": "10.56.160.76.39996>142.250.185.33.443",
- "VERSION": "IETF QUIC RFC9000",
"SNI": "yt3.ggpht.com",
"UA": "com.google.android.youtube Cronet/96.0.4655.4",
- "name": "QUIC_RESULT_4"
+ "VERSION": "IETF QUIC RFC9000",
+ "name": "QUIC_RESULT_3"
}, {
"Tuple4": "10.56.160.76.48527>216.58.209.130.443",
- "VERSION": "IETF QUIC RFC9000",
"SNI": "www.googleadservices.com",
"UA": "com.google.android.youtube Cronet/96.0.4655.4",
- "name": "QUIC_RESULT_5"
+ "VERSION": "IETF QUIC RFC9000",
+ "name": "QUIC_RESULT_4"
}, {
"Tuple4": "10.56.160.76.43569>197.156.74.146.443",
- "VERSION": "Google QUIC 43",
"SNI": "r7---sn-xuj-5qqs.googlevideo.com",
"UA": "com.google.android.youtube Cronet/96.0.4655.4",
- "name": "QUIC_RESULT_6"
+ "VERSION": "Google QUIC 43",
+ "name": "QUIC_RESULT_5"
}, {
"Tuple4": "10.56.160.76.52114>197.156.74.147.443",
- "VERSION": "Google QUIC 43",
"SNI": "r8---sn-xuj-5qqs.googlevideo.com",
"UA": "com.google.android.youtube Cronet/96.0.4655.4",
- "name": "QUIC_RESULT_7"
+ "VERSION": "Google QUIC 43",
+ "name": "QUIC_RESULT_6"
}, {
"Tuple4": "10.56.160.76.59023>213.55.110.13.443",
- "VERSION": "Google QUIC 43",
"SNI": "r2---sn-xuj-5qqz.googlevideo.com",
"UA": "com.google.android.youtube Cronet/96.0.4655.4",
- "name": "QUIC_RESULT_8"
+ "VERSION": "Google QUIC 43",
+ "name": "QUIC_RESULT_7"
}, {
"Tuple4": "10.56.160.76.46224>197.156.74.140.443",
- "VERSION": "Google QUIC 43",
"SNI": "r1---sn-xuj-5qqs.googlevideo.com",
"UA": "com.google.android.youtube Cronet/96.0.4655.4",
- "name": "QUIC_RESULT_9"
+ "VERSION": "Google QUIC 43",
+ "name": "QUIC_RESULT_8"
}, {
"Tuple4": "10.56.160.76.54334>197.156.74.145.443",
- "VERSION": "Google QUIC 43",
"SNI": "r6---sn-xuj-5qqs.googlevideo.com",
"UA": "com.google.android.youtube Cronet/96.0.4655.4",
- "name": "QUIC_RESULT_10"
+ "VERSION": "Google QUIC 43",
+ "name": "QUIC_RESULT_9"
}, {
"Tuple4": "10.56.160.76.41069>142.250.180.42.443",
- "VERSION": "IETF QUIC RFC9000",
"SNI": "youtubei.googleapis.com",
"UA": "com.google.android.youtube Cronet/96.0.4655.4",
- "name": "QUIC_RESULT_11"
+ "VERSION": "IETF QUIC RFC9000",
+ "name": "QUIC_RESULT_10"
}, {
"Tuple4": "10.56.160.76.48756>213.55.110.14.443",
- "VERSION": "Google QUIC 43",
"SNI": "r3---sn-xuj-5qqz.googlevideo.com",
"UA": "com.google.android.youtube Cronet/96.0.4655.4",
- "name": "QUIC_RESULT_12"
+ "VERSION": "Google QUIC 43",
+ "name": "QUIC_RESULT_11"
}, {
"Tuple4": "10.56.160.76.51113>142.250.180.54.443",
- "VERSION": "IETF QUIC RFC9000",
"SNI": "i.ytimg.com",
"UA": "com.google.android.youtube Cronet/96.0.4655.4",
+ "VERSION": "IETF QUIC RFC9000",
+ "name": "QUIC_RESULT_12"
+ }, {
+ "Tuple4": "10.56.160.76.38866>197.156.74.141.443",
+ "SNI": "r2---sn-xuj-5qqs.googlevideo.com",
+ "UA": "com.google.android.youtube Cronet/96.0.4655.4",
+ "VERSION": "Google QUIC 43",
"name": "QUIC_RESULT_13"
}, {
"Tuple4": "10.56.160.76.46131>196.188.31.18.443",
- "VERSION": "Facebook mvfst 02",
"SNI": "video.fadd1-1.fna.fbcdn.net",
+ "VERSION": "Facebook mvfst 02",
"name": "QUIC_RESULT_14"
}, {
"Tuple4": "10.56.160.76.40267>102.132.96.18.443",
- "VERSION": "Facebook mvfst 02",
"SNI": "graph.facebook.com",
+ "VERSION": "Facebook mvfst 02",
"name": "QUIC_RESULT_15"
}, {
"Tuple4": "10.56.160.76.46761>196.188.31.17.443",
- "VERSION": "Facebook mvfst 02",
"SNI": "scontent.fadd1-1.fna.fbcdn.net",
+ "VERSION": "Facebook mvfst 02",
"name": "QUIC_RESULT_16"
}]
diff --git a/test/pcap/gquic/43/quic_result.json b/test/pcap/gquic/43/quic_result.json
index 278622f..d8b0d5a 100644
--- a/test/pcap/gquic/43/quic_result.json
+++ b/test/pcap/gquic/43/quic_result.json
@@ -1,15 +1,15 @@
[{
- "Tuple4": "192.168.50.26.55209>34.102.215.99.443",
+ "Tuple4": "112.43.145.231.18699>112.46.25.216.443",
+ "SNI": "client.weixin.qq.com",
"VERSION": "Google QUIC 43",
"name": "QUIC_RESULT_1"
}, {
- "Tuple4": "192.168.50.26.60851>34.102.215.99.443",
+ "Tuple4": "192.168.50.26.55209>34.102.215.99.443",
"VERSION": "Google QUIC 43",
"name": "QUIC_RESULT_2"
}, {
- "Tuple4": "112.43.145.231.18699>112.46.25.216.443",
+ "Tuple4": "192.168.50.26.60851>34.102.215.99.443",
"VERSION": "Google QUIC 43",
- "SNI": "client.weixin.qq.com",
"name": "QUIC_RESULT_3"
}, {
"Tuple4": "192.168.50.26.63533>34.102.215.99.443",
diff --git a/test/pcap/gquic/44/quic_result.json b/test/pcap/gquic/44/quic_result.json
index c5db421..1f08140 100644
--- a/test/pcap/gquic/44/quic_result.json
+++ b/test/pcap/gquic/44/quic_result.json
@@ -57,8 +57,6 @@
}, {
"Tuple4": "85.117.117.190.11567>64.233.165.94.443",
"VERSION": "Google QUIC 44",
- "SNI": "www.google.kz",
- "UA": "dev Chrome/73.0.3664.3 Windows NT 6.3; Win64; x64",
"name": "QUIC_RESULT_10"
}, {
"Tuple4": "85.117.117.190.48098>173.194.221.95.443",
@@ -69,8 +67,6 @@
}, {
"Tuple4": "85.117.119.57.4009>64.233.162.155.443",
"VERSION": "Google QUIC 44",
- "SNI": "stats.g.doubleclick.net",
- "UA": "dev Chrome/73.0.3664.3 Windows NT 6.1; Win64; x64",
"name": "QUIC_RESULT_12"
}, {
"Tuple4": "85.117.126.11.11719>64.233.165.138.443",
diff --git a/test/pcap/iquic/29/quic_result.json b/test/pcap/iquic/29/quic_result.json
index e6bd13b..dfc757f 100644
--- a/test/pcap/iquic/29/quic_result.json
+++ b/test/pcap/iquic/29/quic_result.json
@@ -1,7 +1,8 @@
[{
"Tuple4": "192.168.50.29.61891>31.13.77.35.443",
- "VERSION": "IETF QUIC 29",
"SNI": "www.facebook.com",
+ "UA": "Chrome/86.0.4240.183 Windows NT 10.0; Win64; x64",
+ "VERSION": "IETF QUIC 29",
"name": "QUIC_RESULT_1"
}, {
"Tuple4": "223.104.233.102.13650>203.208.40.98.443",
@@ -9,9 +10,8 @@
"name": "QUIC_RESULT_2"
}, {
"Tuple4": "192.168.50.33.57220>114.250.70.38.443",
- "VERSION": "IETF QUIC 29",
"SNI": "securepubads.g.doubleclick.net",
"UA": "Chrome/90.0.4430.72 Windows NT 10.0; Win64; x64",
+ "VERSION": "IETF QUIC 29",
"name": "QUIC_RESULT_3"
}]
-
diff --git a/test/pcap/tquic/quic_result.json b/test/pcap/tquic/quic_result.json
index 2c0f128..3d2d43e 100644
--- a/test/pcap/tquic/quic_result.json
+++ b/test/pcap/tquic/quic_result.json
@@ -1,21 +1,25 @@
[{
- "Tuple4": "195.12.120.14.41803>173.194.222.101.443",
- "VERSION": "Google QUIC with TLS 51",
- "SNI": "clients4.google.com",
- "name": "QUIC_RESULT_1"
- }, {
- "Tuple4": "195.12.120.14.39526>64.233.165.113.443",
- "VERSION": "Google QUIC with TLS 51",
- "SNI": "m.youtube.com",
- "name": "QUIC_RESULT_2"
- }, {
- "Tuple4": "195.12.120.14.41747>173.194.222.138.443",
- "VERSION": "Google QUIC with TLS 51",
- "SNI": "clients4.google.com",
- "name": "QUIC_RESULT_3"
- }, {
- "Tuple4": "195.12.120.14.59012>173.194.222.138.443",
- "VERSION": "Google QUIC with TLS 51",
- "SNI": "clients4.google.com",
- "name": "QUIC_RESULT_4"
+ "Tuple4": "195.12.120.14.41803>173.194.222.101.443",
+ "SNI": "clients4.google.com",
+ "UA": "Chrome/87.0.4280.101 Android 9; ANE-LX1",
+ "VERSION": "Google QUIC with TLS 51",
+ "name": "QUIC_RESULT_1"
+ }, {
+ "Tuple4": "195.12.120.14.39526>64.233.165.113.443",
+ "SNI": "m.youtube.com",
+ "UA": "Chrome/87.0.4280.101 Android 9; ANE-LX1",
+ "VERSION": "Google QUIC with TLS 51",
+ "name": "QUIC_RESULT_2"
+ }, {
+ "Tuple4": "195.12.120.14.41747>173.194.222.138.443",
+ "SNI": "clients4.google.com",
+ "UA": "Chrome/87.0.4280.101 Android 9; ANE-LX1",
+ "VERSION": "Google QUIC with TLS 51",
+ "name": "QUIC_RESULT_3"
+ }, {
+ "Tuple4": "195.12.120.14.59012>173.194.222.138.443",
+ "SNI": "clients4.google.com",
+ "UA": "Chrome/87.0.4280.101 Android 9; ANE-LX1",
+ "VERSION": "Google QUIC with TLS 51",
+ "name": "QUIC_RESULT_4"
}]
diff --git a/test/quic_test_plug.cpp b/test/quic_test_plug.cpp
index a8b48c7..ab89087 100644
--- a/test/quic_test_plug.cpp
+++ b/test/quic_test_plug.cpp
@@ -3,16 +3,14 @@
* create time:2021-8-21
*
*/
-
-
-
+
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <assert.h>
#include "cJSON.h"
-#include "gquic.h"
+#include "quic.h"
#include "MESA_prof_load.h"
#include <MESA/stream.h>
@@ -26,7 +24,7 @@ extern "C" unsigned char QUIC_TEST_PLUG_ENTRY(stSessionInfo *session_info, void
assert(NULL != session_info || pme != NULL);
cJSON *ctx = (cJSON *)*pme;
- struct _quic_info *quic_info=NULL;
+ struct quic_info *quic_info=NULL;
char version_str[128]={0};
unsigned int version = 0;
@@ -47,9 +45,22 @@ extern "C" unsigned char QUIC_TEST_PLUG_ENTRY(stSessionInfo *session_info, void
{
break;
}
- quic_info = (struct _quic_info *)session_info->app_info;
- cJSON_AddStringToObject(ctx, "SNI", (char *)(quic_info->client_hello->ext_tags[quic_info->client_hello->sni_idx].value));
- cJSON_AddStringToObject(ctx, "UA", (char *)(quic_info->client_hello->ext_tags[quic_info->client_hello->ua_idx].value));
+ quic_info = (struct quic_info *)session_info->app_info;
+ if(quic_info->client_hello==NULL)
+ {
+ break;
+ }
+ if(quic_info->client_hello->sni!=NULL)
+ {
+ cJSON_AddStringToObject(ctx, "SNI", (char *)(quic_info->client_hello->sni));
+ }
+ if(quic_info->client_hello->user_agent!=NULL)
+ {
+ cJSON_AddStringToObject(ctx, "UA", (char *)(quic_info->client_hello->user_agent));
+ }
+
+ quic_version_int2string((unsigned int)(quic_info->quic_version), version_str, sizeof(version_str));
+ cJSON_AddStringToObject(ctx, "VERSION", version_str);
break;
case QUIC_USEING_VERSION:
version = *(unsigned int *)(session_info->buf);
@@ -86,7 +97,7 @@ extern "C" int QUIC_TEST_PLUG_INIT()
extern "C" void QUIC_TEST_PLUG_DESTROY(void)
{
return ;
-}/*CHAR_DESTRORY*/
+}