This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
mesa-platform-gquic/src/gquic_process.c

901 lines
23 KiB
C
Raw Normal View History

2020-05-12 12:18:02 +08:00
/*
* gquic_process.c
*
* Created on: 2019<EFBFBD><EFBFBD>4<EFBFBD><EFBFBD>2<EFBFBD><EFBFBD>
* Author: root
*/
#include "gquic_process.h"
#include "quic_analysis.h"
#include "quic_callback.h"
#include <stdbool.h>
#include <stdio.h>
#include<assert.h>
2020-05-22 18:44:00 +08:00
#include <MESA/MESA_handle_logger.h>
2020-05-12 12:18:02 +08:00
#define C2S 0x01
#define S2C 0x02
#define GQUIC_HANDSHAKE_LEN 12+1+1+4+4
#define DIVERSIFICATION_NONCE_LEN 32
2020-05-22 18:44:00 +08:00
extern struct quic_param_t g_quic_param;
enum gquic_type
{
GQUIC=1,
UNKNOWN_QUIC_TYPE
2020-05-12 12:18:02 +08:00
};
2020-05-22 18:44:00 +08:00
enum gquic_handshake_type
{
QUIC_Crypto=1,
UNKNOWN_HANDSHAKE_TYPE
2020-05-12 12:18:02 +08:00
};
2020-05-22 18:44:00 +08:00
int get_quic_tlv(char *start_pos, quic_tlv_t *tlv, int len, int type, int thread_seq)
{
if(tlv->ptr_value==NULL && len>0)
{
tlv->ptr_value=(char *)dictator_malloc(thread_seq, len);
memset(tlv->ptr_value, 0, len);
tlv->length=len;
tlv->type=type;
memcpy(tlv->ptr_value, start_pos, tlv->length);
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
return 0;
}
UINT32 get_stream_id(struct streaminfo *pstream, char* quic_data, UINT8 frame_type, UINT32 *skip_len)
{
UINT16 data_length=0;
UINT32 stream_id=0;
UINT8 stream_id_len=0;
UINT8 len_data=0,len_stream=0, len_offset=0;
len_stream = read_stream_len(frame_type);
switch(len_stream)
{
case 1:
stream_id=quic_data[*skip_len];
break;
case 2:
stream_id=a_pletoh16((void *)quic_data, *skip_len);
break;
case 3:
stream_id=a_pletoh24((void *)quic_data, *skip_len);
break;
default:
stream_id=a_pletoh32((void *)quic_data, *skip_len);
break;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
*skip_len+=len_stream; // stream ID length
2020-05-12 12:18:02 +08:00
2020-05-22 18:44:00 +08:00
if(frame_type&STREAM_D)
{
data_length=ntohs(a_pletoh16((void *)quic_data, *skip_len));
*skip_len+=2; //data length
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
len_offset=read_offset_len(frame_type);
*skip_len+=len_offset;
2020-05-12 12:18:02 +08:00
2020-05-22 18:44:00 +08:00
MESA_handle_runtime_log(g_quic_param.logger,
RLOG_LV_DEBUG,
"QUIC_FRAME",
"stream_id: %u data length: %u offset length: %u addr: %s",
stream_id,
data_length,
len_offset,
printaddr(&pstream->addr, pstream->threadnum));
return stream_id;
}
UINT32 get_packet_number(char* g_data_t, UINT32 offset, UINT8 pkn_len)
{
switch(pkn_len)
{
case 1:
return g_data_t[offset];
break;
case 2:
return ntohs(a_pletoh16((void *)g_data_t, offset));
break;
case 4:
return a_pletoh32((void *)g_data_t, offset);
break;
default:
return a_pletoh48((void *)g_data_t, offset);
break;
}
return 0;
}
enum GQUIC_VERSION is_gquic_protocol(struct streaminfo *pstream, char *payload, uint32_t payload_len, uint8_t *pub_flags, uint32_t *version, uint32_t *skip_len)
{
uint32_t is_q064=0;
uint64_t connection_id = 0;
int connection_id_len = 0;
enum GQUIC_VERSION quic_version=GQUIC_UNKNOWN;
if(a_canRead(5, payload_len, *skip_len))
{
*skip_len+=1;
strncpy((char*)&is_q064, payload+(*skip_len), 4);
if(ntohl(is_q064)==VER_Q046)
{
*skip_len += 2;
*version=(payload[*skip_len]&0x0f)*10 + (payload[*skip_len+1]&0x0f);
*skip_len += 2;
MESA_handle_runtime_log(g_quic_param.logger,
RLOG_LV_DEBUG,
"QUIC_PUB_FLAGS",
"version: Q0%u addr: %s",
*version,
printaddr(&pstream->addr, pstream->threadnum));
return GQUIC_Q046;
}
*skip_len-=1;
}
*pub_flags=payload[*skip_len]; // public flags
*skip_len+=1;
if(*pub_flags>PACKET_PUBLIC_FLAGS_MAX)
{
return quic_version;
}
connection_id_len=read_conn_id_len(*pub_flags);
connection_id=(connection_id_len==0) ? 0 : (a_pntoh64((void *)payload, *skip_len));
*skip_len+=connection_id_len; // CID length
if(payload[*skip_len]==PUBLIC_FLAG_VER_FST_BYTE && *pub_flags&PUBLIC_FLAG_VER)
{
*skip_len += 2;
*version=(payload[*skip_len]&0x0f)*10 + (payload[*skip_len+1]&0x0f);
*skip_len += 2;
quic_version=GQUIC_OTHERS;
}
if(*pub_flags==PUBLIC_FLAG_NONCE)
{
*skip_len+=32; //diversification nonce
}
UINT8 pkt_seq_len=read_seq_num_len(*pub_flags);
UINT32 pkt_seq=get_packet_number(payload, *skip_len, pkt_seq_len);
*skip_len+=pkt_seq_len; // skip pkt_num
if(*pub_flags&PUBLIC_FLAG_VER)
{
//message authentication hash
*skip_len+=MSG_AUTH_HASH_LEN;
if(*version>0 && *version<34)
{
*skip_len+=1; //private flags
}
}
MESA_handle_runtime_log(g_quic_param.logger,
RLOG_LV_DEBUG,
"QUIC_IDETIFY",
"pub_flags: 0X%02X connection_id: %llu version: Q%03u packet number: %u dir(1: C2S;2: S2C): %d addr: %s",
*pub_flags,
connection_id,
*version,
pkt_seq,
pstream->curdir,
printaddr(&pstream->addr, pstream->threadnum));
return quic_version;
}
void gquic_proc_tag(struct streaminfo *pstream, struct quic_stream *a_quic_stream, UINT16 tag_num, UINT8 direction, void* a_packet, char * quic_data, UINT32 quic_data_len, UINT32 *used_len)
{
UCHAR return_val;
UINT32 tag_type;
UINT32 total_tag_len=0, tag_len=0;
UINT32 tag_value_start=tag_num*4*2+(*used_len); // skip length of type and offset, type(offset)=szieof(int)
UINT32 tag_offset_end=0, pre_tag_offset_end=0;
int tag_type_len=4, tag_offset_len=4,num=0;
enum quic_interested_region region_mask=QUIC_INTEREST_KEY_MASK;
while(tag_num > 0 && a_canRead(tag_type_len+tag_offset_len, quic_data_len, *used_len))
{
tag_type=a_pntoh32(quic_data, *used_len);
*used_len+=4;
tag_offset_end=a_pletoh32(quic_data, *used_len);
*used_len+=4;
tag_len=tag_offset_end-pre_tag_offset_end;
if(tag_len<0 || (tag_offset_end>=quic_data_len) || (tag_len>quic_data_len-tag_value_start))
{
return ;
}
switch(tag_type)
{
case TAG_PAD:
2020-05-12 12:18:02 +08:00
break;
2020-05-22 18:44:00 +08:00
case TAG_CCS: //common_cert
region_mask=QUIC_COMM_CERT_MASK;
get_quic_tlv(quic_data+tag_value_start, &a_quic_stream->common_cert, tag_len, tag_type, pstream->threadnum);
2020-05-12 12:18:02 +08:00
break;
2020-05-22 18:44:00 +08:00
case TAG_CCRT: //cached_cert
region_mask=QUIC_CACHED_CERT_MASK;
get_quic_tlv(quic_data+tag_value_start, &a_quic_stream->cached_cert, tag_len, tag_type, pstream->threadnum);
2020-05-12 12:18:02 +08:00
break;
2020-05-22 18:44:00 +08:00
case TAG_CRT: //cert_chain ????? length need change
if(a_quic_stream->cert_chain.length==0)
{
//tag_value_start += a_quic_stream->cert_chain.length;
tag_len=(tag_len>(quic_data_len-tag_value_start+1) ? (quic_data_len-tag_value_start+1) : tag_len);
get_quic_tlv(quic_data+tag_value_start, &a_quic_stream->cached_cert, tag_len, tag_type, pstream->threadnum);
region_mask=QUIC_CERT_CHAIN_MASK;
}
2020-05-12 12:18:02 +08:00
break;
2020-05-22 18:44:00 +08:00
case TAG_SNI:
if(a_quic_stream->st_client_hello.server_name_len==0)
{
a_quic_stream->st_client_hello.server_name_len=(tag_len>SERVER_NAME_LEN ? SERVER_NAME_LEN : tag_len);
memcpy(a_quic_stream->st_client_hello.server_name, quic_data + tag_value_start, tag_len);
MESA_handle_runtime_log(g_quic_param.logger,
RLOG_LV_DEBUG,
"QUIC_SNI",
"SNI: %s addr: %s",
a_quic_stream->st_client_hello.server_name,
printaddr(&pstream->addr, pstream->threadnum));
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
break;
case TAG_UAID:
if(a_quic_stream->st_client_hello.user_agent_len==0)
{
a_quic_stream->st_client_hello.user_agent_len=(tag_len>USER_AGENT_LEN ? USER_AGENT_LEN : tag_len);
memcpy(a_quic_stream->st_client_hello.user_agent, quic_data + tag_value_start, a_quic_stream->st_client_hello.user_agent_len);
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
break;
default:
if(direction == 0x01 && num < a_quic_stream->st_client_hello.ext_tag_num)
{
a_quic_stream->st_client_hello.ext_tags[num]=(quic_tlv_t *)dictator_malloc(pstream->threadnum, sizeof(quic_tlv_t));
get_quic_tlv(quic_data+tag_value_start, a_quic_stream->st_client_hello.ext_tags[num], (tag_len>MAX_TAG_VALUE_LEN-1 ? MAX_TAG_VALUE_LEN-1 : tag_len), tag_type, pstream->threadnum);
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
else if(num < a_quic_stream->st_server_hello.ext_tag_num)
{
a_quic_stream->st_server_hello.ext_tags[num]=(quic_tlv_t *)dictator_malloc(pstream->threadnum, sizeof(quic_tlv_t));
get_quic_tlv(quic_data+tag_value_start, a_quic_stream->st_server_hello.ext_tags[num], (tag_len>MAX_TAG_VALUE_LEN-1 ? MAX_TAG_VALUE_LEN-1 : tag_len), tag_type, pstream->threadnum);
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
num++;
break;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
tag_num--;
tag_value_start+=tag_len;
total_tag_len+=tag_len;
pre_tag_offset_end=tag_offset_end;
return_val=quic_callPlugins(a_quic_stream, pstream, region_mask, pstream->threadnum, a_packet);
region_mask=QUIC_INTEREST_KEY_MASK;
}
*used_len += total_tag_len;
return;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
int gquic_frame_type_ack(struct quic_stream* a_quic_stream, char * quic_data, UINT32 quic_data_len, UINT8 frame_type, UINT32 *used_len)
{
UINT8 num_timestamp, num_ranges, num_revived, num_blocks;
UINT32 len_largest_observed=0, len_missing_packet=0;
*used_len+=1;
len_largest_observed = read_largest_observed_len(frame_type);
len_missing_packet = read_missing_packet_len(frame_type);
//No longer Entropy after Q034
if(a_quic_stream->version < 34)
{
//Send Entropy
*used_len += 1;
*used_len += len_largest_observed;
*used_len += 2; //ack delay time
strncpy((char*)&num_timestamp, quic_data+*used_len,1);
*used_len += 1;
if(num_timestamp > 0)
{
*used_len += 1;
*used_len += 4;
*used_len += (num_timestamp - 1)*(1+2);
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
if(frame_type & ACK_N)
{
strncpy((char*)&num_ranges, quic_data+*used_len,1);
*used_len += 1;
*used_len += num_ranges*(len_missing_packet+1);
strncpy((char*)&num_revived, quic_data+*used_len,1);
*used_len += 1;
//Num Revived x Length Largest Observed
*used_len += num_revived*len_largest_observed;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
}
else
{
*used_len += len_largest_observed; //Largest Acked
*used_len += 2; //Largest Acked Delta Time
if(frame_type & ACK_N) //Ack Block
{
strncpy((char*)&num_blocks, quic_data+*used_len,1);
*used_len += 1;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
*used_len += len_missing_packet; //First Ack Block Length
if(num_blocks)
{
//Gap to next block
*used_len += 1;
num_blocks -= 1;
*used_len += (num_blocks - 1)*len_missing_packet;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
strncpy((char*)&num_timestamp, quic_data+*used_len,1); //Timestamp
*used_len += 1;
if(num_timestamp > 0)
{
*used_len += 1; //Delta Largest Acked
*used_len += 4; //Time Since Largest Acked
//Num Timestamp x (Delta Largest Acked + Time Since Previous Timestamp)
*used_len += (num_timestamp - 1)*(1+2);
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
}
return 0;
}
// return value: Have no meaning, only numerical value
int gquic_frame_type_control(struct quic_stream* a_quic_stream, char * quic_data, UINT32 quic_data_len, UINT8 frame_type, uint32_t pkt_num_len, UINT32 *used_len)
{
UINT16 len_reason;
*used_len+=1;
switch(frame_type)
{
case RST_STREAM:
*used_len +=4; //stream id
*used_len+=8; //Byte Offset
*used_len+=4; //Error Code
a_quic_stream->fin_flag=QUIC_TRUE;
break;
case CONNECTION_CLOSE:
len_reason = 0;
*used_len += 4; //Error Code
len_reason = a_pntoh16(quic_data, *used_len); //Reason Phrase Length
*used_len += 2;
//Reason Phrase,If length remaining == len_reason, it is Connection Close
if(get_remaining_len(quic_data_len, *used_len) == len_reason)
{
return QUIC_DATA;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
a_quic_stream->fin_flag=(a_quic_stream->fin_flag==QUIC_FALSE) ? QUIC_HALF_CLOSE : QUIC_TRUE;
break;
case GOAWAY:
len_reason = 0;
*used_len += 4; //Error Code
*used_len += 4; //Last Good Stream ID
len_reason = a_pntoh16(quic_data, *used_len); //Reason Phrase Length
*used_len += 2;
*used_len += len_reason; //Reason Phrase
break;
case WINDOW_UPDATE:
*used_len += 4; //Stream ID
*used_len += 8; //Byte Offset
break;
case BLOCKED:
*used_len += 4; //Stream ID
break;
case STOP_WAITING:
//No longer Entropy after Q034
if(a_quic_stream->version < 34)
{
*used_len += 1; // Send Entropy
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
//Least Unacked Delta
*used_len += pkt_num_len;
break;
case PING: //No Payload
case PADDING:
default:
return QUIC_FALSE;
break;
}
return QUIC_TRUE;
}
int gquic_frame_type_stream(struct streaminfo *pstream, struct quic_stream* a_quic_stream, char *quic_data, UINT32 quic_data_len, UINT8 frame_type, UINT32 *used_len, void* a_packet)
{
UINT8 return_val;
UINT16 tag_num = 0;
UINT32 stream_id, message_tag;
if(frame_type&STREAM_F)
{
a_quic_stream->fin_flag=QUIC_TRUE;
}
stream_id=get_stream_id(pstream, quic_data, frame_type, used_len);
if(stream_id==1) //handshake
{
message_tag = a_pntoh32((void *)quic_data, *used_len);
*used_len += 4;
tag_num = a_pletoh16(quic_data, *used_len);
*used_len += 2; //tag_num
*used_len += 2; //padding
switch(message_tag)
{
case CHLO: //MTAG_CHLO;
if(a_quic_stream->st_client_hello.ext_tags==NULL)
{
a_quic_stream->st_client_hello.ext_tags=(quic_tlv_t **)dictator_malloc(pstream->threadnum, tag_num*sizeof(quic_tlv_t*));
a_quic_stream->st_client_hello.ext_tag_num = tag_num;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
else
{
if(a_quic_stream->st_server_hello.ext_tag_num && tag_num>a_quic_stream->st_client_hello.ext_tag_num)
{
quic_release_exts(pstream->threadnum, a_quic_stream->st_client_hello.ext_tags, a_quic_stream->st_client_hello.ext_tag_num);
a_quic_stream->st_client_hello.ext_tags=(quic_tlv_t **)dictator_malloc(pstream->threadnum, tag_num*sizeof(quic_tlv_t*));
a_quic_stream->st_client_hello.ext_tag_num = tag_num;
}
else
{
return -1;
}
}
gquic_proc_tag(pstream, a_quic_stream, tag_num, C2S, a_packet, quic_data, quic_data_len, used_len);
if(a_quic_stream->st_client_hello.server_name_len>0 || a_quic_stream->st_client_hello.user_agent_len>0)
{
quic_callPlugins(a_quic_stream, pstream, QUIC_CLIENT_HELLO_MASK, pstream->threadnum, a_packet);
}
break;
case SHLO: //MTAG_SHLO;
if(a_quic_stream->st_server_hello.ext_tags==NULL)
{
return -2;
}
a_quic_stream->st_server_hello.ext_tags=(quic_tlv_t **)dictator_malloc(pstream->threadnum, tag_num*sizeof(quic_tlv_t*));
a_quic_stream->st_server_hello.ext_tag_num=tag_num;
gquic_proc_tag(pstream, a_quic_stream, tag_num, S2C, a_packet, quic_data, quic_data_len, used_len);
if(a_quic_stream->st_server_hello.ext_tags != NULL)
{
quic_callPlugins(a_quic_stream, pstream, QUIC_SERVER_HELLO_MASK, pstream->threadnum, a_packet);
}
break;
case REJ: //MTAG_REJ;
if(a_quic_stream->st_server_hello.ext_tags!=NULL)
{
return -3;
}
a_quic_stream->st_server_hello.ext_tags=(quic_tlv_t **)dictator_malloc(pstream->threadnum, tag_num*sizeof(quic_tlv_t*));
a_quic_stream->st_server_hello.ext_tag_num=tag_num;
gquic_proc_tag(pstream, a_quic_stream, tag_num, S2C, a_packet, quic_data, quic_data_len, used_len);
if(a_quic_stream->st_server_hello.ext_tags != NULL)
{
quic_callPlugins(a_quic_stream, pstream, QUIC_SERVER_HELLO_MASK, pstream->threadnum, a_packet);
}
break;
default:
break;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
}
return 0;
}
2020-05-12 12:18:02 +08:00
2020-05-22 18:44:00 +08:00
//frame type->stream->offset->data length
void gquic_proc_unencrypt(struct streaminfo *pstream, struct quic_stream* a_quic_stream, uint32_t pkt_num_len, void* a_packet, char * quic_data, UINT32 quic_data_len, UINT32 *used_len)
{
UINT8 frame_type;
UINT32 ret=0;
while(*used_len<quic_data_len)
{
a_readUInt8(&frame_type, quic_data, quic_data_len, used_len);
if(!(frame_type&FRAM_SPECIAL))
{
ret=gquic_frame_type_control(a_quic_stream, quic_data, quic_data_len, frame_type, pkt_num_len, used_len);
}
else
{
//special packet
if(frame_type&STREAM)
{
ret=gquic_frame_type_stream(pstream, a_quic_stream, quic_data, quic_data_len, frame_type, used_len, a_packet);
}
else if(frame_type&ACK)
{
gquic_frame_type_ack(a_quic_stream, quic_data, quic_data_len, frame_type, used_len);
}
else
{
*used_len+=1;
ret=QUIC_FALSE;
2020-05-12 12:18:02 +08:00
}
}
2020-05-22 18:44:00 +08:00
if(ret!=QUIC_TRUE)
{
return ;
2020-05-12 12:18:02 +08:00
}
}
return;
}
2020-05-22 18:44:00 +08:00
//QUIC_DATA:is quic data pcap;QUIC_TRUE:is handshake pcap;QUIC_RETURN_DROPME:not quic protocol;
UCHAR is_handshake_pkt(struct quic_stream* a_quic_stream,uint32_t pkt_num_len, char * quic_data, UINT32 quic_data_len, UINT32 *used_len)
{
int ret=0;
UINT8 frame_type=0;
UINT32 message_tag;
while(*used_len < quic_data_len)
{
frame_type = quic_data[*used_len];
if(!(frame_type & FRAM_SPECIAL))
{
ret=gquic_frame_type_control(a_quic_stream, quic_data, quic_data_len, frame_type, pkt_num_len, used_len);
a_quic_stream->fin_flag=QUIC_FALSE; // is_handshake_pkt don't identify QUIC; but function set QUIC_TRUE
if(ret!=QUIC_TRUE)
{
return ret;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
}
else
{
if(frame_type&STREAM)
{
if(frame_type&STREAM_D)
{
*used_len+=2;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
*used_len+=1;
*used_len+=read_stream_len(frame_type);
*used_len+=read_offset_len(frame_type);
if((quic_data_len-*used_len)<=4)
{
return QUIC_FALSE;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
strncpy((char*)&message_tag, quic_data+*used_len, 4);
if(ntohl(message_tag)==CHLO || ntohl(message_tag)==SHLO || ntohl(message_tag)==REJ)
{
return QUIC_TRUE;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
}
else if(frame_type&ACK)
{
gquic_frame_type_ack(a_quic_stream, quic_data, quic_data_len, frame_type, used_len);
}
else
{
*used_len +=1;
return QUIC_FALSE;
2020-05-12 12:18:02 +08:00
}
}
}
2020-05-22 18:44:00 +08:00
return QUIC_FALSE;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
UINT8 parse_gquic_Q046(struct streaminfo *pstream, void* a_packet, char * payload, uint32_t payload_len, uint32_t *used_len, struct quic_stream* a_quic_stream, uint8_t pub_flags)
{
uint8_t frame_type;
uint16_t tag_num=0;
uint32_t stream_id, message_tag;
if(!a_canRead(25, payload_len, *used_len))
{
2020-05-12 12:18:02 +08:00
return QUIC_RETURN_DROPME;
}
2020-05-22 18:44:00 +08:00
*used_len += 25;
while(*used_len < payload_len)
{
a_readUInt8(&frame_type, payload, payload_len, used_len);
if(frame_type & STREAM)
{
stream_id=get_stream_id(pstream, payload, frame_type, used_len);
if(stream_id==1)
{
message_tag = a_pntoh32((void *)payload, *used_len);
*used_len += 4;
tag_num = a_pletoh16(payload, *used_len);
*used_len += 2; //tag_num
*used_len += 2; //padding
switch(message_tag)
{
case CHLO: //MTAG_CHLO;
if(a_quic_stream->st_client_hello.ext_tags==NULL && tag_num>0)
{
a_quic_stream->st_client_hello.ext_tags=(quic_tlv_t **)dictator_malloc(pstream->threadnum, tag_num*sizeof(quic_tlv_t*));
a_quic_stream->st_client_hello.ext_tag_num = tag_num;
}
gquic_proc_tag(pstream, a_quic_stream, tag_num, C2S, a_packet, payload, payload_len, used_len);
if(a_quic_stream->st_client_hello.server_name_len > 0 || a_quic_stream->st_client_hello.user_agent_len > 0)
{
quic_callPlugins(a_quic_stream, pstream, QUIC_CLIENT_HELLO_MASK, pstream->threadnum, a_packet);
}
break;
default:
break;
2020-05-12 12:18:02 +08:00
}
}
}
}
2020-05-22 18:44:00 +08:00
2020-05-12 12:18:02 +08:00
return QUIC_RETURN_NORM;
}
2020-05-22 18:44:00 +08:00
UINT8 parse_gquic(struct streaminfo *pstream, void* a_packet, char * payload, uint32_t payload_len, uint32_t *used_len, struct quic_stream* a_quic_stream, uint8_t pub_flags)
{
int is_handshake=0;
2020-05-12 12:18:02 +08:00
uint32_t pkt_num_len = 0;
2020-05-22 18:44:00 +08:00
uint32_t skip_len=0;
pkt_num_len=read_seq_num_len(pub_flags);
2020-05-12 12:18:02 +08:00
//version Э<><D0AD>
2020-05-22 18:44:00 +08:00
if(!(PUBLIC_FLAG_VER&pub_flags!=0) && a_quic_stream->version && !a_quic_stream->version_cfm)
{
2020-05-12 12:18:02 +08:00
a_quic_stream->version_cfm = QUIC_TRUE;
2020-05-22 18:44:00 +08:00
quic_callPlugins(a_quic_stream, pstream, QUIC_VERSION_MASK, pstream->threadnum, a_packet);
MESA_handle_runtime_log(g_quic_param.logger, RLOG_LV_DEBUG, "QUIC_VERSION", "version: %u addr: %s", a_quic_stream->version, printaddr(&pstream->addr, pstream->threadnum));
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
skip_len=*used_len;
is_handshake=is_handshake_pkt(a_quic_stream, pkt_num_len, payload, payload_len, &skip_len); // just identify
switch(is_handshake)
{
case QUIC_TRUE: //handshake
2020-05-12 12:18:02 +08:00
a_quic_stream->is_quic_stream = QUIC_TRUE;
2020-05-22 18:44:00 +08:00
gquic_proc_unencrypt(pstream, a_quic_stream, pkt_num_len, a_packet, payload, payload_len, used_len);
break;
case QUIC_DATA: //ack or special stream
a_quic_stream->is_quic_stream = QUIC_TRUE;
break;
default: //gquic data or not gquic packet
if(!a_quic_stream->is_quic_stream)
{
return QUIC_RETURN_DROPME;
}
quic_callPlugins(a_quic_stream, pstream, QUIC_APPLICATION_DATA_MASK, pstream->threadnum, a_packet);
break;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
return QUIC_RETURN_NORM;
}
2020-05-12 12:18:02 +08:00
//cid->version->nounce->pkt num->ahn hash(12)
2020-05-22 18:44:00 +08:00
UINT8 gquic_process(struct streaminfo *pstream, struct quic_stream* a_quic_stream, int thread_seq, void* a_packet)
{
uint8_t pub_flags = 0;
uint32_t used_len = 0;
int ret=QUIC_RETURN_DROPME;
enum GQUIC_VERSION is_gquic=GQUIC_UNKNOWN;
struct udpdetail *udp_detail=(struct udpdetail *)pstream->pdetail;
if(!a_quic_stream->is_quic_stream && udp_detail->datalen<=GQUIC_HEADER_LEN)
{
MESA_handle_runtime_log(g_quic_param.logger,
RLOG_LV_DEBUG,
"QUIC",
"This is not quic (!a_quic_stream->is_quic_stream)=%d, or packet length is litter udp_detail->datalen<=GQUIC_HEADER_LEN(%d<=%d) addr: %s",
!a_quic_stream->is_quic_stream,
udp_detail->datalen,
GQUIC_HEADER_LEN,
printaddr(&pstream->addr, thread_seq));
2020-05-12 12:18:02 +08:00
return QUIC_RETURN_DROPME;
}
2020-05-22 18:44:00 +08:00
if(udp_detail->pdata==NULL || udp_detail->datalen<=0)
{
return QUIC_RETURN_NORM;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
is_gquic=is_gquic_protocol(pstream, (char *)udp_detail->pdata, udp_detail->datalen, &pub_flags, &a_quic_stream->version, &used_len);
if(is_gquic!=GQUIC_UNKNOWN)
{
a_quic_stream->is_quic_stream=QUIC_TRUE;
quic_callPlugins(a_quic_stream, pstream, QUIC_VERSION_MASK, thread_seq, a_packet);
2020-05-12 12:18:02 +08:00
2020-05-22 18:44:00 +08:00
switch(is_gquic)
{
case GQUIC_OTHERS:
ret=parse_gquic(pstream, a_packet, (char *)udp_detail->pdata, udp_detail->datalen, &used_len, a_quic_stream, pub_flags);
break;
case GQUIC_Q046:
ret=parse_gquic_Q046(pstream, a_packet, (char *)udp_detail->pdata, udp_detail->datalen, &used_len, a_quic_stream, pub_flags);
break;
default:
break;
2020-05-12 12:18:02 +08:00
}
}
2020-05-22 18:44:00 +08:00
if(a_quic_stream->is_quic_stream==QUIC_TRUE)
{
return QUIC_RETURN_NORM;
}
return ret;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
UINT32 read_offset_len(UINT8 frame_type)
{
switch((frame_type&STREAM_OOO)>>2)
{
2020-05-12 12:18:02 +08:00
case 0:
return 0;
2020-05-22 18:44:00 +08:00
break;
2020-05-12 12:18:02 +08:00
case 1:
return 2;
2020-05-22 18:44:00 +08:00
break;
2020-05-12 12:18:02 +08:00
case 2:
return 3;
2020-05-22 18:44:00 +08:00
break;
2020-05-12 12:18:02 +08:00
case 3:
return 4;
2020-05-22 18:44:00 +08:00
break;
2020-05-12 12:18:02 +08:00
case 4:
return 5;
2020-05-22 18:44:00 +08:00
break;
2020-05-12 12:18:02 +08:00
case 5:
return 6;
2020-05-22 18:44:00 +08:00
break;
2020-05-12 12:18:02 +08:00
case 6:
return 7;
2020-05-22 18:44:00 +08:00
break;
2020-05-12 12:18:02 +08:00
case 7:
return 8;
2020-05-22 18:44:00 +08:00
break;
2020-05-12 12:18:02 +08:00
default:
2020-05-22 18:44:00 +08:00
break;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
2020-05-12 12:18:02 +08:00
return 0;
}
2020-05-22 18:44:00 +08:00
UINT32 read_stream_len(UINT8 frame_type)
{
2020-05-12 12:18:02 +08:00
UINT32 stream_len = 0;
2020-05-22 18:44:00 +08:00
switch(frame_type&STREAM_SS)
{
2020-05-12 12:18:02 +08:00
case STREAM_ID_1BYTE:
stream_len = 1;
break;
case STREAM_ID_2BYTE:
stream_len = 2;
break;
case STREAM_ID_3BYTE:
stream_len = 3;
break;
case STREAM_ID_4BYTE:
stream_len = 4;
break;
default:
break;
}
2020-05-22 18:44:00 +08:00
2020-05-12 12:18:02 +08:00
return stream_len;
}
2020-05-22 18:44:00 +08:00
int read_conn_id_len(UINT8 flags)
{
switch (flags&BYTE_CNTID_8)
{
2020-05-12 12:18:02 +08:00
case BYTE_CNTID_8:
return 8;
case BYTE_CNTID_0:
return 0;
default:
2020-05-22 18:44:00 +08:00
return 0; // modify by liuxueli 20200522
//return -1;
2020-05-12 12:18:02 +08:00
}
}
2020-05-22 18:44:00 +08:00
UINT32 read_seq_num_len(UINT8 flags)
{
switch (flags & PKT_NUM_6)
{
case PKT_NUM_6:
return 6;
case PKT_NUM_4:
return 4;
case PKT_NUM_2:
return 2;
case PKT_NUM_1:
return 1;
default:
break;
}
2020-05-12 12:18:02 +08:00
return 1;
}
2020-05-22 18:44:00 +08:00
UINT32 read_largest_observed_len(UINT8 frame_type)
{
switch((frame_type & ACK_LL) >> 2)
{
case 0:
return 1;
break;
case 1:
return 2;
break;
case 2:
return 4;
break;
case 3:
return 6;
break;
default:
break;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
return 1;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
UINT32 read_missing_packet_len(UINT8 frame_type)
{
switch(frame_type & ACK_MM)
{
case 0:
return 1;
break;
case 1:
return 2;
break;
case 2:
return 4;
break;
case 3:
return 6;
break;
default:
break;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00
return 1;
2020-05-12 12:18:02 +08:00
}
2020-05-22 18:44:00 +08:00