
    dx:                         d dl Z d dlZd dlZd dlZd dlmc mZ d dlmZ d dl	m
Z
 d dlmZ d dlmZmZmZmZmZmZmZ dZd Z G d d	e      Zd
 Zd Zd Zd Zd Zd Zd Zy)    N)	DhcpError)
get_osutil)KNOWN_WIRESERVER_IP)hex_dump	hex_dump2	hex_dump3compare_bytes
str_to_ordunpack_big_endianint_to_ip4_addr10813FA8c                      t               S N)DhcpHandler     =/usr/lib/python3/dist-packages/azurelinuxagent/common/dhcp.pyget_dhcp_handlerr   $   s
    =r   c                   T    e Zd ZdZd Zd Zd Zed        Zed        Z	d Z
d Zd	 Zy
)r   z?
    Azure use DHCP option 245 to pass endpoint ip to VMs.
    c                 h    t               | _        d | _        d | _        d | _        d| _        d| _        y )NF)r   osutilendpointgatewayroutes_request_broadcast
skip_cacheselfs    r   __init__zDhcpHandler.__init__-   s/     l"'r   c                 v    | j                   s| j                  ry| j                          | j                          y)z{
        Send dhcp request
        Configure default gateway and routes
        Save wire server endpoint if found
        N)wireserver_route_existsdhcp_cache_existssend_dhcp_reqconf_routesr   s    r   runzDhcpHandler.run5   s0     ''4+A+Ar   c                 L   | j                   j                         }|dk(  s|dk(  rt        j                  d       t	        j
                  d       t        j                  d       | j                   j                          | j                   j                         }|dk(  ry|dk(  ryy)z;
        Wait for network stack to be initialized.
         0.0.0.0zWaiting for network.
   zTry to start network interface.N)r   get_ip4_addrloggerinfotimesleepstart_network)r   ipv4s     r   wait_for_networkzDhcpHandler.wait_for_networkA   s{     {{'')bjDI-KK./JJrNKK9:KK%%';;++-D bjDI-r   c                    d}t        j                  dj                  t                     	 | j                  j                         }t        d |D              rEt        | _        d| _        d| _	        d}t        j                  dj                  t                     |S t        j                  dj                  t                     	 |S # t        $ r4}t        j                  dj                  t        |             Y d}~|S d}~ww xY w)	z
        Determine whether a route to the known wireserver
        ip already exists, and if so use that as the endpoint.
        This is true when running in a virtual network.
        :return: True if a route to KNOWN_WIRESERVER_IP exists.
        FzTest for route to {0}c              3   ,   K   | ]  }t         |v   y wr   )KNOWN_WIRESERVER_IP_ENTRY).0routes     r   	<genexpr>z6DhcpHandler.wireserver_route_exists.<locals>.<genexpr>Y   s     QE-6Qs   NTzRoute to {0} existszNo route exists to {0}z4Could not determine whether route exists to {0}: {1})r+   r,   formatr   r   read_route_tableanyr   r   r   warn	Exceptionerror)r   route_existsroute_tablees       r   r!   z#DhcpHandler.wireserver_route_existsM   s     +223FGH	-++668KQ[QQ !4#"#1889LMN  4;;<OPQ   	-LLFMM',- - 	-s   A/C (C 	D)D  Dc                     | j                   ryd}t        j                  d       | j                  j	                         }|	|| _        d}t        j                  dj                  |             |S )z
        Check whether the dhcp options cache exists and contains the
        wireserver endpoint, unless skip_cache is True.
        :return: True if the cached endpoint was found in the dhcp lease
        FzChecking for dhcp lease cacheTzCache exists [{0}])r   r+   r,   r   get_dhcp_lease_endpointr   r8   )r   existscached_endpoints      r   r"   zDhcpHandler.dhcp_cache_existsj   sa     ??34++==?&+DMF(//78r   c                    t        j                  d       t        j                  d| j                         t        j                  d| j                         | j                  A| j                  j                         r'| j                  j                  dd| j                         | j                  8| j                  D ](  }| j                  j                  |d   |d   |d          * y y )NzConfigure routeszGateway:{0}z
