mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-22 09:57:20 +00:00
Merged rt44535 (relay port)
This commit is contained in:
parent
0d6d300fec
commit
563f0b8aef
13
RELNOTES
13
RELNOTES
@ -312,6 +312,19 @@ dhcp-users@lists.isc.org.
|
||||
when building with --enable-use-sockets and --enable-ipv4-pktinfo.
|
||||
[ISC-Bugs #36118]
|
||||
|
||||
(to be finalized before code freeze next year)
|
||||
- Added experimental support for relay port (draft-ietf-dhc-relay-port-10.txt)
|
||||
feature for DHCPv4, DHCPv6 and DHCPv4-over-DHCPv6. As the code points
|
||||
were not yet assigned by IANA temporary (next free) values are used.
|
||||
Relay port had be enabled at compile time via --enable-relay-port and
|
||||
is fully backward compatible, i.e. works with previous implementations
|
||||
of servers and relays, of course in this case using legacy ports.
|
||||
A new --rp <relay-port> command line option specifies to dhcrelay
|
||||
an alternate source port for upstream (i.e. toward the server) messages.
|
||||
(update this)
|
||||
Thanks to Naiming Shen and Enke Chen for submitting patches.
|
||||
[ISC-Bugs #44535]
|
||||
|
||||
Changes since 4.3.6 (Bugs):
|
||||
|
||||
- Corrected an issue where the server would return a client's previously
|
||||
|
57
common/bpf.c
57
common/bpf.c
@ -192,12 +192,51 @@ struct bpf_insn dhcp_bpf_filter [] = {
|
||||
BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), /* patch */
|
||||
|
||||
/* If we passed all the tests, ask for the whole packet. */
|
||||
BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
|
||||
BPF_STMT (BPF_RET + BPF_K, (u_int)-1),
|
||||
|
||||
/* Otherwise, drop it. */
|
||||
BPF_STMT(BPF_RET+BPF_K, 0),
|
||||
BPF_STMT (BPF_RET + BPF_K, 0),
|
||||
};
|
||||
|
||||
#if defined(RELAY_PORT)
|
||||
/*
|
||||
* For relay port extension
|
||||
*/
|
||||
struct bpf_insn dhcp_bpf_relay_filter [] = {
|
||||
/* Make sure this is an IP packet... */
|
||||
BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 12),
|
||||
BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 10),
|
||||
|
||||
/* Make sure it's a UDP packet... */
|
||||
BPF_STMT (BPF_LD + BPF_B + BPF_ABS, 23),
|
||||
BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 8),
|
||||
|
||||
/* Make sure this isn't a fragment... */
|
||||
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20),
|
||||
BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 6, 0),
|
||||
|
||||
/* Get the IP header length... */
|
||||
BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 14),
|
||||
|
||||
/* Make sure it's to the right port... */
|
||||
BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16),
|
||||
BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 2, 0), /* patch */
|
||||
|
||||
/* relay can have an alternative port... */
|
||||
BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16),
|
||||
BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 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_relay_filter_len =
|
||||
sizeof dhcp_bpf_relay_filter / sizeof (struct bpf_insn);
|
||||
#endif
|
||||
|
||||
#if defined (DEC_FDDI)
|
||||
struct bpf_insn *bpf_fddi_filter = NULL;
|
||||
#endif
|
||||
@ -309,7 +348,19 @@ void if_register_receive (info)
|
||||
/* Patch the server port into the BPF program...
|
||||
XXX changes to filter program may require changes
|
||||
to the insn number(s) used below! XXX */
|
||||
dhcp_bpf_filter [8].k = ntohs (local_port);
|
||||
#if defined(RELAY_PORT)
|
||||
if (relay_port) {
|
||||
/*
|
||||
* If user defined relay UDP port, we need to filter
|
||||
* also on the user UDP port.
|
||||
*/
|
||||
p.bf_len = dhcp_bpf_relay_filter_len;
|
||||
p.bf_insns = dhcp_bpf_relay_filter;
|
||||
|
||||
dhcp_bpf_relay_filter [10].k = ntohs (relay_port);
|
||||
}
|
||||
#endif
|
||||
p.bf_insns [8].k = ntohs (local_port);
|
||||
|
||||
if (ioctl (info -> rfdesc, BIOCSETF, &p) < 0)
|
||||
log_fatal ("Can't install packet filter program: %m");
|
||||
|
@ -44,6 +44,7 @@ int interfaces_invalidated;
|
||||
int quiet_interface_discovery;
|
||||
u_int16_t local_port;
|
||||
u_int16_t remote_port;
|
||||
u_int16_t relay_port = 0;
|
||||
int dhcpv4_over_dhcpv6 = 0;
|
||||
int (*dhcp_interface_setup_hook) (struct interface_info *, struct iaddr *);
|
||||
int (*dhcp_interface_discovery_hook) (struct interface_info *);
|
||||
@ -581,6 +582,10 @@ discover_interfaces(int state) {
|
||||
int ir;
|
||||
isc_result_t status;
|
||||
int wifcount = 0;
|
||||
#ifdef RELAY_PORT
|
||||
int updone = 0;
|
||||
int downdone = 0;
|
||||
#endif
|
||||
|
||||
static int setup_fallback = 0;
|
||||
|
||||
@ -946,9 +951,39 @@ discover_interfaces(int state) {
|
||||
switch (local_family) {
|
||||
#ifdef DHCPv6
|
||||
case AF_INET6:
|
||||
#ifdef RELAY_PORT
|
||||
#define UPSTREAM(ifp) \
|
||||
((ifp->flags & INTERFACE_STREAMS) == INTERFACE_UPSTREAM)
|
||||
#define DOWNSTREAM(ifp) \
|
||||
((ifp->flags & INTERFACE_STREAMS) == INTERFACE_DOWNSTREAM)
|
||||
|
||||
if (relay_port) {
|
||||
/*
|
||||
* The normal IPv6 relay only needs one
|
||||
* socket as long as we find an interface.
|
||||
* When user relay port is defined, and we
|
||||
* have two different UDP ports. One to
|
||||
* receive from DHCP client with port 547,
|
||||
* and the other is user defined for sending
|
||||
* to the server or upstream relay agent.
|
||||
* Thus we need to register sockets for one
|
||||
* upstream and one downstream interfaces.
|
||||
*/
|
||||
if (updone && UPSTREAM(tmp))
|
||||
continue;
|
||||
if (downdone && DOWNSTREAM(tmp))
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
status = omapi_register_io_object((omapi_object_t *)tmp,
|
||||
if_readsocket,
|
||||
0, got_one_v6, 0, 0);
|
||||
#ifdef RELAY_PORT
|
||||
if (UPSTREAM(tmp))
|
||||
updone++;
|
||||
else
|
||||
downdone++;
|
||||
#endif
|
||||
break;
|
||||
#endif /* DHCPv6 */
|
||||
case AF_INET:
|
||||
@ -970,8 +1005,12 @@ discover_interfaces(int state) {
|
||||
* dynamically adding and removing interfaces, but
|
||||
* we're well beyond that point in terms of mess.
|
||||
*/
|
||||
if (((state == DISCOVER_SERVER) || (state == DISCOVER_RELAY)) &&
|
||||
(local_family == AF_INET6))
|
||||
if (((state == DISCOVER_SERVER) || (state == DISCOVER_RELAY))
|
||||
&& (local_family == AF_INET6)
|
||||
#if defined(RELAY_PORT)
|
||||
&& ((relay_port == 0) || (updone && downdone))
|
||||
#endif
|
||||
)
|
||||
break;
|
||||
#endif
|
||||
} /* for (tmp = interfaces; ... */
|
||||
|
@ -409,6 +409,10 @@ void if_deregister_send (info)
|
||||
XXX Changes to the filter program may require changes to the constant
|
||||
offsets used in if_register_send to patch the NIT program! XXX */
|
||||
|
||||
#if defined(RELAY_PORT)
|
||||
#error "Relay port is not yet supported for DLPI"
|
||||
#endif
|
||||
|
||||
void if_register_receive (info)
|
||||
struct interface_info *info;
|
||||
{
|
||||
|
19
common/lpf.c
19
common/lpf.c
@ -177,6 +177,11 @@ void if_deregister_send (info)
|
||||
extern struct sock_filter dhcp_bpf_filter [];
|
||||
extern int dhcp_bpf_filter_len;
|
||||
|
||||
#if defined(RELAY_PORT)
|
||||
extern struct sock_filter dhcp_bpf_relay_filter [];
|
||||
extern int dhcp_bpf_relay_filter_len;
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_TR_SUPPORT)
|
||||
extern struct sock_filter dhcp_bpf_tr_filter [];
|
||||
extern int dhcp_bpf_tr_filter_len;
|
||||
@ -256,7 +261,19 @@ static void lpf_gen_filter_setup (info)
|
||||
/* 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_filter [8].k = ntohs ((short)local_port);
|
||||
#if defined(RELAY_PORT)
|
||||
if (relay_port) {
|
||||
/*
|
||||
* If user defined relay UDP port, we need to filter
|
||||
* also on the user UDP port.
|
||||
*/
|
||||
p.len = dhcp_bpf_relay_filter_len;
|
||||
p.filter = dhcp_bpf_relay_filter;
|
||||
|
||||
dhcp_bpf_relay_filter [10].k = ntohs (relay_port);
|
||||
}
|
||||
#endif
|
||||
dhcp_bpf_filter [8].k = ntohs (local_port);
|
||||
|
||||
if (setsockopt (info -> rfdesc, SOL_SOCKET, SO_ATTACH_FILTER, &p,
|
||||
sizeof p) < 0) {
|
||||
|
@ -172,6 +172,10 @@ void if_deregister_send (info)
|
||||
XXX Changes to the filter program may require changes to the constant
|
||||
offsets used in if_register_send to patch the NIT program! XXX */
|
||||
|
||||
#if defined(RELAY_PORT)
|
||||
#error "Relay port is not yet supported for NIT"
|
||||
#endif
|
||||
|
||||
void if_register_receive (info)
|
||||
struct interface_info *info;
|
||||
{
|
||||
|
@ -167,6 +167,12 @@ void assemble_udp_ip_header (interface, buf, bufix,
|
||||
/* Fill out the UDP header */
|
||||
udp.uh_sport = local_port; /* XXX */
|
||||
udp.uh_dport = port; /* XXX */
|
||||
#if defined(RELAY_PORT)
|
||||
/* Change to relay port defined if sending to server */
|
||||
if (relay_port && (port == htons(67))) {
|
||||
udp.uh_sport = relay_port;
|
||||
}
|
||||
#endif
|
||||
udp.uh_ulen = htons(sizeof(udp) + len);
|
||||
memset (&udp.uh_sum, 0, sizeof udp.uh_sum);
|
||||
|
||||
@ -296,7 +302,12 @@ decode_udp_ip_header(struct interface_info *interface,
|
||||
return -1;
|
||||
|
||||
/* Is it to the port we're serving? */
|
||||
#if defined(RELAY_PORT)
|
||||
if ((udp.uh_dport != local_port) &&
|
||||
((relay_port == 0) || (udp.uh_dport != relay_port)))
|
||||
#else
|
||||
if (udp.uh_dport != local_port)
|
||||
#endif
|
||||
return -1;
|
||||
#endif /* USERLAND_FILTER */
|
||||
|
||||
|
@ -55,14 +55,14 @@ void if_register_send (info)
|
||||
|
||||
/* Set up the address we're going to connect to. */
|
||||
name.sin_family = AF_INET;
|
||||
name.sin_port = local_port;
|
||||
name.sin_port = relay_port ? relay_port : local_port;
|
||||
name.sin_addr.s_addr = htonl (INADDR_BROADCAST);
|
||||
memset (name.sin_zero, 0, sizeof (name.sin_zero));
|
||||
|
||||
/* List addresses on which we're listening. */
|
||||
if (!quiet_interface_discovery)
|
||||
log_info ("Sending on %s, port %d",
|
||||
piaddr (info -> address), htons (local_port));
|
||||
piaddr (info -> address), htons (name.sin_port));
|
||||
if ((sock = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
|
||||
log_fatal ("Can't create dhcp socket: %m");
|
||||
|
||||
|
@ -65,6 +65,10 @@
|
||||
static int no_global_v6_socket = 0;
|
||||
static unsigned int global_v6_socket_references = 0;
|
||||
static int global_v6_socket = -1;
|
||||
#if defined(RELAY_PORT)
|
||||
static unsigned int relay_port_v6_socket_references = 0;
|
||||
static int relay_port_v6_socket = -1;
|
||||
#endif
|
||||
|
||||
static void if_register_multicast(struct interface_info *info);
|
||||
#endif
|
||||
@ -157,6 +161,11 @@ if_register_socket(struct interface_info *info, int family,
|
||||
addr6 = (struct sockaddr_in6 *)&name;
|
||||
addr6->sin6_family = AF_INET6;
|
||||
addr6->sin6_port = local_port;
|
||||
#if defined(RELAY_PORT)
|
||||
if (relay_port &&
|
||||
((info->flags & INTERFACE_STREAMS) == INTERFACE_UPSTREAM))
|
||||
addr6->sin6_port = relay_port;
|
||||
#endif
|
||||
/* A server feature */
|
||||
if (bind_local_address6) {
|
||||
memcpy(&addr6->sin6_addr,
|
||||
@ -187,7 +196,7 @@ if_register_socket(struct interface_info *info, int family,
|
||||
default:
|
||||
addr = (struct sockaddr_in *)&name;
|
||||
addr->sin_family = AF_INET;
|
||||
addr->sin_port = local_port;
|
||||
addr->sin_port = relay_port ? relay_port : local_port;
|
||||
memcpy(&addr->sin_addr,
|
||||
&local_address,
|
||||
sizeof(addr->sin_addr));
|
||||
@ -496,6 +505,10 @@ if_register6(struct interface_info *info, int do_multicast) {
|
||||
log_fatal("Impossible condition at %s:%d", MDL);
|
||||
}
|
||||
|
||||
#if defined(RELAY_PORT)
|
||||
if (!relay_port ||
|
||||
((info->flags & INTERFACE_STREAMS) == INTERFACE_DOWNSTREAM)) {
|
||||
#endif
|
||||
if (global_v6_socket_references == 0) {
|
||||
global_v6_socket = if_register_socket(info, AF_INET6,
|
||||
&req_multi, NULL);
|
||||
@ -527,6 +540,30 @@ if_register6(struct interface_info *info, int do_multicast) {
|
||||
info->wfdesc = global_v6_socket;
|
||||
global_v6_socket_references++;
|
||||
|
||||
#if defined(RELAY_PORT)
|
||||
} else {
|
||||
/*
|
||||
* If relay port is defined, we need to register one
|
||||
* IPv6 UPD socket to handle upstream server or relay agent
|
||||
* with a non-547 UDP local port.
|
||||
*/
|
||||
if ((relay_port_v6_socket_references == 0) &&
|
||||
((info->flags & INTERFACE_STREAMS) == INTERFACE_UPSTREAM)) {
|
||||
relay_port_v6_socket = if_register_socket(info, AF_INET6,
|
||||
&req_multi, NULL);
|
||||
if (relay_port_v6_socket < 0) {
|
||||
log_fatal("Impossible condition at %s:%d", MDL);
|
||||
} else {
|
||||
log_info("Bound to relay port *:%d",
|
||||
(int) ntohs(relay_port));
|
||||
}
|
||||
}
|
||||
info->rfdesc = relay_port_v6_socket;
|
||||
info->wfdesc = relay_port_v6_socket;
|
||||
relay_port_v6_socket_references++;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (req_multi)
|
||||
if_register_multicast(info);
|
||||
|
||||
@ -617,6 +654,16 @@ if_deregister6(struct interface_info *info) {
|
||||
global_v6_socket_references--;
|
||||
info->rfdesc = -1;
|
||||
info->wfdesc = -1;
|
||||
#if defined(RELAY_PORT)
|
||||
} else if (relay_port &&
|
||||
(info->rfdesc == relay_port_v6_socket) &&
|
||||
(info->wfdesc == relay_port_v6_socket) &&
|
||||
(relay_port_v6_socket_references > 0)) {
|
||||
/* Dereference the relay port v6 socket. */
|
||||
relay_port_v6_socket_references--;
|
||||
info->rfdesc = -1;
|
||||
info->wfdesc = -1;
|
||||
#endif
|
||||
} else {
|
||||
log_fatal("Impossible condition at %s:%d", MDL);
|
||||
}
|
||||
@ -633,12 +680,23 @@ if_deregister6(struct interface_info *info) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!no_global_v6_socket &&
|
||||
(global_v6_socket_references == 0)) {
|
||||
if (!no_global_v6_socket) {
|
||||
if (global_v6_socket_references == 0) {
|
||||
close(global_v6_socket);
|
||||
global_v6_socket = -1;
|
||||
|
||||
log_info("Unbound from *:%d", ntohs(local_port));
|
||||
log_info("Unbound from *:%d",
|
||||
(int) ntohs(local_port));
|
||||
}
|
||||
#if defined(RELAY_PORT)
|
||||
if (relay_port && (relay_port_v6_socket_references == 0)) {
|
||||
close(relay_port_v6_socket);
|
||||
relay_port_v6_socket = -1;
|
||||
|
||||
log_info("Unbound from relay port *:%d",
|
||||
(int) ntohs(relay_port));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif /* DHCPv6 */
|
||||
|
@ -557,12 +557,6 @@ static struct option dhcpv6_options[] = {
|
||||
{ "solmax-rt", "L", &dhcpv6_universe, 82, 1 },
|
||||
{ "inf-max-rt", "L", &dhcpv6_universe, 83, 1 },
|
||||
#endif
|
||||
#if defined(RFC7710_OPTIONS)
|
||||
{ "v6-captive-portal", "t", &dhcpv6_universe, 103, 1 },
|
||||
#endif
|
||||
#if defined(RFC6153_OPTIONS)
|
||||
{ "ipv6-address-andsf", "6A", &dhcpv6_universe, 143, 1 },
|
||||
#endif
|
||||
|
||||
/* RFC7341 OPTIONS */
|
||||
#if defined(RFC7341_OPTIONS)
|
||||
@ -570,6 +564,16 @@ static struct option dhcpv6_options[] = {
|
||||
{ "dhcp4-o-dhcp6-server", "6A", &dhcpv6_universe, 88, 1 },
|
||||
#endif
|
||||
|
||||
#if defined(RFC7710_OPTIONS)
|
||||
{ "v6-captive-portal", "t", &dhcpv6_universe, 103, 1 },
|
||||
#endif
|
||||
|
||||
{ "relay-source-port", "S", &dhcpv6_universe, 135, 1 },
|
||||
|
||||
#if defined(RFC6153_OPTIONS)
|
||||
{ "ipv6-address-andsf", "6A", &dhcpv6_universe, 143, 1 },
|
||||
#endif
|
||||
|
||||
{ NULL, NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
|
@ -156,6 +156,9 @@ void if_deregister_send (info)
|
||||
XXX Changes to the filter program may require changes to the constant
|
||||
offsets used in if_register_send to patch the UPF program! XXX */
|
||||
|
||||
#if defined(RELAY_PORT)
|
||||
#error "Relay port is not yet supported for UPF"
|
||||
#endif
|
||||
|
||||
void if_register_receive (info)
|
||||
struct interface_info *info;
|
||||
|
25
configure
vendored
25
configure
vendored
@ -768,6 +768,7 @@ enable_tracing
|
||||
enable_delayed_ack
|
||||
enable_dhcpv6
|
||||
enable_dhcpv4o6
|
||||
enable_relay_port
|
||||
enable_paranoia
|
||||
enable_early_chroot
|
||||
enable_ipv4_pktinfo
|
||||
@ -1446,6 +1447,7 @@ Optional Features:
|
||||
--enable-dhcpv6 enable support for DHCPv6 (default is yes)
|
||||
--enable-dhcpv4o6 enable support for DHCPv4-over-DHCPv6 (default is
|
||||
no)
|
||||
--enable-relay-port enable support for relay port (default is no)
|
||||
--enable-paranoia enable support for chroot/setuid (default is no)
|
||||
--enable-early-chroot enable chrooting prior to configuration (default is
|
||||
no)
|
||||
@ -5487,6 +5489,19 @@ else
|
||||
enable_dhcpv4o6="no"
|
||||
fi
|
||||
|
||||
# Relay port (draft-ietf-dhc-relay-port-10.txt) optional compile-time feature.
|
||||
# Check whether --enable-relay-port was given.
|
||||
if test "${enable_relay_port+set}" = set; then :
|
||||
enableval=$enable_relay_port;
|
||||
fi
|
||||
|
||||
# Relay port is off by default (for now)
|
||||
if test "$enable_relay_port" = "yes"; then
|
||||
|
||||
$as_echo "#define RELAY_PORT 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
# PARANOIA is off by default (until we can test it with all features)
|
||||
# Check whether --enable-paranoia was given.
|
||||
if test "${enable_paranoia+set}" = set; then :
|
||||
@ -6207,6 +6222,7 @@ fi
|
||||
done
|
||||
# needed for linux/filter.h on old systems
|
||||
|
||||
relay_port_supported="no"
|
||||
ac_fn_c_check_header_compile "$LINENO" "linux/filter.h" "ac_cv_header_linux_filter_h" "
|
||||
#ifdef HAVE_LINUX_TYPES_H
|
||||
#include <linux/types.h>
|
||||
@ -6223,6 +6239,7 @@ then
|
||||
|
||||
$as_echo "#define HAVE_LPF 1" >>confdefs.h
|
||||
|
||||
relay_port_supported="yes"
|
||||
else
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "sys/dlpi.h" "ac_cv_header_sys_dlpi_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_sys_dlpi_h" = xyes; then :
|
||||
@ -6247,10 +6264,17 @@ fi
|
||||
|
||||
$as_echo "#define HAVE_BPF 1" >>confdefs.h
|
||||
|
||||
relay_port_supported="yes"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$enable_relay_port" = "yes"; then
|
||||
if test "$relay_port_supported" != "yes"; then
|
||||
as_fn_error $? "--enable-relay-port requires BPF or LPF" "$LINENO" 5
|
||||
fi
|
||||
fi
|
||||
|
||||
# SIOCGLIFCONF uses some transport structures. Trick is not all platforms
|
||||
# use the same structures. We like to use 'struct lifconf' and 'struct
|
||||
# lifreq', but we'll use these other structures if they're present. HPUX
|
||||
@ -9014,6 +9038,7 @@ Features:
|
||||
dhcpv6: $enable_dhcpv6
|
||||
delayed-ack: $enable_delayed_ack
|
||||
dhcpv4o6: $enable_dhcpv4o6
|
||||
relay-port: $enable_relay_port
|
||||
|
||||
Developer:
|
||||
ATF unittests : $atf_path
|
||||
|
19
configure.ac
19
configure.ac
@ -177,6 +177,15 @@ else
|
||||
enable_dhcpv4o6="no"
|
||||
fi
|
||||
|
||||
# Relay port (draft-ietf-dhc-relay-port-10.txt) optional compile-time feature.
|
||||
AC_ARG_ENABLE(relay-port,
|
||||
AS_HELP_STRING([--enable-relay-port],[enable support for relay port (default is no)]))
|
||||
# Relay port is off by default (for now)
|
||||
if test "$enable_relay_port" = "yes"; then
|
||||
AC_DEFINE([RELAY_PORT], [1],
|
||||
[Define to 1 to include relay port support.])
|
||||
fi
|
||||
|
||||
# PARANOIA is off by default (until we can test it with all features)
|
||||
AC_ARG_ENABLE(paranoia,
|
||||
AS_HELP_STRING([--enable-paranoia],[enable support for chroot/setuid (default is no)]))
|
||||
@ -521,6 +530,7 @@ AC_CHECK_HEADERS(ifaddrs.h)
|
||||
# figure out what IPv4 interface code to use
|
||||
AC_CHECK_HEADERS(linux/types.h) # needed for linux/filter.h on old systems
|
||||
|
||||
relay_port_supported="no"
|
||||
AC_CHECK_HEADER(linux/filter.h, DO_LPF=1, ,
|
||||
[
|
||||
#ifdef HAVE_LINUX_TYPES_H
|
||||
@ -531,6 +541,7 @@ if test -n "$DO_LPF"
|
||||
then
|
||||
AC_DEFINE([HAVE_LPF], [1],
|
||||
[Define to 1 to use the Linux Packet Filter interface code.])
|
||||
relay_port_supported="yes"
|
||||
else
|
||||
AC_CHECK_HEADER(sys/dlpi.h, DO_DLPI=1)
|
||||
if test -n "$DO_DLPI"
|
||||
@ -544,10 +555,17 @@ else
|
||||
AC_DEFINE([HAVE_BPF], [1],
|
||||
[Define to 1 to use the
|
||||
Berkeley Packet Filter interface code.])
|
||||
relay_port_supported="yes"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$enable_relay_port" = "yes"; then
|
||||
if test "$relay_port_supported" != "yes"; then
|
||||
AC_MSG_ERROR([--enable-relay-port requires BPF or LPF])
|
||||
fi
|
||||
fi
|
||||
|
||||
# SIOCGLIFCONF uses some transport structures. Trick is not all platforms
|
||||
# use the same structures. We like to use 'struct lifconf' and 'struct
|
||||
# lifreq', but we'll use these other structures if they're present. HPUX
|
||||
@ -1035,6 +1053,7 @@ Features:
|
||||
dhcpv6: $enable_dhcpv6
|
||||
delayed-ack: $enable_delayed_ack
|
||||
dhcpv4o6: $enable_dhcpv4o6
|
||||
relay-port: $enable_relay_port
|
||||
|
||||
Developer:
|
||||
ATF unittests : $atf_path
|
||||
|
@ -178,6 +178,15 @@ else
|
||||
enable_dhcpv4o6="no"
|
||||
fi
|
||||
|
||||
# Relay port (draft-ietf-dhc-relay-port-10.txt) optional compile-time feature.
|
||||
AC_ARG_ENABLE(relay-port,
|
||||
AS_HELP_STRING([--enable-relay-port],[enable support for relay port (default is no)]))
|
||||
# Relay port is off by default (for now)
|
||||
if test "$enable_relay_port" = "yes"; then
|
||||
AC_DEFINE([RELAY_PORT], [1],
|
||||
[Define to 1 to include relay port support.])
|
||||
fi
|
||||
|
||||
# PARANOIA is off by default (until we can test it with all features)
|
||||
AC_ARG_ENABLE(paranoia,
|
||||
AS_HELP_STRING([--enable-paranoia],[enable support for chroot/setuid (default is no)]))
|
||||
@ -522,6 +531,7 @@ AC_CHECK_HEADERS(ifaddrs.h)
|
||||
# figure out what IPv4 interface code to use
|
||||
AC_CHECK_HEADERS(linux/types.h) # needed for linux/filter.h on old systems
|
||||
|
||||
relay_port_supported="no"
|
||||
AC_CHECK_HEADER(linux/filter.h, DO_LPF=1, ,
|
||||
[
|
||||
#ifdef HAVE_LINUX_TYPES_H
|
||||
@ -532,6 +542,7 @@ if test -n "$DO_LPF"
|
||||
then
|
||||
AC_DEFINE([HAVE_LPF], [1],
|
||||
[Define to 1 to use the Linux Packet Filter interface code.])
|
||||
relay_port_supported="yes"
|
||||
else
|
||||
AC_CHECK_HEADER(sys/dlpi.h, DO_DLPI=1)
|
||||
if test -n "$DO_DLPI"
|
||||
@ -545,10 +556,17 @@ else
|
||||
AC_DEFINE([HAVE_BPF], [1],
|
||||
[Define to 1 to use the
|
||||
Berkeley Packet Filter interface code.])
|
||||
relay_port_supported="yes"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$enable_relay_port" = "yes"; then
|
||||
if test "$relay_port_supported" != "yes"; then
|
||||
AC_MSG_ERROR([--enable-relay-port requires BPF or LPF])
|
||||
fi
|
||||
fi
|
||||
|
||||
# SIOCGLIFCONF uses some transport structures. Trick is not all platforms
|
||||
# use the same structures. We like to use 'struct lifconf' and 'struct
|
||||
# lifreq', but we'll use these other structures if they're present. HPUX
|
||||
@ -1040,6 +1058,7 @@ Features:
|
||||
dhcpv6: $enable_dhcpv6
|
||||
delayed-ack: $enable_delayed_ack
|
||||
dhcpv4o6: $enable_dhcpv4o6
|
||||
relay-port: $enable_relay_port
|
||||
|
||||
Developer:
|
||||
ATF unittests : $atf_path
|
||||
|
@ -183,6 +183,15 @@ else
|
||||
enable_dhcpv4o6="no"
|
||||
fi
|
||||
|
||||
# Relay port (draft-ietf-dhc-relay-port-10.txt) optional compile-time feature.
|
||||
AC_ARG_ENABLE(relay-port,
|
||||
AS_HELP_STRING([--enable-relay-port],[enable support for relay port (default is no)]))
|
||||
# Relay port is off by default (for now)
|
||||
if test "$enable_relay_port" = "yes"; then
|
||||
AC_DEFINE([RELAY_PORT], [1],
|
||||
[Define to 1 to include relay port support.])
|
||||
fi
|
||||
|
||||
# PARANOIA is off by default (until we can test it with all features)
|
||||
AC_ARG_ENABLE(paranoia,
|
||||
AS_HELP_STRING([--enable-paranoia],[enable support for chroot/setuid (default is no)]))
|
||||
@ -527,6 +536,7 @@ AC_CHECK_HEADERS(ifaddrs.h)
|
||||
# figure out what IPv4 interface code to use
|
||||
AC_CHECK_HEADERS(linux/types.h) # needed for linux/filter.h on old systems
|
||||
|
||||
relay_port_supported="no"
|
||||
AC_CHECK_HEADER(linux/filter.h, DO_LPF=1, ,
|
||||
[
|
||||
#ifdef HAVE_LINUX_TYPES_H
|
||||
@ -537,6 +547,7 @@ if test -n "$DO_LPF"
|
||||
then
|
||||
AC_DEFINE([HAVE_LPF], [1],
|
||||
[Define to 1 to use the Linux Packet Filter interface code.])
|
||||
relay_port_supported="yes"
|
||||
else
|
||||
AC_CHECK_HEADER(sys/dlpi.h, DO_DLPI=1)
|
||||
if test -n "$DO_DLPI"
|
||||
@ -550,10 +561,17 @@ else
|
||||
AC_DEFINE([HAVE_BPF], [1],
|
||||
[Define to 1 to use the
|
||||
Berkeley Packet Filter interface code.])
|
||||
relay_port_supported="yes"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$enable_relay_port" = "yes"; then
|
||||
if test "$relay_port_supported" != "yes"; then
|
||||
AC_MSG_ERROR([--enable-relay-port requires BPF or LPF])
|
||||
fi
|
||||
fi
|
||||
|
||||
# SIOCGLIFCONF uses some transport structures. Trick is not all platforms
|
||||
# use the same structures. We like to use 'struct lifconf' and 'struct
|
||||
# lifreq', but we'll use these other structures if they're present. HPUX
|
||||
@ -1076,6 +1094,7 @@ Features:
|
||||
dhcpv6: $enable_dhcpv6
|
||||
delayed-ack: $enable_delayed_ack
|
||||
dhcpv4o6: $enable_dhcpv4o6
|
||||
relay-port: $enable_relay_port
|
||||
|
||||
Developer:
|
||||
ATF unittests : $atf_path
|
||||
|
@ -177,6 +177,15 @@ else
|
||||
enable_dhcpv4o6="no"
|
||||
fi
|
||||
|
||||
# Relay port (draft-ietf-dhc-relay-port-10.txt) optional compile-time feature.
|
||||
AC_ARG_ENABLE(relay-port,
|
||||
AS_HELP_STRING([--enable-relay-port],[enable support for relay port (default is no)]))
|
||||
# Relay port is off by default (for now)
|
||||
if test "$enable_relay_port" = "yes"; then
|
||||
AC_DEFINE([RELAY_PORT], [1],
|
||||
[Define to 1 to include relay port support.])
|
||||
fi
|
||||
|
||||
# PARANOIA is off by default (until we can test it with all features)
|
||||
AC_ARG_ENABLE(paranoia,
|
||||
AS_HELP_STRING([--enable-paranoia],[enable support for chroot/setuid (default is no)]))
|
||||
@ -521,6 +530,7 @@ AC_CHECK_HEADERS(ifaddrs.h)
|
||||
# figure out what IPv4 interface code to use
|
||||
AC_CHECK_HEADERS(linux/types.h) # needed for linux/filter.h on old systems
|
||||
|
||||
relay_port_supported="no"
|
||||
AC_CHECK_HEADER(linux/filter.h, DO_LPF=1, ,
|
||||
[
|
||||
#ifdef HAVE_LINUX_TYPES_H
|
||||
@ -531,6 +541,7 @@ if test -n "$DO_LPF"
|
||||
then
|
||||
AC_DEFINE([HAVE_LPF], [1],
|
||||
[Define to 1 to use the Linux Packet Filter interface code.])
|
||||
relay_port_supported="yes"
|
||||
else
|
||||
AC_CHECK_HEADER(sys/dlpi.h, DO_DLPI=1)
|
||||
if test -n "$DO_DLPI"
|
||||
@ -544,10 +555,17 @@ else
|
||||
AC_DEFINE([HAVE_BPF], [1],
|
||||
[Define to 1 to use the
|
||||
Berkeley Packet Filter interface code.])
|
||||
relay_port_supported="yes"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$enable_relay_port" = "yes"; then
|
||||
if test "$relay_port_supported" != "yes"; then
|
||||
AC_MSG_ERROR([--enable-relay-port requires BPF or LPF])
|
||||
fi
|
||||
fi
|
||||
|
||||
# SIOCGLIFCONF uses some transport structures. Trick is not all platforms
|
||||
# use the same structures. We like to use 'struct lifconf' and 'struct
|
||||
# lifreq', but we'll use these other structures if they're present. HPUX
|
||||
@ -1035,6 +1053,7 @@ Features:
|
||||
dhcpv6: $enable_dhcpv6
|
||||
delayed-ack: $enable_delayed_ack
|
||||
dhcpv4o6: $enable_dhcpv4o6
|
||||
relay-port: $enable_relay_port
|
||||
|
||||
Developer:
|
||||
ATF unittests : $atf_path
|
||||
|
@ -219,3 +219,10 @@ to start the server.
|
||||
|
||||
Finally note in the configuration file the use of the shared-network to
|
||||
connect the DHCPv4 and DHCPv6 subnets.
|
||||
|
||||
USE WITH DHCPv6 RELAY(s)
|
||||
If the DHCPv6 infrastructure uses one (or more) relay because the client
|
||||
and the server are not on the same link the best choice is to put the
|
||||
first (closest to client) relay address in the dhcp4-o-dhcp6-server
|
||||
option so the same path between the DHCPv6 client part and server part
|
||||
will be used for DHCPv6 and DHCPv4-over-DHCPv6 traffic.
|
||||
|
@ -157,6 +157,9 @@
|
||||
/* Define to any value to include Ari's PARANOIA patch. */
|
||||
#undef PARANOIA
|
||||
|
||||
/* Define to 1 to include relay port support. */
|
||||
#undef RELAY_PORT
|
||||
|
||||
/* The size of `struct iaddr *', as computed by sizeof. */
|
||||
#undef SIZEOF_STRUCT_IADDR_P
|
||||
|
||||
|
@ -183,6 +183,8 @@ struct dhcp_packet {
|
||||
#define RAI_REMOTE_ID 2
|
||||
#define RAI_AGENT_ID 3
|
||||
#define RAI_LINK_SELECT 5
|
||||
/* not yet assigned but next free value */
|
||||
#define RAI_RELAY_PORT 19
|
||||
|
||||
/* FQDN suboptions: */
|
||||
#define FQDN_NO_CLIENT_UPDATE 1
|
||||
|
@ -115,6 +115,8 @@
|
||||
#define D6O_V6_PCP_SERVER 86 /* RFC7291 */
|
||||
#define D6O_DHCPV4_MSG 87 /* RFC7341 */
|
||||
#define D6O_DHCP4_O_DHCP6_SERVER 88 /* RFC7341 */
|
||||
/* not yet assigned but next free value */
|
||||
#define D6O_RELAY_SOURCE_PORT 135 /* I-D */
|
||||
|
||||
/*
|
||||
* Status Codes, from RFC 3315 section 24.4, and RFC 3633, 5007, 5460.
|
||||
|
@ -469,9 +469,12 @@ struct packet {
|
||||
*/
|
||||
isc_boolean_t unicast;
|
||||
|
||||
/* Propogates server value SV_ECHO_CLIENT_ID so it is available
|
||||
/* Propagates server value SV_ECHO_CLIENT_ID so it is available
|
||||
* in cons_options() */
|
||||
int sv_echo_client_id;
|
||||
|
||||
/* Relay port check */
|
||||
isc_boolean_t relay_source_port;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -2440,6 +2443,8 @@ void eval_network_statements(struct option_state **options,
|
||||
struct packet *packet,
|
||||
struct group *network_group);
|
||||
|
||||
u_int16_t dhcp_check_relayport(struct packet *packet);
|
||||
|
||||
/* dhcpleasequery.c */
|
||||
void dhcpleasequery (struct packet *, int);
|
||||
void dhcpv6_leasequery (struct data_string *, struct packet *);
|
||||
@ -2833,6 +2838,7 @@ extern int bind_local_address6;
|
||||
|
||||
extern u_int16_t local_port;
|
||||
extern u_int16_t remote_port;
|
||||
extern u_int16_t relay_port;
|
||||
extern int dhcpv4_over_dhcpv6;
|
||||
extern int (*dhcp_interface_setup_hook) (struct interface_info *,
|
||||
struct iaddr *);
|
||||
|
@ -43,6 +43,9 @@ dhcrelay - Dynamic Host Configuration Protocol Relay Agent
|
||||
[
|
||||
.B -p
|
||||
.I port
|
||||
|
|
||||
.B -rp
|
||||
.I relay-port
|
||||
]
|
||||
[
|
||||
.B -c
|
||||
@ -112,6 +115,9 @@ dhcrelay - Dynamic Host Configuration Protocol Relay Agent
|
||||
[
|
||||
.B -p
|
||||
.I port
|
||||
|
|
||||
.B -rp
|
||||
.I relay-port
|
||||
]
|
||||
[
|
||||
.B -c
|
||||
@ -174,7 +180,7 @@ the command line, to which DHCP/BOOTP queries should be relayed.
|
||||
.PP
|
||||
\fIOptions available for both DHCPv4 and DHCPv6:\fR
|
||||
.TP
|
||||
-c COUNT
|
||||
-c \fIcount\fR
|
||||
Maximum hop count. When forwarding packets, dhcrelay discards packets
|
||||
which have reached a hop count of COUNT. Default is 10. Maximum is 255.
|
||||
.TP
|
||||
@ -182,9 +188,17 @@ which have reached a hop count of COUNT. Default is 10. Maximum is 255.
|
||||
Force dhcrelay to run as a foreground process. Useful when running
|
||||
dhcrelay under a debugger, or running out of inittab on System V systems.
|
||||
.TP
|
||||
-p PORT
|
||||
-p \fIport\fR
|
||||
Listen and transmit on port PORT. This is mostly useful for debugging
|
||||
purposes. Default is port 67 for DHCPv4/BOOTP, or port 547 for DHCPv6.
|
||||
Incompatible with \fB-rp\fR.
|
||||
.TP
|
||||
-rp \fIrelay-port\fR
|
||||
Alternative source port for upstream (i.e toward the server) messages
|
||||
with DHCPv4 RAI relay-port sub-option or DHCPv6 relay-source-port
|
||||
option. Relay port support is only available if the code was compiled
|
||||
with (./configure --enable-relay-port) and requires LPF or BPF link
|
||||
layer access.
|
||||
.TP
|
||||
-q
|
||||
Quiet mode. Prevents dhcrelay6 from printing its network configuration
|
||||
@ -209,7 +223,7 @@ be the printable name of the interface on which the client request was
|
||||
received. The client supports inclusion of a Remote ID suboption as well,
|
||||
but this is not used by default.
|
||||
.TP
|
||||
-A LENGTH
|
||||
-A \fIlength\fR
|
||||
Specify the maximum packet size to send to a DHCPv4/BOOTP server. This
|
||||
might be done to allow sufficient space for addition of relay agent
|
||||
options while still fitting into the Ethernet MTU size.
|
||||
|
154
relay/dhcrelay.c
154
relay/dhcrelay.c
@ -152,8 +152,30 @@ static const char url[] =
|
||||
char *progname;
|
||||
|
||||
#ifdef DHCPv6
|
||||
#ifdef RELAY_PORT
|
||||
#define DHCRELAY_USAGE \
|
||||
"Usage: %s [-4] [-d] [-q] [-a] [-D]\n"\
|
||||
"Usage: %s [-4] [-d] [-q] [-a] [-D]\n" \
|
||||
" [-A <length>] [-c <hops>]\n" \
|
||||
" [-p <port> | -rp <relay-port>]\n" \
|
||||
" [-pf <pid-file>] [--no-pid]\n"\
|
||||
" [-m append|replace|forward|discard]\n" \
|
||||
" [-i interface0 [ ... -i interfaceN]\n" \
|
||||
" [-iu interface0 [ ... -iu interfaceN]\n" \
|
||||
" [-id interface0 [ ... -id interfaceN]\n" \
|
||||
" [-U interface]\n" \
|
||||
" server0 [ ... serverN]\n\n" \
|
||||
" %s -6 [-d] [-q] [-I] [-c <hops>]\n" \
|
||||
" [-p <port> | -rp <relay-port>]\n" \
|
||||
" [-pf <pid-file>] [--no-pid]\n" \
|
||||
" [-s <subscriber-id>]\n" \
|
||||
" -l lower0 [ ... -l lowerN]\n" \
|
||||
" -u upper0 [ ... -u upperN]\n" \
|
||||
" lower (client link): [address%%]interface[#index]\n" \
|
||||
" upper (server link): [address%%]interface\n\n" \
|
||||
" %s {--version|--help|-h}"
|
||||
#else
|
||||
#define DHCRELAY_USAGE \
|
||||
"Usage: %s [-4] [-d] [-q] [-a] [-D]\n" \
|
||||
" [-A <length>] [-c <hops>] [-p <port>]\n" \
|
||||
" [-pf <pid-file>] [--no-pid]\n"\
|
||||
" [-m append|replace|forward|discard]\n" \
|
||||
@ -170,6 +192,20 @@ char *progname;
|
||||
" lower (client link): [address%%]interface[#index]\n" \
|
||||
" upper (server link): [address%%]interface\n\n" \
|
||||
" %s {--version|--help|-h}"
|
||||
#endif
|
||||
#else /* !DHCPv6 */
|
||||
#ifdef RELAY_PORT
|
||||
#define DHCRELAY_USAGE \
|
||||
"Usage: %s [-d] [-q] [-a] [-D] [-A <length>] [-c <hops>]\n" \
|
||||
" [-p <port> | -rp <relay-port>]\n" \
|
||||
" [-pf <pid-file>] [--no-pid]\n" \
|
||||
" [-m append|replace|forward|discard]\n" \
|
||||
" [-i interface0 [ ... -i interfaceN]\n" \
|
||||
" [-iu interface0 [ ... -iu interfaceN]\n" \
|
||||
" [-id interface0 [ ... -id interfaceN]\n" \
|
||||
" [-U interface]\n" \
|
||||
" server0 [ ... serverN]\n\n" \
|
||||
" %s {--version|--help|-h}"
|
||||
#else
|
||||
#define DHCRELAY_USAGE \
|
||||
"Usage: %s [-d] [-q] [-a] [-D] [-A <length>] [-c <hops>] [-p <port>]\n" \
|
||||
@ -182,6 +218,7 @@ char *progname;
|
||||
" server0 [ ... serverN]\n\n" \
|
||||
" %s {--version|--help|-h}"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*!
|
||||
*
|
||||
@ -199,6 +236,12 @@ char *progname;
|
||||
* \return Nothing
|
||||
*/
|
||||
static const char use_noarg[] = "No argument for command: %s";
|
||||
#ifdef RELAY_PORT
|
||||
static const char use_port_defined[] = "Port already set, %s inappropriate";
|
||||
#if !defined (USE_BPF_RECEIVE) && !defined (USE_LPF_RECEIVE)
|
||||
static const char bpf_sock_support[] = "Only LPF and BPF are supported: %s";
|
||||
#endif
|
||||
#endif
|
||||
#ifdef DHCPv6
|
||||
static const char use_badproto[] = "Protocol already set, %s inappropriate";
|
||||
static const char use_v4command[] = "Command not used for DHCPv6: %s";
|
||||
@ -236,6 +279,9 @@ main(int argc, char **argv) {
|
||||
int quiet = 0;
|
||||
int fd;
|
||||
int i;
|
||||
#ifdef RELAY_PORT
|
||||
int port_defined = 0;
|
||||
#endif
|
||||
#ifdef DHCPv6
|
||||
struct stream_list *sl = NULL;
|
||||
int local_family_set = 0;
|
||||
@ -349,9 +395,26 @@ main(int argc, char **argv) {
|
||||
} else if (!strcmp(argv[i], "-p")) {
|
||||
if (++i == argc)
|
||||
usage(use_noarg, argv[i-1]);
|
||||
#ifdef RELAY_PORT
|
||||
if (port_defined)
|
||||
usage(use_port_defined, argv[i-1]);
|
||||
port_defined = 1;
|
||||
#endif
|
||||
local_port = validate_port(argv[i]);
|
||||
log_debug("binding to user-specified port %d",
|
||||
ntohs(local_port));
|
||||
#ifdef RELAY_PORT
|
||||
} else if (!strcmp(argv[i], "-rp")) {
|
||||
if (++i == argc)
|
||||
usage(use_noarg, argv[i-1]);
|
||||
if (port_defined)
|
||||
usage(use_port_defined, argv[i-1]);
|
||||
port_defined = 1;
|
||||
relay_port = validate_port(argv[i]);
|
||||
log_debug("binding to user-specified relay port %d",
|
||||
ntohs(relay_port));
|
||||
add_agent_options = 1;
|
||||
#endif
|
||||
} else if (!strcmp(argv[i], "-c")) {
|
||||
int hcount;
|
||||
if (++i == argc)
|
||||
@ -572,6 +635,12 @@ main(int argc, char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(RELAY_PORT) && \
|
||||
!defined (USE_BPF_RECEIVE) && !defined (USE_LPF_RECEIVE)
|
||||
if (relay_port && (local_family == AF_INET))
|
||||
usage(bpf_sock_support, "-rp");
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If the user didn't specify a pid file directly
|
||||
* find one from environment variables or defaults
|
||||
@ -1259,6 +1328,12 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet,
|
||||
optlen += 6;
|
||||
}
|
||||
|
||||
#ifdef RELAY_PORT
|
||||
if (relay_port) {
|
||||
optlen += 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We do not support relay option fragmenting(multiple options to
|
||||
* support an option data exceeding 255 bytes).
|
||||
*/
|
||||
@ -1303,6 +1378,14 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet,
|
||||
log_debug ("Adding link selection suboption"
|
||||
" with addr: %s", inet_ntoa(giaddr));
|
||||
}
|
||||
|
||||
#ifdef RELAY_PORT
|
||||
/* draft-ietf-dhc-relay-port-10.txt section 5.1 */
|
||||
if (relay_port) {
|
||||
*sp++ = RAI_RELAY_PORT;
|
||||
*sp++ = 0u;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
++agent_option_errors;
|
||||
log_error("No room in packet (used %d of %d) "
|
||||
@ -1548,6 +1631,9 @@ setup_streams(void) {
|
||||
static const int required_forw_opts[] = {
|
||||
D6O_INTERFACE_ID,
|
||||
D6O_SUBSCRIBER_ID,
|
||||
#if defined(RELAY_PORT)
|
||||
D6O_RELAY_SOURCE_PORT,
|
||||
#endif
|
||||
D6O_RELAY_MSG,
|
||||
0
|
||||
};
|
||||
@ -1562,6 +1648,7 @@ process_up6(struct packet *packet, struct stream_list *dp) {
|
||||
struct dhcpv6_relay_packet *relay;
|
||||
struct option_state *opts;
|
||||
struct stream_list *up;
|
||||
u_int16_t relay_client_port = 0;
|
||||
|
||||
/* Check if the message should be relayed to the server. */
|
||||
switch (packet->dhcpv6_msg_type) {
|
||||
@ -1622,6 +1709,10 @@ process_up6(struct packet *packet, struct stream_list *dp) {
|
||||
}
|
||||
memset(&relay->link_address, 0, 16);
|
||||
}
|
||||
|
||||
if (packet->client_port != htons(547)) {
|
||||
relay_client_port = packet->client_port;
|
||||
}
|
||||
} else {
|
||||
relay->hop_count = 0;
|
||||
if (!dp)
|
||||
@ -1674,6 +1765,30 @@ process_up6(struct packet *packet, struct stream_list *dp) {
|
||||
}
|
||||
|
||||
|
||||
#if defined(RELAY_PORT)
|
||||
/*
|
||||
* If we use a non-547 UDP source port or if we have received
|
||||
* from a downstream relay agent uses a non-547 port, we need
|
||||
* to include the RELAY-SOURCE-PORT option. The "Downstream
|
||||
* UDP Port" field value in the option allow us to send
|
||||
* relay-reply message back to the downstream relay agent
|
||||
* with the correct UDP source port.
|
||||
*/
|
||||
if (relay_port || relay_client_port) {
|
||||
if (!save_option_buffer(&dhcpv6_universe, opts, NULL,
|
||||
(unsigned char *) &relay_client_port,
|
||||
sizeof(u_int16_t),
|
||||
D6O_RELAY_SOURCE_PORT, 0)) {
|
||||
log_error("Can't save relay-source-port.");
|
||||
option_state_dereference(&opts, MDL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* Avoid unused but set warning, */
|
||||
(void)(relay_client_port);
|
||||
#endif
|
||||
|
||||
/* Add the relay-msg carrying the packet. */
|
||||
if (!save_option_buffer(&dhcpv6_universe, opts,
|
||||
NULL, (unsigned char *) packet->raw,
|
||||
@ -1708,6 +1823,9 @@ process_down6(struct packet *packet) {
|
||||
struct data_string relay_msg;
|
||||
const struct dhcpv6_packet *msg;
|
||||
struct data_string if_id;
|
||||
#if defined(RELAY_PORT)
|
||||
struct data_string down_port;
|
||||
#endif
|
||||
struct sockaddr_in6 to;
|
||||
struct iaddr peer;
|
||||
|
||||
@ -1729,6 +1847,9 @@ process_down6(struct packet *packet) {
|
||||
/* Inits. */
|
||||
memset(&relay_msg, 0, sizeof(relay_msg));
|
||||
memset(&if_id, 0, sizeof(if_id));
|
||||
#if defined(RELAY_PORT)
|
||||
memset(&down_port, 0, sizeof(down_port));
|
||||
#endif
|
||||
memset(&to, 0, sizeof(to));
|
||||
to.sin6_family = AF_INET6;
|
||||
#ifdef HAVE_SA_LEN
|
||||
@ -1799,6 +1920,37 @@ process_down6(struct packet *packet) {
|
||||
/* Relay-Reply of for another relay, not a client. */
|
||||
case DHCPV6_RELAY_REPL:
|
||||
to.sin6_port = local_port;
|
||||
|
||||
#if defined(RELAY_PORT)
|
||||
oc = lookup_option(&dhcpv6_universe, packet->options,
|
||||
D6O_RELAY_SOURCE_PORT);
|
||||
if (oc != NULL) {
|
||||
u_int16_t down_relay_port;
|
||||
|
||||
memset(&down_port, 0, sizeof(down_port));
|
||||
if (!evaluate_option_cache(&down_port, packet, NULL,
|
||||
NULL, packet->options, NULL,
|
||||
&global_scope, oc, MDL) ||
|
||||
(down_port.len != sizeof(u_int16_t))) {
|
||||
log_info("Can't evaluate down "
|
||||
"relay-source-port.");
|
||||
goto cleanup;
|
||||
}
|
||||
memcpy(&down_relay_port, down_port.data,
|
||||
sizeof(u_int16_t));
|
||||
/*
|
||||
* If the down_relay_port value is non-zero,
|
||||
* that means our downstream relay agent uses
|
||||
* a non-547 UDP source port sending
|
||||
* relay-forw message to us. We need to use
|
||||
* the same UDP port sending reply back.
|
||||
*/
|
||||
if (down_relay_port) {
|
||||
to.sin6_port = down_relay_port;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Fall into: */
|
||||
|
||||
case DHCPV6_ADVERTISE:
|
||||
|
@ -1063,6 +1063,20 @@ void dhcpdecline (packet, ms_nulltp)
|
||||
lease_dereference (&lease, MDL);
|
||||
}
|
||||
|
||||
#if defined(RELAY_PORT)
|
||||
u_int16_t dhcp_check_relayport(packet)
|
||||
struct packet *packet;
|
||||
{
|
||||
if (lookup_option(&agent_universe,
|
||||
packet->options,
|
||||
RAI_RELAY_PORT) != NULL) {
|
||||
return (packet->client_port);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void dhcpinform (packet, ms_nulltp)
|
||||
struct packet *packet;
|
||||
int ms_nulltp;
|
||||
@ -1084,6 +1098,7 @@ void dhcpinform (packet, ms_nulltp)
|
||||
struct interface_info *interface;
|
||||
int result, h_m_client_ip = 0;
|
||||
struct host_decl *host = NULL, *hp = NULL, *h;
|
||||
u_int16_t relay_port = 0;
|
||||
#if defined (DEBUG_INFORM_HOST)
|
||||
int h_w_fixed_addr = 0;
|
||||
#endif
|
||||
@ -1146,6 +1161,10 @@ void dhcpinform (packet, ms_nulltp)
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(RELAY_PORT)
|
||||
relay_port = dhcp_check_relayport(packet);
|
||||
#endif
|
||||
|
||||
/* Find the subnet that the client is on.
|
||||
* CC: Do the link selection / subnet selection
|
||||
*/
|
||||
@ -1696,7 +1715,7 @@ void dhcpinform (packet, ms_nulltp)
|
||||
*/
|
||||
if (!raw.ciaddr.s_addr && gip.len) {
|
||||
memcpy(&to.sin_addr, gip.iabuf, 4);
|
||||
to.sin_port = local_port;
|
||||
to.sin_port = relay_port ? relay_port : local_port;
|
||||
raw.flags |= htons(BOOTP_BROADCAST);
|
||||
} else {
|
||||
gip.len = 0;
|
||||
@ -1753,6 +1772,7 @@ void nak_lease (packet, cip, network_group)
|
||||
unsigned char nak = DHCPNAK;
|
||||
struct packet outgoing;
|
||||
unsigned i;
|
||||
u_int16_t relay_port = 0;
|
||||
struct option_state *options = (struct option_state *)0;
|
||||
struct option_cache *oc = (struct option_cache *)0;
|
||||
struct option_state *eval_options = NULL;
|
||||
@ -1781,6 +1801,10 @@ void nak_lease (packet, cip, network_group)
|
||||
save_option (&dhcp_universe, options, oc);
|
||||
option_cache_dereference (&oc, MDL);
|
||||
|
||||
#if defined(RELAY_PORT)
|
||||
relay_port = dhcp_check_relayport(packet);
|
||||
#endif
|
||||
|
||||
/* Set DHCP_MESSAGE to whatever the message is */
|
||||
if (!option_cache_allocate (&oc, MDL)) {
|
||||
log_error ("No memory for DHCPNAK message type.");
|
||||
@ -1929,7 +1953,7 @@ void nak_lease (packet, cip, network_group)
|
||||
if (raw.giaddr.s_addr) {
|
||||
to.sin_addr = raw.giaddr;
|
||||
if (raw.giaddr.s_addr != htonl (INADDR_LOOPBACK))
|
||||
to.sin_port = local_port;
|
||||
to.sin_port = relay_port ? relay_port : local_port;
|
||||
else
|
||||
to.sin_port = remote_port; /* for testing. */
|
||||
|
||||
@ -3752,6 +3776,7 @@ void dhcp_reply (lease)
|
||||
int result;
|
||||
struct lease_state *state = lease -> state;
|
||||
int nulltp, bootpp, unicastp = 1;
|
||||
u_int16_t relay_port = 0;
|
||||
struct data_string d1;
|
||||
const char *s;
|
||||
|
||||
@ -3921,11 +3946,15 @@ void dhcp_reply (lease)
|
||||
#endif
|
||||
memset (to.sin_zero, 0, sizeof to.sin_zero);
|
||||
|
||||
#if defined(RELAY_PORT)
|
||||
relay_port = dhcp_check_relayport(state->packet);
|
||||
#endif
|
||||
|
||||
/* If this was gatewayed, send it back to the gateway... */
|
||||
if (raw.giaddr.s_addr) {
|
||||
to.sin_addr = raw.giaddr;
|
||||
if (raw.giaddr.s_addr != htonl (INADDR_LOOPBACK))
|
||||
to.sin_port = local_port;
|
||||
to.sin_port = relay_port ? relay_port : local_port;
|
||||
else
|
||||
to.sin_port = remote_port; /* For debugging. */
|
||||
|
||||
|
@ -152,6 +152,7 @@ dhcpleasequery(struct packet *packet, int ms_nulltp) {
|
||||
u_int32_t time_rebinding;
|
||||
u_int32_t time_expiry;
|
||||
u_int32_t client_last_transaction_time;
|
||||
u_int16_t relay_port = 0;
|
||||
struct sockaddr_in to;
|
||||
struct in_addr siaddr;
|
||||
struct data_string prl;
|
||||
@ -660,12 +661,16 @@ dhcpleasequery(struct packet *packet, int ms_nulltp) {
|
||||
#endif
|
||||
memset(to.sin_zero, 0, sizeof(to.sin_zero));
|
||||
|
||||
#if defined(RELAY_PORT)
|
||||
relay_port = dhcp_check_relayport(packet);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Leasequery packets are be sent to the gateway address.
|
||||
*/
|
||||
to.sin_addr = packet->raw->giaddr;
|
||||
if (packet->raw->giaddr.s_addr != htonl(INADDR_LOOPBACK)) {
|
||||
to.sin_port = local_port;
|
||||
to.sin_port = relay_port ? relay_port : local_port;
|
||||
} else {
|
||||
to.sin_port = remote_port; /* XXXSK: For debugging. */
|
||||
}
|
||||
|
154
server/dhcpv6.c
154
server/dhcpv6.c
@ -27,6 +27,14 @@ static void send_dhcpv4_response(struct data_string *raw);
|
||||
static void recv_dhcpv4_query(struct data_string *raw);
|
||||
static void dhcp4o6_dhcpv4_query(struct data_string *reply_ret,
|
||||
struct packet *packet);
|
||||
|
||||
struct udp_data4o6 {
|
||||
u_int16_t src_port;
|
||||
u_int8_t rsp_opt_exist;
|
||||
u_int8_t reserved;
|
||||
};
|
||||
|
||||
static int offset_data4o6 = 36; /* 16+16+4 */
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -211,7 +219,7 @@ isc_result_t dhcpv4o6_handler(omapi_object_t *h) {
|
||||
|
||||
cc = recv(dhcp4o6_fd, buf, sizeof(buf), 0);
|
||||
|
||||
if (cc < DHCP_FIXED_NON_UDP + 32)
|
||||
if (cc < DHCP_FIXED_NON_UDP + offset_data4o6)
|
||||
return ISC_R_UNEXPECTED;
|
||||
memset(&raw, 0, sizeof(raw));
|
||||
if (!buffer_allocate(&raw.buffer, cc, MDL)) {
|
||||
@ -237,7 +245,7 @@ isc_result_t dhcpv4o6_handler(omapi_object_t *h) {
|
||||
* \brief Send the DHCPv4-response back to the DHCPv6 side
|
||||
* (DHCPv6 server function)
|
||||
*
|
||||
* Format: interface:16 + address:16 + DHCPv6 DHCPv4-response message
|
||||
* Format: interface:16 + address:16 + udp:4 + DHCPv6 DHCPv4-response message
|
||||
*
|
||||
* \param raw the IPC message content
|
||||
*/
|
||||
@ -246,6 +254,7 @@ static void send_dhcpv4_response(struct data_string *raw) {
|
||||
char name[16 + 1];
|
||||
struct sockaddr_in6 to_addr;
|
||||
char pbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
|
||||
struct udp_data4o6 udp_data;
|
||||
int send_ret;
|
||||
|
||||
memset(name, 0, sizeof(name));
|
||||
@ -263,26 +272,32 @@ static void send_dhcpv4_response(struct data_string *raw) {
|
||||
memset(&to_addr, 0, sizeof(to_addr));
|
||||
to_addr.sin6_family = AF_INET6;
|
||||
memcpy(&to_addr.sin6_addr, raw->data + 16, 16);
|
||||
if ((raw->data[32] == DHCPV6_RELAY_FORW) ||
|
||||
(raw->data[32] == DHCPV6_RELAY_REPL)) {
|
||||
memset(&udp_data, 0, sizeof(udp_data));
|
||||
memcpy(&udp_data, raw->data + 32, 4);
|
||||
if ((raw->data[36] == DHCPV6_RELAY_FORW) ||
|
||||
(raw->data[36] == DHCPV6_RELAY_REPL)) {
|
||||
if (udp_data.rsp_opt_exist) {
|
||||
to_addr.sin6_port = udp_data.src_port;
|
||||
} else {
|
||||
to_addr.sin6_port = local_port;
|
||||
}
|
||||
} else {
|
||||
to_addr.sin6_port = remote_port;
|
||||
}
|
||||
|
||||
log_info("send_dhcpv4_response(): sending %s on %s to %s port %d",
|
||||
dhcpv6_type_names[raw->data[32]],
|
||||
dhcpv6_type_names[raw->data[36]],
|
||||
name,
|
||||
inet_ntop(AF_INET6, raw->data + 16, pbuf, sizeof(pbuf)),
|
||||
ntohs(to_addr.sin6_port));
|
||||
|
||||
send_ret = send_packet6(ip, raw->data + 32, raw->len - 32, &to_addr);
|
||||
send_ret = send_packet6(ip, raw->data + 36, raw->len - 36, &to_addr);
|
||||
if (send_ret < 0) {
|
||||
log_error("send_dhcpv4_response: send_packet6(): %m");
|
||||
} else if (send_ret != raw->len - 32) {
|
||||
} else if (send_ret != raw->len - 36) {
|
||||
log_error("send_dhcpv4_response: send_packet6() "
|
||||
"sent %d of %d bytes",
|
||||
send_ret, raw->len - 32);
|
||||
send_ret, raw->len - 36);
|
||||
}
|
||||
}
|
||||
#endif /* DHCP4o6 */
|
||||
@ -857,6 +872,9 @@ static const int required_opts_solicit[] = {
|
||||
};
|
||||
static const int required_opts_agent[] = {
|
||||
D6O_INTERFACE_ID,
|
||||
#if defined(RELAY_PORT)
|
||||
D6O_RELAY_SOURCE_PORT,
|
||||
#endif
|
||||
D6O_RELAY_MSG,
|
||||
0
|
||||
};
|
||||
@ -6854,6 +6872,35 @@ dhcpv6_relay_forw(struct data_string *reply_ret, struct packet *packet) {
|
||||
data_string_forget(&a_opt, MDL);
|
||||
}
|
||||
|
||||
#if defined(RELAY_PORT)
|
||||
/*
|
||||
* Append the relay_source_port option if present.
|
||||
*/
|
||||
oc = lookup_option(&dhcpv6_universe, packet->options,
|
||||
D6O_RELAY_SOURCE_PORT);
|
||||
if (oc != NULL) {
|
||||
if (!evaluate_option_cache(&a_opt, packet,
|
||||
NULL, NULL,
|
||||
packet->options, NULL,
|
||||
&global_scope, oc, MDL)) {
|
||||
log_error("dhcpv6_relay_forw: error evaluating "
|
||||
"Relay Source Port.");
|
||||
goto exit;
|
||||
}
|
||||
if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL,
|
||||
(unsigned char *)a_opt.data,
|
||||
a_opt.len,
|
||||
D6O_RELAY_SOURCE_PORT, 0)) {
|
||||
log_error("dhcpv6_relay_forw: error saving "
|
||||
"Relay Source Port.");
|
||||
goto exit;
|
||||
}
|
||||
data_string_forget(&a_opt, MDL);
|
||||
|
||||
packet->relay_source_port = ISC_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Append our encapsulated stuff for caller.
|
||||
*/
|
||||
@ -7147,6 +7194,35 @@ dhcp4o6_relay_forw(struct data_string *reply_ret, struct packet *packet) {
|
||||
data_string_forget(&a_opt, MDL);
|
||||
}
|
||||
|
||||
#if defined(RELAY_PORT)
|
||||
/*
|
||||
* Append the relay_source_port option if present.
|
||||
*/
|
||||
oc = lookup_option(&dhcpv6_universe, packet->options,
|
||||
D6O_RELAY_SOURCE_PORT);
|
||||
if (oc != NULL) {
|
||||
if (!evaluate_option_cache(&a_opt, packet,
|
||||
NULL, NULL,
|
||||
packet->options, NULL,
|
||||
&global_scope, oc, MDL)) {
|
||||
log_error("dhcpv4o6_relay_forw: error evaluating "
|
||||
"Relay Source Port.");
|
||||
goto exit;
|
||||
}
|
||||
if (!save_option_buffer(&dhcpv6_universe, opt_state, NULL,
|
||||
(unsigned char *)a_opt.data,
|
||||
a_opt.len,
|
||||
D6O_RELAY_SOURCE_PORT, 0)) {
|
||||
log_error("dhcpv4o6_relay_forw: error saving "
|
||||
"Relay Source Port.");
|
||||
goto exit;
|
||||
}
|
||||
data_string_forget(&a_opt, MDL);
|
||||
|
||||
packet->relay_source_port = ISC_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Append our encapsulated stuff for caller.
|
||||
*/
|
||||
@ -7436,12 +7512,13 @@ exit:
|
||||
* \brief Forward a DHCPv4-query message to the DHCPv4 side
|
||||
* (DHCPv6 server function)
|
||||
*
|
||||
* Format: interface:16 + address:16 + DHCPv6 DHCPv4-query message
|
||||
* Format: interface:16 + address:16 + udp:4 + DHCPv6 DHCPv4-query message
|
||||
*
|
||||
* \brief packet the DHCPv6 DHCPv4-query message
|
||||
*/
|
||||
static void forw_dhcpv4_query(struct packet *packet) {
|
||||
struct data_string ds;
|
||||
struct udp_data4o6 udp_data;
|
||||
unsigned len;
|
||||
int cc;
|
||||
|
||||
@ -7458,7 +7535,7 @@ static void forw_dhcpv4_query(struct packet *packet) {
|
||||
}
|
||||
|
||||
/* Get a buffer. */
|
||||
len = packet->packet_length + 32;
|
||||
len = packet->packet_length + 36;
|
||||
memset(&ds, 0, sizeof(ds));
|
||||
if (!buffer_allocate(&ds.buffer, len, MDL)) {
|
||||
log_error("forw_dhcpv4_query: "
|
||||
@ -7472,7 +7549,10 @@ static void forw_dhcpv4_query(struct packet *packet) {
|
||||
strncpy((char *)ds.buffer->data, packet->interface->name, 16);
|
||||
memcpy(ds.buffer->data + 16,
|
||||
packet->client_addr.iabuf, 16);
|
||||
memcpy(ds.buffer->data + 32,
|
||||
memset(&udp_data, 0, sizeof(udp_data));
|
||||
udp_data.src_port = packet->client_port;
|
||||
memcpy(ds.buffer->data + 32, &udp_data, 4);
|
||||
memcpy(ds.buffer->data + 36,
|
||||
(unsigned char *)packet->raw,
|
||||
packet->packet_length);
|
||||
|
||||
@ -7690,6 +7770,15 @@ dhcpv6(struct packet *packet) {
|
||||
to_addr.sin6_port = packet->client_port;
|
||||
#endif
|
||||
|
||||
#if defined(RELAY_PORT)
|
||||
/*
|
||||
* Check relay source port.
|
||||
*/
|
||||
if (packet->relay_source_port) {
|
||||
to_addr.sin6_port = packet->client_port;
|
||||
}
|
||||
#endif
|
||||
|
||||
memcpy(&to_addr.sin6_addr, packet->client_addr.iabuf,
|
||||
sizeof(to_addr.sin6_addr));
|
||||
|
||||
@ -7716,7 +7805,7 @@ dhcpv6(struct packet *packet) {
|
||||
* Receive a message with a DHCPv4-query inside from the DHCPv6 server.
|
||||
* (code copied from \ref do_packet6() \ref and dhcpv6())
|
||||
*
|
||||
* Format: interface:16 + address:16 + DHCPv6 DHCPv4-query message
|
||||
* Format: interface:16 + address:16 + udp:4 + DHCPv6 DHCPv4-query message
|
||||
*
|
||||
* \param raw the DHCPv6 DHCPv4-query message raw content
|
||||
*/
|
||||
@ -7730,6 +7819,7 @@ static void recv_dhcpv4_query(struct data_string *raw) {
|
||||
const struct dhcpv4_over_dhcpv6_packet *msg;
|
||||
struct data_string reply;
|
||||
struct data_string ds;
|
||||
struct udp_data4o6 udp_data;
|
||||
unsigned len;
|
||||
int cc;
|
||||
|
||||
@ -7748,14 +7838,17 @@ static void recv_dhcpv4_query(struct data_string *raw) {
|
||||
iaddr.len = 16;
|
||||
memcpy(iaddr.iabuf, raw->data + 16, 16);
|
||||
|
||||
memset(&udp_data, 0, sizeof(udp_data));
|
||||
memcpy(&udp_data, raw->data + 32, 4);
|
||||
|
||||
/*
|
||||
* From do_packet6().
|
||||
*/
|
||||
|
||||
if (!packet6_len_okay((char *)raw->data + 32, raw->len - 32)) {
|
||||
if (!packet6_len_okay((char *)raw->data + 36, raw->len - 36)) {
|
||||
log_error("recv_dhcpv4_query: "
|
||||
"short packet from %s, len %d, dropped",
|
||||
piaddr(iaddr), raw->len - 32);
|
||||
piaddr(iaddr), raw->len - 36);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -7774,18 +7867,18 @@ static void recv_dhcpv4_query(struct data_string *raw) {
|
||||
return;
|
||||
}
|
||||
|
||||
packet->raw = (struct dhcp_packet *)(raw->data + 32);
|
||||
packet->packet_length = raw->len - 32;
|
||||
packet->client_port = remote_port;
|
||||
packet->raw = (struct dhcp_packet *)(raw->data + 36);
|
||||
packet->packet_length = raw->len - 36;
|
||||
packet->client_port = udp_data.src_port;
|
||||
packet->client_addr = iaddr;
|
||||
interface_reference(&packet->interface, ip, MDL);
|
||||
|
||||
msg_type = raw->data[32];
|
||||
msg_type = raw->data[36];
|
||||
if ((msg_type == DHCPV6_RELAY_FORW) ||
|
||||
(msg_type == DHCPV6_RELAY_REPL)) {
|
||||
int relaylen =
|
||||
(int)(offsetof(struct dhcpv6_relay_packet, options));
|
||||
relay = (const struct dhcpv6_relay_packet *)(raw->data + 32);
|
||||
relay = (const struct dhcpv6_relay_packet *)(raw->data + 36);
|
||||
packet->dhcpv6_msg_type = relay->msg_type;
|
||||
|
||||
/* relay-specific data */
|
||||
@ -7797,7 +7890,7 @@ static void recv_dhcpv4_query(struct data_string *raw) {
|
||||
|
||||
if (!parse_option_buffer(packet->options,
|
||||
relay->options,
|
||||
raw->len - 32 - relaylen,
|
||||
raw->len - 36 - relaylen,
|
||||
&dhcpv6_universe)) {
|
||||
/* no logging here, as parse_option_buffer() logs all
|
||||
cases where it fails */
|
||||
@ -7808,7 +7901,7 @@ static void recv_dhcpv4_query(struct data_string *raw) {
|
||||
(msg_type == DHCPV6_DHCPV4_RESPONSE)) {
|
||||
int msglen =
|
||||
(int)(offsetof(struct dhcpv4_over_dhcpv6_packet, options));
|
||||
msg = (struct dhcpv4_over_dhcpv6_packet *)(raw->data + 32);
|
||||
msg = (struct dhcpv4_over_dhcpv6_packet *)(raw->data + 36);
|
||||
packet->dhcpv6_msg_type = msg->msg_type;
|
||||
|
||||
/* message-specific data */
|
||||
@ -7817,7 +7910,7 @@ static void recv_dhcpv4_query(struct data_string *raw) {
|
||||
|
||||
if (!parse_option_buffer(packet->options,
|
||||
msg->options,
|
||||
raw->len - 32 - msglen,
|
||||
raw->len - 36 - msglen,
|
||||
&dhcpv6_universe)) {
|
||||
/* no logging here, as parse_option_buffer() logs all
|
||||
cases where it fails */
|
||||
@ -7878,18 +7971,19 @@ static void recv_dhcpv4_query(struct data_string *raw) {
|
||||
*/
|
||||
build_dhcpv6_reply(&reply, packet);
|
||||
|
||||
if (reply.data == NULL) {
|
||||
packet_dereference(&packet, MDL);
|
||||
|
||||
if (reply.data == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Forward the response.
|
||||
*/
|
||||
len = reply.len + 32;
|
||||
len = reply.len + 36;
|
||||
memset(&ds, 0, sizeof(ds));
|
||||
if (!buffer_allocate(&ds.buffer, len, MDL)) {
|
||||
log_error("recv_dhcpv4_query: no memory.");
|
||||
packet_dereference(&packet, MDL);
|
||||
return;
|
||||
}
|
||||
ds.data = ds.buffer->data;
|
||||
@ -7897,7 +7991,15 @@ static void recv_dhcpv4_query(struct data_string *raw) {
|
||||
|
||||
memcpy(ds.buffer->data, name, 16);
|
||||
memcpy(ds.buffer->data + 16, iaddr.iabuf, 16);
|
||||
memcpy(ds.buffer->data + 32, reply.data, reply.len);
|
||||
udp_data.rsp_opt_exist = packet->relay_source_port ? 1 : 0;
|
||||
memcpy(ds.buffer->data + 32, &udp_data, 4);
|
||||
memcpy(ds.buffer->data + 36, reply.data, reply.len);
|
||||
|
||||
/*
|
||||
* Now we can release the packet.
|
||||
*/
|
||||
packet_dereference(&packet, MDL);
|
||||
|
||||
cc = send(dhcp4o6_fd, ds.data, ds.len, 0);
|
||||
if (cc < 0)
|
||||
log_error("recv_dhcpv4_query: send(): %m");
|
||||
|
@ -169,6 +169,7 @@ static struct option agent_options[] = {
|
||||
{ "agent-id", "I", &agent_universe, 3, 1 },
|
||||
{ "DOCSIS-device-class", "L", &agent_universe, 4, 1 },
|
||||
{ "link-selection", "I", &agent_universe, 5, 1 },
|
||||
{ "relay-port", "Z", &agent_universe, 19, 1 },
|
||||
{ NULL, NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user