Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2010-2016. 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                 = 5             ; 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 - disabled, 1 - static, 2 - dhcp, 3 - 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     .invalid
  179.         mov     eax, dword[inibuf]
  180.         or      eax, 0x20202020
  181.         mov     [ebp + interface.mode], 0
  182.         cmp     eax, 'disa'
  183.         je      .next
  184.         mov     [ebp + interface.mode], 1
  185.         cmp     eax, 'stat'
  186.         je      static
  187.         mov     [ebp + interface.mode], 2
  188.         cmp     eax, 'dhcp'
  189.         je      dhcp
  190.         mov     [ebp + interface.mode], 3
  191.         cmp     eax, 'auto'
  192.         je      dhcp
  193.  
  194.   .invalid:
  195.         DEBUGF  2, "Invalid settings for interface: %s.\n", str_ini_int
  196.         jmp     .next
  197.  
  198.   .maintain_link:
  199.  
  200. ; Check for IP conflicts
  201.         mov     ebx, API_ARP
  202.         mov     bh, byte[ebp + interface.number]
  203.         mov     bl, 7
  204.         mcall   76                      ; Number of IP conflicts
  205.         cmp     eax, [ebp + interface.ip_conflicts]
  206.         je      @f
  207.         mov     [ebp + interface.ip_conflicts], eax
  208.         DEBUGF  2, "IP address conflict on interface %u\n", [ebp + interface.number]
  209.         ; Notify user of the IP address conflict
  210.         mov     [notify_struct.msg], str_conflict
  211.         mcall   70, notify_struct
  212.   @@:
  213.  
  214. ; Check if device is still there
  215.         mov     bh, byte[ebp + interface.number]
  216.         mov     bl, 0                   ; Get device type
  217.         mcall   74
  218.         test    eax, eax                ; No device
  219.         jz      .link_down
  220.  
  221. ; Check if link is still there
  222.         mov     bl, 10                  ; Get Link status
  223.         mcall   74
  224.         test    eax, eax
  225.         jnz     .next
  226.  
  227.   .link_down:
  228.         mov     [ebp + interface.state], 0
  229.  
  230. ; Notify user that the link is down
  231.         mov     [notify_struct.msg], str_disconnected
  232.         mcall   70, notify_struct
  233.  
  234. ; CHECKME: should we do this in kernel instead? Should we even do this at all?
  235.         xor     ecx, ecx
  236.         mov     ebx, API_IPv4 + 3
  237.         mov     bh, byte[ebp + interface.number]
  238.         mcall   76                      ; ip
  239.         mov     bl, 5
  240.         mcall   76                      ; dns
  241.         mov     bl, 7
  242.         mcall   76                      ; subnet
  243.         mov     bl, 9
  244.         mcall   76                      ; gateway
  245.  
  246.         jmp     .next
  247.  
  248. link_up:
  249.  
  250. ; Read number of previous IP conflicts
  251.         mov     ebx, API_ARP
  252.         mov     bh, byte[ebp + interface.number]
  253.         mov     bl, 7
  254.         mcall   76
  255.         mov     [ebp + interface.ip_conflicts], eax
  256.  
  257. ; Notify user that the link is up and running
  258.         mov     [notify_struct.msg], str_connected
  259.         mcall   70, notify_struct
  260.  
  261.   .fail:
  262.         mcall   40, EVM_STACK2
  263.         jmp     mainloop.next
  264.  
  265. static:
  266.         DEBUGF  1, "Applying Static IP settings\n"
  267.  
  268.         invoke  ini.get_str, ini_path, str_ini_int, str_ip, inibuf, 16, str_null
  269.         mov     esi, inibuf
  270.         call    ip_str_to_dword
  271.         mov     ebx, API_IPv4 + 3       ; set IP
  272.         mov     bh, byte[ebp + interface.number]
  273.         mcall   76
  274.  
  275.         invoke  ini.get_str, ini_path, str_ini_int, str_subnet, inibuf, 16, str_null
  276.         mov     esi, inibuf
  277.         call    ip_str_to_dword
  278.         mov     ebx, API_IPv4 + 7       ; set subnet
  279.         mov     bh, byte[ebp + interface.number]
  280.         mcall   76
  281.  
  282.         invoke  ini.get_str, ini_path, str_ini_int, str_gateway, inibuf, 16, str_null
  283.         mov     esi, inibuf
  284.         call    ip_str_to_dword
  285.         mov     ebx, API_IPv4 + 9       ; set gateway
  286.         mov     bh, byte[ebp + interface.number]
  287.         mcall   76
  288.  
  289.   .dns:
  290.         invoke  ini.get_str, ini_path, str_ini_int, str_dns, inibuf, 16, str_null
  291.         mov     esi, inibuf
  292.         call    ip_str_to_dword
  293.         mov     ebx, API_IPv4 + 5       ; set DNS
  294.         mov     bh, byte[ebp + interface.number]
  295.         mcall   76
  296.  
  297.         jmp     link_up
  298.  
  299.  
  300. dhcp:
  301.  
  302.         DEBUGF  2, "Trying to contact DHCP server\n"
  303.  
  304.         mcall   40, EVM_STACK
  305.  
  306.         mcall   75, 0, AF_INET4, SOCK_DGRAM, 0                          ; open socket (parameters: domain, type, reserved)
  307.         cmp     eax, -1
  308.         je      dhcp_error
  309.         mov     [ebp + interface.socketNum], eax
  310.  
  311.         DEBUGF  1, "Socket %x opened\n", eax
  312.  
  313.         mcall   75, 2, [ebp + interface.socketNum], sock_local, 18      ; bind socket to local port 68
  314.         cmp     eax, -1
  315.         je      socket_error
  316.  
  317.         DEBUGF  1, "Socket Bound to local port 68\n"
  318.  
  319.         pushd   [ebp + interface.number]
  320.         pushd   4                       ; length of option
  321.         pushd   SO_BINDTODEVICE
  322.         pushd   SOL_SOCKET
  323.         mcall   75, 8, [ebp + interface.socketNum], esp
  324.         add     esp, 16
  325.         cmp     eax, -1
  326.         je      socket_error
  327.  
  328.         DEBUGF  1, "Socket Bound to local interface %u\n", [ebp + interface.number]
  329.  
  330.         mcall   75, 4, [ebp + interface.socketNum], sock_remote, 18     ; connect to 255.255.255.255 on port 67
  331.         cmp     eax, -1
  332.         je      socket_error
  333.  
  334.         DEBUGF  1, "Connected to 255.255.255.255 on port 67\n"
  335.  
  336.         ; Read preferred IP address from settings file
  337.         invoke  ini.get_str, ini_path, str_ini_int, str_ip, inibuf, 16, str_null
  338.         mov     esi, inibuf
  339.         call    ip_str_to_dword
  340.         mov     [ebp + interface.ip], ecx
  341.  
  342.         call    random
  343.         mov     [tx_msg.xid], eax                                       ; randomize session ID
  344.         mov     [tx_msg_type], 1                                        ; DHCP discover
  345.  
  346. build_dhcp_packet:
  347.  
  348.         DEBUGF  1, "Building DHCP packet\n"
  349.  
  350.         mov     [ebp + interface.tries], DHCP_TRIES
  351.  
  352.         ; Boot protocol legacy
  353.         mov     [tx_msg.op], 1                                          ; Boot request
  354.         mov     [tx_msg.htype], 1                                       ; Ethernet
  355.         mov     [tx_msg.hlen], 6                                        ; Ethernet address h/w len
  356.         mov     [tx_msg.hops], 0
  357.         mcall   26, 9                                                   ; Time since boot
  358.         xor     edx, edx
  359.         mov     ebx, 100
  360.         div     ebx                                                     ; Divide by 100 to get number of seconds
  361.         mov     [tx_msg.secs], ax
  362.         mov     [tx_msg.flags], 0
  363.  
  364.         ; DHCP extension
  365.         mov     [tx_msg.cookie], 0x63538263                             ; magic cookie
  366.  
  367.         mov     word[tx_msg+240], 0x0135                                ; option DHCP msg type
  368.         mov     al,[tx_msg_type]
  369.         mov     [tx_msg+240+2], al
  370.  
  371.         mov     word[tx_msg+240+3], 0x0433                              ; option Lease time
  372.         mov     dword[tx_msg+240+5], -1                                 ; infinite
  373.  
  374.         mov     word[tx_msg+240+9], 0x0432                              ; option requested IP address
  375.         mov     eax,[ebp + interface.ip]
  376.         mov     [tx_msg+240+11], eax
  377.  
  378.         mov     word[tx_msg+240+15], 0x0437                             ; option request list
  379.         mov     dword[tx_msg+240+17], 0x0f060301
  380.  
  381.         cmp     [tx_msg_type], 1                                        ; Check which msg we are sending
  382.         jne     .request
  383.  
  384.         mov     byte[tx_msg+240+21], 0xff                               ; end of options marker
  385.  
  386.         mov     [tx_msg_len], 262                                       ; length
  387.         jmp     send_dhcp_packet
  388.  
  389.   .request:
  390.         mov     word[tx_msg+240+21], 0x0436                             ; server IP
  391.         mov     eax,[ebp + interface.ServerIP]
  392.         mov     [tx_msg+240+23], eax
  393.  
  394.         mov     byte[tx_msg+240+27], 0xff                               ; end of options marker
  395.  
  396.         mov     [tx_msg_len], 268                                       ; length
  397.  
  398.  
  399. send_dhcp_packet:
  400.         DEBUGF  1, "Sending DHCP packet\n"
  401.         lea     edx, [tx_msg]
  402.         mcall   75, 6, [ebp + interface.socketNum], , [tx_msg_len]
  403.  
  404. ; Wait for reply
  405.         mcall   26, 9
  406.         add     eax, TIMEOUT*100
  407.         mov     [ebp + interface.timeout], eax
  408.         mov     ebx, TIMEOUT*100
  409.   .wait:
  410.         mcall   23                                                      ; Wait for event with timeout
  411. read_packet:                                                            ; we have data - this will be the response
  412.         lea     edx, [rx_msg]
  413.         mcall   75, 7, [ebp + interface.socketNum], , BUFFER, MSG_DONTWAIT    ; read data from socket
  414.         cmp     eax, -1
  415.         jne     .got_data
  416.  
  417.         mcall   26, 9
  418.         mov     ebx, eax
  419.         sub     ebx, [ebp + interface.timeout]
  420.         ja      send_dhcp_packet.wait
  421.  
  422.         DEBUGF  1, "No answer from DHCP server\n"
  423.         dec     [ebp + interface.tries]
  424.         jnz     send_dhcp_packet
  425.         jmp     dhcp_fail
  426.  
  427.   .got_data:
  428.         DEBUGF  1, "%d bytes received\n", eax
  429.         mov     [rx_msg_len], eax
  430.  
  431. ; depending on which msg we sent, handle the response
  432. ; accordingly.
  433. ; If the response is to a dhcp discover, then:
  434. ;  1) If response is DHCP OFFER then
  435. ;  1.1) record server IP, lease time & IP address.
  436. ;  1.2) send a request packet
  437. ; If the response is to a dhcp request, then:
  438. ;  1) If the response is DHCP ACK then
  439. ;  1.1) extract the DNS & subnet fields. Set them in the stack
  440.  
  441.         cmp     [tx_msg_type], 1                ; did we send a discover?
  442.         je      discover_sent
  443.         cmp     [tx_msg_type], 3                ; did we send a request?
  444.         je      request_sent
  445.         jmp     exit_immediately
  446.  
  447. discover_sent:
  448.         call    parse_dhcp_reply
  449.         cmp     [rx_msg_type], 2                ; Was the response an offer?
  450.         jne     read_packet
  451.  
  452.         DEBUGF  1, "Got offer, making request\n"
  453.         mov     [tx_msg_type], 3                ; make it a request
  454.         jmp     build_dhcp_packet
  455.  
  456. request_sent:
  457.         call    parse_dhcp_reply
  458.         cmp     [rx_msg_type], 5                ; Was the response an ACK? It should be
  459.         jne     read_packet                     ; NO - read next packets
  460.  
  461.         DEBUGF  2, "IP address %u.%u.%u.%u assigned to network interface %u by DHCP\n",\
  462.         [ebp+interface.ip+0]:1, [ebp+interface.ip+1]:1, [ebp+interface.ip+2]:1, [ebp+interface.ip+3]:1, [ebp + interface.number]:1
  463.  
  464.         mcall   close, [ebp + interface.socketNum]
  465.  
  466.         mov     ebx, API_IPv4 + 3
  467.         mov     bh, byte[ebp + interface.number]
  468.         mcall   76, , [ebp + interface.ip]            ; ip
  469.         mov     bl, 7
  470.         mcall   76, , [ebp + interface.subnet]        ; subnet
  471.         mov     bl, 9
  472.         mcall   76, , [ebp + interface.gateway]       ; gateway
  473.  
  474.         invoke  ini.get_str, ini_path, str_ini_int, str_dns_type, inibuf, 16, str_null
  475.         test    eax, eax
  476.         jnz     @f
  477.         mov     eax, dword[inibuf]
  478.         or      eax, 0x202020
  479.         cmp     eax, 'stat'
  480.         je      static.dns
  481.   @@:
  482.         mov     ebx, API_IPv4 + 5
  483.         mov     bh, byte[ebp + interface.number]
  484.         mcall   76, , [ebp + interface.dns]           ; dns
  485.  
  486.         jmp     link_up
  487.  
  488.  
  489. parse_dhcp_reply:
  490.  
  491.         DEBUGF  1, "Parsing response\n"
  492.         mov     [rx_msg_type], 0
  493.  
  494. ; Verify if session ID matches
  495.         mov     eax, [tx_msg.xid]
  496.         cmp     [rx_msg.xid], eax
  497.         jne     .done
  498.  
  499.         pushd   [rx_msg.yiaddr]
  500.         pop     [ebp + interface.ip]
  501.         DEBUGF  1, "Client: %u.%u.%u.%u\n", \
  502.         [rx_msg.yiaddr]:1, [rx_msg.yiaddr+1]:1, [rx_msg.yiaddr+2]:1, [rx_msg.yiaddr+3]:1
  503.  
  504. ; Verify magic cookie
  505.         cmp     [rx_msg.cookie], 0x63538263
  506.         jne     .done
  507.  
  508. ; Parse the DHCP options
  509.         lea     esi, [rx_msg]
  510.         mov     ecx, 240                        ; point to the first option
  511.   .next_option:
  512. ; TODO: check if we still are inside the buffer!
  513.         add     esi, ecx
  514.  
  515.         lodsb                                   ; get message identifier
  516.         mov     bl, al
  517.         cmp     bl, 0xff                        ; End of options?
  518.         je      .done
  519.         test    bl, bl
  520.         jz      .pad
  521.  
  522.         lodsb                                   ; load data length
  523.         movzx   ecx, al
  524.         cmp     bl, dhcp_msg_type               ; Msg type is a single byte option
  525.         je      .msgtype
  526.         cmp     bl, dhcp_dhcp_server_id
  527.         je      .server
  528.         cmp     bl, dhcp_address_time
  529.         je      .lease
  530.         cmp     bl, dhcp_subnet_mask
  531.         je      .subnet
  532.         cmp     bl, dhcp_router
  533.         je      .router
  534.         cmp     bl, dhcp_domain_server
  535.         je      .dns
  536.  
  537.         DEBUGF  1, "Unsupported DHCP option: %u\n", bl
  538.         jmp     .next_option
  539.  
  540.   .pad:
  541.         xor     ecx, ecx
  542.         inc     ecx
  543.         jmp     .next_option
  544.  
  545.   .msgtype:
  546.         mov     al, [esi]
  547.         mov     [rx_msg_type], al
  548.  
  549.         DEBUGF  1, "DHCP Msg type: %u\n", al
  550.         jmp     .next_option                    ; Get next option
  551.  
  552.   .server:
  553.         pushd   [esi]
  554.         pop     [ebp + interface.ServerIP]
  555.         DEBUGF  1, "Server: %u.%u.%u.%u\n", [esi]:1, [esi+1]:1, [esi+2]:1, [esi+3]:1
  556.         jmp     .next_option
  557.  
  558.   .lease:
  559.         pusha
  560.         mov     eax,[esi]
  561.         bswap   eax
  562.         mov     [ebp + interface.lease], eax
  563.         DEBUGF  1, "Lease: %d\n", eax
  564.         popa
  565.         jmp     .next_option
  566.  
  567.   .subnet:
  568.         pushd   [esi]
  569.         pop     [ebp + interface.subnet]
  570.         DEBUGF  1, "Subnet: %u.%u.%u.%u\n", [esi]:1, [esi+1]:1, [esi+2]:1, [esi+3]:1
  571.         jmp     .next_option
  572.  
  573.   .router:
  574.         pushd   [esi]
  575.         pop     [ebp + interface.gateway]
  576.         DEBUGF  1, "Gateway: %u.%u.%u.%u\n", [esi]:1, [esi+1]:1, [esi+2]:1, [esi+3]:1
  577.         jmp     .next_option
  578.  
  579.   .dns:
  580.         pushd   [esi]
  581.         pop     [ebp + interface.dns]
  582.         DEBUGF  1, "DNS: %u.%u.%u.%u\n", [esi]:1, [esi+1]:1, [esi+2]:1, [esi+3]:1
  583.         jmp     .next_option
  584.  
  585.   .done:
  586.         ret
  587.  
  588. exit_immediately:
  589.         DEBUGF  2, "Zeroconf failed!\n"
  590.         mcall   -1
  591.  
  592. socket_error:
  593.         DEBUGF  2, "Socket error!\n"
  594.  
  595. dhcp_fail:
  596.         mcall   close, [ebp + interface.socketNum]
  597.  
  598. dhcp_error:
  599.         DEBUGF  2, "DHCP failed\n"
  600.         cmp     [ebp + interface.mode], 3               ; zero config mode?
  601.         jne     link_up
  602.  
  603. link_local:
  604.  
  605. ; TODO: send ARP probes before setting the IP address in stack!
  606.  
  607.         call    random
  608.         mov     cx, ax
  609.         shl     ecx, 16
  610.         mov     cx, 0xfea9                              ; IP 169.254.0.0 link local net, see RFC3927
  611.         mov     ebx, API_IPv4 + 3
  612.         mov     bh, byte[ebp + interface.number]
  613.         mcall   76, , ecx                               ; mask is 255.255.0.0
  614.         DEBUGF  2, "IP address 169.254.%u.%u assigned to network interface %u through Link-Local\n",\
  615.         [generator+0]:1, [generator+1]:1, [ebp + interface.number]:1
  616.         mov     bl, 7
  617.         mcall   76, , 0xffff
  618.         mov     bl, 9
  619.         mcall   76, , 0x0
  620.         mov     bl, 5
  621.         mcall   76, , 0x0
  622.  
  623.         jmp     link_up
  624.  
  625.  
  626. random:  ; Pseudo random actually
  627.  
  628.         mov     eax,[generator]
  629.         add     eax, -43ab45b5h
  630.         ror     eax, 1
  631.         bswap   eax
  632.         xor     eax, dword[tx_msg.chaddr]
  633.         ror     eax, 1
  634.         xor     eax, dword[tx_msg.chaddr+2]
  635.         mov     [generator], eax
  636.  
  637.         ret
  638.  
  639.  
  640.  
  641. create_str_ini_int:
  642.         mov     eax, [ebp + interface.number]
  643.         mov     ebx, 10
  644.         xor     edx, edx
  645.         push    0
  646.   @@:
  647.         div     ebx
  648.         add     dl, '0'
  649.         push    edx
  650.         test    eax, eax
  651.         jnz     @r
  652.   @@:
  653.         mov     edi, str_ini_int+2
  654.   @@:
  655.         pop     eax
  656.         stosb
  657.         test    eax, eax
  658.         jnz     @r
  659.  
  660.         ret
  661.  
  662.  
  663.  
  664. ; In: esi = ptr to ASCIIZ IP address
  665. ; Out: ecx = IP (0 on error)
  666.  
  667. ip_str_to_dword:
  668.  
  669.         xor     ecx, ecx        ; end result
  670.   .charloop:
  671.         lodsb
  672.         test    al, al
  673.         jz      .finish
  674.         cmp     al, '.'
  675.         je      .dot
  676.         sub     al, '0'
  677.         jb      .fail
  678.         cmp     al, 9
  679.         ja      .fail
  680.         mov     dl, cl
  681.         shl     cl, 2
  682.         jc      .fail
  683.         add     cl, dl
  684.         jc      .fail
  685.         add     cl, cl
  686.         jc      .fail
  687.         add     cl, al
  688.         jc      .fail
  689.         jmp     .charloop
  690.   .dot:
  691.         shl     ecx, 8
  692.         jc      .fail
  693.         xor     cl, cl
  694.         jmp     .charloop
  695.   .finish:
  696.         bswap   ecx             ; we want little endian order
  697.         ret
  698.  
  699.   .fail:
  700.         xor     ecx, ecx
  701.         ret
  702.  
  703. ; DATA AREA
  704.  
  705. align 16
  706. @IMPORT:
  707.  
  708. library \
  709.         libini,         'libini.obj'
  710.  
  711. import  libini, \
  712.         ini.get_str,    'ini_get_str',\
  713.         ini.set_str,    'ini_set_str'
  714.  
  715. include_debug_strings
  716.  
  717. str_ip          db 'ip', 0
  718. str_subnet      db 'subnet', 0
  719. str_gateway     db 'gateway', 0
  720. str_dns         db 'dns', 0
  721.  
  722. str_ip_type     db 'ip_type', 0
  723. str_dns_type    db 'dns_type', 0
  724.  
  725. str_ini_int     db 'ip1', 0
  726.                 rb 10
  727.  
  728. str_null        db 0
  729.  
  730. sock_local:
  731.         dw AF_INET4
  732.         dw 68 shl 8     ; local port
  733.         dd 0            ; local IP
  734.         rb 10
  735.  
  736.  
  737. sock_remote:
  738.         dw AF_INET4
  739.         dw 67 shl 8     ; destination port
  740.         dd -1           ; destination IP
  741.         rb 10
  742.  
  743. notify_struct:
  744.         dd 7            ; run application
  745.         dd 0
  746.  .msg   dd 0
  747.         dd 0
  748.         dd 0
  749.         db '/sys/@notify', 0
  750.  
  751. str_connected           db '"You are now connected to the network." -N', 0
  752. str_disconnected        db '"You are now disconnected from the network." -N', 0
  753. str_conflict            db '"An IP address conflict has been detected on the network." -W', 0
  754.  
  755. ini_path                db '/sys/settings/network.ini',0
  756.  
  757. IM_END:
  758.  
  759. generator       dd ?
  760.  
  761. inibuf          rb 16
  762.  
  763. tx_msg_len      dd ?
  764. rx_msg_len      dd ?
  765. tx_msg_type     db ?
  766. rx_msg_type     db ?
  767. tx_msg          dhcp_msg
  768. rx_msg          dhcp_msg
  769.  
  770. device_list     rd MAX_INTERFACES*sizeof.interface
  771.  
  772. I_END: