summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlijia <[email protected]>2021-09-14 15:50:53 +0800
committerlijia <[email protected]>2021-09-14 15:50:53 +0800
commitf6f399f69a950ab1c45ea0e8c0787a476ff58754 (patch)
tree3cca11bd40a8209a534855a53525ea83763620b0 /src
create new project.v1.0.0
除sapp和插件之外, 其他模块也经常有从某个层跳转到某个层的需求, 从sapp中剥离此部分代码, 独立成为一个公共库.
Diffstat (limited to 'src')
-rw-r--r--src/MESA_jump_layer.cpp1501
-rw-r--r--src/Makefile10
-rw-r--r--src/deal_ipv6.h113
-rw-r--r--src/mesa_net.h885
4 files changed, 2509 insertions, 0 deletions
diff --git a/src/MESA_jump_layer.cpp b/src/MESA_jump_layer.cpp
new file mode 100644
index 0000000..0641498
--- /dev/null
+++ b/src/MESA_jump_layer.cpp
@@ -0,0 +1,1501 @@
+#include "stream.h"
+#include "mesa_net.h"
+#include "deal_ipv6.h"
+/* Linux OS std */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <dlfcn.h>
+#include <linux/if_ether.h>
+#include <linux/limits.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <net/if_arp.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <linux/version.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/prctl.h>
+#include <sys/un.h>
+#include <link.h>
+#include <execinfo.h>
+#include <pcap/pcap.h>
+#include <getopt.h>
+#include <sys/sysinfo.h>
+#include <dirent.h>
+#include <sys/syscall.h>
+
+
+static int eth_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type);
+static int vlan8021q_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type);
+static int ipv4_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type);
+static int ipv6_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type);
+static int ppp_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type);
+
+static char _g_mesa_jump_layer_last_error[PIPE_BUF];
+
+
+/* ascii�ַ�ת16���� */
+char MESA_ascii_to_hex(char ascii)
+{
+ char c = 0;
+
+ switch(ascii)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ c = ascii - 0x30;
+ break;
+
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ c = 10 + ascii - 0x61;
+ break;
+
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ c = 10 + ascii - 0x41;
+ break;
+
+ default:
+ c = 0; //todo , what error number return?
+ break;
+ }
+
+ return c;
+}
+
+static int __mjl_guess_mpls_with_control_word(const unsigned char *maybe_eth_hdr)
+{
+ const struct mesa_ethernet_hdr *ehdr = (struct mesa_ethernet_hdr *)(maybe_eth_hdr);
+
+ /*
+ MPLSû���ֶα�ʾ���ص�Э������, ����!!
+
+ https://tools.ietf.org/html/rfc4623
+ https://wiki.mikrotik.com/wiki/Manual:VPLS_Control_Word
+ https://www.ciscopress.com/articles/article.asp?p=386788&seqNum=2
+
+ ����׼��ipv4, ipv6֮��, ���п�����ethernet, ���п����Ǵ�PW Ethernet Control Word��, ��ʽ����:
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |0 0 0 0| flags |frag|len(6bit) | Sequence Number(16bit) |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ ʵ�����֤��, ��4bit�Ƿ�==0Ϊ����, ���ǿ��ܲ´�, ���ж�һ����̫�����Ƿ�Ϊ��������.
+ */
+
+ switch(ntohs(ehdr->ether_type)){
+ case ETH_P_IP:
+ case ETH_P_IPV6:
+ case ETH_P_8021Q:
+ case ETH_P_MPLS_UC:
+ case ETH_P_PPP_SES:
+ return 0; /* �Ϸ���ethernet����, ����CW */
+ break;
+
+ default:
+ break;
+ }
+
+ ehdr = (struct mesa_ethernet_hdr *)(maybe_eth_hdr + 4);
+ switch(ntohs(ehdr->ether_type)){
+ case ETH_P_IP:
+ case ETH_P_IPV6:
+ case ETH_P_8021Q:
+ case ETH_P_MPLS_UC:
+ case ETH_P_PPP_SES:
+ return 1; /* �Ϸ���ethernet����, ����CW */
+ break;
+
+ default:
+ break;
+ }
+
+ /* TODO: ���϶�����, �˴�Ӧ�÷��ظ�ʲôֵ? */
+ return 0;
+}
+
+static int __mjl_mpls_addr_net_to_mem(const struct mesa_mpls_hdr *net_mpls_hdr, struct single_layer_mpls_addr *mem_mpls_hdr)
+{
+ memset(mem_mpls_hdr, 0, sizeof(struct single_layer_mpls_addr));
+
+ mem_mpls_hdr->label = htonl( (net_mpls_hdr->mpls_label_low<<12) | (net_mpls_hdr->mpls_label_mid<<4) | net_mpls_hdr->mpls_label_high ); /* network order */
+ mem_mpls_hdr->experimental = net_mpls_hdr->mpls_exp;
+ mem_mpls_hdr->bottom = net_mpls_hdr->mpls_bls;
+ mem_mpls_hdr->ttl = net_mpls_hdr->mpls_ttl;
+
+ return 0;
+}
+
+static int __mjl_set_mpls_addr(struct layer_addr_mpls *addr, const unsigned char *raw_mpls_pkt_data)
+{
+ const struct mesa_mpls_hdr *this_mpls_hdr;
+ int i;
+
+ memset(addr, 0, sizeof(struct layer_addr_mpls));
+ for(i = 0; i < MAX_MPLS_ADDR_LAYER; i++)
+ {
+ this_mpls_hdr = (const struct mesa_mpls_hdr *)raw_mpls_pkt_data;
+ //memcpy(&addr->src_mpls_pkt[i], raw_mpls_pkt_data, sizeof(struct mesa_mpls_hdr));
+ __mjl_mpls_addr_net_to_mem(this_mpls_hdr, &addr->c2s_addr_array[i]); /* ����ջ��ĵ�ַ, ÿ���ݴ���c2s����, TCP/UDP���ٸ���������ת */
+
+ addr->c2s_layer_num += 1;
+ if(1 == this_mpls_hdr->mpls_bls){
+ raw_mpls_pkt_data += sizeof(struct mesa_mpls_hdr); /* Ϊ�˺��淽���ж��Ƿ���ctrl word */
+ break;
+ }
+ raw_mpls_pkt_data += sizeof(struct mesa_mpls_hdr);
+ }
+
+ if(1 != this_mpls_hdr->mpls_bls) /* ����MAX_MPLS_ADDR_LAYER, MPLS��û�н��� */
+ {
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF, "MPLS layer number over load, only support %d", MAX_MPLS_ADDR_LAYER);
+ return -1;
+ }
+
+ if(((*raw_mpls_pkt_data & 0xF0) != 0x40) && ((*raw_mpls_pkt_data & 0xF0) != 0x60)){ //VPLS, MPLS with Control Word
+ if(__mjl_guess_mpls_with_control_word(raw_mpls_pkt_data) > 0){
+ memcpy(&addr->c2s_mpls_ctrl_word, raw_mpls_pkt_data, sizeof(int));
+ addr->c2s_has_ctrl_word = 1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ gprsͷ�����ݱ�־λ�IJ�ͬ, ����Ҳ��ͬ, ����ֱ����sizeof(struct gtp_hdr)��ȡ����.
+*/
+static int __mjl_gtp_calc_gtp_hdr_len(const struct gtp_hdr *gtph)
+{
+ const unsigned char *p_ext_hdr = (unsigned char *)gtph + sizeof(struct gtp_hdr);
+ unsigned char next_hdr_type;
+ unsigned char this_ext_field_cont_len;
+
+ /*
+ v0̫������, �ѱ�����;
+ ������GTPv2-UЭ��, ��LTE�е�GTP-U��ʹ��GTPv1-U,
+ ����, sappĿǰ��֧��gtp v1�汾.
+ */
+ if(((gtph->flags & GTP_HDR_VER_MASK) >> 5) != 1){
+ return -1;
+ }
+
+ if(gtph->flags & (GTP_HDR_FLAG_SEQ_NUM | GTP_HDR_FLAG_N_PDU | GTP_HDR_FLAG_NEXT_EXT_HDR)){
+ //todo, parse and get seq field
+ p_ext_hdr += 2; //seq field length is 2 bytes
+
+ //todo, parse and get N-PDU field
+ p_ext_hdr++; //N-PDU field length is 1 byte
+
+ /*
+ ����gtp��չͷ���ֶ�,
+ �ο�3GPP�ĵ���5.1, 5.2�½�,
+ �Լ�wiresharkԴ��, packet-gtp.c -> dissect_gtp_common()����.
+ */
+
+ next_hdr_type = *p_ext_hdr;
+ if(gtph->flags & GTP_HDR_FLAG_NEXT_EXT_HDR){
+ while(next_hdr_type != 0){
+ //todo, parse and get extension headers
+ p_ext_hdr++; //ָ�򳤶��ֶ�, ��4���ֽ�Ϊ��λ
+ this_ext_field_cont_len = *p_ext_hdr * 4 - 2;
+
+ p_ext_hdr++; //ָ�����ݲ��ֵ�һ���ֽ�
+ p_ext_hdr += this_ext_field_cont_len;
+
+ //ָ����һ��ͷ���ֶ�
+ next_hdr_type = *p_ext_hdr;
+ p_ext_hdr++;
+ }
+ }else{
+ p_ext_hdr++;
+ }
+ }
+
+ return (char *)p_ext_hdr - (char *)gtph;
+}
+
+static inline int check_layer_type(int layer_type)
+{
+ if((layer_type <= __ADDR_TYPE_INIT) || (layer_type >= __ADDR_TYPE_MAX)){
+ return -1;
+ }
+
+ return 0;
+}
+
+static int arp_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ /* arpЭ�鲻�����κ��ϲ�����Э�� */
+ return -1;
+}
+
+
+static int gtp_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ const struct gtp_hdr *gh = (struct gtp_hdr *)raw_data;
+ const unsigned char *next_ip_layer_hdr;
+ int skip_len;
+ int gtp_hdr_len;
+
+ if(ADDR_TYPE_GPRS_TUNNEL == expect_layer_type){
+ return 0;
+ }
+
+ gtp_hdr_len = __mjl_gtp_calc_gtp_hdr_len(gh);
+ if(gtp_hdr_len < 0){
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF, "calc gtp hdr len error");
+ return -1;
+ }
+
+ next_ip_layer_hdr = (unsigned char *)raw_data + gtp_hdr_len;
+
+ if((*next_ip_layer_hdr & 0x40) == 0x40){
+ skip_len = ipv4_jump_to_layer((char *)next_ip_layer_hdr, __ADDR_TYPE_IP_PAIR_V4, expect_layer_type);
+ }else if((*next_ip_layer_hdr & 0x60) == 0x60){
+ skip_len = ipv6_jump_to_layer((char *)next_ip_layer_hdr, __ADDR_TYPE_IP_PAIR_V6, expect_layer_type);
+ }else{
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF, "gtp_jump_to_layer() error, unsupport type in GTP, 0x%x!", (*next_ip_layer_hdr));
+ return -1;
+ }
+
+ return gtp_hdr_len + skip_len;
+}
+
+static int __mjl_guess_l2tp_ppp_layer_len(const unsigned char *maybe_l2tp_ppp_hdr)
+{
+ int ppp_layer_len = -1;
+ const unsigned short *ppp_proto;
+ if((0xFF == maybe_l2tp_ppp_hdr[0]) && (0x03 == maybe_l2tp_ppp_hdr[1])){
+ ppp_proto = (unsigned short *)(maybe_l2tp_ppp_hdr + 2);
+
+ switch(ntohs(*ppp_proto)){
+ case PPP_PROTOCOL_IPv4:
+ case PPP_PROTOCOL_PAP:
+ case PPP_PROTOCOL_CHAP:
+ case PPP_PROTOCOL_IPv6:
+ case PPP_PROTOCOL_LCP:
+ case PPP_PROTOCOL_CCP:
+ case PPP_PROTOCOL_IPCP:
+ ppp_layer_len = 4;
+ break;
+ }
+ }else{
+ if((0x21 == maybe_l2tp_ppp_hdr[0]) || (0x57 == maybe_l2tp_ppp_hdr[0])){
+
+ ppp_layer_len = 1; /* ʡ����control, address�ֶ�, ֻ��һ���ֽڵ�Э���, �ο�: http://www2.ic.uff.br/~michael/kr1999/5-datalink/5_08-ppp.htm#[RFC%201662] */
+ }
+ }
+
+ return ppp_layer_len;
+}
+
+static int __mjl_parse_l2tpv2_ppp_hdr(const unsigned char *l2tp_ppp_hdr, struct layer_addr_l2tp *l2tpaddr)
+{
+ int ppp_hdr_len;
+ const unsigned short *ppp_protocol;
+
+ ppp_hdr_len = __mjl_guess_l2tp_ppp_layer_len(l2tp_ppp_hdr);
+ if(ppp_hdr_len < 0){
+ return -1;
+ }
+
+ if(sizeof(struct layer_compress_ppp_hdr) == ppp_hdr_len){
+ l2tpaddr->l2tpun.l2tp_addr_v2.ppp_hdr_compress_enable = 1;
+ l2tpaddr->l2tpun.l2tp_addr_v2.compress_ppp_hdr.protocol = l2tp_ppp_hdr[0];
+ }else if(sizeof(struct layer_ppp_hdr) == ppp_hdr_len){
+ l2tpaddr->l2tpun.l2tp_addr_v2.ppp_hdr_compress_enable = 0;
+ l2tpaddr->l2tpun.l2tp_addr_v2.ppp_hdr.address = l2tp_ppp_hdr[0];
+ l2tpaddr->l2tpun.l2tp_addr_v2.ppp_hdr.control = l2tp_ppp_hdr[1];
+
+ ppp_protocol = (unsigned short *)&l2tp_ppp_hdr[2];
+ l2tpaddr->l2tpun.l2tp_addr_v2.ppp_hdr.protocol = *ppp_protocol;
+ }else{
+ return -1;
+ }
+
+ return ppp_hdr_len;
+}
+
+static int __mjl_parse_l2tpv2_hdr(const struct l2tp_hdr_v2 *pl2tphdrv2, struct layer_addr_l2tp *l2tpaddr)
+{
+ unsigned short l2top_tot_len, offset_size;
+ const char *ptr = (const char *)pl2tphdrv2 + sizeof(struct l2tp_hdr_v2);
+ int l2tp_ppp_hdr_len;
+
+ memset(l2tpaddr, 0, sizeof(struct layer_addr_l2tp));
+
+ if(pl2tphdrv2->length_present){
+ l2top_tot_len = ntohs(*((unsigned short *)ptr));
+ ptr += sizeof(short);
+ if(l2top_tot_len < sizeof(struct l2tp_hdr_v2) + 1/* compress ppp hdr len */ + sizeof(struct mesa_ip4_hdr)){
+ return -1; /* ���������� */
+ }
+ }
+
+ /* L2TP��ַC2S, S2C�������, �޷�����ǰ����ַ����dir, ÿ��ջ��ı������洢��source����, ��C2S����,
+ ������ʱ, �����Ҫreverse����, ��source, dest�ߵ�, ����ֱ��memcpy�������addr.
+ */
+
+ l2tpaddr->l2tpun.l2tp_addr_v2.tunnelid_C2S = *((unsigned short *)ptr);
+ ptr += sizeof(short);
+ l2tpaddr->l2tpun.l2tp_addr_v2.sessionid_C2S = *((unsigned short *)ptr);
+ ptr += sizeof(short);
+
+ if(pl2tphdrv2->seq_present){
+ ptr += sizeof(int);
+ l2tpaddr->l2tpun.l2tp_addr_v2.seq_present_C2S = 1;
+ }
+
+ if(pl2tphdrv2->offset_present){
+ offset_size = ntohs(*((unsigned short *)ptr));
+ ptr += sizeof(short); /* 2 byte fix len offset size */
+ ptr += offset_size; /* var bytes offset value length */
+ }
+
+ l2tp_ppp_hdr_len = __mjl_parse_l2tpv2_ppp_hdr((unsigned char *)ptr, l2tpaddr);
+ if(l2tp_ppp_hdr_len < 0){
+ return -1;
+ }
+ ptr += l2tp_ppp_hdr_len;
+
+ l2tpaddr->version = 2; /* version, RFC2661 */
+
+ return ptr - (char *)pl2tphdrv2;
+}
+static int l2tp_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ int l2tp_hdr_len, skip_len = 0;
+
+ const unsigned char *next_layer_hdr;
+ struct layer_addr_l2tp tmp_l2tp_addr;
+
+ if(ADDR_TYPE_L2TP == expect_layer_type){
+ return 0;
+ }
+
+ l2tp_hdr_len = __mjl_parse_l2tpv2_hdr((const struct l2tp_hdr_v2 *)raw_data, &tmp_l2tp_addr);
+ if(l2tp_hdr_len < 0){
+ return -1;
+ }
+
+ next_layer_hdr = (unsigned char *)raw_data + l2tp_hdr_len;
+
+ if(tmp_l2tp_addr.l2tpun.l2tp_addr_v2.ppp_hdr_compress_enable){
+ if(tmp_l2tp_addr.l2tpun.l2tp_addr_v2.compress_ppp_hdr.protocol == 0x21){
+ skip_len = ipv4_jump_to_layer((char *)next_layer_hdr, __ADDR_TYPE_IP_PAIR_V4, expect_layer_type);
+ }else if(tmp_l2tp_addr.l2tpun.l2tp_addr_v2.compress_ppp_hdr.protocol == 0x57){
+ skip_len = ipv6_jump_to_layer((char *)next_layer_hdr, __ADDR_TYPE_IP_PAIR_V6, expect_layer_type);
+ }
+ }else{
+ if(ntohs(tmp_l2tp_addr.l2tpun.l2tp_addr_v2.ppp_hdr.protocol) == 0x0021){
+ skip_len = ipv4_jump_to_layer((char *)next_layer_hdr, __ADDR_TYPE_IP_PAIR_V4, expect_layer_type);
+ }else if(ntohs(tmp_l2tp_addr.l2tpun.l2tp_addr_v2.ppp_hdr.protocol) == 0x57){
+ skip_len = ipv6_jump_to_layer((char *)next_layer_hdr, __ADDR_TYPE_IP_PAIR_V6, expect_layer_type);
+ }
+ }
+
+ return l2tp_hdr_len + skip_len;
+}
+
+static int teredo_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ const char *next_layer_hdr;
+ struct teredo_auth_hdr *p_teredo_hdr;
+ int teredo_layer_len = 0, tmp_hdr_len = 0, skip_len = 0;
+
+
+ /* teredoʵ��û�����ݰ�ͷ */
+ next_layer_hdr = raw_data;
+
+ while((*next_layer_hdr & 0xF0) != 0x60){
+ p_teredo_hdr = (struct teredo_auth_hdr *)next_layer_hdr;
+ if(p_teredo_hdr->flags == ntohs(TEREDO_AUTH_HDR_FLAG))
+ {
+ //rfc4380 5.1.1 teredo ����0x0001ʱΪTeredo authentication headers����Ҫ����
+ tmp_hdr_len += sizeof(struct teredo_auth_hdr) + ntohs(p_teredo_hdr->au_len) + ntohs
+ (p_teredo_hdr->id_len) + 8 + 1;
+ next_layer_hdr += tmp_hdr_len;
+ teredo_layer_len += tmp_hdr_len;
+ }
+ else if(p_teredo_hdr->flags == ntohs(TEREDO_INDICATION_HDR_FLAG))
+ {
+ //rfc4380 teredo ����0x0000ʱΪTeredo indication headers����Ҫ����
+ next_layer_hdr += TEREDO_INDICATION_HDR_LEN;
+ teredo_layer_len += TEREDO_INDICATION_HDR_LEN;
+ }
+ else
+ {
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF, "teredo_jump_to_layer(): unsupport teredo hdr:0x%d!\n", *(unsigned int *)(next_layer_hdr));
+ return -1;
+ }
+ }
+ skip_len = ipv6_jump_to_layer(next_layer_hdr, __ADDR_TYPE_IP_PAIR_V6, expect_layer_type);
+ if(skip_len < 0){
+ return -1;
+ }
+ skip_len += teredo_layer_len;
+
+ return skip_len;
+}
+
+
+
+static int udp_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ const struct mesa_udp_hdr *uh = (const struct mesa_udp_hdr *)raw_data;
+ unsigned short usport, udport;
+ int skip_len;
+
+ if(ADDR_TYPE_UDP == expect_layer_type){
+ return 0;
+ }
+
+ usport = ntohs(uh->uh_sport);
+ udport = ntohs(uh->uh_dport);
+
+ if((2152 == usport) || (2152 == udport)){
+ skip_len = gtp_jump_to_layer(raw_data+sizeof(struct mesa_udp_hdr), ADDR_TYPE_UDP, expect_layer_type);
+ }else if(4789 == udport){
+ /* vxlanģʽ��ʱֻ֧��ethernet. TODO: �����hdlc, ppp��װ, ��Ҫʵ��һ��������vxlan_jump_to_layer()���� */
+ skip_len = eth_jump_to_layer(raw_data+sizeof(struct mesa_udp_hdr)+8, ADDR_TYPE_MAC, expect_layer_type);
+ if(skip_len < 0){
+ return -1;
+ }
+ skip_len += 8; /* skip vxlan header */
+ }else if((3544 == usport) || (3544 == udport)){
+ skip_len = teredo_jump_to_layer(raw_data+sizeof(struct mesa_udp_hdr), 0, expect_layer_type);
+ }else if((1701 == usport) || (1701 == udport)){
+ skip_len = l2tp_jump_to_layer(raw_data+sizeof(struct mesa_udp_hdr), ADDR_TYPE_UDP, expect_layer_type);
+ }else{
+ /* ����UDP���Ͳ�֧������ת */
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF, "MESA_net_jump_to_layer_greedy() not support layer type:%d", expect_layer_type);
+ return -1;
+ }
+ if(skip_len < 0){
+ return -1;
+ }
+
+ return skip_len + sizeof(struct mesa_udp_hdr);
+}
+
+static int udp_jump_to_layer_greedy(const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ const struct mesa_udp_hdr *uh = (const struct mesa_udp_hdr *)raw_data;
+ unsigned short usport, udport;
+ int skip_len;
+
+ usport = ntohs(uh->uh_sport);
+ udport = ntohs(uh->uh_dport);
+
+ if((2152 == usport) || (2152 == udport)){
+ skip_len = gtp_jump_to_layer(raw_data+sizeof(struct mesa_udp_hdr), ADDR_TYPE_UDP, expect_layer_type);
+ }else if(4789 == udport){
+ /* vxlanģʽ��ʱֻ֧��ethernet. TODO: �����hdlc, ppp��װ, ��Ҫʵ��һ��������vxlan_jump_to_layer()���� */
+ skip_len = eth_jump_to_layer(raw_data+sizeof(struct mesa_udp_hdr)+8, ADDR_TYPE_MAC, expect_layer_type);
+ if(skip_len < 0){
+ return -1;
+ }
+ skip_len += 8; /* skip vxlan header */
+ }else if((3544 == usport) || (3544 == udport)){
+ skip_len = teredo_jump_to_layer(raw_data+sizeof(struct mesa_udp_hdr), 0, expect_layer_type);
+ }else if((1701 == usport) || (1701 == udport)){
+ skip_len = l2tp_jump_to_layer(raw_data+sizeof(struct mesa_udp_hdr), ADDR_TYPE_UDP, expect_layer_type);
+ }else{
+ /* ����UDP���Ͳ�֧������ת */
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF, "udp_jump_to_layer(): unsupport udp sport:%u, dport:%u!\n", usport, udport);
+ return -1;
+ }
+ if(skip_len < 0){
+ return -1;
+ }
+
+ return skip_len + sizeof(struct mesa_udp_hdr);
+}
+
+static int set_gre_hdr_ver0(struct mesa_gre_hdr *stack_gre_addr, const struct mesa_gre_hdr *net_gre_addr)
+{
+ struct mesa_gre_extend_hdr *stack_gre_ext = &stack_gre_addr->gre_extend;
+ const struct mesa_gre_base_hdr_v0 *net_gre_base = &net_gre_addr->gre_base;
+ const char *net_ext_hdr_value = (const char *)(&net_gre_addr->gre_extend);
+ //const struct gre_source_route_entry_hdr *rse_hdr;
+
+ if(net_gre_base->checksum_flag || net_gre_base->route_flag){
+ stack_gre_ext->checksum = *((unsigned short *)net_ext_hdr_value);
+ net_ext_hdr_value += sizeof(short);
+
+ /* ���checksum����, ��offsetҲ�ش��� */
+ stack_gre_ext->offset = *((unsigned short *)net_ext_hdr_value);
+ net_ext_hdr_value += sizeof(short);
+ }
+
+ if(net_gre_base->key_flag){
+ stack_gre_ext->key = *((unsigned int *)net_ext_hdr_value);
+ net_ext_hdr_value += sizeof(int);
+ }
+
+ if(net_gre_base->seq_flag){
+ stack_gre_ext->seq_num = *((unsigned int *)net_ext_hdr_value);
+ net_ext_hdr_value += sizeof(int);
+ }
+
+ /* SRE��Ϣ��GREͷ�������, ��Ϊ������, �������� */
+ if(net_gre_base->route_flag){
+ //rse_hdr = (const struct gre_source_route_entry_hdr *)net_ext_hdr_value;
+ //TODO 1, copy SRE
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF, "found GRE SRE data, but not parse yet!");
+ return -1;
+ }
+
+ return sizeof(struct mesa_gre_base_hdr_v1) + (net_ext_hdr_value - (char *)&net_gre_addr->gre_extend);
+}
+
+static int set_gre_hdr_ver1(struct mesa_gre_hdr *stack_gre_addr, const struct mesa_gre_hdr *net_gre_addr)
+{
+ //struct mesa_gre_base_hdr_v1 *stack_gre_base = (struct mesa_gre_base_hdr_v1 *)&stack_gre_addr->gre_base;
+ struct mesa_gre_extend_hdr *stack_gre_ext = &stack_gre_addr->gre_extend;
+ const struct mesa_gre_base_hdr_v1 *net_gre_base = (struct mesa_gre_base_hdr_v1 *)&net_gre_addr->gre_base;
+ //const struct mesa_gre_extend_hdr *net_gre_ext = &net_gre_addr->gre_extend;
+ const char *net_ext_hdr_value = (const char *)(&net_gre_addr->gre_extend);
+
+ if(net_gre_base->checksum_flag != 0){
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF,"error! in gre version1, checksum flag not zero!");
+ return -1;
+ }
+
+ if(net_gre_base->route_flag != 0){
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF,"error! in gre version1, route flag not zero!");
+ return -1;
+ }
+
+ if(net_gre_base->recur != 0){
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF,"error! in gre version1, recur flag not zero!");
+ return -1;
+ }
+
+ if(net_gre_base->strict_src_route_flag != 0){
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF,"error! in gre version1, strict_src_route flag not zero!");
+ return -1;
+ }
+
+ if(ntohs(net_gre_base->protocol) != GRE_PRO_PPP){
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF,"error! in gre version1, protocol not 0x%x!", GRE_PRO_PPP);
+ return -1;
+ }
+
+ stack_gre_ext->payload_len = *((unsigned short *)net_ext_hdr_value);
+ net_ext_hdr_value += sizeof(short);
+
+ stack_gre_ext->call_id = *((unsigned short *)net_ext_hdr_value);
+ net_ext_hdr_value += sizeof(short);
+
+ if(net_gre_base->seq_flag){
+ stack_gre_ext->seq_num = *((unsigned int *)net_ext_hdr_value);
+ net_ext_hdr_value += sizeof(int);
+ }
+
+ /* version 1 has ack number */
+ if(net_gre_base->ack_flag){
+ stack_gre_ext->ack_num = *((unsigned int *)net_ext_hdr_value);
+ net_ext_hdr_value += sizeof(int);
+ }
+
+ return sizeof(struct mesa_gre_base_hdr_v1) + (net_ext_hdr_value - (char *)&net_gre_addr->gre_extend);
+}
+
+extern int __mjl_set_gre_hdr(struct mesa_gre_hdr *stack_gre_addr, const void *this_layer_data)
+{
+ int gre_hdr_len = 0;
+ const struct mesa_gre_hdr *net_gre_addr = (const struct mesa_gre_hdr *)this_layer_data;
+
+ memcpy(&stack_gre_addr->gre_base, &net_gre_addr->gre_base, sizeof(struct mesa_gre_base_hdr_v0));
+ memset(&stack_gre_addr->gre_extend, 0, sizeof(struct mesa_gre_extend_hdr));
+
+ if(0 == net_gre_addr->gre_base.version){
+ gre_hdr_len = set_gre_hdr_ver0(stack_gre_addr, net_gre_addr);
+ }else if(1 == net_gre_addr->gre_base.version){
+ gre_hdr_len = set_gre_hdr_ver1(stack_gre_addr, net_gre_addr);
+ }else{
+ //TODO 1, δ֪�汾
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF,"Unknown gre hdr version:%d", net_gre_addr->gre_base.version);
+ gre_hdr_len = -1;
+ }
+
+ return gre_hdr_len;
+}
+
+static int gre_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ int skip_len = 0;
+ int this_gre_layer_len;
+ struct mesa_gre_hdr this_layer_hdr;
+
+ if(raw_layer_type == expect_layer_type){
+ return 0;
+ }
+
+ this_gre_layer_len = __mjl_set_gre_hdr(&this_layer_hdr, (void *)raw_data);
+ if(this_gre_layer_len < 0){
+ return -1;
+ }
+
+ switch(ntohs(this_layer_hdr.gre_base.protocol))
+ {
+ case GRE_PRO_IPV4:
+ if(expect_layer_type == ADDR_TYPE_IPV4){
+ skip_len = 0;
+ break;
+ }else{
+ skip_len=ipv4_jump_to_layer(raw_data+this_gre_layer_len, __ADDR_TYPE_IP_PAIR_V4, expect_layer_type);
+ }
+ break;
+
+ case GRE_PRO_IPV6:
+ if(expect_layer_type == ADDR_TYPE_IPV4){
+ skip_len = 0;
+ break;
+ }else{
+ skip_len=ipv6_jump_to_layer(raw_data+this_gre_layer_len, __ADDR_TYPE_IP_PAIR_V6, expect_layer_type);
+ }
+ break;
+
+ case GRE_PRO_PPP:
+ if((expect_layer_type == ADDR_TYPE_PPP) || (expect_layer_type == ADDR_TYPE_PPTP)){
+ skip_len = this_gre_layer_len;
+ break;
+ }else{
+ skip_len = ppp_jump_to_layer(raw_data+this_gre_layer_len, ADDR_TYPE_PPP, expect_layer_type);
+ }
+ break;
+
+ default:
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF, "gre_jump_to_layer(): unknown gre protocol:0x%x!", ntohs(this_layer_hdr.gre_base.protocol));
+ return -1;
+ break;
+ }
+
+ if(skip_len < 0){
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF, "gre_jump_to_layer() error!");
+ return -1;
+ }
+
+ return skip_len + this_gre_layer_len;
+}
+
+static int ipv4_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ struct mesa_ip4_hdr *p_ip_hdr = (struct mesa_ip4_hdr *)raw_data;
+ int skip_len = 0;
+ int ip_hdr_len = p_ip_hdr->ip_hl * 4;
+ //const char *next_layer_data = raw_data + ip_hdr_len;
+
+ if(raw_layer_type == expect_layer_type){
+ return 0;
+ }
+
+ if((ntohs(p_ip_hdr->ip_off) & IP_MF ) || (ntohs(p_ip_hdr->ip_off) & IP_OFFMASK)){
+ /* IP��Ƭ���ټ������ڲ���ת */
+ return -1;
+ }
+
+ switch(p_ip_hdr->ip_p){
+ case IPPROTO_TCP:
+ if(ADDR_TYPE_TCP == expect_layer_type){
+ skip_len = 0;
+ break;
+ }else{
+ skip_len = -1; /* tcp ��֮�ϲ���������Э�� */
+ }
+ break;
+
+ case IPPROTO_UDP:
+ if(ADDR_TYPE_UDP == expect_layer_type){
+ skip_len = 0;
+ break;
+ }else{
+ skip_len = udp_jump_to_layer(raw_data+ip_hdr_len, ADDR_TYPE_UDP, expect_layer_type);
+ }
+ break;
+
+ case IPPROTO_IPV6:
+ if(__ADDR_TYPE_IP_PAIR_V6 == expect_layer_type){
+ skip_len = 0;
+ break;
+ }else{
+ skip_len = ipv6_jump_to_layer(raw_data+ip_hdr_len, __ADDR_TYPE_IP_PAIR_V6, expect_layer_type);
+ }
+ break;
+
+ case IPPROTO_GRE:
+ if((ADDR_TYPE_GRE == expect_layer_type) || (ADDR_TYPE_PPTP == expect_layer_type)){
+ skip_len = 0;
+ break;
+ }else{
+ skip_len = gre_jump_to_layer(raw_data+ip_hdr_len, ADDR_TYPE_GRE, expect_layer_type);
+ }
+ break;
+
+ default:
+ skip_len = -1;
+ break;
+ }
+
+ if(skip_len < 0){
+ return -1;
+ }
+
+ return skip_len + sizeof(struct ip);
+}
+
+static int ipv6_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ const struct mesa_ip6_hdr *a_packet = (const struct mesa_ip6_hdr *)raw_data;
+ UINT8 next_hdr_type = a_packet->ip6_nxt_hdr;
+ UINT8 *next_hdr_ptr = (UINT8 *)a_packet + sizeof(struct mesa_ip6_hdr);
+ int skip_len = 0;
+ int offset_to_ip6 = 0;
+
+ if(raw_layer_type == expect_layer_type){
+ return 0;
+ }
+
+ while(1){
+ offset_to_ip6 = 0;
+ switch(next_hdr_type)
+ {
+ case NEXTHDR_HOP:
+ case NEXTHDR_ROUTING:
+ case NEXTHDR_AUTH:
+ case NEXTHDR_DEST:
+ offset_to_ip6 = (*(next_hdr_ptr + 1))*8 + 8; /* ѡ�����8�ֽ�Ϊ��λ */
+ break;
+
+ case NEXTHDR_IPIP:
+ if(__ADDR_TYPE_IP_PAIR_V4 == expect_layer_type){
+ skip_len = next_hdr_ptr - (UINT8 *)raw_data;
+ }else{
+ skip_len = ipv4_jump_to_layer((const char *)next_hdr_ptr, __ADDR_TYPE_IP_PAIR_V4, expect_layer_type);
+ if(skip_len < 0){
+ return -1;
+ }else{
+ return skip_len + next_hdr_ptr - (UINT8 *)raw_data;
+ }
+ }
+ goto done;
+ break;
+
+ case NEXTHDR_NONE:
+ skip_len = -1;
+ goto done;
+ break;
+
+ case NEXTHDR_ICMP: /* IMCP���ٳ�������Э�� */
+ skip_len = -1;
+ goto done;
+ break;
+
+ case NEXTHDR_TCP:
+ if(ADDR_TYPE_TCP == expect_layer_type){
+ skip_len = next_hdr_ptr - (UINT8 *)raw_data;
+ }else{
+ skip_len = -1;
+ }
+ goto done;
+ break;
+
+ case NEXTHDR_UDP:
+ if(ADDR_TYPE_UDP == expect_layer_type){
+ skip_len = next_hdr_ptr - (UINT8 *)raw_data;
+ }else{
+ skip_len = udp_jump_to_layer((char *)next_hdr_ptr, ADDR_TYPE_UDP, expect_layer_type);
+ if(skip_len < 0){
+ return -1;
+ }else{
+ return skip_len + next_hdr_ptr - (UINT8 *)raw_data;
+ }
+ }
+ goto done;
+ break;
+
+ case NEXTHDR_FRAGMENT:
+ /* IP��Ƭ���ټ������ڲ���ת */
+ skip_len = -1;
+ goto done;
+ break;
+
+ case NEXTHDR_ESP:
+ skip_len = -1;
+ goto done;
+
+ default:
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF, "ipv6_jump_to_layer(): unknown IPv6 header type:0x%x!", next_hdr_type);
+ skip_len = -1;
+ goto done;
+ break;
+ }
+
+ next_hdr_type = *next_hdr_ptr;
+ next_hdr_ptr += offset_to_ip6;
+ }
+
+done:
+ if(skip_len < 0){
+ return -1;
+ }
+
+ return skip_len;
+}
+
+static int ppp_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ int skip_len = 0;
+ struct mesa_ppp_hdr *ppp_data_hdr;
+ char *next_hdr;
+
+ if(raw_layer_type == expect_layer_type){
+ return 0;
+ }
+ ppp_data_hdr = (struct mesa_ppp_hdr *)raw_data;
+ next_hdr = (char *)raw_data + sizeof(struct mesa_ppp_hdr);
+
+ switch(ntohs(ppp_data_hdr->protocol)){
+ case PPP_PROTOCOL_IPv4:
+ if(__ADDR_TYPE_IP_PAIR_V4 == expect_layer_type){
+ break;
+ }else{
+ skip_len = ipv4_jump_to_layer(next_hdr, __ADDR_TYPE_IP_PAIR_V4, expect_layer_type);
+ }
+ break;
+
+ case PPP_IPV6:
+ if(__ADDR_TYPE_IP_PAIR_V6 == expect_layer_type){
+ break;
+ }else{
+ skip_len = ipv6_jump_to_layer(next_hdr, __ADDR_TYPE_IP_PAIR_V6, expect_layer_type);
+ }
+ break;
+
+ case PPP_COMP:
+ case PPP_CCP:
+ case PPP_IPCP:
+ case PPP_PAP:
+ case PPP_CHAP:
+ case PPP_LQR:
+ case PPP_PROTOCOL_LCP:
+
+ /* ������Ӧ�ò�Э�� */
+ skip_len = -1;
+ break;
+
+ default:
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF, "ppp_jump_to_layer(): unsupport ppp pro:0x%x!", ntohs(ppp_data_hdr->protocol));
+ break;
+ }
+
+ if(skip_len < 0){
+ return -1;
+ }
+
+ return skip_len + sizeof(struct mesa_ppp_hdr);
+}
+
+static int pppoe_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ int skip_len = 0;
+ struct mesa_pppoe_session_hdr *pppoe_ses_hdr;
+ char *next_hdr;
+
+ if(raw_layer_type == expect_layer_type){
+ return 0;
+ }
+ pppoe_ses_hdr = (struct mesa_pppoe_session_hdr *)raw_data;
+ next_hdr = (char *)raw_data + sizeof(struct mesa_pppoe_session_hdr);
+
+ switch(ntohs(pppoe_ses_hdr->ppp_protocol)){
+ case PPP_PROTOCOL_IPv4:
+ if(__ADDR_TYPE_IP_PAIR_V4 == expect_layer_type){
+ break;
+ }else{
+ skip_len = ipv4_jump_to_layer(next_hdr, __ADDR_TYPE_IP_PAIR_V4, expect_layer_type);
+ }
+ break;
+
+ case PPP_IPV6:
+ if(__ADDR_TYPE_IP_PAIR_V6 == expect_layer_type){
+ break;
+ }else{
+ skip_len = ipv6_jump_to_layer(next_hdr, __ADDR_TYPE_IP_PAIR_V6, expect_layer_type);
+ }
+ break;
+
+ case PPP_COMP:
+ case PPP_CCP:
+ case PPP_IPCP:
+ case PPP_PAP:
+ case PPP_CHAP:
+ case PPP_LQR:
+ case PPP_PROTOCOL_LCP:
+
+ /* ������Ӧ�ò�Э�� */
+ skip_len = -1;
+ break;
+
+ default:
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF, "pppoe_jump_to_layer(): unsupport ppp pro:0x%x!", ntohs(pppoe_ses_hdr->ppp_protocol));
+ break;
+
+ }
+
+ if(skip_len < 0){
+ return -1;
+ }
+
+ return skip_len + sizeof(struct mesa_pppoe_session_hdr);
+}
+
+
+extern int __mjl_set_mpls_addr(struct layer_addr_mpls *addr, const unsigned char *raw_mpls_pkt_data);
+static int mpls_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ int skip_len = 0;
+ struct layer_addr_mpls mpls_addr = {};
+ const char *next_layer_data;
+ int mpls_layer_len;
+
+ if(raw_layer_type == expect_layer_type){
+ return 0;
+ }
+
+ __mjl_set_mpls_addr(&mpls_addr, (unsigned char *)raw_data);
+ mpls_layer_len = mpls_addr.c2s_layer_num * sizeof(struct mesa_mpls_hdr);
+ if(mpls_addr.c2s_has_ctrl_word){
+ mpls_layer_len += sizeof(int);
+ }
+
+ next_layer_data = raw_data + mpls_layer_len;
+
+ /* MPLSû���ֶα�ʶ��һ����ʲô, ���²���һ���IP���� */
+ if((*next_layer_data & 0xF0) == 0x40){
+ skip_len = ipv4_jump_to_layer(next_layer_data, __ADDR_TYPE_IP_PAIR_V4, expect_layer_type);
+ }else if((*next_layer_data & 0xF0) == 0x60){
+ skip_len = ipv6_jump_to_layer(next_layer_data, __ADDR_TYPE_IP_PAIR_V6, expect_layer_type);
+ }else{
+ /* VPLS�Ͳ���control wordһ������, ��__mjl_set_mpls_addr()������, �������Control word, next_layer_data�Ѿ����������ֽڵ�control word */
+ skip_len = eth_jump_to_layer(next_layer_data, ADDR_TYPE_MAC, expect_layer_type);
+ if(skip_len < 0){
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF,"WARNING: jmp unsupport type in MPLS to Ethernet, 0x%x!",
+ (unsigned char)(*next_layer_data));
+ return -1;
+ }
+ }
+
+ return skip_len + mpls_layer_len;
+}
+
+static int __common_eth_type_dispatch(UINT16 eth_type, const char *next_layer_data, int raw_layer_type, int expect_layer_type)
+{
+ int skip_len = 0;
+
+ switch(eth_type){
+ case ETH_P_ARP:
+ if(ADDR_TYPE_ARP == expect_layer_type){
+ break;
+ }else{
+ skip_len = arp_jump_to_layer(next_layer_data, ADDR_TYPE_ARP, expect_layer_type);
+ }
+ break;
+
+ case ETH_P_8021Q:
+ case ETH_P_8021AD:
+ if(ADDR_TYPE_VLAN == expect_layer_type){
+ break;
+ }else{
+ skip_len = vlan8021q_jump_to_layer(next_layer_data, ADDR_TYPE_VLAN, expect_layer_type);
+ }
+ break;
+
+ case ETH_P_IP:
+ if(__ADDR_TYPE_IP_PAIR_V4 == expect_layer_type){
+ break;
+ }else{
+ skip_len = ipv4_jump_to_layer(next_layer_data, __ADDR_TYPE_IP_PAIR_V4, expect_layer_type);
+ }
+ break;
+
+ case ETH_P_IPV6:
+ if(__ADDR_TYPE_IP_PAIR_V6 == expect_layer_type){
+ break;
+ }else{
+ skip_len = ipv6_jump_to_layer(next_layer_data, __ADDR_TYPE_IP_PAIR_V6, expect_layer_type);
+ }
+ break;
+
+ case ETH_P_PPP_SES:
+ if(ADDR_TYPE_PPPOE_SES == expect_layer_type){
+ break;
+ }else{
+ skip_len = pppoe_jump_to_layer(next_layer_data, ADDR_TYPE_PPPOE_SES, expect_layer_type);
+ }
+ break;
+
+ case ETH_P_MPLS_UC: /* MPLS, ETH_P_MPLS_UC */
+ skip_len = mpls_jump_to_layer(next_layer_data, ADDR_TYPE_MPLS, expect_layer_type);
+ break;
+
+ default:
+ skip_len = -1;
+ break;
+ }
+
+ return skip_len;
+}
+
+/* �����紫��ĵ�ַת��Ϊ�ڴ�ṹ, ����ҵ�������� */
+static int __mjl_vlan_addr_net_to_mem(const struct mesa_vlan_detail_hdr *net_vlan_hdr, struct single_layer_vlan_addr *mem_vlan_hdr)
+{
+ mem_vlan_hdr->VID = htons(net_vlan_hdr->vlan_id_high << 8 | net_vlan_hdr->vlan_id_low);
+ mem_vlan_hdr->TPID = net_vlan_hdr->type;
+ mem_vlan_hdr->PCP = net_vlan_hdr->priority;
+ mem_vlan_hdr->DEI = net_vlan_hdr->del_flag;
+
+ return 0;
+}
+
+static int __mjl_set_vlan_addr(struct layer_addr_vlan *addr, const unsigned char *vlan_tag)
+{
+ int i;
+ const struct mesa_vlan_detail_hdr *net_vhdr;
+ int vlan_layer_len = 0;
+
+ memset(addr, 0, sizeof(struct layer_addr_vlan));
+
+ for(i = 0; i < MAX_VLAN_ADDR_LAYER; i++){
+ net_vhdr = (struct mesa_vlan_detail_hdr *)vlan_tag;
+ //memcpy(&addr->c2s_addr_array[i], vlan_tag, sizeof(struct mesa_vlan_hdr));
+
+ __mjl_vlan_addr_net_to_mem(net_vhdr, &addr->c2s_addr_array[i]);
+ vlan_tag += sizeof(struct mesa_vlan_detail_hdr);
+ vlan_layer_len += sizeof(struct mesa_vlan_detail_hdr);
+ addr->c2s_layer_num++;
+ if(ETH_P_8021Q != ntohs(net_vhdr->type)){
+ break;
+ }
+ }
+
+ return vlan_layer_len;
+}
+
+static int vlan8021q_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ int skip_len = 0;
+ struct layer_addr_vlan vlan_addr;
+ const char *next_layer_data;
+ //const struct mesa_vlan_hdr *vhdr;
+ unsigned short next_layer_type;
+ int vlan_layer_len;
+
+ if(raw_layer_type == expect_layer_type){
+ return 0;
+ }
+
+ __mjl_set_vlan_addr(&vlan_addr, (const unsigned char *)raw_data);
+ vlan_layer_len = sizeof(struct mesa_vlan_hdr) * vlan_addr.c2s_layer_num;
+ next_layer_data = raw_data + vlan_layer_len;
+ //vhdr = (struct mesa_vlan_hdr *)&vlan_addr.c2s_addr_array[vlan_addr.c2s_layer_num-1];
+ next_layer_type = ntohs(vlan_addr.c2s_addr_array[vlan_addr.c2s_layer_num-1].TPID);
+
+ switch(next_layer_type){
+ case ETH_P_ARP:
+ if(ADDR_TYPE_ARP == expect_layer_type){
+ break;
+ }else{
+ skip_len = arp_jump_to_layer(next_layer_data, ADDR_TYPE_ARP, expect_layer_type);
+ }
+ break;
+
+ case ETH_P_IP:
+ if(__ADDR_TYPE_IP_PAIR_V4 == expect_layer_type){
+ break;
+ }else{
+ skip_len = ipv4_jump_to_layer(next_layer_data, __ADDR_TYPE_IP_PAIR_V4, expect_layer_type);
+ }
+ break;
+
+ case ETH_P_IPV6:
+ if(__ADDR_TYPE_IP_PAIR_V6 == expect_layer_type){
+ break;
+ }else{
+ skip_len = ipv6_jump_to_layer(next_layer_data, __ADDR_TYPE_IP_PAIR_V6, expect_layer_type);
+ }
+ break;
+
+ case ETH_P_PPP_SES:
+ if(ADDR_TYPE_PPPOE_SES == expect_layer_type){
+ break;
+ }else{
+ skip_len = pppoe_jump_to_layer(next_layer_data, ADDR_TYPE_PPPOE_SES, expect_layer_type);
+ }
+ break;
+
+ case ETH_P_PPP_DISC: /* pppoe���ֽ׶� */
+ skip_len = -1;
+ break;
+
+ /* QinQ */
+ case ETH_P_8021Q:
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF, "vlan8021q_jump_to_layer(): multiple VLAN combine to one layer!");
+ assert(0);
+ break;
+
+ case ETH_P_MPLS_UC:
+ skip_len = mpls_jump_to_layer(next_layer_data, ADDR_TYPE_MPLS, expect_layer_type);
+ break;
+
+ default:
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF, "vlan8021q_jump_to_layer(): unsupport type: 0x%x!", next_layer_type);
+ skip_len = -1;
+ }
+
+ if(skip_len < 0){
+ return -1;
+ }
+
+ return skip_len + vlan_layer_len;
+}
+
+static int eth_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ struct ethhdr *p_eth_hdr = (struct ethhdr *)raw_data;
+ unsigned short eth_type = ntohs(p_eth_hdr->h_proto);
+ //int skip_len = -1;
+ const char *next_layer_data = raw_data + sizeof(struct ethhdr);
+ int layer_skip_len;
+
+ if(raw_layer_type == expect_layer_type){
+ return 0;
+ }
+
+ layer_skip_len = __common_eth_type_dispatch(eth_type, next_layer_data, raw_layer_type, expect_layer_type);
+ if(layer_skip_len < 0){
+ return -1;
+ }
+
+ return layer_skip_len + sizeof(struct ethhdr);
+}
+
+
+static int mac_in_mac_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ struct ethhdr *inner_eth_hdr = (struct ethhdr *)(raw_data + sizeof(struct ethhdr ));
+ unsigned short inner_eth_type = ntohs(inner_eth_hdr->h_proto);
+ //int skip_len = -1;
+ const char *next_layer_data = raw_data + sizeof(struct ethhdr);
+ int layer_skip_len;
+
+ if(raw_layer_type == expect_layer_type){
+ return 0;
+ }
+
+ layer_skip_len = __common_eth_type_dispatch(inner_eth_type, next_layer_data, raw_layer_type, expect_layer_type);
+ if(layer_skip_len < 0){
+ return -1;
+ }
+
+ return layer_skip_len + sizeof(struct ethhdr) * 2;
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ return value:
+ Non-NULL: the pointer to expect layer;
+ NULL: not found expect layer.
+*/
+const void *MESA_net_jump_to_layer(const void *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ int ret;
+
+ if(check_layer_type(raw_layer_type) < 0){
+ return NULL;
+ }
+
+ if(check_layer_type(expect_layer_type) < 0){
+ return NULL;
+ }
+
+ if(ADDR_TYPE_IPV4 == raw_layer_type){
+ /* ת�ɴ�IPv4��ַ���� */
+ raw_layer_type = __ADDR_TYPE_IP_PAIR_V4;
+ }
+
+ if(ADDR_TYPE_IPV6 == raw_layer_type){
+ /* ת�ɴ�IPv6��ַ���� */
+ raw_layer_type = __ADDR_TYPE_IP_PAIR_V6;
+ }
+
+ if(ADDR_TYPE_IPV4 == expect_layer_type){
+ /* ת�ɴ�IPv4��ַ���� */
+ expect_layer_type = __ADDR_TYPE_IP_PAIR_V4;
+ }
+
+ if(ADDR_TYPE_IPV6 == expect_layer_type){
+ /* ת�ɴ�IPv6��ַ���� */
+ expect_layer_type = __ADDR_TYPE_IP_PAIR_V6;
+ }
+
+ if(raw_layer_type == expect_layer_type){
+ return raw_data;
+ }
+
+ switch(raw_layer_type){
+ case ADDR_TYPE_MAC:
+ ret = eth_jump_to_layer((const char *)raw_data, raw_layer_type, expect_layer_type);
+ break;
+
+ case ADDR_TYPE_ARP:
+ ret = arp_jump_to_layer((const char *)raw_data, raw_layer_type, expect_layer_type);
+ break;
+ case ADDR_TYPE_VLAN:
+ ret = vlan8021q_jump_to_layer((const char *)raw_data, raw_layer_type, expect_layer_type);
+ break;
+
+ case __ADDR_TYPE_IP_PAIR_V4:
+ ret = ipv4_jump_to_layer((const char *)raw_data, raw_layer_type, expect_layer_type);
+ break;
+
+ case __ADDR_TYPE_IP_PAIR_V6:
+ ret = ipv6_jump_to_layer((const char *)raw_data, raw_layer_type, expect_layer_type);
+ break;
+
+ case ADDR_TYPE_MAC_IN_MAC:
+ ret = mac_in_mac_jump_to_layer((const char *)raw_data, raw_layer_type, expect_layer_type);
+ break;
+
+ case ADDR_TYPE_UDP:
+ ret = udp_jump_to_layer((const char *)raw_data, raw_layer_type, expect_layer_type);
+ break;
+
+ case ADDR_TYPE_MPLS:
+ ret = mpls_jump_to_layer((const char *)raw_data, raw_layer_type, expect_layer_type);
+ break;
+
+ case ADDR_TYPE_GRE:
+ ret = gre_jump_to_layer((const char *)raw_data, raw_layer_type, expect_layer_type);
+ break;
+
+ case ADDR_TYPE_PPPOE_SES:
+ return NULL;
+ break;
+
+ default:
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF, "MESA_net_jump_to_layer(): unsupport raw_layer_type:%d in MESA_net_jump_to_layer()!", raw_layer_type);
+ return NULL;
+ }
+
+ if(ret < 0){
+ return NULL;
+ }
+
+ return ((const char *)raw_data + ret);
+}
+
+/*
+ ��MESA_net_jump_to_layer()������:
+ MESA_net_jump_to_layer()������㿪ʼ, �ҵ���һ�����������IJ���˳�;
+ MESA_net_jump_to_layer_greedy()��һֱ���������ڲ�Э��ͷ, �ʺ�����ģʽ.
+
+ return value:
+ Non-NULL: the pointer to expect layer;
+ NULL: not found expect layer.
+*/
+const void *MESA_net_jump_to_layer_greedy(const void *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ int skip_len;
+ const void *expect_layer;
+ const void *success_layer = NULL; /* ���һ�γɹ��ҵ��IJ� */
+ int new_raw_layer_type = raw_layer_type; /* ����ת������, ���ܻ�����м����Ϣ */
+ const char *new_next_layer_data = (char *)raw_data;
+
+ if(ADDR_TYPE_IPV4 == raw_layer_type){
+ /* ת�ɴ�IPv4��ַ���� */
+ raw_layer_type = __ADDR_TYPE_IP_PAIR_V4;
+ }
+
+ if(ADDR_TYPE_IPV6 == raw_layer_type){
+ /* ת�ɴ�IPv6��ַ���� */
+ raw_layer_type = __ADDR_TYPE_IP_PAIR_V6;
+ }
+
+ if(ADDR_TYPE_IPV4 == expect_layer_type){
+ /* ת�ɴ�IPv4��ַ���� */
+ expect_layer_type = __ADDR_TYPE_IP_PAIR_V4;
+ }
+
+ if(ADDR_TYPE_IPV6 == expect_layer_type){
+ /* ת�ɴ�IPv6��ַ���� */
+ expect_layer_type = __ADDR_TYPE_IP_PAIR_V6;
+ }
+
+ expect_layer = MESA_net_jump_to_layer(new_next_layer_data, new_raw_layer_type, expect_layer_type);
+ while(expect_layer){
+ success_layer = expect_layer;
+
+ switch(expect_layer_type){
+ case __ADDR_TYPE_IP_PAIR_V4:
+ {
+ const struct mesa_ip4_hdr *ip4hdr = (const struct mesa_ip4_hdr *)expect_layer;
+ if((ntohs(ip4hdr->ip_off) & IP_MF ) || (ntohs(ip4hdr->ip_off) & IP_OFFMASK)){
+ /* IP��Ƭ���ټ������ڲ���ת */
+ goto done;
+ }
+ if(IPPROTO_UDP == ip4hdr->ip_p){
+ new_next_layer_data = (char *)expect_layer + ip4hdr->ip_hl * 4;
+ new_raw_layer_type = ADDR_TYPE_UDP; /* IP���������һ��ƫ�� */
+ }else if(IPPROTO_GRE == ip4hdr->ip_p){
+ new_next_layer_data = (char *)expect_layer + ip4hdr->ip_hl * 4;
+ new_raw_layer_type = ADDR_TYPE_GRE; /* GRE */
+ }else{
+ //TODO 2, IPIP, L2TPv3
+ goto done;
+ }
+ }
+ break;
+
+ case __ADDR_TYPE_IP_PAIR_V6:
+ {
+ //TODO2,
+ goto done;
+ }
+ break;
+
+ case ADDR_TYPE_UDP:
+ {
+ skip_len = udp_jump_to_layer_greedy((char *)expect_layer, ADDR_TYPE_UDP, expect_layer_type);
+ if(skip_len < 0){
+ goto done;
+ }
+
+ success_layer = (char *)expect_layer + skip_len;
+ goto done;
+ }
+ break;
+
+ default:
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF, "MESA_net_jump_to_layer_greedy() not support layer type:%d\n", expect_layer_type);
+ goto done;
+ }
+
+ expect_layer = MESA_net_jump_to_layer(new_next_layer_data, new_raw_layer_type, expect_layer_type);
+ }
+
+done:
+ return success_layer;
+}
+
+/* ģ��tcpdump��ʽ: 192.168.40.137.22 > 192.168.36.40.49429 */
+const char *MESA_jump_layer_ipv4_ntop(const struct ip *ip4_hdr, char *out_buf, int buf_len )
+{
+ unsigned char inner_ip_proto;
+ const struct mesa_tcp_hdr *inner_thdr = NULL;
+ const struct mesa_udp_hdr *inner_uhdr = NULL;
+ unsigned short sport, dport;
+ char ipsrc_str[INET6_ADDRSTRLEN];
+ char ipdst_str[INET6_ADDRSTRLEN];
+
+ inner_ip_proto = ip4_hdr->ip_p;
+ if(IPPROTO_TCP == inner_ip_proto){
+ inner_thdr = (struct mesa_tcp_hdr *)((char *)ip4_hdr + ip4_hdr->ip_hl*4);
+ sport = ntohs(inner_thdr->th_sport);
+ dport = ntohs(inner_thdr->th_dport);
+ }else if(IPPROTO_UDP){
+ inner_uhdr = (struct mesa_udp_hdr *)((char *)ip4_hdr + ip4_hdr->ip_hl*4);
+ sport = ntohs(inner_uhdr->uh_sport);
+ dport = ntohs(inner_uhdr->uh_dport);
+ }else{
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF, "MESA_jump_layer_ipv4_ntop() error, unsupport ip protocol:%d", inner_ip_proto);
+ return NULL;
+ }
+
+ inet_ntop(AF_INET, &ip4_hdr->ip_src.s_addr, ipsrc_str, sizeof(ipsrc_str));
+ inet_ntop(AF_INET, &ip4_hdr->ip_dst.s_addr, ipdst_str, sizeof(ipdst_str));
+
+ snprintf(out_buf, buf_len, "%s.%u > %s.%u", ipsrc_str, sport, ipdst_str, dport);
+
+ return out_buf;
+}
+
+
+const char *MESA_jump_layer_ipv6_ntop(const struct ip6_hdr *ip6_hdr, char *out_buf, int buf_len)
+{
+ unsigned char inner_ip_proto;
+ const struct tcphdr *inner_thdr = NULL;
+ const struct udphdr *inner_uhdr = NULL;
+ unsigned short sport, dport;
+ char ipsrc_str[INET6_ADDRSTRLEN];
+ char ipdst_str[INET6_ADDRSTRLEN];
+
+ /* TODO: �˴��п��ܰ���ѡ�����Ƭ, ����ֱ�ӻ�ȡ��һ���Э������, ��˴��������Ͻ�! */
+ inner_ip_proto = ip6_hdr->ip6_nxt;
+ if(IPPROTO_TCP == inner_ip_proto){
+ inner_thdr = (struct tcphdr *)((char *)ip6_hdr + sizeof(struct ip6_hdr));
+ sport = inner_thdr->source;
+ dport = inner_thdr->dest;
+ }else if(IPPROTO_UDP){
+ inner_uhdr = (struct udphdr *)((char *)ip6_hdr + sizeof(struct ip6_hdr));
+ sport = inner_uhdr->source;
+ dport = inner_uhdr->dest;
+ }else{
+ snprintf(_g_mesa_jump_layer_last_error, PIPE_BUF, "MESA_jump_layer_ipv6_ntop() error, unsupport ip6_nxt_hdr:%d", inner_ip_proto);
+ return NULL;
+ }
+
+ inet_ntop(AF_INET6, &ip6_hdr->ip6_src, ipsrc_str, sizeof(ipsrc_str));
+ inet_ntop(AF_INET6, &ip6_hdr->ip6_dst, ipdst_str, sizeof(ipdst_str));
+
+ snprintf(out_buf, buf_len, "%s.%u > %s.%u", ipsrc_str, sport, ipdst_str, dport);
+
+ return out_buf;
+}
+
+const char *MESA_jump_layer_get_last_error(void)
+{
+ return _g_mesa_jump_layer_last_error;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..38a95cc
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,10 @@
+INC=-I../inc -I/opt/MESA/include -I/opt/MESA/include/MESA -I/opt/MESA/include/MESA/stream_inc
+CFLAGS=-g -Wall
+
+all:libMESA_jump_layer.so
+
+libMESA_jump_layer.so:MESA_jump_layer.o
+ g++ -o $@ $^ -fPIC -shared
+
+MESA_jump_layer.o:MESA_jump_layer.cpp
+ g++ -c -fPIC -o $@ $^ $(INC) $(CFLAGS)
diff --git a/src/deal_ipv6.h b/src/deal_ipv6.h
new file mode 100644
index 0000000..9fe520f
--- /dev/null
+++ b/src/deal_ipv6.h
@@ -0,0 +1,113 @@
+#ifndef __DEAL_IPV6_H_
+#define __DEAL_IPV6_H_
+
+#include <netinet/ip6.h>
+
+#define IPV6_DEBUG (0)
+
+#define IPV6_FRAG_DUMP (1 && IPV6_DEBUG)
+
+#define IPV6_MAXPLEN (65535)
+
+#define IPV6_FRAG_RESERVED_HDR_LEN (40) /* Ԥ����һ��IPv6��Ƭͷ������ */
+
+//#define IPV6_FRAG_TIMEOUT (60) /* ���鳬ʱʱ�� */
+/*
+ 2015-12-02 lijia modify,
+ ��ȻRFC�涨, 60�������з�Ƭ������ɾ��ǺϷ���,
+ ���ʵ�����, IPv6��Ƭ�����10���ڻ�δ�������, ����Ϊ�ǹ�����Ϊ�򶪰�, ֱ��free.
+*/
+#define IPV6_FRAG_TIMEOUT (10) /* ���鳬ʱʱ�� */
+
+
+#define IPV6_FRAG_MEM_FREE_ONCE (512*1024) /* ÿ���ͷ��ڴ����� */
+#define IPV6_FRAG_MEM_HIGH_THRESH (16*1024*1024) /* �ڴ����� */
+
+#define IPV6_FRAG_NUM_PER_IPQ (100) /* ͬһIPQ����Ƭ���� */
+
+#if IPV6_DEBUG
+#define IPV6_PRINT(fmt, args...) printf(fmt, ##args)
+#else
+#define IPV6_PRINT(fmt, args...)
+#endif
+
+
+struct simple_ip6_hdr
+{
+ unsigned char ip6_flags[4]; /* version, traffic-class, flow-label */
+ u_int16_t ip6_payload_len; /* payload length, not contain header */
+ unsigned char ip6_nxt_hdr; /* next header, same as protocol in IPv4 */
+ unsigned char ip6_hop; /* hop limit, same as TTL in IPv4 */
+ struct in6_addr ip6_src; /* source address */
+ struct in6_addr ip6_dst; /* dest address */
+};
+
+
+/*
+ * NextHeader field of IPv6 header
+ */
+#define NEXTHDR_HOP 0 /* Hop-by-hop option header. */
+#define NEXTHDR_IPIP 4 /* IPIP header. */
+#define NEXTHDR_TCP 6 /* TCP segment. */
+#define NEXTHDR_UDP 17 /* UDP message. */
+#define NEXTHDR_IPV6 41 /* IPv6 in IPv6 */
+#define NEXTHDR_ROUTING 43 /* Routing header. */
+#define NEXTHDR_FRAGMENT 44 /* Fragmentation/reassembly header. */
+#define NEXTHDR_ESP 50 /* Encapsulating security payload. */
+#define NEXTHDR_AUTH 51 /* Authentication header. */
+#define NEXTHDR_ICMP 58 /* ICMP for IPv6. */
+#define NEXTHDR_NONE 59 /* No next header */
+#define NEXTHDR_DEST 60 /* Destination options header. */
+#define NEXTHDR_MOBILITY 135 /* Mobility header. */
+
+struct ipv6_opt_hdr{
+ unsigned char nexthdr;
+ unsigned char hdrlen;
+ /*
+ * TLV encoded option data follows.
+ */
+} __attribute__((packed)); /* required for some archs */
+
+
+
+/*
+ * Hop-By-Hop header
+ */
+struct ipv6_hop_hdr{
+ unsigned char nexthdr;
+ unsigned char hdrlen;
+};
+
+
+/*
+ * fragmentation header
+ */
+
+#define IPv6_FRAG_ISF (1) /* ������һ����Ƭ�� */
+#define IPv6_FRAG_NEW (2) /* ���յ����з�Ƭ��������ɵ��°� */
+
+#define IP6_MF (0x0001)
+
+struct ipv6_frag_hdr{
+ unsigned char nexthdr;
+ unsigned char reserved;
+ unsigned short frag_off;
+ unsigned int identification;
+};
+
+struct ipv6_frag_key{
+ unsigned int identification; /* ���п��ܲ�ͬ��ֵ���ڽṹ��ǰ�棬�Ƚ�ʱ���һЩ */
+ int __pad__; /* ����ṹ8�ֽڶ��� */
+ struct in6_addr ip6_src; /* source address */
+ struct in6_addr ip6_dst; /* dest address */
+ struct streaminfo_private *pfstream_pr;
+};
+
+struct ipv6_frag_private{
+ unsigned char raw_next_hdr; /* ԭʼIP���ĵ�һ���ɷ�Ƭ����ͷ������ */
+ int unfragmentable_len; /* ԭʼIP���IJ��ɷ�Ƭ���ֳ��� */
+};
+
+
+#endif
+
diff --git a/src/mesa_net.h b/src/mesa_net.h
new file mode 100644
index 0000000..f0319f8
--- /dev/null
+++ b/src/mesa_net.h
@@ -0,0 +1,885 @@
+#ifndef _MESA_NET_H_
+#define _MESA_NET_H_
+
+#include <stdio.h>
+#include <endian.h>
+#include <netinet/in.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/in_systm.h>
+#include <linux/ppp_defs.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define BYTE_ALIGNED(n) __attribute__((packed, aligned(n)))
+
+
+#define SENDPACKET_ARP_H 0x1c /* ARP header: 28 bytes */
+#define SENDPACKET_ETH_H 0xe /* Etherner header: 14 bytes */
+#define SENDPACKET_IP_H 0x14 /* IP header: 20 bytes */
+/* See sendpacket-ospf.h for OSPF related header sizes */
+#define SENDPACKET_RIP_H 0x18 /* RIP header base: 24 bytes */
+#define SENDPACKET_TCP_H 0x14 /* TCP header: 20 bytes */
+#define SENDPACKET_UDP_H 0x8 /* UDP header: 8 bytes */
+
+/*
+ * Ethernet packet header prototype. Too many O/S's define this differently.
+ * Easy enough to solve that and define it here.
+ */
+#ifndef ETHER_ADDR_LEN
+#define ETHER_ADDR_LEN 6
+#endif
+#define ETHERTYPE_PUP 0x0200 /* PUP protocol */
+#define ETHERTYPE_IP 0x0800 /* IP protocol */
+#define ETHERTYPE_IPv6 0x86dd /* IPv6 protocol */
+#define ETHERTYPE_ARP 0x0806 /* Addr. resolution protocol */
+#define ETHERTYPE_REVARP 0x8035 /* reverse Addr. resolution protocol */
+#define ETHERTYPE_VLAN 0x8100 /* IEEE 802.1Q VLAN tagging */
+#define ETHERTYPE_LOOPBACK 0x9000 /* used to test interfaces */
+
+//#define ETH_P_8021AD 0x88A8
+//#define ETHERTYPE_PANGU_MAC_IN_MAC 0x88A8 /* 2018-08-16 lijia add, for pangu MAC-in-MAC */
+
+
+
+#define ETHERNET_HDR_LEN (14)
+struct mesa_ethernet_hdr
+{
+ u_int8_t ether_dhost[ETHER_ADDR_LEN]; /* destination ethernet address */
+ u_int8_t ether_shost[ETHER_ADDR_LEN]; /* source ethernet address */
+ u_int16_t ether_type; /* packet type ID */
+}BYTE_ALIGNED(1);
+
+
+/*
+ * IPv4 packet header prototype.
+ */
+#ifndef IP_RF
+#define IP_RF 0x8000 /* reserved fragment flag */
+#endif
+#ifndef IP_DF
+#define IP_DF 0x4000 /* dont fragment flag */
+#endif
+#ifndef IP_MF
+#define IP_MF 0x2000 /* more fragments flag */
+#endif
+#ifndef IP_OFFMASK
+#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
+#endif
+
+
+#define IPPROTO_L2TPV3 (115) /* L2TPv3, RFC3931-page17 */
+
+struct mesa_ip4_hdr
+{
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ u_int8_t ip_hl:4, /* header length */
+ ip_v:4; /* version */
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ u_int8_t ip_v:4, /* version */
+ ip_hl:4; /* header length */
+#else
+#error "Please check <endian.h>"
+#endif
+ u_int8_t ip_tos; /* type of service */
+ u_int16_t ip_len; /* total length */
+ u_int16_t ip_id; /* identification */
+ u_int16_t ip_off;
+ u_int8_t ip_ttl; /* time to live */
+ u_int8_t ip_p; /* protocol */
+ u_int16_t ip_sum; /* checksum */
+ struct in_addr ip_src, ip_dst; /* source and dest address */
+};
+
+
+/*
+ * ARP packet header prototype. Too many O/S's define this differently.
+ * Easy enough to solve that and define it here.
+ */
+#define ARPOP_REQUEST 1 /* req to resolve address */
+#define ARPOP_REPLY 2 /* resp to previous request */
+#define ARPOP_REVREQUEST 3 /* req protocol address given hardware */
+#define ARPOP_REVREPLY 4 /* resp giving protocol address */
+#define ARPOP_INVREQUEST 8 /* req to identify peer */
+#define ARPOP_INVREPLY 9 /* resp identifying peer */
+
+
+#define ARPHRD_ETHER 1 /* ethernet hardware format */
+struct mesa_arp_hdr
+{
+ u_short ar_hrd; /* format of hardware address */
+
+ u_short ar_pro; /* format of protocol address */
+ u_char ar_hln; /* length of hardware address */
+ u_char ar_pln; /* length of protocol addres */
+ u_short ar_op; /* operation type */
+
+ /*
+ * These should implementation defined but I've hardcoded eth/IP.
+ */
+ u_char ar_sha[6]; /* sender hardware address */
+ u_char ar_spa[4]; /* sender protocol address */
+ u_char ar_tha[6]; /* target hardware address */
+ u_char ar_tpa[4]; /* target protocol address */
+};
+
+
+/*
+ * IPv6 packet header prototype, add by LiJia 2012-03-19.
+ */
+struct mesa_ip6_hdr
+{
+ u_int8_t ip6_flags[4]; /* version, traffic-class, flow-label */
+ u_int16_t ip6_payload_len; /* payload length, not contain header */
+ u_int8_t ip6_nxt_hdr; /* next header, same as protocol in IPv4 */
+ u_int8_t ip6_hop; /* hop limit, same as TTL in IPv4 */
+ struct in6_addr ip6_src; /* source address */
+ struct in6_addr ip6_dst; /* dest address */
+};
+
+
+struct mesa_icmp_echo_hdr{
+ unsigned char icmp_type;
+ unsigned char icmp_code;
+ unsigned short icmp_cksum;
+ unsigned short icd_id;
+ unsigned short icd_seq;
+ //char echo_data[];
+};
+
+
+/*
+ * ICMP packet header prototype. // from libnet-headers.h
+ */
+struct mesa_icmp_hdr
+{
+ u_char icmp_type;
+/*
+ * ICMP types.
+ */
+#ifndef ICMP_ECHOREPLY
+#define ICMP_ECHOREPLY 0
+#endif
+#ifndef ICMP_UNREACH
+#define ICMP_UNREACH 3
+#endif
+#ifndef ICMP_SOURCEQUENCH
+#define ICMP_SOURCEQUENCH 4
+#endif
+#ifndef ICMP_REDIRECT
+#define ICMP_REDIRECT 5
+#endif
+#ifndef ICMP_ECHO
+#define ICMP_ECHO 8
+#endif
+#ifndef ICMP_ROUTERADVERT
+#define ICMP_ROUTERADVERT 9
+#endif
+#ifndef ICMP_ROUTERSOLICIT
+#define ICMP_ROUTERSOLICIT 10
+#endif
+#ifndef ICMP_TIMXCEED
+#define ICMP_TIMXCEED 11
+#endif
+#ifndef ICMP_PARAMPROB
+#define ICMP_PARAMPROB 12
+#endif
+#ifndef ICMP_TSTAMP
+#define ICMP_TSTAMP 13
+#endif
+#ifndef ICMP_TSTAMPREPLY
+#define ICMP_TSTAMPREPLY 14
+#endif
+#ifndef ICMP_IREQ
+#define ICMP_IREQ 15
+#endif
+#ifndef ICMP_IREQREPLY
+#define ICMP_IREQREPLY 16
+#endif
+#ifndef ICMP_MASKREQ
+#define ICMP_MASKREQ 17
+#endif
+#ifndef ICMP_MASKREPLY
+#define ICMP_MASKREPLY 18
+#endif
+ u_char icmp_code;
+/*
+ * ICMP codes.
+ */
+#ifndef ICMP_UNREACH_NET
+#define ICMP_UNREACH_NET 0
+#endif
+#ifndef ICMP_UNREACH_HOST
+#define ICMP_UNREACH_HOST 1
+#endif
+#ifndef ICMP_UNREACH_PROTOCOL
+#define ICMP_UNREACH_PROTOCOL 2
+#endif
+#ifndef ICMP_UNREACH_PORT
+#define ICMP_UNREACH_PORT 3
+#endif
+#ifndef ICMP_UNREACH_NEEDFRAG
+#define ICMP_UNREACH_NEEDFRAG 4
+#endif
+#ifndef ICMP_UNREACH_SRCFAIL
+#define ICMP_UNREACH_SRCFAIL 5
+#endif
+#ifndef ICMP_UNREACH_NET_UNKNOWN
+#define ICMP_UNREACH_NET_UNKNOWN 6
+#endif
+#ifndef ICMP_UNREACH_HOST_UNKNOWN
+#define ICMP_UNREACH_HOST_UNKNOWN 7
+#endif
+#ifndef ICMP_UNREACH_ISOLATED
+#define ICMP_UNREACH_ISOLATED 8
+#endif
+#ifndef ICMP_UNREACH_NET_PROHIB
+#define ICMP_UNREACH_NET_PROHIB 9
+#endif
+#ifndef ICMP_UNREACH_HOST_PROHIB
+#define ICMP_UNREACH_HOST_PROHIB 10
+#endif
+#ifndef ICMP_UNREACH_TOSNET
+#define ICMP_UNREACH_TOSNET 11
+#endif
+#ifndef ICMP_UNREACH_TOSHOST
+#define ICMP_UNREACH_TOSHOST 12
+#endif
+#ifndef ICMP_UNREACH_FILTER_PROHIB
+#define ICMP_UNREACH_FILTER_PROHIB 13
+#endif
+#ifndef ICMP_UNREACH_HOST_PRECEDENCE
+#define ICMP_UNREACH_HOST_PRECEDENCE 14
+#endif
+#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
+#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15
+#endif
+#ifndef ICMP_REDIRECT_NET
+#define ICMP_REDIRECT_NET 0
+#endif
+#ifndef ICMP_REDIRECT_HOST
+#define ICMP_REDIRECT_HOST 1
+#endif
+#ifndef ICMP_REDIRECT_TOSNET
+#define ICMP_REDIRECT_TOSNET 2
+#endif
+#ifndef ICMP_REDIRECT_TOSHOST
+#define ICMP_REDIRECT_TOSHOST 3
+#endif
+#ifndef ICMP_TIMXCEED_INTRANS
+#define ICMP_TIMXCEED_INTRANS 0
+#endif
+#ifndef ICMP_TIMXCEED_REASS
+#define ICMP_TIMXCEED_REASS 1
+#endif
+#ifndef ICMP_PARAMPROB_OPTABSENT
+#define ICMP_PARAMPROB_OPTABSENT 1
+#endif
+
+ u_short icmp_sum;
+
+ union
+ {
+ struct
+ {
+ u_short id;
+ u_short seq;
+ }echo;
+
+#undef icmp_id
+#undef icmp_seq
+#define icmp_id hun.echo.id
+#define icmp_seq hun.echo.seq
+
+ u_long gateway;
+ struct
+ {
+ u_short pad;
+ u_short mtu;
+ }frag;
+ }hun;
+ union
+ {
+ struct
+ {
+ n_time its_otime;
+ n_time its_rtime;
+ n_time its_ttime;
+ }ts;
+ struct
+ {
+ struct ip idi_ip;
+ /* options and then 64 bits of data */
+ }ip;
+ u_long mask;
+ char data[1];
+
+#undef icmp_mask
+#define icmp_mask dun.mask
+#undef icmp_data
+#define icmp_data dun.data
+
+#undef icmp_otime
+#define icmp_otime dun.ts.its_otime
+#undef icmp_rtime
+#define icmp_rtime dun.ts.its_rtime
+#undef icmp_ttime
+#define icmp_ttime dun.ts.its_ttime
+ }dun;
+
+};
+
+/*
+ * TCP packet header prototype.
+ */
+#ifndef TH_FIN
+#define TH_FIN 0x01
+#endif
+#ifndef TH_SYN
+#define TH_SYN 0x02
+#endif
+#ifndef TH_RST
+#define TH_RST 0x04
+#endif
+#ifndef TH_PUSH
+#define TH_PUSH 0x08
+#endif
+#ifndef TH_ACK
+#define TH_ACK 0x10
+#endif
+#ifndef TH_URG
+#define TH_URG 0x20
+#endif
+struct mesa_tcp_hdr
+{
+ u_int16_t th_sport; /* source port */
+ u_int16_t th_dport; /* destination port */
+ u_int32_t th_seq; /* sequence number */
+ u_int32_t th_ack; /* acknowledgement number */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ u_int8_t th_x2:4, /* (unused) */
+ th_off:4; /* data offset */
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ u_int8_t th_off:4, /* data offset */
+ th_x2:4; /* (unused) */
+#else
+#error "Please check <endian.h>"
+#endif
+ u_int8_t th_flags; /* control flags */
+ u_int16_t th_win; /* window */
+ u_int16_t th_sum; /* checksum */
+ u_int16_t th_urp; /* urgent pointer */
+};
+
+
+/*
+ * UDP packet header prototype.
+ */
+struct mesa_udp_hdr
+{
+ u_int16_t uh_sport; /* soure port */
+ u_int16_t uh_dport; /* destination port */
+ u_int16_t uh_ulen; /* length */
+ u_int16_t uh_sum; /* checksum */
+};
+
+
+#define PPPOE_HDR_LEN (sizeof(struct mesa_pppoe_session_hdr))
+#define PPP_PROTOCOL_PAD (0x0001)
+#define PPP_PROTOCOL_IPv4 (0x0021)
+#define PPP_PROTOCOL_PAP (0xC023)
+#define PPP_PROTOCOL_CHAP (0xC223)
+#define PPP_PROTOCOL_IPv6 (0x0057)
+#define PPP_COMPRESS_DATA (0x00FD)
+
+#define PPP_PROTOCOL_LCP (0xC021)
+#define PPP_PROTOCOL_CCP (0x80FD)
+#define PPP_PROTOCOL_IPCP (0x8021)
+
+struct mesa_pppoe_session_hdr{
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned int ver:4;
+ unsigned int type:4;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int type:4;
+ unsigned int ver:4;
+#else
+#error "Please check <endian.h>"
+#endif
+ unsigned char code;
+ unsigned short session_id;
+ unsigned short len;
+ /* to do:
+ pppӦ�õ�����Ϊһ�����, Ϊ�˼򻯴���, ǿ�ƽ����PPPOE_SES����һ��,
+ �����Ҫ����PPPЭ�̹���, �˽ṹ��Ҫ�Ķ�.
+ */
+ unsigned short ppp_protocol;
+}BYTE_ALIGNED(1);
+
+
+struct mesa_ppp_hdr{
+ unsigned char address;
+ unsigned char control;
+ unsigned short protocol;
+}BYTE_ALIGNED(1);
+
+#define PPP_LCP_CODE_REQUEST (1)
+#define PPP_LCP_CODE_ACK (2)
+#define PPP_LCP_CODE_NAK (3)
+#define PPP_LCP_CODE_REJECT (4)
+#define PPP_LCP_CODE_TERMINATE_REQ (5)
+#define PPP_LCP_CODE_TERMINATE_ACK (6)
+
+/* refer to RFC1661 */
+#define PPP_LCP_OPT_RESERVED (0)
+#define PPP_LCP_OPT_MAX_RCV_UNIT (1)
+#define PPP_LCP_OPT_AUTH_PRO (3)
+#define PPP_LCP_OPT_QA_PRO (4)
+#define PPP_LCP_OPT_MAGIC (5)
+#define PPP_LCP_OPT_PRO_FIELD_COMPRESS (7)
+#define PPP_LCP_OPT_ADDR_CTRL_FIELD_COMPRESS (8)
+
+#define PPP_LCP_OPT_AUTH_PRO_PAP (0xC023)
+#define PPP_LCP_OPT_AUTH_PRO_CHAP (0xC223)
+
+#define PPP_LCP_OPT_AUTH_PRO_CHAP_ALGO_MS_CHAP_V2 (0x81)
+#define PPP_LCP_OPT_AUTH_PRO_CHAP_ALGO_CHAP_MD5 (0x05)
+
+
+/* refer to RFC1962 Page6 */
+#define PPP_CCP_OPT_OUI (0)
+#define PPP_CCP_OPT_MS_PPC (18)
+
+struct mesa_ppp_lcp_ack_hdr{ /* RFC1661-Page29 */
+ unsigned char code;
+ unsigned char identifier;
+ unsigned short length;
+}BYTE_ALIGNED(1);
+
+struct mesa_ppp_ccp_ack_hdr{ /* RFC1661-Page29 */
+ unsigned char code;
+ unsigned char identifier;
+ unsigned short length;
+}BYTE_ALIGNED(1);
+
+#define PPP_CHAP_CHALLENGE (1)
+#define PPP_CHAP_RESPONSE (2)
+#define PPP_CHAP_SUCCESS (3)
+#define PPP_CHAP_FAILURE (4)
+
+struct mesa_ppp_chap_hdr{
+ unsigned char code;
+ unsigned char identifier;
+ unsigned short length;
+}BYTE_ALIGNED(1);
+
+struct mesa_ppp_ipcp_ack_hdr{
+ unsigned char code;
+ unsigned char identifier;
+ unsigned short length;
+}BYTE_ALIGNED(1);
+
+enum pptp_control_message_type{
+ PPTP_CTRL_START_CONN_REQ = 1,
+ PPTP_CTRL_START_CONN_REPLY = 2,
+ PPTP_CTRL_STOP_CONN_REQ = 3,
+ PPTP_CTRL_STOP_CONN_REPLY = 4,
+ PPTP_CTRL_ECHO_REQ = 5,
+ PPTP_CTRL_ECHO_REPLY = 6,
+ PPTP_CTRL_OUT_GO_REQ = 7,
+ PPTP_CTRL_OUT_GO_REPLY = 8,
+ PPTP_CTRL_IN_CALL_REQ = 9,
+ PPTP_CTRL_IN_CALL_REPLY = 10,
+ PPTP_CTRL_IN_CALL_CONN = 11,
+ PPTP_CTRL_CALL_CLEAR_REQ = 12,
+ PPTP_CTRL_CALL_DISCONN_NOTIFY = 13,
+ PPTP_CTRL_WAN_ERROR_NOTIFY = 14,
+ PPTP_CTRL_SET_LINK_INFO = 15,
+};
+
+struct mesa_pptp_control_hdr{
+ unsigned short length; /* ȫ�����ݳ���, ������ͷ�� */
+ unsigned short pptp_message_type;
+ unsigned int magic_cookie;
+ unsigned short control_message_type;
+ char ignore_bytes[0]; /* �����ֶ��ݲ�����, ����Ҳ��һ�� */
+};
+
+struct mesa_vlan_hdr{
+ unsigned short pri_cfi_id;
+ unsigned short type;
+};
+
+struct mesa_vlan_detail_hdr{
+ unsigned char vlan_id_high:4;
+ unsigned char del_flag:1;
+ unsigned char priority:3;
+ unsigned char vlan_id_low;
+ unsigned short type;
+};
+
+/* 2018-08-28 lijia add, for pangu ��Ŀmac_in_mac���� */
+struct mesa_mac_in_mac_net_hdr{
+ unsigned int route_dir:1;
+ unsigned int link_id:3;
+ unsigned int dev_id:6;
+ unsigned int region_id:5;
+ unsigned int __pad1:1;
+ unsigned int encap_type:4;
+ unsigned int __pad2:20;
+ unsigned int __pad3:8;
+};
+
+
+#define GRE_PRO_IPV4 (0x0800)
+#define GRE_PRO_IPV6 (0x86DD)
+#define GRE_PRO_ARP (0x0806)
+#define GRE_PRO_PPP (0x880B)
+
+struct mesa_gre_base_hdr_v0{
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned char recur:3;
+ unsigned char strict_src_route_flag:1;
+ unsigned char seq_flag:1;
+ unsigned char key_flag:1;
+ unsigned char route_flag:1;
+ unsigned char checksum_flag:1;
+
+ unsigned char version:3;
+ unsigned char flags:5; /* version 0 flags is 5 bit */
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ unsigned char checksum_flag:1;
+ unsigned char route_flag:1;
+ unsigned char key_flag:1;
+ unsigned char seq_flag:1;
+ unsigned char strict_src_route_flag:1;
+ unsigned char recur:3;
+
+ unsigned char flags:5; /* version 0 flags is 5 bit */
+ unsigned char version:3;
+#else
+#error "Please check <endian.h>"
+#endif
+ unsigned short protocol;
+};
+
+struct mesa_gre_base_hdr_v1{
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned char recur:3;
+ unsigned char strict_src_route_flag:1;
+ unsigned char seq_flag:1;
+ unsigned char key_flag:1;
+ unsigned char route_flag:1;
+ unsigned char checksum_flag:1;
+
+ unsigned char version:3;
+ unsigned char flags:4; /* version 1 flags is 4 bit */
+ unsigned char ack_flag:1;
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ unsigned char checksum_flag:1;
+ unsigned char route_flag:1;
+ unsigned char key_flag:1;
+ unsigned char seq_flag:1;
+ unsigned char strict_src_route_flag:1;
+ unsigned char recur:3;
+
+ unsigned char ack_flag:1;
+ unsigned char flags:4; /* version 1 flags is 4 bit */
+ unsigned char version:3;
+#else
+#error "Please check <endian.h>"
+#endif
+ unsigned short protocol;
+};
+
+#define GRE_SRE_MAX_LEN (256) /* �����Ϊһ���ֽ�, 256 */
+struct gre_source_route_entry_hdr{
+ unsigned short address_family;
+ unsigned char sre_offset;
+ unsigned char sre_length;
+ unsigned char sre_entry_list[GRE_SRE_MAX_LEN];
+};
+
+/* ���п��ܵ�ֵ����, ��Ҫ����mesa_gre_base_hdr����bit��ֵ, �ж��Ƿ�������ֵ */
+struct mesa_gre_extend_hdr{
+ unsigned short checksum; //version0
+ unsigned short offset; //version0, if checksum present, then offset also present
+ unsigned short payload_len; //version1
+ unsigned short call_id; //version1
+ unsigned int key; //version0
+ unsigned int seq_num; //version0 and version1
+ unsigned int ack_num; //version1
+ //struct gre_source_route_entry_hdr sre_list;
+};
+
+struct mesa_gre_hdr{
+ /* version0��version1��ͷ����, version�ֶ�ʱһ�µ�, ������С����, Ĭ��ʹ��v0��ʽ���� */
+ struct mesa_gre_base_hdr_v0 gre_base;
+ struct mesa_gre_extend_hdr gre_extend;
+};
+
+
+#define MPLS_LABEL_MASK (0xFFFFF000)
+#define MPLS_EXP_MASK (0x00000E00)
+#define MPLS_BLS_MASK (0x00000100)
+#define MPLS_TTL_MASK (0x000000FF)
+struct mesa_mpls_hdr{
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned char mpls_label_low;
+ unsigned char mpls_label_mid;
+ unsigned char mpls_bls:1; /* bottom of label stack */
+ unsigned char mpls_exp:3;
+ unsigned char mpls_label_high:4;
+ unsigned char mpls_ttl;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ unsigned char mpls_ttl;
+ unsigned char mpls_label_high:4;
+ unsigned char mpls_exp:3;
+ unsigned char mpls_bls:1; /* bottom of label stack */
+ unsigned short mpls_label_low;
+#else
+#error "Please check <endian.h>"
+#endif
+};
+
+#define L2TP_REGISTERED_IP_PRO (115)
+#define L2TP_REGISTERED_PORT (1701)
+
+#define L2TP_HDR_TYPE_DATA (0)
+#define L2TP_HDR_TYPE_CONTROL (1)
+
+struct l2tp_hdr_v2{
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned char priority:1;
+ unsigned char offset_present:1;
+ unsigned char reserved2:1;
+ unsigned char seq_present:1;
+ unsigned char reserved1:2;
+ unsigned char length_present:1;
+ unsigned char type:1;
+
+ unsigned char version:4;
+ unsigned char reserved3:4;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ unsigned char reserved3:4;
+ unsigned char version:4;
+
+ unsigned char type:1;
+ unsigned char length_present:1;
+ unsigned char reserved1:2;
+ unsigned char seq_present:1;
+ unsigned char reserved2:1;
+ unsigned char offset_present:1;
+ unsigned char priority:1;
+#else
+#error "Please check <endian.h>"
+#endif
+};
+
+/* refer to RFC2661-Page12 */
+#define L2TP_CTRL_MSG_RESERVED0 (0)
+#define L2TP_CTRL_MSG_SCCRQ (1)
+#define L2TP_CTRL_MSG_SCCRP (2)
+#define L2TP_CTRL_MSG_SCCCN (3)
+#define L2TP_CTRL_MSG_STOP_CCN (4)
+#define L2TP_CTRL_MSG_RESERVED5 (5)
+#define L2TP_CTRL_MSG_HELLO (6)
+#define L2TP_CTRL_MSG_OCRQ (7)
+#define L2TP_CTRL_MSG_OCRP (8)
+#define L2TP_CTRL_MSG_OCCN (9)
+#define L2TP_CTRL_MSG_ICRQ (10)
+#define L2TP_CTRL_MSG_ICRP (11)
+#define L2TP_CTRL_MSG_ICCN (12)
+#define L2TP_CTRL_MSG_RESERVED13 (13)
+#define L2TP_CTRL_MSG_CDN (14)
+#define L2TP_CTRL_MSG_WEN (15)
+#define L2TP_CTRL_MSG_SLI (16)
+
+#define L2TP_AVP_GET_LEN(u) (ntohs(u) & 0x3F)
+struct l2tp_avp{
+ unsigned short M_H_rsvd_len_union;
+ unsigned short vendor_id;
+ unsigned short attribute_type;
+}BYTE_ALIGNED(1);
+
+/* RFC2408-Page23 */
+#define ISAKMP_PAYLOAD_TYPE_NONE (0)
+#define ISAKMP_PAYLOAD_TYPE_SA (1)
+#define ISAKMP_PAYLOAD_TYPE_PROPOSAL (2)
+#define ISAKMP_PAYLOAD_TYPE_TRANSFORM (3)
+#define ISAKMP_PAYLOAD_TYPE_KEY_EXCHANGE (4)
+#define ISAKMP_PAYLOAD_TYPE_ID (5)
+#define ISAKMP_PAYLOAD_TYPE_CERT (6)
+#define ISAKMP_PAYLOAD_TYPE_CR (7)
+#define ISAKMP_PAYLOAD_TYPE_HASH (8)
+#define ISAKMP_PAYLOAD_TYPE_SIG (9)
+#define ISAKMP_PAYLOAD_TYPE_NONCE (10)
+#define ISAKMP_PAYLOAD_TYPE_NOTIFY (11)
+#define ISAKMP_PAYLOAD_TYPE_DELETE (12)
+#define ISAKMP_PAYLOAD_TYPE_VENDOR_ID (13)
+#define ISAKMP_PAYLOAD_TYPE_RESERVED_BEGIN (14) /* 14 - 127 */
+#define ISAKMP_PAYLOAD_TYPE_RESERVED_END (127) /* 14 - 127 */
+#define ISAKMP_PAYLOAD_TYPE_PRIVATE_USE_BEGIN (128) /* 128-255 */
+#define ISAKMP_PAYLOAD_TYPE_PRIVATE_USE_END (255) /* 128-255 */
+
+/* RFC2408-Page23 */
+#define ISAKMP_EXCHANGE_TYPE_NONE (0)
+#define ISAKMP_EXCHANGE_TYPE_BASE (1)
+#define ISAKMP_EXCHANGE_TYPE_ID_PROT (2) /* RFC-2409 page8, main mode is instantiation os ISAKMP Identity Protect Exchange */
+#define ISAKMP_EXCHANGE_TYPE_AUTH (3)
+#define ISAKMP_EXCHANGE_TYPE_AGGRESS (4)/* RFC-2409 page8, Aggressive mode is instantiation os ISAKMP Aggressive Exchange */
+#define ISAKMP_EXCHANGE_TYPE_INFO (5)
+#define ISAKMP_EXCHANGE_TYPE_FEATURE_USE_BEGIN (6) /* 6-31��ֵ�ݲ����� */
+#define ISAKMP_EXCHANGE_TYPE_FEATURE_USE_END (31) /* 6-31��ֵ�ݲ����� */
+
+struct mesa_isakmp_hdr{ /* RFC2408-Page22 */
+ unsigned long long init_cookie;
+ unsigned long long resp_cookie;
+ unsigned char next_payload;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned char minor_version:4;
+ unsigned char major_version:4;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ unsigned char major_version:4;
+ unsigned char minor_version:4;
+#else
+#error "Please check <endian.h>"
+#endif
+
+ unsigned char exchange_type;
+ unsigned char flags;
+ unsigned int message_id;
+ unsigned int length;
+};
+
+struct mesa_isakmp_payload_hdr{ /* RFC2408-Page22 */
+ unsigned char next_payload;
+ unsigned char reserver;
+ unsigned short payload_len;
+};
+
+#define GTP_MSG_TYPE_T_PDU (0xFF)
+
+#define GTP_HDR_VER_MASK (0xE0)
+
+#define GTP_HDR_FLAG_NEXT_EXT_HDR (0x04)
+#define GTP_HDR_FLAG_SEQ_NUM (0x02)
+#define GTP_HDR_FLAG_N_PDU (0x01)
+
+
+struct gtp_hdr{
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned char flags;
+ unsigned char msg_type;
+ unsigned short len;
+ unsigned int teid;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int teid;
+ unsigned short len;
+ unsigned char msg_type;
+ unsigned char flags;
+#else
+#error "Please check <endian.h>"
+#endif
+};
+
+#define TEREDO_AUTH_HDR_FLAG (0x0001)
+#define TEREDO_INDICATION_HDR_FLAG (0x0000)
+
+#define TEREDO_INDICATION_HDR_LEN (8)
+
+struct teredo_auth_hdr{
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned short flags;
+ unsigned char id_len;
+ unsigned char au_len;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ unsigned char au_len;
+ unsigned char id_len;
+ unsigned short flags;
+#else
+#error "Please check <endian.h>"
+#endif
+};
+
+#define MAX_ADDR_TYPE_STRING_LEN (64)
+#define MAX_ADDR_LIST_STRING_LEN (2048)
+#define MAX_ADDR_EMBED_LAYER_NUM (20) /* ����ַǶ�ײ��� */
+#define MAX_ADDR_BIN_VALUE_LEN (40) /* paddrʵ��������󳤶�, Ŀǰ��tuple4v6� */
+
+/* ����ģʽ��, ��¼MAC��ַ���ڷ��� */
+struct packet_io_mac_addr{
+ struct mesa_ethernet_hdr eth_hdr;
+ char route_dir;
+ char __pad__; /* ����ṹ8�ֽڶ��� */
+};
+
+
+
+struct hdlc_net_hdr{
+ unsigned char address;
+ unsigned char control;
+ unsigned short protocol; /* network order */
+}__attribute__((packed));
+
+
+
+/* ������������ֶ�, ��Ϊ������, network order */
+#define VXLAN_KEEPALIVE_PKT_PORT (3784)
+#define VXLAN_OVERLAY_PKT_PORT (4789)
+
+
+typedef enum{
+ VXLAN_ENCAP_ETH = 0x0,
+ VXLAN_ENCAP_PPP = 0x8,
+ VXLAN_ENCAP_HDLC = 0xC,
+}vxlan_encap_type_t;
+
+struct __inline_vxlan_hdr{
+ unsigned char flags;
+ unsigned char reserved[3];
+ /*--------int delim -------*/
+ unsigned char vlan_id_half_high;
+ unsigned char link_layer_type : 4; /* ���㱨�ķ�װ��ʽ */
+ unsigned char vlan_id_half_low : 4;
+
+ unsigned int dir : 1;
+ unsigned int link_id : 6;
+ unsigned int online_test : 1;
+
+ unsigned int r7 : 1;
+ unsigned int r6 : 1;
+ unsigned int r5 : 1;
+ unsigned int r4 : 1;
+ unsigned int vni_flag : 1;
+ unsigned int r2 : 1;
+ unsigned int r1 : 1;
+ unsigned int r0 : 1;
+}__attribute__((packed));
+typedef struct __inline_vxlan_hdr inline_vxlan_hdr_t;
+
+
+
+unsigned char net_layer_to_ipv4_protocol(int addr_type);
+unsigned char net_layer_to_ipv6_protocol(int addr_type);
+unsigned short net_layer_to_ethernet_protocol(int addr_type);
+UINT16 net_layer_to_ethernet_protocol_by_stream(const struct streaminfo *pstream);
+enum addr_type_t ethernet_protocol_to_net_layer(UINT16 ether_type_host);
+int net_common_build_send_mac(unsigned char *buf, const struct mesa_ethernet_hdr *raw_eth_hdr, int addr_type, int dir_reverse, int net_topology_mode);
+int net_common_adjust_forward_mac(struct mesa_ethernet_hdr *raw_eth_hdr,int net_topology_mode);
+const void *MESA_net_jump_to_layer(const void *raw_data, int raw_layer_type, int expect_layer_type);
+const void *MESA_net_jump_to_layer_greedy(const void *raw_data, int raw_layer_type, int expect_layer_type);
+char MESA_ascii_to_hex(char ascii);
+const char *sapp_raw_ipv4_ntop(const struct mesa_ip4_hdr *ip4_hdr, char *out_buf, int buf_len );
+const char *sapp_raw_ipv6_ntop(const struct mesa_ip6_hdr *ip6_hdr, char *out_buf, int buf_len);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+