⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 109.htm

📁 unix高级编程原吗
💻 HTM
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>CTerm非常精华下载</title>
</head>
<body bgcolor="#FFFFFF">
<table border="0" width="100%" cellspacing="0" cellpadding="0" height="577">
<tr><td width="32%" rowspan="3" height="123"><img src="DDl_back.jpg" width="300" height="129" alt="DDl_back.jpg"></td><td width="30%" background="DDl_back2.jpg" height="35"><p align="center"><a href="http://apue.dhs.org"><font face="黑体"><big><big>123</big></big></font></a></td></tr>
<tr>
<td width="68%" background="DDl_back2.jpg" height="44"><big><big><font face="黑体"><p align="center">               ● UNIX网络编程                       (BM: clown)                </font></big></big></td></tr>
<tr>
<td width="68%" height="44" bgcolor="#000000"><font face="黑体"><big><big><p   align="center"></big></big><a href="http://cterm.163.net"><img src="banner.gif" width="400" height="60" alt="banner.gif"border="0"></a></font></td>
</tr>
<tr><td width="100%" colspan="2" height="100" align="center" valign="top"><br><p align="center">[<a href="index.htm">回到开始</a>][<a href="54.htm">上一层</a>][<a href="110.htm">下一篇</a>]
<hr><p align="left"><small>发信人: clown (梧桐叶), 信区: UNP <br>

标  题: 模仿unp写的一个简单的traceroute程序 <br>

发信站: UNIX编程 (2001年11月15日19:54:26 星期四), 站内信件 <br>

  <br>

#include <stdio.h> <br>

#include <stdlib.h> <br>

#include <unistd.h> <br>

#include <sys/types.h> <br>

#include <sys/socket.h> <br>

#include <arpa/inet.h> <br>

#include <sys/time.h> <br>

#include <netinet/in.h> <br>

#include <netinet/ip.h> <br>

#include <netinet/udp.h> <br>

#include <netinet/ip_icmp.h> <br>

#include <signal.h> <br>

#include <netdb.h> <br>

#include <errno.h> <br>

#include <string.h> <br>

  <br>

#define SIZE 60 <br>

#define MAX_PROBE 3 <br>

struct rec {    //format of outgoing UDP data <br>



    u_short rec_seq; <br>

    u_short rec_ttl; <br>

    struct timeval rec_tv; <br>

}; <br>

  <br>

int recvfd; <br>

struct sockaddr_in saddr; <br>

int socklen; <br>

int max_ttl = 30; <br>

u_short sport; <br>

u_short dport = 32768 + 666; <br>

  <br>

void sig_alarm(int); <br>

void traceloop(); <br>

int recv_v4(int, struct timeval *); <br>

  <br>

int main(int argc, char **argv) <br>

