我有一个程序,可以将TCP / Ipv4数据包发送到我的Localhost地址。
我尝试扩展程序,因此我在Ip标头中编辑/设置Ip标志。在执行完此程序并启动程序后,我仅在Wireshark中接收到具有ipv4协议的数据包,因此它没有随IP数据包一起发送tcp数据包。
如果我使用旧的Ip标头,则该程序可以正常工作,因此没有Ip标志。
您知道吗,为什么程序没有发送ipv4 + tcp数据包?
我的旧IP页眉:
struct ipheader {
unsigned char ip_hl :4, ip_v :4;
unsigned char ip_tos;
unsigned short int ip_len;
unsigned short int ip_id;
unsigned short int ip_off;
unsigned char ip_ttl;
unsigned char ip_p;
unsigned short int ip_sum;
unsigned int ip_src;
unsigned int ip_dst;
};
我的旧Tcp标头:
struct tcpheader {
unsigned short int th_sport;
unsigned short int th_dport;
unsigned int th_seq;
unsigned int th_acknum;
unsigned char th_reserved :4, th_off :4;
unsigned int th_fin :1, th_syn :1, th_rst :1, th_psh :1, th_ack :1,
th_urg :1, th_cwr :1, th_ece :1, th_ns :1;
unsigned short int th_win;
unsigned short int th_sum;
unsigned short int th_urp;
};
我的新IP标头
struct ipheader {
unsigned char ip_hl :4, ip_v :4;
unsigned char ip_tos:8;
unsigned short int ip_len:16;
unsigned short int ip_id:16;
unsigned short int ip_moreFrag:1,
ip_doNotFrag :1, ip_reserved :1;
unsigned short int ip_off:13;
unsigned char ip_ttl:8;
unsigned char ip_p:8;
unsigned short int ip_sum:16;
unsigned int ip_src:32;
unsigned int ip_dst:32;
};
我的新TCP-标头:
struct tcpheader {
unsigned short int th_sport:16;
unsigned short int th_dport:16;
unsigned int th_seq:32;
unsigned int th_acknum:32;
unsigned char th_reserved :4, th_off :4;
// unsigned char th_flags;
// unsigned int tcp_res1 :4, th_hlen :4;
unsigned int th_fin :1, th_syn :1, th_rst :1, th_psh :1, th_ack :1,
th_urg :1, th_cwr :1, th_ece :1; //th_ns :1;
unsigned short int th_win:16;
unsigned short int th_sum:16;
unsigned short int th_urp:16;
};
第一个输入:
"ip_v": "4",
"ip_hl": "5" ,
"ip_type": "16" ,
"ip_off": "0",
"ip_reserved" : "0",
"ip_DoNotFragment": "1",
"ip_MoreFragment": "1",
"ip_len": "200",
"ip_id": "4321",
"ip_ttl": "255",
"ip_proto": "6",
"ip_sum": "0",
"ip_src": "1.2.3.4",
"ip_dest":"127.0.0.1",
"ip_data": "------" ,
"tcp_sourcePort": "1000",
"tcp_destPort": "1000",
"tcp_seqnum" : "0",
"tcp_acknum" : "0",
"tcp_reserved" : "4",
"tcp_offset" : "5",
"tcp_fin" : "0",
"tcp_syn" : "1",
"tcp_rst" : "0",
"tcp_psh" : "0",
"tcp_ack" : "1",
"tcp_urg" : "0",
"tcp_cwr" : "1",
"tcp_ece" : "1",
"tcp_win" : "32767",
"tcp_sum": "0",
"tcp_urp" : "0"
第二次输入相同。第一个输入和第二个输入之间的区别在于,我为ip标志设置的值为0而不是1
因此,如果我使用“第一个”输入,我会在Wireshark中输入如下内容:
Output Wireshark for First Input
如果我使用第二个输入,那么对于所有Ip标志值为0,我都会在Wireshark中获得以下输出:
Output Wireshark for Second Input
// Run as root or SUID 0,
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
// Packet length
#define PCKT_LEN 8192
struct ipheader {
unsigned char ip_hl :4, ip_v :4;
unsigned char ip_tos :8;
unsigned short int ip_len :16;
unsigned short int ip_id :16;
unsigned short int ip_off :13;
unsigned short int ip_moreFrag :1, ip_doNotFrag:1, ip_reserved : 1;
unsigned char ip_ttl :8;
unsigned char ip_p :8;
unsigned short int ip_sum :16;
unsigned int iph_sourceip :32;
unsigned int iph_destip :32;
};
/* Structure of a TCP header */
struct tcpheader {
unsigned short int th_sport :16;
unsigned short int th_dport :16;
unsigned int th_seq :32;
unsigned int th_acknum :32;
unsigned char th_reserved :4, th_off :4;
unsigned short int th_fin :1, th_syn :1, th_rst :1, th_psh :1, th_ack :1,
th_urg :1, th_cwr :1, th_ece :1;
unsigned short int th_win :16;
unsigned short int th_sum :16;
unsigned short int th_urp :16;
};
unsigned short csum(unsigned short *buf, int len) {
unsigned long sum;
for (sum = 0; len > 0; len--)
sum += *buf++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return (unsigned short) (~sum);
}
int main(int argc, char *argv[]) {
int sd;
// No data, just datagram
char buffer[PCKT_LEN];
// The size of the headers
struct ipheader *ip = (struct ipheader *) buffer;
struct tcpheader *tcp = (struct tcpheader *) (buffer
+ sizeof(struct ipheader));
struct sockaddr_in sin, din;
int one = 1;
const int *val = &one;
memset(buffer, 0, PCKT_LEN);
sd = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
if (sd < 0) {
perror("socket() error");
exit(-1);
} else
printf("socket()-SOCK_RAW and tcp protocol is OK.\n");
// The source is redundant, may be used later if needed
// Address family
sin.sin_family = AF_INET;
din.sin_family = AF_INET;
// Source port, can be any, modify as needed
sin.sin_port = htons(atoi("1000"));
din.sin_port = htons(atoi("1000"));
// Source IP, can be any, modify as needed
sin.sin_addr.s_addr = inet_addr("1.2.3.4");
din.sin_addr.s_addr = inet_addr("127.0.0.1");
// IP structure
ip->ip_v = 4;
ip->ip_hl = 5;
ip->ip_tos = 16;
ip->ip_off = 0;
ip->ip_reserved = 1;
ip->ip_doNotFrag = 1;
ip->ip_moreFrag = 1;
ip->ip_len = htons(sizeof(struct ipheader) + sizeof(struct tcpheader));
ip->ip_id = htons(54321);
ip->ip_ttl = 255;
ip->ip_p = 6; // TCP
ip->ip_sum = 0; // Done by kernel
ip->iph_sourceip = inet_addr("1.2.3.4");
ip->iph_destip = inet_addr("127.0.0.1");
tcp->th_sport = htons(atoi("1000"));
tcp->th_dport = htons(atoi("1000"));
tcp->th_seq = htonl(0);
tcp->th_acknum = 0;
tcp->th_reserved = 4;
tcp->th_off = 5;
tcp->th_fin = 1;
tcp->th_syn = 1;
tcp->th_rst = 1;
tcp->th_psh = 1;
tcp->th_ack = 1;
tcp->th_urg = 1;
tcp->th_cwr = 1;
tcp->th_ece = 1;
tcp->th_win = htons(32767);
tcp->th_sum = 0; // Done by kernel
tcp->th_urp = 0;
// IP checksum calculation
ip->ip_sum = htons(
csum((unsigned short *) buffer,
(sizeof(struct ipheader) + sizeof(struct tcpheader))));
// Inform the kernel do not fill up the headers' structure, we fabricated our own
if (setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0) {
perror("setsockopt() error");
exit(-1);
} else
printf("setsockopt() is OK\n");
unsigned int count;
if (sendto(sd, buffer, ip->ip_len, 0, (struct sockaddr *) &din, sizeof(din))
< 0)
// Verify
{
perror("sendto() error");
exit(-1);
} else
printf("Count #%u - sendto() is OK\n", count);
close(sd);
return 0;
}