xref: /minix3/external/bsd/dhcp/dist/common/upf.c (revision 83ee113ee0d94f3844d44065af2311604e9a30ad)
1*83ee113eSDavid van Moolenbroek /*	$NetBSD: upf.c,v 1.1.1.2 2014/07/12 11:57:48 spz Exp $	*/
2*83ee113eSDavid van Moolenbroek /* upf.c
3*83ee113eSDavid van Moolenbroek 
4*83ee113eSDavid van Moolenbroek    Ultrix PacketFilter interface code. */
5*83ee113eSDavid van Moolenbroek 
6*83ee113eSDavid van Moolenbroek /*
7*83ee113eSDavid van Moolenbroek  * Copyright (c) 2004,2007,2009,2014 by Internet Systems Consortium, Inc. ("ISC")
8*83ee113eSDavid van Moolenbroek  * Copyright (c) 1996-2003 by Internet Software Consortium
9*83ee113eSDavid van Moolenbroek  *
10*83ee113eSDavid van Moolenbroek  * Permission to use, copy, modify, and distribute this software for any
11*83ee113eSDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
12*83ee113eSDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
13*83ee113eSDavid van Moolenbroek  *
14*83ee113eSDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15*83ee113eSDavid van Moolenbroek  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16*83ee113eSDavid van Moolenbroek  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
17*83ee113eSDavid van Moolenbroek  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18*83ee113eSDavid van Moolenbroek  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19*83ee113eSDavid van Moolenbroek  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20*83ee113eSDavid van Moolenbroek  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21*83ee113eSDavid van Moolenbroek  *
22*83ee113eSDavid van Moolenbroek  *   Internet Systems Consortium, Inc.
23*83ee113eSDavid van Moolenbroek  *   950 Charter Street
24*83ee113eSDavid van Moolenbroek  *   Redwood City, CA 94063
25*83ee113eSDavid van Moolenbroek  *   <info@isc.org>
26*83ee113eSDavid van Moolenbroek  *   https://www.isc.org/
27*83ee113eSDavid van Moolenbroek  *
28*83ee113eSDavid van Moolenbroek  */
29*83ee113eSDavid van Moolenbroek 
30*83ee113eSDavid van Moolenbroek #include <sys/cdefs.h>
31*83ee113eSDavid van Moolenbroek __RCSID("$NetBSD: upf.c,v 1.1.1.2 2014/07/12 11:57:48 spz Exp $");
32*83ee113eSDavid van Moolenbroek 
33*83ee113eSDavid van Moolenbroek #include "dhcpd.h"
34*83ee113eSDavid van Moolenbroek #if defined (USE_UPF_SEND) || defined (USE_UPF_RECEIVE)
35*83ee113eSDavid van Moolenbroek #include <sys/ioctl.h>
36*83ee113eSDavid van Moolenbroek #include <sys/uio.h>
37*83ee113eSDavid van Moolenbroek 
38*83ee113eSDavid van Moolenbroek #include <net/pfilt.h>
39*83ee113eSDavid van Moolenbroek #include <netinet/in_systm.h>
40*83ee113eSDavid van Moolenbroek #include "includes/netinet/ip.h"
41*83ee113eSDavid van Moolenbroek #include "includes/netinet/udp.h"
42*83ee113eSDavid van Moolenbroek #include "includes/netinet/if_ether.h"
43*83ee113eSDavid van Moolenbroek 
44*83ee113eSDavid van Moolenbroek /* Reinitializes the specified interface after an address change.   This
45*83ee113eSDavid van Moolenbroek    is not required for packet-filter APIs. */
46*83ee113eSDavid van Moolenbroek 
47*83ee113eSDavid van Moolenbroek #ifdef USE_UPF_SEND
if_reinitialize_send(info)48*83ee113eSDavid van Moolenbroek void if_reinitialize_send (info)
49*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
50*83ee113eSDavid van Moolenbroek {
51*83ee113eSDavid van Moolenbroek }
52*83ee113eSDavid van Moolenbroek #endif
53*83ee113eSDavid van Moolenbroek 
54*83ee113eSDavid van Moolenbroek #ifdef USE_UPF_RECEIVE
if_reinitialize_receive(info)55*83ee113eSDavid van Moolenbroek void if_reinitialize_receive (info)
56*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
57*83ee113eSDavid van Moolenbroek {
58*83ee113eSDavid van Moolenbroek }
59*83ee113eSDavid van Moolenbroek #endif
60*83ee113eSDavid van Moolenbroek 
61*83ee113eSDavid van Moolenbroek /* Called by get_interface_list for each interface that's discovered.
62*83ee113eSDavid van Moolenbroek    Opens a packet filter for each interface and adds it to the select
63*83ee113eSDavid van Moolenbroek    mask. */
64*83ee113eSDavid van Moolenbroek 
if_register_upf(info)65*83ee113eSDavid van Moolenbroek int if_register_upf (info)
66*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
67*83ee113eSDavid van Moolenbroek {
68*83ee113eSDavid van Moolenbroek 	int sock;
69*83ee113eSDavid van Moolenbroek 	char filename[50];
70*83ee113eSDavid van Moolenbroek 	int b;
71*83ee113eSDavid van Moolenbroek 	struct endevp param;
72*83ee113eSDavid van Moolenbroek 
73*83ee113eSDavid van Moolenbroek 	/* Open a UPF device */
74*83ee113eSDavid van Moolenbroek 	for (b = 0; 1; b++) {
75*83ee113eSDavid van Moolenbroek 		/* %Audit% Cannot exceed 36 bytes. %2004.06.17,Safe% */
76*83ee113eSDavid van Moolenbroek 		sprintf(filename, "/dev/pf/pfilt%d", b);
77*83ee113eSDavid van Moolenbroek 
78*83ee113eSDavid van Moolenbroek 		sock = open (filename, O_RDWR, 0);
79*83ee113eSDavid van Moolenbroek 		if (sock < 0) {
80*83ee113eSDavid van Moolenbroek 			if (errno == EBUSY) {
81*83ee113eSDavid van Moolenbroek 				continue;
82*83ee113eSDavid van Moolenbroek 			} else {
83*83ee113eSDavid van Moolenbroek 				log_fatal ("Can't find free upf: %m");
84*83ee113eSDavid van Moolenbroek 			}
85*83ee113eSDavid van Moolenbroek 		} else {
86*83ee113eSDavid van Moolenbroek 			break;
87*83ee113eSDavid van Moolenbroek 		}
88*83ee113eSDavid van Moolenbroek 	}
89*83ee113eSDavid van Moolenbroek 
90*83ee113eSDavid van Moolenbroek 	/* Set the UPF device to point at this interface. */
91*83ee113eSDavid van Moolenbroek 	if (ioctl (sock, EIOCSETIF, info -> ifp) < 0)
92*83ee113eSDavid van Moolenbroek 		log_fatal ("Can't attach interface %s to upf device %s: %m",
93*83ee113eSDavid van Moolenbroek 		       info -> name, filename);
94*83ee113eSDavid van Moolenbroek 
95*83ee113eSDavid van Moolenbroek 	/* Get the hardware address. */
96*83ee113eSDavid van Moolenbroek 	if (ioctl (sock, EIOCDEVP, &param) < 0)
97*83ee113eSDavid van Moolenbroek 		log_fatal ("Can't get interface %s hardware address: %m",
98*83ee113eSDavid van Moolenbroek 		       info -> name);
99*83ee113eSDavid van Moolenbroek 
100*83ee113eSDavid van Moolenbroek 	/* We only know how to do ethernet. */
101*83ee113eSDavid van Moolenbroek 	if (param.end_dev_type != ENDT_10MB)
102*83ee113eSDavid van Moolenbroek 		log_fatal ("Invalid device type on network interface %s: %d",
103*83ee113eSDavid van Moolenbroek 		       info -> name, param.end_dev_type);
104*83ee113eSDavid van Moolenbroek 
105*83ee113eSDavid van Moolenbroek 	if (param.end_addr_len != 6)
106*83ee113eSDavid van Moolenbroek 		log_fatal ("Invalid hardware address length on %s: %d",
107*83ee113eSDavid van Moolenbroek 		       info -> name, param.end_addr_len);
108*83ee113eSDavid van Moolenbroek 
109*83ee113eSDavid van Moolenbroek 	info -> hw_address.hlen = 7;
110*83ee113eSDavid van Moolenbroek 	info -> hw_address.hbuf [0] = ARPHRD_ETHER;
111*83ee113eSDavid van Moolenbroek 	memcpy (&info -> hw_address.hbuf [1], param.end_addr, 6);
112*83ee113eSDavid van Moolenbroek 
113*83ee113eSDavid van Moolenbroek 	return sock;
114*83ee113eSDavid van Moolenbroek }
115*83ee113eSDavid van Moolenbroek #endif /* USE_UPF_SEND || USE_UPF_RECEIVE */
116*83ee113eSDavid van Moolenbroek 
117*83ee113eSDavid van Moolenbroek #ifdef USE_UPF_SEND
if_register_send(info)118*83ee113eSDavid van Moolenbroek void if_register_send (info)
119*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
120*83ee113eSDavid van Moolenbroek {
121*83ee113eSDavid van Moolenbroek 	/* If we're using the upf API for sending and receiving,
122*83ee113eSDavid van Moolenbroek 	   we don't need to register this interface twice. */
123*83ee113eSDavid van Moolenbroek #ifndef USE_UPF_RECEIVE
124*83ee113eSDavid van Moolenbroek 	info -> wfdesc = if_register_upf (info, interface);
125*83ee113eSDavid van Moolenbroek #else
126*83ee113eSDavid van Moolenbroek 	info -> wfdesc = info -> rfdesc;
127*83ee113eSDavid van Moolenbroek #endif
128*83ee113eSDavid van Moolenbroek         if (!quiet_interface_discovery)
129*83ee113eSDavid van Moolenbroek 		log_info ("Sending on   UPF/%s/%s%s%s",
130*83ee113eSDavid van Moolenbroek 		      info -> name,
131*83ee113eSDavid van Moolenbroek 		      print_hw_addr (info -> hw_address.hbuf [0],
132*83ee113eSDavid van Moolenbroek 				     info -> hw_address.hlen - 1,
133*83ee113eSDavid van Moolenbroek 				     &info -> hw_address.hbuf [1]),
134*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ? "/" : ""),
135*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ?
136*83ee113eSDavid van Moolenbroek 		       info -> shared_network -> name : ""));
137*83ee113eSDavid van Moolenbroek }
138*83ee113eSDavid van Moolenbroek 
if_deregister_send(info)139*83ee113eSDavid van Moolenbroek void if_deregister_send (info)
140*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
141*83ee113eSDavid van Moolenbroek {
142*83ee113eSDavid van Moolenbroek #ifndef USE_UPF_RECEIVE
143*83ee113eSDavid van Moolenbroek 	close (info -> wfdesc);
144*83ee113eSDavid van Moolenbroek #endif
145*83ee113eSDavid van Moolenbroek 	info -> wfdesc = -1;
146*83ee113eSDavid van Moolenbroek         if (!quiet_interface_discovery)
147*83ee113eSDavid van Moolenbroek 		log_info ("Disabling output on UPF/%s/%s%s%s",
148*83ee113eSDavid van Moolenbroek 		      info -> name,
149*83ee113eSDavid van Moolenbroek 		      print_hw_addr (info -> hw_address.hbuf [0],
150*83ee113eSDavid van Moolenbroek 				     info -> hw_address.hlen - 1,
151*83ee113eSDavid van Moolenbroek 				     &info -> hw_address.hbuf [1]),
152*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ? "/" : ""),
153*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ?
154*83ee113eSDavid van Moolenbroek 		       info -> shared_network -> name : ""));
155*83ee113eSDavid van Moolenbroek }
156*83ee113eSDavid van Moolenbroek #endif /* USE_UPF_SEND */
157*83ee113eSDavid van Moolenbroek 
158*83ee113eSDavid van Moolenbroek #ifdef USE_UPF_RECEIVE
159*83ee113eSDavid van Moolenbroek /* Packet filter program...
160*83ee113eSDavid van Moolenbroek    XXX Changes to the filter program may require changes to the constant
161*83ee113eSDavid van Moolenbroek    offsets used in if_register_send to patch the UPF program! XXX */
162*83ee113eSDavid van Moolenbroek 
163*83ee113eSDavid van Moolenbroek 
if_register_receive(info)164*83ee113eSDavid van Moolenbroek void if_register_receive (info)
165*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
166*83ee113eSDavid van Moolenbroek {
167*83ee113eSDavid van Moolenbroek 	int flag = 1;
168*83ee113eSDavid van Moolenbroek 	u_int32_t addr;
169*83ee113eSDavid van Moolenbroek 	struct enfilter pf;
170*83ee113eSDavid van Moolenbroek 	u_int32_t bits;
171*83ee113eSDavid van Moolenbroek 
172*83ee113eSDavid van Moolenbroek 	/* Open a UPF device and hang it on this interface... */
173*83ee113eSDavid van Moolenbroek 	info -> rfdesc = if_register_upf (info);
174*83ee113eSDavid van Moolenbroek 
175*83ee113eSDavid van Moolenbroek 	/* Allow the copyall flag to be set... */
176*83ee113eSDavid van Moolenbroek 	if (ioctl(info -> rfdesc, EIOCALLOWCOPYALL, &flag) < 0)
177*83ee113eSDavid van Moolenbroek 		log_fatal ("Can't set ALLOWCOPYALL: %m");
178*83ee113eSDavid van Moolenbroek 
179*83ee113eSDavid van Moolenbroek 	/* Clear all the packet filter mode bits first... */
180*83ee113eSDavid van Moolenbroek 	flag = (ENHOLDSIG | ENBATCH | ENTSTAMP | ENPROMISC |
181*83ee113eSDavid van Moolenbroek 		ENNONEXCL | ENCOPYALL);
182*83ee113eSDavid van Moolenbroek 	if (ioctl (info -> rfdesc, EIOCMBIC, &flag) < 0)
183*83ee113eSDavid van Moolenbroek 		log_fatal ("Can't clear pfilt bits: %m");
184*83ee113eSDavid van Moolenbroek 
185*83ee113eSDavid van Moolenbroek 	/* Set the ENBATCH and ENCOPYALL bits... */
186*83ee113eSDavid van Moolenbroek 	bits = ENBATCH | ENCOPYALL;
187*83ee113eSDavid van Moolenbroek 	if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
188*83ee113eSDavid van Moolenbroek 		log_fatal ("Can't set ENBATCH|ENCOPYALL: %m");
189*83ee113eSDavid van Moolenbroek 
190*83ee113eSDavid van Moolenbroek 	/* Set up the UPF filter program. */
191*83ee113eSDavid van Moolenbroek 	/* XXX Unlike the BPF filter program, this one won't work if the
192*83ee113eSDavid van Moolenbroek 	   XXX IP packet is fragmented or if there are options on the IP
193*83ee113eSDavid van Moolenbroek 	   XXX header. */
194*83ee113eSDavid van Moolenbroek 	pf.enf_Priority = 0;
195*83ee113eSDavid van Moolenbroek 	pf.enf_FilterLen = 0;
196*83ee113eSDavid van Moolenbroek 
197*83ee113eSDavid van Moolenbroek 	pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHWORD + 6;
198*83ee113eSDavid van Moolenbroek 	pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHLIT + ENF_CAND;
199*83ee113eSDavid van Moolenbroek 	pf.enf_Filter [pf.enf_FilterLen++] = htons (ETHERTYPE_IP);
200*83ee113eSDavid van Moolenbroek 	pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHLIT;
201*83ee113eSDavid van Moolenbroek 	pf.enf_Filter [pf.enf_FilterLen++] = htons (IPPROTO_UDP);
202*83ee113eSDavid van Moolenbroek 	pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHWORD + 11;
203*83ee113eSDavid van Moolenbroek 	pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHLIT + ENF_AND;
204*83ee113eSDavid van Moolenbroek 	pf.enf_Filter [pf.enf_FilterLen++] = htons (0xFF);
205*83ee113eSDavid van Moolenbroek 	pf.enf_Filter [pf.enf_FilterLen++] = ENF_CAND;
206*83ee113eSDavid van Moolenbroek 	pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHWORD + 18;
207*83ee113eSDavid van Moolenbroek 	pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHLIT + ENF_CAND;
208*83ee113eSDavid van Moolenbroek 	pf.enf_Filter [pf.enf_FilterLen++] = local_port;
209*83ee113eSDavid van Moolenbroek 
210*83ee113eSDavid van Moolenbroek 	if (ioctl (info -> rfdesc, EIOCSETF, &pf) < 0)
211*83ee113eSDavid van Moolenbroek 		log_fatal ("Can't install packet filter program: %m");
212*83ee113eSDavid van Moolenbroek         if (!quiet_interface_discovery)
213*83ee113eSDavid van Moolenbroek 		log_info ("Listening on UPF/%s/%s%s%s",
214*83ee113eSDavid van Moolenbroek 		      info -> name,
215*83ee113eSDavid van Moolenbroek 		      print_hw_addr (info -> hw_address.hbuf [0],
216*83ee113eSDavid van Moolenbroek 				     info -> hw_address.hlen - 1,
217*83ee113eSDavid van Moolenbroek 				     &info -> hw_address.hbuf [1]),
218*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ? "/" : ""),
219*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ?
220*83ee113eSDavid van Moolenbroek 		       info -> shared_network -> name : ""));
221*83ee113eSDavid van Moolenbroek }
222*83ee113eSDavid van Moolenbroek 
if_deregister_receive(info)223*83ee113eSDavid van Moolenbroek void if_deregister_receive (info)
224*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
225*83ee113eSDavid van Moolenbroek {
226*83ee113eSDavid van Moolenbroek 	close (info -> rfdesc);
227*83ee113eSDavid van Moolenbroek 	info -> rfdesc = -1;
228*83ee113eSDavid van Moolenbroek         if (!quiet_interface_discovery)
229*83ee113eSDavid van Moolenbroek 		log_info ("Disabling input on UPF/%s/%s%s%s",
230*83ee113eSDavid van Moolenbroek 		      info -> name,
231*83ee113eSDavid van Moolenbroek 		      print_hw_addr (info -> hw_address.hbuf [0],
232*83ee113eSDavid van Moolenbroek 				     info -> hw_address.hlen - 1,
233*83ee113eSDavid van Moolenbroek 				     &info -> hw_address.hbuf [1]),
234*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ? "/" : ""),
235*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ?
236*83ee113eSDavid van Moolenbroek 		       info -> shared_network -> name : ""));
237*83ee113eSDavid van Moolenbroek }
238*83ee113eSDavid van Moolenbroek #endif /* USE_UPF_RECEIVE */
239*83ee113eSDavid van Moolenbroek 
240*83ee113eSDavid van Moolenbroek #ifdef USE_UPF_SEND
send_packet(interface,packet,raw,len,from,to,hto)241*83ee113eSDavid van Moolenbroek ssize_t send_packet (interface, packet, raw, len, from, to, hto)
242*83ee113eSDavid van Moolenbroek 	struct interface_info *interface;
243*83ee113eSDavid van Moolenbroek 	struct packet *packet;
244*83ee113eSDavid van Moolenbroek 	struct dhcp_packet *raw;
245*83ee113eSDavid van Moolenbroek 	size_t len;
246*83ee113eSDavid van Moolenbroek 	struct in_addr from;
247*83ee113eSDavid van Moolenbroek 	struct sockaddr_in *to;
248*83ee113eSDavid van Moolenbroek 	struct hardware *hto;
249*83ee113eSDavid van Moolenbroek {
250*83ee113eSDavid van Moolenbroek 	unsigned hbufp = 0, ibufp = 0;
251*83ee113eSDavid van Moolenbroek 	double hw [4];
252*83ee113eSDavid van Moolenbroek 	double ip [32];
253*83ee113eSDavid van Moolenbroek 	struct iovec iov [3];
254*83ee113eSDavid van Moolenbroek 	int result;
255*83ee113eSDavid van Moolenbroek 	int fudge;
256*83ee113eSDavid van Moolenbroek 
257*83ee113eSDavid van Moolenbroek 	if (!strcmp (interface -> name, "fallback"))
258*83ee113eSDavid van Moolenbroek 		return send_fallback (interface, packet, raw,
259*83ee113eSDavid van Moolenbroek 				      len, from, to, hto);
260*83ee113eSDavid van Moolenbroek 
261*83ee113eSDavid van Moolenbroek 	if (hto == NULL && interface->anycast_mac_addr.hlen)
262*83ee113eSDavid van Moolenbroek 		hto = &interface->anycast_mac_addr;
263*83ee113eSDavid van Moolenbroek 
264*83ee113eSDavid van Moolenbroek 	/* Assemble the headers... */
265*83ee113eSDavid van Moolenbroek 	assemble_hw_header (interface, (unsigned char *)hw, &hbufp, hto);
266*83ee113eSDavid van Moolenbroek 	assemble_udp_ip_header (interface,
267*83ee113eSDavid van Moolenbroek 				(unsigned char *)ip, &ibufp, from.s_addr,
268*83ee113eSDavid van Moolenbroek 				to -> sin_addr.s_addr, to -> sin_port,
269*83ee113eSDavid van Moolenbroek 				(unsigned char *)raw, len);
270*83ee113eSDavid van Moolenbroek 
271*83ee113eSDavid van Moolenbroek 	/* Fire it off */
272*83ee113eSDavid van Moolenbroek 	iov [0].iov_base = ((char *)hw);
273*83ee113eSDavid van Moolenbroek 	iov [0].iov_len = hbufp;
274*83ee113eSDavid van Moolenbroek 	iov [1].iov_base = ((char *)ip);
275*83ee113eSDavid van Moolenbroek 	iov [1].iov_len = ibufp;
276*83ee113eSDavid van Moolenbroek 	iov [2].iov_base = (char *)raw;
277*83ee113eSDavid van Moolenbroek 	iov [2].iov_len = len;
278*83ee113eSDavid van Moolenbroek 
279*83ee113eSDavid van Moolenbroek 	result = writev(interface -> wfdesc, iov, 3);
280*83ee113eSDavid van Moolenbroek 	if (result < 0)
281*83ee113eSDavid van Moolenbroek 		log_error ("send_packet: %m");
282*83ee113eSDavid van Moolenbroek 	return result;
283*83ee113eSDavid van Moolenbroek }
284*83ee113eSDavid van Moolenbroek #endif /* USE_UPF_SEND */
285*83ee113eSDavid van Moolenbroek 
286*83ee113eSDavid van Moolenbroek #ifdef USE_UPF_RECEIVE
receive_packet(interface,buf,len,from,hfrom)287*83ee113eSDavid van Moolenbroek ssize_t receive_packet (interface, buf, len, from, hfrom)
288*83ee113eSDavid van Moolenbroek 	struct interface_info *interface;
289*83ee113eSDavid van Moolenbroek 	unsigned char *buf;
290*83ee113eSDavid van Moolenbroek 	size_t len;
291*83ee113eSDavid van Moolenbroek 	struct sockaddr_in *from;
292*83ee113eSDavid van Moolenbroek 	struct hardware *hfrom;
293*83ee113eSDavid van Moolenbroek {
294*83ee113eSDavid van Moolenbroek 	int nread;
295*83ee113eSDavid van Moolenbroek 	int length = 0;
296*83ee113eSDavid van Moolenbroek 	int offset = 0;
297*83ee113eSDavid van Moolenbroek 	unsigned char ibuf [1500 + sizeof (struct enstamp)];
298*83ee113eSDavid van Moolenbroek 	int bufix = 0;
299*83ee113eSDavid van Moolenbroek 	unsigned paylen;
300*83ee113eSDavid van Moolenbroek 
301*83ee113eSDavid van Moolenbroek 	length = read (interface -> rfdesc, ibuf, sizeof ibuf);
302*83ee113eSDavid van Moolenbroek 	if (length <= 0)
303*83ee113eSDavid van Moolenbroek 		return length;
304*83ee113eSDavid van Moolenbroek 
305*83ee113eSDavid van Moolenbroek 	bufix = sizeof (struct enstamp);
306*83ee113eSDavid van Moolenbroek 	/* Decode the physical header... */
307*83ee113eSDavid van Moolenbroek 	offset = decode_hw_header (interface, ibuf, bufix, hfrom);
308*83ee113eSDavid van Moolenbroek 
309*83ee113eSDavid van Moolenbroek 	/* If a physical layer checksum failed (dunno of any
310*83ee113eSDavid van Moolenbroek 	   physical layer that supports this, but WTH), skip this
311*83ee113eSDavid van Moolenbroek 	   packet. */
312*83ee113eSDavid van Moolenbroek 	if (offset < 0) {
313*83ee113eSDavid van Moolenbroek 		return 0;
314*83ee113eSDavid van Moolenbroek 	}
315*83ee113eSDavid van Moolenbroek 
316*83ee113eSDavid van Moolenbroek 	bufix += offset;
317*83ee113eSDavid van Moolenbroek 	length -= offset;
318*83ee113eSDavid van Moolenbroek 
319*83ee113eSDavid van Moolenbroek 	/* Decode the IP and UDP headers... */
320*83ee113eSDavid van Moolenbroek 	offset = decode_udp_ip_header (interface, ibuf, bufix,
321*83ee113eSDavid van Moolenbroek 				       from, length, &paylen);
322*83ee113eSDavid van Moolenbroek 
323*83ee113eSDavid van Moolenbroek 	/* If the IP or UDP checksum was bad, skip the packet... */
324*83ee113eSDavid van Moolenbroek 	if (offset < 0)
325*83ee113eSDavid van Moolenbroek 		return 0;
326*83ee113eSDavid van Moolenbroek 
327*83ee113eSDavid van Moolenbroek 	bufix += offset;
328*83ee113eSDavid van Moolenbroek 	length -= offset;
329*83ee113eSDavid van Moolenbroek 
330*83ee113eSDavid van Moolenbroek 	if (length < paylen)
331*83ee113eSDavid van Moolenbroek 		log_fatal("Internal inconsistency at %s:%d.", MDL);
332*83ee113eSDavid van Moolenbroek 
333*83ee113eSDavid van Moolenbroek 	/* Copy out the data in the packet... */
334*83ee113eSDavid van Moolenbroek 	memcpy (buf, &ibuf[bufix], paylen);
335*83ee113eSDavid van Moolenbroek 	return paylen;
336*83ee113eSDavid van Moolenbroek }
337*83ee113eSDavid van Moolenbroek 
can_unicast_without_arp(ip)338*83ee113eSDavid van Moolenbroek int can_unicast_without_arp (ip)
339*83ee113eSDavid van Moolenbroek 	struct interface_info *ip;
340*83ee113eSDavid van Moolenbroek {
341*83ee113eSDavid van Moolenbroek 	return 1;
342*83ee113eSDavid van Moolenbroek }
343*83ee113eSDavid van Moolenbroek 
can_receive_unicast_unconfigured(ip)344*83ee113eSDavid van Moolenbroek int can_receive_unicast_unconfigured (ip)
345*83ee113eSDavid van Moolenbroek 	struct interface_info *ip;
346*83ee113eSDavid van Moolenbroek {
347*83ee113eSDavid van Moolenbroek 	return 1;
348*83ee113eSDavid van Moolenbroek }
349*83ee113eSDavid van Moolenbroek 
supports_multiple_interfaces(ip)350*83ee113eSDavid van Moolenbroek int supports_multiple_interfaces (ip)
351*83ee113eSDavid van Moolenbroek 	struct interface_info *ip;
352*83ee113eSDavid van Moolenbroek {
353*83ee113eSDavid van Moolenbroek 	return 1;
354*83ee113eSDavid van Moolenbroek }
355*83ee113eSDavid van Moolenbroek 
maybe_setup_fallback()356*83ee113eSDavid van Moolenbroek void maybe_setup_fallback ()
357*83ee113eSDavid van Moolenbroek {
358*83ee113eSDavid van Moolenbroek 	isc_result_t status;
359*83ee113eSDavid van Moolenbroek 	struct interface_info *fbi = (struct interface_info *)0;
360*83ee113eSDavid van Moolenbroek 	if (setup_fallback (&fbi, MDL)) {
361*83ee113eSDavid van Moolenbroek 		if_register_fallback (fbi);
362*83ee113eSDavid van Moolenbroek 		status = omapi_register_io_object ((omapi_object_t *)fbi,
363*83ee113eSDavid van Moolenbroek 						   if_readsocket, 0,
364*83ee113eSDavid van Moolenbroek 						   fallback_discard, 0, 0);
365*83ee113eSDavid van Moolenbroek 		if (status != ISC_R_SUCCESS)
366*83ee113eSDavid van Moolenbroek 			log_fatal ("Can't register I/O handle for %s: %s",
367*83ee113eSDavid van Moolenbroek 				   fbi -> name, isc_result_totext (status));
368*83ee113eSDavid van Moolenbroek 		interface_dereference (&fbi, MDL);
369*83ee113eSDavid van Moolenbroek 	}
370*83ee113eSDavid van Moolenbroek }
371*83ee113eSDavid van Moolenbroek #endif
372