1ea022d16SRodney W. Grimes /* 2ea022d16SRodney W. Grimes * Copyright (c) 1988, 1992 The University of Utah and the Center 3ea022d16SRodney W. Grimes * for Software Science (CSS). 4ea022d16SRodney W. Grimes * Copyright (c) 1992, 1993 5ea022d16SRodney W. Grimes * The Regents of the University of California. All rights reserved. 6ea022d16SRodney W. Grimes * 7ea022d16SRodney W. Grimes * This code is derived from software contributed to Berkeley by 8ea022d16SRodney W. Grimes * the Center for Software Science of the University of Utah Computer 9ea022d16SRodney W. Grimes * Science Department. CSS requests users of this software to return 10ea022d16SRodney W. Grimes * to css-dist@cs.utah.edu any improvements that they make and grant 11ea022d16SRodney W. Grimes * CSS redistribution rights. 12ea022d16SRodney W. Grimes * 13ea022d16SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 14ea022d16SRodney W. Grimes * modification, are permitted provided that the following conditions 15ea022d16SRodney W. Grimes * are met: 16ea022d16SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 17ea022d16SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 18ea022d16SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 19ea022d16SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 20ea022d16SRodney W. Grimes * documentation and/or other materials provided with the distribution. 21ea022d16SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 22ea022d16SRodney W. Grimes * must display the following acknowledgement: 23ea022d16SRodney W. Grimes * This product includes software developed by the University of 24ea022d16SRodney W. Grimes * California, Berkeley and its contributors. 25ea022d16SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 26ea022d16SRodney W. Grimes * may be used to endorse or promote products derived from this software 27ea022d16SRodney W. Grimes * without specific prior written permission. 28ea022d16SRodney W. Grimes * 29ea022d16SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30ea022d16SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31ea022d16SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32ea022d16SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33ea022d16SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34ea022d16SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35ea022d16SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36ea022d16SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37ea022d16SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38ea022d16SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39ea022d16SRodney W. Grimes * SUCH DAMAGE. 40ea022d16SRodney W. Grimes * 415c8709fdSSteve Price * from: @(#)bpf.c 8.1 (Berkeley) 6/4/93 425c8709fdSSteve Price * $Id: bpf.c,v 1.6 1997/02/22 14:21:57 peter Exp $ 43ea022d16SRodney W. Grimes * 445c8709fdSSteve Price * From: Utah Hdr: bpf.c 3.1 92/07/06 45ea022d16SRodney W. Grimes * Author: Jeff Forys, University of Utah CSS 46ea022d16SRodney W. Grimes */ 47ea022d16SRodney W. Grimes 48ea022d16SRodney W. Grimes #ifndef lint 495c8709fdSSteve Price static const char sccsid[] = "@(#)bpf.c 8.1 (Berkeley) 6/4/93"; 50ea022d16SRodney W. Grimes #endif /* not lint */ 51ea022d16SRodney W. Grimes 52ea022d16SRodney W. Grimes #include <sys/param.h> 53ea022d16SRodney W. Grimes #include <sys/ioctl.h> 54ea022d16SRodney W. Grimes #include <sys/socket.h> 55628d2ac1SGarrett Wollman #include <sys/time.h> 56ea022d16SRodney W. Grimes 57ea022d16SRodney W. Grimes #include <net/if.h> 58ea022d16SRodney W. Grimes #include <net/bpf.h> 59ea022d16SRodney W. Grimes 60ea022d16SRodney W. Grimes #include <ctype.h> 61ea022d16SRodney W. Grimes #include <errno.h> 62ea022d16SRodney W. Grimes #include <fcntl.h> 63ea022d16SRodney W. Grimes #include <stdio.h> 64ea022d16SRodney W. Grimes #include <stdlib.h> 65ea022d16SRodney W. Grimes #include <string.h> 66ea022d16SRodney W. Grimes #include <syslog.h> 67ea022d16SRodney W. Grimes #include <unistd.h> 68ea022d16SRodney W. Grimes #include "defs.h" 69ea022d16SRodney W. Grimes #include "pathnames.h" 70ea022d16SRodney W. Grimes 71ea022d16SRodney W. Grimes static int BpfFd = -1; 72ea022d16SRodney W. Grimes static unsigned BpfLen = 0; 735c8709fdSSteve Price static u_int8_t *BpfPkt = NULL; 74ea022d16SRodney W. Grimes 75ea022d16SRodney W. Grimes /* 76ea022d16SRodney W. Grimes ** BpfOpen -- Open and initialize a BPF device. 77ea022d16SRodney W. Grimes ** 78ea022d16SRodney W. Grimes ** Parameters: 79ea022d16SRodney W. Grimes ** None. 80ea022d16SRodney W. Grimes ** 81ea022d16SRodney W. Grimes ** Returns: 82ea022d16SRodney W. Grimes ** File descriptor of opened BPF device (for select() etc). 83ea022d16SRodney W. Grimes ** 84ea022d16SRodney W. Grimes ** Side Effects: 85ea022d16SRodney W. Grimes ** If an error is encountered, the program terminates here. 86ea022d16SRodney W. Grimes */ 87ea022d16SRodney W. Grimes int 88ea022d16SRodney W. Grimes BpfOpen() 89ea022d16SRodney W. Grimes { 90ea022d16SRodney W. Grimes struct ifreq ifr; 91ea022d16SRodney W. Grimes char bpfdev[32]; 92ea022d16SRodney W. Grimes int n = 0; 93ea022d16SRodney W. Grimes 94ea022d16SRodney W. Grimes /* 95ea022d16SRodney W. Grimes * Open the first available BPF device. 96ea022d16SRodney W. Grimes */ 97ea022d16SRodney W. Grimes do { 98ea022d16SRodney W. Grimes (void) sprintf(bpfdev, _PATH_BPF, n++); 99ea022d16SRodney W. Grimes BpfFd = open(bpfdev, O_RDWR); 100ea022d16SRodney W. Grimes } while (BpfFd < 0 && (errno == EBUSY || errno == EPERM)); 101ea022d16SRodney W. Grimes 102ea022d16SRodney W. Grimes if (BpfFd < 0) { 103ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: no available devices: %m"); 104ea022d16SRodney W. Grimes Exit(0); 105ea022d16SRodney W. Grimes } 106ea022d16SRodney W. Grimes 107ea022d16SRodney W. Grimes /* 108ea022d16SRodney W. Grimes * Set interface name for bpf device, get data link layer 109ea022d16SRodney W. Grimes * type and make sure it's type Ethernet. 110ea022d16SRodney W. Grimes */ 111ea022d16SRodney W. Grimes (void) strncpy(ifr.ifr_name, IntfName, sizeof(ifr.ifr_name)); 112ea022d16SRodney W. Grimes if (ioctl(BpfFd, BIOCSETIF, (caddr_t)&ifr) < 0) { 113ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: ioctl(BIOCSETIF,%s): %m", IntfName); 114ea022d16SRodney W. Grimes Exit(0); 115ea022d16SRodney W. Grimes } 116ea022d16SRodney W. Grimes 117ea022d16SRodney W. Grimes /* 118ea022d16SRodney W. Grimes * Make sure we are dealing with an Ethernet device. 119ea022d16SRodney W. Grimes */ 120ea022d16SRodney W. Grimes if (ioctl(BpfFd, BIOCGDLT, (caddr_t)&n) < 0) { 121ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: ioctl(BIOCGDLT): %m"); 122ea022d16SRodney W. Grimes Exit(0); 123ea022d16SRodney W. Grimes } 124ea022d16SRodney W. Grimes if (n != DLT_EN10MB) { 125ea022d16SRodney W. Grimes syslog(LOG_ERR,"bpf: %s: data-link type %d unsupported", 126ea022d16SRodney W. Grimes IntfName, n); 127ea022d16SRodney W. Grimes Exit(0); 128ea022d16SRodney W. Grimes } 129ea022d16SRodney W. Grimes 130ea022d16SRodney W. Grimes /* 131ea022d16SRodney W. Grimes * On read(), return packets immediately (do not buffer them). 132ea022d16SRodney W. Grimes */ 133ea022d16SRodney W. Grimes n = 1; 134ea022d16SRodney W. Grimes if (ioctl(BpfFd, BIOCIMMEDIATE, (caddr_t)&n) < 0) { 135ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: ioctl(BIOCIMMEDIATE): %m"); 136ea022d16SRodney W. Grimes Exit(0); 137ea022d16SRodney W. Grimes } 138ea022d16SRodney W. Grimes 139ea022d16SRodney W. Grimes /* 140ea022d16SRodney W. Grimes * Try to enable the chip/driver's multicast address filter to 141ea022d16SRodney W. Grimes * grab our RMP address. If this fails, try promiscuous mode. 142ea022d16SRodney W. Grimes * If this fails, there's no way we are going to get any RMP 143ea022d16SRodney W. Grimes * packets so just exit here. 144ea022d16SRodney W. Grimes */ 145ea022d16SRodney W. Grimes #ifdef MSG_EOR 146ea022d16SRodney W. Grimes ifr.ifr_addr.sa_len = RMP_ADDRLEN + 2; 147ea022d16SRodney W. Grimes #endif 148ea022d16SRodney W. Grimes ifr.ifr_addr.sa_family = AF_UNSPEC; 149ea022d16SRodney W. Grimes bcopy(&RmpMcastAddr[0], (char *)&ifr.ifr_addr.sa_data[0], RMP_ADDRLEN); 150ea022d16SRodney W. Grimes if (ioctl(BpfFd, BIOCPROMISC, (caddr_t)0) < 0) { 151ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: can't set promiscuous mode: %m"); 152ea022d16SRodney W. Grimes Exit(0); 153ea022d16SRodney W. Grimes } 154ea022d16SRodney W. Grimes 155ea022d16SRodney W. Grimes /* 156ea022d16SRodney W. Grimes * Ask BPF how much buffer space it requires and allocate one. 157ea022d16SRodney W. Grimes */ 158ea022d16SRodney W. Grimes if (ioctl(BpfFd, BIOCGBLEN, (caddr_t)&BpfLen) < 0) { 159ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: ioctl(BIOCGBLEN): %m"); 160ea022d16SRodney W. Grimes Exit(0); 161ea022d16SRodney W. Grimes } 162ea022d16SRodney W. Grimes if (BpfPkt == NULL) 1635c8709fdSSteve Price BpfPkt = (u_int8_t *)malloc(BpfLen); 164ea022d16SRodney W. Grimes 165ea022d16SRodney W. Grimes if (BpfPkt == NULL) { 166ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: out of memory (%u bytes for bpfpkt)", 167ea022d16SRodney W. Grimes BpfLen); 168ea022d16SRodney W. Grimes Exit(0); 169ea022d16SRodney W. Grimes } 170ea022d16SRodney W. Grimes 171ea022d16SRodney W. Grimes /* 172ea022d16SRodney W. Grimes * Write a little program to snarf RMP Boot packets and stuff 173ea022d16SRodney W. Grimes * it down BPF's throat (i.e. set up the packet filter). 174ea022d16SRodney W. Grimes */ 175ea022d16SRodney W. Grimes { 176ea022d16SRodney W. Grimes #define RMP ((struct rmp_packet *)0) 177ea022d16SRodney W. Grimes static struct bpf_insn bpf_insn[] = { 178ea022d16SRodney W. Grimes { BPF_LD|BPF_B|BPF_ABS, 0, 0, (long)&RMP->hp_llc.dsap }, 179ea022d16SRodney W. Grimes { BPF_JMP|BPF_JEQ|BPF_K, 0, 5, IEEE_DSAP_HP }, 180ea022d16SRodney W. Grimes { BPF_LD|BPF_H|BPF_ABS, 0, 0, (long)&RMP->hp_llc.cntrl }, 181ea022d16SRodney W. Grimes { BPF_JMP|BPF_JEQ|BPF_K, 0, 3, IEEE_CNTL_HP }, 182ea022d16SRodney W. Grimes { BPF_LD|BPF_H|BPF_ABS, 0, 0, (long)&RMP->hp_llc.dxsap }, 183ea022d16SRodney W. Grimes { BPF_JMP|BPF_JEQ|BPF_K, 0, 1, HPEXT_DXSAP }, 184ea022d16SRodney W. Grimes { BPF_RET|BPF_K, 0, 0, RMP_MAX_PACKET }, 185ea022d16SRodney W. Grimes { BPF_RET|BPF_K, 0, 0, 0x0 } 186ea022d16SRodney W. Grimes }; 187ea022d16SRodney W. Grimes #undef RMP 188ea022d16SRodney W. Grimes static struct bpf_program bpf_pgm = { 189ea022d16SRodney W. Grimes sizeof(bpf_insn)/sizeof(bpf_insn[0]), bpf_insn 190ea022d16SRodney W. Grimes }; 191ea022d16SRodney W. Grimes 192ea022d16SRodney W. Grimes if (ioctl(BpfFd, BIOCSETF, (caddr_t)&bpf_pgm) < 0) { 193ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: ioctl(BIOCSETF): %m"); 194ea022d16SRodney W. Grimes Exit(0); 195ea022d16SRodney W. Grimes } 196ea022d16SRodney W. Grimes } 197ea022d16SRodney W. Grimes 198ea022d16SRodney W. Grimes return(BpfFd); 199ea022d16SRodney W. Grimes } 200ea022d16SRodney W. Grimes 201ea022d16SRodney W. Grimes /* 202ea022d16SRodney W. Grimes ** BPF GetIntfName -- Return the name of a network interface attached to 203ea022d16SRodney W. Grimes ** the system, or 0 if none can be found. The interface 204ea022d16SRodney W. Grimes ** must be configured up; the lowest unit number is 205ea022d16SRodney W. Grimes ** preferred; loopback is ignored. 206ea022d16SRodney W. Grimes ** 207ea022d16SRodney W. Grimes ** Parameters: 208ea022d16SRodney W. Grimes ** errmsg - if no network interface found, *errmsg explains why. 209ea022d16SRodney W. Grimes ** 210ea022d16SRodney W. Grimes ** Returns: 211ea022d16SRodney W. Grimes ** A (static) pointer to interface name, or NULL on error. 212ea022d16SRodney W. Grimes ** 213ea022d16SRodney W. Grimes ** Side Effects: 214ea022d16SRodney W. Grimes ** None. 215ea022d16SRodney W. Grimes */ 216ea022d16SRodney W. Grimes char * 217ea022d16SRodney W. Grimes BpfGetIntfName(errmsg) 218ea022d16SRodney W. Grimes char **errmsg; 219ea022d16SRodney W. Grimes { 220ea022d16SRodney W. Grimes struct ifreq ibuf[8], *ifrp, *ifend, *mp; 221ea022d16SRodney W. Grimes struct ifconf ifc; 222ea022d16SRodney W. Grimes int fd; 223ea022d16SRodney W. Grimes int minunit, n; 224ea022d16SRodney W. Grimes char *cp; 225ea022d16SRodney W. Grimes static char device[sizeof(ifrp->ifr_name)]; 226ea022d16SRodney W. Grimes static char errbuf[128] = "No Error!"; 227ea022d16SRodney W. Grimes 228ea022d16SRodney W. Grimes if (errmsg != NULL) 229ea022d16SRodney W. Grimes *errmsg = errbuf; 230ea022d16SRodney W. Grimes 231ea022d16SRodney W. Grimes if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 232ea022d16SRodney W. Grimes (void) strcpy(errbuf, "bpf: socket: %m"); 233ea022d16SRodney W. Grimes return(NULL); 234ea022d16SRodney W. Grimes } 235ea022d16SRodney W. Grimes ifc.ifc_len = sizeof ibuf; 236ea022d16SRodney W. Grimes ifc.ifc_buf = (caddr_t)ibuf; 237ea022d16SRodney W. Grimes 238ea022d16SRodney W. Grimes #ifdef OSIOCGIFCONF 239ea022d16SRodney W. Grimes if (ioctl(fd, OSIOCGIFCONF, (char *)&ifc) < 0 || 240ea022d16SRodney W. Grimes ifc.ifc_len < sizeof(struct ifreq)) { 241ea022d16SRodney W. Grimes (void) strcpy(errbuf, "bpf: ioctl(OSIOCGIFCONF): %m"); 242ea022d16SRodney W. Grimes return(NULL); 243ea022d16SRodney W. Grimes } 244ea022d16SRodney W. Grimes #else 245ea022d16SRodney W. Grimes if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 || 246ea022d16SRodney W. Grimes ifc.ifc_len < sizeof(struct ifreq)) { 247ea022d16SRodney W. Grimes (void) strcpy(errbuf, "bpf: ioctl(SIOCGIFCONF): %m"); 248ea022d16SRodney W. Grimes return(NULL); 249ea022d16SRodney W. Grimes } 250ea022d16SRodney W. Grimes #endif 251ea022d16SRodney W. Grimes ifrp = ibuf; 252ea022d16SRodney W. Grimes ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len); 253ea022d16SRodney W. Grimes 254ea022d16SRodney W. Grimes mp = 0; 255ea022d16SRodney W. Grimes minunit = 666; 256ea022d16SRodney W. Grimes for (; ifrp < ifend; ++ifrp) { 257ea022d16SRodney W. Grimes if (ioctl(fd, SIOCGIFFLAGS, (char *)ifrp) < 0) { 258ea022d16SRodney W. Grimes (void) strcpy(errbuf, "bpf: ioctl(SIOCGIFFLAGS): %m"); 259ea022d16SRodney W. Grimes return(NULL); 260ea022d16SRodney W. Grimes } 261ea022d16SRodney W. Grimes 262ea022d16SRodney W. Grimes /* 263ea022d16SRodney W. Grimes * If interface is down or this is the loopback interface, 264ea022d16SRodney W. Grimes * ignore it. 265ea022d16SRodney W. Grimes */ 266ea022d16SRodney W. Grimes if ((ifrp->ifr_flags & IFF_UP) == 0 || 267ea022d16SRodney W. Grimes #ifdef IFF_LOOPBACK 268ea022d16SRodney W. Grimes (ifrp->ifr_flags & IFF_LOOPBACK)) 269ea022d16SRodney W. Grimes #else 270ea022d16SRodney W. Grimes (strcmp(ifrp->ifr_name, "lo0") == 0)) 271ea022d16SRodney W. Grimes #endif 272ea022d16SRodney W. Grimes continue; 273ea022d16SRodney W. Grimes 274ea022d16SRodney W. Grimes for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp) 275ea022d16SRodney W. Grimes ; 276ea022d16SRodney W. Grimes n = atoi(cp); 277ea022d16SRodney W. Grimes if (n < minunit) { 278ea022d16SRodney W. Grimes minunit = n; 279ea022d16SRodney W. Grimes mp = ifrp; 280ea022d16SRodney W. Grimes } 281ea022d16SRodney W. Grimes } 282ea022d16SRodney W. Grimes 283ea022d16SRodney W. Grimes (void) close(fd); 284ea022d16SRodney W. Grimes if (mp == 0) { 285ea022d16SRodney W. Grimes (void) strcpy(errbuf, "bpf: no interfaces found"); 286ea022d16SRodney W. Grimes return(NULL); 287ea022d16SRodney W. Grimes } 288ea022d16SRodney W. Grimes 289ea022d16SRodney W. Grimes (void) strcpy(device, mp->ifr_name); 290ea022d16SRodney W. Grimes return(device); 291ea022d16SRodney W. Grimes } 292ea022d16SRodney W. Grimes 293ea022d16SRodney W. Grimes /* 294ea022d16SRodney W. Grimes ** BpfRead -- Read packets from a BPF device and fill in `rconn'. 295ea022d16SRodney W. Grimes ** 296ea022d16SRodney W. Grimes ** Parameters: 297ea022d16SRodney W. Grimes ** rconn - filled in with next packet. 298ea022d16SRodney W. Grimes ** doread - is True if we can issue a read() syscall. 299ea022d16SRodney W. Grimes ** 300ea022d16SRodney W. Grimes ** Returns: 301ea022d16SRodney W. Grimes ** True if `rconn' contains a new packet, False otherwise. 302ea022d16SRodney W. Grimes ** 303ea022d16SRodney W. Grimes ** Side Effects: 304ea022d16SRodney W. Grimes ** None. 305ea022d16SRodney W. Grimes */ 306ea022d16SRodney W. Grimes int 307ea022d16SRodney W. Grimes BpfRead(rconn, doread) 308ea022d16SRodney W. Grimes RMPCONN *rconn; 309ea022d16SRodney W. Grimes int doread; 310ea022d16SRodney W. Grimes { 311ea022d16SRodney W. Grimes register int datlen, caplen, hdrlen; 3125c8709fdSSteve Price static u_int8_t *bp = NULL, *ep = NULL; 313ea022d16SRodney W. Grimes int cc; 314ea022d16SRodney W. Grimes 315ea022d16SRodney W. Grimes /* 316ea022d16SRodney W. Grimes * The read() may block, or it may return one or more packets. 317ea022d16SRodney W. Grimes * We let the caller decide whether or not we can issue a read(). 318ea022d16SRodney W. Grimes */ 319ea022d16SRodney W. Grimes if (doread) { 320ea022d16SRodney W. Grimes if ((cc = read(BpfFd, (char *)BpfPkt, (int)BpfLen)) < 0) { 321ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: read: %m"); 322ea022d16SRodney W. Grimes return(0); 323ea022d16SRodney W. Grimes } else { 324ea022d16SRodney W. Grimes bp = BpfPkt; 325ea022d16SRodney W. Grimes ep = BpfPkt + cc; 326ea022d16SRodney W. Grimes } 327ea022d16SRodney W. Grimes } 328ea022d16SRodney W. Grimes 329ea022d16SRodney W. Grimes #define bhp ((struct bpf_hdr *)bp) 330ea022d16SRodney W. Grimes /* 331ea022d16SRodney W. Grimes * If there is a new packet in the buffer, stuff it into `rconn' 332ea022d16SRodney W. Grimes * and return a success indication. 333ea022d16SRodney W. Grimes */ 334ea022d16SRodney W. Grimes if (bp < ep) { 335ea022d16SRodney W. Grimes datlen = bhp->bh_datalen; 336ea022d16SRodney W. Grimes caplen = bhp->bh_caplen; 337ea022d16SRodney W. Grimes hdrlen = bhp->bh_hdrlen; 338ea022d16SRodney W. Grimes 339ea022d16SRodney W. Grimes if (caplen != datlen) 340ea022d16SRodney W. Grimes syslog(LOG_ERR, 341ea022d16SRodney W. Grimes "bpf: short packet dropped (%d of %d bytes)", 342ea022d16SRodney W. Grimes caplen, datlen); 343ea022d16SRodney W. Grimes else if (caplen > sizeof(struct rmp_packet)) 344ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: large packet dropped (%d bytes)", 345ea022d16SRodney W. Grimes caplen); 346ea022d16SRodney W. Grimes else { 347ea022d16SRodney W. Grimes rconn->rmplen = caplen; 348ea022d16SRodney W. Grimes bcopy((char *)&bhp->bh_tstamp, (char *)&rconn->tstamp, 349ea022d16SRodney W. Grimes sizeof(struct timeval)); 350ea022d16SRodney W. Grimes bcopy((char *)bp + hdrlen, (char *)&rconn->rmp, caplen); 351ea022d16SRodney W. Grimes } 352ea022d16SRodney W. Grimes bp += BPF_WORDALIGN(caplen + hdrlen); 353ea022d16SRodney W. Grimes return(1); 354ea022d16SRodney W. Grimes } 355ea022d16SRodney W. Grimes #undef bhp 356ea022d16SRodney W. Grimes 357ea022d16SRodney W. Grimes return(0); 358ea022d16SRodney W. Grimes } 359ea022d16SRodney W. Grimes 360ea022d16SRodney W. Grimes /* 361ea022d16SRodney W. Grimes ** BpfWrite -- Write packet to BPF device. 362ea022d16SRodney W. Grimes ** 363ea022d16SRodney W. Grimes ** Parameters: 364ea022d16SRodney W. Grimes ** rconn - packet to send. 365ea022d16SRodney W. Grimes ** 366ea022d16SRodney W. Grimes ** Returns: 367ea022d16SRodney W. Grimes ** True if write succeeded, False otherwise. 368ea022d16SRodney W. Grimes ** 369ea022d16SRodney W. Grimes ** Side Effects: 370ea022d16SRodney W. Grimes ** None. 371ea022d16SRodney W. Grimes */ 372ea022d16SRodney W. Grimes int 373ea022d16SRodney W. Grimes BpfWrite(rconn) 374ea022d16SRodney W. Grimes RMPCONN *rconn; 375ea022d16SRodney W. Grimes { 376ea022d16SRodney W. Grimes if (write(BpfFd, (char *)&rconn->rmp, rconn->rmplen) < 0) { 377ea022d16SRodney W. Grimes syslog(LOG_ERR, "write: %s: %m", EnetStr(rconn)); 378ea022d16SRodney W. Grimes return(0); 379ea022d16SRodney W. Grimes } 380ea022d16SRodney W. Grimes 381ea022d16SRodney W. Grimes return(1); 382ea022d16SRodney W. Grimes } 383ea022d16SRodney W. Grimes 384ea022d16SRodney W. Grimes /* 385ea022d16SRodney W. Grimes ** BpfClose -- Close a BPF device. 386ea022d16SRodney W. Grimes ** 387ea022d16SRodney W. Grimes ** Parameters: 388ea022d16SRodney W. Grimes ** None. 389ea022d16SRodney W. Grimes ** 390ea022d16SRodney W. Grimes ** Returns: 391ea022d16SRodney W. Grimes ** Nothing. 392ea022d16SRodney W. Grimes ** 393ea022d16SRodney W. Grimes ** Side Effects: 394ea022d16SRodney W. Grimes ** None. 395ea022d16SRodney W. Grimes */ 396ea022d16SRodney W. Grimes void 397ea022d16SRodney W. Grimes BpfClose() 398ea022d16SRodney W. Grimes { 399ea022d16SRodney W. Grimes struct ifreq ifr; 400ea022d16SRodney W. Grimes 401ea022d16SRodney W. Grimes if (BpfPkt != NULL) { 402ea022d16SRodney W. Grimes free((char *)BpfPkt); 403ea022d16SRodney W. Grimes BpfPkt = NULL; 404ea022d16SRodney W. Grimes } 405ea022d16SRodney W. Grimes 406ea022d16SRodney W. Grimes if (BpfFd == -1) 407ea022d16SRodney W. Grimes return; 408ea022d16SRodney W. Grimes 409ea022d16SRodney W. Grimes #ifdef MSG_EOR 410ea022d16SRodney W. Grimes ifr.ifr_addr.sa_len = RMP_ADDRLEN + 2; 411ea022d16SRodney W. Grimes #endif 412ea022d16SRodney W. Grimes ifr.ifr_addr.sa_family = AF_UNSPEC; 413ea022d16SRodney W. Grimes bcopy(&RmpMcastAddr[0], (char *)&ifr.ifr_addr.sa_data[0], RMP_ADDRLEN); 414ea022d16SRodney W. Grimes if (ioctl(BpfFd, SIOCDELMULTI, (caddr_t)&ifr) < 0) 415ea022d16SRodney W. Grimes (void) ioctl(BpfFd, BIOCPROMISC, (caddr_t)0); 416ea022d16SRodney W. Grimes 417ea022d16SRodney W. Grimes (void) close(BpfFd); 418ea022d16SRodney W. Grimes BpfFd = -1; 419ea022d16SRodney W. Grimes } 420