网络编程,自己模仿编写IGMP报文

chenmo074639 2012-11-16 10:05:26
通过抓包工具,我检测到以下问题:
1,抓到的包,抓包工具只能分析出,此包为IGMP报文。
2,我在程序中填写的报文内容(数据),抓包工具分析出来都不正确。
3,抓到的程序的内容基本都没变,同时我在程序中将自己填写的内容改变,也没真作用
4,抓包工具抓的包一直显示check sum 不正确




#include <linux/icmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/time.h>

unsigned short cal_chksum( unsigned short *addr, int len );
int SocketBinding(int socket_num, struct sockaddr_in BindAddress,
char BindingIP[16], int bind_port_num);
struct sockaddr_in InitSocketAdd(int socket_port_num, char SocketIPNum[16],
struct sockaddr_in InitAddress);
void *CreatBuffer(int buffer_len);
unsigned short cal_chksum( unsigned short *addr, int len );

int main(int argc, char** argv)
{
struct timeval sendtime;
struct sockaddr_in send_add;
bzero((void *)&send_add, sizeof(struct sockaddr_in));
struct protoent * protocol = NULL;

char* remote_ip_str = "172.16.2.162";
int remote_port_num = 0;

int sock_raw = 0;
int buffer_len = sizeof(struct icmphdr)+20;

unsigned short send_num = 0;

if ((sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
{
perror("error on socket\n");
printf("sock_raw:%d\n",sock_raw);
return(-1);
}
if (SocketBinding(sock_raw, send_add, "172.16.2.111", 33333) < 0)
{
perror("error on SocketBinding");
return(-1);
}

char *pToFillSpace = NULL;
pToFillSpace = CreatBuffer(buffer_len);

bzero((void *)&send_add, sizeof(struct sockaddr_in));
send_add = InitSocketAdd(remote_port_num,remote_ip_str,send_add);

struct icmphdr *icmphdr = (struct icmphdr *)pToFillSpace;
while(send_num <10)
{
printf( "PING %s: %d bytes of data in ICMP packets.\n", remote_ip_str, buffer_len );
icmphdr->type = (unsigned char)ICMP_DEST_UNREACH;

icmphdr->code = (unsigned char)0;

icmphdr->checksum = 0;
icmphdr->checksum =cal_chksum((unsigned short*)icmphdr, sizeof(struct icmphdr));

icmphdr->un.echo.id = (unsigned short)getpid();
icmphdr->un.echo.sequence = 0x11;

printf("type:%d,code:%x,icmphdr->checksum:%x,icmphdr->un.echo.id:%x,icmphdr->un.echo.sequence:%x\n",
icmphdr->type,icmphdr->code,icmphdr->checksum,icmphdr->un.echo.id,icmphdr->un.echo.sequence);
int ret = 0;
ret = sendto(sock_raw, &pToFillSpace, buffer_len, 0, (struct sockaddr *)&send_add, (socklen_t)sizeof(struct sockaddr_in));
if (ret < 0)
{
perror("sendto\n");
return(-1);
}
sleep(1);
printf("send_num:%d\n",send_num++);
}
close(sock_raw);
free(pToFillSpace);
pToFillSpace = NULL;
}

void *CreatBuffer(int buffer_len)
{
char * pToBuffer = (char *)malloc(buffer_len);
if (NULL == pToBuffer)
{
perror("error on pToFillSpace");
return NULL;
}
memset((void*)pToBuffer, '5',buffer_len);

return (void *)pToBuffer;
}

unsigned short cal_chksum( unsigned short *addr, int len )
{
int nleft = len;
int sum = 0;
unsigned short *w = addr;
unsigned short answer = 0;

//把ICMP报头二进制数据以2字节为单位累加起来
while( nleft > 1 )
{
sum += *w++;
nleft -= 2;
}
//若ICMP报头为奇数个字节,会剩下最后一字节。
//把最后一个字节视为一个2字节数据的高字节,这个2字节数据的低字节为0,继续累加。
if( nleft == 1 )
{
*(unsigned char *)(&answer) = *(unsigned char *)w;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return answer;
}

int SocketBinding(int socket_num, struct sockaddr_in BindAddress,
char BindingIP[16], int bind_port_num)
{
BindAddress = InitSocketAdd(bind_port_num, BindingIP, BindAddress);
if (bind(socket_num, (const struct sockaddr *)&BindAddress, sizeof(BindAddress)) < 0)
{
perror("ERROR on bind\n");
return(-1);
}

return 0;
}

struct sockaddr_in InitSocketAdd(int socket_port_num, char SocketIPNum[16],
struct sockaddr_in InitAddress)
{
bzero((void*)&InitAddress,sizeof(InitAddress));
InitAddress.sin_family = AF_INET;
InitAddress.sin_port = htons(socket_port_num);

if (inet_pton(AF_INET,SocketIPNum, (void *)&InitAddress.sin_addr.s_addr) <= 0)
{
perror(" ERROR in transforming the IP add\n");
exit(-1);
}
return InitAddress;
}
...全文
460 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
nossiac 2012-11-20
  • 打赏
  • 举报
回复
部分关键代码,供参考。 数据结构

#define PING_DATA_LEN (61)

typedef unsigned char byte;


typedef struct {
    byte type;
    byte code;
    char * description;
} ICMP_DESCRIPTION;

typedef struct {
    byte protocol;
    char * description;
} PROTOCOLS_ON_IP;


typedef struct
{
    byte type;
    byte code;
    unsigned short checksum;
} ICMPHead;

typedef struct
{
    unsigned short label;
    unsigned short seqnum;
    byte text[PING_DATA_LEN];
}PingData;

typedef struct
{
    byte ver_headlen;
    byte tos;
    unsigned short packlen;
    unsigned short seq;
    unsigned short segment_offset;
    byte ttl;
    byte protocol;
    unsigned short checksum;
    unsigned int srcip;
    unsigned int dstip;
}IPHead;
组包发送


unsigned short chksum16(byte *buf, size_t len)
{
    unsigned int sum = 0;
    for(sum = 0; len > 1; len -= 2)
    {
        sum += *((unsigned short *)buf);
        buf += 2;
    }
    if(len == 1) // for odd byte
        sum += ((*buf)<<8);

    sum = (sum>>16) + (sum&0xffff);
    sum += (sum>>16);
    return ~sum;
}

int main(int argc, char ** argv)
{
    int rawsock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
    pthread_t tid;
    struct sockaddr_in destaddr;
    destaddr.sin_family = AF_INET;
    destaddr.sin_port = 0;

    if(argc>1)
        destaddr.sin_addr.s_addr = inet_addr(argv[1]);
    else
        destaddr.sin_addr.s_addr = inet_addr("172.26.11.123");

    int pinglen = sizeof(ICMPHead) + sizeof(PingData);
    void * data = malloc(pinglen);
    char * p = (char *)data;
    ((ICMPHead *)p)->type = 8;
    ((ICMPHead *)p)->code = 0;
    ((ICMPHead *)p)->checksum = 0; // we take care of this later
    p = p + sizeof(ICMPHead);
    ((PingData *)p)->label = 0;
    ((PingData *)p)->seqnum = 0;
    memset(p+4, 'A', PING_DATA_LEN);

    ((ICMPHead *)data)->checksum = chksum16((byte *)data, pinglen);

    printf("create receiver!\n");
    pthread_create(&tid, NULL, receiver, (void *)rawsock);

    int i = 0;
    while (i<4)
    {
        printf("send icmp package %d!\n", i);
        sendto(rawsock, (void *)data, pinglen, 0, (struct sockaddr *)&destaddr, sizeof(destaddr));
        i++; sleep(1);
    }

    sleep(4);
    printf("Mission Completed!\n");
    return 0;
}
chenmo074639 2012-11-16
  • 打赏
  • 举报
回复
你说的这种方法我以前试过,只是一直没有成功,所以一直在修改,没有写回原来的方式,实在不好意思
nossiac 2012-11-16
  • 打赏
  • 举报
回复
引用 2 楼 chenmo074639 的回复:
谢谢遗漏,我现在的IGMP包就一个头部,没有其他内容。
还有就是checksum计算时机问题,正确的过程应该是: 应该先把数据包checksum置0,等数据包的所有其它数据填充完毕,再计算checksum填回去。 你代码里貌似计算完checksum后,又去修改了数据包啊。
chenmo074639 2012-11-16
  • 打赏
  • 举报
回复
谢谢遗漏,我现在的IGMP包就一个头部,没有其他内容。
nossiac 2012-11-16
  • 打赏
  • 举报
回复

icmphdr->checksum =cal_chksum((unsigned short*)icmphdr, sizeof(struct icmphdr));
ICMP校验和需要覆盖整个ICMP包,你这里只计算了头部吧? 另外,发大段代码的时候,使用code标签,会有不错的格式化。这样子观众才有兴趣看。
zodiac1111 2012-11-16
  • 打赏
  • 举报
回复
业余也搞过乱七八糟的协议,关键是熟读协议文本(标准) 严格按照那个协议的标准构造,一个bit都不差,应该没什么问题. wireshark分析协议,我还得字节写插件分析(解析)别人给的协议包. = =,完全是在自己构造/实现协议,好累
nossiac 2012-11-16
  • 打赏
  • 举报
回复
引用 4 楼 chenmo074639 的回复:
你说的这种方法我以前试过,只是一直没有成功,所以一直在修改,没有写回原来的方式,实在不好意思
搞不定再找我。我做过这个。没什么跑不通的。

3,286

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 实用资料发布区
社区管理员
  • 实用资料发布区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