Bjørn Mork <[email protected]> writes: > And DHCP support is even more complex. DHCP clients must know how to > handle (add/remove/parse) L2 headers. Or lack of headers in this case. > I don't know of any client supporting that at the moment. But it should > be easier than any other L2 interface type support, since all you need > to do is drop the L2 header adding/removing/parsing.
I made an attempt to see just how hard it is. The attached patch is a bit rough, and doesn't include support for anything but Linux, but it sort of works: nemi:/tmp# ./dhclient -d -4 wwan0 Internet Systems Consortium DHCP Client 4.3.3 Copyright 2004-2015 Internet Systems Consortium. All rights reserved. For info, please visit https://www.isc.org/software/dhcp/ Listening on LPF/wwan0/ Sending on LPF/wwan0/ Sending on Socket/fallback DHCPDISCOVER on wwan0 to 255.255.255.255 port 67 interval 3 Attempt to assemble hw header for pure IP Attempt to decode hw header for Pure IP Received DHCPv4 packet without client-id option and empty hlen field. DHCPREQUEST on wwan0 to 255.255.255.255 port 67 Attempt to assemble hw header for pure IP DHCPOFFER from 10.140.149.145 Attempt to decode hw header for Pure IP Received DHCPv4 packet without client-id option and empty hlen field. DHCPACK from 10.140.149.145 RTNETLINK answers: File exists bound to 10.140.149.146 -- renewal in 3595 seconds. Bjørn
>From ba61b258dd373b4395c08a4fb89a6542d1bec9d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <[email protected]> Date: Mon, 21 Dec 2015 01:28:31 +0100 Subject: [PATCH] dhclient: raw IP support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bjørn Mork <[email protected]> --- common/bpf.c | 27 +++++++++++++++++++++++++++ common/lpf.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ common/packet.c | 6 ++++++ includes/dhcp.h | 1 + 4 files changed, 78 insertions(+) diff --git a/common/bpf.c b/common/bpf.c index 39d4f45..27c025d 100644 --- a/common/bpf.c +++ b/common/bpf.c @@ -204,6 +204,33 @@ struct bpf_insn *bpf_fddi_filter; #endif int dhcp_bpf_filter_len = sizeof dhcp_bpf_filter / sizeof (struct bpf_insn); + +struct bpf_insn dhcp_bpf_ip_filter [] = { + /* Make sure it's a UDP packet... */ + BPF_STMT (BPF_LD + BPF_B + BPF_ABS, 9), + BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6), + + /* Make sure this isn't a fragment... */ + BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 6), + BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0), + + /* Get the IP header length... */ + BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 0), + + /* Make sure it's to the right port... */ + BPF_STMT (BPF_LD + BPF_H + BPF_IND, 2), + BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 37, 0, 1), /* patch */ + + /* If we passed all the tests, ask for the whole packet. */ + BPF_STMT(BPF_RET+BPF_K, (u_int)-1), + + /* Otherwise, drop it. */ + BPF_STMT(BPF_RET+BPF_K, 0), +}; + +int dhcp_bpf_ip_filter_len = sizeof dhcp_bpf_ip_filter / sizeof (struct bpf_insn); + + #if defined (HAVE_TR_SUPPORT) struct bpf_insn dhcp_bpf_tr_filter [] = { /* accept all token ring packets due to variable length header */ diff --git a/common/lpf.c b/common/lpf.c index ee3820b..22ad61b 100644 --- a/common/lpf.c +++ b/common/lpf.c @@ -179,6 +179,9 @@ void if_deregister_send (info) extern struct sock_filter dhcp_bpf_filter []; extern int dhcp_bpf_filter_len; +extern struct sock_filter dhcp_bpf_ip_filter []; +extern int dhcp_bpf_ip_filter_len; + #if defined (HAVE_TR_SUPPORT) extern struct sock_filter dhcp_bpf_tr_filter []; extern int dhcp_bpf_tr_filter_len; @@ -186,6 +189,7 @@ static void lpf_tr_filter_setup (struct interface_info *); #endif static void lpf_gen_filter_setup (struct interface_info *); +static void lpf_pureip_filter_setup (struct interface_info *); void if_register_receive (info) struct interface_info *info; @@ -212,6 +216,9 @@ void if_register_receive (info) lpf_tr_filter_setup (info); else #endif + if (info -> hw_address.hbuf [0] == HTYPE_PUREIP) + lpf_pureip_filter_setup (info); + else lpf_gen_filter_setup (info); if (!quiet_interface_discovery) @@ -276,6 +283,39 @@ static void lpf_gen_filter_setup (info) } } +static void lpf_pureip_filter_setup (info) + struct interface_info *info; +{ + struct sock_fprog p; + + memset(&p, 0, sizeof(p)); + + /* Set up the bpf filter program structure. This is defined in + bpf.c */ + p.len = dhcp_bpf_ip_filter_len; + p.filter = dhcp_bpf_ip_filter; + + /* Patch the server port into the LPF program... + XXX changes to filter program may require changes + to the insn number(s) used below! XXX */ + dhcp_bpf_ip_filter [6].k = ntohs ((short)local_port); + + if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p, + sizeof p) < 0) { + if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT || + errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT || + errno == EAFNOSUPPORT) { + log_error ("socket: %m - make sure"); + log_error ("CONFIG_PACKET (Packet socket) %s", + "and CONFIG_FILTER"); + log_error ("(Socket Filtering) are enabled %s", + "in your kernel"); + log_fatal ("configuration!"); + } + log_fatal ("Can't install packet filter program: %m"); + } +} + #if defined (HAVE_TR_SUPPORT) static void lpf_tr_filter_setup (info) struct interface_info *info; @@ -548,6 +588,10 @@ get_hw_addr(const char *name, struct hardware *hw) { hw->hbuf[0] = HTYPE_FDDI; memcpy(&hw->hbuf[1], sa->sa_data, 6); break; + case ARPHRD_NONE: + hw->hlen = 1; + hw->hbuf[0] = HTYPE_PUREIP; + break; default: log_fatal("Unsupported device type %ld for \"%s\"", (long int)sa->sa_family, name); diff --git a/common/packet.c b/common/packet.c index b530432..570e2a5 100644 --- a/common/packet.c +++ b/common/packet.c @@ -120,6 +120,9 @@ void assemble_hw_header (interface, buf, bufix, to) case HTYPE_INFINIBAND: log_error("Attempt to assemble hw header for infiniband"); break; + case HTYPE_PUREIP: + log_error("Attempt to assemble hw header for pure IP"); + break; case HTYPE_ETHER: default: assemble_ethernet_header(interface, buf, bufix, to); @@ -214,6 +217,9 @@ ssize_t decode_hw_header (interface, buf, bufix, from) case HTYPE_INFINIBAND: log_error("Attempt to decode hw header for infiniband"); return (0); + case HTYPE_PUREIP: + log_error("Attempt to decode hw header for Pure IP"); + return (0); case HTYPE_ETHER: default: return (decode_ethernet_header(interface, buf, bufix, from)); diff --git a/includes/dhcp.h b/includes/dhcp.h index f916468..72593d8 100644 --- a/includes/dhcp.h +++ b/includes/dhcp.h @@ -77,6 +77,7 @@ struct dhcp_packet { #define HTYPE_IEEE802 6 /* IEEE 802.2 Token Ring... */ #define HTYPE_FDDI 8 /* FDDI... */ #define HTYPE_INFINIBAND 32 /* IP over Infiniband */ +#define HTYPE_PUREIP 35 /* Pure IP */ #define HTYPE_IPMP 255 /* IPMP - random hw address - there * is no standard for this so we * just steal a type */ -- 2.1.4
_______________________________________________ networkmanager-list mailing list [email protected] https://mail.gnome.org/mailman/listinfo/networkmanager-list
