diff options
Diffstat (limited to 'networking/udhcp/clientpacket.c')
-rw-r--r-- | networking/udhcp/clientpacket.c | 25 |
1 files changed, 13 insertions, 12 deletions
diff --git a/networking/udhcp/clientpacket.c b/networking/udhcp/clientpacket.c index 03473109f..b8190ba43 100644 --- a/networking/udhcp/clientpacket.c +++ b/networking/udhcp/clientpacket.c | |||
@@ -167,39 +167,40 @@ int send_release(uint32_t server, uint32_t ciaddr) | |||
167 | } | 167 | } |
168 | 168 | ||
169 | 169 | ||
170 | /* return -1 on errors that are fatal for the socket, -2 for those that aren't */ | 170 | /* Returns -1 on errors that are fatal for the socket, -2 for those that aren't */ |
171 | int get_raw_packet(struct dhcpMessage *payload, int fd) | 171 | int get_raw_packet(struct dhcpMessage *payload, int fd) |
172 | { | 172 | { |
173 | int bytes; | 173 | int bytes; |
174 | struct udp_dhcp_packet packet; | 174 | struct udp_dhcp_packet packet; |
175 | uint16_t check; | 175 | uint16_t check; |
176 | 176 | ||
177 | memset(&packet, 0, sizeof(struct udp_dhcp_packet)); | 177 | memset(&packet, 0, sizeof(packet)); |
178 | bytes = read(fd, &packet, sizeof(struct udp_dhcp_packet)); | 178 | bytes = safe_read(fd, &packet, sizeof(packet)); |
179 | if (bytes < 0) { | 179 | if (bytes < 0) { |
180 | DEBUG("Cannot read on raw listening socket - ignoring"); | 180 | DEBUG("Cannot read on raw listening socket - ignoring"); |
181 | sleep(1); /* possible down interface, looping condition */ | 181 | sleep(1); /* possible down interface, looping condition */ |
182 | return -1; | 182 | return bytes; /* returns -1 */ |
183 | } | 183 | } |
184 | 184 | ||
185 | if (bytes < (int) (sizeof(struct iphdr) + sizeof(struct udphdr))) { | 185 | if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp))) { |
186 | DEBUG("Message too short, ignoring"); | 186 | DEBUG("Packet is too short, ignoring"); |
187 | return -2; | 187 | return -2; |
188 | } | 188 | } |
189 | 189 | ||
190 | if (bytes < ntohs(packet.ip.tot_len)) { | 190 | if (bytes < ntohs(packet.ip.tot_len)) { |
191 | DEBUG("Truncated packet"); | 191 | /* packet is bigger than sizeof(packet), we did partial read */ |
192 | DEBUG("Oversized packet, ignoring"); | ||
192 | return -2; | 193 | return -2; |
193 | } | 194 | } |
194 | 195 | ||
195 | /* ignore any extra garbage bytes */ | 196 | /* ignore any extra garbage bytes */ |
196 | bytes = ntohs(packet.ip.tot_len); | 197 | bytes = ntohs(packet.ip.tot_len); |
197 | 198 | ||
198 | /* Make sure its the right packet for us, and that it passes sanity checks */ | 199 | /* make sure its the right packet for us, and that it passes sanity checks */ |
199 | if (packet.ip.protocol != IPPROTO_UDP || packet.ip.version != IPVERSION | 200 | if (packet.ip.protocol != IPPROTO_UDP || packet.ip.version != IPVERSION |
200 | || packet.ip.ihl != (sizeof(packet.ip) >> 2) | 201 | || packet.ip.ihl != (sizeof(packet.ip) >> 2) |
201 | || packet.udp.dest != htons(CLIENT_PORT) | 202 | || packet.udp.dest != htons(CLIENT_PORT) |
202 | || bytes > (int) sizeof(struct udp_dhcp_packet) | 203 | /* || bytes > (int) sizeof(packet) - can't happen */ |
203 | || ntohs(packet.udp.len) != (uint16_t)(bytes - sizeof(packet.ip)) | 204 | || ntohs(packet.udp.len) != (uint16_t)(bytes - sizeof(packet.ip)) |
204 | ) { | 205 | ) { |
205 | DEBUG("Unrelated/bogus packet"); | 206 | DEBUG("Unrelated/bogus packet"); |
@@ -211,12 +212,12 @@ int get_raw_packet(struct dhcpMessage *payload, int fd) | |||
211 | packet.ip.check = 0; | 212 | packet.ip.check = 0; |
212 | if (check != udhcp_checksum(&packet.ip, sizeof(packet.ip))) { | 213 | if (check != udhcp_checksum(&packet.ip, sizeof(packet.ip))) { |
213 | DEBUG("Bad IP header checksum, ignoring"); | 214 | DEBUG("Bad IP header checksum, ignoring"); |
214 | return -1; | 215 | return -2; |
215 | } | 216 | } |
216 | 217 | ||
217 | /* verify UDP checksum. IP header has to be modified for this */ | 218 | /* verify UDP checksum. IP header has to be modified for this */ |
218 | memset(&packet.ip, 0, offsetof(struct iphdr, protocol)); | 219 | memset(&packet.ip, 0, offsetof(struct iphdr, protocol)); |
219 | /* fields which are not memset: protocol, check, saddr, daddr */ | 220 | /* ip.xx fields which are not memset: protocol, check, saddr, daddr */ |
220 | packet.ip.tot_len = packet.udp.len; /* yes, this is needed */ | 221 | packet.ip.tot_len = packet.udp.len; /* yes, this is needed */ |
221 | check = packet.udp.check; | 222 | check = packet.udp.check; |
222 | packet.udp.check = 0; | 223 | packet.udp.check = 0; |
@@ -228,7 +229,7 @@ int get_raw_packet(struct dhcpMessage *payload, int fd) | |||
228 | memcpy(payload, &packet.data, bytes - (sizeof(packet.ip) + sizeof(packet.udp))); | 229 | memcpy(payload, &packet.data, bytes - (sizeof(packet.ip) + sizeof(packet.udp))); |
229 | 230 | ||
230 | if (payload->cookie != htonl(DHCP_MAGIC)) { | 231 | if (payload->cookie != htonl(DHCP_MAGIC)) { |
231 | bb_error_msg("received bogus message (bad magic) - ignoring"); | 232 | bb_error_msg("received bogus message (bad magic), ignoring"); |
232 | return -2; | 233 | return -2; |
233 | } | 234 | } |
234 | DEBUG("Got valid DHCP packet"); | 235 | DEBUG("Got valid DHCP packet"); |