1 /* $OpenBSD: loop-bsd.c,v 1.6 2002/03/14 16:44:25 mpech 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 #ifndef LINT 33 static char rcsid[] = "$OpenBSD: loop-bsd.c,v 1.6 2002/03/14 16:44:25 mpech Exp $"; 34 #endif 35 36 #include <stdlib.h> 37 #include <string.h> 38 #include <unistd.h> 39 #if defined(__bsdi__) || defined(__FreeBSD__) 40 #include <sys/time.h> 41 #endif 42 #include <net/bpf.h> 43 #include <sys/ioctl.h> 44 #include <sys/errno.h> 45 46 #include "os.h" 47 #include "common/common.h" 48 #include "common/mopdef.h" 49 50 int 51 mopOpenRC(p, trans) 52 struct if_info *p; 53 int trans; 54 { 55 #ifndef NORC 56 return (*(p->iopen))(p->if_name, 57 O_RDWR, 58 MOP_K_PROTO_RC, 59 trans); 60 #else 61 return -1; 62 #endif 63 } 64 65 int 66 mopOpenDL(p, trans) 67 struct if_info *p; 68 int trans; 69 { 70 #ifndef NODL 71 return (*(p->iopen))(p->if_name, 72 O_RDWR, 73 MOP_K_PROTO_DL, 74 trans); 75 #else 76 return -1; 77 #endif 78 } 79 80 void 81 mopReadRC() 82 { 83 } 84 85 void 86 mopReadDL() 87 { 88 } 89 90 /* 91 * The list of all interfaces that are being listened to. loop() 92 * "selects" on the descriptors in this list. 93 */ 94 struct if_info *iflist; 95 96 void mopProcess(struct if_info *, u_char *); 97 98 /* 99 * Loop indefinitely listening for MOP requests on the 100 * interfaces in 'iflist'. 101 */ 102 void 103 Loop() 104 { 105 u_char *buf, *bp, *ep; 106 int cc; 107 fd_set fds, listeners; 108 int bufsize, maxfd = 0; 109 struct if_info *ii; 110 111 if (iflist == 0) { 112 syslog(LOG_ERR, "no interfaces"); 113 exit(0); 114 } 115 if (iflist->fd != -1) { 116 if (ioctl(iflist->fd, BIOCGBLEN, (caddr_t) & bufsize) < 0) { 117 syslog(LOG_ERR, "BIOCGBLEN: %m"); 118 exit(0); 119 } 120 } 121 buf = (u_char *) malloc((unsigned) bufsize); 122 if (buf == 0) { 123 syslog(LOG_ERR, "malloc: %m"); 124 exit(0); 125 } 126 /* 127 * Find the highest numbered file descriptor for select(). 128 * Initialize the set of descriptors to listen to. 129 */ 130 FD_ZERO(&fds); 131 for (ii = iflist; ii; ii = ii->next) { 132 if (ii->fd != -1) { 133 FD_SET(ii->fd, &fds); 134 if (ii->fd > maxfd) 135 maxfd = ii->fd; 136 } 137 } 138 while (1) { 139 listeners = fds; 140 if (select(maxfd + 1, &listeners, (fd_set *) 0, 141 (fd_set *) 0, (struct timeval *) 0) < 0) { 142 syslog(LOG_ERR, "select: %m"); 143 exit(0); 144 } 145 for (ii = iflist; ii; ii = ii->next) { 146 if (ii->fd != -1) { 147 if (!FD_ISSET(ii->fd, &listeners)) 148 continue; 149 } 150 again: 151 cc = read(ii->fd, (char *) buf, bufsize); 152 /* Don't choke when we get ptraced */ 153 if (cc < 0 && errno == EINTR) 154 goto again; 155 /* Due to a SunOS bug, after 2^31 bytes, the file 156 * offset overflows and read fails with EINVAL. The 157 * lseek() to 0 will fix things. */ 158 if (cc < 0) { 159 if (errno == EINVAL && 160 (lseek(ii->fd, 0, SEEK_CUR) + bufsize) < 0) { 161 (void) lseek(ii->fd, 0, 0); 162 goto again; 163 } 164 syslog(LOG_ERR, "read: %m"); 165 exit(0); 166 } 167 /* Loop through the packet(s) */ 168 #define bhp ((struct bpf_hdr *)bp) 169 bp = buf; 170 ep = bp + cc; 171 while (bp < ep) { 172 int caplen, hdrlen; 173 174 caplen = bhp->bh_caplen; 175 hdrlen = bhp->bh_hdrlen; 176 mopProcess(ii, bp + hdrlen); 177 bp += BPF_WORDALIGN(hdrlen + caplen); 178 } 179 } 180 } 181 } 182