xref: /minix3/external/bsd/dhcp/dist/common/lpf.c (revision 83ee113ee0d94f3844d44065af2311604e9a30ad)
1*83ee113eSDavid van Moolenbroek /*	$NetBSD: lpf.c,v 1.1.1.4 2014/07/12 11:57:44 spz Exp $	*/
2*83ee113eSDavid van Moolenbroek /* lpf.c
3*83ee113eSDavid van Moolenbroek 
4*83ee113eSDavid van Moolenbroek    Linux packet filter code, contributed by Brian Murrel at Interlinx
5*83ee113eSDavid van Moolenbroek    Support Services in Vancouver, B.C. */
6*83ee113eSDavid van Moolenbroek 
7*83ee113eSDavid van Moolenbroek /*
8*83ee113eSDavid van Moolenbroek  * Copyright (c) 2009,2012 by Internet Systems Consortium, Inc. ("ISC")
9*83ee113eSDavid van Moolenbroek  * Copyright (c) 2004,2007 by Internet Systems Consortium, Inc. ("ISC")
10*83ee113eSDavid van Moolenbroek  * Copyright (c) 1996-2003 by Internet Software Consortium
11*83ee113eSDavid van Moolenbroek  *
12*83ee113eSDavid van Moolenbroek  * Permission to use, copy, modify, and distribute this software for any
13*83ee113eSDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
14*83ee113eSDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
15*83ee113eSDavid van Moolenbroek  *
16*83ee113eSDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
17*83ee113eSDavid van Moolenbroek  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
18*83ee113eSDavid van Moolenbroek  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
19*83ee113eSDavid van Moolenbroek  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20*83ee113eSDavid van Moolenbroek  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
21*83ee113eSDavid van Moolenbroek  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
22*83ee113eSDavid van Moolenbroek  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23*83ee113eSDavid van Moolenbroek  *
24*83ee113eSDavid van Moolenbroek  *   Internet Systems Consortium, Inc.
25*83ee113eSDavid van Moolenbroek  *   950 Charter Street
26*83ee113eSDavid van Moolenbroek  *   Redwood City, CA 94063
27*83ee113eSDavid van Moolenbroek  *   <info@isc.org>
28*83ee113eSDavid van Moolenbroek  *   https://www.isc.org/
29*83ee113eSDavid van Moolenbroek  */
30*83ee113eSDavid van Moolenbroek 
31*83ee113eSDavid van Moolenbroek #include <sys/cdefs.h>
32*83ee113eSDavid van Moolenbroek __RCSID("$NetBSD: lpf.c,v 1.1.1.4 2014/07/12 11:57:44 spz Exp $");
33*83ee113eSDavid van Moolenbroek 
34*83ee113eSDavid van Moolenbroek #include "dhcpd.h"
35*83ee113eSDavid van Moolenbroek #if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE)
36*83ee113eSDavid van Moolenbroek #include <sys/uio.h>
37*83ee113eSDavid van Moolenbroek #include <errno.h>
38*83ee113eSDavid van Moolenbroek 
39*83ee113eSDavid van Moolenbroek #include <asm/types.h>
40*83ee113eSDavid van Moolenbroek #include <linux/filter.h>
41*83ee113eSDavid van Moolenbroek #include <linux/if_ether.h>
42*83ee113eSDavid van Moolenbroek #include <netinet/in_systm.h>
43*83ee113eSDavid van Moolenbroek #include <net/if_packet.h>
44*83ee113eSDavid van Moolenbroek #include "includes/netinet/ip.h"
45*83ee113eSDavid van Moolenbroek #include "includes/netinet/udp.h"
46*83ee113eSDavid van Moolenbroek #include "includes/netinet/if_ether.h"
47*83ee113eSDavid van Moolenbroek #endif
48*83ee113eSDavid van Moolenbroek 
49*83ee113eSDavid van Moolenbroek #if defined (USE_LPF_RECEIVE) || defined (USE_LPF_HWADDR)
50*83ee113eSDavid van Moolenbroek #include <sys/ioctl.h>
51*83ee113eSDavid van Moolenbroek #include <net/if.h>
52*83ee113eSDavid van Moolenbroek #endif
53*83ee113eSDavid van Moolenbroek 
54*83ee113eSDavid van Moolenbroek #if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE)
55*83ee113eSDavid van Moolenbroek /* Reinitializes the specified interface after an address change.   This
56*83ee113eSDavid van Moolenbroek    is not required for packet-filter APIs. */
57*83ee113eSDavid van Moolenbroek 
58*83ee113eSDavid van Moolenbroek #ifdef USE_LPF_SEND
if_reinitialize_send(info)59*83ee113eSDavid van Moolenbroek void if_reinitialize_send (info)
60*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
61*83ee113eSDavid van Moolenbroek {
62*83ee113eSDavid van Moolenbroek }
63*83ee113eSDavid van Moolenbroek #endif
64*83ee113eSDavid van Moolenbroek 
65*83ee113eSDavid van Moolenbroek #ifdef USE_LPF_RECEIVE
if_reinitialize_receive(info)66*83ee113eSDavid van Moolenbroek void if_reinitialize_receive (info)
67*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
68*83ee113eSDavid van Moolenbroek {
69*83ee113eSDavid van Moolenbroek }
70*83ee113eSDavid van Moolenbroek #endif
71*83ee113eSDavid van Moolenbroek 
72*83ee113eSDavid van Moolenbroek /* Called by get_interface_list for each interface that's discovered.
73*83ee113eSDavid van Moolenbroek    Opens a packet filter for each interface and adds it to the select
74*83ee113eSDavid van Moolenbroek    mask. */
75*83ee113eSDavid van Moolenbroek 
if_register_lpf(info)76*83ee113eSDavid van Moolenbroek int if_register_lpf (info)
77*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
78*83ee113eSDavid van Moolenbroek {
79*83ee113eSDavid van Moolenbroek 	int sock;
80*83ee113eSDavid van Moolenbroek 	struct sockaddr sa;
81*83ee113eSDavid van Moolenbroek 
82*83ee113eSDavid van Moolenbroek 	/* Make an LPF socket. */
83*83ee113eSDavid van Moolenbroek 	if ((sock = socket(PF_PACKET, SOCK_PACKET,
84*83ee113eSDavid van Moolenbroek 			   htons((short)ETH_P_ALL))) < 0) {
85*83ee113eSDavid van Moolenbroek 		if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
86*83ee113eSDavid van Moolenbroek 		    errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
87*83ee113eSDavid van Moolenbroek 		    errno == EAFNOSUPPORT || errno == EINVAL) {
88*83ee113eSDavid van Moolenbroek 			log_error ("socket: %m - make sure");
89*83ee113eSDavid van Moolenbroek 			log_error ("CONFIG_PACKET (Packet socket) %s",
90*83ee113eSDavid van Moolenbroek 				   "and CONFIG_FILTER");
91*83ee113eSDavid van Moolenbroek 			log_error ("(Socket Filtering) are enabled %s",
92*83ee113eSDavid van Moolenbroek 				   "in your kernel");
93*83ee113eSDavid van Moolenbroek 			log_fatal ("configuration!");
94*83ee113eSDavid van Moolenbroek 		}
95*83ee113eSDavid van Moolenbroek 		log_fatal ("Open a socket for LPF: %m");
96*83ee113eSDavid van Moolenbroek 	}
97*83ee113eSDavid van Moolenbroek 
98*83ee113eSDavid van Moolenbroek 	/* Bind to the interface name */
99*83ee113eSDavid van Moolenbroek 	memset (&sa, 0, sizeof sa);
100*83ee113eSDavid van Moolenbroek 	sa.sa_family = AF_PACKET;
101*83ee113eSDavid van Moolenbroek 	strncpy (sa.sa_data, (const char *)info -> ifp, sizeof sa.sa_data);
102*83ee113eSDavid van Moolenbroek 	if (bind (sock, &sa, sizeof sa)) {
103*83ee113eSDavid van Moolenbroek 		if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
104*83ee113eSDavid van Moolenbroek 		    errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
105*83ee113eSDavid van Moolenbroek 		    errno == EAFNOSUPPORT || errno == EINVAL) {
106*83ee113eSDavid van Moolenbroek 			log_error ("socket: %m - make sure");
107*83ee113eSDavid van Moolenbroek 			log_error ("CONFIG_PACKET (Packet socket) %s",
108*83ee113eSDavid van Moolenbroek 				   "and CONFIG_FILTER");
109*83ee113eSDavid van Moolenbroek 			log_error ("(Socket Filtering) are enabled %s",
110*83ee113eSDavid van Moolenbroek 				   "in your kernel");
111*83ee113eSDavid van Moolenbroek 			log_fatal ("configuration!");
112*83ee113eSDavid van Moolenbroek 		}
113*83ee113eSDavid van Moolenbroek 		log_fatal ("Bind socket to interface: %m");
114*83ee113eSDavid van Moolenbroek 	}
115*83ee113eSDavid van Moolenbroek 
116*83ee113eSDavid van Moolenbroek 	get_hw_addr(info->name, &info->hw_address);
117*83ee113eSDavid van Moolenbroek 
118*83ee113eSDavid van Moolenbroek 	return sock;
119*83ee113eSDavid van Moolenbroek }
120*83ee113eSDavid van Moolenbroek #endif /* USE_LPF_SEND || USE_LPF_RECEIVE */
121*83ee113eSDavid van Moolenbroek 
122*83ee113eSDavid van Moolenbroek #ifdef USE_LPF_SEND
if_register_send(info)123*83ee113eSDavid van Moolenbroek void if_register_send (info)
124*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
125*83ee113eSDavid van Moolenbroek {
126*83ee113eSDavid van Moolenbroek 	/* If we're using the lpf API for sending and receiving,
127*83ee113eSDavid van Moolenbroek 	   we don't need to register this interface twice. */
128*83ee113eSDavid van Moolenbroek #ifndef USE_LPF_RECEIVE
129*83ee113eSDavid van Moolenbroek 	info -> wfdesc = if_register_lpf (info);
130*83ee113eSDavid van Moolenbroek #else
131*83ee113eSDavid van Moolenbroek 	info -> wfdesc = info -> rfdesc;
132*83ee113eSDavid van Moolenbroek #endif
133*83ee113eSDavid van Moolenbroek 	if (!quiet_interface_discovery)
134*83ee113eSDavid van Moolenbroek 		log_info ("Sending on   LPF/%s/%s%s%s",
135*83ee113eSDavid van Moolenbroek 		      info -> name,
136*83ee113eSDavid van Moolenbroek 		      print_hw_addr (info -> hw_address.hbuf [0],
137*83ee113eSDavid van Moolenbroek 				     info -> hw_address.hlen - 1,
138*83ee113eSDavid van Moolenbroek 				     &info -> hw_address.hbuf [1]),
139*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ? "/" : ""),
140*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ?
141*83ee113eSDavid van Moolenbroek 		       info -> shared_network -> name : ""));
142*83ee113eSDavid van Moolenbroek }
143*83ee113eSDavid van Moolenbroek 
if_deregister_send(info)144*83ee113eSDavid van Moolenbroek void if_deregister_send (info)
145*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
146*83ee113eSDavid van Moolenbroek {
147*83ee113eSDavid van Moolenbroek 	/* don't need to close twice if we are using lpf for sending and
148*83ee113eSDavid van Moolenbroek 	   receiving */
149*83ee113eSDavid van Moolenbroek #ifndef USE_LPF_RECEIVE
150*83ee113eSDavid van Moolenbroek 	/* for LPF this is simple, packet filters are removed when sockets
151*83ee113eSDavid van Moolenbroek 	   are closed */
152*83ee113eSDavid van Moolenbroek 	close (info -> wfdesc);
153*83ee113eSDavid van Moolenbroek #endif
154*83ee113eSDavid van Moolenbroek 	info -> wfdesc = -1;
155*83ee113eSDavid van Moolenbroek 	if (!quiet_interface_discovery)
156*83ee113eSDavid van Moolenbroek 		log_info ("Disabling output on LPF/%s/%s%s%s",
157*83ee113eSDavid van Moolenbroek 		      info -> name,
158*83ee113eSDavid van Moolenbroek 		      print_hw_addr (info -> hw_address.hbuf [0],
159*83ee113eSDavid van Moolenbroek 				     info -> hw_address.hlen - 1,
160*83ee113eSDavid van Moolenbroek 				     &info -> hw_address.hbuf [1]),
161*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ? "/" : ""),
162*83ee113eSDavid van Moolenbroek 		      (info -> shared_network ?
163*83ee113eSDavid van Moolenbroek 		       info -> shared_network -> name : ""));
164*83ee113eSDavid van Moolenbroek }
165*83ee113eSDavid van Moolenbroek #endif /* USE_LPF_SEND */
166*83ee113eSDavid van Moolenbroek 
167*83ee113eSDavid van Moolenbroek #ifdef USE_LPF_RECEIVE
168*83ee113eSDavid van Moolenbroek /* Defined in bpf.c.   We can't extern these in dhcpd.h without pulling
169*83ee113eSDavid van Moolenbroek    in bpf includes... */
170*83ee113eSDavid van Moolenbroek extern struct sock_filter dhcp_bpf_filter [];
171*83ee113eSDavid van Moolenbroek extern int dhcp_bpf_filter_len;
172*83ee113eSDavid van Moolenbroek 
173*83ee113eSDavid van Moolenbroek #if defined (HAVE_TR_SUPPORT)
174*83ee113eSDavid van Moolenbroek extern struct sock_filter dhcp_bpf_tr_filter [];
175*83ee113eSDavid van Moolenbroek extern int dhcp_bpf_tr_filter_len;
176*83ee113eSDavid van Moolenbroek static void lpf_tr_filter_setup (struct interface_info *);
177*83ee113eSDavid van Moolenbroek #endif
178*83ee113eSDavid van Moolenbroek 
179*83ee113eSDavid van Moolenbroek static void lpf_gen_filter_setup (struct interface_info *);
180*83ee113eSDavid van Moolenbroek 
if_register_receive(info)181*83ee113eSDavid van Moolenbroek void if_register_receive (info)
182*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
183*83ee113eSDavid van Moolenbroek {
184*83ee113eSDavid van Moolenbroek 	/* Open a LPF device and hang it on this interface... */
185*83ee113eSDavid van Moolenbroek 	info -> rfdesc = if_register_lpf (info);
186*83ee113eSDavid van Moolenbroek 
187*83ee113eSDavid van Moolenbroek #if defined (HAVE_TR_SUPPORT)
188*83ee113eSDavid van Moolenbroek 	if (info -> hw_address.hbuf [0] == HTYPE_IEEE802)
189*83ee113eSDavid van Moolenbroek 		lpf_tr_filter_setup (info);
190*83ee113eSDavid van Moolenbroek 	else
191*83ee113eSDavid van Moolenbroek #endif
192*83ee113eSDavid van Moolenbroek 		lpf_gen_filter_setup (info);
193*83ee113eSDavid van Moolenbroek 
194*83ee113eSDavid van Moolenbroek 	if (!quiet_interface_discovery)
195*83ee113eSDavid van Moolenbroek 		log_info ("Listening on LPF/%s/%s%s%s",
196*83ee113eSDavid van Moolenbroek 			  info -> name,
197*83ee113eSDavid van Moolenbroek 			  print_hw_addr (info -> hw_address.hbuf [0],
198*83ee113eSDavid van Moolenbroek 					 info -> hw_address.hlen - 1,
199*83ee113eSDavid van Moolenbroek 					 &info -> hw_address.hbuf [1]),
200*83ee113eSDavid van Moolenbroek 			  (info -> shared_network ? "/" : ""),
201*83ee113eSDavid van Moolenbroek 			  (info -> shared_network ?
202*83ee113eSDavid van Moolenbroek 			   info -> shared_network -> name : ""));
203*83ee113eSDavid van Moolenbroek }
204*83ee113eSDavid van Moolenbroek 
if_deregister_receive(info)205*83ee113eSDavid van Moolenbroek void if_deregister_receive (info)
206*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
207*83ee113eSDavid van Moolenbroek {
208*83ee113eSDavid van Moolenbroek 	/* for LPF this is simple, packet filters are removed when sockets
209*83ee113eSDavid van Moolenbroek 	   are closed */
210*83ee113eSDavid van Moolenbroek 	close (info -> rfdesc);
211*83ee113eSDavid van Moolenbroek 	info -> rfdesc = -1;
212*83ee113eSDavid van Moolenbroek 	if (!quiet_interface_discovery)
213*83ee113eSDavid van Moolenbroek 		log_info ("Disabling input on LPF/%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 
lpf_gen_filter_setup(info)223*83ee113eSDavid van Moolenbroek static void lpf_gen_filter_setup (info)
224*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
225*83ee113eSDavid van Moolenbroek {
226*83ee113eSDavid van Moolenbroek 	struct sock_fprog p;
227*83ee113eSDavid van Moolenbroek 
228*83ee113eSDavid van Moolenbroek 	memset(&p, 0, sizeof(p));
229*83ee113eSDavid van Moolenbroek 
230*83ee113eSDavid van Moolenbroek 	/* Set up the bpf filter program structure.    This is defined in
231*83ee113eSDavid van Moolenbroek 	   bpf.c */
232*83ee113eSDavid van Moolenbroek 	p.len = dhcp_bpf_filter_len;
233*83ee113eSDavid van Moolenbroek 	p.filter = dhcp_bpf_filter;
234*83ee113eSDavid van Moolenbroek 
235*83ee113eSDavid van Moolenbroek         /* Patch the server port into the LPF  program...
236*83ee113eSDavid van Moolenbroek 	   XXX changes to filter program may require changes
237*83ee113eSDavid van Moolenbroek 	   to the insn number(s) used below! XXX */
238*83ee113eSDavid van Moolenbroek 	dhcp_bpf_filter [8].k = ntohs ((short)local_port);
239*83ee113eSDavid van Moolenbroek 
240*83ee113eSDavid van Moolenbroek 	if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p,
241*83ee113eSDavid van Moolenbroek 			sizeof p) < 0) {
242*83ee113eSDavid van Moolenbroek 		if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
243*83ee113eSDavid van Moolenbroek 		    errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
244*83ee113eSDavid van Moolenbroek 		    errno == EAFNOSUPPORT) {
245*83ee113eSDavid van Moolenbroek 			log_error ("socket: %m - make sure");
246*83ee113eSDavid van Moolenbroek 			log_error ("CONFIG_PACKET (Packet socket) %s",
247*83ee113eSDavid van Moolenbroek 				   "and CONFIG_FILTER");
248*83ee113eSDavid van Moolenbroek 			log_error ("(Socket Filtering) are enabled %s",
249*83ee113eSDavid van Moolenbroek 				   "in your kernel");
250*83ee113eSDavid van Moolenbroek 			log_fatal ("configuration!");
251*83ee113eSDavid van Moolenbroek 		}
252*83ee113eSDavid van Moolenbroek 		log_fatal ("Can't install packet filter program: %m");
253*83ee113eSDavid van Moolenbroek 	}
254*83ee113eSDavid van Moolenbroek }
255*83ee113eSDavid van Moolenbroek 
256*83ee113eSDavid van Moolenbroek #if defined (HAVE_TR_SUPPORT)
lpf_tr_filter_setup(info)257*83ee113eSDavid van Moolenbroek static void lpf_tr_filter_setup (info)
258*83ee113eSDavid van Moolenbroek 	struct interface_info *info;
259*83ee113eSDavid van Moolenbroek {
260*83ee113eSDavid van Moolenbroek 	struct sock_fprog p;
261*83ee113eSDavid van Moolenbroek 
262*83ee113eSDavid van Moolenbroek 	memset(&p, 0, sizeof(p));
263*83ee113eSDavid van Moolenbroek 
264*83ee113eSDavid van Moolenbroek 	/* Set up the bpf filter program structure.    This is defined in
265*83ee113eSDavid van Moolenbroek 	   bpf.c */
266*83ee113eSDavid van Moolenbroek 	p.len = dhcp_bpf_tr_filter_len;
267*83ee113eSDavid van Moolenbroek 	p.filter = dhcp_bpf_tr_filter;
268*83ee113eSDavid van Moolenbroek 
269*83ee113eSDavid van Moolenbroek         /* Patch the server port into the LPF  program...
270*83ee113eSDavid van Moolenbroek 	   XXX changes to filter program may require changes
271*83ee113eSDavid van Moolenbroek 	   XXX to the insn number(s) used below!
272*83ee113eSDavid van Moolenbroek 	   XXX Token ring filter is null - when/if we have a filter
273*83ee113eSDavid van Moolenbroek 	   XXX that's not, we'll need this code.
274*83ee113eSDavid van Moolenbroek 	   XXX dhcp_bpf_filter [?].k = ntohs (local_port); */
275*83ee113eSDavid van Moolenbroek 
276*83ee113eSDavid van Moolenbroek 	if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p,
277*83ee113eSDavid van Moolenbroek 			sizeof p) < 0) {
278*83ee113eSDavid van Moolenbroek 		if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
279*83ee113eSDavid van Moolenbroek 		    errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
280*83ee113eSDavid van Moolenbroek 		    errno == EAFNOSUPPORT) {
281*83ee113eSDavid van Moolenbroek 			log_error ("socket: %m - make sure");
282*83ee113eSDavid van Moolenbroek 			log_error ("CONFIG_PACKET (Packet socket) %s",
283*83ee113eSDavid van Moolenbroek 				   "and CONFIG_FILTER");
284*83ee113eSDavid van Moolenbroek 			log_error ("(Socket Filtering) are enabled %s",
285*83ee113eSDavid van Moolenbroek 				   "in your kernel");
286*83ee113eSDavid van Moolenbroek 			log_fatal ("configuration!");
287*83ee113eSDavid van Moolenbroek 		}
288*83ee113eSDavid van Moolenbroek 		log_fatal ("Can't install packet filter program: %m");
289*83ee113eSDavid van Moolenbroek 	}
290*83ee113eSDavid van Moolenbroek }
291*83ee113eSDavid van Moolenbroek #endif /* HAVE_TR_SUPPORT */
292*83ee113eSDavid van Moolenbroek #endif /* USE_LPF_RECEIVE */
293*83ee113eSDavid van Moolenbroek 
294*83ee113eSDavid van Moolenbroek #ifdef USE_LPF_SEND
send_packet(interface,packet,raw,len,from,to,hto)295*83ee113eSDavid van Moolenbroek ssize_t send_packet (interface, packet, raw, len, from, to, hto)
296*83ee113eSDavid van Moolenbroek 	struct interface_info *interface;
297*83ee113eSDavid van Moolenbroek 	struct packet *packet;
298*83ee113eSDavid van Moolenbroek 	struct dhcp_packet *raw;
299*83ee113eSDavid van Moolenbroek 	size_t len;
300*83ee113eSDavid van Moolenbroek 	struct in_addr from;
301*83ee113eSDavid van Moolenbroek 	struct sockaddr_in *to;
302*83ee113eSDavid van Moolenbroek 	struct hardware *hto;
303*83ee113eSDavid van Moolenbroek {
304*83ee113eSDavid van Moolenbroek 	unsigned hbufp = 0, ibufp = 0;
305*83ee113eSDavid van Moolenbroek 	double hh [16];
306*83ee113eSDavid van Moolenbroek 	double ih [1536 / sizeof (double)];
307*83ee113eSDavid van Moolenbroek 	unsigned char *buf = (unsigned char *)ih;
308*83ee113eSDavid van Moolenbroek 	struct sockaddr_pkt sa;
309*83ee113eSDavid van Moolenbroek 	int result;
310*83ee113eSDavid van Moolenbroek 	int fudge;
311*83ee113eSDavid van Moolenbroek 
312*83ee113eSDavid van Moolenbroek 	if (!strcmp (interface -> name, "fallback"))
313*83ee113eSDavid van Moolenbroek 		return send_fallback (interface, packet, raw,
314*83ee113eSDavid van Moolenbroek 				      len, from, to, hto);
315*83ee113eSDavid van Moolenbroek 
316*83ee113eSDavid van Moolenbroek 	if (hto == NULL && interface->anycast_mac_addr.hlen)
317*83ee113eSDavid van Moolenbroek 		hto = &interface->anycast_mac_addr;
318*83ee113eSDavid van Moolenbroek 
319*83ee113eSDavid van Moolenbroek 	/* Assemble the headers... */
320*83ee113eSDavid van Moolenbroek 	assemble_hw_header (interface, (unsigned char *)hh, &hbufp, hto);
321*83ee113eSDavid van Moolenbroek 	fudge = hbufp % 4;	/* IP header must be word-aligned. */
322*83ee113eSDavid van Moolenbroek 	memcpy (buf + fudge, (unsigned char *)hh, hbufp);
323*83ee113eSDavid van Moolenbroek 	ibufp = hbufp + fudge;
324*83ee113eSDavid van Moolenbroek 	assemble_udp_ip_header (interface, buf, &ibufp, from.s_addr,
325*83ee113eSDavid van Moolenbroek 				to -> sin_addr.s_addr, to -> sin_port,
326*83ee113eSDavid van Moolenbroek 				(unsigned char *)raw, len);
327*83ee113eSDavid van Moolenbroek 	memcpy (buf + ibufp, raw, len);
328*83ee113eSDavid van Moolenbroek 
329*83ee113eSDavid van Moolenbroek 	/* For some reason, SOCK_PACKET sockets can't be connected,
330*83ee113eSDavid van Moolenbroek 	   so we have to do a sentdo every time. */
331*83ee113eSDavid van Moolenbroek 	memset (&sa, 0, sizeof sa);
332*83ee113eSDavid van Moolenbroek 	sa.spkt_family = AF_PACKET;
333*83ee113eSDavid van Moolenbroek 	strncpy ((char *)sa.spkt_device,
334*83ee113eSDavid van Moolenbroek 		 (const char *)interface -> ifp, sizeof sa.spkt_device);
335*83ee113eSDavid van Moolenbroek 	sa.spkt_protocol = htons(ETH_P_IP);
336*83ee113eSDavid van Moolenbroek 
337*83ee113eSDavid van Moolenbroek 	result = sendto (interface -> wfdesc,
338*83ee113eSDavid van Moolenbroek 			 buf + fudge, ibufp + len - fudge, 0,
339*83ee113eSDavid van Moolenbroek 			 (const struct sockaddr *)&sa, sizeof sa);
340*83ee113eSDavid van Moolenbroek 	if (result < 0)
341*83ee113eSDavid van Moolenbroek 		log_error ("send_packet: %m");
342*83ee113eSDavid van Moolenbroek 	return result;
343*83ee113eSDavid van Moolenbroek }
344*83ee113eSDavid van Moolenbroek #endif /* USE_LPF_SEND */
345*83ee113eSDavid van Moolenbroek 
346*83ee113eSDavid van Moolenbroek #ifdef USE_LPF_RECEIVE
receive_packet(interface,buf,len,from,hfrom)347*83ee113eSDavid van Moolenbroek ssize_t receive_packet (interface, buf, len, from, hfrom)
348*83ee113eSDavid van Moolenbroek 	struct interface_info *interface;
349*83ee113eSDavid van Moolenbroek 	unsigned char *buf;
350*83ee113eSDavid van Moolenbroek 	size_t len;
351*83ee113eSDavid van Moolenbroek 	struct sockaddr_in *from;
352*83ee113eSDavid van Moolenbroek 	struct hardware *hfrom;
353*83ee113eSDavid van Moolenbroek {
354*83ee113eSDavid van Moolenbroek 	int length = 0;
355*83ee113eSDavid van Moolenbroek 	int offset = 0;
356*83ee113eSDavid van Moolenbroek 	unsigned char ibuf [1536];
357*83ee113eSDavid van Moolenbroek 	unsigned bufix = 0;
358*83ee113eSDavid van Moolenbroek 	unsigned paylen;
359*83ee113eSDavid van Moolenbroek 
360*83ee113eSDavid van Moolenbroek 	length = read (interface -> rfdesc, ibuf, sizeof ibuf);
361*83ee113eSDavid van Moolenbroek 	if (length <= 0)
362*83ee113eSDavid van Moolenbroek 		return length;
363*83ee113eSDavid van Moolenbroek 
364*83ee113eSDavid van Moolenbroek 	bufix = 0;
365*83ee113eSDavid van Moolenbroek 	/* Decode the physical header... */
366*83ee113eSDavid van Moolenbroek 	offset = decode_hw_header (interface, ibuf, bufix, hfrom);
367*83ee113eSDavid van Moolenbroek 
368*83ee113eSDavid van Moolenbroek 	/* If a physical layer checksum failed (dunno of any
369*83ee113eSDavid van Moolenbroek 	   physical layer that supports this, but WTH), skip this
370*83ee113eSDavid van Moolenbroek 	   packet. */
371*83ee113eSDavid van Moolenbroek 	if (offset < 0) {
372*83ee113eSDavid van Moolenbroek 		return 0;
373*83ee113eSDavid van Moolenbroek 	}
374*83ee113eSDavid van Moolenbroek 
375*83ee113eSDavid van Moolenbroek 	bufix += offset;
376*83ee113eSDavid van Moolenbroek 	length -= offset;
377*83ee113eSDavid van Moolenbroek 
378*83ee113eSDavid van Moolenbroek 	/* Decode the IP and UDP headers... */
379*83ee113eSDavid van Moolenbroek 	offset = decode_udp_ip_header (interface, ibuf, bufix, from,
380*83ee113eSDavid van Moolenbroek 				       (unsigned)length, &paylen);
381*83ee113eSDavid van Moolenbroek 
382*83ee113eSDavid van Moolenbroek 	/* If the IP or UDP checksum was bad, skip the packet... */
383*83ee113eSDavid van Moolenbroek 	if (offset < 0)
384*83ee113eSDavid van Moolenbroek 		return 0;
385*83ee113eSDavid van Moolenbroek 
386*83ee113eSDavid van Moolenbroek 	bufix += offset;
387*83ee113eSDavid van Moolenbroek 	length -= offset;
388*83ee113eSDavid van Moolenbroek 
389*83ee113eSDavid van Moolenbroek 	if (length < paylen)
390*83ee113eSDavid van Moolenbroek 		log_fatal("Internal inconsistency at %s:%d.", MDL);
391*83ee113eSDavid van Moolenbroek 
392*83ee113eSDavid van Moolenbroek 	/* Copy out the data in the packet... */
393*83ee113eSDavid van Moolenbroek 	memcpy(buf, &ibuf[bufix], paylen);
394*83ee113eSDavid van Moolenbroek 	return paylen;
395*83ee113eSDavid van Moolenbroek }
396*83ee113eSDavid van Moolenbroek 
can_unicast_without_arp(ip)397*83ee113eSDavid van Moolenbroek int can_unicast_without_arp (ip)
398*83ee113eSDavid van Moolenbroek 	struct interface_info *ip;
399*83ee113eSDavid van Moolenbroek {
400*83ee113eSDavid van Moolenbroek 	return 1;
401*83ee113eSDavid van Moolenbroek }
402*83ee113eSDavid van Moolenbroek 
can_receive_unicast_unconfigured(ip)403*83ee113eSDavid van Moolenbroek int can_receive_unicast_unconfigured (ip)
404*83ee113eSDavid van Moolenbroek 	struct interface_info *ip;
405*83ee113eSDavid van Moolenbroek {
406*83ee113eSDavid van Moolenbroek 	return 1;
407*83ee113eSDavid van Moolenbroek }
408*83ee113eSDavid van Moolenbroek 
supports_multiple_interfaces(ip)409*83ee113eSDavid van Moolenbroek int supports_multiple_interfaces (ip)
410*83ee113eSDavid van Moolenbroek 	struct interface_info *ip;
411*83ee113eSDavid van Moolenbroek {
412*83ee113eSDavid van Moolenbroek 	return 1;
413*83ee113eSDavid van Moolenbroek }
414*83ee113eSDavid van Moolenbroek 
maybe_setup_fallback()415*83ee113eSDavid van Moolenbroek void maybe_setup_fallback ()
416*83ee113eSDavid van Moolenbroek {
417*83ee113eSDavid van Moolenbroek 	isc_result_t status;
418*83ee113eSDavid van Moolenbroek 	struct interface_info *fbi = (struct interface_info *)0;
419*83ee113eSDavid van Moolenbroek 	if (setup_fallback (&fbi, MDL)) {
420*83ee113eSDavid van Moolenbroek 		if_register_fallback (fbi);
421*83ee113eSDavid van Moolenbroek 		status = omapi_register_io_object ((omapi_object_t *)fbi,
422*83ee113eSDavid van Moolenbroek 						   if_readsocket, 0,
423*83ee113eSDavid van Moolenbroek 						   fallback_discard, 0, 0);
424*83ee113eSDavid van Moolenbroek 		if (status != ISC_R_SUCCESS)
425*83ee113eSDavid van Moolenbroek 			log_fatal ("Can't register I/O handle for \"%s\": %s",
426*83ee113eSDavid van Moolenbroek 				   fbi -> name, isc_result_totext (status));
427*83ee113eSDavid van Moolenbroek 		interface_dereference (&fbi, MDL);
428*83ee113eSDavid van Moolenbroek 	}
429*83ee113eSDavid van Moolenbroek }
430*83ee113eSDavid van Moolenbroek #endif
431*83ee113eSDavid van Moolenbroek 
432*83ee113eSDavid van Moolenbroek #if defined (USE_LPF_RECEIVE) || defined (USE_LPF_HWADDR)
433*83ee113eSDavid van Moolenbroek void
get_hw_addr(const char * name,struct hardware * hw)434*83ee113eSDavid van Moolenbroek get_hw_addr(const char *name, struct hardware *hw) {
435*83ee113eSDavid van Moolenbroek 	int sock;
436*83ee113eSDavid van Moolenbroek 	struct ifreq tmp;
437*83ee113eSDavid van Moolenbroek 	struct sockaddr *sa;
438*83ee113eSDavid van Moolenbroek 
439*83ee113eSDavid van Moolenbroek 	if (strlen(name) >= sizeof(tmp.ifr_name)) {
440*83ee113eSDavid van Moolenbroek 		log_fatal("Device name too long: \"%s\"", name);
441*83ee113eSDavid van Moolenbroek 	}
442*83ee113eSDavid van Moolenbroek 
443*83ee113eSDavid van Moolenbroek 	sock = socket(AF_INET, SOCK_DGRAM, 0);
444*83ee113eSDavid van Moolenbroek 	if (sock < 0) {
445*83ee113eSDavid van Moolenbroek 		log_fatal("Can't create socket for \"%s\": %m", name);
446*83ee113eSDavid van Moolenbroek 	}
447*83ee113eSDavid van Moolenbroek 
448*83ee113eSDavid van Moolenbroek 	memset(&tmp, 0, sizeof(tmp));
449*83ee113eSDavid van Moolenbroek 	strcpy(tmp.ifr_name, name);
450*83ee113eSDavid van Moolenbroek 	if (ioctl(sock, SIOCGIFHWADDR, &tmp) < 0) {
451*83ee113eSDavid van Moolenbroek 		log_fatal("Error getting hardware address for \"%s\": %m",
452*83ee113eSDavid van Moolenbroek 			  name);
453*83ee113eSDavid van Moolenbroek 	}
454*83ee113eSDavid van Moolenbroek 
455*83ee113eSDavid van Moolenbroek 	sa = &tmp.ifr_hwaddr;
456*83ee113eSDavid van Moolenbroek 	switch (sa->sa_family) {
457*83ee113eSDavid van Moolenbroek 		case ARPHRD_ETHER:
458*83ee113eSDavid van Moolenbroek 			hw->hlen = 7;
459*83ee113eSDavid van Moolenbroek 			hw->hbuf[0] = HTYPE_ETHER;
460*83ee113eSDavid van Moolenbroek 			memcpy(&hw->hbuf[1], sa->sa_data, 6);
461*83ee113eSDavid van Moolenbroek 			break;
462*83ee113eSDavid van Moolenbroek 		case ARPHRD_IEEE802:
463*83ee113eSDavid van Moolenbroek #ifdef ARPHRD_IEEE802_TR
464*83ee113eSDavid van Moolenbroek 		case ARPHRD_IEEE802_TR:
465*83ee113eSDavid van Moolenbroek #endif /* ARPHRD_IEEE802_TR */
466*83ee113eSDavid van Moolenbroek 			hw->hlen = 7;
467*83ee113eSDavid van Moolenbroek 			hw->hbuf[0] = HTYPE_IEEE802;
468*83ee113eSDavid van Moolenbroek 			memcpy(&hw->hbuf[1], sa->sa_data, 6);
469*83ee113eSDavid van Moolenbroek 			break;
470*83ee113eSDavid van Moolenbroek 		case ARPHRD_FDDI:
471*83ee113eSDavid van Moolenbroek 			hw->hlen = 7;
472*83ee113eSDavid van Moolenbroek 			hw->hbuf[0] = HTYPE_FDDI;
473*83ee113eSDavid van Moolenbroek 			memcpy(&hw->hbuf[1], sa->sa_data, 6);
474*83ee113eSDavid van Moolenbroek 			break;
475*83ee113eSDavid van Moolenbroek 		default:
476*83ee113eSDavid van Moolenbroek 			log_fatal("Unsupported device type %ld for \"%s\"",
477*83ee113eSDavid van Moolenbroek 				  (long int)sa->sa_family, name);
478*83ee113eSDavid van Moolenbroek 	}
479*83ee113eSDavid van Moolenbroek 
480*83ee113eSDavid van Moolenbroek 	close(sock);
481*83ee113eSDavid van Moolenbroek }
482*83ee113eSDavid van Moolenbroek #endif
483