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;
}