The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

[Phrack] Watcher (security )


<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>
Ключевые слова: security,  (найти похожие документы)
Subject: [Phrack] Watcher ---[ Phrack Magazine Volume 8, Issue 53 July 8, 1998, article 11 of 15 -------------------------[ Watcher --------[ hyperion <[email protected]> ----[ INTRODUCTION Do you know if your system has been hacked? If you found those funny user accounts or that Trojaned program, its too late. You're owned. Chances are that your systems were scanned for holes before your systems were cracked. If you had just seen them coming you wouldn't be reloading that OS right now. Programs like TCP Wrappers do some good, but they don't see the stealth scans or DOS attacks. You could by a nice commercial network intrusion detector, but your wallet screams in agony. What you need is a low cost (as in free) fast, somewhat paranoid network monitor that watches all packets and uses few resources. Watcher provides this. ----[ IMPLEMENTATION Watcher examines all packets on the network interface and assumes they all are potentially hostile. Watcher examines every packet within a 10 second window, and, at the end of each window it will record any malicious activity it sees using syslog. Watcher currently detects the following attacks: - All TCP scans - All UDP scans - Synflood attacks - Teardrop attacks - Land attacks - Smurf attacks - Ping of death attacks All parameters and thresholds are configurable through command line options. You can also configure watcher to just look for scans or just look for DOS attacks. Watcher assumes any TCP packet other than a RST (which elicits no response) may be used to scan for services. If packets of any type are received by more than 7 different ports within the window, an event is logged. The same criteria are used for UDP scans. If watcher sees more than 8 SYN packets to the same port with no ACK's or FIN's associated with the SYN's, a synflood event is logged. If a fragmented UDP packet with an IP id of 242 is seen, it is assumed to be a teardrop attack since the published code uses an id of 242. This is somewhat lame since anyone could change the attacking code to use other id's. The code should track all fragmented IP's and check for overlapping offsets. I may do this in a future version. Any TCP SYN packets with source and destination address and ports the same is a identified as a land attack. If more than 5 ICMP ECHO REPLIES are seen within the window, Watcher assumes it may be a Smurf attack. Note that this is not a certainty, since someone your watching may just be pinging the hell out of someone. Watcher also assumes that any fragmented ICMP packet is bad, bad, bad. This catches attacks such as the ping of death. Watcher has three modes of monitoring. In the default mode, it just watches for attacks against its own host. The second monitoring mode is to watch all hosts on it's class C subnet. In the third mode, it watches all hosts whose packets it sees. Watching multiple hosts is useful if you put Watcher on your border to external networks, or to have hosts watch out for each other in case one gets cracked before you can react. Even if log files are destroyed, the other host has a record. It must be noted that since Watcher treats every packet as potentially hostile, it sometimes can report false positives. There are some checks in the code to minimize this by increasing its tolerance for certain activity. Unfortunately this also increases the rate at which scans can be done before Watcher notices. The usual false positives are TCP scans and synfloods, mostly resulting from WWW activity. Some web pages have many URL's to GIF files and other pretty stuff. Each of these may cause the client to open a separate TCP connection to download. Watcher sees these and treats them as a TCP scan of the client. To minimize this, watcher will only log TCP scans if more than 40 are received in the window AND the source port of the scan was 80. This of course can be configured higher or lower as desired. As for synfloods we will use the same WWW example above. If the client opens a lot of connections to the server right before the 10 second window expires and Watcher does not see the ACK's or FIN's for those SYN packets, Watcher will think the client is synflooding port 80 on the server. This only happens if watcher is watching the server, or if you are watching everyone. You may also get occasional false UDP scans if the system being watched makes lots of DNS queries within the window. The output for Watcher is pretty simple. Every 10 seconds, any detected attacks are logged to syslog. The source and target IP's are logged along with the type of attack. Where appropriate, other information such as the number of packets, or the port involved are logged. If the attack is normally associated with false IP addresses, the MAC address is also logged. If the attack is external, the MAC will be for the local router that handled the packet. If it was from your LAN, you'll have the source machine and you can thank the sender in an appropriate manner. ----[ PROGRAM EXECUTION Watcher was written to run on Linux systems. Watcher has a variety of, most of the self-explanatory. To execute watcher, simply run it in the background, usually from the system startup script. The options are: Usage: watcher [options] -d device Use 'device' as the network interface device The first non-loopback interface is the default -f flood Assume a synflood attack occurred if more than 'flood' uncompleted connections are received -h A little help here -i icmplimit Assume we may be part of a smurf attack if more than icmplimit ICMP ECHO REPLIES are seen -m level Monitor more than just our own host. A level of 'subnet' watches all addresses in our subnet and 'all' watches all addresses -p portlimit Logs a portscan alert if packets are received for more than portlimit ports in the timeout period. -r reporttype If reporttype is dos, only Denial Of Service attacks are reported. If reporttype is scan then only scanners are reported. Everything is reported by default. -t timeout Count packets and print potential attacks every timeout seconds -w webcount Assume we are being portscanned if more than webcount packets are received from port 80 Hopefully, watcher will keep your systems a little better protected. But remember that good security is multiple layers, and no single defense tool will save you by itself. If you forget this, you'll be reloading that OS one day. ----[ THE CODE <++> EX/Watcher.c /********************************************************************* Program: watcher A network level monitoring tool to detect incoming packets indicative of potential attacks. This software detects low level packet scanners and several DOS attacks. Its primary use is to detect low level packet scans, since these are usually done first to identify active systems and services to mount further attacks. The package assumes every incoming packet is potentially hostile. Some checks are done to minimize false positives, but on occasion a site may be falsely identified as having performed a packet scan or SYNFLOOD attack. This usually occurs if a large number of connections are done in a brief time right before the reporting timeout period (i.e. when browsing a WWW site with lots of little GIF's, each requiring a connection to download). You can also get false positives if you scan another site, since the targets responses will be viewed as a potential scan of your system. By default, alerts are printed to SYSLOG every 10 seconds. ***********************************************************************/ #include <stdio.h> #include <sys/types.h> #include <sys/time.h> #include <sys/socket.h> #include <sys/file.h> #include <sys/time.h> #include <netinet/in.h> #include <netdb.h> #include <string.h> #include <errno.h> #include <ctype.h> #include <malloc.h> #include <netinet/tcp.h> #include <netinet/in_systm.h> #include <net/if_arp.h> #include <net/if.h> #include <netinet/udp.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> #include <linux/if_ether.h> #include <syslog.h> #define PKTLEN 96 /* Should be enough for what we want */ #ifndef IP_MF #define IP_MF 0x2000 #endif /***** WATCH LEVELS ******/ #define MYSELFONLY 1 #define MYSUBNET 2 #define HUMANITARIAN 3 /***** REPORT LEVELS *****/ #define REPORTALL 1 #define REPORTDOS 2 #define REPORTSCAN 3 struct floodinfo { u_short sport; struct floodinfo *next; }; struct addrlist { u_long saddr; int cnt; int wwwcnt; struct addrlist *next; }; struct atk { u_long saddr; u_char eaddr[ETH_ALEN]; time_t atktime; }; struct pktin { u_long saddr; u_short sport; u_short dport; time_t timein; u_char eaddr[ETH_ALEN]; struct floodinfo *fi; struct pktin *next; }; struct scaninfo { u_long addr; struct atk teardrop; struct atk land; struct atk icmpfrag; struct pktin *tcpin; struct pktin *udpin; struct scaninfo *next; u_long icmpcnt; } ; struct scaninfo *Gsilist = NULL, *Gsi; u_long Gmaddr; time_t Gtimer = 10, Gtimein; int Gportlimit = 7; int Gsynflood = 8; int Gwebcount = 40; int Gicmplimit = 5; int Gwatchlevel = MYSELFONLY; int Greportlevel = REPORTALL; char *Gprogramname, *Gdevice = "eth0"; /******** IP packet info ********/ u_long Gsaddr, Gdaddr; int Giplen, Gisfrag, Gid; /****** Externals *************/ extern int errno; extern char *optarg; extern int optind, opterr; void do_tcp(), do_udp(), do_icmp(), print_info(), process_packet(); void addtcp(), addudp(), clear_pktin(), buildnet(); void doargs(), usage(), addfloodinfo(), rmfloodinfo(); struct scaninfo *doicare(), *addtarget(); char *anetaddr(), *ether_ntoa(); u_char *readdevice(); main(argc, argv) int argc; char *argv[]; { int pktlen = 0, i, netfd; u_char *pkt; char hostname[32]; struct hostent *hp; time_t t; doargs(argc, argv); openlog("WATCHER", 0, LOG_DAEMON); if(gethostname(hostname, sizeof(hostname)) < 0) { perror("gethostname"); exit(-1); } if((hp = gethostbyname(hostname)) == NULL) { fprintf(stderr, "Cannot find own address\n"); exit(-1); } memcpy((char *)&Gmaddr, hp->h_addr, hp->h_length); buildnet(); if((netfd = initdevice(O_RDWR, 0)) < 0) exit(-1); /* Now read packets forever and process them. */ t = time((time_t *)0); while(pkt = readdevice(netfd, &pktlen)) { process_packet(pkt, pktlen); if(time((time_t *)0) - t > Gtimer) { /* Times up. Print what we found and clean out old stuff. */ for(Gsi = Gsilist, i = 0; Gsi; Gsi = Gsi->next, i++) { clear_pktin(Gsi); print_info(); Gsi->icmpcnt = 0; } t = time((time_t *)0); } } } /********************************************************************** Function: doargs Purpose: sets values from environment or command line arguments. **********************************************************************/ void doargs(argc, argv) int argc; char **argv; { char c; Gprogramname = argv[0]; while((c = getopt(argc,argv,"d:f:hi:m:p:r:t:w:")) != EOF) { switch(c) { case 'd': Gdevice = optarg; break; case 'f': Gsynflood = atoi(optarg); break; case 'h': usage(); exit(0); case 'i': Gicmplimit = atoi(optarg); break; case 'm': if(strcmp(optarg, "all") == 0) Gwatchlevel = HUMANITARIAN; else if(strcmp(optarg, "subnet") == 0) Gwatchlevel = MYSUBNET; else { usage(); exit(-1); } break; case 'p': Gportlimit = atoi(optarg); break; case 'r': if(strcmp(optarg, "dos") == 0) Greportlevel = REPORTDOS; else if(strcmp(optarg, "scan") == 0) Greportlevel = REPORTSCAN; else { exit(-1); } break; case 't': Gtimer = atoi(optarg); break; case 'w': Gwebcount = atoi(optarg); break; default: usage(); exit(-1); } } } /********************************************************************** Function: usage Purpose: Display the usage of the program **********************************************************************/ void usage() { printf("Usage: %s [options]\n", Gprogramname); printf(" -d device Use 'device' as the network interface device\n"); printf(" The first non-loopback interface is the default\n"); printf(" -f flood Assume a synflood attack occurred if more than\n"); printf(" 'flood' uncompleted connections are received\n"); printf(" -h A little help here\n"); printf(" -i icmplimit Assume we may be part of a smurf attack if more\n"); printf(" than icmplimit ICMP ECHO REPLIES are seen\n"); printf(" -m level Monitor more than just our own host.\n"); printf(" A level of 'subnet' watches all addresses in our\n"); printf(" subnet and 'all' watches all addresses\n"); printf(" -p portlimit Logs a portscan alert if packets are received for\n"); printf(" more than portlimit ports in the timeout period.\n"); printf(" -r reporttype If reporttype is dos, only Denial Of Service\n"); printf(" attacks are reported. If reporttype is scan\n"); printf(" then only scanners are reported. Everything is\n"); printf(" reported by default.\n"); printf(" -t timeout Count packets and print potential attacks every\n"); printf(" timeout seconds\n"); printf(" -w webcount Assume we are being portscanned if more than\n"); printf(" webcount packets are received from port 80\n"); } /********************************************************************** Function: buildnet Purpose: Setup for monitoring of our host or entire subnet. **********************************************************************/ void buildnet() { u_long addr; u_char *p; int i; if(Gwatchlevel == MYSELFONLY) /* Just care about me */ { (void) addtarget(Gmaddr); } else if(Gwatchlevel == MYSUBNET) /* Friends and neighbors */ { addr = htonl(Gmaddr); addr = addr & 0xffffff00; for(i = 0; i < 256; i++) (void) addtarget(ntohl(addr + i)); } } /********************************************************************** Function: doicare Purpose: See if we monitor this address **********************************************************************/ struct scaninfo *doicare(addr) u_long addr; { struct scaninfo *si; int i; for(si = Gsilist; si; si = si->next) { if(si->addr == addr) return(si); } if(Gwatchlevel == HUMANITARIAN) /* Add a new address, we always care */ { si = addtarget(addr); return(si); } return(NULL); } /********************************************************************** Function: addtarget Purpose: Adds a new IP address to the list of hosts to watch. **********************************************************************/ struct scaninfo *addtarget(addr) u_long addr; { struct scaninfo *si; if((si = (struct scaninfo *)malloc(sizeof(struct scaninfo))) == NULL) { perror("malloc scaninfo"); exit(-1); } memset(si, 0, sizeof(struct scaninfo)); si->addr = addr; si->next = Gsilist; Gsilist = si; return(si); } /********************************************************************** Function: process_packet Purpose: Process raw packet and figure out what we need to to with it. Pulls the packet apart and stores key data in global areas for reference by other functions. **********************************************************************/ void process_packet(pkt, pktlen) u_char *pkt; int pktlen; { struct ethhdr *ep; struct iphdr *ip; static struct align { struct iphdr ip; char buf[PKTLEN]; } a1; u_short off; Gtimein = time((time_t *)0); ep = (struct ethhdr *) pkt; if(ntohs(ep->h_proto) != ETH_P_IP) return; pkt += sizeof(struct ethhdr); pktlen -= sizeof(struct ethhdr); memcpy(&a1, pkt, pktlen); ip = &a1.ip; Gsaddr = ip->saddr; Gdaddr = ip->daddr; if((Gsi = doicare(Gdaddr)) == NULL) return; off = ntohs(ip->frag_off); Gisfrag = (off & IP_MF); /* Set if packet is fragmented */ Giplen = ntohs(ip->tot_len); Gid = ntohs(ip->id); pkt = (u_char *)ip + (ip->ihl << 2); Giplen -= (ip->ihl << 2); switch(ip->protocol) { case IPPROTO_TCP: do_tcp(ep, pkt); break; case IPPROTO_UDP: do_udp(ep, pkt); break; case IPPROTO_ICMP: do_icmp(ep, pkt); break; default: break; } } /********************************************************************** Function: do_tcp Purpose: Process this TCP packet if it is important. **********************************************************************/ void do_tcp(ep, pkt) struct ethhdr *ep; u_char *pkt; { struct tcphdr *thdr; u_short sport, dport; thdr = (struct tcphdr *) pkt; if(thdr->th_flags & TH_RST) /* RST generates no response */ return; /* Therefore can't be used to scan. */ sport = ntohs(thdr->th_sport); dport = ntohs(thdr->th_dport); if(thdr->th_flags & TH_SYN) { if(Gsaddr == Gdaddr && sport == dport) { Gsi->land.atktime = Gtimein; Gsi->land.saddr = Gsaddr; memcpy(Gsi->land.eaddr, ep->h_source, ETH_ALEN); } } addtcp(sport, dport, thdr->th_flags, ep->h_source); } /********************************************************************** Function: addtcp Purpose: Add this TCP packet to our list. **********************************************************************/ void addtcp(sport, dport, flags, eaddr) u_short sport; u_short dport; u_char flags; u_char *eaddr; { struct pktin *pi, *last, *tpi; /* See if this packet relates to other packets already received. */ for(pi = Gsi->tcpin; pi; pi = pi->next) { if(pi->saddr == Gsaddr && pi->dport == dport) { if(flags == TH_SYN) addfloodinfo(pi, sport); else if((flags & TH_FIN) || (flags & TH_ACK)) rmfloodinfo(pi, sport); return; } last = pi; } /* Must be new entry */ if((tpi = (struct pktin *)malloc(sizeof(struct pktin))) == NULL) { perror("Malloc"); exit(-1); } memset(tpi, 0, sizeof(struct pktin)); memcpy(tpi->eaddr, eaddr, ETH_ALEN); tpi->saddr = Gsaddr; tpi->sport = sport; tpi->dport = dport; tpi->timein = Gtimein; if(flags == TH_SYN) addfloodinfo(tpi, sport); if(Gsi->tcpin) last->next = tpi; else Gsi->tcpin = tpi; } /********************************************************************** Function: addfloodinfo Purpose: Add floodinfo information **********************************************************************/ void addfloodinfo(pi, sport) struct pktin *pi; u_short sport; { struct floodinfo *fi; fi = (struct floodinfo *)malloc(sizeof(struct floodinfo)); if(fi == NULL) { perror("Malloc of floodinfo"); exit(-1); } memset(fi, 0, sizeof(struct floodinfo)); fi->sport = sport; fi->next = pi->fi; pi->fi = fi; } /********************************************************************** Function: rmfloodinfo Purpose: Removes floodinfo information **********************************************************************/ void rmfloodinfo(pi, sport) struct pktin *pi; u_short sport; { struct floodinfo *fi, *prev = NULL; for(fi = pi->fi; fi; fi = fi->next) { if(fi->sport == sport) break; prev = fi; } if(fi == NULL) return; if(prev == NULL) /* First element */ pi->fi = fi->next; else prev->next = fi->next; free(fi); } /********************************************************************** Function: do_udp Purpose: Process this udp packet. Currently teardrop and all its derivitives put 242 in the IP id field. This could obviously be changed. The truly paranoid might want to flag all fragmented UDP packets. The truly adventurous might enhance the code to track fragments and check them for overlaping boundaries. **********************************************************************/ void do_udp(ep, pkt) struct ethhdr *ep; u_char *pkt; { struct udphdr *uhdr; u_short sport, dport; uhdr = (struct udphdr *) pkt; if(Gid == 242 && Gisfrag) /* probable teardrop */ { Gsi->teardrop.saddr = Gsaddr; memcpy(Gsi->teardrop.eaddr, ep->h_source, ETH_ALEN); Gsi->teardrop.atktime = Gtimein; } sport = ntohs(uhdr->source); dport = ntohs(uhdr->dest); addudp(sport, dport, ep->h_source); } /********************************************************************** Function: addudp Purpose: Add this udp packet to our list. **********************************************************************/ void addudp(sport, dport, eaddr) u_short sport; u_short dport; u_char *eaddr; { struct pktin *pi, *last, *tpi; for(pi = Gsi->udpin; pi; pi = pi->next) { if(pi->saddr == Gsaddr && pi->dport == dport) { pi->timein = Gtimein; return; } last = pi; } /* Must be new entry */ if((tpi = (struct pktin *)malloc(sizeof(struct pktin))) == NULL) { perror("Malloc"); exit(-1); } memset(tpi, 0, sizeof(struct pktin)); memcpy(tpi->eaddr, eaddr, ETH_ALEN); tpi->saddr = Gsaddr; tpi->sport = sport; tpi->dport = dport; tpi->timein = Gtimein; if(Gsi->udpin) last->next = tpi; else Gsi->udpin = tpi; } /********************************************************************** Function: do_icmp Purpose: Process an ICMP packet. We assume there is no valid reason to receive a fragmented ICMP packet. **********************************************************************/ void do_icmp(ep, pkt) struct ethhdr *ep; u_char *pkt; { struct icmphdr *icmp; icmp = (struct icmphdr *) pkt; if(Gisfrag) /* probable ICMP attack (i.e. Ping of Death) */ { Gsi->icmpfrag.saddr = Gsaddr; memcpy(Gsi->icmpfrag.eaddr, ep->h_source, ETH_ALEN); Gsi->icmpfrag.atktime = Gtimein; } if(icmp->type == ICMP_ECHOREPLY) Gsi->icmpcnt++; return; } /********************************************************************** Function: clear_pkt Purpose: Delete and free space for any old packets. **********************************************************************/ void clear_pktin(si) struct scaninfo *si; { struct pktin *pi; struct floodinfo *fi, *tfi; time_t t, t2; t = time((time_t *)0); while(si->tcpin) { t2 = t - si->tcpin->timein; if(t2 > Gtimer) { pi = si->tcpin; fi = pi->fi; while(fi) { tfi = fi; fi = fi->next; free(tfi); } si->tcpin = pi->next; free(pi); } else break; } while(si->udpin) { t2 = t - si->udpin->timein; if(t2 > Gtimer) { pi = si->udpin; si->udpin = pi->next; free(pi); } else break; } } /********************************************************************** Function: print_info Purpose: Print out any alerts. **********************************************************************/ void print_info() { struct pktin *pi; struct addrlist *tcplist = NULL, *udplist = NULL, *al; struct floodinfo *fi; char buf[1024], *eaddr, abuf[32]; int i; strcpy(abuf, anetaddr(Gsi->addr)); if(Greportlevel == REPORTALL || Greportlevel == REPORTDOS) { if(Gsi->teardrop.atktime) { eaddr = ether_ntoa(Gsi->teardrop.eaddr); sprintf(buf, "Possible teardrop attack from %s (%s) against %s", anetaddr(Gsi->teardrop), eaddr, abuf); syslog(LOG_ALERT, buf); memset(&Gsi->teardrop, 0, sizeof(struct atk)); } if(Gsi->land.atktime) { eaddr = ether_ntoa(Gsi->land.eaddr); sprintf(buf, "Possible land attack from (%s) against %s", eaddr, abuf); syslog(LOG_ALERT, buf); memset(&Gsi->land, 0, sizeof(struct atk)); } if(Gsi->icmpfrag.atktime) { eaddr = ether_ntoa(Gsi->icmpfrag.eaddr); sprintf(buf, "ICMP fragment detected from %s (%s) against %s", anetaddr(Gsi->icmpfrag), eaddr, abuf); syslog(LOG_ALERT, buf); memset(&Gsi->icmpfrag, 0, sizeof(struct atk)); } if(Gsi->icmpcnt > Gicmplimit) { sprintf(buf, "ICMP ECHO threshold exceeded, smurfs up. I saw %d packets\n", Gsi->icmpcnt); syslog(LOG_ALERT, buf); Gsi->icmpcnt = 0; } } for(pi = Gsi->tcpin; pi; pi = pi->next) { i = 0; for(fi = pi->fi; fi; fi = fi->next) i++; if(Greportlevel == REPORTALL || Greportlevel == REPORTDOS) { if(i > Gsynflood) { eaddr = ether_ntoa(pi->eaddr); sprintf(buf, "Possible SYNFLOOD from %s (%s), against %s. I saw %d packets\n", anetaddr(pi->saddr), eaddr, abuf, i); syslog(LOG_ALERT, buf); } } for(al = tcplist; al; al = al->next) { if(pi->saddr == al->saddr) { al->cnt++; if(pi->sport == 80) al->wwwcnt++; break; } } if(al == NULL) /* new address */ { al = (struct addrlist *)malloc(sizeof(struct addrlist)); if(al == NULL) { perror("Malloc address list"); exit(-1); } memset(al, 0, sizeof(struct addrlist)); al->saddr = pi->saddr; al->cnt = 1; if(pi->sport == 80) al->wwwcnt = 1; al->next = tcplist; tcplist = al; } } if(Greportlevel == REPORTALL || Greportlevel == REPORTSCAN) { for(al = tcplist; al; al = al->next) { if((al->cnt - al->wwwcnt) > Gportlimit || al->wwwcnt > Gwebcount) { sprintf(buf, "Possible TCP port scan from %s (%d ports) against %s\n", anetaddr(al->saddr), al->cnt, abuf); syslog(LOG_ALERT, buf); } } for(pi = Gsi->udpin; pi; pi = pi->next) { for(al = udplist; al; al = al->next) { if(pi->saddr == al->saddr) { al->cnt++; break; } } if(al == NULL) /* new address */ { al = (struct addrlist *)malloc(sizeof(struct addrlist)); if(al == NULL) { perror("Malloc address list"); exit(-1); } memset(al, 0, sizeof(struct addrlist)); al->saddr = pi->saddr; al->cnt = 1; al->next = udplist; udplist = al; } } for(al = udplist; al; al = al->next) { if(al->cnt > Gportlimit) { sprintf(buf, "Possible UDP port scan from %s (%d ports) against %s\n", anetaddr(al->saddr), al->cnt, abuf); syslog(LOG_ALERT, buf); } } } while(tcplist) { al = tcplist->next; free(tcplist); tcplist = al; } while(udplist) { al = udplist->next; free(udplist); udplist = al; } } /************************************************************************ Function: anetaddr Description: Another version of the intoa function. ************************************************************************/ char *anetaddr(addr) u_long addr; { u_long naddr; static char buf[16]; u_char b[4]; int i; naddr = ntohl(addr); for(i = 3; i >= 0; i--) { b[i] = (u_char) (naddr & 0xff); naddr >>= 8; } sprintf(buf, "%d.%d.%d.%d", b[0], b[1], b[2], b[3]); return(buf); } /************************************************************************ Function: initdevice Description: Set up the network device so we can read it. **************************************************************************/ initdevice(fd_flags, dflags) int fd_flags; u_long dflags; { struct ifreq ifr; int fd, flags = 0; if((fd = socket(PF_INET, SOCK_PACKET, htons(0x0003))) < 0) { perror("Cannot open device socket"); exit(-1); } /* Get the existing interface flags */ strcpy(ifr.ifr_name, Gdevice); if(ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { perror("Cannot get interface flags"); exit(-1); } ifr.ifr_flags |= IFF_PROMISC; if(ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) { perror("Cannot set interface flags"); exit(-1); } return(fd); } /************************************************************************ Function: readdevice Description: Read a packet from the device. **************************************************************************/ u_char *readdevice(fd, pktlen) int fd; int *pktlen; { int cc = 0, from_len, readmore = 1; struct sockaddr from; static u_char pktbuffer[PKTLEN]; u_char *cp; while(readmore) { from_len = sizeof(from); if((cc = recvfrom(fd, pktbuffer, PKTLEN, 0, &from, &from_len)) < 0) { if(errno != EWOULDBLOCK) return(NULL); } if(strcmp(Gdevice, from.sa_data) == 0) readmore = 0; } *pktlen = cc; return(pktbuffer); } /************************************************************************* Function: ether_ntoa Description: Translates a MAC address into ascii. This function emulates the ether_ntoa function that exists on Sun and Solaris, but not on Linux. It could probably (almost certainly) be more efficent, but it will do. *************************************************************************/ char *ether_ntoa(etheraddr) u_char etheraddr[ETH_ALEN]; { int i, j; static char eout[32]; char tbuf[10]; for(i = 0, j = 0; i < 5; i++) { eout[j++] = etheraddr[i] >> 4; eout[j++] = etheraddr[i] & 0xF; eout[j++] = ':'; } eout[j++] = etheraddr[i] >> 4; eout[j++] = etheraddr[i] & 0xF; eout[j++] = '\0'; for(i = 0; i < 17; i++) { if(eout[i] < 10) eout[i] += 0x30; else if(eout[i] < 16) eout[i] += 0x57; } return(eout); } <--> ----[ EOF

<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>

 Добавить комментарий
Имя:
E-Mail:
Заголовок:
Текст:




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру