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); } |