Ottenere informazioni dal proprio dispositivo wireless con le risorse del API di libiw

Da Gambas-it.org - Wikipedia.

Utilizzando alcune risorse della libreria "libiw" è possibile ottenere alcune informazioni attinenti al proprio dispositivo wireless, come ad esempio poter controllare la portata e la copertura del router wireless di casa. Ciò può essere utile per trovare aree difficili, scarsamente coperte, cosìcché si possa migliorare la ricezione del segnale wireless spostando il router.

E' necessario avere installata e richiamare in Gambas la seguente libreria esterna condivisa: "libiw.so.30 ".

Mostriamo un semplice esempio:

Library "libiw:30"

Private Const SIOCGIWSENS As Integer = 35593
Private Const SIOCGIWAP As Integer = 35605
Private Const SIOCGIWRATE As Integer = 35617
Private Const SIOCGIWRTS As Integer = 35619
Private Const SIOCGIWFRAG As Integer = 35621
Private Const SIOCGIWTXPOW As Integer = 35623
Private Const SIOCGIWRETRY As Integer = 35625
Private Const SIOCGIWPOWER As Integer = 35629
Private Const IW_RETRY_TYPE As Integer = 61440
Private Const ENODEV As Integer = 19
Private Const ENOTSUP As Integer = 95

Private iw_operation_mode As String[] = ["Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary", "Monitor"]

' int iw_sockets_open(void)
Private Extern iw_sockets_open() As Integer

' void iw_enum_devices(int skfd, iw_enum_handler fn, char * args[], int count)
Private Extern iw_enum_devices(skfd As Integer, fn As Pointer, args As String[], count As Integer)

' int iw_get_basic_config(int skfd, const char * ifname, wireless_config * info)
Private Extern iw_get_basic_config(skfd As Integer, ifname As String, info As Pointer) As Integer

' int iw_get_range_info (int 	skfd, const char * ifname, iwrange * range)
Private Extern iw_get_range_info(skfd As Integer, ifname As String, range As Pointer) As Integer

' int iw_get_stats(int skfd, const char * ifname, iwstats * stats, const iwrange * range, int has_range)
Private Extern iw_get_stats(skfd As Integer, ifname As String, stats As Pointer, range As Pointer, has_range As Integer) As Integer

' void iw_print_txpower(char * buffer, int buflen, struct iw_param * txpower)
Private Extern iw_print_txpower(buffer As Pointer, buflen As Integer, txpower As Pointer)

' void iw_print_retry_value(char * buffer, int buflen, int value, int flags, int we_version)
Private Extern iw_print_retry_value(buffer As Pointer, buflen As Integer, value As Integer, flags As Integer, we_version As Integer)

' int ioctl(int __fd, unsigned long int __request, ...)
Private Extern ioctl(fd As Integer, request As Long, arg As Pointer) As Integer In "libc:6"


Public Sub Main()
 
 Dim skfd As Integer
 
' Crea un canale al kernel NET:
 skfd = iw_sockets_open()
 If skfd < 0 Then Error.Raise("Errore !")
 
 Print "Dispositivi:\n"
 
' Mostra la lista dei dispositivi e le informazioni:
 iw_enum_devices(skfd, Mostra_info, Null, 0)
 
End


Private Function Mostra_info(skfd As Integer, ifname As Pointer)
 
 Dim info As Pointer
 Dim rc As Integer
 
 info = Alloc(SizeOf(gb.byte), 984)
 
 Ottiene_info(skfd, ifname, info)
 
 Print
 
 Free(info)
 
End


Private Function Ottiene_info(skfd As Integer, ifname As Pointer, info As Pointer) As Integer
 
 Dim ifreq, iwreq, buf As Pointer
 Dim rit, range, stats, i As Integer
 Dim st As Stream
 
 ifreq = Alloc(SizeOf(gb.Byte), 40)
 iwreq = Alloc(SizeOf(gb.Byte), 32)
 
' Ottiene informazione di base:
 rit = iw_get_basic_config(skfd, String@(ifname), info)
 If rit < 0 Then
   st = Memory ifreq For Write
   Write #st, ifname
   st.Close
   rit = ioctl(skfd, SIOCGIWAP, ifreq)
   If rit < 0 Then
     Print String@(ifname)
     Free(iwreq)
     Free(ifreq)
     Return -ENODEV
   Else
     Print String@(ifname)
     Free(iwreq)
     Free(ifreq)
     Return -ENOTSUP
   Endif
   
 Else
 
   Print "\e[1m"; String@(ifname);
   Print String(4, Chr(32)); String@(info); "  ESSID: "; Quote(String@(info + 136))
   Print String(10, Chr(32)); "Mode: "; iw_operation_mode[Int@(info + 180)]; "  Frequency: "; Float@(info + 40) / 1000000000; " Ghz";
   
