diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 1a383b5..d9e2559 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -13,5 +13,6 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libqrencode-dev libpng-dev build-essential gcc g++ pkg-config make
+ make test
make
sudo make install
diff --git a/Makefile b/Makefile
index 312b472..050cace 100644
--- a/Makefile
+++ b/Makefile
@@ -8,6 +8,11 @@ install:
@echo "Installing..."
cd src && $(MAKE) install
+test:
+ mkdir -p build
+ @echo "Testing..."
+ cd test && $(MAKE)
+
install-cli-only:
@echo "Installing command line interface only..."
cd src/scripts && $(MAKE) install-cli-only
@@ -19,7 +24,8 @@ uninstall:
clean-old:
cd src && $(MAKE) clean-old
-.PHONY: clean
+.PHONY: clean test
clean:
cd src && $(MAKE) clean
+ cd test && $(MAKE) clean
diff --git a/debian/changelog b/debian/changelog
index 76dca97..1ccb0e7 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,4 +1,4 @@
-linux-wifi-hotspot (4.3.3) UNRELEASED; urgency=high
+linux-wifi-hotspot (4.4.0) UNRELEASED; urgency=low
* Minor secrurty fixes
diff --git a/src/scripts/create_ap.conf b/src/scripts/create_ap.conf
index 9f55f09..aa4527d 100644
--- a/src/scripts/create_ap.conf
+++ b/src/scripts/create_ap.conf
@@ -1,5 +1,5 @@
CHANNEL=default
-GATEWAY=10.0.0.1
+GATEWAY=192.168.12.1
WPA_VERSION=2
ETC_HOSTS=0
DHCP_DNS=gateway
diff --git a/src/ui/glade/about.glade b/src/ui/glade/about.glade
index 5fd60cc..07cb234 100644
--- a/src/ui/glade/about.glade
+++ b/src/ui/glade/about.glade
@@ -9,7 +9,7 @@
dialog
center
Linux Wifi Hotspot
- 4.3.3
+ 4.4.0
(c) lakinduakash 2021
For more info visit
https://github.com/lakinduakash/linux-wifi-hotspot
diff --git a/src/ui/glade/wifih.ui b/src/ui/glade/wifih.ui
index 4af0e3e..bb38fec 100644
--- a/src/ui/glade/wifih.ui
+++ b/src/ui/glade/wifih.ui
@@ -221,21 +221,62 @@
10
True
-
+
+
+ Auto
+ True
+ True
+ False
+ True
+ rb_freq_5
+
+
+ 1
+ 0
+
+
+
+
+ True
+ False
+ start
+ Frequency band
0
- 1
+ 0
-
- No Haveged
+
+ 5Ghz
+ True
+ True
+ False
+ True
+ rb_freq_auto
+
+
+ 3
+ 0
+
+
+
+
+ Hidden
True
True
False
@@ -243,7 +284,7 @@
0
- 9
+ 1
@@ -322,57 +363,27 @@
-
- 2.4Ghz
- True
- True
- False
- True
- rb_freq_auto
-
-
- 2
- 0
-
-
-
-
- Auto
+
+ Gateway
True
True
False
True
- rb_freq_5
-
-
- 1
- 0
-
-
-
-
- True
- False
- start
- Frequency band
0
- 0
+ 6
-
- 5Ghz
+
True
True
- False
- True
- rb_freq_auto
+ start
- 3
- 0
+ 1
+ 6
@@ -385,7 +396,7 @@
0
- 6
+ 7
@@ -398,7 +409,7 @@
1
- 6
+ 7
2
@@ -412,7 +423,7 @@
0
- 8
+ 9
@@ -425,9 +436,28 @@
2
- 8
+ 9
+
+
+ No Haveged
+ True
+ True
+ False
+ True
+
+
+ 0
+ 10
+
+
+
+
+
+
+
+
diff --git a/src/ui/h_prop.c b/src/ui/h_prop.c
index 4bcdbdc..1e9c258 100644
--- a/src/ui/h_prop.c
+++ b/src/ui/h_prop.c
@@ -101,9 +101,9 @@ const char *build_wh_start_command(char *iface_src, char *iface_dest, char *ssid
const char *build_wh_mkconfig_command(ConfigValues* cv){
- const char* a=get_config_file(CONFIG_FILE_NAME);
+ const char* config_ffile_name=get_config_file(CONFIG_FILE_NAME);
- snprintf(cmd_mkconfig, BUFSIZE, "%s %s %s %s '%s' '%s' %s %s",SUDO, CREATE_AP, cv->iface_wifi, cv->iface_inet, cv->ssid, cv->pass,MKCONFIG,a);
+ snprintf(cmd_mkconfig, BUFSIZE, "%s %s %s %s '%s' '%s' %s %s",SUDO, CREATE_AP, cv->iface_wifi, cv->iface_inet, cv->ssid, cv->pass,MKCONFIG,config_ffile_name);
if(cv->freq!=NULL){
strcat(cmd_mkconfig," --freq-band ");
@@ -141,6 +141,11 @@ const char *build_wh_mkconfig_command(ConfigValues* cv){
strcat(cmd_mkconfig, cv->mac);
}
+ if(cv->gateway!=NULL) {
+ strcat(cmd_mkconfig, " --gateway ");
+ strcat(cmd_mkconfig, cv->gateway);
+ }
+
if(cv->mac_filter!=NULL && (strcmp(cv->mac_filter,"1") == 0)){
strcat(cmd_mkconfig, " --mac-filter ");
strcat(cmd_mkconfig, cv->mac_filter);
diff --git a/src/ui/read_config.cpp b/src/ui/read_config.cpp
index 8eb3b3e..3e2dc72 100644
--- a/src/ui/read_config.cpp
+++ b/src/ui/read_config.cpp
@@ -133,6 +133,9 @@ static void setConfigValues(const char * key, char *value){
if( !strcmp ( IEEE80211AC, key ))
configValues.ieee80211ac = value;
+
+ if( !strcmp ( GATEWAY, key ))
+ configValues.gateway = value;
}
diff --git a/src/ui/read_config.h b/src/ui/read_config.h
index a46769a..2fb240f 100644
--- a/src/ui/read_config.h
+++ b/src/ui/read_config.h
@@ -92,6 +92,7 @@ typedef struct{
char *ieee80211n;
char *ieee80211ac;
char *no_haveged;
+ char *gateway;
} ConfigValues;
diff --git a/src/ui/ui.c b/src/ui/ui.c
index dbe541c..56666f2 100644
--- a/src/ui/ui.c
+++ b/src/ui/ui.c
@@ -52,6 +52,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define ERROR_CHANNEL_MSG_2 "Channel must be 1-11"
#define ERROR_CHANNEL_MSG_5 "Channel must be 1-196"
#define ERROR_MAC_MSG "Invalid Mac address"
+#define ERROR_GATEWAY_MSG "Invalid gateway IP address"
+
+#define DEFAULT_GATEWAY_IP "192.168.12.1"
GtkBuilder *builder;
GObject *window;
@@ -72,6 +75,7 @@ GtkEntry *entry_ssd;
GtkEntry *entry_pass;
GtkEntry *entry_mac;
GtkEntry *entry_channel;
+GtkEntry *entry_gateway;
GtkTextView *tv_mac_filter;
GtkTextBuffer *buffer_mac_filter;
@@ -86,6 +90,7 @@ GtkRadioButton *rb_freq_5;
GtkCheckButton *cb_hidden;
GtkCheckButton *cb_no_haveged;
GtkCheckButton *cb_psk;
+GtkCheckButton *cb_gateway;
GtkCheckButton *cb_mac;
GtkCheckButton *cb_novirt;
GtkCheckButton *cb_channel;
@@ -111,6 +116,7 @@ GtkStyleContext *context_entry_ssid;
GtkStyleContext *context_entry_channel;
GtkStyleContext *context_label_input_error;
GtkStyleContext *context_tv_mac_filter;
+GtkStyleContext *context_entry_gateway;
const char** iface_list;
@@ -142,9 +148,12 @@ static void on_create_hp_clicked(GtkWidget *widget, gpointer data) {
if(validator(&configValues) == FALSE){
- set_error_text("Check inputs");
+ set_error_text("Some inputes are not valid!");
return;
}
+ else{
+ set_error_text("");
+ }
startShell(build_wh_mkconfig_command(&configValues));
@@ -187,6 +196,7 @@ static void init_style_contexts(){
context_entry_channel = gtk_widget_get_style_context((GtkWidget*)entry_channel);
context_label_input_error = gtk_widget_get_style_context((GtkWidget*)label_input_error);
context_tv_mac_filter = gtk_widget_get_style_context((GtkWidget*)tv_mac_filter);
+ context_entry_gateway = gtk_widget_get_style_context((GtkWidget*)entry_gateway);
}
@@ -343,6 +353,30 @@ static void* tv_mac_filter_warn(){
return NULL;
}
+static void* entry_gateway_warn(GtkWidget *widget, gpointer data){
+
+ const char *gateway = gtk_entry_get_text(GTK_ENTRY(widget));
+
+ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cb_gateway))==TRUE){
+ if (isValidIPaddress(gateway)==-1){
+ gtk_style_context_add_class(context_tv_mac_filter, "entry-error");
+ set_error_text(ERROR_GATEWAY_MSG);
+ return FALSE;
+ }
+ else{
+ set_error_text("");
+ gtk_style_context_remove_class(context_tv_mac_filter,"entry-error");
+ return NULL;
+ }
+
+ }
+
+ gtk_style_context_remove_class(context_tv_mac_filter,"entry-error");
+ set_error_text("");
+
+ return NULL;
+}
+
static void *update_freq_toggle(){
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(rb_freq_2)))
@@ -386,7 +420,9 @@ int initUi(int argc, char *argv[]){
entry_mac = (GtkEntry *) gtk_builder_get_object(builder, "entry_mac");
entry_channel = (GtkEntry *) gtk_builder_get_object(builder, "entry_channel");
- tv_mac_filter = (GtkTextView *) gtk_builder_get_object(builder, "tv_mac_filter");
+ entry_gateway = (GtkEntry *) gtk_builder_get_object(builder, "entry_gateway");
+
+ tv_mac_filter = (GtkTextView *) gtk_builder_get_object(builder, "entry_gateway");
buffer_mac_filter = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv_mac_filter));
@@ -399,6 +435,7 @@ int initUi(int argc, char *argv[]){
cb_mac = (GtkCheckButton *) gtk_builder_get_object(builder, "cb_mac");
cb_novirt = (GtkCheckButton *) gtk_builder_get_object(builder, "cb_novirt");
cb_channel = (GtkCheckButton *) gtk_builder_get_object(builder, "cb_channel");
+ cb_gateway = (GtkCheckButton *) gtk_builder_get_object(builder, "cb_gateway");
cb_open = (GtkCheckButton *) gtk_builder_get_object(builder, "cb_open");
cb_mac_filter = (GtkCheckButton *) gtk_builder_get_object(builder, "cb_mac_filter");
cb_ieee80211n = (GtkCheckButton *) gtk_builder_get_object(builder, "cb_ieee80211n");
@@ -430,6 +467,7 @@ int initUi(int argc, char *argv[]){
g_signal_connect (cb_mac, "toggled", G_CALLBACK(on_cb_mac_toggle), NULL); //new
g_signal_connect (cb_channel, "toggled", G_CALLBACK(on_cb_channel_toggle), NULL); //new
g_signal_connect (cb_mac_filter, "toggled", G_CALLBACK(on_cb_mac_filter_toggle), NULL); //new
+ g_signal_connect (cb_gateway, "toggled", G_CALLBACK(on_cb_gateway_toggle), NULL); //new
g_signal_connect (entry_mac, "changed", G_CALLBACK(entry_mac_warn), NULL);
g_signal_connect (entry_ssd, "changed", G_CALLBACK(entry_ssid_warn), NULL);
@@ -438,6 +476,8 @@ int initUi(int argc, char *argv[]){
g_signal_connect (entry_channel, "changed", G_CALLBACK(entry_channel_warn), NULL);
g_signal_connect (buffer_mac_filter, "changed", G_CALLBACK(tv_mac_filter_warn), NULL);
+ g_signal_connect (entry_gateway, "changed", G_CALLBACK(entry_gateway_warn), NULL);
+
g_signal_connect (rb_freq_2, "toggled", G_CALLBACK(update_freq_toggle), NULL);
g_signal_connect (rb_freq_5, "toggled", G_CALLBACK(update_freq_toggle), NULL);
g_signal_connect (rb_freq_auto, "toggled", G_CALLBACK(update_freq_toggle), NULL);
@@ -545,6 +585,16 @@ void init_ui_from_config(){
gtk_toggle_button_set_active((GtkToggleButton*) cb_novirt,TRUE);
}
+ // Check if default ip is set as gateway
+ if(strcmp(values->gateway,DEFAULT_GATEWAY_IP)!=0){
+ gtk_toggle_button_set_active((GtkToggleButton*) cb_gateway,TRUE);
+ gtk_entry_set_text(entry_gateway,values->gateway);
+ } else {
+ gtk_widget_set_sensitive((GtkWidget*)entry_gateway, FALSE);
+ gtk_toggle_button_set_active((GtkToggleButton*) cb_gateway,FALSE); // Check this line needed
+ gtk_entry_set_text(entry_gateway,values->gateway);
+ }
+
if(strcmp(values->mac_filter,"1")==0){
gtk_toggle_button_set_active((GtkToggleButton*) cb_mac_filter,TRUE);
} else {
@@ -806,6 +856,11 @@ static gboolean validator(ConfigValues *cv){
return FALSE;
}
+ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cb_gateway))==TRUE){
+ if (isValidIPaddress(cv->gateway)==-1)
+ return FALSE;
+ }
+
return TRUE;
}
@@ -846,7 +901,11 @@ static int init_config_val_input(ConfigValues* cv){
else
cv->channel = NULL;
-
+ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cb_gateway)))
+ cv->gateway = (char*)gtk_entry_get_text(entry_gateway);
+ else
+ cv->gateway = NULL;
+
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cb_mac)))
cv->mac = (char*)gtk_entry_get_text(entry_mac);
else
@@ -1025,3 +1084,16 @@ static void on_cb_mac_filter_toggle(GtkWidget *widget, gpointer data)
gtk_widget_set_sensitive((GtkWidget*)tv_mac_filter, FALSE);
}
}
+
+
+/**
+ * When gateway button is not toogled, disable gateway entry
+*/
+static void on_cb_gateway_toggle(GtkWidget *widget, gpointer data)
+{
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
+ gtk_widget_set_sensitive((GtkWidget*)entry_gateway, TRUE);
+ } else {
+ gtk_widget_set_sensitive((GtkWidget*)entry_gateway, FALSE);
+ }
+}
diff --git a/src/ui/ui.h b/src/ui/ui.h
index df3b341..bd6aef7 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -82,6 +82,8 @@ static void on_cb_channel_toggle(GtkWidget *widget, gpointer data);
static void on_cb_mac_filter_toggle(GtkWidget *widget, gpointer data);
+static void on_cb_gateway_toggle(GtkWidget *widget, gpointer data);
+
static void clear_connecetd_devices_list();
#endif //WIHOTSPOT_UI_H
diff --git a/src/ui/util.c b/src/ui/util.c
index 0d19930..067503f 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -1,122 +1,151 @@
-//
-// Created by lakinduakash on 16/04/19.
-//
-/*
-Copyright (c) 2019, lakinduaksh
- All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
-list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
-and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- */
-
-#include
-#include
-#include
-#include
-#include
-#include "util.h"
-#include
-
-regex_t regex;
-int reti;
-char msgbuf[100];
-
-int find_str(char *find, const char **array, int length) {
- int i;
-
- for ( i = 0; i < length; i++ ) {
- if (strcmp(array[i], find) == 0) {
- return i;
- }
- }
-
-
- return -1;
-
-}
-
-
-void rand_str(char *dest, size_t length) {
- char charset[] = "0123456789"
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-
- while (length-- > 0) {
- size_t index = (size_t) ((double) rand() / RAND_MAX * (sizeof charset - 1));
- *dest++ = charset[index];
- }
- *dest = '\0';
-}
-
-
-int isValidMacAddress(const char* mac) {
- int i = 0;
- int s = 0;
-
- while (*mac) {
- if (isxdigit(*mac)) {
- i++;
- }
- else if (*mac == ':' || *mac == '-') {
-
- if (i == 0 || i / 2 - 1 != s)
- break;
-
- ++s;
- }
- else {
- s = -1;
- }
-
-
- ++mac;
- }
-
- return (i == 12 && (s == 5 || s == 0));
-}
-
-
-int isValidAcceptedMacs(const char *macs){
-
- /* Compile regular expression */
-reti = regcomp(®ex, "^(((([0-9A-Fa-f]{2}):){5}[0-9A-Fa-f]{2}\\s*)(^((([0-9A-Fa-f]{2}):){5}[0-9A-Fa-f]{2}\\s*))*)$", REG_EXTENDED);
-if (reti) {
- //printf( "Could not compile regex\n");
- return -1;
-}
-
-/* Execute regular expression */
-reti = regexec(®ex, macs, 0, NULL, 0);
-if (!reti) {
- return 0;
-}
-else if (reti == REG_NOMATCH) {
- //puts("Invalid mac addresses");
- return -1;
-}
-else {
- regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
- //printf("Regex match failed: %s\n", msgbuf);
- return -1;
-}
-
-}
+//
+// Created by lakinduakash on 16/04/19.
+//
+/*
+Copyright (c) 2019, lakinduaksh
+ All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include "util.h"
+#include
+
+regex_t regex;
+int reti;
+char msgbuf[100];
+
+int find_str(char *find, const char **array, int length) {
+ int i;
+
+ for ( i = 0; i < length; i++ ) {
+ if (strcmp(array[i], find) == 0) {
+ return i;
+ }
+ }
+
+
+ return -1;
+
+}
+
+
+void rand_str(char *dest, size_t length) {
+ char charset[] = "0123456789"
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ while (length-- > 0) {
+ size_t index = (size_t) ((double) rand() / RAND_MAX * (sizeof charset - 1));
+ *dest++ = charset[index];
+ }
+ *dest = '\0';
+}
+
+
+int isValidMacAddress(const char* mac) {
+ int i = 0;
+ int s = 0;
+
+ while (*mac) {
+ if (isxdigit(*mac)) {
+ i++;
+ }
+ else if (*mac == ':' || *mac == '-') {
+
+ if (i == 0 || i / 2 - 1 != s)
+ break;
+
+ ++s;
+ }
+ else {
+ s = -1;
+ }
+
+
+ ++mac;
+ }
+
+ return (i == 12 && (s == 5 || s == 0));
+}
+
+
+int isValidAcceptedMacs(const char *macs){
+
+ /* Compile regular expression */
+ reti = regcomp(®ex, "^(((([0-9A-Fa-f]{2}):){5}[0-9A-Fa-f]{2}\\s*)(^((([0-9A-Fa-f]{2}):){5}[0-9A-Fa-f]{2}\\s*))*)$", REG_EXTENDED);
+ if (reti) {
+ //printf( "Could not compile regex\n");
+ return -1;
+ }
+
+ /* Execute regular expression */
+ reti = regexec(®ex, macs, 0, NULL, 0);
+ if (!reti) {
+ return 0;
+ }
+ else if (reti == REG_NOMATCH) {
+ //puts("Invalid mac addresses");
+ return -1;
+ }
+ else {
+ regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
+ //printf("Regex match failed: %s\n", msgbuf);
+ return -1;
+ }
+
+}
+
+int isValidIPaddress(const char * ip){
+
+
+ /* Compile regular expression */
+ reti = regcomp(®ex,
+ "^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$",
+ REG_EXTENDED);
+ if (reti) {
+ //printf( "Could not compile regex\n");
+ return -1;
+ }
+
+ /* Execute regular expression */
+ reti = regexec(®ex, ip, 0, NULL, 0);
+ if (!reti) {
+ return 0;
+ }
+ else if (reti == REG_NOMATCH) {
+ //puts("Invalid ip addresses");
+ return -1;
+ }
+ else {
+ regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
+ //printf("Regex match failed: %s\n", msgbuf);
+ return -1;
+ }
+
+}
\ No newline at end of file
diff --git a/src/ui/util.h b/src/ui/util.h
index 7357b88..75427eb 100644
--- a/src/ui/util.h
+++ b/src/ui/util.h
@@ -35,5 +35,6 @@ int find_str(char *find, const char **array, int length);
void rand_str(char *dest, size_t length);
int isValidMacAddress(const char*);
int isValidAcceptedMacs(const char*);
+int isValidIPaddress(const char*);
#endif //WIHOTSPOT_UTIL_H
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 0000000..fc2aa5f
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1,37 @@
+CC=gcc
+PKGCONFIG = $(shell which pkg-config)
+
+CFLAGS=`pkg-config --cflags gtk+-3.0` -I./../src/ui
+
+LIBS=`pkg-config --libs gtk+-3.0 --libs x11` -lstdc++ -lpng -lqrencode
+
+
+ODIR=./../build
+
+# Determine this makefile's path.
+# Be sure to place this BEFORE `include` directives, if any.
+THIS_FILE := $(lastword $(MAKEFILE_LIST))
+
+_OBJ = util.o test_util.o
+OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
+
+
+.PHONY: clean
+
+all: $(OBJ) test
+
+
+$(ODIR)/util.o: ../src/ui/util.c
+ $(CC) -c $? -o $@ $(CFLAGS)
+
+$(ODIR)/test_util.o: test_util.c
+ $(CC) -c $? -o $@ $(CFLAGS)
+
+test: $(OBJ)
+ $(CC) -o $(ODIR)/test $^
+ @$(ODIR)/test
+
+clean:
+ rm -f $(OBJ)
+ rm -f $(ODIR)/test
+
diff --git a/test/test_util.c b/test/test_util.c
new file mode 100644
index 0000000..50b3037
--- /dev/null
+++ b/test/test_util.c
@@ -0,0 +1,14 @@
+#include
+#include
+#include
+
+int main(int argc, char *argv[]){
+
+ assert(0 == isValidIPaddress("192.12.23.123"));
+ assert(0 == isValidIPaddress("255.255.255.255"));
+ assert(-1 == isValidIPaddress("255.255.255.256"));
+ assert(-1 == isValidIPaddress("255.255.255.2551"));
+ assert(-1 == isValidIPaddress("192.168.12"));
+
+ return 0;
+}
\ No newline at end of file