1 /* $NetBSD: loop-bsd.c,v 1.6 2002/09/20 14:16:03 mycroft 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.6 2002/09/20 14:16:03 mycroft 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 54 int 55 mopOpenRC(p, trans) 56 struct if_info *p; 57 int trans; 58 { 59 #ifndef NORC 60 return (*(p->iopen))(p->if_name, 61 O_RDWR, 62 MOP_K_PROTO_RC, 63 trans); 64 #else 65 return -1; 66 #endif 67 } 68 69 int 70 mopOpenDL(p, trans) 71 struct if_info *p; 72 int trans; 73 { 74 #ifndef NODL 75 return (*(p->iopen))(p->if_name, 76 O_RDWR, 77 MOP_K_PROTO_DL, 78 trans); 79 #else 80 return -1; 81 #endif 82 } 83 84 void 85 mopReadRC() 86 { 87 } 88 89 void 90 mopReadDL() 91 { 92 } 93 94 /* 95 * The list of all interfaces that are being listened to. loop() 96 * "selects" on the descriptors in this list. 97 */ 98 struct if_info *iflist; 99 100 void mopProcess __P((struct if_info *, u_char *)); 101 102 /* 103 * Loop indefinitely listening for MOP requests on the 104 * interfaces in 'iflist'. 105 */ 106 void 107 Loop() 108 { 109 u_char *buf, *bp, *ep; 110 int cc, n, m; 111 struct pollfd *set; 112 int bufsize; 113 struct if_info *ii; 114 115 if (iflist == 0) { 116 syslog(LOG_ERR, "no interfaces"); 117 exit(0); 118 } 119 if (iflist->fd != -1) { 120 if (ioctl(iflist->fd, BIOCGBLEN, (caddr_t) & bufsize) < 0) { 121 syslog(LOG_ERR, "BIOCGBLEN: %m"); 122 exit(0); 123 } 124 } 125 buf = (u_char *) malloc((unsigned) bufsize); 126 if (buf == 0) { 127 syslog(LOG_ERR, "malloc: %m"); 128 exit(0); 129 } 130 /* 131 * Find the highest numbered file descriptor for select(). 132 * Initialize the set of descriptors to listen to. 133 */ 134 for (ii = iflist, n = 0; ii; ii = ii->next, n++) 135 ; 136 set = malloc(n * sizeof(*set)); 137 for (ii = iflist, m = 0; ii; ii = ii->next, m++) { 138 assert(ii->fd != -1); 139 set[m].fd = ii->fd; 140 set[m].events = POLLIN; 141 } 142 for (;;) { 143 if (poll(set, n, INFTIM) < 0) { 144 syslog(LOG_ERR, "poll: %m"); 145 exit(0); 146 } 147 for (ii = iflist, m = 0; ii; ii = ii->next, m++) { 148 if (!(set[m].revents & POLLIN)) 149 continue; 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