Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在c中使用sendto()发送自定义tcp数据包?_C_Sockets_Networking_Tcp - Fatal编程技术网

在c中使用sendto()发送自定义tcp数据包?

在c中使用sendto()发送自定义tcp数据包?,c,sockets,networking,tcp,C,Sockets,Networking,Tcp,确切地说,我创建了这个简单的TCP程序,通过网络向目标计算机发送一个简单的TCP数据包,但不知何故,我真的不知道我做错了什么,但它似乎没有向目标主机发送任何数据包。我在我的wireshark里也找不到 rawtcp.c: //---cat rawtcp.c--- // Run as root or SUID 0, just datagram no data/payload #include <stdlib.h> #include <string.h> #include

确切地说,我创建了这个简单的TCP程序,通过网络向目标计算机发送一个简单的TCP数据包,但不知何故,我真的不知道我做错了什么,但它似乎没有向目标主机发送任何数据包。我在我的wireshark里也找不到

rawtcp.c:

//---cat rawtcp.c---
// Run as root or SUID 0, just datagram no data/payload

#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
#pragma pack(push, 1)
// May create separate header file (.h) for all
// headers' structures
// IP header's structure
struct ipheader {
 unsigned char      iph_ihl:4, /* Little-endian */
                iph_ver:4;
 unsigned char      iph_tos;
 unsigned short int iph_len;
 unsigned short int iph_ident;
 unsigned short int iph_offset;
 unsigned char      iph_ttl;
 unsigned char      iph_protocol;
 unsigned short int iph_chksum;
 unsigned int       iph_sourceip;
 unsigned int       iph_destip;
};

/* Structure of a TCP header */
struct tcpheader {
 unsigned short int tcph_srcport;
 unsigned short int tcph_destport;
 unsigned int       tcph_seqnum;
 unsigned int       tcph_acknum;
 unsigned char      tcph_reserved:4, tcph_offset:4;
 // unsigned char tcph_flags;
 unsigned int
       tcp_res1:4,       /*little-endian*/
       tcph_hlen:4,      /*length of tcp header in 32-bit words*/
       tcph_fin:1,       /*Finish flag "fin"*/
       tcph_syn:1,       /*Synchronize sequence numbers to start a connection*/
       tcph_rst:1,       /*Reset flag */
       tcph_psh:1,       /*Push, sends data to the application*/
       tcph_ack:1,       /*acknowledge*/
       tcph_urg:1,       /*urgent pointer*/
       tcph_res2:2;

 unsigned short int tcph_win;
 unsigned short int tcph_chksum;
 unsigned short int tcph_urgptr;
};
#pragma pack(pop)
// Simple checksum function, may use others such as Cyclic Redundancy Check, CRC
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);

    if(argc != 5)
    {
        printf("- Invalid parameters!!!\n");
        printf("- Usage: %s <source hostname/IP> <source port> <target hostname/IP> <target port>\n", argv[0]);
        exit(-1);
    }

    sd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
    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(argv[2]));
    din.sin_port = htons(atoi(argv[4]));

    // Source IP, can be any, modify as needed
    sin.sin_addr.s_addr = inet_addr(argv[1]);
    din.sin_addr.s_addr = inet_addr(argv[3]);

    // IP structure
    ip->iph_ihl = 5;
    ip->iph_ver = 4;
    ip->iph_tos = 16;
    ip->iph_len = htons(sizeof(struct ipheader) + sizeof(struct tcpheader));
    ip->iph_ident = htons(54321);
    ip->iph_offset = 0;
    ip->iph_ttl = 64;
    ip->iph_protocol = 6; // TCP
    ip->iph_chksum = 0; // Done by kernel

    // Source IP, modify as needed, spoofed, we accept through command line argument
    ip->iph_sourceip = inet_addr(argv[1]);

    // Destination IP, modify as needed, but here we accept through command line argument
    ip->iph_destip = inet_addr(argv[3]);

    // The TCP structure. The source port, spoofed, we accept through the command line
    tcp->tcph_srcport = htons(atoi(argv[2]));

    // The destination port, we accept through command line
    tcp->tcph_destport = htons(atoi(argv[4]));
    tcp->tcph_seqnum = htonl(1);
    tcp->tcph_acknum = 0;
    tcp->tcph_offset = 5;
    tcp->tcph_syn = 1;
    tcp->tcph_ack = 0;
    tcp->tcph_win = htons(32767);
    tcp->tcph_chksum = 0; // Done by kernel
    tcp->tcph_urgptr = 0;

    // IP checksum calculation
    ip->iph_chksum = 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");
    printf("Using:::::Destination IP: %s port: %u, Source IP: %s port: %u.\n", argv[1], atoi(argv[2]), argv[3], atoi(argv[4]));

    // sendto() loop, send every 2 second for 50 counts
    unsigned int count;
    for(count = 0; count < 20; count++)
    {
        if(sendto(sd, buffer, ip->iph_len, 0, (struct sockaddr *)&din, sizeof(din)) < 0)
    // Verify
    {
        perror("sendto() error");
        exit(-1);
    } else
        printf("Count #%u - sendto() is OK\n", count);

        sleep(2);
   }
   close(sd);
   return 0;
}
但是,当筛选wireshark为
tcp.port==1000
时,它从未显示(注意:源ip为192.168.1.152,目标ip为192.168.1.151)。但是如果我做一个简单的
hping3-p1000192.168.1.151
,它工作得很好,我也可以在wireshark中看到它


