Subversion Repositories Kolibri OS

Rev

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

  1. ; Zero-config
  2. ; v 1.4
  3. ;
  4. ; DHCP code is based on that by Mike Hibbet (DHCP client for menuetos)
  5. ;
  6. ; Written 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 , path             ; 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 '../../../proc32.inc'
  45. include '../../../macros.inc'
  46. include 'ETH.INC'
  47. include 'debug-fdo.inc'
  48. include 'dhcp.inc'
  49. include '../../../dll.inc'
  50.  
  51. START:                                      ; start of execution
  52.  
  53.     mcall 40, 0
  54.  
  55.     eth.set_network_drv 0x00000383
  56.  
  57.     DEBUGF  1,"Zero-config service:\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 found!\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,"Cable disconnected!\n"
  72.     mcall   5, 500                          ; loop until cable is connected (check every 5 sec)
  73.     jmp     @r
  74.  
  75.    @@:
  76.     eth.read_mac MAC
  77.     DEBUGF  1,"MAC: %x-%x-%x-%x-%x-%x\n",[MAC]:2,[MAC+1]:2,[MAC+2]:2,[MAC+3]:2,[MAC+4]:2,[MAC+5]:2
  78.  
  79.     cld
  80.     mov     edi, path      ; Calculate the length of zero-terminated string
  81.     xor     al , al
  82.     mov     ecx, 1024
  83.     repnz   scas byte[es:edi]
  84.     dec     edi
  85.  
  86.     mov     esi, filename
  87.     mov     ecx, 5
  88.     rep     movsb
  89.  
  90.     mcall 68,11
  91.  
  92.     stdcall dll.Load,@IMPORT
  93.     or      eax,eax
  94.     jnz     skip_ini
  95.  
  96.  
  97.     invoke ini.get_str, path, str_ipconfig, str_type, inibuf, 16, 0
  98.  
  99.     mov  eax,dword[inibuf]
  100.  
  101.     cmp  eax,'stat'
  102.     jne  skip_ini
  103.  
  104.     invoke ini.get_str, path, str_ipconfig, str_ip, inibuf, 16, 0
  105.     mov    edx, inibuf
  106.     call   Ip2dword
  107.     eth.set_IP edx
  108.  
  109.     invoke ini.get_str, path, str_ipconfig, str_gateway, inibuf, 16, 0
  110.     mov    edx, inibuf
  111.     call   Ip2dword
  112.     eth.set_GATEWAY edx
  113.  
  114.     invoke ini.get_str, path, str_ipconfig, str_dns, inibuf, 16, 0
  115.     mov    edx, inibuf
  116.     call   Ip2dword
  117.     eth.set_DNS edx
  118.  
  119.     invoke ini.get_str, path, str_ipconfig, str_subnet, inibuf, 16, 0
  120.     mov    edx, inibuf
  121.     call   Ip2dword
  122.     eth.set_SUBNET edx
  123.  
  124.  
  125.     mcall  -1
  126.  
  127.  
  128. skip_ini:
  129.  
  130.     eth.check_port 68,eax                   ; Check if port 68 is available
  131.     cmp     eax,1
  132.     je      @f
  133.  
  134.     DEBUGF  1,"Port 68 is already in use!\n"
  135.     jmp     close
  136.  
  137.    @@:
  138.     eth.open_udp 68,67,-1,[socketNum]       ; open socket (local,remote,ip,socket)
  139.                                             ; Setup the first msg we will send
  140.     mov     byte [dhcpMsgType], 0x01        ; DHCP discover
  141.     mov     dword [dhcpLease], esi          ; esi is still -1 (-1 = forever)
  142.  
  143.     mcall   26, 9
  144.     imul    eax,100
  145.     mov     [currTime],eax
  146.  
  147. buildRequest:                               ; Creates a DHCP request packet.
  148.     stdcall mem.Alloc, BUFFER
  149.     mov     [dhcpMsg], eax
  150.     test    eax,eax
  151.     jz      apipa
  152.  
  153.  
  154.     mov     edi, eax
  155.     mov     ecx,BUFFER
  156.     xor     eax,eax
  157.     cld
  158.     rep     stosb
  159.  
  160.     mov     edx,[dhcpMsg]
  161.  
  162.     mov     [edx], byte 0x01                ; Boot request
  163.     mov     [edx+1], byte 0x01              ; Ethernet
  164.     mov     [edx+2], byte 0x06              ; Ethernet h/w len
  165.     mov     [edx+4], dword 0x11223344       ; xid
  166.     mov     eax,[currTime]
  167.     mov     [edx+8], eax                    ; secs, our uptime
  168.     mov     [edx+10], byte 0x80             ; broadcast flag set
  169.     mov     eax, dword [MAC]                ; first 4 bytes of MAC
  170.     mov     [edx+28],dword eax
  171.     mov     ax, word [MAC+4]                ; last 2 bytes of MAC
  172.     mov     [edx+32],word ax
  173.     mov     [edx+236], dword 0x63538263     ; magic number
  174.     mov     [edx+240], word 0x0135          ; option DHCP msg type
  175.     mov     al, [dhcpMsgType]
  176.     mov     [edx+240+2], al
  177.     mov     [edx+240+3], word 0x0433        ; option Lease time = infinity
  178.     mov     eax, [dhcpLease]
  179.     mov     [edx+240+5], eax
  180.     mov     [edx+240+9], word 0x0432        ; option requested IP address
  181.     mov     eax, [dhcpClientIP]
  182.     mov     [edx+240+11], eax
  183.     mov     [edx+240+15], word 0x0437       ; option request list
  184.     mov     [edx+240+17], dword 0x0f060301
  185.  
  186.     cmp     [dhcpMsgType], byte 0x01        ; Check which msg we are sending
  187.     jne     request_options
  188.  
  189.     mov     [edx+240+21], byte 0xff         ; "Discover" options
  190.  
  191.     mov     [dhcpMsgLen], dword 262         ; end of options marker
  192.     jmp     send_request
  193.  
  194. request_options:
  195.     mov     [edx+240+21], word 0x0436       ; server IP
  196.     mov     eax, [dhcpServerIP]
  197.     mov     [edx+240+23], eax
  198.  
  199.     mov     [edx+240+27], byte 0xff         ; end of options marker
  200.  
  201.     mov     [dhcpMsgLen], dword 268
  202.  
  203. send_request:
  204.     eth.write_udp [socketNum],[dhcpMsgLen],[dhcpMsg] ; write to socket ( send broadcast request )
  205.  
  206.     mov     eax, [dhcpMsg]                    ; Setup the DHCP buffer to receive response
  207.     mov     [dhcpMsgLen], eax               ; Used as a pointer to the data
  208.  
  209.     mov     eax,23                          ; wait here for event (data from remote)
  210.     mov     ebx,TIMEOUT*10
  211.     mcall
  212.  
  213.     eth.poll [socketNum]
  214.  
  215.     test    eax,eax
  216.     jnz     read_data
  217.  
  218.     DEBUGF  2,"Timeout!\n"
  219.     eth.close_udp [socketNum]
  220.     jmp    apipa                            ; no server found, lets try zeroconf
  221.  
  222.  
  223. read_data:                                  ; we have data - this will be the response
  224.     eth.read_packet [socketNum], [dhcpMsg], BUFFER
  225.     mov     [dhcpMsgLen], eax
  226.     eth.close_udp [socketNum]
  227.  
  228.     ; depending on which msg we sent, handle the response
  229.     ; accordingly.
  230.     ; If the response is to a dhcp discover, then:
  231.     ;  1) If response is DHCP OFFER then
  232.     ;  1.1) record server IP, lease time & IP address.
  233.     ;  1.2) send a request packet
  234.     ; If the response is to a dhcp request, then:
  235.     ;  1) If the response is DHCP ACK then
  236.     ;  1.1) extract the DNS & subnet fields. Set them in the stack
  237.  
  238.     cmp     [dhcpMsgType], byte 0x01        ; did we send a discover?
  239.     je      discover
  240.     cmp     [dhcpMsgType], byte 0x03        ; did we send a request?
  241.     je      request
  242.  
  243.     jmp     close                           ; really unknown, what we did
  244.  
  245. discover:
  246.     call    parseResponse
  247.  
  248.     cmp     [dhcpMsgType], byte 0x02        ; Was the response an offer?
  249.     jne     apipa                           ; NO - so we do zeroconf
  250.     mov     [dhcpMsgType], byte 0x03        ; DHCP request
  251.     jmp     buildRequest
  252.  
  253. request:
  254.     call    parseResponse
  255.  
  256.     cmp     [dhcpMsgType], byte 0x05        ; Was the response an ACK? It should be
  257.     jne     apipa                           ; NO - so we do zeroconf
  258.  
  259.     jmp     close
  260.  
  261. ;***************************************************************************
  262. ;   Function
  263. ;      parseResponse
  264. ;
  265. ;   Description
  266. ;      extracts the fields ( client IP address and options ) from
  267. ;      a DHCP response
  268. ;      The values go into
  269. ;       dhcpMsgType,dhcpLease,dhcpClientIP,dhcpServerIP,
  270. ;       dhcpDNSIP, dhcpSubnet
  271. ;      The message is stored in dhcpMsg
  272. ;
  273. ;***************************************************************************
  274. parseResponse:
  275.     DEBUGF  1,"Data received, parsing response\n"
  276.     mov     edx, [dhcpMsg]
  277.  
  278.     pusha
  279.     eth.set_IP [edx+16]
  280.     mov     eax,[edx]
  281.     mov     [dhcpClientIP],eax
  282.     DEBUGF  1,"Client: %u.%u.%u.%u\n",[edx+16]:1,[edx+17]:1,[edx+18]:1,[edx+19]:1
  283.     popa
  284.  
  285.     add     edx, 240                        ; Point to first option
  286.     xor     ecx, ecx
  287.  
  288. next_option:
  289.     add     edx, ecx
  290. pr001:
  291.     mov     al, [edx]
  292.     cmp     al, 0xff                        ; End of options?
  293.     je      pr_exit
  294.  
  295.     cmp     al, dhcp_msg_type               ; Msg type is a single byte option
  296.     jne     @f
  297.  
  298.     mov     al, [edx+2]
  299.     mov     [dhcpMsgType], al
  300.     add     edx, 3
  301.     jmp     pr001                           ; Get next option
  302.  
  303. @@:
  304.     inc     edx
  305.     movzx   ecx, byte [edx]
  306.     inc     edx                             ; point to data
  307.  
  308.     cmp     al, dhcp_dhcp_server_id         ; server ip
  309.     jne     @f
  310.     mov     eax, [edx]
  311.     mov     [dhcpServerIP], eax
  312.     DEBUGF  1,"Server: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
  313.     jmp     next_option
  314.  
  315. @@:
  316.     cmp     al, dhcp_address_time
  317.     jne     @f
  318.  
  319.     pusha
  320.     mov     eax,[edx]
  321.     bswap   eax
  322.     mov     [dhcpLease],eax
  323.     DEBUGF  1,"lease: %d\n",eax
  324.     popa
  325.  
  326.     jmp     next_option
  327.  
  328. @@:
  329.     cmp     al, dhcp_subnet_mask
  330.     jne     @f
  331.  
  332.     pusha
  333.     eth.set_SUBNET [edx]
  334.     DEBUGF  1,"Subnet: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
  335.     popa
  336.  
  337.     jmp     next_option
  338.  
  339. @@:
  340.     cmp     al, dhcp_router
  341.     jne     @f
  342.  
  343.     pusha
  344.     eth.set_GATEWAY [edx]
  345.     DEBUGF  1,"Gateway: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
  346.     popa
  347.  
  348.     jmp     next_option
  349.  
  350.  
  351. @@:
  352.     cmp     al, dhcp_domain_server
  353.     jne     next_option
  354.  
  355.     pusha
  356.     eth.set_DNS [edx]
  357.     DEBUGF  1,"DNS: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
  358.     popa
  359.  
  360.     jmp     next_option
  361.  
  362. pr_exit:
  363.  
  364. ;    DEBUGF  1,"Sending ARP announce\n"
  365. ;    eth.ARP_ANNOUNCE [dhcpClientIP]         ; send an ARP announce packet
  366.  
  367.     jmp close
  368.  
  369. apipa:
  370.     stdcall mem.Free, [dhcpMsg]
  371.  
  372. link_local:
  373.     call random
  374.     mov  ecx,0xfea9                         ; IP 169.254.0.0 link local net, see RFC3927
  375.     mov  cx,ax
  376.     eth.set_IP ecx                          ; mask is 255.255.0.0
  377.     DEBUGF 1,"Link Local IP assigned: 169.254.%u.%u\n",[generator+2]:1,[generator+3]:1
  378.     eth.set_SUBNET 0xffff
  379.     eth.set_GATEWAY 0x0
  380.     eth.set_DNS 0x0
  381.  
  382.     mcall 5, PROBE_WAIT*100
  383.  
  384.     xor esi,esi
  385.    probe_loop:
  386.     call  random                            ; create a pseudo random number in eax (seeded by MAC)
  387.  
  388.     cmp   al,PROBE_MIN*100                  ; check if al is bigger then PROBE_MIN
  389.     jge   @f                                ; all ok
  390.     add   al,(PROBE_MAX-PROBE_MIN)*100      ; al is too small
  391.    @@:
  392.  
  393.     cmp   al,PROBE_MAX*100
  394.     jle   @f
  395.     sub   al,(PROBE_MAX-PROBE_MIN)*100
  396.    @@:
  397.  
  398.     movzx ebx,al
  399.     DEBUGF  1,"Waiting %u0ms\n",ebx
  400.     mcall 5
  401.  
  402.     DEBUGF  1,"Sending Probe\n"
  403. ;    eth.ARP_PROBE MAC
  404.     inc   esi
  405.  
  406.     cmp   esi,PROBE_NUM
  407.     jl    probe_loop
  408.  
  409. ; now we wait further ANNOUNCE_WAIT seconds and send ANNOUNCE_NUM ARP announces. If any other host has assigned
  410. ; IP within this time, we should create another adress, that have to be done later
  411.  
  412.     DEBUGF  1,"Waiting %us\n",ANNOUNCE_WAIT
  413.     mcall 5, ANNOUNCE_WAIT*100
  414.     xor   esi,esi
  415.    announce_loop:
  416.  
  417.     DEBUGF  1,"Sending Announce\n"
  418. ;    eth.ARP_ANNOUNCE MAC
  419.  
  420.     inc   esi
  421.     cmp   esi,ANNOUNCE_NUM
  422.     je    @f
  423.  
  424.     DEBUGF  1,"Waiting %us\n",ANNOUNCE_INTERVAL
  425.     mcall 5, ANNOUNCE_INTERVAL*100
  426.     jmp   announce_loop
  427.    @@:
  428.     ; we should, instead of closing, detect ARP conflicts and detect if cable keeps connected ;)
  429.  
  430. close:
  431.     mcall -1
  432.  
  433.  
  434. random:  ; Pseudo random actually
  435.  
  436.     mov   eax,[generator]
  437.     add   eax,-43ab45b5h
  438.     ror   eax,1
  439.     bswap eax
  440.     xor   eax,dword[MAC]
  441.     ror   eax,1
  442.     xor   eax,dword[MAC+2]
  443.     mov   [generator],eax
  444.  
  445. ret
  446.  
  447. ; DATA AREA
  448.  
  449. align 16
  450. @IMPORT:
  451.  
  452. library \
  453.         libini,'libini.obj'
  454.  
  455. import  libini, \
  456.         ini.get_str,'ini_get_str'
  457.  
  458. include_debug_strings
  459.  
  460. filename db '.ini',0
  461. str_ip db 'ip',0
  462. str_subnet db 'subnet',0
  463. str_gateway db 'gateway',0
  464. str_dns db 'dns',0
  465. str_ipconfig db 'ipconfig',0
  466. str_type db 'type',0
  467.  
  468.  
  469. IM_END:
  470.  
  471. inibuf          rb 16
  472.  
  473. dhcpClientIP    dd  ?
  474. dhcpMsgType     db  ?
  475. dhcpLease       dd  ?
  476. dhcpServerIP    dd  ?
  477.  
  478. dhcpMsgLen      dd  ?
  479. socketNum       dd  ?
  480.  
  481. MAC             dp  ?
  482. currTime        dd  ?
  483. renewTime       dd  ?
  484. generator       dd  ?
  485.  
  486. dhcpMsg         dd  ?
  487.  
  488. I_END_2:
  489.  
  490. path            rb  1024+5
  491.  
  492. I_END:
  493.