1 /* $NetBSD: loop-bsd.c,v 1.8 2006/05/25 00:27:56 christos 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.8 2006/05/25 00:27:56 christos 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 #include <sys/poll.h> 47 #include <assert.h> 48 49 #include "os.h" 50 #include "common.h" 51 #include "device.h" 52 #include "mopdef.h" 53 #include "log.h" 54 55 int 56 mopOpenRC(p, trans) 57 struct if_info *p; 58 int trans; 59 { 60 #ifndef NORC 61 return (*(p->iopen))(p->if_name, 62 O_RDWR, 63 MOP_K_PROTO_RC, 64 trans); 65 #else 66 return -1; 67 #endif 68 } 69 70 int 71 mopOpenDL(p, trans) 72 struct if_info *p; 73 int trans; 74 { 75 #ifndef NODL 76 return (*(p->iopen))(p->if_name, 77 O_RDWR, 78 MOP_K_PROTO_DL, 79 trans); 80 #else 81 return -1; 82 #endif 83 } 84 85 void 86 mopReadRC() 87 { 88 } 89 90 void 91 mopReadDL() 92 { 93 } 94 95 /* 96 * The list of all interfaces that are being listened to. loop() 97 * "selects" on the descriptors in this list. 98 */ 99 struct if_info *iflist; 100 101 void mopProcess __P((struct if_info *, u_char *)); 102 103 /* 104 * Loop indefinitely listening for MOP requests on the 105 * interfaces in 'iflist'. 106 */ 107 void 108 Loop() 109 { 110 u_char *buf, *bp, *ep; 111 int cc, n, m; 112 struct pollfd *set; 113 int bufsize; 114 struct if_info *ii; 115 116 if (iflist == 0) 117 mopLogErrX("no interfaces"); 118 if (iflist->fd != -1) { 119 if (ioctl(iflist->fd, BIOCGBLEN, (caddr_t) & bufsize) < 0) 120 mopLogErr("BIOCGBLEN"); 121 } else 122 mopLogErrX("cannot get buffer size"); 123 buf = (u_char *) malloc((unsigned) bufsize); 124 if (buf == 0) 125 mopLogErr("malloc"); 126 /* 127 * Find the highest numbered file descriptor for select(). 128 * Initialize the set of descriptors to listen to. 129 */ 130 for (ii = iflist, n = 0; ii; ii = ii->next, n++) 131 ; 132 set = malloc(n * sizeof(*set)); 133 for (ii = iflist, m = 0; ii; ii = ii->next, m++) { 134 assert(ii->fd != -1); 135 set[m].fd = ii->fd; 136 set[m].events = POLLIN; 137 } 138 for (;;) { 139 if (poll(set, n, INFTIM) < 0) 140 mopLogErr("poll"); 141 for (ii = iflist, m = 0; ii; ii = ii->next, m++) { 142 if (!(set[m].revents & POLLIN)) 143 continue; 144 again: 145 cc = read(ii->fd, (char *) buf, bufsize); 146 /* Don't choke when we get ptraced */ 147 if (cc < 0 && errno == EINTR) 148 goto again; 149 /* Due to a SunOS bug, after 2^31 bytes, the file 150 * offset overflows and read fails with EINVAL. The 151 * lseek() to 0 will fix things. */ 152 if (cc < 0) { 153 if (errno == EINVAL && 154 (lseek(ii->fd, 0, SEEK_CUR) + bufsize) < 0) { 155 (void) lseek(ii->fd, 0, 0); 156 goto again; 157 } 158 mopLogErr("read"); 159 } 160 /* Loop through the packet(s) */ 161 #define bhp ((struct bpf_hdr *)bp) 162 bp = buf; 163 ep = bp + cc; 164 while (bp < ep) { 165 int caplen, hdrlen; 166 167 caplen = bhp->bh_caplen; 168 hdrlen = bhp->bh_hdrlen; 169 mopProcess(ii, bp + hdrlen); 170 bp += BPF_WORDALIGN(hdrlen + caplen); 171 } 172 } 173 } 174 } 175