如果您能告诉我我的代码有什么错误,我将不胜感激:)

我想您的端口已经被使用了

您应该将端口更改为30000或更高,其他应用程序通常会使用1000个端口


您还应该使用telnet[ip][port]进行调试。首先,您缺少
头,它提供了您正在使用的
inet\u addr
函数。由于隐式函数声明,您的程序仍然应该在C89下编译,但依赖于它是不好的做法,它可能会导致微妙的错误

一个问题是您误用了
#pragma pack

在声明结构之前,应该执行
#pragma pack(push,1)
,这两项操作都将结构打包对齐设置为1,并将打包对齐的上一个状态推送到堆栈。声明完结构后,可以执行
#pragma pack(pop)
将结构打包重置为以下任何声明中的正常状态。在您的程序中,在声明后省略
#pragma pack(pop)
应该仍然有效,但最好将其重置,以防您声明了任何其他不希望紧密打包的结构,或者之后包含任何其他头文件

#pragma pack(push, 1)
struct a {
    /* ... */
};

struct b {
    /* ... */
};
#pragma pack(pop)
struct ipheader
的另一个问题是既有8位的
iph_标志
又有16位的
iph_偏移量
,而IP报头中的标志字段应该是3位,偏移量字段应该是13位(两者加起来总共16位)。这意味着您的头中有一个额外的8位不应该在那里。由于无论如何都要用零填充这两个字段,因此可以通过从结构中完全删除
iph_标志
,只需将一个16位
iph_偏移量
字段保留为零来修复此问题,该字段实际上跨越了IP标头中3位和13位字段的空间


通过这些修复,您的程序可以为我工作,并且可以在Wireshark中看到一个数据包。

如果您在源系统上进行检查(例如使用Wireshark),数据包是否已发送?端口1000的防火墙是否已关闭?@Someprogrammerdude因我的延迟回复而抱歉。我甚至看不到数据包是从源目的地发送的。@ralfhtp不,没有防火墙可以阻止数据包,事实上,数据包从未生成。请检查结构的大小。他们说得对吗?你确定没有填充吗?不,端口不是问题。为了保证这一点,我可以做一个简单的
hping3-p1000-s1000192.168.1.151
,它工作得很好。无论如何,我也会尝试一个diffrenet端口。我完全按照你说的方式做了,检查我的代码更新。包括
arpa/inet.h
,删除了
iph_标志
,修复了
#pragma
,但仍然不起作用。你能再次发布你的工作代码吗?@IwontDoIt你更新的代码示例对我很有用。你是怎么运作的?如果我执行sudo./tcp 127.0.0.1 54321 127.0.0.1 1234,然后在“Loopback:lo”界面查看wireshark(作为根),我会看到数据包显示出来。您可能正在监视wireshark中的错误接口。它对您有什么作用?我以root用户身份登录,因此不需要
sudo
。我的wireshark过滤器也很好,我的意思是我在wireshark上有这个过滤器:
tcp.port==54321或tcp.port==1234或(ip.src==192.168.1.152和ip.dst==192.168.1.151)
,我运行的程序是:
sudo./rawtcp 127.0.0.1 1234 192.168.1.151 54321
,你确定它对你有用吗,如果可以的话:这是TCP。@我试着从127.0.0.1开始src和dst。1当我将代码编译为
gcc-o rawtcp rawtcp.c-Wall时,我得到了以下警告:
rawtcp.c:57:0:警告:忽略#pragma(pop[-Wunknown pragmas]rawtcp.c:在函数“main”中:rawtcp.c:79:29:警告:变量“din”已设置但未使用[-Wunused但已设置变量]`可能与此有关吗?
#pragma pack(push, 1)
struct a {
    /* ... */
};

struct b {
    /* ... */
};
#pragma pack(pop)