Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 24 Aug 1995 19:07:21 +0900
From:      Toshihiro Kanda <candy@fct.kgc.co.jp>
To:        guido@gvr.win.tue.nl (Guido van Rooij)
Cc:        FreeBSD-hackers@freefall.FreeBSD.org
Subject:   bpf output examples
Message-ID:  <199508241007.TAA18570@xxx.fct.kgc.co.jp>
In-Reply-To: guido@gvr.win.tue.nl's message of 24 Aug 1995 12:19:38 %2B0900

next in thread | raw e-mail | index | archive | help
> Does anyone have a pointer to a program that uses the write feature
> fopr bpf? Tcpdump only reads, as does libpcap etc..
> 
> -Guido

  Here's a very PART of my program which talks EtherTalk Phase 2.
Pardon for comments in Japanese.  See bpf(4) which once lost in
FreeBSD 2.0 :-)

You can write to bpf by:
   err = write(bpf_fd, ether_frame, len);

Warning: If you use FreeBSD 2.0 or 2.0.5, Ethernet type field
(ether_frame[12] and ether_frame[13]) must be in machine byte order
NOT network byte order.  I thought it's a bug and asked
hackers@freebsd, though no answer was given yet.

candy@fct.kgc.co.jp (Toshihiro Kanda)

---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ----

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <errno.h>
#include <fcntl.h> /* open */
#include <unistd.h>
#include <sys/uio.h> /* read */
#include <sys/param.h>
#include <netdb.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <net/bpf.h>
#include <net/if.h> /* struct ifr */


#define BPF_BUFFER_SIZE 0x8000 /* bpf read buffer */

static volatile unsigned ringring;
static unsigned char mac_addr[6];
static int bpf_fd;
static unsigned int bpf_len;
static struct bpf_program prog;
static char *bpf_buf;
static void (*callback)(unsigned long, void *, unsigned long, unsigned long);
static int pipe_fd[2];
static int child;

/*
 * bpf $B%W%m%0%i%`(B
 */
static struct bpf_insn insns[] = {
/* GENERATED by tcpdump. source is:
#!/bin/sh
super tcpdump -dds-1 '
(
  (ether[0:2] == 0x0000 and ether[2:4] == 0x1b384d97) or
  (ether[0:2] == 0xffff and ether[2:4] == 0xffffffff) or
  (ether[0:2] == 0x0900 and
     (ether[2:4] == 0x07ffffff or
        (ether[2:4] >= 0x07000000 and ether[2:4] <= 0x070000fc)))
)
and
(
  (ether[12:2] == 0x809b or ether[12:2] == 0x80f3) or
  (ether[12:2] < 0x600 and ether[14:2] == 0xaaaa and
     (ether[20:2] == 0x809b or ether[20:2] == 0x80f3))
)
'
*/
{ 0x28, 0, 0, 0x00000000 },
{ 0x15, 0, 2, 0x00000000 },
{ 0x20, 0, 0, 0x00000002 },
{ 0x15, 10, 0, 0x1b384d97 },
{ 0x28, 0, 0, 0x00000000 },
{ 0x15, 0, 2, 0x0000ffff },
{ 0x20, 0, 0, 0x00000002 },
{ 0x15, 6, 0, 0xffffffff },
{ 0x28, 0, 0, 0x00000000 },
{ 0x15, 0, 14, 0x00000900 },
{ 0x20, 0, 0, 0x00000002 },
{ 0x15, 2, 0, 0x07ffffff },
{ 0x35, 0, 11, 0x07000000 },
{ 0x25, 10, 0, 0x070000fc },
{ 0x28, 0, 0, 0x0000000c },
{ 0x15, 7, 0, 0x0000809b },
{ 0x15, 6, 0, 0x000080f3 },
{ 0x35, 6, 0, 0x00000600 },
{ 0x28, 0, 0, 0x0000000e },
{ 0x15, 0, 4, 0x0000aaaa },
{ 0x28, 0, 0, 0x00000014 },
{ 0x15, 1, 0, 0x0000809b },
{ 0x15, 0, 1, 0x000080f3 },
{ 0x6, 0, 0, 0xffffffff },
{ 0x6, 0, 0, 0x00000000 },
};

/* 
 * bpf?? $B$r%*!<%W%s(B
 */
static int
open_bpf(void)
{
	int fd = -1, n = 0;
	char name[32];
	do {
		sprintf(name, "/dev/bpf%d", n++);
		errno = 0;
		fd = open(name, O_RDWR);
	} while (fd < 0 && errno == EBUSY);
	return fd;
}/* open_bfp */

/*
 * bpf $B$r%*!<%W%s$73F<o@_Dj$r$9$k!#(B
 */
static int
open_dev(const char *name, struct bpf_program *prog)
{
	int err = -1, fd = open_bpf();
	if (fd >= 0) {
		/* $B$^$:%P!<%8%g%s$r%A%'%C%/$9$k!#(B */
		struct bpf_version ver;
		if (ioctl(fd, BIOCVERSION, &ver) == 0) {
			if (BPF_MAJOR_VERSION == ver.bv_major && BPF_MINOR_VERSION <= ver.bv_minor) {
				/* bpf $B$NFI$_9~$_%P%C%U%!%5%$%:$r@_Dj$9$k!#(B */
				unsigned int blen = BPF_BUFFER_SIZE;
				if (ioctl(fd, BIOCSBLEN, &blen) == 0) {
					/* $B%O!<%I%&%(%"%$%s%?!<%U%'!<%9$r@_Dj$9$k!#(B */
					struct ifreq ifr;
					strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
					if (ioctl(fd, BIOCSETIF, &ifr) == 0) {
						/* promiscuous $B%b!<%I$K$9$k(B */
						if (ioctl(fd, BIOCPROMISC, NULL) == 0) {
							/* immediate $B%b!<%I$K$9$k(B */
							unsigned int im = 1;
							if (ioctl(fd, BIOCIMMEDIATE, &im) == 0) {
								/* $B%U%#%k%?%W%m%0%i%`$r@_Dj$9$k!#(B */
								if (ioctl(fd, BIOCSETF, prog) == 0) {
#if 0
									/* $B%G!<%?%j%s%/%?%$%W$rD4$Y$k(B */
									unsigned dlt;
									if (ioctl(fd, BIOCGDLT, &dlt) == 0) {
										printf("DLT=%u\n", dlt);
									}
#endif
									err = fd;
								}
							}
						}
					}
				}
			}
		}
		if (err < 0)
			close(fd);
	}
	return err;
}/* open_dev */

/*
 * unix version only
 */
int
ETDInit(void)
{
	int err = -1;
	extern int getmac(char *ifname, char *result);
	getmac("ed0", mac_addr);
	insns[1].k = GETUW(&mac_addr[0]);
	insns[3].k = GETUL(&mac_addr[2]);
	prog.bf_len = sizeof(insns) / sizeof(insns[0]);
	prog.bf_insns = insns;
	bpf_fd = open_dev("ed0", &prog);
#ifdef unix
	setgid(getgid());
	setuid(getuid());
#endif
	if (bpf_fd >= 0) {
		if (ioctl(bpf_fd, BIOCGBLEN, &bpf_len) == 0) {
			bpf_buf = malloc(bpf_len);
			if (bpf_buf != NULL) {
				err = 0;
			}
		}
	}
	return err;
}/* ETDInit */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199508241007.TAA18570>