4bf24c8243
- Had to rename the -T option to -timeout as ISC is now using -T - Allow package rebuilders to easily enable DHCPv6 support with: rpmbuild --with DHCPv6 dhcp.spec Note that Fedora is still using the 'dhcpv6' package, but some users may want to experiment with the ISC DHCPv6 implementation locally.
246 lines
8.3 KiB
Diff
246 lines
8.3 KiB
Diff
diff -up dhcp-4.1.0/common/bpf.c.xen dhcp-4.1.0/common/bpf.c
|
|
--- dhcp-4.1.0/common/bpf.c.xen 2007-08-22 23:49:51.000000000 -1000
|
|
+++ dhcp-4.1.0/common/bpf.c 2009-01-06 10:41:32.000000000 -1000
|
|
@@ -482,7 +482,7 @@ ssize_t receive_packet (interface, buf,
|
|
offset = decode_udp_ip_header (interface,
|
|
interface -> rbuf,
|
|
interface -> rbuf_offset,
|
|
- from, hdr.bh_caplen, &paylen);
|
|
+ from, hdr.bh_caplen, &paylen, 0);
|
|
|
|
/* If the IP or UDP checksum was bad, skip the packet... */
|
|
if (offset < 0) {
|
|
diff -up dhcp-4.1.0/common/dlpi.c.xen dhcp-4.1.0/common/dlpi.c
|
|
--- dhcp-4.1.0/common/dlpi.c.xen 2008-02-29 13:57:56.000000000 -1000
|
|
+++ dhcp-4.1.0/common/dlpi.c 2009-01-06 10:41:32.000000000 -1000
|
|
@@ -689,7 +689,7 @@ ssize_t receive_packet (interface, buf,
|
|
length -= offset;
|
|
#endif
|
|
offset = decode_udp_ip_header (interface, dbuf, bufix,
|
|
- from, length, &paylen);
|
|
+ from, length, &paylen, 0);
|
|
|
|
/* If the IP or UDP checksum was bad, skip the packet... */
|
|
if (offset < 0) {
|
|
diff -up dhcp-4.1.0/common/lpf.c.xen dhcp-4.1.0/common/lpf.c
|
|
--- dhcp-4.1.0/common/lpf.c.xen 2009-01-06 10:41:31.000000000 -1000
|
|
+++ dhcp-4.1.0/common/lpf.c 2009-01-06 10:41:32.000000000 -1000
|
|
@@ -29,18 +29,33 @@
|
|
#include "dhcpd.h"
|
|
#if defined (USE_LPF_SEND) || defined (USE_LPF_RECEIVE)
|
|
#include <sys/ioctl.h>
|
|
+#include <sys/socket.h>
|
|
#include <sys/uio.h>
|
|
#include <errno.h>
|
|
|
|
#include <asm/types.h>
|
|
#include <linux/filter.h>
|
|
#include <linux/if_ether.h>
|
|
+#include <linux/if_packet.h>
|
|
#include <netinet/in_systm.h>
|
|
#include "includes/netinet/ip.h"
|
|
#include "includes/netinet/udp.h"
|
|
#include "includes/netinet/if_ether.h"
|
|
#include <net/if.h>
|
|
|
|
+#ifndef PACKET_AUXDATA
|
|
+#define PACKET_AUXDATA 8
|
|
+
|
|
+struct tpacket_auxdata
|
|
+{
|
|
+ __u32 tp_status;
|
|
+ __u32 tp_len;
|
|
+ __u32 tp_snaplen;
|
|
+ __u16 tp_mac;
|
|
+ __u16 tp_net;
|
|
+};
|
|
+#endif
|
|
+
|
|
/* Reinitializes the specified interface after an address change. This
|
|
is not required for packet-filter APIs. */
|
|
|
|
@@ -66,10 +81,14 @@ int if_register_lpf (info)
|
|
struct interface_info *info;
|
|
{
|
|
int sock;
|
|
- struct sockaddr sa;
|
|
+ union {
|
|
+ struct sockaddr_ll ll;
|
|
+ struct sockaddr common;
|
|
+ } sa;
|
|
+ struct ifreq ifr;
|
|
|
|
/* Make an LPF socket. */
|
|
- if ((sock = socket(PF_PACKET, SOCK_PACKET,
|
|
+ if ((sock = socket(PF_PACKET, SOCK_RAW,
|
|
htons((short)ETH_P_ALL))) < 0) {
|
|
if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
|
|
errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
|
|
@@ -84,11 +103,16 @@ int if_register_lpf (info)
|
|
log_fatal ("Open a socket for LPF: %m");
|
|
}
|
|
|
|
+ memset (&ifr, 0, sizeof ifr);
|
|
+ strncpy (ifr.ifr_name, (const char *)info -> ifp, sizeof ifr.ifr_name);
|
|
+ if (ioctl (sock, SIOCGIFINDEX, &ifr))
|
|
+ log_fatal ("Failed to get interface index: %m");
|
|
+
|
|
/* Bind to the interface name */
|
|
memset (&sa, 0, sizeof sa);
|
|
- sa.sa_family = AF_PACKET;
|
|
- strncpy (sa.sa_data, (const char *)info -> ifp, sizeof sa.sa_data);
|
|
- if (bind (sock, &sa, sizeof sa)) {
|
|
+ sa.ll.sll_family = AF_PACKET;
|
|
+ sa.ll.sll_ifindex = ifr.ifr_ifindex;
|
|
+ if (bind (sock, &sa.common, sizeof sa)) {
|
|
if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT ||
|
|
errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT ||
|
|
errno == EAFNOSUPPORT || errno == EINVAL) {
|
|
@@ -170,9 +194,18 @@ static void lpf_gen_filter_setup (struct
|
|
void if_register_receive (info)
|
|
struct interface_info *info;
|
|
{
|
|
+ int val;
|
|
+
|
|
/* Open a LPF device and hang it on this interface... */
|
|
info -> rfdesc = if_register_lpf (info);
|
|
|
|
+ val = 1;
|
|
+ if (setsockopt (info -> rfdesc, SOL_PACKET, PACKET_AUXDATA, &val,
|
|
+ sizeof val) < 0) {
|
|
+ if (errno != ENOPROTOOPT)
|
|
+ log_fatal ("Failed to set auxiliary packet data: %m");
|
|
+ }
|
|
+
|
|
#if defined (HAVE_TR_SUPPORT)
|
|
if (info -> hw_address.hbuf [0] == HTYPE_IEEE802)
|
|
lpf_tr_filter_setup (info);
|
|
@@ -293,7 +326,6 @@ ssize_t send_packet (interface, packet,
|
|
double hh [16];
|
|
double ih [1536 / sizeof (double)];
|
|
unsigned char *buf = (unsigned char *)ih;
|
|
- struct sockaddr sa;
|
|
int result;
|
|
int fudge;
|
|
|
|
@@ -311,15 +343,7 @@ ssize_t send_packet (interface, packet,
|
|
(unsigned char *)raw, len);
|
|
memcpy (buf + ibufp, raw, len);
|
|
|
|
- /* For some reason, SOCK_PACKET sockets can't be connected,
|
|
- so we have to do a sentdo every time. */
|
|
- memset (&sa, 0, sizeof sa);
|
|
- sa.sa_family = AF_PACKET;
|
|
- strncpy (sa.sa_data,
|
|
- (const char *)interface -> ifp, sizeof sa.sa_data);
|
|
-
|
|
- result = sendto (interface -> wfdesc,
|
|
- buf + fudge, ibufp + len - fudge, 0, &sa, sizeof sa);
|
|
+ result = write (interface -> wfdesc, buf + fudge, ibufp + len - fudge);
|
|
if (result < 0)
|
|
log_error ("send_packet: %m");
|
|
return result;
|
|
@@ -336,14 +360,35 @@ ssize_t receive_packet (interface, buf,
|
|
{
|
|
int length = 0;
|
|
int offset = 0;
|
|
+ int nocsum = 0;
|
|
unsigned char ibuf [1536];
|
|
unsigned bufix = 0;
|
|
unsigned paylen;
|
|
+ unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
|
|
+ struct iovec iov = {
|
|
+ .iov_base = ibuf,
|
|
+ .iov_len = sizeof ibuf,
|
|
+ };
|
|
+ struct msghdr msg = {
|
|
+ .msg_iov = &iov,
|
|
+ .msg_iovlen = 1,
|
|
+ .msg_control = cmsgbuf,
|
|
+ .msg_controllen = sizeof(cmsgbuf),
|
|
+ };
|
|
+ struct cmsghdr *cmsg;
|
|
|
|
- length = read (interface -> rfdesc, ibuf, sizeof ibuf);
|
|
+ length = recvmsg (interface -> rfdesc, &msg, 0);
|
|
if (length <= 0)
|
|
return length;
|
|
|
|
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
|
|
+ if (cmsg->cmsg_level == SOL_PACKET &&
|
|
+ cmsg->cmsg_type == PACKET_AUXDATA) {
|
|
+ struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg);
|
|
+ nocsum = aux->tp_status & TP_STATUS_CSUMNOTREADY;
|
|
+ }
|
|
+ }
|
|
+
|
|
bufix = 0;
|
|
/* Decode the physical header... */
|
|
offset = decode_hw_header (interface, ibuf, bufix, hfrom);
|
|
@@ -360,7 +405,7 @@ ssize_t receive_packet (interface, buf,
|
|
|
|
/* Decode the IP and UDP headers... */
|
|
offset = decode_udp_ip_header (interface, ibuf, bufix, from,
|
|
- (unsigned)length, &paylen);
|
|
+ (unsigned)length, &paylen, nocsum);
|
|
|
|
/* If the IP or UDP checksum was bad, skip the packet... */
|
|
if (offset < 0)
|
|
diff -up dhcp-4.1.0/common/nit.c.xen dhcp-4.1.0/common/nit.c
|
|
--- dhcp-4.1.0/common/nit.c.xen 2007-09-05 07:32:10.000000000 -1000
|
|
+++ dhcp-4.1.0/common/nit.c 2009-01-06 10:41:32.000000000 -1000
|
|
@@ -366,7 +366,7 @@ ssize_t receive_packet (interface, buf,
|
|
|
|
/* Decode the IP and UDP headers... */
|
|
offset = decode_udp_ip_header (interface, ibuf, bufix,
|
|
- from, length, &paylen);
|
|
+ from, length, &paylen, 0);
|
|
|
|
/* If the IP or UDP checksum was bad, skip the packet... */
|
|
if (offset < 0)
|
|
diff -up dhcp-4.1.0/common/packet.c.xen dhcp-4.1.0/common/packet.c
|
|
--- dhcp-4.1.0/common/packet.c.xen 2009-01-06 10:41:31.000000000 -1000
|
|
+++ dhcp-4.1.0/common/packet.c 2009-01-06 10:41:32.000000000 -1000
|
|
@@ -210,7 +210,7 @@ ssize_t
|
|
decode_udp_ip_header(struct interface_info *interface,
|
|
unsigned char *buf, unsigned bufix,
|
|
struct sockaddr_in *from, unsigned buflen,
|
|
- unsigned *rbuflen)
|
|
+ unsigned *rbuflen, int nocsum)
|
|
{
|
|
unsigned char *data;
|
|
struct ip ip;
|
|
@@ -321,7 +321,7 @@ decode_udp_ip_header(struct interface_in
|
|
8, IPPROTO_UDP + ulen))));
|
|
|
|
udp_packets_seen++;
|
|
- if (usum && usum != sum) {
|
|
+ if (!nocsum && usum && usum != sum) {
|
|
udp_packets_bad_checksum++;
|
|
if (udp_packets_seen > 4 &&
|
|
(udp_packets_seen / udp_packets_bad_checksum) < 2) {
|
|
diff -up dhcp-4.1.0/common/upf.c.xen dhcp-4.1.0/common/upf.c
|
|
--- dhcp-4.1.0/common/upf.c.xen 2007-07-12 20:43:42.000000000 -1000
|
|
+++ dhcp-4.1.0/common/upf.c 2009-01-06 10:41:32.000000000 -1000
|
|
@@ -317,7 +317,7 @@ ssize_t receive_packet (interface, buf,
|
|
|
|
/* Decode the IP and UDP headers... */
|
|
offset = decode_udp_ip_header (interface, ibuf, bufix,
|
|
- from, length, &paylen);
|
|
+ from, length, &paylen, 0);
|
|
|
|
/* If the IP or UDP checksum was bad, skip the packet... */
|
|
if (offset < 0)
|
|
diff -up dhcp-4.1.0/includes/dhcpd.h.xen dhcp-4.1.0/includes/dhcpd.h
|
|
--- dhcp-4.1.0/includes/dhcpd.h.xen 2009-01-06 10:41:32.000000000 -1000
|
|
+++ dhcp-4.1.0/includes/dhcpd.h 2009-01-06 10:41:32.000000000 -1000
|
|
@@ -2640,7 +2640,7 @@ ssize_t decode_hw_header PROTO ((struct
|
|
unsigned, struct hardware *));
|
|
ssize_t decode_udp_ip_header PROTO ((struct interface_info *, unsigned char *,
|
|
unsigned, struct sockaddr_in *,
|
|
- unsigned, unsigned *));
|
|
+ unsigned, unsigned *, int));
|
|
|
|
/* ethernet.c */
|
|
void assemble_ethernet_header PROTO ((struct interface_info *, unsigned char *,
|