Routes:{0}r         )r+   r,   r   r   r   is_missing_default_route	route_add)r   r6   s     r   r$   zDhcpHandler.conf_routes~   s    &'M4<<0L$++.<<#(L(L(NKK!!!Q5;;" D%%eAha%(CD #r   c                    g d}|D ]7  }	 | j                   j                          t        |      }t        ||       |c S  y # t        $ r }t        j                  d|       Y d }~nd }~ww xY wt        j                  |       })N)r   r)      <   rL   z Failed to send DHCP request: {0})	r   allow_dhcp_broadcastsocket_sendvalidate_dhcp_respr   r+   r;   r-   r.   )r   request__waiting_duration__durationresponser@   s         r   _send_dhcp_reqzDhcpHandler._send_dhcp_req   s}    2, 	!HC002&w/"7H5	!   C>BBCJJx s   2A	A+A&&A+c                 T   | j                   j                         }|s!t        j                  d       t        | _        y	 t        j                  d       | j                   j                         }t        || j                        }| j                  sd| _        | j                   j                         }| j                   j                         }|r| j                   j                  |       | j                   j                         r| j                   j                          | j                  |      }| j                   j                         r| j                   j                          |r| j                   j!                  |       |t#        d      t%        |      \  | _        | _        | _        y)z,
        Check if DHCP is available
        z!send_dhcp_req: DHCP not availableNzSend dhcp requestTz Failed to receive dhcp response.)r   is_dhcp_availabler+   r,   r   r   get_mac_addrbuild_dhcp_requestr   rH   get_if_nameset_route_for_dhcp_broadcastis_dhcp_enabledstop_dhcp_servicerT   start_dhcp_serviceremove_route_for_dhcp_broadcastr   parse_dhcp_respr   r   )r   dhcp_availablemac_addrreqmissing_default_routeifnameresps          r   r#   zDhcpHandler.send_dhcp_req   sF    ++779KK;</DM	 	'(;;++- !4+B+BC&&&*D# !% D D F((* KK44V< ;;&&(KK))+""3';;&&(KK**, KK77?<>??3B43H0t|T[r   N)__name__
__module____qualname____doc__r   r%   r1   propertyr!   r"   r$   rT   r#   r   r   r   r   r   (   sO     

.  8  &	D/Ir   r   c           	      t   t        |      }|dk  rt        j                  d|       yt        j                  dt	        |             t        j                  dt        ||             t        | |dd      s8t        j                  dt        | dd      t        |dd             t        d	      t        | |dd      s8t        j                  d
t        | dd      t        |dd             t        d      t        | |dd      s8t        j                  dt        | dd      t        |dd             t        d      y )N   z.HandleDhcpResponse: Too few bytes received:{0}FzBytesReceived:{0}zDHCP response:{0}      z'Cookie not match:
send={0},
receive={1}z1Cookie in dhcp respones doesn't match the requestz.TransactionID not match:
send={0},
receive={1}z8TransactionID in dhcp respones doesn't match the request      z,Mac Address not match:
send={0},
receive={1}z3Mac Addr in dhcp respones doesn't match the request)	lenr+   r=   verbosehexr   r	   r   r   )rP   rS   
bytes_recvs      r   rO   rO      s/   XJDE	!
NN&J8
NN&:(FG
 (D!4B $2 43	5 KLL(Aq1I !Q/ 1a0	2  4 5 	5 (D!4G $2 43	5  4 5 	5	 5r   c                    t        j                  dt        |      t        |             g }|dk  rt        j                  d|       |dz   }|||z   dz   k  r}t	        | |         }|dz   dz  dz	  }ddd	|z
  z  z  }	|d
z  }t        | ||      }
|
d	|dz  z
  z  }
|
|	z  }
||z  }t        | |d      }|dz  }|j                  |
|	|f       |||z   dz   k  r}|||z   dz   k7  rt        j                  d       |S )Nz%Routes at offset: {0} with length:{1}   Data too small for option:{0}rG      i   l        rF      rn   zUnable to parse routes)r+   rr   rs   r=   r
   r   append)rS   optionilengthrt   r   jmask_len_bitsmask_len_bytesmasknetr   s               r   parse_router      s&   
