After the many iterations of the layer 2 diff, I noticed I broke the layer 3 default Relay Agent Information insertion: the relayed packet is using the wrong address in the remote-id field.
This diff makes the Relay Agent Information init function to run later and get the right address for the default remote-id. ok? Index: dhcrelay.c =================================================================== RCS file: /home/obsdcvs/src/usr.sbin/dhcrelay/dhcrelay.c,v retrieving revision 1.52 diff -u -p -r1.52 dhcrelay.c --- dhcrelay.c 13 Dec 2016 09:29:05 -0000 1.52 +++ dhcrelay.c 13 Dec 2016 13:57:16 -0000 @@ -72,7 +72,7 @@ char *print_hw_addr(int, int, unsigned c void got_response(struct protocol *); int get_rdomain(char *); -void relay_agentinfo(struct packet_ctx *, struct interface_info *); +void relay_agentinfo(struct packet_ctx *, struct interface_info *, int); int relay_agentinfo_cmp(struct packet_ctx *pc, uint8_t *, int); ssize_t relay_agentinfo_append(struct packet_ctx *, struct dhcp_packet *, @@ -337,8 +337,6 @@ relay(struct interface_info *ip, struct return; } - relay_agentinfo(pc, ip); - /* If it's a bootreply, forward it to the client. */ if (packet->op == BOOTREPLY) { /* Filter packet that were not meant for us. */ @@ -373,6 +371,7 @@ relay(struct interface_info *ip, struct memset(pc->pc_dmac, 0xff, sizeof(pc->pc_dmac)); } + relay_agentinfo(pc, interfaces, packet->op); if ((length = relay_agentinfo_remove(pc, packet, length)) == -1) { note("ignoring BOOTREPLY with invalid " @@ -420,6 +419,7 @@ relay(struct interface_info *ip, struct if (!packet->giaddr.s_addr) packet->giaddr = ip->primary_address; + relay_agentinfo(pc, interfaces, packet->op); if ((length = relay_agentinfo_append(pc, packet, length)) == -1) { note("ignoring BOOTREQUEST with invalid " "relay agent information"); @@ -559,9 +559,11 @@ got_response(struct protocol *l) } void -relay_agentinfo(struct packet_ctx *pc, struct interface_info *intf) +relay_agentinfo(struct packet_ctx *pc, struct interface_info *intf, + int bootop) { - static u_int8_t buf[8]; + static u_int8_t buf[8]; + struct sockaddr_in *sin; if (oflag == 0) return; @@ -579,10 +581,15 @@ relay_agentinfo(struct packet_ctx *pc, s pc->pc_circuitlen = 2; if (rai_remote == NULL) { + if (bootop == BOOTREPLY) + sin = ss2sin(&pc->pc_dst); + else + sin = ss2sin(&pc->pc_src); + pc->pc_remote = - (uint8_t *)&ss2sin(&pc->pc_dst)->sin_addr; + (uint8_t *)&sin->sin_addr; pc->pc_remotelen = - sizeof(ss2sin(&pc->pc_dst)->sin_addr); + sizeof(sin->sin_addr); } } else { pc->pc_circuit = (u_int8_t *)rai_circuit; @@ -867,7 +874,7 @@ l2relay(struct interface_info *ip, struc return; } - relay_agentinfo(pc, ip); + relay_agentinfo(pc, ip, dp->op); switch (dp->op) { case BOOTREQUEST: