:: [DNG] Debugging netman auto-connect…
Etusivu
Poista viesti
Vastaa
Lähettäjä: Edward Bartolo
Päiväys:  
Vastaanottaja: dng
Aihe: [DNG] Debugging netman auto-connect.
Hi all,

Since yesterday I have been trying to understand why "char**
essid_list" is working inside getInstalledEssidList(&count,
essid_list) but failing as soon as I try to access essid_list[0]
outside the function.

Both the source and the gdb text output are attached.

Any helpful pointers are appreciated.


Edward.
gdb auto-conn
GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from auto-conn...done.
(gdb) b 202
Breakpoint 1 at 0x401223: file automated_scanner.c, line 202.
(gdb) r
Starting program: /home/edbarx/netman/backend_src/src/auto-conn

Breakpoint 1, autoWirelessScanPlus () at automated_scanner.c:202
202        getInstalledEssidList(&count, essid_list);
(gdb) s
getInstalledEssidList (count=0x7fffffffe284, essid_list=0x1) at automated_scanner.c:48
48        int el_size = 0; // stands for essid_list size
(gdb) n
51        if ((dir = opendir(IFACES_PATH)) != 0) {
(gdb) n
52            while ((ent = readdir (dir)) != 0)
(gdb) n
54                    strcmp(".", ent->d_name) != 0 && 
(gdb) n
53                if(
(gdb) n
52            while ((ent = readdir (dir)) != 0)
(gdb) n
54                    strcmp(".", ent->d_name) != 0 && 
(gdb) n
53                if(
(gdb) n
55                    strcmp("..", ent->d_name) != 0
(gdb) n
54                    strcmp(".", ent->d_name) != 0 && 
(gdb) n
57                    (*count)++;
(gdb) n
62                    encoded_essid = ent->d_name;
(gdb) n
63                    if (el_size < *count) {
(gdb) p encoded_essid
$1 = 0x60206b "EB-TP-LNK67"
(gdb) n
64                        el_size =+ 10;
(gdb) n
65                        if (el_size == 10)
(gdb) n
66                            essid_list = calloc(*count + 9, sizeof(char*));
(gdb) n
70                    essid_list[*count - 1] = calloc(strlen(encoded_essid) + 1, sizeof(char));
(gdb) n
71                    strcpy(essid_list[*count - 1], encoded_essid);
(gdb) n
52            while ((ent = readdir (dir)) != 0)
(gdb) p essid_list[0]
$2 = 0x60a0b0 "EB-TP-LNK67"
(gdb) n
54                    strcmp(".", ent->d_name) != 0 && 
(gdb) n
53                if(
(gdb) n
55                    strcmp("..", ent->d_name) != 0
(gdb) n
54                    strcmp(".", ent->d_name) != 0 && 
(gdb) n
52            while ((ent = readdir (dir)) != 0)
(gdb) n
73            closedir(dir);
(gdb) n
87        return 0;
(gdb) n
88    }
(gdb) n
autoWirelessScanPlus () at automated_scanner.c:206
206        getRadiatingWifiList(&active_wifis, active_wifi_list);
(gdb) p essid_list[0]
Cannot access memory at address 0x1
(gdb) s
getRadiatingWifiList (active_wifis=0x7fffffffe280, active_wifi_list=0x0) at automated_scanner.c:94
94        char * scan_buffer = NULL;
(gdb) n
96        scan_buffer = calloc(1024, 1);
(gdb) n
99        shell_reader = popen("/sbin/iwlist wlan0 scan | grep \"Quality=\\|ESSID:\"", "r");
(gdb) n
101        if(!shell_reader) {
(gdb) n
113        int z = 0;
(gdb) n
115        *active_wifis = -1;
(gdb) n
116        while((scan_buffer = fgets(scan_buffer, 1024, shell_reader)))
(gdb) n
118            z++;
(gdb) n
119            if (z == 1) 
(gdb) n
120                active_wifi_list = calloc(sizeof(void*), 10);
(gdb) n
124            if (z % 2 == 1) {
(gdb) n
125                    active_wifis++;
(gdb) n
126                    tmp_wifi_quality = calloc(sizeof(wifi_quality), 1);
(gdb) n
127                    active_wifi_list[*active_wifis] = tmp_wifi_quality;
(gdb) n
129                    char* substr = strstr((char *) scan_buffer, "Signal level=");
(gdb) n
130                    substr = strstr(substr, "=");
(gdb) n
131                    char* endstr = strstr(substr + 1, " ");
(gdb) n
133                    strncpy(tmpstr, substr + 1, endstr - substr - 1);
(gdb) n
134                    tmpstr[endstr - substr + 1] = '\0';
(gdb) n
136                    tmp_wifi_quality->quality = strtod(tmpstr, NULL);
(gdb) n
144                    double log_quality = (tmp_wifi_quality->quality)/10;
(gdb) n
145                    tmp_wifi_quality->quality = pow(10, log_quality);
(gdb) n
116        while((scan_buffer = fgets(scan_buffer, 1024, shell_reader)))
(gdb) n
118            z++;
(gdb) n
119            if (z == 1) 
(gdb) n
121            else if (z % 20 == 0)
(gdb) n
124            if (z % 2 == 1) {
(gdb) n
148                    char* tmpstr = strtok((char*) scan_buffer, "\"");
(gdb) n
149                    tmpstr = strtok(NULL, "\"");    
(gdb) n
151                    strncpy(tmp_wifi_quality->name,  tmpstr, strlen(tmpstr)); 
(gdb) n
116        while((scan_buffer = fgets(scan_buffer, 1024, shell_reader)))
(gdb) n
156        if (scan_buffer != NULL) free(scan_buffer);
(gdb) n
157        pclose(shell_reader);    
(gdb) n
158    }
(gdb) n
autoWirelessScanPlus () at automated_scanner.c:209
209        sortRadiatingWifisList(active_wifis, active_wifi_list);
(gdb) s
sortRadiatingWifisList (active_wifis=-1, active_wifi_list=0x0) at automated_scanner.c:163
163        int i, j = 0;
(gdb) n
164        while (j < active_wifis) {
(gdb) n
177    }
(gdb) n
autoWirelessScanPlus () at automated_scanner.c:212
212        int wireless = 0;
(gdb) s
214        for (counter = 0; counter < count; counter++) {
(gdb) n
215            char* tmp_essid_list_item = essid_list[counter];
(gdb) n


Program received signal SIGSEGV, Segmentation fault.
0x0000000000401281 in autoWirelessScanPlus () at automated_scanner.c:215
215            char* tmp_essid_list_item = essid_list[counter];
(gdb) 

/*
    netman - A Network Connection Manager
    Copyright (C) 2015  Edward Bartolo


    "netman" is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.


    "netman" is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.


    You should have received a copy of the GNU General Public License
    along with "netman".  If not, see <http://www.gnu.org/licenses/>.
*/


#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <alloca.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <math.h>

//#include "core_functions.h"
//#include "essid_encoder.h"
#include "paths.h"

#define MAX_ESSID_LENGTH 1024



typedef struct {
    double quality;
    char name[MAX_ESSID_LENGTH];
} wifi_quality;



int getInstalledEssidList(int* count, char** essid_list)
{
    DIR * dir;
    struct dirent * ent;
    int el_size = 0; // stands for essid_list size

    
    // First get a list of installed wireless "interfaces" files
    if ((dir = opendir(IFACES_PATH)) != 0) {
        while ((ent = readdir (dir)) != 0)
            if(
                strcmp(".", ent->d_name) != 0 && 
                strcmp("..", ent->d_name) != 0
            ) {
                (*count)++;

                            
                char* encoded_essid;
                int err;


                encoded_essid = ent->d_name;
                if (el_size < *count) {
                    el_size =+ 10;
                    if (el_size == 10)
                        essid_list = calloc(*count + 9, sizeof(char*));
                        else essid_list = realloc(essid_list, (*count + 9)*sizeof(char*));
                }    

                    
                essid_list[*count - 1] = calloc(strlen(encoded_essid) + 1, sizeof(char));
                strcpy(essid_list[*count - 1], encoded_essid);
            } 
        closedir(dir);
    } 
    else {
        int old_errno = errno;


        fprintf(
            stderr, "Error: "
            "loadExisting(): opendir(%s) failed (Error: %s)\n",
            IFACES_PATH, strerror(errno)
        );


        return old_errno;
    }

    
    return 0;
}


int getRadiatingWifiList(int* active_wifis, void** active_wifi_list)
{
    // Hopefully, here we have a list of installed essid interfaces files
    FILE * shell_reader;
    char * scan_buffer = NULL;
    int err;
    scan_buffer = calloc(1024, 1);

    
    // read output lines containing 'Quality=' and 'ESSID:'
    shell_reader = popen("/sbin/iwlist wlan0 scan | grep \"Quality=\\|ESSID:\"", "r");


    if(!shell_reader) {
        fprintf(
            stderr, 
            "ERROR: power_scan(): "
            "popen() failed (Error: %s)\n", 
            strerror(errno)
        );


        return -1;
    }


    wifi_quality* tmp_wifi_quality;
    int z = 0;

    
    *active_wifis = -1;
    while((scan_buffer = fgets(scan_buffer, 1024, shell_reader)))
    {
        z++;
        if (z == 1) 
            active_wifi_list = calloc(sizeof(void*), 10);
        else if (z % 20 == 0)
            active_wifi_list = realloc(active_wifis + 10, sizeof(void*));

            
        if (z % 2 == 1) {
                active_wifis++;
                tmp_wifi_quality = calloc(sizeof(wifi_quality), 1);
                active_wifi_list[*active_wifis] = tmp_wifi_quality;

                
                char* substr = strstr((char *) scan_buffer, "Signal level=");
                substr = strstr(substr, "=");
                char* endstr = strstr(substr + 1, " ");
                char tmpstr[MAX_ESSID_LENGTH];
                strncpy(tmpstr, substr + 1, endstr - substr - 1);
                tmpstr[endstr - substr + 1] = '\0';

                
                tmp_wifi_quality->quality = strtod(tmpstr, NULL);

                
                // P(dBm) = 10 · log10( P(mW) / 1mW)
                // we want the absolute power

                
                // P(mW) / 1mW = P*
                // P* = antilog(P/10)

                
                double log_quality = (tmp_wifi_quality->quality)/10;
                tmp_wifi_quality->quality = pow(10, log_quality);
          }
        else {
                char* tmpstr = strtok((char*) scan_buffer, "\"");
                tmpstr = strtok(NULL, "\"");    

                
                strncpy(tmp_wifi_quality->name,  tmpstr, strlen(tmpstr)); 
            }
        //printf("%s", scan_buffer);
    }

    
    if (scan_buffer != NULL) free(scan_buffer);
    pclose(shell_reader);    
}


// sort radiating wifis according to signal strength
int sortRadiatingWifisList(const int active_wifis, void** active_wifi_list)
{
    int i, j = 0;
    while (j < active_wifis) {
        for (i = active_wifis - j - 1; i == 0; i--)
            if (
                ((wifi_quality*) active_wifi_list[i - 1])->quality <
                ((wifi_quality*) active_wifi_list[i])->quality
            ) {
                wifi_quality* awifi_quality = (wifi_quality*) active_wifi_list[i - 1];
              active_wifi_list[i - 1] = active_wifi_list[i];
                active_wifi_list[i] = awifi_quality;
            }

            
        j++;                 
    }
}


int wifiEssidInstalled(const int active_wifis, void** active_wifi_list, char* essid)
{
    int i;
    for (i = 0; i <= active_wifis; i++) {
        if (strcmp(((wifi_quality*) active_wifi_list[i])->name, essid) == 0) {
            return i;
        }
    }

    
    return -1;    // ie not found
}


int autoWirelessScanPlus()
{
    char** essid_list;
    int count = 0;

    
    int active_wifis;
    void** active_wifi_list;

    
    char* scan_buffer;

    
    // get a list of currently installed wifi essids
    getInstalledEssidList(&count, essid_list);
    //fprintf(stdout, essid_list[0], "\n");    

    
    // get a list of irradiating wifis
    getRadiatingWifiList(&active_wifis, active_wifi_list);

    
    // sort the radiating wifis in descending order according to strength
    sortRadiatingWifisList(active_wifis, active_wifi_list);

    
    int connection_result;
    int wireless = 0;
    int counter;
    for (counter = 0; counter < count; counter++) {
        char* tmp_essid_list_item = essid_list[counter];
        if (wifiEssidInstalled(active_wifis, active_wifi_list, tmp_essid_list_item) > -1) {
            FILE * shell_reader;

    
            // required command for popen: /sbin/ifup wlan0 -i IFACES_PATH"/"essid_list[counter]
            char ifup_cmd[40 + MAX_ESSID_LENGTH];
            strncpy(ifup_cmd, "/sbin/ifup wlan0 -i "IFACES_PATH"/", 38);
            strncat(ifup_cmd, essid_list[counter], strlen(essid_list[counter]));            

            
            shell_reader = popen(ifup_cmd, "r");

            
            if(!shell_reader) {
                fprintf(
                    stderr, 
                    "ERROR: autoWirelessScanPlus(): "
                    "popen() failed (Error: %s)\n", 
                    strerror(errno)
                );
            }
            pclose(shell_reader);

            
            shell_reader = popen(
                "/bin/ip a | grep \"state UP\"", "r"
            );

            
            if(!shell_reader) {
                fprintf(
                    stderr, 
                    "ERROR: autoWirelessScanPlus(): "
                    "popen() failed (Error: %s)\n", 
                    strerror(errno)
                );
            }

            
            scan_buffer = (char *) calloc(1025, 1);
            if (scan_buffer == NULL)
            {
                fprintf(
                    stderr, 
                    "ERROR: autoWirelessScanPlus(): "
                    "popen() failed (Error: %s)\n", 
                    strerror(errno)
                );
            }

    
            while((scan_buffer = fgets(scan_buffer, 1024, shell_reader))) {
                if (strstr((char *) scan_buffer, "wlan0") != NULL)
                    wireless++;
                //else if (strstr((char *) scan_buffer, "eth0") != NULL)
                //    wired++;
            }
            pclose(shell_reader);    
            free(scan_buffer);

            
            if (wireless) break; // if connected to wireless stop iterating
        }
    }

        
            
    // free all the allocated memory
    // free the essid string list
    int u;
    for (u = 0; u < count; u++)
      free(essid_list[u]);

        
    free(essid_list);

    
    // free the radiating wifis list
    for (u = 0; u <= active_wifis; u++)
        free((wifi_quality*) active_wifi_list[u]);

        
    free((void*) active_wifi_list);    
}


int main(int argc, char *argv[])
{
    autoWirelessScanPlus();
    return 0;
}