1
1
from enum import Enum
2
2
import ipaddress
3
3
import json
4
+ import struct
5
+ import binascii
4
6
import os
5
7
from os import path
6
8
from select import select
@@ -30,7 +32,7 @@ class DHCPClientError(Exception):
30
32
def _nspopen_wrapper (netns ):
31
33
return lambda * args , ** kwargs : NSPopen (netns , * args , ** kwargs )
32
34
class DHCPClient :
33
- def __init__ (self , iface , v6 = False , once = False , event_listener = None ):
35
+ def __init__ (self , iface , v6 = False , once = False , hostname = None , event_listener = None ):
34
36
self .iface = iface
35
37
self .v6 = v6
36
38
self .once = once
@@ -47,13 +49,27 @@ def __init__(self, iface, v6=False, once=False, event_listener=None):
47
49
bin_path = '/usr/bin/udhcpc6' if v6 else '/sbin/udhcpc'
48
50
cmdline = [bin_path , '-s' , HANDLER_SCRIPT , '-i' , iface ['ifname' ], '-f' ]
49
51
cmdline .append ('-q' if once else '-R' )
52
+ if hostname :
53
+ cmdline .append ('-x' )
54
+ if v6 :
55
+ # TODO: We encode the fqdn for DHCPv6 because udhcpc6 seems to be broken
56
+ # flags: S bit set (see RFC4704)
57
+ enc_hostname = hostname .encode ('utf-8' )
58
+ enc_hostname = struct .pack ('BB' , 0b0001 , len (enc_hostname )) + enc_hostname
59
+ enc_hostname = binascii .hexlify (enc_hostname ).decode ('ascii' )
60
+ hostname_opt = f'0x27:{ enc_hostname } '
61
+ else :
62
+ hostname_opt = f'hostname:{ hostname } '
63
+ cmdline .append (hostname_opt )
50
64
if not v6 :
51
65
cmdline += ['-V' , VENDOR_ID ]
52
66
53
67
self ._suffix = '6' if v6 else ''
54
68
self ._event_queue = posix_ipc .MessageQueue (f'/udhcpc{ self ._suffix } _{ iface ["address" ].replace (":" , "_" )} ' , \
55
69
flags = os .O_CREAT | os .O_EXCL )
56
70
self .proc = Popen (cmdline , env = {'EVENT_QUEUE' : self ._event_queue .name })
71
+ if hostname :
72
+ logger .debug ('[udhcpc%s#%d] using hostname "%s"' , self ._suffix , self .proc .pid , hostname )
57
73
58
74
self ._has_lease = threading .Event ()
59
75
self .ip = None
@@ -110,7 +126,7 @@ def finish(self, timeout=5):
110
126
if self ._shutdown_event .is_set ():
111
127
return
112
128
113
- if self .proc .returncode != None and (not self .once or self .proc .returncode != 0 ):
129
+ if self .proc .returncode is not None and (not self .once or self .proc .returncode != 0 ):
114
130
raise DHCPClientError (f'udhcpc{ self ._suffix } exited early with code { self .proc .returncode } ' )
115
131
if self .once :
116
132
self .await_ip ()
0 commit comments