Hi,

comments inline.
> RFC3527 link selection sub-option is used to select the "uplink"
interface of
> dhcrelay in cases where the DHCP server does not know how to reach the 
> dhcrelay
> based on the DHCP range. This can happen in weird network configurations like
> Mesh networks.
> 
> Signed-off-by: Bruno Randolf <b...@einfach.org>
> ---
>  net/isc-dhcp/files/dhcrelay4.init                  |   8 ++
>  net/isc-dhcp/files/etc/config/dhcrelay             |   3 +
>  .../patches/100-relay-rfc3527-link-selection.patch | 100 
> +++++++++++++++++++++
>  3 files changed, 111 insertions(+)
>  create mode 100644 
> net/isc-dhcp/patches/100-relay-rfc3527-link-selection.patch
> 
> diff --git a/net/isc-dhcp/files/dhcrelay4.init 
> b/net/isc-dhcp/files/dhcrelay4.init
> index 0f87b37..d03722f 100644
> --- a/net/isc-dhcp/files/dhcrelay4.init
> +++ b/net/isc-dhcp/files/dhcrelay4.init
> @@ -29,6 +29,14 @@ start() {
>               done
>       fi
>  
> +     # link selection sub-option (RFC3527)
> +     local link_selection
> +     config_get link_selection ipv4 link_selection
> +     if [ -n "$link_selection" ]; then
> +             config_get ifname "$link_selection" ifname

This relies on state vars which will get deprecated soon. Should be
converted to use "network_get_device" from /lib/functions/network.sh.

Example:

if network_get_device ifname "$link_selection"; then
    append args "-l $ifname"
fi

> +             append args "-l $ifname"
> +     fi
> +
>       # relay mode
>       local relay_mode
>       config_get relay_mode ipv4 relay_mode
> diff --git a/net/isc-dhcp/files/etc/config/dhcrelay 
> b/net/isc-dhcp/files/etc/config/dhcrelay
> index 1b89782..b3b53b5 100644
> --- a/net/isc-dhcp/files/etc/config/dhcrelay
> +++ b/net/isc-dhcp/files/etc/config/dhcrelay
> @@ -15,6 +15,9 @@ config dhcrelay ipv4
>       # 'discard': Don't forward
>       option 'relay_mode' ''
>  
> +     # enable RFC3527 link selection sub-option and use the IP address of
> +     # the specified network interface as "uplink" IP address (e.g. wan)
> +     option 'link_selection' ''
>  
>  config dhcrelay ipv6
>  #    option dhcpserver '2001:db8:1::1'
> diff --git a/net/isc-dhcp/patches/100-relay-rfc3527-link-selection.patch 
> b/net/isc-dhcp/patches/100-relay-rfc3527-link-selection.patch
> new file mode 100644
> index 0000000..1f593ee
> --- /dev/null
> +++ b/net/isc-dhcp/patches/100-relay-rfc3527-link-selection.patch

Can you elaborate on the origin of this patch? Was it written by you?

> @@ -0,0 +1,100 @@
> +--- a/relay/dhcrelay.c
> ++++ b/relay/dhcrelay.c
> +@@ -65,6 +65,7 @@ int server_packets_relayed = 0;    /* Packe
> + int client_packet_errors = 0;       /* Errors sending packets to clients. */
> + 
> + int add_agent_options = 0;  /* If nonzero, add relay agent options. */
> ++int add_rfc3527_suboption = 0;      /* If nonzero, add RFC3527 link 
> selection sub-option. */
> + 
> + int agent_option_errors = 0;    /* Number of packets forwarded without
> +                                agent options because there was no room. */
> +@@ -104,6 +105,8 @@ struct server_list {
> +     struct sockaddr_in to;
> + } *servers;
> + 
> ++struct interface_info *uplink;
> ++
> + #ifdef DHCPv6
> + struct stream_list {
> +     struct stream_list *next;
> +@@ -144,6 +147,7 @@ static const char url[] =
> + "                     [-pf <pid-file>] [--no-pid]\n"\
> + "                     [-m append|replace|forward|discard]\n" \
> + "                     [-i interface0 [ ... -i interfaceN]\n" \
> ++"                     [-l interface]\n" \
> + "                     server0 [ ... serverN]\n\n" \
> + "       dhcrelay -6   [-d] [-q] [-I] [-c <hops>] [-p <port>]\n" \
> + "                     [-pf <pid-file>] [--no-pid]\n"\
> +@@ -157,6 +161,7 @@ static const char url[] =
> + "                [-pf <pid-file>] [--no-pid]\n"\
> + "                [-m append|replace|forward|discard]\n" \
> + "                [-i interface0 [ ... -i interfaceN]\n" \
> ++"                [-l interface]\n" \
> + "                server0 [ ... serverN]\n\n"
> + #endif
> + 
> +@@ -314,6 +319,20 @@ main(int argc, char **argv) {
> +                             agent_relay_mode = discard;
> +                     } else
> +                             usage();
> ++            } else if (!strcmp (argv [i], "-l")) {
> ++                    add_agent_options = 1;
> ++                    add_rfc3527_suboption = 1;
> ++                    if (++i == argc)
> ++                            usage();
> ++
> ++                    status = interface_allocate(&uplink, MDL);
> ++                    if (status != ISC_R_SUCCESS)
> ++                            log_fatal("%s: interface_allocate: %s",
> ++                                      argv[i],
> ++                                      isc_result_totext(status));
> ++                    strcpy(uplink->name, argv[i]);
> ++                    interface_snorf(uplink, INTERFACE_REQUESTED);
> ++                    //interface_dereference(&uplink, MDL);
> +             } else if (!strcmp(argv[i], "-D")) {
> + #ifdef DHCPv6
> +                     if (local_family_set && (local_family == AF_INET6)) {
> +@@ -685,12 +704,17 @@ do_relay4(struct interface_info *ip, str
> +                                            ip->addresses[0])))
> +             return;
> + 
> ++    /* RFC3527: Replace giaddr address by uplink address. The original
> ++     * giaddr will be used in the link selection sub-option */
> ++    if (add_rfc3527_suboption)
> ++            packet->giaddr = uplink->addresses[0];
> ++
> +     /* If giaddr is not already set, Set it so the server can
> +        figure out what net it's from and so that we can later
> +        forward the response to the correct net.    If it's already
> +        set, the response will be sent directly to the relay agent
> +        that set giaddr, so we won't see it. */
> +-    if (!packet->giaddr.s_addr)
> ++    else if (!packet->giaddr.s_addr)
> +             packet->giaddr = ip->addresses[0];
> +     if (packet->hops < max_hop_count)
> +             packet->hops = packet->hops + 1;
> +@@ -1062,6 +1086,9 @@ add_relay_agent_options(struct interface
> +             optlen += ip->remote_id_len + 2;    /* RAI_REMOTE_ID + len */
> +     }
> + 
> ++    if (add_rfc3527_suboption)
> ++            optlen += 6;
> ++
> +     /* We do not support relay option fragmenting(multiple options to
> +      * support an option data exceeding 255 bytes).
> +      */
> +@@ -1093,6 +1120,14 @@ add_relay_agent_options(struct interface
> +                     memcpy(sp, ip->remote_id, ip->remote_id_len);
> +                     sp += ip->remote_id_len;
> +             }
> ++
> ++            if (add_rfc3527_suboption) {
> ++                    *sp++ = RAI_LINK_SELECT;
> ++                    *sp++ = 4u;
> ++                    memcpy(sp, &giaddr.s_addr, 4);
> ++                    sp += 4;
> ++                    log_debug ("RFC3527 link selection sub-option added: 
> %s", inet_ntoa(giaddr));
> ++            }
> +     } else {
> +             ++agent_option_errors;
> +             log_error("No room in packet (used %d of %d) "
> 

~ Jow


Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to