' Ottiene la gamma:
   rit = iw_get_range_info(skfd, String@(ifname), info + 368)
   If rit >= 0 Then range = 1
   
' Ottiene l'indirizzo AP:
   st = Memory iwreq For Write
   Write #st, String@(ifname)
   st.Close
   rit = ioctl(skfd, SIOCGIWAP, iwreq)
   If rit >= 0 Then
     Write "  Access Point: "
     For i = 18 To 23
       Print Hex(Byte@(iwreq + i), 2);
       If i < 23 Then Write ":"
     Next
   Endif
   
   Pulisci(iwreq)
' Ottiene il bit rate:
   st = Memory iwreq For Write
   Write #st, String@(ifname)
   st.Close
   rit = ioctl(skfd, SIOCGIWRATE, iwreq)
   If rit >= 0 Then Print "\n          Bit Rate="; Int@(iwreq + 16) / 1000000; " Mb/s";
   
   Pulisci(iwreq)
' Ottiene il Transmit Power:
   st = Memory iwreq For Write
   Write #st, String@(ifname)
   st.Close
   rit = ioctl(skfd, SIOCGIWTXPOW, iwreq)
   If rit >= 0 Then
     buf = Alloc(SizeOf(gb.Byte), 128)
     iw_print_txpower(buf, 128, iwreq + 16)
     Print "   Tx-Power"; IIf(Byte@(iwreq + 4), "=", ":"); String@(buf)
     Free(buf)
   Endif
   
   Pulisci(iwreq)
' Ottiene le impostazioni del Power Management:
   st = Memory iwreq For Write
   Write #st, String@(ifname)
   st.Close
   rit = ioctl(skfd, SIOCGIWPOWER, iwreq)
   If rit >= 0 Then Print String(10, " "); "Power Management"; IIf(Byte@(iwreq + 5), ":off", ":on")
   
' Ottiene le statistiche:
   rit = iw_get_stats(skfd, String@(ifname), info + 328, info + 368, range)
   If rit >= 0 Then stats = 1
   
' Ottiene il limite/durata di tentativi:
   Pulisci(iwreq)
   st = Memory iwreq For Write
   Write #st, String@(ifname)
   st.Close
   rit = ioctl(skfd, SIOCGIWRETRY, iwreq)
   If rit >= 0 Then
     Print String(10, Chr(32)); "Retry";
     If Byte@(iwreq + 20) Then
       Print ": off";
     Else
       If Short@(iwreq + 21) And IW_RETRY_TYPE Then
         buf = Alloc(SizeOf(gb.Byte), 128)
         iw_print_retry_value(buf, 128, iwreq, Short@(iwreq + 20), info + 649)
         Print Left(String@(buf - 0), 7); " "; Byte@(iwreq + 16);
         Free(buf)
       Endif
     Endif
   Endif
   
   Pulisci(iwreq)
' Ottiene la soglia RTS:
   st = Memory iwreq For Write
   Write #st, String@(ifname)
   st.Close
   rit = ioctl(skfd, SIOCGIWRTS, iwreq)
   If rit >= 0 Then
     Print String(3, Chr(32));
     If Byte@(iwreq + 5) Then     ' info->rts.disabled
       Print "RTS thr:off   ";
     Else
       Print "RTS thr"; IIf(Byte@(iwreq + 4), "=", ":"), Int@(iwreq); " B   ";
     Endif
   Endif
   
   Pulisci(iwreq)
' Ottiene la soglia di frammentazione:
   st = Memory iwreq For Write
   Write #st, String@(ifname)
   st.Close
   rit = ioctl(skfd, SIOCGIWFRAG, iwreq)
   If rit >= 0 Then
     If Byte@(iwreq + 5) Then
       Print "Fragment thr:off"
     Else
       Print "Fragment thr"; IIf(Byte@(iwreq + 4), "=", ":"), Int@(iwreq); " B   "
     Endif
   Endif
   
' Mostra statistiche:
   If stats Then
     Print String(10, Chr(32)); "Link Quality: "; Byte@(info + 330);
     Print "  Signal level= "; CShort(Byte@(info + 331)) - 256; " dBm \e[0m"   ' Val("&" & Hex(Byte@(info + 331))) - 256
   Endif
 Endif
  
 Free(ifreq)
 Free(iwreq)
 
End


Private Function Pulisci(p As Pointer)
 
 Dim st As Stream
 Dim b As Byte
 
 st = Memory p For Write
 For b = 0 To 31
   Write #st, &00 As Byte
 Next
 st.Close
 
End


Riferimenti