internet

[알림판목록 I] [알림판목록 II] [글목록][이 전][다 음]
From   : Liszt (장 진 웅)
Date   : Wed Sep  9 12:07:58 1992
Subject: ICMP Subnet Mask Request Client

제가 시간이 나서 틈틈이 짜본 프로그램입니다..
별로 도움이 되진 않겠지만.... 필요할 때도 있겠죠?
/*
Name: GETMASK; Internet Control Message Protocol "Subnet Mask Request" client.
Author: Chang Jin-woong, KAIST, CS Department
Usage: "getmask hostname" (dotted decimal notation allowed)
Remark: This program must be used by root or SETUID'ed to create
        RAW socket. This code may be compiled cleanly or with little
        modification on 4.3 BSD-compatible network library. Only tested
        on SunOS 4.1.1/SS 2.
See Also: UNIX Network Programming, by W. R. Stevens, Prentice-Hall
        Internetworking with TCP/IP, by D. E. Comer, Prentice-Hall
*/

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

#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN  64
#endif

#define MAXPACKETLEN    256
#define ICMPHDRLEN      8
#define TIMESTAMPLEN    sizeof(struct timeval)

extern  int     errno;
int     count   = 0;

/*
Checksum computation routine for TCP/IP family headers
This code is from ping.c, written by Mike Muuss
For more information, refer to "Computing the Internet Checksum" by
R. Braden and C. Partridge, Computer Communication Review, Vol 19, No 2,
April 1989, pp. 86-101.
*/
int     ip_chksum(packet, length)
register u_short *packet;       /* Ptr to target packet */
register int    length;         /* Length of packet */
{
register long   sum;
u_short oddbyte;
register u_short ans;

        sum = 0;
        while(length > 1) {
                sum += *packet++;
                length -= 2;
        }
        if(length == 1) {
                oddbyte = 0;
                *((u_char *)&oddbyte) = *(u_char *)packet;
                sum += oddbyte;
        }

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

timer()
{
int     oldmask;

        oldmask = sigblock((sigmask(SIGALRM)));
        count++;
        fprintf(stderr, "Not responding after %d seconds.\n", count);
        sigsetmask(oldmask);
}

finish()
{
        exit(0);
}

main(argc, argv)
int     argc;
char    **argv;
{
char    hostname[MAXHOSTNAMELEN];
char    *inet_ntoa();
u_char  opacket[MAXPACKETLEN];
u_char  ipacket[MAXPACKETLEN];
int     sock, ident, packetlen, iphdrlen, i, n, srclen;
struct  sockaddr_in     dst, src;
struct  in_addr         dest, *netmask;
struct  hostent         *dhost;
struct  protoent        *proto;
struct  icmp            *pk_icmp, *icmp_h;
struct  ip      *ip_h;

        /* Command line processing */
        if(argc < 2) {
                fprintf(stderr, "Usage: getmask hostname\n");
                exit(1);
        }
        else if(argc > 2) {
                fprintf(stderr, "Warning: Too many arguments\n");
        }

        /* Retrieve hostname field */
        bzero(hostname, MAXHOSTNAMELEN);
        strncpy(hostname, argv[1], MAXHOSTNAMELEN-1);

        /* Convert hostname to sockaddr_in structure */
        bzero((char *)&dst, sizeof(dst));
        dst.sin_family = AF_INET;
        if((dst.sin_addr.s_addr = inet_addr(hostname)) == -1) {
                if((dhost = gethostbyname(hostname)) == NULL) {
                        fprintf(stderr, "%s: Unknown host\n", hostname);
                        exit(1);
                }
                dst.sin_family = dhost->h_addrtype;
                bcopy((char *)dhost->h_addr, (char *)&dst.sin_addr,
                        dhost->h_length);
        }

        /* Create socket */
        if((proto = getprotobyname("icmp")) == NULL) {
                fprintf(stderr, "Unknown protocol: ICMP\n");
                exit(1);
        }
        if((sock = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) {
                perror("socket");
                exit(1);
        }

        /* Send ICMP packet */
        ident = getpid();               /* Use PID as "IDENT" field */
        packetlen = ICMPHDRLEN + TIMESTAMPLEN;
        pk_icmp = (struct icmp *)opacket;
        pk_icmp->icmp_type = ICMP_MASKREQ;
        pk_icmp->icmp_code = 0;
        pk_icmp->icmp_cksum = 0;
        pk_icmp->icmp_id = ident;
        pk_icmp->icmp_seq = 0;
        gettimeofday((struct timeval *)&(opacket[ICMPHDRLEN]),
                        (struct timezone *)0);
        pk_icmp->icmp_cksum = ip_chksum(pk_icmp, packetlen);
        i = sendto(sock, opacket, packetlen, 0,
                        (struct sockaddr *)&dst, sizeof(dst));
        dest.s_addr = dst.sin_addr.s_addr;
        fprintf(stdout, "ICMP Network Mask Request to %s, id = %d.\n",
                inet_ntoa(dest), ident);

        if(i < 0 || i != packetlen) {
                fprintf(stderr, "sendto failed\n");
                exit(1);
        }

        signal(SIGALRM, timer);
        signal(SIGINT, finish);
        ualarm(1000000, 1000000);

        while(1) {
                srclen = sizeof(src);
                if((n = recvfrom(sock, ipacket, sizeof(ipacket), 0,
                                (struct sockaddr *)&src, &srclen)) < 0) {
                        if(errno == EINTR) continue;
                        else {
                                perror("recvfrom");
                                exit(1);
                        }
                }

                ip_h = (struct ip *)ipacket;
                iphdrlen = (ip_h->ip_hl) * 4;
                icmp_h = (struct icmp *)(ipacket+iphdrlen);

                /* check if the packet is from the valid source */
                i = bcmp((char *)&src.sin_addr.s_addr,
                        (char *)&dst.sin_addr.s_addr, sizeof(struct in_addr));
                if(i != 0 || icmp_h->icmp_id !=ident) {
                        fprintf(stderr, "Packet from invald source %s",
                                inet_ntoa(src.sin_addr.s_addr));
                        continue;
                }

                /* check if the packet has valid length */
                if(n < iphdrlen + ICMPHDRLEN) {
                        fprintf(stderr, "Short packet from %s, ignored.\n",
                                inet_ntoa(src.sin_addr.s_addr));
                        continue;
                }

                /* check if the packet is ICMP_MASKREPLY type */
                if(icmp_h->icmp_type != ICMP_MASKREPLY) {
                        fprintf(stderr, "Invald reply, ignored.\n");
                        continue;
                }

                netmask = (struct in_addr *)(ipacket+iphdrlen+ICMPHDRLEN);
                fprintf(stdout, "Reply = %s\n", inet_ntoa(netmask));
                break;
        }
        fflush(stdout); fflush(stderr);
        close(sock);
}
[알림판목록 I] [알림판목록 II] [글 목록][이 전][다 음]
키 즈 는 열 린 사 람 들 의 모 임 입 니 다.