Lines 164-171
dhcp_printoptions(const struct dhcpcd_ctx *ctx,
Link Here
|
164 |
} |
164 |
} |
165 |
} |
165 |
} |
166 |
|
166 |
|
167 |
#define get_option_raw(ctx, bootp, bootp_len, opt) \ |
|
|
168 |
get_option((ctx), (bootp), (bootp_len), NULL) |
169 |
static const uint8_t * |
167 |
static const uint8_t * |
170 |
get_option(struct dhcpcd_ctx *ctx, |
168 |
get_option(struct dhcpcd_ctx *ctx, |
171 |
const struct bootp *bootp, size_t bootp_len, |
169 |
const struct bootp *bootp, size_t bootp_len, |
Lines 3275-3300
is_packet_udp_bootp(void *packet, size_t plen)
Link Here
|
3275 |
{ |
3273 |
{ |
3276 |
struct ip *ip = packet; |
3274 |
struct ip *ip = packet; |
3277 |
size_t ip_hlen; |
3275 |
size_t ip_hlen; |
3278 |
struct udphdr *udp; |
3276 |
struct udphdr udp; |
3279 |
|
3277 |
|
3280 |
if (sizeof(*ip) > plen) |
3278 |
if (plen < sizeof(*ip)) |
3281 |
return false; |
3279 |
return false; |
3282 |
|
3280 |
|
3283 |
if (ip->ip_v != IPVERSION || ip->ip_p != IPPROTO_UDP) |
3281 |
if (ip->ip_v != IPVERSION || ip->ip_p != IPPROTO_UDP) |
3284 |
return false; |
3282 |
return false; |
3285 |
|
3283 |
|
3286 |
/* Sanity. */ |
3284 |
/* Sanity. */ |
3287 |
if (ntohs(ip->ip_len) != plen) |
3285 |
if (ntohs(ip->ip_len) > plen) |
3288 |
return false; |
3286 |
return false; |
3289 |
|
3287 |
|
3290 |
ip_hlen = (size_t)ip->ip_hl * 4; |
3288 |
ip_hlen = (size_t)ip->ip_hl * 4; |
|
|
3289 |
if (ip_hlen < sizeof(*ip)) |
3290 |
return false; |
3291 |
|
3291 |
/* Check we have a UDP header and BOOTP. */ |
3292 |
/* Check we have a UDP header and BOOTP. */ |
3292 |
if (ip_hlen + sizeof(*udp) + offsetof(struct bootp, vend) > plen) |
3293 |
if (ip_hlen + sizeof(udp) + offsetof(struct bootp, vend) > plen) |
|
|
3294 |
return false; |
3295 |
|
3296 |
/* Sanity. */ |
3297 |
memcpy(&udp, (char *)ip + ip_hlen, sizeof(udp)); |
3298 |
if (ntohs(udp.uh_ulen) < sizeof(udp)) |
3299 |
return false; |
3300 |
if (ip_hlen + ntohs(udp.uh_ulen) > plen) |
3293 |
return false; |
3301 |
return false; |
3294 |
|
3302 |
|
3295 |
/* Check it's to and from the right ports. */ |
3303 |
/* Check it's to and from the right ports. */ |
3296 |
udp = (struct udphdr *)(void *)((char *)ip + ip_hlen); |
3304 |
if (udp.uh_dport != htons(BOOTPC) || udp.uh_sport != htons(BOOTPS)) |
3297 |
if (udp->uh_dport != htons(BOOTPC) || udp->uh_sport != htons(BOOTPS)) |
|
|
3298 |
return false; |
3305 |
return false; |
3299 |
|
3306 |
|
3300 |
return true; |
3307 |
return true; |
Lines 3313-3319
checksums_valid(void *packet,
Link Here
|
3313 |
}; |
3320 |
}; |
3314 |
size_t ip_hlen; |
3321 |
size_t ip_hlen; |
3315 |
uint16_t udp_len, uh_sum; |
3322 |
uint16_t udp_len, uh_sum; |
3316 |
struct udphdr *udp; |
3323 |
struct udphdr udp; |
|
|
3324 |
char *udpp, *uh_sump; |
3317 |
uint32_t csum; |
3325 |
uint32_t csum; |
3318 |
|
3326 |
|
3319 |
if (from != NULL) |
3327 |
if (from != NULL) |
Lines 3324-3344
checksums_valid(void *packet,
Link Here
|
3324 |
return false; |
3332 |
return false; |
3325 |
|
3333 |
|
3326 |
if (flags & BPF_PARTIALCSUM) |
3334 |
if (flags & BPF_PARTIALCSUM) |
3327 |
return 0; |
3335 |
return true; |
3328 |
|
3336 |
|
3329 |
udp = (struct udphdr *)(void *)((char *)ip + ip_hlen); |
3337 |
udpp = (char *)ip + ip_hlen; |
3330 |
if (udp->uh_sum == 0) |
3338 |
memcpy(&udp, udpp, sizeof(udp)); |
3331 |
return 0; |
3339 |
if (udp.uh_sum == 0) |
|
|
3340 |
return true; |
3332 |
|
3341 |
|
3333 |
/* UDP checksum is based on a pseudo IP header alongside |
3342 |
/* UDP checksum is based on a pseudo IP header alongside |
3334 |
* the UDP header and payload. */ |
3343 |
* the UDP header and payload. */ |
3335 |
udp_len = ntohs(udp->uh_ulen); |
3344 |
udp_len = ntohs(udp.uh_ulen); |
3336 |
uh_sum = udp->uh_sum; |
3345 |
uh_sum = udp.uh_sum; |
3337 |
udp->uh_sum = 0; |
3346 |
|
3338 |
pseudo_ip.ip_len = udp->uh_ulen; |
3347 |
/* Need to zero the UDP sum in the packet for the checksum to work. */ |
|
|
3348 |
uh_sump = udpp + offsetof(struct udphdr, uh_sum); |
3349 |
memset(uh_sump, 0, sizeof(udp.uh_sum)); |
3350 |
|
3351 |
pseudo_ip.ip_len = udp.uh_ulen; |
3339 |
csum = 0; |
3352 |
csum = 0; |
3340 |
in_cksum(&pseudo_ip, sizeof(pseudo_ip), &csum); |
3353 |
in_cksum(&pseudo_ip, sizeof(pseudo_ip), &csum); |
3341 |
csum = in_cksum(udp, udp_len, &csum); |
3354 |
csum = in_cksum(udpp, udp_len, &csum); |
|
|
3355 |
|
3356 |
/* Put the checksum back. */ |
3357 |
memcpy(uh_sump, &uh_sum, sizeof(udp.uh_sum)); |
3358 |
|
3342 |
return csum == uh_sum; |
3359 |
return csum == uh_sum; |
3343 |
} |
3360 |
} |
3344 |
|
3361 |
|