3 Linux packet filter code, contributed by Brian Murrel at Interlinx
4 Support Services in Vancouver, B.C. */
7 * Copyright (c) 1996-1999 Internet Software Consortium.
8 * Use is subject to license terms which appear in the file named
9 * ISC-LICENSE that should have accompanied this file when you
10 * received it. If a file named ISC-LICENSE did not accompany this
11 * file, or you are not sure the one you have is correct, you may
12 * obtain an applicable copy of the license at:
14 * http://www.isc.org/isc-license-1.0.html.
16 * This file is part of the ISC DHCP distribution. The documentation
17 * associated with this file is listed in the file DOCUMENTATION,
18 * included in the top-level directory of this release.
20 * Support and other services are available for ISC products - see
21 * http://www.isc.org for more information.
25 static char copyright
[] =
26 "$Id: lpf.c,v 1.22 2000/03/06 19:39:53 mellon Exp $ Copyright (c) 1995, 1996, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
30 #if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE)
31 #include <sys/ioctl.h>
34 #include <asm/types.h>
35 #include <linux/filter.h>
36 #include <linux/if_ether.h>
37 #include <netinet/in_systm.h>
38 #include "includes/netinet/ip.h"
39 #include "includes/netinet/udp.h"
40 #include "includes/netinet/if_ether.h"
42 /* Reinitializes the specified interface after an address change. This
43 is not required for packet-filter APIs. */
46 void if_reinitialize_send (info
)
47 struct interface_info
*info
;
52 #ifdef USE_LPF_RECEIVE
53 void if_reinitialize_receive (info
)
54 struct interface_info
*info
;
59 /* Called by get_interface_list for each interface that's discovered.
60 Opens a packet filter for each interface and adds it to the select
63 int if_register_lpf (info
)
64 struct interface_info
*info
;
71 /* Make an LPF socket. */
72 if ((sock
= socket(PF_PACKET
, SOCK_PACKET
, htons(ETH_P_ALL
))) < 0) {
73 if (errno
== ENOPROTOOPT
|| errno
== EPROTONOSUPPORT
||
74 errno
== ESOCKTNOSUPPORT
|| errno
== EPFNOSUPPORT
||
75 errno
== EAFNOSUPPORT
|| errno
== EINVAL
)
76 log_fatal ("socket: %m - make sure %s %s %s!",
77 "CONFIG_PACKET (Packet socket)"
78 "and CONFIG_FILTER (Socket Filtering) are",
79 "enabled in your kernel configuration");
80 log_fatal ("Open a socket for LPF: %m");
83 /* Bind to the interface name */
84 memset (&sa
, 0, sizeof sa
);
85 sa
.sa_family
= AF_PACKET
;
86 strncpy (sa
.sa_data
, (const char *)info
-> ifp
, sizeof sa
.sa_data
);
87 if (bind (sock
, &sa
, sizeof sa
)) {
88 if (errno
== ENOPROTOOPT
|| errno
== EPROTONOSUPPORT
||
89 errno
== ESOCKTNOSUPPORT
|| errno
== EPFNOSUPPORT
||
90 errno
== EAFNOSUPPORT
|| errno
== EINVAL
)
91 log_fatal ("socket: %m - make sure %s %s %s!",
92 "CONFIG_PACKET (Packet socket)"
93 "and CONFIG_FILTER (Socket Filtering) are",
94 "enabled in your kernel configuration");
95 log_fatal ("Bind socket to interface: %m");
100 #endif /* USE_LPF_SEND || USE_LPF_RECEIVE */
103 void if_register_send (info
)
104 struct interface_info
*info
;
106 /* If we're using the lpf API for sending and receiving,
107 we don't need to register this interface twice. */
108 #ifndef USE_LPF_RECEIVE
109 info
-> wfdesc
= if_register_lpf (info
);
111 info
-> wfdesc
= info
-> rfdesc
;
113 if (!quiet_interface_discovery
)
114 log_info ("Sending on LPF/%s/%s%s%s",
116 print_hw_addr (info
-> hw_address
.hbuf
[0],
117 info
-> hw_address
.hlen
- 1,
118 &info
-> hw_address
.hbuf
[1]),
119 (info
-> shared_network
? "/" : ""),
120 (info
-> shared_network
?
121 info
-> shared_network
-> name
: ""));
124 void if_deregister_send (info
)
125 struct interface_info
*info
;
127 /* don't need to close twice if we are using lpf for sending and
129 #ifndef USE_LPF_RECEIVE
130 /* for LPF this is simple, packet filters are removed when sockets
132 close (info
-> wfdesc
);
135 if (!quiet_interface_discovery
)
136 log_info ("Disabling output on LPF/%s/%s%s%s",
138 print_hw_addr (info
-> hw_address
.hbuf
[0],
139 info
-> hw_address
.hlen
- 1,
140 &info
-> hw_address
.hbuf
[1]),
141 (info
-> shared_network
? "/" : ""),
142 (info
-> shared_network
?
143 info
-> shared_network
-> name
: ""));
145 #endif /* USE_LPF_SEND */
147 #ifdef USE_LPF_RECEIVE
148 /* Defined in bpf.c. We can't extern these in dhcpd.h without pulling
149 in bpf includes... */
150 extern struct sock_filter dhcp_bpf_filter
[];
151 extern int dhcp_bpf_filter_len
;
152 extern struct sock_filter dhcp_bpf_tr_filter
[];
153 extern int dhcp_bpf_tr_filter_len
;
155 static void lpf_gen_filter_setup (struct interface_info
*);
156 static void lpf_tr_filter_setup (struct interface_info
*);
158 void if_register_receive (info
)
159 struct interface_info
*info
;
161 /* Open a LPF device and hang it on this interface... */
162 info
-> rfdesc
= if_register_lpf (info
);
164 if (info
-> hw_address
.hbuf
[0] == HTYPE_IEEE802
)
165 lpf_tr_filter_setup (info
);
167 lpf_gen_filter_setup (info
);
169 if (!quiet_interface_discovery
)
170 log_info ("Listening on LPF/%s/%s%s%s",
172 print_hw_addr (info
-> hw_address
.hbuf
[0],
173 info
-> hw_address
.hlen
- 1,
174 &info
-> hw_address
.hbuf
[1]),
175 (info
-> shared_network
? "/" : ""),
176 (info
-> shared_network
?
177 info
-> shared_network
-> name
: ""));
180 void if_deregister_receive (info
)
181 struct interface_info
*info
;
183 /* for LPF this is simple, packet filters are removed when sockets
185 close (info
-> rfdesc
);
187 if (!quiet_interface_discovery
)
188 log_info ("Disabling input on LPF/%s/%s%s%s",
190 print_hw_addr (info
-> hw_address
.hbuf
[0],
191 info
-> hw_address
.hlen
- 1,
192 &info
-> hw_address
.hbuf
[1]),
193 (info
-> shared_network
? "/" : ""),
194 (info
-> shared_network
?
195 info
-> shared_network
-> name
: ""));
198 static void lpf_gen_filter_setup (info
)
199 struct interface_info
*info
;
203 /* Set up the bpf filter program structure. This is defined in
205 p
.len
= dhcp_bpf_filter_len
;
206 p
.filter
= dhcp_bpf_filter
;
208 /* Patch the server port into the LPF program...
209 XXX changes to filter program may require changes
210 to the insn number(s) used below! XXX */
211 dhcp_bpf_filter
[8].k
= ntohs (local_port
);
213 if (setsockopt (info
-> rfdesc
, SOL_SOCKET
, SO_ATTACH_FILTER
, &p
,
215 if (errno
== ENOPROTOOPT
|| errno
== EPROTONOSUPPORT
||
216 errno
== ESOCKTNOSUPPORT
|| errno
== EPFNOSUPPORT
||
217 errno
== EAFNOSUPPORT
)
218 log_fatal ("socket: %m - make sure %s %s %s!",
219 "CONFIG_PACKET (Packet socket)"
220 "and CONFIG_FILTER (Socket Filtering) are",
221 "enabled in your kernel configuration");
222 log_fatal ("Can't install packet filter program: %m");
226 static void lpf_tr_filter_setup (info
)
227 struct interface_info
*info
;
231 /* Set up the bpf filter program structure. This is defined in
233 p
.len
= dhcp_bpf_tr_filter_len
;
234 p
.filter
= dhcp_bpf_tr_filter
;
236 /* Patch the server port into the LPF program...
237 XXX changes to filter program may require changes
238 XXX to the insn number(s) used below!
239 XXX Token ring filter is null - when/if we have a filter
240 XXX that's not, we'll need this code.
241 XXX dhcp_bpf_filter [?].k = ntohs (local_port); */
243 if (setsockopt (info
-> rfdesc
, SOL_SOCKET
, SO_ATTACH_FILTER
, &p
,
245 if (errno
== ENOPROTOOPT
|| errno
== EPROTONOSUPPORT
||
246 errno
== ESOCKTNOSUPPORT
|| errno
== EPFNOSUPPORT
||
247 errno
== EAFNOSUPPORT
)
248 log_fatal ("socket: %m - make sure %s %s %s!",
249 "CONFIG_PACKET (Packet socket)"
250 "and CONFIG_FILTER (Socket Filtering) are",
251 "enabled in your kernel configuration");
252 log_fatal ("Can't install packet filter program: %m");
255 #endif /* USE_LPF_RECEIVE */
258 ssize_t
send_packet (interface
, packet
, raw
, len
, from
, to
, hto
)
259 struct interface_info
*interface
;
260 struct packet
*packet
;
261 struct dhcp_packet
*raw
;
264 struct sockaddr_in
*to
;
265 struct hardware
*hto
;
268 unsigned char buf
[1500];
272 if (!strcmp (interface
-> name
, "fallback"))
273 return send_fallback (interface
, packet
, raw
,
276 /* Assemble the headers... */
277 assemble_hw_header (interface
, buf
, &bufp
, hto
);
278 assemble_udp_ip_header (interface
, buf
, &bufp
, from
.s_addr
,
279 to
-> sin_addr
.s_addr
, to
-> sin_port
,
280 (unsigned char *)raw
, len
);
281 memcpy (buf
+ bufp
, raw
, len
);
283 /* For some reason, SOCK_PACKET sockets can't be connected,
284 so we have to do a sentdo every time. */
285 memset (&sa
, 0, sizeof sa
);
286 sa
.sa_family
= AF_PACKET
;
288 (const char *)interface
-> ifp
, sizeof sa
.sa_data
);
290 result
= sendto (interface
-> wfdesc
, buf
, bufp
+ len
, 0,
293 log_error ("send_packet: %m");
296 #endif /* USE_LPF_SEND */
298 #ifdef USE_LPF_RECEIVE
299 ssize_t
receive_packet (interface
, buf
, len
, from
, hfrom
)
300 struct interface_info
*interface
;
303 struct sockaddr_in
*from
;
304 struct hardware
*hfrom
;
309 unsigned char ibuf
[1500];
312 length
= read (interface
-> rfdesc
, ibuf
, sizeof ibuf
);
317 /* Decode the physical header... */
318 offset
= decode_hw_header (interface
, ibuf
, bufix
, hfrom
);
320 /* If a physical layer checksum failed (dunno of any
321 physical layer that supports this, but WTH), skip this
330 /* Decode the IP and UDP headers... */
331 offset
= decode_udp_ip_header (interface
, ibuf
, bufix
,
332 from
, (unsigned char *)0, length
);
334 /* If the IP or UDP checksum was bad, skip the packet... */
341 /* Copy out the data in the packet... */
342 memcpy (buf
, &ibuf
[bufix
], length
);
346 int can_unicast_without_arp (ip
)
347 struct interface_info
*ip
;
352 int can_receive_unicast_unconfigured (ip
)
353 struct interface_info
*ip
;
358 void maybe_setup_fallback ()
361 struct interface_info
*fbi
;
362 fbi
= setup_fallback ();
364 if_register_fallback (fbi
);
366 fbi
-> type
= dhcp_type_interface
;
367 status
= omapi_register_io_object ((omapi_object_t
*)fbi
,
369 fallback_discard
, 0, 0);
370 if (status
!= ISC_R_SUCCESS
)
371 log_fatal ("Can't register I/O handle for %s: %s",
372 fbi
-> name
, isc_result_totext (status
));