HenriWahl / dhcpy6d

MAC address aware DHCPv6 server written in Python
https://dhcpy6d.de
GNU General Public License v2.0
94 stars 27 forks source link

dhcpy6d does not assign IPv6 addresses if 'call' (ndp) output is incomplete #13

Closed n1000 closed 6 years ago

n1000 commented 6 years ago

I recently ran into an issue where dhcpy6d was unable to assign an IPv6 address due to the ndp output having unexpected values.

Console dump:

2017-10-28 14:59:11,628 dhcpy6d INFO SOLICIT | TransactionID: cd64a8 | Answer: normal | ClientLLIP: fe80:0000:0000:0000:a90c:7d95:0a0e:cf5a | Counter: 5 | DUID: 000100011dea9c1f3052cb832e05 | DUIDType: 1 | Hostname: yttrium | IAID: 043052cb | IA_Option: 3 | ID: cd64a8 | Interface: em2 | LastMessageReceivedType: 1 | OptionsRequest: [17, 23, 24, 39] | VendorClassData: MSFT 5.0 | VendorClassEN: 311
Traceback (most recent call last):
  File "./dhcpy6d", line 683, in CollectMACs
    f[NC[OS]['mac']] = CorrectMAC(f[NC[OS]['mac']])
  File "/home/nathan/src/dhcpy6d/dhcpy6/Helpers.py", line 138, in CorrectMAC
    decompressed = map(lambda m: '%02x' % (int(m, 16)), mac.split(':'))
  File "/home/nathan/src/dhcpy6d/dhcpy6/Helpers.py", line 138, in <lambda>
    decompressed = map(lambda m: '%02x' % (int(m, 16)), mac.split(':'))
ValueError: invalid literal for int() with base 16: '(incomplete)'
2017-10-28 14:59:11,639 dhcpy6d ERROR CollectMACs(): invalid literal for int() with base 16: '(incomplete)'
2017-10-28 14:59:11,639 dhcpy6d INFO REPLY | TransactionID: cd64a8 | Options: [13]
Traceback (most recent call last):
  File "./dhcpy6d", line 683, in CollectMACs
    f[NC[OS]['mac']] = CorrectMAC(f[NC[OS]['mac']])
  File "/home/nathan/src/dhcpy6d/dhcpy6/Helpers.py", line 138, in CorrectMAC
    decompressed = map(lambda m: '%02x' % (int(m, 16)), mac.split(':'))
  File "/home/nathan/src/dhcpy6d/dhcpy6/Helpers.py", line 138, in <lambda>
    decompressed = map(lambda m: '%02x' % (int(m, 16)), mac.split(':'))
ValueError: invalid literal for int() with base 16: '(incomplete)'
2017-10-28 14:59:11,650 dhcpy6d ERROR CollectMACs(): invalid literal for int() with base 16: '(incomplete)'

Offending output line in ndp output:

$ /usr/sbin/ndp -a -n
Neighbor                             Linklayer Address   Netif Expire    S Flags
...
fd00:0:1::7                          (incomplete)          em2 expired   I  2
...

If I delete the entry, things work fine afterwards:

$ /usr/sbin/ndp -d fd00:0:1::7
fd00:0:1::7 (fd00:0:1::) deleted

I think this incomplete entry was formed by pinging before the station had been assigned the address.

n1000 commented 6 years ago

Note I'm not actually using the mac address identification feature (identification = duid).

I'm using tag 0.5 from Git, on OpenBSD 6.2.

Thanks, Nate

n1000 commented 6 years ago

Something like this would probably fix the issue, but now I'm unable to get my ndp output to contain the '(incomplete)' line :(

diff --git a/dhcpy6d b/dhcpy6d
index 5f36865..e3d7d10 100755
--- a/dhcpy6d
+++ b/dhcpy6d
@@ -904,6 +904,8 @@ def collect_macs():
                 if f[NC[OS]['dev']] in cfg.INTERFACE and len(f) >= NC[OS]['len'] :
                     # get rid of %interface
                     f[NC[OS]['llip']] = decompress_ip6(f[NC[OS]['llip']].split('%')[0])
+                    if f[NC[OS]['mac']] == '(incomplete)':
+                        continue
                     # correct maybe shortened MAC
                     f[NC[OS]['mac']] = correct_mac(f[NC[OS]['mac']])
                     # put non yet existing LLIPs into dictionary - if they have MACs
HenriWahl commented 6 years ago

Thanks for the hint and nice to see it running on OpenBSD 6.2 :-) I applied your fix and it will come with the latest push.

n1000 commented 6 years ago

So far I've tried WIDE dhcpdv6, ISC DHCPv6, and now dhcpy6d. dhcpy6d seems to be the only one that can get me the configuration that I want (static ULA + dynamically prefixed global addresses assigned by the DHCP server).

Thanks!