Subversion Repositories Kolibri OS

Rev

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