xref: /openbsd/usr.sbin/mopd/common/loop-bsd.c (revision 891d7ab6)
1 /*	$OpenBSD: loop-bsd.c,v 1.13 2009/10/27 23:59:52 deraadt 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  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include <errno.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #if defined(__bsdi__) || defined(__FreeBSD__)
32 #include <sys/time.h>
33 #endif
34 #include <net/bpf.h>
35 #include <sys/ioctl.h>
36 
37 #include "os.h"
38 #include "common/common.h"
39 #include "common/mopdef.h"
40 
41 int
42 mopOpenRC(struct if_info *p, int trans)
43 {
44 #ifndef NORC
45 	return (*(p->iopen))(p->if_name, O_RDWR, MOP_K_PROTO_RC, trans);
46 #else
47 	return (-1);
48 #endif
49 }
50 
51 int
52 mopOpenDL(struct if_info *p, int trans)
53 {
54 #ifndef NODL
55 	return (*(p->iopen))(p->if_name, O_RDWR, MOP_K_PROTO_DL, trans);
56 #else
57 	return (-1);
58 #endif
59 }
60 
61 void
62 mopReadRC(void)
63 {
64 }
65 
66 void
67 mopReadDL(void)
68 {
69 }
70 
71 /*
72  * The list of all interfaces that are being listened to.  loop()
73  * "selects" on the descriptors in this list.
74  */
75 struct if_info *iflist;
76 
77 void   mopProcess(struct if_info *, u_char *);
78 
79 /*
80  * Loop indefinitely listening for MOP requests on the
81  * interfaces in 'iflist'.
82  */
83 void
84 Loop(void)
85 {
86 	u_char		*buf, *bp, *ep;
87 	int		 cc;
88 	fd_set		 fds, listeners;
89 	int		 bufsize, maxfd = 0;
90 	struct if_info	*ii;
91 
92 	if (iflist == 0) {
93 		syslog(LOG_ERR, "no interfaces");
94 		exit(0);
95 	}
96 	if (iflist->fd != -1)
97 		if (ioctl(iflist->fd, BIOCGBLEN, (caddr_t)&bufsize) < 0) {
98 			syslog(LOG_ERR, "BIOCGBLEN: %m");
99 			exit(0);
100 		}
101 
102 	buf = malloc(bufsize);
103 	if (buf == 0) {
104 		syslog(LOG_ERR, "malloc: %m");
105 		exit(0);
106 	}
107 	/*
108          * Find the highest numbered file descriptor for select().
109          * Initialize the set of descriptors to listen to.
110          */
111 	FD_ZERO(&fds);
112 	for (ii = iflist; ii; ii = ii->next)
113 		if (ii->fd != -1) {
114 			FD_SET(ii->fd, &fds);
115 			if (ii->fd > maxfd)
116 				maxfd = ii->fd;
117 		}
118 
119 	while (1) {
120 		listeners = fds;
121 		if (select(maxfd + 1, &listeners, NULL, NULL, NULL) < 0) {
122 			syslog(LOG_ERR, "select: %m");
123 			exit(0);
124 		}
125 		for (ii = iflist; ii; ii = ii->next)
126 			if (ii->fd != -1) {
127 				if (!FD_ISSET(ii->fd, &listeners))
128 					continue;
129 again:
130 			cc = read(ii->fd, buf, bufsize);
131 			/* Don't choke when we get ptraced */
132 			if (cc < 0 && errno == EINTR)
133 				goto again;
134 			/* Due to a SunOS bug, after 2^31 bytes, the file
135 			 * offset overflows and read fails with EINVAL.  The
136 			 * lseek() to 0 will fix things. */
137 			if (cc < 0) {
138 				if (errno == EINVAL && (lseek(ii->fd, 0,
139 				    SEEK_CUR) + bufsize) < 0) {
140 					lseek(ii->fd, 0, SEEK_SET);
141 					goto again;
142 				}
143 				syslog(LOG_ERR, "read: %m");
144 				exit(0);
145 			}
146 			/* Loop through the packet(s) */
147 #define bhp ((struct bpf_hdr *)bp)
148 			bp = buf;
149 			ep = bp + cc;
150 			while (bp < ep) {
151 				int caplen, hdrlen;
152 
153 				caplen = bhp->bh_caplen;
154 				hdrlen = bhp->bh_hdrlen;
155 				mopProcess(ii, bp + hdrlen);
156 				bp += BPF_WORDALIGN(hdrlen + caplen);
157 			}
158 		}
159 	}
160 }
161