{ <br>

    struct hostent *host; <br>

    char dest[16]; <br>

    struct sigaction act; <br>

  <br>

  <br>

    if(argc != 2) { <br>

        printf("Usage: %s <host>\n", argv[0]); <br>

        exit(1); <br>

    } <br>

    errno = 0; <br>

    h_errno = 0; <br>

  <br>

    act.sa_handler = sig_alarm; <br>

    sigemptyset(&act.sa_mask); <br>

    act.sa_flags = SA_INTERRUPT; <br>

  <br>

    if((host = gethostbyname(argv[1])) == NULL) { <br>

        herror("gethostbyname"); <br>

        exit(1); <br>

    } <br>

    if(host->h_addrtype != AF_INET) { <br>

        printf("Unsupported net family %d\n", host->h_addrtype); <br>

        exit(1); <br>

    } <br>

    if(inet_ntop(AF_INET, host->h_addr, dest, sizeof(dest)) == NULL) { <br>

        perror("inet_ntop"); <br>

        exit(1); <br>



    } <br>

  <br>

    //set the dest address to globel varibal <br>

    memset(&saddr, 0, sizeof(struct sockaddr_in)); <br>

    saddr.sin_family = AF_INET; <br>

    memcpy((void *)&saddr.sin_addr, host->h_addr, host->h_length); <br>

    socklen = sizeof(struct sockaddr_in); <br>

  <br>

    printf("Traceroute %s(%s): %d hops max, %d data bytes\n", host->h_name, dest <br>

, max_ttl, sizeof(struct rec)); <br>

  <br>

    if((recvfd=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1) { <br>

        perror("socket"); <br>

        exit(1); <br>

    } <br>

    setuid(getuid()); <br>

  <br>

    if(sigaction(SIGALRM, &act, NULL) == -1) { <br>

        perror("signal"); <br>

        exit(1); <br>

    } <br>

  <br>

  <br>

    traceloop(); <br>

    return 0; <br>

} <br>

  <br>

void traceloop() <br>

{ <br>

    int sendfd, seq, ttl, ret; <br>

    int done, probe; <br>

    double rtt; <br>

    struct rec *rec; <br>

    struct timeval tvrecv; <br>

    struct sockaddr_in locaddr; <br>

    char sendbuf[SIZE]; <br>

  <br>

    void timeval_sub(struct timeval *, struct timeval *); <br>

  <br>

    if((sendfd=socket(AF_INET, SOCK_DGRAM, 0)) == -1) { <br>

        perror("socket"); <br>

        exit(1); <br>

    } <br>

    sport = (getpid() & 0xffff) | 0x8000; <br>

    locaddr.sin_family = AF_INET; <br>



    locaddr.sin_port = htons(sport); <br>

    if(bind(sendfd, (struct sockaddr *)&locaddr, sizeof(struct sockaddr_in)) == <br>

-1) { <br>

        perror("bind"); <br>

        exit(1); <br>

    } <br>

  <br>

    seq = 0; <br>

    done = 0; <br>

    for(ttl=1; ttl<=max_ttl && done==0; ttl++) { <br>

        if(setsockopt(sendfd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) == -1) { <br>

            perror("setsockopt"); <br>

            exit(1); <br>

        } <br>

        printf("%2d", ttl); <br>

        for(probe=0; probe<MAX_PROBE; probe++) { <br>

            memset(sendbuf, 0, sizeof(sendbuf)); <br>

            rec = (struct rec *)sendbuf; <br>

            rec->rec_seq = ++seq; <br>

            rec->rec_ttl = ttl; <br>

            if(gettimeofday(&rec->rec_tv, NULL) == -1) { <br>

                perror("gettimeofday"); <br>



                exit(1); <br>

            } <br>

            //set dest address' port <br>

            saddr.sin_port = htons(dport + seq); <br>

            if(sendto(sendfd, sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&s <br>

addr, sizeof(struct sockaddr_in)) == -1) { <br>

                perror("sendto"); <br>

                exit(1); <br>

            } <br>

  <br>

            //receive the packet <br>

            if((ret = recv_v4(seq, &tvrecv)) == -3) <br>

                //timed out, no reply <br>

                printf("\t*\n"); <br>

            else if(ret < 0){ <br>

                timeval_sub(&tvrecv, &rec->rec_tv); <br>

                rtt = tvrecv.tv_sec * 1000.0 + tvrecv.tv_usec/1000.0; <br>

                printf("\t%.3fms\n", rtt); <br>

                if(ret == -1)  //at destination <br>

                    done++; <br>

  <br>

            } else <br>



                printf("\tICMP code %d\n", ret); <br>

        } <br>

    } <br>

} <br>

  <br>

void sig_alarm(int signo) <br>

{ <br>

    return;  //just interrupt the recvfrom() <br>

} <br>

  <br>

void timeval_sub(struct timeval *recv, struct timeval *send) <br>

{ <br>

    if((recv->tv_usec -= send->tv_usec) < 0) { <br>

        recv->tv_sec--; <br>

        recv->tv_usec += 1000000; <br>

    } <br>

    recv->tv_sec -= send->tv_sec; <br>

    return; <br>

} <br>

  <br>

/*The packet should receive <br>

 * <br>

 * <br>

 |-------------------------------------n--------------------------------------| <br>

                          |-----------------icmplen---------------------------| <br>

 |------------hlen1-------|             |------------hlen2-------| <br>

  <br>

 | IPv4 header | IPv4 opt | ICMP header | IPv4 header | IPv4 opt | UDP header | <br>

  <br>

 |-----20B-----|--0~40B---|-----8B------|-----20B-----|---0~40B--|-----8B-----| <br>

 * <br>

 */ <br>

  <br>

/* <br>

 * return value: <br>

 *  -3 timeout <br>

 *  -2 ICMP time exceeded in transmit(the last router replied) <br>

 *  -1 ICMP port unreachable <br>

 *  >=0 other ICMP unreachable code <br>

 */ <br>

  <br>

int recv_v4(int seq, struct timeval *tvrecv) <br>

{ <br>

    char recvbuf[SIZE+100]; <br>

  <br>

  <br>

    int n, hlen1, hlen2, icmplen; <br>

    struct ip *ip, *hip; <br>

    struct icmp *icmp; <br>

    struct udphdr *udp; <br>

    struct sockaddr_in cliaddr; <br>

    int clilen; <br>

    char dest[16]; <br>

  <br>

    alarm(3); <br>

    while(1) { <br>

        clilen = sizeof(struct sockaddr_in); <br>

        memset(&cliaddr, 0, clilen); <br>

        if((n = recvfrom(recvfd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr * <br>

)&cliaddr, &clilen)) < 0) { <br>

            if(errno == EINTR) <br>

                return -3;  //timed out <br>

            else { <br>

                perror("recvfrom"); <br>

                exit(1); <br>

            } <br>

        } <br>

        //an icmp packet received <br>



        printf("\ta packet received"); <br>

        if(gettimeofday(tvrecv, NULL) == -1) { <br>

            perror("gettimeofday"); <br>

            exit(1); <br>

        } <br>

  <br>

        memset(dest, 0, sizeof(dest)); <br>

        if(inet_ntop(AF_INET, &cliaddr.sin_addr, dest, sizeof(dest)) == NULL) { <br>

            perror("inet_ntop"); <br>

            exit(1); <br>

        } <br>

        printf("\t%s", dest); <br>

  <br>

        ip = (struct ip *)recvbuf; <br>

        hlen1 = ip->ip_hl << 2; <br>

        icmp = (struct icmp *)(recvbuf + hlen1); <br>

        if((icmplen = n - hlen1) < 8 + 20 + 8) { <br>

            printf("icmplen %d < 8+20+8\n", icmplen); <br>

            continue; <br>

        } <br>

        if(icmp->icmp_type == ICMP_TIMXCEED && icmp->icmp_code <br>

                == ICMP_TIMXCEED_INTRANS) { <br>



            hip = (struct ip *)(recvbuf + hlen1 + 8); <br>

            hlen2 = hip->ip_hl << 2; <br>

            udp = (struct udphdr *)(recvbuf + hlen1 + 8 + hlen2); <br>

            if(hip->ip_p == IPPROTO_UDP && <br>

                    udp->source == htons(sport) && <br>

                    udp->dest == htons(dport + seq)) <br>

                return -2;  //hit an intermediate router <br>

        } else if(icmp->icmp_type == ICMP_UNREACH) { <br>

            hip = (struct ip *)(recvbuf + hlen1 + 8); <br>

            hlen2 = hip->ip_hl << 2; <br>

            udp = (struct udphdr *)(recvbuf + hlen1 + 8 + hlen2); <br>

            if(hip->ip_p == IPPROTO_UDP && <br>

                    udp->source == htons(sport) && <br>

                    udp->dest == htons(dport + seq)) { <br>

                if(icmp->icmp_code == ICMP_UNREACH_PORT) <br>

                    return -1;  //reached destination <br>

                else <br>

                    return(icmp->icmp_code); <br>

            } <br>

        } <br>

    } <br>

} <br>



  <br>

  <br>

-- <br>

易朽的是生命,似那转瞬即谢的花朵;然而永存的,是对未来的渴望, <br>

是那生生世世传递下来的,不朽的,生的激情。每一朵勇敢开放的花, <br>

都是一个死亡唇边的微笑。 <br>

※ 来源:·UNIX编程 apue.dhs.org·[FROM: 202.114.1.61] <br>

</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="54.htm">上一层</a>][<a href="110.htm">下一篇</a>]
<p align="center"><a href="http://cterm.163.net">欢迎访问Cterm主页</a></p>
</table>
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -