|
/* Test if a host is in promiscuous mode. * Copyright (C) 1998 Richard W.M. Jones (rjones@orchestream.com) * This program is GPL. It is derived from a program by * Paul Gortmaker (called bogon.c), also under GPL. * * It works as follows: send out a ICMP echo request to the host * in question, but wrap the echo request in a bogus ethernet packet. * If the host is acting normally, it will ignore the bogus packet. * If the host is listening to the network in promiscuous mode, then * it will pick up the packet and push it up to the IP layer which * will respond to the ping. This is obviously not foolproof, since * you could modify your kernel to disallow responses to echo requests. */ #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <malloc.h> #include <string.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <net/if.h> #include <netinet/if_ether.h> #include <netinet/ip.h> #include <netinet/in.h> #include <netinet/ip_icmp.h> #include <asm/checksum.h> #define PACKET_SIZE 1024 // Bogus ethernet MAC address. unsigned char bogus[ETH_ALEN] = { 0, 0x60, 0x97, 0xb4, 0x34, 0x82 }; unsigned char us[ETH_ALEN]; struct ifreq ifreq; struct ethhdr *eth_pkt; struct iphdr *ip_pkt; struct icmphdr *icmp_pkt; int fd, i, j; unsigned char *packet; struct in_addr ip_dest; struct hostent *dest_name; struct in_addr ip_source; // Set the ethernet interface here. #define INTERFACE "eth0" struct sockaddr interface = { AF_INET, INTERFACE }; void main (int argc, char **argv) { if (argc != 2) { fprintf (stderr, "Usage: promisc destination\n"); exit (1); } dest_name = gethostbyname (argv [1]); if (dest_name == NULL) { perror (argv [1]); exit (1); } ip_dest = *(struct in_addr *) (dest_name->h_addr); printf ("Destination IP address: %s\n", inet_ntoa (ip_dest)); fd = socket (AF_INET, SOCK_PACKET, htons (ETH_P_802_3)); if (fd == -1) { perror ("socket"); exit (1); } strcpy (ifreq.ifr_name, INTERFACE); if (ioctl (fd, SIOCGIFHWADDR, &ifreq) < 0) { perror ("SIOCGIFHWADDR"); exit (1); } memcpy (us, ifreq.ifr_hwaddr.sa_data, ETH_ALEN); printf ("My ethernet address: "); for (i = 0; i < ETH_ALEN; i++) printf (" %X", us[i]); printf ("\n"); strcpy (ifreq.ifr_name, INTERFACE); if (ioctl (fd, SIOCGIFADDR, &ifreq) < 0) { perror ("SIOCGIFADDR"); exit (1); } memcpy (&ip_source, &((struct sockaddr_in *) &ifreq.ifr_ifru.ifru_addr)->sin_addr, sizeof (struct sockaddr_in)); printf ("My IP address: %s\n", inet_ntoa (ip_source)); packet = (char *) malloc (PACKET_SIZE); if (packet == NULL) { perror ("malloc"); exit (1); } memset (packet, 0, PACKET_SIZE); /* Fill out the ethernet header. */ eth_pkt = (struct ethhdr *) packet; memcpy (eth_pkt->h_dest, bogus, ETH_ALEN); memcpy (eth_pkt->h_source, us, ETH_ALEN); eth_pkt->h_proto = htons (ETH_P_IP); /* Fill out the IP header. */ ip_pkt = (struct iphdr *) (packet + sizeof (struct ethhdr)); ip_pkt->ihl = 5; /* Header length / 4. Always 5 if no opts. */ ip_pkt->version = 4; /* IP version. Always 4. */ ip_pkt->tos = 0; /* Type of service. 8 bits. */ /* Total length. Bytes, up to 64K. */ ip_pkt->tot_len = htons (PACKET_SIZE - sizeof (struct ethhdr)); ip_pkt->id = 0; /* Identification. */ ip_pkt->frag_off = 0; /* Fragment offset. */ ip_pkt->ttl = 64; /* Time to live. 8 bits. */ ip_pkt->protocol = IPPROTO_ICMP; /* Protocol. IPPROTO_xxx */ /* Source address. IP address. */ ip_pkt->saddr = ip_source.s_addr; /* Destination address.IP address. */ ip_pkt->daddr = ip_dest.s_addr; /* Compute the IP header checksum. */ ip_pkt->check = 0; ip_pkt->check = ip_fast_csum ((unsigned char *) ip_pkt, ip_pkt->ihl); /* Construct the echo request. */ icmp_pkt = (struct icmphdr *) (packet + sizeof (struct ethhdr) + sizeof (struct iphdr)); icmp_pkt->type = ICMP_ECHO; icmp_pkt->code = 0; icmp_pkt->checksum = ip_fast_csum ((unsigned char *) icmp_pkt, sizeof (struct icmphdr)); /* Send 10 packets. */ for (j = 0; j < 10; j++) { i = sendto (fd, packet, PACKET_SIZE, 0, &interface, sizeof (struct sockaddr)); if (i < 0) { perror ("sendto"); exit (1); } } printf ("sent %d bytes %d times.\n", i, j); exit (0); } ------------------------------------------------------------------- --- /mnt/cdrom/c/promisc.c Thu Jan 29 13:28:52 1998 +++ promisc.c Tue Nov 10 17:53:01 1998 @@ -28,11 +28,22 @@ #include <netinet/ip.h> #include <netinet/in.h> #include <netinet/ip_icmp.h> + +/* Hack for kernel >= 2.1 */ +#if defined(linux) +#include <linux/version.h> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) +typedef unsigned short __u16; +typedef unsigned int __u32; +#define VERIFY_WRITE 0 +#endif +#endif + #include <asm/checksum.h> #define PACKET_SIZE 1024 -// Bogus ethernet MAC address. +/* Bogus ethernet MAC address. */ unsigned char bogus[ETH_ALEN] = { 0, 0x60, 0x97, 0xb4, 0x34, 0x82 }; unsigned char us[ETH_ALEN]; @@ -49,11 +60,11 @@ struct in_addr ip_source; -// Set the ethernet interface here. +/* Set the ethernet interface here. */ #define INTERFACE "eth0" struct sockaddr interface = { AF_INET, INTERFACE }; -void +int main (int argc, char **argv) { if (argc != 2) @@ -155,6 +166,8 @@ perror ("sendto"); exit (1); } + + sleep (1); } printf ("sent %d bytes %d times.\n", i, j);