: This is a shar archive. Extract with sh, not csh. echo x - README sed -e 's/^X//' > README << '!Funky!Stuff!' X This code is an example of how to write raw frames to a datalink, Xusing the libpcap library. This example writes a gratuitous ARP frame Xusing hardcoded constants. This code is UNSUPPORTED and was hacked Xtogether just to show that it is easy to write, as well as read, using Xlibpcap. There are only a few things required to write using libpcap: X X- Some datalinks are opened read-only and you must change this to be X read-write. For example, the call to open() in pcap-bpf.c must be X changed from O_RDONLY to O_RDWR. Some datalinks are already opened X read-write (e.g., pcap-dlpi.c) so no change is required for these. X X- You use the descriptor that libpcap has already opened for the datalink. X To do this you must #include the pcap-int.h header in your libpcap/ X directory, and use the fd member of the pcap{} structure. X XThen just build your raw frame (e.g., a raw Ethernet frame starting with Xthe 6-byte destination Ethernet address) and call write(). X XNote the difference between a raw IP socket, which lets you write any Xtype of IP datagram, versus using libpcap as in this example, which lets Xyou write any type of datalink frame. X X Rich Stevens !Funky!Stuff! echo x - Makefile sed -e 's/^X//' > Makefile << '!Funky!Stuff!' Xinclude ../Make.defines X XOBJS = main.o pcap.o writepcap.o XPROGS = writepcap X Xall: ${PROGS} X X# Also need /usr/local/src/libpcap-0.2.1/pcap-bpf.o for BSD/OS Xwritepcap: ${OBJS} X ${CC} ${CFLAGS} -o $@ ${OBJS} \ X /usr/local/lib/libpcap.a ${LIBS} X Xclean: X rm -f ${PROGS} ${CLEANFILES} !Funky!Stuff! echo x - main.c sed -e 's/^X//' > main.c << '!Funky!Stuff!' X#include "writepcap.h" X X /* DefinE global variables */ X Xint datalink; /* from pcap_datalink(), in */ Xchar *device; /* pcap device */ Xint fddipad; /* HACK; for libpcap if FDDI defined */ Xpcap_t *pd; /* packet capture struct pointer */ Xint snaplen = 200; /* amount of data to capture */ Xint verbose; X Xstatic void usage(const char *); X Xint Xmain(int argc, char *argv[]) X{ X int c; X char *ptr, localname[1024]; X X if (argc < 2) X usage(""); X X /* X * Need local IP address for source IP address for UDP datagrams. X * Can't specify 0 and let IP choose, as we need to know it for X * the pseudo-header to calculate the UDP checksum. X * Both localname and localport can be overridden by -l option. X */ X X if (gethostname(localname, sizeof(localname)) < 0) X err_sys("gethostname error"); X X opterr = 0; /* don't want getopt() writing to stderr */ X while ( (c = getopt(argc, argv, "i:l:v")) != -1) { X switch (c) { X X case 'i': X device = optarg; /* pcap device */ X break; X X case 'l': /* local IP address: a.b.c.d */ X if ( (ptr = strrchr(optarg, '.')) == NULL) X usage("invalid -l option"); X X *ptr++ = 0; /* null replaces final period */ X strcpy(localname, optarg); /* save dotted-decimal IP */ X break; X X case 'v': X verbose = 1; X break; X X case '?': X usage("unrecognized option"); X } X } X X open_pcap(); /* open packet capture device */ X X setuid(getuid()); /* don't need superuser privileges any more */ X X write_pcap(); X X exit(0); X} X Xstatic void Xusage(const char *msg) X{ X err_msg( X"usage: writepcap [ options ] \n" X"options: -i s packet capture device\n" X" -l a.b.c.d.p local IP=a.b.c.d, local port=p\n" X" -v verbose output" X); X X if (msg[0] != 0) X err_quit("%s", msg); X exit(1); X} !Funky!Stuff! echo x - pcap.c sed -e 's/^X//' > pcap.c << '!Funky!Stuff!' X#include "writepcap.h" X Xvoid Xopen_pcap(void) X{ X u_long localnet, netmask; X char errbuf[PCAP_ERRBUF_SIZE]; X X if (device == NULL) { X if ( (device = pcap_lookupdev(errbuf)) == NULL) X err_quit("pcap_lookup: %s", errbuf); X } X printf("device = %s\n", device); X X /* hardcode: promisc=0, to_ms=500 */ X if ( (pd = pcap_open_live(device, snaplen, 0, 500, errbuf)) == NULL) X err_quit("pcap_open_live: %s", errbuf); X X if (pcap_lookupnet(device, &localnet, &netmask, errbuf) < 0) X err_quit("pcap_lookupnet: %s", errbuf); X if (verbose) X printf("localnet = %lx, netmask = %lx\n", X ntohl(localnet), ntohl(netmask)); X X if ( (datalink = pcap_datalink(pd)) < 0) X err_quit("pcap_datalink: %s", pcap_geterr(pd)); X if (verbose) X printf("data link = %d\n", datalink); X} !Funky!Stuff! echo x - writepcap.c sed -e 's/^X//' > writepcap.c << '!Funky!Stuff!' X#include "writepcap.h" X X/* char enet_src[6] = {0x00, 0x20, 0xaf, 0x9c, 0xee, 0x95}; */ Xchar enet_src[6] = {0x08, 0x00, 0x20, 0x78, 0xe3, 0xe3}; Xchar enet_dst[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; Xchar ip_src[4] = {206, 62, 226, 35}; Xchar ip_dst[4] = {206, 62, 226, 35}; X /* source and destination IP the same for gratuitous ARP */ X X#include "/usr/local/src/libpcap-0.2.1/pcap-int.h" X Xvoid Xsend_grat_arp(void) X{ X char buf[42]; X struct ether_header *eptr; X struct ether_arp *aptr; X X /* See Figure 21.7, p. 681 of Volume 2 */ X bzero(buf, sizeof(buf)); X eptr = buf; /* start of 16-byte Ethernet header */ X aptr = &buf[14]; /* start of 28-byte ARP packet */ X /* BSD defines ether_dhost as an array, Solaris as a struct. X Sigh. We'll just skip these two members */ X memcpy(&buf[0], enet_dst, 6); X memcpy(&buf[6], enet_src, 6); X eptr->ether_type = htons(ETHERTYPE_ARP); X X aptr->ea_hdr.ar_hrd = htons(ARPHRD_ETHER); X aptr->ea_hdr.ar_pro = htons(ETHERTYPE_IP); X aptr->ea_hdr.ar_hln = 6; X aptr->ea_hdr.ar_pln = 4; X aptr->ea_hdr.ar_op = htons(ARPOP_REQUEST); X memcpy(aptr->arp_sha, enet_src, 6); X /* aptr->arp_tha[] left empty */ X memcpy(aptr->arp_spa, ip_src, 4); X memcpy(aptr->arp_tpa, ip_dst, 4); X X if (write(pd->fd, buf, sizeof(buf)) != sizeof(buf)) X err_sys("write error to pcap device"); X} X Xvoid Xwrite_pcap(void) X{ X send_grat_arp(); X sleep(1); X} !Funky!Stuff! echo x - writepcap.h sed -e 's/^X//' > writepcap.h << '!Funky!Stuff!' X#include "unp.h" X#include X X#include /* required for ip.h */ X#include X#include X#include X#include X#include X#include X#include X X /* declare global variables */ Xextern int datalink; Xextern char *device; Xextern pcap_t *pd; Xextern int rawfd; Xextern int snaplen; Xextern int verbose; X X /* function prototypes */ Xvoid cleanup(int); Xvoid open_pcap(void); Xvoid write_pcap(void); !Funky!Stuff! exit