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
common-tools-tcpdump-mesa/net_common.c
2018-11-16 11:42:54 +08:00

837 lines
20 KiB
C

#include <linux/if_ether.h>
#include <net/if_arp.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <assert.h>
#include <ctype.h>
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "stream_base.h"
#include "mesa_net.h"
#include "ip.h"
#include "ip6.h"
#include "tcp.h"
#include "udp.h"
#include "ppp.h"
#ifdef __cplusplus
extern "C" {
#endif
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);
int treat_vlan_as_mac_in_mac_sw = 0; /* 将vlan强制按mac_in_mac格式解析, 先不传递给sapp, 因为影响sapp全局处理开关 */
/* 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;
}
return c;
}
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;
int opt_len = 0; /* 可选项长度 */
const unsigned char *next_ip_layer_hdr;
int skip_len;
if(ADDR_TYPE_GPRS_TUNNEL == expect_layer_type){
return 0;
}
if(gh->flags & 0x2){
opt_len += sizeof(int); /* sequence */
}
next_ip_layer_hdr = (unsigned char *)raw_data + opt_len + sizeof(struct gtp_hdr);
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{
////sapp_runtime_log(20, "TODO: jmp unsupport type in GTP, 0x%x!\n", (*next_ip_layer_hdr));
return -1;
}
return opt_len + sizeof(struct gtp_hdr) + 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)){
/* teredo实际没有数据包头, 直接跳转到ipv6层即可 */
skip_len = ipv6_jump_to_layer(raw_data+sizeof(struct mesa_udp_hdr), __ADDR_TYPE_IP_PAIR_V6, expect_layer_type);
if(skip_len < 0){
return -1;
}
}else{
/* 其他UDP类型不支持再跳转 */
return -1;
}
return skip_len + sizeof(struct mesa_udp_hdr);
}
static int ipv4_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type)
{
struct ip *p_ip_hdr = (struct ip *)raw_data;
int skip_len = 0;
int ip_hdr_len = IP_HL(p_ip_hdr) * 4;
//const char *next_layer_data = raw_data + ip_hdr_len;
if(raw_layer_type == expect_layer_type){
return 0;
}
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;
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 0: //NEXTHDR_HOP:
case 43://NEXTHDR_ROUTING:
case 51://NEXTHDR_AUTH:
case 60://NEXTHDR_DEST:
offset_to_ip6 = (*(next_hdr_ptr + 1))*8 + 8; /* 选项长度以8字节为单位 */
break;
case 4://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 59://NEXTHDR_NONE:
skip_len = -1;
goto done;
break;
case 58://NEXTHDR_ICMP: /* IMCP不再承载其他协议 */
skip_len = -1;
goto done;
break;
case 6://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 17://NEXTHDR_UDP:
if(ADDR_TYPE_UDP == expect_layer_type){
skip_len = next_hdr_ptr - (UINT8 *)raw_data;
}else{
/* TODO: IPv6的其他隧道模式 */
skip_len = -1;
}
goto done;
break;
case 44:///NEXTHDR_FRAGMENT:
offset_to_ip6 = 8; // 8 == sizeof(struct ipv6_frag_hdr);
break;
case 50://NEXTHDR_ESP:
skip_len = -1;
goto done;
default:
printf("TODO:jmp Unknown IPv6 header type:0x%x!\n", 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_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_V4, expect_layer_type);
}
break;
case PPP_COMP:
case PPP_CCP:
case PPP_IPCP:
case PPP_PAP:
case PPP_CHAP:
case 0xC025: ///PPP_LQR:
case PPP_PROTOCOL_LCP:
/* 不承载应用层协议 */
skip_len = -1;
break;
default:
printf("TODO: jmp unsupport ppp pro:0x%x!\n", ntohs(pppoe_ses_hdr->ppp_protocol));
break;
}
if(skip_len < 0){
return -1;
}
return skip_len + sizeof(struct mesa_pppoe_session_hdr);
}
static int mpls_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type)
{
int skip_len = 0;
const struct mesa_mpls_hdr *mpls_hdr = (const struct mesa_mpls_hdr *)raw_data;
const char *next_layer_data = raw_data + sizeof(struct mesa_mpls_hdr);
if(raw_layer_type == expect_layer_type){
return 0;
}
if(0 == mpls_hdr->mpls_bls){ /* 非MPLS栈底, 递归调用自身 */
return mpls_jump_to_layer(next_layer_data, ADDR_TYPE_MPLS, expect_layer_type) + sizeof(struct mesa_mpls_hdr);
}
/* MPLS没有字段标识下一层是什么, 靠猜测下一层的IP类型 */
if((*next_layer_data & 0x40) == 0x40){
skip_len = ipv4_jump_to_layer(next_layer_data, __ADDR_TYPE_IP_PAIR_V4, expect_layer_type);
}else if((*next_layer_data & 0x60) == 0x60){
skip_len = ipv6_jump_to_layer(next_layer_data, __ADDR_TYPE_IP_PAIR_V6, expect_layer_type);
}else{
//sapp_runtime_log(20, "TODO: jmp unsupport type in MPLS, 0x%x!\n", (unsigned char)(*next_layer_data));
return -1;
}
return skip_len + sizeof(struct mesa_mpls_hdr); /* mpls header is 4 byte */
}
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:
if(ADDR_TYPE_VLAN == expect_layer_type){
break;
}else{
if(treat_vlan_as_mac_in_mac_sw){
skip_len = eth_jump_to_layer(next_layer_data, ADDR_TYPE_MAC, expect_layer_type);
}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 = ppp_jump_to_layer(next_layer_data, ADDR_TYPE_PPPOE_SES, expect_layer_type);
}
break;
case 0x88A8: /* MAC_IN_MAC */
skip_len = eth_jump_to_layer(next_layer_data, ADDR_TYPE_MAC, expect_layer_type);
break;
case 0x8847: /* 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 vlan8021q_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type)
{
int skip_len = 0;
const struct mesa_vlan_hdr *vlan_hdr = (const struct mesa_vlan_hdr *)raw_data;
const char *next_layer_data = raw_data + sizeof(struct mesa_vlan_hdr);
if(raw_layer_type == expect_layer_type){
return 0;
}
switch(ntohs(vlan_hdr->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 = ppp_jump_to_layer(next_layer_data, ADDR_TYPE_PPPOE_SES, expect_layer_type);
}
break;
case ETH_P_PPP_DISC: /* pppoe发现阶段 */
skip_len = -1;
break;
case 0x8200: /* XinJing捕包发现此类型, 未知什么包 */
skip_len = -1;
break;
default:
printf("unsupport type in vlan8021q, 0x%x, You can try set the '--vlan-as-mac-in-mac' arg!\n", ntohs(vlan_hdr->type));
skip_len = -1;
}
if(skip_len < 0){
return -1;
}
return skip_len + sizeof(struct mesa_vlan_hdr);
}
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;
}
/*
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(raw_layer_type <= __ADDR_TYPE_INIT || raw_layer_type >= __ADDR_TYPE_MAX){
return NULL;
}
if(expect_layer_type <= __ADDR_TYPE_INIT || expect_layer_type >= __ADDR_TYPE_MAX){
return NULL;
}
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:
if(treat_vlan_as_mac_in_mac_sw){
ret = mac_in_mac_jump_to_layer((const char *)raw_data, raw_layer_type, expect_layer_type);
}else{
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_PPPOE_SES:
case ADDR_TYPE_MPLS:
case ADDR_TYPE_GRE:
default:
printf("TODO: jmp unsupport raw_layer_type:%d in MESA_net_jump_to_layer()!\n", 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()从最外层开始, 找到第一个符合条件的层就退出;
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)
{
const void *expect_layer;
const void *success_layer = NULL; /* 最后一次成功找到的层 */
int new_raw_layer_type = raw_layer_type; /* 在跳转过程中, 可能会更新中间层信息 */
const char *new_next_layer_data = (char *)raw_data;
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(IPPROTO_UDP == ip4hdr->ip_p){
new_next_layer_data = (char *)expect_layer + ip4hdr->ip_hl * 4;
new_raw_layer_type = ADDR_TYPE_UDP; /* IP层如果继续向下一层偏移, 只支持UDP, IPIP, GRE, L2TPv3. */
}else{
//TODO 2, GRE, IPIP, L2TPv3
goto done;
}
}
break;
case __ADDR_TYPE_IP_PAIR_V6:
{
//TODO2,
//sapp_runtime_log(20, "MESA_net_jump_to_layer_greedy() not support IPv6 layer yet\n");
goto done;
}
break;
default:
//sapp_runtime_log(20, "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;
}
UINT8 net_layer_to_ipv4_protocol(int addr_type)
{
UINT8 proto = 0;
switch(addr_type){
case __ADDR_TYPE_IP_PAIR_V4:
proto = IPPROTO_IPIP;
break;
case __ADDR_TYPE_IP_PAIR_V6:
proto = IPPROTO_IPV6;
break;
case ADDR_TYPE_TCP:
proto = IPPROTO_TCP;
break;
case ADDR_TYPE_UDP:
proto = IPPROTO_UDP;
break;
case ADDR_TYPE_GRE:
proto = IPPROTO_GRE;
break;
default:
printf("unknown ip4 protocolr:%d\n", addr_type);
proto = 0xFF;
break;
}
return proto;
}
UINT8 net_layer_to_ipv6_protocol(int addr_type)
{
UINT8 proto = 0;
switch(addr_type){
case ADDR_TYPE_TCP:
proto = 6; //NEXTHDR_TCP;
break;
case ADDR_TYPE_UDP:
proto = 17;///NEXTHDR_UDP;
break;
case __ADDR_TYPE_IP_PAIR_V4:
proto = 4;///NEXTHDR_IPIP;
break;
default:
printf("unknown ip6 next-hdr:%d\n", addr_type);
return 0xFF;
break;
}
return proto;
}
/*
将MESA地址类型转换为标准Ethernet类型;
return value:
ethernet type, host order.
*/
UINT16 net_layer_to_ethernet_protocol(int addr_type)
{
UINT16 ether_type = 0;
switch(addr_type){
case __ADDR_TYPE_IP_PAIR_V4:
ether_type = ETH_P_IP;
break;
case __ADDR_TYPE_IP_PAIR_V6:
ether_type = ETH_P_IPV6;
break;
case ADDR_TYPE_VLAN:
ether_type = ETHERTYPE_VLAN;
break;
case ADDR_TYPE_TCP:
case ADDR_TYPE_UDP:
//sapp_runtime_log(RLOG_LV_FATAL, "%s:%d: Ethernet can't carry addr type:%d directly!\n", __FILE__, __LINE__,addr_type);
//assert(0);
ether_type = -1;
break;
case ADDR_TYPE_PPPOE_SES:
ether_type = ETH_P_PPP_SES;
break;
case ADDR_TYPE_MPLS:
ether_type = ETH_P_MPLS_UC;
break;
case ADDR_TYPE_ARP:
ether_type = ETH_P_ARP;
break;
default:
/* to do, unknown type */
///sapp_runtime_log(RLOG_LV_FATAL, "%s:%d: Ethernet addr type:%d!\n", __FILE__, __LINE__, addr_type);
ether_type = -1;
break;
}
return ether_type;
}
/* 删除末尾的换行符"\r\n" */
void del_last_rn(char *data, int max_len)
{
int i;
for(i = 0; i < max_len; i++){
if(('\r' == data[i]) || ('\n' == data[i])){
data[i] = '\0';
return;
}
}
return;
}
/*
返回值:
ethernet长度, 包括eth头部.
*/
int get_pkt_len_from_eth_hdr(const struct mesa_ethernet_hdr *ehdr)
{
int raw_pkt_len = -1;
switch(ntohs(ehdr->ether_type)){
case ETHERTYPE_IP:
{
struct mesa_ip4_hdr *ip4hdr = (struct mesa_ip4_hdr *)((char *)ehdr + sizeof(struct mesa_ethernet_hdr));
raw_pkt_len = ntohs(ip4hdr->ip_len) + sizeof(struct mesa_ethernet_hdr);
}
break;
case ETHERTYPE_IPv6:
{
struct mesa_ip6_hdr *ip6hdr = (struct mesa_ip6_hdr *)((char *)ehdr + sizeof(struct mesa_ethernet_hdr));
raw_pkt_len = ntohs(ip6hdr->ip6_payload_len) + sizeof(struct mesa_ip6_hdr) + sizeof(struct mesa_ethernet_hdr);
}
break;
default:
break;
}
return raw_pkt_len;
}
#ifdef __cplusplus
}
#endif