We would like to the patch split as follows: 1. V4 Server support 2. V4 Relay support 3. V6 Server support 4. V6 Relay 5. 4o6 Support 2. The BPF filter changes seem fine. They allows an interface to accept messages either from the standard port or the alternate port which matches the RFC draft. For interfaces that are both up and down, though it would mean that the upstream could only receive on the alternate port as the first port in the filter would be the standard downstream port. This is likely acceptable versus more complicated filter logic. 3. The patch implements a global command line parameter, "-rp", used by dhcrelay to specify an alternate port value. When this parameter is specified the interface discovery code has been modified to only register one upstream and one downstream interface. It is unclear if this was done for simplicity or based upon a perceived most likely use-case. There is a more flexible approach, that supports multiple interfaces, and has the additional benefit of being more seamless: Add an optional port value to the v4's "-i,-iu,-U" and v6's "-u" command arguments: -iu interface[/port] -u [address%]interface[/port] This makes the alternate port use specific to an upstream interface. If users want only a single upstream or downstream interfaces they explicitly configure it that way, if they want more than one they can still do that. The steps to implement this are outlined below: Rather than a single global relay_port variable, add a member for it to struct interface_info: struct interface_info { : unit16_t relay_port; } relay/dhcrealy.c:request_v4_interface() Modify to look for the port value and populate it in the structure, only allowed if the flag parameter includes INTERFACE_UPSTREAM. relay/dhcrealy.c:parse_upstream() Modify to look for the port value and populate it in the structure. discover.c::discover_interfaces() Would not require the changes made by the patch, it would revert to as is. Several places would need look at the structure port value, instead of the global value: common/discover.c::lpf_gen_filter_setup(): if ((udp.uh_dport != local_port) && ((interface->relay_port == 0) || (udp.uh_dport != interface->relay_port))) common/packet.c:assemble_udp_ip_header(): udp.uh_sport = (interface->relay_port ? interface->relay_port : local_port); common/packet.c:decode_udp_ip_header(): if ((udp.uh_dport != local_port) && ((interface->relay_port == 0) || (udp.uh_dport != interface->relay_port))) common/raw.c:if_register_send(): name.sin_port = (info->relay_port ? info->relay_port: local_port; common/socket.c:if_register_socket(): addr6->sin6_port = (info->relay_port ? info->relay_port: local_port; The rest of the changes the patch makes to this function are unnecessary. relay/dhcrelay.c:process_up6() Relocate the logic to add the D6O_RELAY_PORT to inside the upstream send loop. Here the logic would need to be a little smarter: /* Send it to all upstreams. */ int has_relay_option = 0; for (up = upstreams; up; up = up->next) { if (has_relay_option) { /* Previous upstream added it, this either shouldn't * have it or needs to replace it, so let's remove it */ delete_option(&dhcpv6_universe, opts, D6O_RELAY_PORT); has_relay_option = 0; } if (upstream->relay_port || relay_client_port) { if (!save_option_buffer(&dhcpv6_universe, opts, NULL, (unsigned char *) &relay_client_port, sizeof(u_int16_t), D6O_RELAY_PORT, 0)) { log_error("Can't save relay-port."); option_state_dereference(&opts, MDL); return; } has_relay_option = 1; } send_packet6(up->ifp, (unsigned char *) forw_data, (size_t) cursor, &up->link); } Note these changes may not have covered everything necessary, and of course have not been been compile so there may syntax errors. However they should suffice to guide the actual code work. 4. The 4o6 patch seems fine. It adds room in the IPC header to accommodate the alternate port the V6 server received the message from so the v4 server can echo it back. This allows the V6 server to send the response back on the alternate port.