Subversion Repositories Kolibri OS

Rev

Rev 339 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. ; Automated dhcp client
  2. ; v 1.3
  3. ;
  4. ; with thanks to authors of DHCP client for menuetos: Mike Hibbet
  5. ;
  6. ; by HidnPlayr & Derpenguin
  7.  
  8. use32
  9.                org    0x0
  10.  
  11.                db     'MENUET01'            ; 8 byte id
  12.                dd     0x01                  ; header version
  13.                dd     START                 ; start of code
  14.                dd     IM_END                ; size of image
  15.                dd     I_END                 ; memory for app
  16.                dd     I_END                 ; esp
  17.                dd     0x0 , 0x0             ; I_Param , I_Icon
  18.  
  19. ; CONFIGURATION
  20.  
  21.  
  22. TIMEOUT             equ 60                  ; in seconds
  23. BUFFER              equ 1024                ; in bytes
  24. __DEBUG__           equ 1                   ; enable/disable
  25. __DEBUG_LEVEL__     equ 1                   ; 1 = all, 2 = errors
  26.  
  27. ; CONFIGURATION FOR LINK-LOCAL
  28.  
  29. PROBE_WAIT          equ 1                   ; second  (initial random delay)
  30. PROBE_MIN           equ 1                   ; second  (minimum delay till repeated probe)
  31. PROBE_MAX           equ 2                   ; seconds (maximum delay till repeated probe)
  32. PROBE_NUM           equ 3                   ;         (number of probe packets)
  33.  
  34. ANNOUNCE_NUM        equ 2                   ;         (number of announcement packets)
  35. ANNOUNCE_INTERVAL   equ 2                   ; seconds (time between announcement packets)
  36. ANNOUNCE_WAIT       equ 2                   ; seconds (delay before announcing)
  37.  
  38. MAX_CONFLICTS       equ 10                  ;         (max conflicts before rate limiting)
  39.  
  40. RATE_LIMIT_INTERVAL equ 60                  ; seconds (delay between successive attempts)
  41.  
  42. DEFEND_INTERVAL     equ 10                  ; seconds (min. wait between defensive ARPs)
  43.  
  44. include '..\..\..\macros.inc'
  45. include 'eth.inc'
  46. include 'debug-fdo.inc'
  47. include 'dhcp.inc'
  48. include 'events.inc'
  49. include 'common.inc'
  50.  
  51.  
  52. START:                                      ; start of execution
  53.  
  54.     set_event_mask      event_network
  55.     eth.set_network_drv 0x00000383
  56.  
  57.     DEBUGF  1,"Stack Initialized.\n"
  58.  
  59.     eth.status eax                          ; Read the Stack status
  60.     test    eax,eax                         ; if eax is zero, no driver was found
  61.     jnz     @f
  62.     DEBUGF  1,"No Card detected\n"
  63.     jmp     close
  64.  
  65.    @@:
  66.     DEBUGF  1,"Detected card: %x\n",eax
  67.    @@:
  68.     eth.check_cable eax
  69.     test    al,al
  70.     jnz     @f
  71.     DEBUGF  1,"Ethernet Cable not connected\n"
  72.     wait 500                                ; loop until cable is connected (check every 5 sec)
  73.     jmp     @r
  74.  
  75.    @@:
  76.     DEBUGF  1,"Ethernet Cable status: %d\n",al
  77.  
  78.     eth.read_mac MAC
  79.     DEBUGF  1,"MAC address: %x-%x-%x-%x-%x-%x\n",[MAC]:2,[MAC+1]:2,[MAC+2]:2,[MAC+3]:2,[MAC+4]:2,[MAC+5]:2
  80.  
  81.     eth.check_port 68,eax                   ; Check if port 68 is available
  82.     cmp     eax,1
  83.     je      @f
  84.  
  85.     DEBUGF  1,"Port 68 is already in use!\n"
  86.     jmp     close
  87.  
  88.    @@:
  89.     eth.open_udp 68,67,-1,[socketNum]       ; open socket (local,remote,ip,socket)
  90.     DEBUGF  1,"Socket opened: %d\n",eax
  91.                                             ; Setup the first msg we will send
  92.     mov     byte [dhcpMsgType], 0x01        ; DHCP discover
  93.     mov     dword [dhcpLease], esi          ; esi is still -1 (-1 = forever)
  94.  
  95.     get_time_counter eax
  96.     imul    eax,100
  97.     mov     [currTime],eax
  98.  
  99. buildRequest:                               ; Creates a DHCP request packet.
  100.     xor     eax,eax                         ; Clear dhcpMsg to all zeros
  101.     mov     edi,dhcpMsg
  102.     mov     ecx,BUFFER
  103.     cld
  104.     rep     stosb
  105.  
  106.     mov     edx, dhcpMsg
  107.  
  108.     mov     [edx], byte 0x01                ; Boot request
  109.     mov     [edx+1], byte 0x01              ; Ethernet
  110.     mov     [edx+2], byte 0x06              ; Ethernet h/w len
  111.     mov     [edx+4], dword 0x11223344       ; xid
  112.     mov     eax,[currTime]
  113.     mov     [edx+8], eax                    ; secs, our uptime
  114.     mov     [edx+10], byte 0x80             ; broadcast flag set
  115.     mov     eax, dword [MAC]                ; first 4 bytes of MAC
  116.     mov     [edx+28],dword eax
  117.     mov     ax, word [MAC+4]                ; last 2 bytes of MAC
  118.     mov     [edx+32],word ax
  119.     mov     [edx+236], dword 0x63538263     ; magic number
  120.     mov     [edx+240], word 0x0135          ; option DHCP msg type
  121.     mov     al, [dhcpMsgType]
  122.     mov     [edx+240+2], al
  123.     mov     [edx+240+3], word 0x0433        ; option Lease time = infinity
  124.     mov     eax, [dhcpLease]
  125.     mov     [edx+240+5], eax
  126.     mov     [edx+240+9], word 0x0432        ; option requested IP address
  127.     mov     eax, [dhcpClientIP]
  128.     mov     [edx+240+11], eax
  129.     mov     [edx+240+15], word 0x0437       ; option request list
  130.     mov     [edx+240+17], dword 0x0f060301
  131.  
  132.     cmp     [dhcpMsgType], byte 0x01        ; Check which msg we are sending
  133.     jne     request_options
  134.  
  135.     mov     [edx+240+21], byte 0xff         ; "Discover" options
  136.  
  137.     mov     [dhcpMsgLen], dword 262         ; end of options marker
  138.     jmp     send_request
  139.  
  140. request_options:
  141.     mov     [edx+240+21], word 0x0436       ; server IP
  142.     mov     eax, [dhcpServerIP]
  143.     mov     [edx+240+23], eax
  144.  
  145.     mov     [edx+240+27], byte 0xff         ; end of options marker
  146.  
  147.     mov     [dhcpMsgLen], dword 268
  148.  
  149. send_request:
  150.     eth.write_udp [socketNum],[dhcpMsgLen],dhcpMsg ; write to socket ( send broadcast request )
  151.  
  152.     mov     eax, dhcpMsg                    ; Setup the DHCP buffer to receive response
  153.     mov     [dhcpMsgLen], eax               ; Used as a pointer to the data
  154.  
  155.     mov     eax,23                          ; wait here for event (data from remote)
  156.     mov     ebx,TIMEOUT*10
  157.     mcall
  158.  
  159.     eth.poll [socketNum]
  160.  
  161.     test    eax,eax
  162.     jnz     read_data
  163.  
  164.     DEBUGF  2,"Timeout!\n"
  165.     eth.close_udp [socketNum]
  166.     jmp    apipa                            ; no server found, lets try zeroconf
  167.  
  168.  
  169. read_data:                                  ; we have data - this will be the response
  170.     eth.read_packet [socketNum], dhcpMsg, BUFFER
  171.     mov     [dhcpMsgLen], eax
  172.     eth.close_udp [socketNum]
  173.  
  174.     ; depending on which msg we sent, handle the response
  175.     ; accordingly.
  176.     ; If the response is to a dhcp discover, then:
  177.     ;  1) If response is DHCP OFFER then
  178.     ;  1.1) record server IP, lease time & IP address.
  179.     ;  1.2) send a request packet
  180.     ; If the response is to a dhcp request, then:
  181.     ;  1) If the response is DHCP ACK then
  182.     ;  1.1) extract the DNS & subnet fields. Set them in the stack
  183.  
  184.     cmp     [dhcpMsgType], byte 0x01        ; did we send a discover?
  185.     je      discover
  186.     cmp     [dhcpMsgType], byte 0x03        ; did we send a request?
  187.     je      request
  188.  
  189.     jmp     close                           ; really unknown, what we did
  190.  
  191. discover:
  192.     call    parseResponse
  193.  
  194.     cmp     [dhcpMsgType], byte 0x02        ; Was the response an offer?
  195.     jne     apipa                           ; NO - so we do zeroconf
  196.     mov     [dhcpMsgType], byte 0x03        ; DHCP request
  197.     jmp     buildRequest
  198.  
  199. request:
  200.     call    parseResponse
  201.  
  202.     cmp     [dhcpMsgType], byte 0x05        ; Was the response an ACK? It should be
  203.     jne     apipa                           ; NO - so we do zeroconf
  204.  
  205.     jmp     close
  206.  
  207. ;***************************************************************************
  208. ;   Function
  209. ;      parseResponse
  210. ;
  211. ;   Description
  212. ;      extracts the fields ( client IP address and options ) from
  213. ;      a DHCP response
  214. ;      The values go into
  215. ;       dhcpMsgType,dhcpLease,dhcpClientIP,dhcpServerIP,
  216. ;       dhcpDNSIP, dhcpSubnet
  217. ;      The message is stored in dhcpMsg
  218. ;
  219. ;***************************************************************************
  220. parseResponse:
  221.     DEBUGF  1,"Data received, parsing response\n"
  222.     mov     edx, dhcpMsg
  223.  
  224.     pusha
  225.     eth.set_IP [edx+16]
  226.     mov     eax,[edx]
  227.     mov     [dhcpClientIP],eax
  228.     DEBUGF  1,"Client: %u.%u.%u.%u\n",[edx+16]:1,[edx+17]:1,[edx+18]:1,[edx+19]:1
  229.     popa
  230.  
  231.     add     edx, 240                        ; Point to first option
  232.     xor     ecx, ecx
  233.  
  234. next_option:
  235.     add     edx, ecx
  236. pr001:
  237.     mov     al, [edx]
  238.     cmp     al, 0xff                        ; End of options?
  239.     je      pr_exit
  240.  
  241.     cmp     al, dhcp_msg_type               ; Msg type is a single byte option
  242.     jne     @f
  243.  
  244.     mov     al, [edx+2]
  245.     mov     [dhcpMsgType], al
  246.     add     edx, 3
  247.     jmp     pr001                           ; Get next option
  248.  
  249. @@:
  250.     inc     edx
  251.     movzx   ecx, byte [edx]
  252.     inc     edx                             ; point to data
  253.  
  254.     cmp     al, dhcp_dhcp_server_id         ; server ip
  255.     jne     @f
  256.     mov     eax, [edx]
  257.     mov     [dhcpServerIP], eax
  258.     DEBUGF  1,"Server: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
  259.     jmp     next_option
  260.  
  261. @@:
  262.     cmp     al, dhcp_address_time
  263.     jne     @f
  264.  
  265.     pusha
  266.     mov     eax,[edx]
  267.     bswap   eax
  268.     mov     [dhcpLease],eax
  269.     DEBUGF  1,"lease: %d\n",eax
  270.     popa
  271.  
  272.     jmp     next_option
  273.  
  274. @@:
  275.     cmp     al, dhcp_subnet_mask
  276.     jne     @f
  277.  
  278.     pusha
  279.     eth.set_SUBNET [edx]
  280.     DEBUGF  1,"Subnet: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
  281.     popa
  282.  
  283.     jmp     next_option
  284.  
  285. @@:
  286.     cmp     al, dhcp_router
  287.     jne     @f
  288.  
  289.     pusha
  290.     eth.set_GATEWAY [edx]
  291.     DEBUGF  1,"Gateway: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
  292.     popa
  293.  
  294.     jmp     next_option
  295.  
  296.  
  297. @@:
  298.     cmp     al, dhcp_domain_server
  299.     jne     next_option
  300.  
  301.     pusha
  302.     eth.set_DNS [edx]
  303.     DEBUGF  1,"DNS: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
  304.     popa
  305.  
  306.     jmp     next_option
  307.  
  308. pr_exit:
  309.  
  310. ;    DEBUGF  1,"Sending ARP announce\n"
  311. ;    eth.ARP_ANNOUNCE [dhcpClientIP]         ; send an ARP announce packet
  312.  
  313.     jmp close
  314.  
  315. apipa:
  316.     call random
  317.     mov  ecx,0xfea9                         ; IP 169.254.0.0 link local net, see RFC3927
  318.     mov  cx,ax
  319.     eth.set_IP ecx                          ; mask is 255.255.0.0
  320.     DEBUGF 1,"Link Local IP assinged: 169.254.%u.%u\n",[generator+2]:1,[generator+3]:1
  321.     eth.set_SUBNET 0xffff
  322.     eth.set_GATEWAY 0x0
  323.     eth.set_DNS 0x0
  324.  
  325.     wait PROBE_WAIT*100
  326.  
  327.     xor esi,esi
  328.    probe_loop:
  329.     call  random                            ; create a pseudo random number in eax (seeded by MAC)
  330.  
  331.     cmp   al,PROBE_MIN*100                  ; check if al is bigger then PROBE_MIN
  332.     jge   @f                                ; all ok
  333.     add   al,(PROBE_MAX-PROBE_MIN)*100      ; al is too small
  334.    @@:
  335.  
  336.     cmp   al,PROBE_MAX*100
  337.     jle   @f
  338.     sub   al,(PROBE_MAX-PROBE_MIN)*100
  339.    @@:
  340.  
  341.     movzx ebx,al
  342.     DEBUGF  1,"Waiting %u0ms\n",ebx
  343.     wait  ebx
  344.  
  345.     DEBUGF  1,"Sending Probe\n"
  346. ;    eth.ARP_PROBE MAC
  347.     inc   esi
  348.  
  349.     cmp   esi,PROBE_NUM
  350.     jl    probe_loop
  351.  
  352. ; now we wait further ANNOUNCE_WAIT seconds and send ANNOUNCE_NUM ARP announces. If any other host has assingned
  353. ; IP within this time, we should create another adress, that have to be done later
  354.  
  355.     DEBUGF  1,"Waiting %us\n",ANNOUNCE_WAIT
  356.     wait ANNOUNCE_WAIT*100
  357.     xor   esi,esi
  358.    announce_loop:
  359.  
  360.     DEBUGF  1,"Sending Announce\n"
  361. ;    eth.ARP_ANNOUNCE MAC
  362.  
  363.     inc   esi
  364.     cmp   esi,ANNOUNCE_NUM
  365.     je    @f
  366.  
  367.     DEBUGF  1,"Waiting %us\n",ANNOUNCE_INTERVAL
  368.     wait  ANNOUNCE_INTERVAL*100
  369.     jmp   announce_loop
  370.    @@:
  371.     ; we should, instead of closing, detect ARP conflicts and detect if cable keeps connected ;)
  372.  
  373. close:
  374.     DEBUGF  1,"Exiting\n"
  375.     exit                                    ; at last, exit
  376.  
  377.  
  378. random:
  379.  
  380.     mov   eax,[generator]
  381.     add   eax,-43ab45b5h
  382.     ror   eax,1
  383.     bswap eax
  384.     xor   eax,dword[MAC]
  385.     ror   eax,1
  386.     xor   eax,dword[MAC+2]
  387.     mov   [generator],eax
  388.  
  389. ret
  390.  
  391. ; DATA AREA
  392.  
  393. include_debug_strings
  394.  
  395. IM_END:
  396.  
  397. dhcpClientIP    dd  0
  398. dhcpMsgType     db  0
  399. dhcpLease       dd  0
  400. dhcpServerIP    dd  0
  401.  
  402. dhcpMsgLen      dd  0
  403. socketNum       dd  0
  404.  
  405. MAC             rb  6
  406. currTime        dd  0
  407. renewTime       dd  0
  408. generator       dd  0
  409.  
  410. dhcpMsg         rb  BUFFER
  411. I_END: