diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-06-16 10:20:27 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-06-16 10:20:27 +0200 |
commit | 47f2d7ef7d4dbeea19a55f9d73ef826f9d06650f (patch) | |
tree | a84db8f0215526b9728f2f2b94214100e853a98c /networking/udhcp/serverpacket.c | |
parent | 1f363a086779152ab04067e81484b8bb69e4af72 (diff) | |
download | busybox-w32-47f2d7ef7d4dbeea19a55f9d73ef826f9d06650f.tar.gz busybox-w32-47f2d7ef7d4dbeea19a55f9d73ef826f9d06650f.tar.bz2 busybox-w32-47f2d7ef7d4dbeea19a55f9d73ef826f9d06650f.zip |
udhcpd: don't fail ARP check if returned MAC matches client's one
Also, do not unicast replies to yiaddr.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking/udhcp/serverpacket.c')
-rw-r--r-- | networking/udhcp/serverpacket.c | 51 |
1 files changed, 31 insertions, 20 deletions
diff --git a/networking/udhcp/serverpacket.c b/networking/udhcp/serverpacket.c index 8b0f1856b..157d157ba 100644 --- a/networking/udhcp/serverpacket.c +++ b/networking/udhcp/serverpacket.c | |||
@@ -31,7 +31,8 @@ static int send_packet_to_relay(struct dhcpMessage *payload) | |||
31 | { | 31 | { |
32 | DEBUG("Forwarding packet to relay"); | 32 | DEBUG("Forwarding packet to relay"); |
33 | 33 | ||
34 | return udhcp_send_kernel_packet(payload, server_config.server, SERVER_PORT, | 34 | return udhcp_send_kernel_packet(payload, |
35 | server_config.server, SERVER_PORT, | ||
35 | payload->giaddr, SERVER_PORT); | 36 | payload->giaddr, SERVER_PORT); |
36 | } | 37 | } |
37 | 38 | ||
@@ -42,23 +43,31 @@ static int send_packet_to_client(struct dhcpMessage *payload, int force_broadcas | |||
42 | const uint8_t *chaddr; | 43 | const uint8_t *chaddr; |
43 | uint32_t ciaddr; | 44 | uint32_t ciaddr; |
44 | 45 | ||
45 | if (force_broadcast) { | 46 | // Was: |
46 | DEBUG("broadcasting packet to client (NAK)"); | 47 | //if (force_broadcast) { /* broadcast */ } |
48 | //else if (payload->ciaddr) { /* unicast to payload->ciaddr */ } | ||
49 | //else if (payload->flags & htons(BROADCAST_FLAG)) { /* broadcast */ } | ||
50 | //else { /* unicast to payload->yiaddr */ } | ||
51 | // But this is wrong: yiaddr is _our_ idea what client's IP is | ||
52 | // (for example, from lease file). Client may not know that, | ||
53 | // and may not have UDP socket listening on that IP! | ||
54 | // We should never unicast to payload->yiaddr! | ||
55 | // payload->ciaddr, OTOH, comes from client's request packet, | ||
56 | // and can be used. | ||
57 | |||
58 | if (force_broadcast | ||
59 | || (payload->flags & htons(BROADCAST_FLAG)) | ||
60 | || !payload->ciaddr | ||
61 | ) { | ||
62 | DEBUG("broadcasting packet to client"); | ||
47 | ciaddr = INADDR_BROADCAST; | 63 | ciaddr = INADDR_BROADCAST; |
48 | chaddr = MAC_BCAST_ADDR; | 64 | chaddr = MAC_BCAST_ADDR; |
49 | } else if (payload->ciaddr) { | 65 | } else { |
50 | DEBUG("unicasting packet to client ciaddr"); | 66 | DEBUG("unicasting packet to client ciaddr"); |
51 | ciaddr = payload->ciaddr; | 67 | ciaddr = payload->ciaddr; |
52 | chaddr = payload->chaddr; | 68 | chaddr = payload->chaddr; |
53 | } else if (payload->flags & htons(BROADCAST_FLAG)) { | ||
54 | DEBUG("broadcasting packet to client (requested)"); | ||
55 | ciaddr = INADDR_BROADCAST; | ||
56 | chaddr = MAC_BCAST_ADDR; | ||
57 | } else { | ||
58 | DEBUG("unicasting packet to client yiaddr"); | ||
59 | ciaddr = payload->yiaddr; | ||
60 | chaddr = payload->chaddr; | ||
61 | } | 69 | } |
70 | |||
62 | return udhcp_send_raw_packet(payload, | 71 | return udhcp_send_raw_packet(payload, |
63 | /*src*/ server_config.server, SERVER_PORT, | 72 | /*src*/ server_config.server, SERVER_PORT, |
64 | /*dst*/ ciaddr, CLIENT_PORT, chaddr, | 73 | /*dst*/ ciaddr, CLIENT_PORT, chaddr, |
@@ -118,17 +127,18 @@ int FAST_FUNC send_offer(struct dhcpMessage *oldpacket) | |||
118 | struct dhcpOfferedAddr *lease; | 127 | struct dhcpOfferedAddr *lease; |
119 | 128 | ||
120 | lease = find_lease_by_chaddr(oldpacket->chaddr); | 129 | lease = find_lease_by_chaddr(oldpacket->chaddr); |
121 | /* the client is in our lease/offered table */ | 130 | /* The client is in our lease/offered table */ |
122 | if (lease) { | 131 | if (lease) { |
123 | signed_leasetime_t tmp = lease->expires - time(NULL); | 132 | signed_leasetime_t tmp = lease->expires - time(NULL); |
124 | if (tmp >= 0) | 133 | if (tmp >= 0) |
125 | lease_time_aligned = tmp; | 134 | lease_time_aligned = tmp; |
126 | packet.yiaddr = lease->yiaddr; | 135 | packet.yiaddr = lease->yiaddr; |
127 | /* Or the client has requested an ip */ | 136 | } |
128 | } else if ((req = get_option(oldpacket, DHCP_REQUESTED_IP)) != NULL | 137 | /* Or the client has requested an IP */ |
129 | /* Don't look here (ugly hackish thing to do) */ | 138 | else if ((req = get_option(oldpacket, DHCP_REQUESTED_IP)) != NULL |
139 | /* (read IP) */ | ||
130 | && (move_from_unaligned32(req_align, req), 1) | 140 | && (move_from_unaligned32(req_align, req), 1) |
131 | /* and the ip is in the lease range */ | 141 | /* and the IP is in the lease range */ |
132 | && ntohl(req_align) >= server_config.start_ip | 142 | && ntohl(req_align) >= server_config.start_ip |
133 | && ntohl(req_align) <= server_config.end_ip | 143 | && ntohl(req_align) <= server_config.end_ip |
134 | /* and is not already taken/offered */ | 144 | /* and is not already taken/offered */ |
@@ -137,9 +147,10 @@ int FAST_FUNC send_offer(struct dhcpMessage *oldpacket) | |||
137 | || lease_expired(lease)) | 147 | || lease_expired(lease)) |
138 | ) { | 148 | ) { |
139 | packet.yiaddr = req_align; | 149 | packet.yiaddr = req_align; |
140 | /* otherwise, find a free IP */ | 150 | } |
141 | } else { | 151 | /* Otherwise, find a free IP */ |
142 | packet.yiaddr = find_free_or_expired_address(); | 152 | else { |
153 | packet.yiaddr = find_free_or_expired_address(oldpacket->chaddr); | ||
143 | } | 154 | } |
144 | 155 | ||
145 | if (!packet.yiaddr) { | 156 | if (!packet.yiaddr) { |