Skip to content

Commit 1e84213

Browse files
committed
dhcp6: make dhcp6_option_parse_{address,pdprefix}() return -EINVAL when received address or prefix is refused
And then the caller ignores the error. Otherwise, `ret_liftime_valid` is not set even if they succeeds.
1 parent cf6c33b commit 1e84213

1 file changed

Lines changed: 36 additions & 30 deletions

File tree

src/libsystemd-network/dhcp6-option.c

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -376,8 +376,7 @@ int dhcp6_option_parse_status(DHCP6Option *option, size_t len) {
376376
return be16toh(statusopt->status);
377377
}
378378

379-
static int dhcp6_option_parse_address(DHCP6Option *option, DHCP6IA *ia,
380-
uint32_t *lifetime_valid) {
379+
static int dhcp6_option_parse_address(DHCP6Option *option, DHCP6IA *ia, uint32_t *ret_lifetime_valid) {
381380
DHCP6AddressOption *addr_option = (DHCP6AddressOption *)option;
382381
DHCP6Address *addr;
383382
uint32_t lt_valid, lt_pref;
@@ -390,16 +389,22 @@ static int dhcp6_option_parse_address(DHCP6Option *option, DHCP6IA *ia,
390389
lt_pref = be32toh(addr_option->iaaddr.lifetime_preferred);
391390

392391
if (lt_valid == 0 || lt_pref > lt_valid) {
393-
log_dhcp6_client(client, "Valid lifetime of an IA address is zero or preferred lifetime %d > valid lifetime %d",
392+
log_dhcp6_client(client,
393+
"Valid lifetime of an IA address is zero or "
394+
"preferred lifetime %"PRIu32" > valid lifetime %"PRIu32,
394395
lt_pref, lt_valid);
395-
396-
return 0;
396+
return -EINVAL;
397397
}
398398

399399
if (be16toh(option->len) + offsetof(DHCP6Option, data) > sizeof(*addr_option)) {
400400
r = dhcp6_option_parse_status((DHCP6Option *)addr_option->options, be16toh(option->len) + offsetof(DHCP6Option, data) - sizeof(*addr_option));
401-
if (r != 0)
402-
return r < 0 ? r: 0;
401+
if (r < 0)
402+
return r;
403+
if (r > 0) {
404+
log_dhcp6_client(client, "Non-zero status code '%s' for address is received",
405+
dhcp6_message_status_to_string(r));
406+
return -EINVAL;
407+
}
403408
}
404409

405410
addr = new0(DHCP6Address, 1);
@@ -411,13 +416,12 @@ static int dhcp6_option_parse_address(DHCP6Option *option, DHCP6IA *ia,
411416

412417
LIST_PREPEND(addresses, ia->addresses, addr);
413418

414-
*lifetime_valid = be32toh(addr->iaaddr.lifetime_valid);
419+
*ret_lifetime_valid = be32toh(addr->iaaddr.lifetime_valid);
415420

416421
return 0;
417422
}
418423

419-
static int dhcp6_option_parse_pdprefix(DHCP6Option *option, DHCP6IA *ia,
420-
uint32_t *lifetime_valid) {
424+
static int dhcp6_option_parse_pdprefix(DHCP6Option *option, DHCP6IA *ia, uint32_t *ret_lifetime_valid) {
421425
DHCP6PDPrefixOption *pdprefix_option = (DHCP6PDPrefixOption *)option;
422426
DHCP6Address *prefix;
423427
uint32_t lt_valid, lt_pref;
@@ -430,16 +434,22 @@ static int dhcp6_option_parse_pdprefix(DHCP6Option *option, DHCP6IA *ia,
430434
lt_pref = be32toh(pdprefix_option->iapdprefix.lifetime_preferred);
431435

432436
if (lt_valid == 0 || lt_pref > lt_valid) {
433-
log_dhcp6_client(client, "Valid lifetieme of a PD prefix is zero or preferred lifetime %d > valid lifetime %d",
437+
log_dhcp6_client(client,
438+
"Valid lifetieme of a PD prefix is zero or "
439+
"preferred lifetime %"PRIu32" > valid lifetime %"PRIu32,
434440
lt_pref, lt_valid);
435-
436-
return 0;
441+
return -EINVAL;
437442
}
438443

439444
if (be16toh(option->len) + offsetof(DHCP6Option, data) > sizeof(*pdprefix_option)) {
440445
r = dhcp6_option_parse_status((DHCP6Option *)pdprefix_option->options, be16toh(option->len) + offsetof(DHCP6Option, data) - sizeof(*pdprefix_option));
441-
if (r != 0)
442-
return r < 0 ? r: 0;
446+
if (r < 0)
447+
return r;
448+
if (r > 0) {
449+
log_dhcp6_client(client, "Non-zero status code '%s' for PD prefix is received",
450+
dhcp6_message_status_to_string(r));
451+
return -EINVAL;
452+
}
443453
}
444454

445455
prefix = new0(DHCP6Address, 1);
@@ -451,7 +461,7 @@ static int dhcp6_option_parse_pdprefix(DHCP6Option *option, DHCP6IA *ia,
451461

452462
LIST_PREPEND(addresses, ia->addresses, prefix);
453463

454-
*lifetime_valid = be32toh(prefix->iapdprefix.lifetime_valid);
464+
*ret_lifetime_valid = be32toh(prefix->iapdprefix.lifetime_valid);
455465

456466
return 0;
457467
}
@@ -483,8 +493,7 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_stat
483493
lt_t2 = be32toh(ia->ia_na.lifetime_t2);
484494

485495
if (lt_t1 && lt_t2 && lt_t1 > lt_t2) {
486-
log_dhcp6_client(client, "IA NA T1 %ds > T2 %ds",
487-
lt_t1, lt_t2);
496+
log_dhcp6_client(client, "IA NA T1 %"PRIu32"sec > T2 %"PRIu32"sec", lt_t1, lt_t2);
488497
return -EINVAL;
489498
}
490499

@@ -502,8 +511,7 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_stat
502511
lt_t2 = be32toh(ia->ia_pd.lifetime_t2);
503512

504513
if (lt_t1 && lt_t2 && lt_t1 > lt_t2) {
505-
log_dhcp6_client(client, "IA PD T1 %ds > T2 %ds",
506-
lt_t1, lt_t2);
514+
log_dhcp6_client(client, "IA PD T1 %"PRIu32"sec > T2 %"PRIu32"sec", lt_t1, lt_t2);
507515
return -EINVAL;
508516
}
509517

@@ -543,10 +551,9 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_stat
543551
}
544552

545553
r = dhcp6_option_parse_address(option, ia, &lt_valid);
546-
if (r < 0)
554+
if (r < 0 && r != -EINVAL)
547555
return r;
548-
549-
if (lt_valid < lt_min)
556+
if (r >= 0 && lt_valid < lt_min)
550557
lt_min = lt_valid;
551558

552559
break;
@@ -559,10 +566,9 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_stat
559566
}
560567

561568
r = dhcp6_option_parse_pdprefix(option, ia, &lt_valid);
562-
if (r < 0)
569+
if (r < 0 && r != -EINVAL)
563570
return r;
564-
565-
if (lt_valid < lt_min)
571+
if (r >= 0 && lt_valid < lt_min)
566572
lt_min = lt_valid;
567573

568574
break;
@@ -595,26 +601,26 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_stat
595601

596602
switch(iatype) {
597603
case SD_DHCP6_OPTION_IA_NA:
598-
if (!ia->ia_na.lifetime_t1 && !ia->ia_na.lifetime_t2) {
604+
if (!ia->ia_na.lifetime_t1 && !ia->ia_na.lifetime_t2 && lt_min != UINT32_MAX) {
599605
lt_t1 = lt_min / 2;
600606
lt_t2 = lt_min / 10 * 8;
601607
ia->ia_na.lifetime_t1 = htobe32(lt_t1);
602608
ia->ia_na.lifetime_t2 = htobe32(lt_t2);
603609

604-
log_dhcp6_client(client, "Computed IA NA T1 %ds and T2 %ds as both were zero",
610+
log_dhcp6_client(client, "Computed IA NA T1 %"PRIu32"sec and T2 %"PRIu32"sec as both were zero",
605611
lt_t1, lt_t2);
606612
}
607613

608614
break;
609615

610616
case SD_DHCP6_OPTION_IA_PD:
611-
if (!ia->ia_pd.lifetime_t1 && !ia->ia_pd.lifetime_t2) {
617+
if (!ia->ia_pd.lifetime_t1 && !ia->ia_pd.lifetime_t2 && lt_min != UINT32_MAX) {
612618
lt_t1 = lt_min / 2;
613619
lt_t2 = lt_min / 10 * 8;
614620
ia->ia_pd.lifetime_t1 = htobe32(lt_t1);
615621
ia->ia_pd.lifetime_t2 = htobe32(lt_t2);
616622

617-
log_dhcp6_client(client, "Computed IA PD T1 %ds and T2 %ds as both were zero",
623+
log_dhcp6_client(client, "Computed IA PD T1 %"PRIu32"sec and T2 %"PRIu32"sec as both were zero",
618624
lt_t1, lt_t2);
619625
}
620626

0 commit comments

Comments
 (0)