[Openmcl-devel] Useful code: get info about network interfaces on Windows.

Kaz Kylheku kaz at kylheku.com
Mon Nov 1 09:46:20 PDT 2010


I found that the IP helper API is not represented in the FFI database, 
so
I hacked this up. Share, criticize, improve ...

Is there a nicer way to handle the len-inout variable? I define it in 
a stack block as a region of the length of :unsigned-long and then set 
its initial value using (setf (%get-unsigned-long ...) ...).

I'd like to just RLET it to be of type #>ULONG and then assign to it 
without mentioning the type in the assignment.

Sample run:

? (get-network-interface-list)
(((144 230 186 208 255 3) (("192.168.1.103" "255.255.255.0"))
  "{BB3E5BE7-4409-4DCC-A96D-FCAD6F80CFBF}"
  "ASUS 802.11 g/b Wireless PCI Adapter")
 ((0 255 163 4 251 147) (("0.0.0.0" "0.0.0.0"))
  "{A304FB93-661E-4C64-BD4C-4988FFF93571}" "TAP-Win32 Adapter V8")
 ((0 255 217 143 238 242) (("0.0.0.0" "0.0.0.0"))
  "{D98FEEF2-3050-45C4-A819-13D583E29F24}" "TAP-Win32 Adapter V9")
 ((0 25 33 80 198 222) (("0.0.0.0" "0.0.0.0"))
  "{49C3B646-9DDD-48CC-9F72-73B8A4DFDF00}"
  "Marvell Yukon 88E8056 PCI-E Gigabit Ethernet Controller")
 ((0 80 86 192 0 1) (("169.254.205.164" "255.255.0.0"))
  "{78D5CAA7-B278-4358-BA60-B4403AB9F635}"
  "VMware Virtual Ethernet Adapter for VMnet1")
 ((0 80 86 192 0 8) (("192.168.206.1" "255.255.255.0"))
  "{31C44EA6-F6D8-44AE-8998-0469EF6FF32D}"
  "VMware Virtual Ethernet Adapter for VMnet8")
 ((8 0 39 0 20 110) (("192.168.56.1" "255.255.255.0"))
  "{B20AEB46-8C0B-4A34-8104-84968E222F89}"
  "VirtualBox Host-Only Ethernet Adapter"))


Microsoft consistency. IP addresses in text, link addresses in binary!


Source:

(eval-when (:compile-toplevel :load-toplevel :execute)
  (open-shared-library "iphlpapi.dll")
  (defconstant MAX_ADAPTER_NAME_LENGTH 256)
  (defconstant MAX_ADAPTER_DESCRIPTION_LENGTH 128)
  (defconstant MAX_ADAPTER_ADDRESS_LENGTH 8))


(def-foreign-type #>IP_ADDR_STRING
  (struct #>IP_ADDR_STRING
    (#>Next :address)
    (#>IpAddress (:array :char 16))
    (#>IpMask (:array :char 16))
    (#>Context #>DWORD)))

(def-foreign-type #>IP_ADAPTER_INFO
  (struct #>IP_ADAPTER_INFO
    (#>Next :address)
    (#>ComboIndex #>DWORD)
    (#>AdapterName (:array :char #.(+ MAX_ADAPTER_NAME_LENGTH 4)))
    (#>Description (:array :char #.(+ MAX_ADAPTER_DESCRIPTION_LENGTH 
4)))
    (#>AddressLength #>UINT)
    (#>Address (:array BYTE #.(+ MAX_ADAPTER_ADDRESS_LENGTH)))
    (#>Index #>DWORD)
    (#>Type #>UINT)
    (#>DhcpEnabled #>UINT)
    (#>CurrentIpAddress :address)
    (#>IpAddressList #>IP_ADDR_STRING)
    #| ... other members omitted ... |# ))


(defun get-ip-address-list (first)
  (loop for ptr = first then (pref ptr #>IP_ADDR_STRING.Next)
        until (%null-ptr-p ptr)
        collecting
          (let ((addr (pref ptr #>IP_ADDR_STRING.IpAddress))
                (mask (pref ptr #>IP_ADDR_STRING.IpMask)))
            (list (%get-cstring addr) (%get-cstring mask)))))


(defun get-network-interface-list ()
  (let ((blk-size 65536) ;; crude!
        (get-adapters-info (foreign-symbol-address 
"GetAdaptersInfo")))
      (if get-adapters-info
        (%stack-block ((blk blk-size)
                       (len-inout (ccl::record-length 
:unsigned-long)))
          (setf (%get-unsigned-long len-inout) blk-size)
          (if (zerop (ff-call get-adapters-info :address blk
                                                :address len-inout
                                                #>DWORD))
            (loop for ptr = blk then (pref ptr #>IP_ADAPTER_INFO.Next)
                  until (%null-ptr-p ptr)
                  collecting
                    (let ((alen (pref ptr 
#>IP_ADAPTER_INFO.AddressLength))
                          (addr (pref ptr #>IP_ADAPTER_INFO.Address))
                          (aname (pref ptr 
#>IP_ADAPTER_INFO.AdapterName))
                          (descr (pref ptr 
#>IP_ADAPTER_INFO.Description))
                          (iplist (pref ptr 
#>IP_ADAPTER_INFO.IpAddressList)))
                      (list (loop for i below alen
                                  collecting (%get-unsigned-byte addr 
i))
                            (get-ip-address-list iplist)
                            (%get-cstring aname)
                            (%get-cstring descr)))))))))




More information about the Openmcl-devel mailing list