1 /* $NetBSD: loop-bsd.c,v 1.5 1999/01/11 22:40:01 kleink Exp $ */ 2 3 /* 4 * Copyright (c) 1993-95 Mats O Jansson. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Mats O Jansson. 17 * 4. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 __RCSID("$NetBSD: loop-bsd.c,v 1.5 1999/01/11 22:40:01 kleink Exp $"); 35 #endif 36 37 #include <errno.h> 38 #include <stdlib.h> 39 #include <strings.h> 40 #include <unistd.h> 41 #if defined(__bsdi__) || defined(__FreeBSD__) || defined(__NetBSD__) 42 #include <sys/time.h> 43 #endif 44 #include <net/bpf.h> 45 #include <sys/ioctl.h> 46 47 #include "os.h" 48 #include "common.h" 49 #include "device.h" 50 #include "mopdef.h" 51 52 int 53 mopOpenRC(p, trans) 54 struct if_info *p; 55 int trans; 56 { 57 #ifndef NORC 58 return (*(p->iopen))(p->if_name, 59 O_RDWR, 60 MOP_K_PROTO_RC, 61 trans); 62 #else 63 return -1; 64 #endif 65 } 66 67 int 68 mopOpenDL(p, trans) 69 struct if_info *p; 70 int trans; 71 { 72 #ifndef NODL 73 return (*(p->iopen))(p->if_name, 74 O_RDWR, 75 MOP_K_PROTO_DL, 76 trans); 77 #else 78 return -1; 79 #endif 80 } 81 82 void 83 mopReadRC() 84 { 85 } 86 87 void 88 mopReadDL() 89 { 90 } 91 92 /* 93 * The list of all interfaces that are being listened to. loop() 94 * "selects" on the descriptors in this list. 95 */ 96 struct if_info *iflist; 97 98 void mopProcess __P((struct if_info *, u_char *)); 99 100 /* 101 * Loop indefinitely listening for MOP requests on the 102 * interfaces in 'iflist'. 103 */ 104 void 105 Loop() 106 { 107 u_char *buf, *bp, *ep; 108 int cc; 109 fd_set fds, listeners; 110 int bufsize, maxfd = 0; 111 struct if_info *ii; 112 113 if (iflist == 0) { 114 syslog(LOG_ERR, "no interfaces"); 115 exit(0); 116 } 117 if (iflist->fd != -1) { 118 if (ioctl(iflist->fd, BIOCGBLEN, (caddr_t) & bufsize) < 0) { 119 syslog(LOG_ERR, "BIOCGBLEN: %m"); 120 exit(0); 121 } 122 } 123 buf = (u_char *) malloc((unsigned) bufsize); 124 if (buf == 0) { 125 syslog(LOG_ERR, "malloc: %m"); 126 exit(0); 127 } 128 /* 129 * Find the highest numbered file descriptor for select(). 130 * Initialize the set of descriptors to listen to. 131 */ 132 FD_ZERO(&fds); 133 for (ii = iflist; ii; ii = ii->next) { 134 if (ii->fd != -1) { 135 FD_SET(ii->fd, &fds); 136 if (ii->fd > maxfd) 137 maxfd = ii->fd; 138 } 139 } 140 while (1) { 141 listeners = fds; 142 if (select(maxfd + 1, &listeners, (struct fd_set *) 0, 143 (struct fd_set *) 0, (struct timeval *) 0) < 0) { 144 syslog(LOG_ERR, "select: %m"); 145 exit(0); 146 } 147 for (ii = iflist; ii; ii = ii->next) { 148 if (ii->fd != -1) { 149 if (!FD_ISSET(ii->fd, &listeners)) 150 continue; 151 } 152 again: 153 cc = read(ii->fd, (char *) buf, bufsize); 154 /* Don't choke when we get ptraced */ 155 if (cc < 0 && errno == EINTR) 156 goto again; 157 /* Due to a SunOS bug, after 2^31 bytes, the file 158 * offset overflows and read fails with EINVAL. The 159 * lseek() to 0 will fix things. */ 160 if (cc < 0) { 161 if (errno == EINVAL && 162 (lseek(ii->fd, 0, SEEK_CUR) + bufsize) < 0) { 163 (void) lseek(ii->fd, 0, 0); 164 goto again; 165 } 166 syslog(LOG_ERR, "read: %m"); 167 exit(0); 168 } 169 /* Loop through the packet(s) */ 170 #define bhp ((struct bpf_hdr *)bp) 171 bp = buf; 172 ep = bp + cc; 173 while (bp < ep) { 174 int caplen, hdrlen; 175 176 caplen = bhp->bh_caplen; 177 hdrlen = bhp->bh_hdrlen; 178 mopProcess(ii, bp + hdrlen); 179 bp += BPF_WORDALIGN(hdrlen + caplen); 180 } 181 } 182 } 183 } 184