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 * 41ea022d16SRodney W. Grimes * @(#)bpf.c 8.1 (Berkeley) 6/4/93 42ea022d16SRodney W. Grimes * 43ea022d16SRodney W. Grimes * Utah $Hdr: bpf.c 3.1 92/07/06$ 44ea022d16SRodney W. Grimes * Author: Jeff Forys, University of Utah CSS 45ea022d16SRodney W. Grimes */ 46ea022d16SRodney W. Grimes 47ea022d16SRodney W. Grimes #ifndef lint 48ea022d16SRodney W. Grimes static char sccsid[] = "@(#)bpf.c 8.1 (Berkeley) 6/4/93"; 49ea022d16SRodney W. Grimes #endif /* not lint */ 50ea022d16SRodney W. Grimes 51ea022d16SRodney W. Grimes #include <sys/param.h> 52ea022d16SRodney W. Grimes #include <sys/ioctl.h> 53ea022d16SRodney W. Grimes #include <sys/socket.h> 54ea022d16SRodney W. Grimes 55ea022d16SRodney W. Grimes #include <net/if.h> 56ea022d16SRodney W. Grimes #include <net/bpf.h> 57ea022d16SRodney W. Grimes 58ea022d16SRodney W. Grimes #include <ctype.h> 59ea022d16SRodney W. Grimes #include <errno.h> 60ea022d16SRodney W. Grimes #include <fcntl.h> 61ea022d16SRodney W. Grimes #include <stdio.h> 62ea022d16SRodney W. Grimes #include <stdlib.h> 63ea022d16SRodney W. Grimes #include <string.h> 64ea022d16SRodney W. Grimes #include <syslog.h> 65ea022d16SRodney W. Grimes #include <unistd.h> 66ea022d16SRodney W. Grimes #include "defs.h" 67ea022d16SRodney W. Grimes #include "pathnames.h" 68ea022d16SRodney W. Grimes 69ea022d16SRodney W. Grimes static int BpfFd = -1; 70ea022d16SRodney W. Grimes static unsigned BpfLen = 0; 71ea022d16SRodney W. Grimes static u_char *BpfPkt = NULL; 72ea022d16SRodney W. Grimes 73ea022d16SRodney W. Grimes /* 74ea022d16SRodney W. Grimes ** BpfOpen -- Open and initialize a BPF device. 75ea022d16SRodney W. Grimes ** 76ea022d16SRodney W. Grimes ** Parameters: 77ea022d16SRodney W. Grimes ** None. 78ea022d16SRodney W. Grimes ** 79ea022d16SRodney W. Grimes ** Returns: 80ea022d16SRodney W. Grimes ** File descriptor of opened BPF device (for select() etc). 81ea022d16SRodney W. Grimes ** 82ea022d16SRodney W. Grimes ** Side Effects: 83ea022d16SRodney W. Grimes ** If an error is encountered, the program terminates here. 84ea022d16SRodney W. Grimes */ 85ea022d16SRodney W. Grimes int 86ea022d16SRodney W. Grimes BpfOpen() 87ea022d16SRodney W. Grimes { 88ea022d16SRodney W. Grimes struct ifreq ifr; 89ea022d16SRodney W. Grimes char bpfdev[32]; 90ea022d16SRodney W. Grimes int n = 0; 91ea022d16SRodney W. Grimes 92ea022d16SRodney W. Grimes /* 93ea022d16SRodney W. Grimes * Open the first available BPF device. 94ea022d16SRodney W. Grimes */ 95ea022d16SRodney W. Grimes do { 96ea022d16SRodney W. Grimes (void) sprintf(bpfdev, _PATH_BPF, n++); 97ea022d16SRodney W. Grimes BpfFd = open(bpfdev, O_RDWR); 98ea022d16SRodney W. Grimes } while (BpfFd < 0 && (errno == EBUSY || errno == EPERM)); 99ea022d16SRodney W. Grimes 100ea022d16SRodney W. Grimes if (BpfFd < 0) { 101ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: no available devices: %m"); 102ea022d16SRodney W. Grimes Exit(0); 103ea022d16SRodney W. Grimes } 104ea022d16SRodney W. Grimes 105ea022d16SRodney W. Grimes /* 106ea022d16SRodney W. Grimes * Set interface name for bpf device, get data link layer 107ea022d16SRodney W. Grimes * type and make sure it's type Ethernet. 108ea022d16SRodney W. Grimes */ 109ea022d16SRodney W. Grimes (void) strncpy(ifr.ifr_name, IntfName, sizeof(ifr.ifr_name)); 110ea022d16SRodney W. Grimes if (ioctl(BpfFd, BIOCSETIF, (caddr_t)&ifr) < 0) { 111ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: ioctl(BIOCSETIF,%s): %m", IntfName); 112ea022d16SRodney W. Grimes Exit(0); 113ea022d16SRodney W. Grimes } 114ea022d16SRodney W. Grimes 115ea022d16SRodney W. Grimes /* 116ea022d16SRodney W. Grimes * Make sure we are dealing with an Ethernet device. 117ea022d16SRodney W. Grimes */ 118ea022d16SRodney W. Grimes if (ioctl(BpfFd, BIOCGDLT, (caddr_t)&n) < 0) { 119ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: ioctl(BIOCGDLT): %m"); 120ea022d16SRodney W. Grimes Exit(0); 121ea022d16SRodney W. Grimes } 122ea022d16SRodney W. Grimes if (n != DLT_EN10MB) { 123ea022d16SRodney W. Grimes syslog(LOG_ERR,"bpf: %s: data-link type %d unsupported", 124ea022d16SRodney W. Grimes IntfName, n); 125ea022d16SRodney W. Grimes Exit(0); 126ea022d16SRodney W. Grimes } 127ea022d16SRodney W. Grimes 128ea022d16SRodney W. Grimes /* 129ea022d16SRodney W. Grimes * On read(), return packets immediately (do not buffer them). 130ea022d16SRodney W. Grimes */ 131ea022d16SRodney W. Grimes n = 1; 132ea022d16SRodney W. Grimes if (ioctl(BpfFd, BIOCIMMEDIATE, (caddr_t)&n) < 0) { 133ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: ioctl(BIOCIMMEDIATE): %m"); 134ea022d16SRodney W. Grimes Exit(0); 135ea022d16SRodney W. Grimes } 136ea022d16SRodney W. Grimes 137ea022d16SRodney W. Grimes /* 138ea022d16SRodney W. Grimes * Try to enable the chip/driver's multicast address filter to 139ea022d16SRodney W. Grimes * grab our RMP address. If this fails, try promiscuous mode. 140ea022d16SRodney W. Grimes * If this fails, there's no way we are going to get any RMP 141ea022d16SRodney W. Grimes * packets so just exit here. 142ea022d16SRodney W. Grimes */ 143ea022d16SRodney W. Grimes #ifdef MSG_EOR 144ea022d16SRodney W. Grimes ifr.ifr_addr.sa_len = RMP_ADDRLEN + 2; 145ea022d16SRodney W. Grimes #endif 146ea022d16SRodney W. Grimes ifr.ifr_addr.sa_family = AF_UNSPEC; 147ea022d16SRodney W. Grimes bcopy(&RmpMcastAddr[0], (char *)&ifr.ifr_addr.sa_data[0], RMP_ADDRLEN); 148ea022d16SRodney W. Grimes if (ioctl(BpfFd, SIOCADDMULTI, (caddr_t)&ifr) < 0) { 149ea022d16SRodney W. Grimes syslog(LOG_WARNING, 150ea022d16SRodney W. Grimes "bpf: can't add mcast addr (%m), setting promiscuous mode"); 151ea022d16SRodney W. Grimes 152ea022d16SRodney W. Grimes if (ioctl(BpfFd, BIOCPROMISC, (caddr_t)0) < 0) { 153ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: can't set promiscuous mode: %m"); 154ea022d16SRodney W. Grimes Exit(0); 155ea022d16SRodney W. Grimes } 156ea022d16SRodney W. Grimes } 157ea022d16SRodney W. Grimes 158ea022d16SRodney W. Grimes /* 159ea022d16SRodney W. Grimes * Ask BPF how much buffer space it requires and allocate one. 160ea022d16SRodney W. Grimes */ 161ea022d16SRodney W. Grimes if (ioctl(BpfFd, BIOCGBLEN, (caddr_t)&BpfLen) < 0) { 162ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: ioctl(BIOCGBLEN): %m"); 163ea022d16SRodney W. Grimes Exit(0); 164ea022d16SRodney W. Grimes } 165ea022d16SRodney W. Grimes if (BpfPkt == NULL) 166ea022d16SRodney W. Grimes BpfPkt = (u_char *)malloc(BpfLen); 167ea022d16SRodney W. Grimes 168ea022d16SRodney W. Grimes if (BpfPkt == NULL) { 169ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: out of memory (%u bytes for bpfpkt)", 170ea022d16SRodney W. Grimes BpfLen); 171ea022d16SRodney W. Grimes Exit(0); 172ea022d16SRodney W. Grimes } 173ea022d16SRodney W. Grimes 174ea022d16SRodney W. Grimes /* 175ea022d16SRodney W. Grimes * Write a little program to snarf RMP Boot packets and stuff 176ea022d16SRodney W. Grimes * it down BPF's throat (i.e. set up the packet filter). 177ea022d16SRodney W. Grimes */ 178ea022d16SRodney W. Grimes { 179ea022d16SRodney W. Grimes #define RMP ((struct rmp_packet *)0) 180ea022d16SRodney W. Grimes static struct bpf_insn bpf_insn[] = { 181ea022d16SRodney W. Grimes { BPF_LD|BPF_B|BPF_ABS, 0, 0, (long)&RMP->hp_llc.dsap }, 182ea022d16SRodney W. Grimes { BPF_JMP|BPF_JEQ|BPF_K, 0, 5, IEEE_DSAP_HP }, 183ea022d16SRodney W. Grimes { BPF_LD|BPF_H|BPF_ABS, 0, 0, (long)&RMP->hp_llc.cntrl }, 184ea022d16SRodney W. Grimes { BPF_JMP|BPF_JEQ|BPF_K, 0, 3, IEEE_CNTL_HP }, 185ea022d16SRodney W. Grimes { BPF_LD|BPF_H|BPF_ABS, 0, 0, (long)&RMP->hp_llc.dxsap }, 186ea022d16SRodney W. Grimes { BPF_JMP|BPF_JEQ|BPF_K, 0, 1, HPEXT_DXSAP }, 187ea022d16SRodney W. Grimes { BPF_RET|BPF_K, 0, 0, RMP_MAX_PACKET }, 188ea022d16SRodney W. Grimes { BPF_RET|BPF_K, 0, 0, 0x0 } 189ea022d16SRodney W. Grimes }; 190ea022d16SRodney W. Grimes #undef RMP 191ea022d16SRodney W. Grimes static struct bpf_program bpf_pgm = { 192ea022d16SRodney W. Grimes sizeof(bpf_insn)/sizeof(bpf_insn[0]), bpf_insn 193ea022d16SRodney W. Grimes }; 194ea022d16SRodney W. Grimes 195ea022d16SRodney W. Grimes if (ioctl(BpfFd, BIOCSETF, (caddr_t)&bpf_pgm) < 0) { 196ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: ioctl(BIOCSETF): %m"); 197ea022d16SRodney W. Grimes Exit(0); 198ea022d16SRodney W. Grimes } 199ea022d16SRodney W. Grimes } 200ea022d16SRodney W. Grimes 201ea022d16SRodney W. Grimes return(BpfFd); 202ea022d16SRodney W. Grimes } 203ea022d16SRodney W. Grimes 204ea022d16SRodney W. Grimes /* 205ea022d16SRodney W. Grimes ** BPF GetIntfName -- Return the name of a network interface attached to 206ea022d16SRodney W. Grimes ** the system, or 0 if none can be found. The interface 207ea022d16SRodney W. Grimes ** must be configured up; the lowest unit number is 208ea022d16SRodney W. Grimes ** preferred; loopback is ignored. 209ea022d16SRodney W. Grimes ** 210ea022d16SRodney W. Grimes ** Parameters: 211ea022d16SRodney W. Grimes ** errmsg - if no network interface found, *errmsg explains why. 212ea022d16SRodney W. Grimes ** 213ea022d16SRodney W. Grimes ** Returns: 214ea022d16SRodney W. Grimes ** A (static) pointer to interface name, or NULL on error. 215ea022d16SRodney W. Grimes ** 216ea022d16SRodney W. Grimes ** Side Effects: 217ea022d16SRodney W. Grimes ** None. 218ea022d16SRodney W. Grimes */ 219ea022d16SRodney W. Grimes char * 220ea022d16SRodney W. Grimes BpfGetIntfName(errmsg) 221ea022d16SRodney W. Grimes char **errmsg; 222ea022d16SRodney W. Grimes { 223ea022d16SRodney W. Grimes struct ifreq ibuf[8], *ifrp, *ifend, *mp; 224ea022d16SRodney W. Grimes struct ifconf ifc; 225ea022d16SRodney W. Grimes int fd; 226ea022d16SRodney W. Grimes int minunit, n; 227ea022d16SRodney W. Grimes char *cp; 228ea022d16SRodney W. Grimes static char device[sizeof(ifrp->ifr_name)]; 229ea022d16SRodney W. Grimes static char errbuf[128] = "No Error!"; 230ea022d16SRodney W. Grimes 231ea022d16SRodney W. Grimes if (errmsg != NULL) 232ea022d16SRodney W. Grimes *errmsg = errbuf; 233ea022d16SRodney W. Grimes 234ea022d16SRodney W. Grimes if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 235ea022d16SRodney W. Grimes (void) strcpy(errbuf, "bpf: socket: %m"); 236ea022d16SRodney W. Grimes return(NULL); 237ea022d16SRodney W. Grimes } 238ea022d16SRodney W. Grimes ifc.ifc_len = sizeof ibuf; 239ea022d16SRodney W. Grimes ifc.ifc_buf = (caddr_t)ibuf; 240ea022d16SRodney W. Grimes 241ea022d16SRodney W. Grimes #ifdef OSIOCGIFCONF 242ea022d16SRodney W. Grimes if (ioctl(fd, OSIOCGIFCONF, (char *)&ifc) < 0 || 243ea022d16SRodney W. Grimes ifc.ifc_len < sizeof(struct ifreq)) { 244ea022d16SRodney W. Grimes (void) strcpy(errbuf, "bpf: ioctl(OSIOCGIFCONF): %m"); 245ea022d16SRodney W. Grimes return(NULL); 246ea022d16SRodney W. Grimes } 247ea022d16SRodney W. Grimes #else 248ea022d16SRodney W. Grimes if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 || 249ea022d16SRodney W. Grimes ifc.ifc_len < sizeof(struct ifreq)) { 250ea022d16SRodney W. Grimes (void) strcpy(errbuf, "bpf: ioctl(SIOCGIFCONF): %m"); 251ea022d16SRodney W. Grimes return(NULL); 252ea022d16SRodney W. Grimes } 253ea022d16SRodney W. Grimes #endif 254ea022d16SRodney W. Grimes ifrp = ibuf; 255ea022d16SRodney W. Grimes ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len); 256ea022d16SRodney W. Grimes 257ea022d16SRodney W. Grimes mp = 0; 258ea022d16SRodney W. Grimes minunit = 666; 259ea022d16SRodney W. Grimes for (; ifrp < ifend; ++ifrp) { 260ea022d16SRodney W. Grimes if (ioctl(fd, SIOCGIFFLAGS, (char *)ifrp) < 0) { 261ea022d16SRodney W. Grimes (void) strcpy(errbuf, "bpf: ioctl(SIOCGIFFLAGS): %m"); 262ea022d16SRodney W. Grimes return(NULL); 263ea022d16SRodney W. Grimes } 264ea022d16SRodney W. Grimes 265ea022d16SRodney W. Grimes /* 266ea022d16SRodney W. Grimes * If interface is down or this is the loopback interface, 267ea022d16SRodney W. Grimes * ignore it. 268ea022d16SRodney W. Grimes */ 269ea022d16SRodney W. Grimes if ((ifrp->ifr_flags & IFF_UP) == 0 || 270ea022d16SRodney W. Grimes #ifdef IFF_LOOPBACK 271ea022d16SRodney W. Grimes (ifrp->ifr_flags & IFF_LOOPBACK)) 272ea022d16SRodney W. Grimes #else 273ea022d16SRodney W. Grimes (strcmp(ifrp->ifr_name, "lo0") == 0)) 274ea022d16SRodney W. Grimes #endif 275ea022d16SRodney W. Grimes continue; 276ea022d16SRodney W. Grimes 277ea022d16SRodney W. Grimes for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp) 278ea022d16SRodney W. Grimes ; 279ea022d16SRodney W. Grimes n = atoi(cp); 280ea022d16SRodney W. Grimes if (n < minunit) { 281ea022d16SRodney W. Grimes minunit = n; 282ea022d16SRodney W. Grimes mp = ifrp; 283ea022d16SRodney W. Grimes } 284ea022d16SRodney W. Grimes } 285ea022d16SRodney W. Grimes 286ea022d16SRodney W. Grimes (void) close(fd); 287ea022d16SRodney W. Grimes if (mp == 0) { 288ea022d16SRodney W. Grimes (void) strcpy(errbuf, "bpf: no interfaces found"); 289ea022d16SRodney W. Grimes return(NULL); 290ea022d16SRodney W. Grimes } 291ea022d16SRodney W. Grimes 292ea022d16SRodney W. Grimes (void) strcpy(device, mp->ifr_name); 293ea022d16SRodney W. Grimes return(device); 294ea022d16SRodney W. Grimes } 295ea022d16SRodney W. Grimes 296ea022d16SRodney W. Grimes /* 297ea022d16SRodney W. Grimes ** BpfRead -- Read packets from a BPF device and fill in `rconn'. 298ea022d16SRodney W. Grimes ** 299ea022d16SRodney W. Grimes ** Parameters: 300ea022d16SRodney W. Grimes ** rconn - filled in with next packet. 301ea022d16SRodney W. Grimes ** doread - is True if we can issue a read() syscall. 302ea022d16SRodney W. Grimes ** 303ea022d16SRodney W. Grimes ** Returns: 304ea022d16SRodney W. Grimes ** True if `rconn' contains a new packet, False otherwise. 305ea022d16SRodney W. Grimes ** 306ea022d16SRodney W. Grimes ** Side Effects: 307ea022d16SRodney W. Grimes ** None. 308ea022d16SRodney W. Grimes */ 309ea022d16SRodney W. Grimes int 310ea022d16SRodney W. Grimes BpfRead(rconn, doread) 311ea022d16SRodney W. Grimes RMPCONN *rconn; 312ea022d16SRodney W. Grimes int doread; 313ea022d16SRodney W. Grimes { 314ea022d16SRodney W. Grimes register int datlen, caplen, hdrlen; 315ea022d16SRodney W. Grimes static u_char *bp = NULL, *ep = NULL; 316ea022d16SRodney W. Grimes int cc; 317ea022d16SRodney W. Grimes 318ea022d16SRodney W. Grimes /* 319ea022d16SRodney W. Grimes * The read() may block, or it may return one or more packets. 320ea022d16SRodney W. Grimes * We let the caller decide whether or not we can issue a read(). 321ea022d16SRodney W. Grimes */ 322ea022d16SRodney W. Grimes if (doread) { 323ea022d16SRodney W. Grimes if ((cc = read(BpfFd, (char *)BpfPkt, (int)BpfLen)) < 0) { 324ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: read: %m"); 325ea022d16SRodney W. Grimes return(0); 326ea022d16SRodney W. Grimes } else { 327ea022d16SRodney W. Grimes bp = BpfPkt; 328ea022d16SRodney W. Grimes ep = BpfPkt + cc; 329ea022d16SRodney W. Grimes } 330ea022d16SRodney W. Grimes } 331ea022d16SRodney W. Grimes 332ea022d16SRodney W. Grimes #define bhp ((struct bpf_hdr *)bp) 333ea022d16SRodney W. Grimes /* 334ea022d16SRodney W. Grimes * If there is a new packet in the buffer, stuff it into `rconn' 335ea022d16SRodney W. Grimes * and return a success indication. 336ea022d16SRodney W. Grimes */ 337ea022d16SRodney W. Grimes if (bp < ep) { 338ea022d16SRodney W. Grimes datlen = bhp->bh_datalen; 339ea022d16SRodney W. Grimes caplen = bhp->bh_caplen; 340ea022d16SRodney W. Grimes hdrlen = bhp->bh_hdrlen; 341ea022d16SRodney W. Grimes 342ea022d16SRodney W. Grimes if (caplen != datlen) 343ea022d16SRodney W. Grimes syslog(LOG_ERR, 344ea022d16SRodney W. Grimes "bpf: short packet dropped (%d of %d bytes)", 345ea022d16SRodney W. Grimes caplen, datlen); 346ea022d16SRodney W. Grimes else if (caplen > sizeof(struct rmp_packet)) 347ea022d16SRodney W. Grimes syslog(LOG_ERR, "bpf: large packet dropped (%d bytes)", 348ea022d16SRodney W. Grimes caplen); 349ea022d16SRodney W. Grimes else { 350ea022d16SRodney W. Grimes rconn->rmplen = caplen; 351ea022d16SRodney W. Grimes bcopy((char *)&bhp->bh_tstamp, (char *)&rconn->tstamp, 352ea022d16SRodney W. Grimes sizeof(struct timeval)); 353ea022d16SRodney W. Grimes bcopy((char *)bp + hdrlen, (char *)&rconn->rmp, caplen); 354ea022d16SRodney W. Grimes } 355ea022d16SRodney W. Grimes bp += BPF_WORDALIGN(caplen + hdrlen); 356ea022d16SRodney W. Grimes return(1); 357ea022d16SRodney W. Grimes } 358ea022d16SRodney W. Grimes #undef bhp 359ea022d16SRodney W. Grimes 360ea022d16SRodney W. Grimes return(0); 361ea022d16SRodney W. Grimes } 362ea022d16SRodney W. Grimes 363ea022d16SRodney W. Grimes /* 364ea022d16SRodney W. Grimes ** BpfWrite -- Write packet to BPF device. 365ea022d16SRodney W. Grimes ** 366ea022d16SRodney W. Grimes ** Parameters: 367ea022d16SRodney W. Grimes ** rconn - packet to send. 368ea022d16SRodney W. Grimes ** 369ea022d16SRodney W. Grimes ** Returns: 370ea022d16SRodney W. Grimes ** True if write succeeded, False otherwise. 371ea022d16SRodney W. Grimes ** 372ea022d16SRodney W. Grimes ** Side Effects: 373ea022d16SRodney W. Grimes ** None. 374ea022d16SRodney W. Grimes */ 375ea022d16SRodney W. Grimes int 376ea022d16SRodney W. Grimes BpfWrite(rconn) 377ea022d16SRodney W. Grimes RMPCONN *rconn; 378ea022d16SRodney W. Grimes { 379ea022d16SRodney W. Grimes if (write(BpfFd, (char *)&rconn->rmp, rconn->rmplen) < 0) { 380ea022d16SRodney W. Grimes syslog(LOG_ERR, "write: %s: %m", EnetStr(rconn)); 381ea022d16SRodney W. Grimes return(0); 382ea022d16SRodney W. Grimes } 383ea022d16SRodney W. Grimes 384ea022d16SRodney W. Grimes return(1); 385ea022d16SRodney W. Grimes } 386ea022d16SRodney W. Grimes 387ea022d16SRodney W. Grimes /* 388ea022d16SRodney W. Grimes ** BpfClose -- Close a BPF device. 389ea022d16SRodney W. Grimes ** 390ea022d16SRodney W. Grimes ** Parameters: 391ea022d16SRodney W. Grimes ** None. 392ea022d16SRodney W. Grimes ** 393ea022d16SRodney W. Grimes ** Returns: 394ea022d16SRodney W. Grimes ** Nothing. 395ea022d16SRodney W. Grimes ** 396ea022d16SRodney W. Grimes ** Side Effects: 397ea022d16SRodney W. Grimes ** None. 398ea022d16SRodney W. Grimes */ 399ea022d16SRodney W. Grimes void 400ea022d16SRodney W. Grimes BpfClose() 401ea022d16SRodney W. Grimes { 402ea022d16SRodney W. Grimes struct ifreq ifr; 403ea022d16SRodney W. Grimes 404ea022d16SRodney W. Grimes if (BpfPkt != NULL) { 405ea022d16SRodney W. Grimes free((char *)BpfPkt); 406ea022d16SRodney W. Grimes BpfPkt = NULL; 407ea022d16SRodney W. Grimes } 408ea022d16SRodney W. Grimes 409ea022d16SRodney W. Grimes if (BpfFd == -1) 410ea022d16SRodney W. Grimes return; 411ea022d16SRodney W. Grimes 412ea022d16SRodney W. Grimes #ifdef MSG_EOR 413ea022d16SRodney W. Grimes ifr.ifr_addr.sa_len = RMP_ADDRLEN + 2; 414ea022d16SRodney W. Grimes #endif 415ea022d16SRodney W. Grimes ifr.ifr_addr.sa_family = AF_UNSPEC; 416ea022d16SRodney W. Grimes bcopy(&RmpMcastAddr[0], (char *)&ifr.ifr_addr.sa_data[0], RMP_ADDRLEN); 417ea022d16SRodney W. Grimes if (ioctl(BpfFd, SIOCDELMULTI, (caddr_t)&ifr) < 0) 418ea022d16SRodney W. Grimes (void) ioctl(BpfFd, BIOCPROMISC, (caddr_t)0); 419ea022d16SRodney W. Grimes 420ea022d16SRodney W. Grimes (void) close(BpfFd); 421ea022d16SRodney W. Grimes BpfFd = -1; 422ea022d16SRodney W. Grimes } 423