Subversion Repositories Kolibri OS

Rev

Rev 5419 | Rev 5587 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2010-2015. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  zeroconfig.asm - Zeroconfig service for KolibriOS              ;;
  7. ;;                                                                 ;;
  8. ;;  Written by hidnplayr@kolibrios.org                             ;;
  9. ;;    Some code contributed by Derpenguin                          ;;
  10. ;;                                                                 ;;
  11. ;;  DHCP code is based on that by Mike Hibbet                      ;;
  12. ;;      (DHCP client for menuetos)                                 ;;
  13. ;;                                                                 ;;
  14. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  15. ;;             Version 2, June 1991                                ;;
  16. ;;                                                                 ;;
  17. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  18.  
  19. format binary as ""
  20.  
  21. ; CONFIGURATION
  22.  
  23. TIMEOUT                 = 3             ; in seconds
  24. BUFFER                  = 1024          ; in bytes
  25. DHCP_TRIES              = 3             ; number of times to try contacting DHCP server
  26. __DEBUG__               = 1             ; enable/disable
  27. __DEBUG_LEVEL__         = 2             ; 1 = all, 2 = errors
  28.  
  29. ; CONFIGURATION FOR LINK-LOCAL
  30.  
  31. PROBE_WAIT              = 1             ; second  (initial random delay)
  32. PROBE_MIN               = 1             ; second  (minimum delay till repeated probe)
  33. PROBE_MAX               = 2             ; seconds (maximum delay till repeated probe)
  34. PROBE_NUM               = 3             ;         (number of probe packets)
  35.  
  36. ANNOUNCE_NUM            = 2             ;         (number of announcement packets)
  37. ANNOUNCE_INTERVAL       = 2             ; seconds (time between announcement packets)
  38. ANNOUNCE_WAIT           = 2             ; seconds (delay before announcing)
  39.  
  40. MAX_CONFLICTS           = 10            ;         (max conflicts before rate limiting)
  41.  
  42. RATE_LIMIT_INTERVAL     = 60            ; seconds (delay between successive attempts)
  43.  
  44. DEFEND_INTERVAL         = 10            ; seconds (min. wait between defensive ARPs)
  45.  
  46. MAX_INTERFACES          = 8
  47.  
  48. use32
  49.         org     0x0
  50.  
  51.         db      'MENUET01'              ; 8 byte id
  52.         dd      0x01                    ; header version
  53.         dd      START                   ; start of code
  54.         dd      IM_END                  ; size of image
  55.         dd      (I_END+0x100)           ; memory for app
  56.         dd      (I_END+0x100)           ; esp
  57.         dd      0, 0                    ; I_Param, I_Path
  58.  
  59.  
  60. include '../../proc32.inc'
  61. include '../../macros.inc'
  62. include '../../debug-fdo.inc'
  63. include '../../network.inc'
  64. include 'dhcp.inc'
  65. include '../../dll.inc'
  66.  
  67. struct  dhcp_msg
  68.         op              db ?    ; Operation Code
  69.         htype           db ?    ; Hardware type
  70.         hlen            db ?    ; Hardware address length
  71.         hops            db ?
  72.         xid             dd ?    ; Transaction Identifier
  73.         secs            dw ?    ; Seconds since boot
  74.         flags           dw ?
  75.         ciaddr          dd ?    ; Client IP address
  76.         yiaddr          dd ?    ; "Your" IP address
  77.         siaddr          dd ?    ; Server IP address
  78.         giaddr          dd ?    ; Gateway IP address
  79.         chaddr          rb 16   ; Client hardware address
  80.         sname           rb 64   ; Server name
  81.         file            rb 128  ; boot filename
  82.         cookie          dd ?    ; Magic cookie (0x63538263)
  83.         options         rb 512
  84. ends
  85.  
  86. struct  interface
  87.         number          dd ?
  88.         state           dd ?    ; 0 - disconnected, 1 - connected
  89.         mode            dd ?    ; 0 - static, 1 - dhcp, 2 - auto (zero config)
  90.         tries           dd ?
  91.         lease           dd ?
  92.         ServerIP        dd ?
  93.         ip              dd ?
  94.         subnet          dd ?
  95.         dns             dd ?
  96.         gateway         dd ?
  97.         socketNum       dd ?
  98.         timeout         dd ?
  99.         ip_conflicts    dd ?
  100. ends
  101.  
  102. START:
  103.         mcall   68, 11                  ; init heap
  104.  
  105.         stdcall dll.Load, @IMPORT       ; load libraries
  106.         or      eax, eax
  107.         jnz     exit_immediately
  108.  
  109.         DEBUGF  2, "Zero-config service loaded\n"
  110.  
  111.         mcall   40, EVM_STACK2          ; We only want low-level network events
  112.  
  113. ; Set up interface list
  114.         mov     edi, device_list
  115.         xor     ebx, ebx
  116.   @@:
  117.         inc     ebx
  118.         mov     eax, ebx
  119.         stosd
  120.         mov     ecx, sizeof.interface/4-1
  121.         xor     eax,eax
  122.         rep stosd
  123.         cmp     ebx, MAX_INTERFACES
  124.         jb      @b
  125.  
  126.         mov     ebp, device_list
  127. mainloop:
  128.         cmp     [ebp + interface.state], 0
  129.         je      .link_up?
  130.         jmp     .maintain_link
  131.  
  132.   .next:
  133.         cmp     [ebp + interface.number], MAX_INTERFACES
  134.         je      .wait
  135.         add     ebp, sizeof.interface
  136.         jmp     mainloop
  137.  
  138.   .wait:
  139.         mcall   10                      ; Wait for event
  140.         mov     ebp, device_list
  141.         jmp     mainloop
  142.  
  143.   .link_up?:
  144.         mov     bh, byte[ebp + interface.number]
  145.         mov     bl, 0                   ; Get device type
  146.         mcall   74
  147.         cmp     eax, 1                  ; Ethernet
  148.         jne     mainloop.next
  149.  
  150.         mov     bl, 10                  ; Get Link status
  151.         mcall   74
  152.         test    eax, eax
  153.         jz      mainloop.next
  154.  
  155.         mov     [ebp + interface.state], 1
  156.  
  157.         call    create_str_ini_int
  158.  
  159. ; Try to read settings from .ini file
  160.         invoke  ini.get_str, ini_path, str_ini_int, str_ip_type, inibuf, 16, str_null
  161.         test    eax, eax
  162.         jz      @f
  163. ; If settings not found, use default settings from 'ip?' section
  164.         mov     dword[str_ini_int], 'ip?'
  165.   @@:
  166.  
  167.         mov     ebx, API_ETH + 0
  168.         mov     bh, byte[ebp + interface.number]
  169.         mcall   76                      ; get MAC of the ethernet interface
  170.         mov     word[tx_msg.chaddr], bx
  171.         mov     dword[tx_msg.chaddr+2], eax
  172.         DEBUGF  1, "MAC: %x-%x-%x-%x-%x-%x\n", \
  173.         [tx_msg.chaddr+0]:2, [tx_msg.chaddr+1]:2, [tx_msg.chaddr+2]:2, \
  174.         [tx_msg.chaddr+3]:2, [tx_msg.chaddr+4]:2, [tx_msg.chaddr+5]:2
  175.  
  176.         invoke  ini.get_str, ini_path, str_ini_int, str_ip_type, inibuf, 16, str_null
  177.         test    eax, eax
  178.         jnz     .fail
  179.         mov     eax, dword[inibuf]
  180.         or      eax, 0x20202020
  181.         mov     [ebp + interface.mode], 0
  182.         cmp     eax, 'stat'
  183.         je      static
  184.         mov     [ebp + interface.mode], 1
  185.         cmp     eax, 'dhcp'
  186.         je      dhcp
  187.         mov     [ebp + interface.mode], 2
  188.         cmp     eax, 'auto'
  189.         je      dhcp
  190.  
  191.   .fail:
  192.         DEBUGF  2, "Invalid network.ini settings\n"
  193.         mcall   -1                      ; Give up
  194.  
  195.   .maintain_link:
  196.  
  197. ; Check for IP conflicts
  198.         mov     ebx, API_ARP
  199.         mov     bh, byte[ebp + interface.number]
  200.         mov     bl, 7
  201.         mcall   76                      ; Number of IP conflicts
  202.         cmp     eax, [ebp + interface.ip_conflicts]
  203.         je      @f
  204.         mov     [ebp + interface.ip_conflicts], eax
  205.         DEBUGF  2, "IP address conflict on interface %u\n", [ebp + interface.number]
  206.         ; Notify user of the IP address conflict
  207.         mov     [notify_struct.msg], str_conflict
  208.         mcall   70, notify_struct
  209.   @@:
  210.  
  211. ; Check if device is still there
  212.         mov     bh, byte[ebp + interface.number]
  213.         mov     bl, 0                   ; Get device type
  214.         mcall   74
  215.         test    eax, eax                ; No device
  216.         jz      .link_down
  217.  
  218. ; Check if link is still there
  219.         mov     bl, 10                  ; Get Link status
  220.         mcall   74
  221.         test    eax, eax
  222.         jnz     .next
  223.  
  224.   .link_down:
  225.         mov     [ebp + interface.state], 0
  226.  
  227. ; Notify user that the link is down
  228.         mov     [notify_struct.msg], str_disconnected
  229.         mcall   70, notify_struct
  230.  
  231. ; CHECKME: should we do this in kernel instead? Should we even do this at all?
  232.         xor     ecx, ecx
  233.         mov     ebx, API_IPv4 + 3
  234.         mov     bh, byte[ebp + interface.number]
  235.         mcall   76                      ; ip
  236.         mov     bl, 5
  237.         mcall   76                      ; dns
  238.         mov     bl, 7
  239.         mcall   76                      ; subnet
  240.         mov     bl, 9
  241.         mcall   76                      ; gateway
  242.  
  243.         jmp     .next
  244.  
  245. link_up:
  246.  
  247. ; Read number of previous IP conflicts
  248.         mov     ebx, API_ARP
  249.         mov     bh, byte[ebp + interface.number]
  250.         mov     bl, 7
  251.         mcall   76
  252.         mov     [ebp + interface.ip_conflicts], eax
  253.  
  254. ; Notify user that the link is up and running
  255.         mov     [notify_struct.msg], str_connected
  256.         mcall   70, notify_struct
  257.  
  258.   .fail:
  259.         mcall   40, EVM_STACK2
  260.         jmp     mainloop.next
  261.  
  262. static:
  263.         DEBUGF  1, "Applying Static IP settings\n"
  264.  
  265.         invoke  ini.get_str, ini_path, str_ini_int, str_ip, inibuf, 16, str_null
  266.         mov     esi, inibuf
  267.         call    ip_str_to_dword
  268.         mov     ebx, API_IPv4 + 3       ; set IP
  269.         mov     bh, byte[ebp + interface.number]
  270.         mcall   76
  271.  
  272.         invoke  ini.get_str, ini_path, str_ini_int, str_subnet, inibuf, 16, str_null
  273.         mov     esi, inibuf
  274.         call    ip_str_to_dword
  275.         mov     ebx, API_IPv4 + 7       ; set subnet
  276.         mov     bh, byte[ebp + interface.number]
  277.         mcall   76
  278.  
  279.         invoke  ini.get_str, ini_path, str_ini_int, str_gateway, inibuf, 16, str_null
  280.         mov     esi, inibuf
  281.         call    ip_str_to_dword
  282.         mov     ebx, API_IPv4 + 9       ; set gateway
  283.         mov     bh, byte[ebp + interface.number]
  284.         mcall   76
  285.  
  286.   .dns:
  287.         invoke  ini.get_str, ini_path, str_ini_int, str_dns, inibuf, 16, str_null
  288.         mov     esi, inibuf
  289.         call    ip_str_to_dword
  290.         mov     ebx, API_IPv4 + 5       ; set DNS
  291.         mov     bh, byte[ebp + interface.number]
  292.         mcall   76
  293.  
  294.         jmp     link_up
  295.  
  296.  
  297. dhcp:
  298.  
  299.         DEBUGF  2, "Trying to contact DHCP server\n"
  300.  
  301.         mcall   40, EVM_STACK
  302.  
  303.         mcall   75, 0, AF_INET4, SOCK_DGRAM, 0                          ; open socket (parameters: domain, type, reserved)
  304.         cmp     eax, -1
  305.         je      dhcp_error
  306.         mov     [ebp + interface.socketNum], eax
  307.  
  308.         DEBUGF  1, "Socket %x opened\n", eax
  309.  
  310.         mcall   75, 2, [ebp + interface.socketNum], sock_local, 18      ; bind socket to local port 68
  311.         cmp     eax, -1
  312.         je      socket_error
  313.  
  314.         DEBUGF  1, "Socket Bound to local port 68\n"
  315.  
  316.         pushd   [ebp + interface.number]
  317.         pushd   4                       ; length of option
  318.         pushd   1 shl 9                 ; SO_BINDTODEVICE
  319.         pushd   0                       ; SOL_SOCKET
  320.         mcall   75, 8, [ebp + interface.socketNum], esp
  321.         add     esp, 16
  322.         cmp     eax, -1
  323.         je      socket_error
  324.  
  325.         DEBUGF  1, "Socket Bound to local interface %u\n", [ebp + interface.number]
  326.  
  327.         mcall   75, 4, [ebp + interface.socketNum], sock_remote, 18     ; connect to 255.255.255.255 on port 67
  328.         cmp     eax, -1
  329.         je      socket_error
  330.  
  331.         DEBUGF  1, "Connected to 255.255.255.255 on port 67\n"
  332.  
  333.         ; Read preferred IP address from settings file
  334.         invoke  ini.get_str, ini_path, str_ini_int, str_ip, inibuf, 16, str_null
  335.         mov     esi, inibuf
  336.         call    ip_str_to_dword
  337.         mov     [ebp + interface.ip], ecx
  338.  
  339.         call    random
  340.         mov     [tx_msg.xid], eax                                       ; randomize session ID
  341.         mov     [tx_msg_type], 1                                        ; DHCP discover
  342.  
  343. build_dhcp_packet:
  344.  
  345.         DEBUGF  1, "Building DHCP packet\n"
  346.  
  347.         mov     [ebp + interface.tries], DHCP_TRIES
  348.  
  349.         ; Boot protocol legacy
  350.         mov     [tx_msg.op], 1                                          ; Boot request
  351.         mov     [tx_msg.htype], 1                                       ; Ethernet
  352.         mov     [tx_msg.hlen], 6                                        ; Ethernet address h/w len
  353.         mov     [tx_msg.hops], 0
  354.         mcall   26, 9                                                   ; Time since boot
  355.         xor     edx, edx
  356.         mov     ebx, 100
  357.         div     ebx                                                     ; Divide by 100 to get number of seconds
  358.         mov     [tx_msg.secs], ax
  359.         mov     [tx_msg.flags], 0
  360.  
  361.         ; DHCP extension
  362.         mov     [tx_msg.cookie], 0x63538263                             ; magic cookie
  363.  
  364.         mov     word[tx_msg+240], 0x0135                                ; option DHCP msg type
  365.         mov     al,[tx_msg_type]
  366.         mov     [tx_msg+240+2], al
  367.  
  368.         mov     word[tx_msg+240+3], 0x0433                              ; option Lease time
  369.         mov     dword[tx_msg+240+5], -1                                 ; infinite
  370.  
  371.         mov     word[tx_msg+240+9], 0x0432                              ; option requested IP address
  372.         mov     eax,[ebp + interface.ip]
  373.         mov     [tx_msg+240+11], eax
  374.  
  375.         mov     word[tx_msg+240+15], 0x0437                             ; option request list
  376.         mov     dword[tx_msg+240+17], 0x0f060301
  377.  
  378.         cmp     [tx_msg_type], 1                                        ; Check which msg we are sending
  379.         jne     .request
  380.  
  381.         mov     byte[tx_msg+240+21], 0xff                               ; end of options marker
  382.  
  383.         mov     [tx_msg_len], 262                                       ; length
  384.         jmp     send_dhcp_packet
  385.  
  386.   .request:
  387.         mov     word[tx_msg+240+21], 0x0436                             ; server IP
  388.         mov     eax,[ebp + interface.ServerIP]
  389.         mov     [tx_msg+240+23], eax
  390.  
  391.         mov     byte[tx_msg+240+27], 0xff                               ; end of options marker
  392.  
  393.         mov     [tx_msg_len], 268                                       ; length
  394.  
  395.  
  396. send_dhcp_packet:
  397.         DEBUGF  1, "Sending DHCP packet\n"
  398.         lea     edx, [tx_msg]
  399.         mcall   75, 6, [ebp + interface.socketNum], , [tx_msg_len]
  400.  
  401. ; Wait for reply
  402.         mcall   26, 9
  403.         add     eax, TIMEOUT*100
  404.         mov     [ebp + interface.timeout], eax
  405.         mov     ebx, TIMEOUT*100
  406.   .wait:
  407.         mcall   23                                                      ; Wait for event with timeout
  408. read_packet:                                                            ; we have data - this will be the response
  409.         lea     edx, [rx_msg]
  410.         mcall   75, 7, [ebp + interface.socketNum], , BUFFER, MSG_DONTWAIT    ; read data from socket
  411.         cmp     eax, -1
  412.         jne     .got_data
  413.  
  414.         mcall   26, 9
  415.         mov     ebx, eax
  416.         sub     ebx, [ebp + interface.timeout]
  417.         ja      send_dhcp_packet.wait
  418.  
  419.         DEBUGF  2, "No answer from DHCP server\n"
  420.         dec     [ebp + interface.tries]
  421.         jnz     send_dhcp_packet
  422.         jmp     dhcp_fail
  423.  
  424.   .got_data:
  425.         DEBUGF  1, "%d bytes received\n", eax
  426.         mov     [rx_msg_len], eax
  427.  
  428. ; depending on which msg we sent, handle the response
  429. ; accordingly.
  430. ; If the response is to a dhcp discover, then:
  431. ;  1) If response is DHCP OFFER then
  432. ;  1.1) record server IP, lease time & IP address.
  433. ;  1.2) send a request packet
  434. ; If the response is to a dhcp request, then:
  435. ;  1) If the response is DHCP ACK then
  436. ;  1.1) extract the DNS & subnet fields. Set them in the stack
  437.  
  438.         cmp     [tx_msg_type], 1                ; did we send a discover?
  439.         je      discover_sent
  440.         cmp     [tx_msg_type], 3                ; did we send a request?
  441.         je      request_sent
  442.         jmp     exit_immediately
  443.  
  444. discover_sent:
  445.         call    parse_dhcp_reply
  446.         cmp     [rx_msg_type], 2                ; Was the response an offer?
  447.         jne     read_packet
  448.  
  449.         DEBUGF  1, "Got offer, making request\n"
  450.         mov     [tx_msg_type], 3                ; make it a request
  451.         jmp     build_dhcp_packet
  452.  
  453. request_sent:
  454.         call    parse_dhcp_reply
  455.         cmp     [rx_msg_type], 5                ; Was the response an ACK? It should be
  456.         jne     read_packet                     ; NO - read next packets
  457.  
  458.         DEBUGF  2, "IP assigned by DHCP server successfully\n"
  459.  
  460.         mcall   close, [ebp + interface.socketNum]
  461.  
  462.         mov     ebx, API_IPv4 + 3
  463.         mov     bh, byte[ebp + interface.number]
  464.         mcall   76, , [ebp + interface.ip]            ; ip
  465.         mov     bl, 5
  466.         mcall   76, , [ebp + interface.subnet]        ; subnet
  467.         mov     bl, 9
  468.         mcall   76, , [ebp + interface.gateway]       ; gateway
  469.  
  470.         invoke  ini.get_str, ini_path, str_ini_int, str_dns_type, inibuf, 16, str_null
  471.         test    eax, eax
  472.         jnz     @f
  473.         mov     eax, dword[inibuf]
  474.         or      eax, 0x202020
  475.         cmp     eax, 'stat'
  476.         je      static.dns
  477.   @@:
  478.         mcall   76, , [ebp + interface.dns]           ; dns
  479.         mov     bl, 7
  480.  
  481.         jmp     link_up
  482.  
  483.  
  484. parse_dhcp_reply:
  485.  
  486.         DEBUGF  1, "Parsing response\n"
  487.         mov     [rx_msg_type], 0
  488.  
  489. ; Verify if session ID matches
  490.         mov     eax, [tx_msg.xid]
  491.         cmp     [rx_msg.xid], eax
  492.         jne     .done
  493.  
  494.         pushd   [rx_msg.yiaddr]
  495.         pop     [ebp + interface.ip]
  496.         DEBUGF  1, "Client: %u.%u.%u.%u\n", \
  497.         [rx_msg.yiaddr]:1, [rx_msg.yiaddr+1]:1, [rx_msg.yiaddr+2]:1, [rx_msg.yiaddr+3]:1
  498.  
  499. ; Verify magic cookie
  500.         cmp     [rx_msg.cookie], 0x63538263
  501.         jne     .done
  502.  
  503. ; Parse the DHCP options
  504.         lea     esi, [rx_msg]
  505.         mov     ecx, 240                        ; point to the first option
  506.   .next_option:
  507. ; TODO: check if we still are inside the buffer!
  508.         add     esi, ecx
  509.  
  510.         lodsb                                   ; get message identifier
  511.         mov     bl, al
  512.         cmp     bl, 0xff                        ; End of options?
  513.         je      .done
  514.         test    bl, bl
  515.         jz      .pad
  516.  
  517.         lodsb                                   ; load data length
  518.         movzx   ecx, al
  519.         cmp     bl, dhcp_msg_type               ; Msg type is a single byte option
  520.         je      .msgtype
  521.         cmp     bl, dhcp_dhcp_server_id
  522.         je      .server
  523.         cmp     bl, dhcp_address_time
  524.         je      .lease
  525.         cmp     bl, dhcp_subnet_mask
  526.         je      .subnet
  527.         cmp     bl, dhcp_router
  528.         je      .router
  529.         cmp     bl, dhcp_domain_server
  530.         je      .dns
  531.  
  532.         DEBUGF  1, "Unsupported DHCP option: %u\n", bl
  533.         jmp     .next_option
  534.  
  535.   .pad:
  536.         xor     ecx, ecx
  537.         inc     ecx
  538.         jmp     .next_option
  539.  
  540.   .msgtype:
  541.         mov     al, [esi]
  542.         mov     [rx_msg_type], al
  543.  
  544.         DEBUGF  1, "DHCP Msg type: %u\n", al
  545.         jmp     .next_option                    ; Get next option
  546.  
  547.   .server:
  548.         pushd   [esi]
  549.         pop     [ebp + interface.ServerIP]
  550.         DEBUGF  1, "Server: %u.%u.%u.%u\n", [esi]:1, [esi+1]:1, [esi+2]:1, [esi+3]:1
  551.         jmp     .next_option
  552.  
  553.   .lease:
  554.         pusha
  555.         mov     eax,[esi]
  556.         bswap   eax
  557.         mov     [ebp + interface.lease], eax
  558.         DEBUGF  1, "Lease: %d\n", eax
  559.         popa
  560.         jmp     .next_option
  561.  
  562.   .subnet:
  563.         pushd   [esi]
  564.         pop     [ebp + interface.subnet]
  565.         DEBUGF  1, "Subnet: %u.%u.%u.%u\n", [esi]:1, [esi+1]:1, [esi+2]:1, [esi+3]:1
  566.         jmp     .next_option
  567.  
  568.   .router:
  569.         pushd   [esi]
  570.         pop     [ebp + interface.gateway]
  571.         DEBUGF  1, "Gateway: %u.%u.%u.%u\n", [esi]:1, [esi+1]:1, [esi+2]:1, [esi+3]:1
  572.         jmp     .next_option
  573.  
  574.   .dns:
  575.         pushd   [esi]
  576.         pop     [ebp + interface.dns]
  577.         DEBUGF  1, "DNS: %u.%u.%u.%u\n", [esi]:1, [esi+1]:1, [esi+2]:1, [esi+3]:1
  578.         jmp     .next_option
  579.  
  580.   .done:
  581.         ret
  582.  
  583. exit_immediately:
  584.         DEBUGF  2, "Zeroconf failed!\n"
  585.         mcall   -1
  586.  
  587. socket_error:
  588.         DEBUGF  2, "Socket error!\n"
  589.  
  590. dhcp_fail:
  591.         mcall   close, [ebp + interface.socketNum]
  592.  
  593. dhcp_error:
  594.         DEBUGF  1, "DHCP failed\n"
  595.         cmp     [ebp + interface.mode], 2               ; zero config mode?
  596.         jne     link_up
  597.  
  598. link_local:
  599.  
  600. ; TODO: send ARP probes before setting the IP address in stack!
  601.  
  602.         call    random
  603.         mov     cx, ax
  604.         shl     ecx, 16
  605.         mov     cx, 0xfea9                              ; IP 169.254.0.0 link local net, see RFC3927
  606.         mov     ebx, API_IPv4 + 3
  607.         mov     bh, byte[ebp + interface.number]
  608.         mcall   76, , ecx                               ; mask is 255.255.0.0
  609.         DEBUGF  2, "Link Local IP assigned: 169.254.%u.%u\n", [generator+0]:1, [generator+1]:1
  610.         mov     bl, 7
  611.         mcall   76, , 0xffff
  612.         mov     bl, 9
  613.         mcall   76, , 0x0
  614.         mov     bl, 5
  615.         mcall   76, , 0x0
  616.  
  617.         jmp     link_up
  618.  
  619.  
  620. random:  ; Pseudo random actually
  621.  
  622.         mov     eax,[generator]
  623.         add     eax, -43ab45b5h
  624.         ror     eax, 1
  625.         bswap   eax
  626.         xor     eax, dword[tx_msg.chaddr]
  627.         ror     eax, 1
  628.         xor     eax, dword[tx_msg.chaddr+2]
  629.         mov     [generator], eax
  630.  
  631.         ret
  632.  
  633.  
  634.  
  635. create_str_ini_int:
  636.         mov     eax, [ebp + interface.number]
  637.         mov     ebx, 10
  638.         xor     edx, edx
  639.         push    0
  640.   @@:
  641.         div     ebx
  642.         add     dl, '0'
  643.         push    edx
  644.         test    eax, eax
  645.         jnz     @r
  646.   @@:
  647.         mov     edi, str_ini_int+2
  648.   @@:
  649.         pop     eax
  650.         stosb
  651.         test    eax, eax
  652.         jnz     @r
  653.  
  654.         ret
  655.  
  656.  
  657.  
  658. ; In: esi = ptr to ASCIIZ IP address
  659. ; Out: ecx = IP (0 on error)
  660.  
  661. ip_str_to_dword:
  662.  
  663.         xor     ecx, ecx        ; end result
  664.   .charloop:
  665.         lodsb
  666.         test    al, al
  667.         jz      .finish
  668.         cmp     al, '.'
  669.         je      .dot
  670.         sub     al, '0'
  671.         jb      .fail
  672.         cmp     al, 9
  673.         ja      .fail
  674.         mov     dl, cl
  675.         shl     cl, 2
  676.         jc      .fail
  677.         add     cl, dl
  678.         jc      .fail
  679.         add     cl, cl
  680.         jc      .fail
  681.         add     cl, al
  682.         jc      .fail
  683.         jmp     .charloop
  684.   .dot:
  685.         shl     ecx, 8
  686.         jc      .fail
  687.         xor     cl, cl
  688.         jmp     .charloop
  689.   .finish:
  690.         bswap   ecx             ; we want little endian order
  691.         ret
  692.  
  693.   .fail:
  694.         xor     ecx, ecx
  695.         ret
  696.  
  697. ; DATA AREA
  698.  
  699. align 16
  700. @IMPORT:
  701.  
  702. library \
  703.         libini,         'libini.obj'
  704.  
  705. import  libini, \
  706.         ini.get_str,    'ini_get_str',\
  707.         ini.set_str,    'ini_set_str'
  708.  
  709. include_debug_strings
  710.  
  711. str_ip          db 'ip', 0
  712. str_subnet      db 'subnet', 0
  713. str_gateway     db 'gateway', 0
  714. str_dns         db 'dns', 0
  715.  
  716. str_ip_type     db 'ip_type', 0
  717. str_dns_type    db 'dns_type', 0
  718.  
  719. str_ini_int     db 'ip1', 0
  720.                 rb 10
  721.  
  722. str_null        db 0
  723.  
  724. sock_local:
  725.         dw AF_INET4
  726.         dw 68 shl 8     ; local port
  727.         dd 0            ; local IP
  728.         rb 10
  729.  
  730.  
  731. sock_remote:
  732.         dw AF_INET4
  733.         dw 67 shl 8     ; destination port
  734.         dd -1           ; destination IP
  735.         rb 10
  736.  
  737. notify_struct:
  738.         dd 7            ; run application
  739.         dd 0
  740.  .msg   dd 0
  741.         dd 0
  742.         dd 0
  743.         db '/sys/@notify', 0
  744.  
  745. str_connected           db '"You are now connected to the network." -N', 0
  746. str_disconnected        db '"You are now disconnected from the network." -N', 0
  747. str_conflict            db '"An IP address conflict has been detected on the network." -W', 0
  748.  
  749. ini_path                db '/sys/settings/network.ini',0
  750.  
  751. IM_END:
  752.  
  753. generator       dd ?
  754.  
  755. inibuf          rb 16
  756.  
  757. tx_msg_len      dd ?
  758. rx_msg_len      dd ?
  759. tx_msg_type     db ?
  760. rx_msg_type     db ?
  761. tx_msg          dhcp_msg
  762. rx_msg          dhcp_msg
  763.  
  764. device_list     rd MAX_INTERFACES*sizeof.interface
  765.  
  766. I_END: