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