我正在尝试使用pcap C库创建一个包含BER格式的H.248消息的数据包,以便使用wireshark应用程序对其进行解码。我写的代码和它的工作原理如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <pcap.h>
#include <pcap/vlan.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <linux/netdevice.h>
#include <linux/if_vlan.h>
#include <linux/if_ether.h>
#ifdef LINUX
#include <netinet/ether.h>
#endif
#define LINE_LEN 16
// chunk identifier
#define SH_DATA 0
#define SH_INIT 1
#define SH_INIT_ACK 2
#define SH_SACK 3
#define SH_HEARTBEAT 4
#define SH_HEARTBEAT_ACK 5
#define SH_ABORT 6
#define SH_SHUTDOWN_ACK 8
#define SH_COOKIE_ECHO 10
#define SH_COOKIE_ACK 11
#define SH_ECNE 12
#define SH_CWR 13
#define SH_SHUTDOWN_COMPLETE 14
//payload protocol identifier for SCTP
#define RESERVED 0 //[RFC4960]
#define IUA 1 //[RFC4233]
#define M2UA 2 //[RFC3331]
#define M3UA 3 //[RFC4666]
#define SUA 4 //[RFC3868]
#define M2PA 5 //[RFC4165]
#define V5UA 6 //[RFC3807]
#define H248 7
#define BICC 8
#define TALI 9 //[RFC3094]
#define DUA 10 //[RFC4129]
#define ASAP 11 //[RFC5352]
#define ENRP 12 //[RFC5353]
#define H323 13
#define QIPC 14 //Q.2150.3
#define SIMCO 15
#define DDPSEGC 16
#define DDPSSC 17
#define S1AP 18
#define RUA 19
#define HNBAP 20
#define FORCESHP 21
#define FORCESMP 22
#define FORCESLP 23
#define SBCAP 24
#define NBAP 25
#define UNASSIGNED 26
#define X2AP 27
u_char payload[] = {0x30, 0x82, 0x01, 0x60, 0xa1, 0x82, 0x01, 0x5c, 0x80, 0x01, 0x02,0xa1, 0x04, 0x84, 0x02, 0x24, 0x1a, 0xa2, 0x82, 0x01, 0x4f, 0xa1, 0x82, 0x01, 0x4b, 0xa0, 0x82, 0x01, 0x47, 0x80, 0x04, 0x2f, 0x00, 0x00, 0xaa, 0xa1, 0x82, 0x01, 0x3d, 0x30, 0x82, 0x01, 0x39,0x80, 0x04, 0x10, 0x00, 0x00, 0x0f, 0xa3, 0x82, 0x01, 0x2f, 0x30, 0x82, 0x01, 0x2b, 0xa0, 0x82, 0x01, 0x27, 0xa6, 0x82, 0x01, 0x23, 0xa0, 0x0a, 0x30, 0x08, 0xa0, 0x00, 0x81, 0x04, 0x28, 0x40, 0x00, 0x07, 0xa1, 0x82, 0x01, 0x13, 0x80, 0x01, 0x2f, 0xa1, 0x82, 0x01, 0x0c, 0x30, 0x2f, 0x80, 0x04, 0x00, 0x21, 0x00, 0x01, 0x81, 0x02, 0x00, 0xff, 0xa2, 0x0d, 0x30, 0x0b, 0x80, 0x02, 0x00, 0x01, 0xa1, 0x05, 0x04, 0x03, 0x0a, 0x01, 0x01, 0xa3, 0x14, 0x80, 0x08, 0x02, 0x00, 0x00, 0x07, 0x00, 0x06, 0x00, 0x05, 0x81, 0x08, 0x01, 0x08, 0x03, 0x01, 0x01, 0x02, 0x03, 0x04, 0x30, 0x81,
0xa7, 0x80, 0x04, 0x00, 0x22, 0x00, 0x01, 0xa2, 0x81, 0x9e, 0x30, 0x81, 0x9b, 0x80, 0x02, 0x00, 0x01, 0xa1, 0x81, 0x94, 0x04, 0x81, 0x91, 0x04, 0x81, 0x8e, 0x20, 0x20, 0x76, 0x3d, 0x30, 0x0d, 0x0a, 0x6f, 0x3d, 0x2d, 0x20, 0x30, 0x20, 0x30, 0x20, 0x49, 0x4e, 0x20, 0x49, 0x50, 0x34, 0x20, 0x31, 0x30, 0x2e, 0x33, 0x2e, 0x31, 0x2e, 0x34, 0x0d, 0x0a, 0x73, 0x3d, 0x2d, 0x0d, 0x0a, 0x63, 0x3d, 0x49, 0x4e, 0x20, 0x49, 0x50, 0x34, 0x20, 0x31, 0x30, 0x2e, 0x33, 0x2e, 0x31, 0x2e, 0x34, 0x0d, 0x0a, 0x74, 0x3d, 0x30, 0x20, 0x30, 0x0d, 0x0a, 0x61, 0x3d, 0x69, 0x70, 0x62, 0x63, 0x70, 0x3a, 0x31, 0x20, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x0d, 0x0a, 0x6d, 0x3d, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x20, 0x31, 0x38, 0x39, 0x34, 0x38, 0x20, 0x52, 0x54, 0x50, 0x2f, 0x41, 0x56, 0x50, 0x20, 0x39, 0x36, 0x0d, 0x0a, 0x61, 0x3d, 0x72, 0x74, 0x70, 0x6d, 0x61, 0x70, 0x3a, 0x39, 0x36, 0x20, 0x56, 0x4e, 0x44, 0x2e, 0x33, 0x47, 0x50, 0x50, 0x2e, 0x49, 0x55, 0x46, 0x50, 0x2f, 0x31, 0x36, 0x30, 0x30, 0x30, 0x0d, 0x0a, 0x30, 0x2f, 0x80, 0x04, 0x00, 0x21, 0x00, 0x02, 0x81, 0x02, 0x00, 0xff, 0xa2, 0x0d, 0x30, 0x0b, 0x80, 0x02, 0x00, 0x01, 0xa1, 0x05, 0x04, 0x03, 0x0a, 0x01, 0x01, 0xa3, 0x14, 0x80, 0x08, 0x02, 0x00, 0x00, 0x07, 0x00, 0x06, 0x00, 0x05, 0x81,
0x08, 0x01, 0x08, 0x03, 0x01, 0x01, 0x02, 0x03, 0x04};
int SCTP_payload = sizeof payload / sizeof(u_char);
struct chunk
{
u_char identifier; // type
u_char flags;
u_short length;
unsigned int seq_num;
u_short stream_id;
u_short stream_seq_num;
unsigned int payload_id;
};
struct sctphdr
{
/*
The data types/sizes we need to use are: unsigned char - 1 byte (8 bits),
unsigned short int - 2 bytes (16 bits) and unsigned int - 4 bytes (32 bits)
*/
u_short sport;
u_short dport;
unsigned int veriftag;
unsigned int sctp_sum;
// chunk follows
struct chunk chnk;
};
struct ethernet {
u_char mac1[6];
u_char mac2[6];
u_short protocol;
};
struct packet{
//struct ethernet ether;
struct iphdr iph;
struct sctphdr sctph;
u_char payload_data[396];
};
int main()
{
pcap_t *fd;
char errbuf[PCAP_ERRBUF_SIZE];
struct pcap_pkthdr *header;
const u_char *pkt_data;
u_int i=1;
pcap_t *pd;
pcap_dumper_t *pdumper;
pd = pcap_open_dead(DLT_RAW, 65535);
pdumper = pcap_dump_open(pd, "test3.pcap");
//lets move on to SCTP header
struct packet mypacket;
#if __BYTE_ORDER == __LITTLE_ENDIAN
mypacket.sctph.sport = htons(2945);
mypacket.sctph.dport = htons(2945);
#endif
mypacket.sctph.veriftag = 0;
mypacket.sctph.sctp_sum = 0;
mypacket.sctph.chnk.identifier = SH_DATA;
mypacket.sctph.chnk.flags = 0x03;
#if __BYTE_ORDER == __LITTLE_ENDIAN
mypacket.sctph.chnk.length = htons(sizeof(struct chunk)+SCTP_payload);
mypacket.sctph.chnk.seq_num = htonl(206);
mypacket.sctph.chnk.stream_id = htons(0x0001);
mypacket.sctph.chnk.stream_seq_num = htons(205);
mypacket.sctph.chnk.payload_id = htonl(H248);
#endif
printf("SCTP_payload:%d\n",SCTP_payload);
struct pcap_pkthdr packet_header;
struct timeval ts;
packet_header.ts = ts;
packet_header.caplen = sizeof(struct packet) + SCTP_payload;
packet_header.len = sizeof(struct packet) + SCTP_payload;
#if __BYTE_ORDER == __LITTLE_ENDIAN
//write data for IP protocol header
char dst_addr[]={"10.87.25.136"};
char src_addr[]={"10.92.152.7"};
mypacket.iph.saddr = inet_addr(src_addr);
mypacket.iph.daddr = inet_addr(dst_addr);
mypacket.iph.version = 4;
mypacket.iph.ihl = 5; //20 bytes
mypacket.iph.tos = 0; //type of service
#endif
#if __BYTE_ORDER == __LITTLE_ENDIAN
mypacket.iph.tot_len = htons(sizeof(struct iphdr)+sizeof(struct sctphdr)+SCTP_payload);
printf("iph.tot_len:%d\n",sizeof(struct iphdr));
mypacket.iph.id = htons(0x9152); //identification
mypacket.iph.frag_off = 0; //fragment offset
mypacket.iph.ttl=255;
mypacket.iph.protocol = 132; //SCTP
mypacket.iph.check = htons(0x6069);
#endif
memcpy(mypacket.payload_data,&payload[0],SCTP_payload*sizeof(u_char));
pcap_dump((u_char*)pdumper, &packet_header, (const u_char*)&mypacket);
pcap_close(pd);
pcap_dump_close(pdumper);
}
运行此代码后,生成可以使用wireshark应用程序打开的test3.pcap文件。请查看下图:
test3.pcap opened with wireshark
我现在要做的是通过使用 u_char * payload_data 来为有效负载数据 u_char payload_data [396]; 创建一个更动态的应用程序。
为了执行此操作,我已经用 u_char * payload_data 替换了 u_char payload_data [396]; ,并在main()函数中使用了以下代码行: / p>
mypacket.payload_data = (u_char *)malloc(SCTP_payload*sizeof(u_char));
memcpy(mypacket.payload_data,&payload[0],SCTP_payload*sizeof(u_char));
不幸的是,当我运行修改的C程序时,无法识别数据包的SCTP有效负载(H.248消息),因为在SCTP有效载荷协议标识符(00 00 00 07)之后插入了一些垃圾数据。请查看下图:
test3.pcap with dynamic solution opened with wireshark
我在这里做错了什么?
提前谢谢!
答案 0 :(得分:0)
pcap_dump()
- 函数需要整个第三个参数(在您的情况下为mypacket
)中指定的数据。在您第一次尝试时,就是这种情况,因为数据直接存储在结构struct packet
:
struct packet {
struct iphdr iph;
struct sctphdr sctph;
u_char payload_data[396];
};
然后你把它改成了:
struct packet {
struct iphdr iph;
struct sctphdr sctph;
u_char *payload_data;
};
现在,不是数据本身存储在结构中,而是存储数据的指针存储位置! pcap_dump
对数据的语义一无所知,因此它当然不能取消引用该指针并使用存储在那里的数据,但它只是存储内存位置。
一种可能的解决方案是按如下方式定义结构:
struct packet {
struct iphdr iph;
struct sctphdr sctph;
u_char payload_data[1];
};
然后为整个结构分配内存,如:
struct packet *p = malloc(sizeof(struct packet)+payloadlen);
这样,您可以使有效负载长度动态,但数据仍然是整体的,因此适用于pcap_dump()