NN:CFv; Fz4f=	AA
q6zA~
"8A;/)A-39ZB,>?@	Q!^<nq(()t	^#Ha3	QsD'*+ q6zA~
 	QZ!^-.Mr   c                     |dz   |k  r8|dk7  rt        j                  d       y t        | |dz   d      }t        |      }|S t        j                  d|       y )Nrv   rn   z'Endpoint or Default Gateway not 4 bytesrG   rw   )r+   r=   r   r   )rS   r}   r~   r   rt   addrip_addrs          r   parse_ip_addrr     sX    1uzQ;LLBC 1q5!4!$'4f=r   c                    t        j                  d       t        |       }d}d}d}d}||k  rBt        | |         }d}|dz   |k  rt        | |dz            }t        j                  dt	        |      t	        |      t	        |             |dk(  r t        j                  dt	        |             n|d	k(  rt        | ||||      }n|d
k(  r0t        | ||||      }t        j                  d|t	        |             nh|dk(  r0t        | ||||      }t        j                  d|t	        |             n3t        j                  dt	        |      t	        |      t	        |             ||dz   z  }||k  rB|||fS )zL
    Parse DHCP response:
    Returns endpoint server or None on error.
    zparse Dhcp ResponseN   r   rF   z-DHCP option {0} at offset:{1} with length:{2}   zDHCP packet ended at offset:{0}   ry   zDefault gateway:{0}, at {1}   z(Azure wire protocol endpoint:{0}, at {1}z/Skipping DHCP option:{0} at {1} with length {2}rG   )r+   rr   rq   r
   rs   r   r   )rS   rt   r   r   r   r~   r}   r   s           r   r_   r_     si   
 NN()XJHGF 	A
j.HQK(EZQ0FF6{CFCK	9S=NN<c!fEs] 61fjIFq[#HfaLGNN8'3q6Js]$Xvq&*MHNNE#q6# NNLv;AF=	VaZ/ j.0 Wf$$r   c                    d }	 t        j                   t         j                  t         j                  t         j                        }|j	                  t         j
                  t         j                  d       |j	                  t         j
                  t         j                  d       |j                  d       |j                  | d       |j                  d       t        j                  d       |j                  d      }|||j                          S S # t        $ r}t!        dj#                  |            d }~ww xY w# ||j                          w w xY w)NrF   )r(   D   )z<broadcast>C   r)   z;Send DHCP request: Setting socket.timeout=10, entering recvi   z{0})socketAF_INET
SOCK_DGRAMIPPROTO_UDP
setsockopt
SOL_SOCKETSO_BROADCASTSO_REUSEADDRbindsendto
settimeoutr+   rr   recvcloseIOErrorr   r8   )rP   sockrS   r@   s       r   rN   rN   <  s   D}}V^^V->->#//1))6+>+>B))6+>+>B		/"G01 ' 	(99T? JJL   )Q(() JJL s$   C:D 	D:D55D::D= =Ec           	         dgdz  }t               }t        dd      D ]  }g d|   ||<    t        dd      D ]  }t        ||         |d|z   <    t        j                  dt        |      t        |dd      fz         |rd|d<   t        dd	      D ]  }t        | |         |d
|z   <    t        dd      D ]  }g d|   |d|z   <    t        j                  d|      S )z$
    Build DHCP request string.
    r      ry   )rF   rF   rp   rn   z'BuildDhcpRequest: transactionId:%s,%04X   r)   rp   ro   r{   )c      S   r   5   rF   rF   r   rm   B)gen_trans_idranger
   r+   rr   r   r   array)ra   request_broadcastrP   trans_idas        r   rX   rX   Q  s   B cCiG~H
 1a[ "q\
" 1a[ 1#HQK0A1 NN<('1a(@* * +   1a[ 4&x{3q4 1a[ @<Q?q@;;sG$$r   c                  ,    t        j                  d      S )Nrn   )osurandomr   r   r   r   r     s    ::a=r   ) r   r   r   r-   azurelinuxagent.common.loggercommonr+    azurelinuxagent.common.exceptionr   azurelinuxagent.common.osutilr   %azurelinuxagent.common.utils.restutilr   %azurelinuxagent.common.utils.textutilr   r   r   r	   r
   r   r   r4   r   objectr   rO   r   r   r_   rN   rX   r   r   r   r   <module>r      sv   "  	   . . 6 4 E   ' ]I& ]I@5D2
)%X*D%Nr   