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