Agrego funciones básicas de wireless
* Agrego manejo de señal de cierre del procesomaster
parent
969415b70c
commit
3aedf1869e
|
@ -10,7 +10,8 @@ network_inador_SOURCES = network-inador.c network-inador.h \
|
|||
rta_aux.c rta_aux.h \
|
||||
routes.c routes.h \
|
||||
manager-events.c manager-events.h \
|
||||
dhcp.c dhcp.h
|
||||
dhcp.c dhcp.h \
|
||||
wireless.c
|
||||
|
||||
#network_inador_CPPFLAGS = -DGAMEDATA_DIR=\"$(gamedatadir)/\" -DLOCALEDIR=\"$(localedir)\" $(AM_CPPFLAGS)
|
||||
network_inador_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" $(AM_CPPFLAGS)
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <arpa/inet.h>
|
||||
|
||||
#include "interfaces.h"
|
||||
#include "wireless.h"
|
||||
#include "manager-events.h"
|
||||
|
||||
Interface * interfaces_locate_by_index (Interface *list, int index);
|
||||
|
@ -331,8 +332,15 @@ void interfaces_add_or_update_rtnl_link (NetworkInadorHandle *handle, struct nlm
|
|||
}
|
||||
}
|
||||
break;
|
||||
//default:
|
||||
//printf ("RTA Attribute \"%hu\" no procesado\n", attribute->rta_type);
|
||||
}
|
||||
}
|
||||
|
||||
if (was_new) {
|
||||
/* Como la interfaz es nueva, buscar si tiene extensiones wireless */
|
||||
wireless_check_is_wireless_interface (handle, new);
|
||||
}
|
||||
}
|
||||
|
||||
void interfaces_del_rtnl_link (NetworkInadorHandle *handle, struct nlmsghdr *h) {
|
||||
|
@ -340,6 +348,7 @@ void interfaces_del_rtnl_link (NetworkInadorHandle *handle, struct nlmsghdr *h)
|
|||
Interface *to_del, *last;
|
||||
IPv4 *address;
|
||||
struct rtattr *attribute;
|
||||
char real_hw[10];
|
||||
int len;
|
||||
int index;
|
||||
|
||||
|
@ -903,7 +912,7 @@ void interfaces_list_all (NetworkInadorHandle *handle, int sock) {
|
|||
|
||||
req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
|
||||
req.hdr.nlmsg_type = RTM_GETLINK;
|
||||
req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
|
||||
req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
|
||||
req.hdr.nlmsg_seq = global_nl_seq++;
|
||||
req.hdr.nlmsg_pid = local_nl.nl_pid;
|
||||
req.gen.rtgen_family = AF_PACKET; /* no preferred AF, we will get *all* interfaces */
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/if.h>
|
||||
|
@ -46,6 +48,7 @@
|
|||
#include "manager.h"
|
||||
#include "bridge.h"
|
||||
#include "routes.h"
|
||||
#include "wireless.h"
|
||||
#include "manager-events.h"
|
||||
#include "dhcp.h"
|
||||
|
||||
|
@ -72,14 +75,88 @@ int create_route_netlink_socket (int groups) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_nl local_nl;
|
||||
socklen_t local_size;
|
||||
|
||||
/* Recuperar el puerto local del netlink */
|
||||
local_size = sizeof (local_nl);
|
||||
getsockname (fd, (struct sockaddr *) &local_nl, &local_size);
|
||||
|
||||
printf ("Primer puerto es %ld\n", local_nl.nl_pid);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int sigterm_pipe_fds[2] = { -1, -1 };
|
||||
|
||||
static void sigterm_handler (int signum) {
|
||||
//fprintf (stderr, "SIGTERM SIGINT Handler\n");
|
||||
if (sigterm_pipe_fds[1] >= 0) {
|
||||
if (write (sigterm_pipe_fds[1], "", 1) == -1 ) {
|
||||
//fprintf (stderr, "Write to sigterm_pipe failed.\n");
|
||||
}
|
||||
close (sigterm_pipe_fds[1]);
|
||||
sigterm_pipe_fds[1] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean quit_handler (GIOChannel *source, GIOCondition cond, gpointer data) {
|
||||
g_main_loop_quit (loop);
|
||||
}
|
||||
|
||||
static void setup_signal (void) {
|
||||
struct sigaction act;
|
||||
sigset_t empty_mask;
|
||||
|
||||
/* Preparar el pipe para la señal de cierre */
|
||||
if (pipe (sigterm_pipe_fds) != 0) {
|
||||
perror ("Failed to create SIGTERM pipe");
|
||||
sigterm_pipe_fds[0] = -1;
|
||||
}
|
||||
|
||||
/* Instalar un manejador de señales para SIGTERM */
|
||||
sigemptyset (&empty_mask);
|
||||
act.sa_mask = empty_mask;
|
||||
act.sa_flags = 0;
|
||||
act.sa_handler = &sigterm_handler;
|
||||
if (sigaction (SIGTERM, &act, NULL) < 0) {
|
||||
perror ("Failed to register SIGTERM handler");
|
||||
}
|
||||
|
||||
if (sigaction (SIGINT, &act, NULL) < 0) {
|
||||
perror ("Failed to register SIGINT handler");
|
||||
}
|
||||
|
||||
if (sigterm_pipe_fds[0] != -1) {
|
||||
GIOChannel *io;
|
||||
|
||||
io = g_io_channel_unix_new (sigterm_pipe_fds[0]);
|
||||
g_io_channel_set_close_on_unref (io, TRUE);
|
||||
|
||||
g_io_add_watch (io, G_IO_IN | G_IO_PRI | G_IO_HUP | G_IO_ERR, quit_handler, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void clean_process (NetworkInadorHandle *handle) {
|
||||
Interface *iface;
|
||||
|
||||
iface = handle->interfaces;
|
||||
|
||||
while (iface != NULL) {
|
||||
if (iface->dhcp_info.process_pid != 0) {
|
||||
kill (iface->dhcp_info.process_pid, SIGTERM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
NetworkInadorHandle handle;
|
||||
int nl_sock;
|
||||
int nl_watch;
|
||||
Interface *to_up;
|
||||
|
||||
//signal (SIGPIPE, SIG_IGN);
|
||||
//signal (SIGCHLD, SIG_IGN);
|
||||
|
||||
#if !defined(GLIB_VERSION_2_36)
|
||||
g_type_init ();
|
||||
|
@ -87,16 +164,21 @@ int main (int argc, char *argv[]) {
|
|||
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
setup_signal ();
|
||||
|
||||
/* Inicializar nuestra estructura principal */
|
||||
handle.interfaces = NULL;
|
||||
handle.rtable_v4 = NULL;
|
||||
|
||||
Interface *to_up;
|
||||
|
||||
nl_sock = create_ntlink_socket (0);
|
||||
/* Crear los sockets de petición */
|
||||
nl_sock = create_route_netlink_socket (0);
|
||||
handle.netlink_sock_request = nl_sock;
|
||||
nl_watch = create_ntlink_socket (-1);
|
||||
nl_watch = create_route_netlink_socket (-1);
|
||||
|
||||
wireless_init (&handle);
|
||||
|
||||
manager_events_setup (&handle);
|
||||
manager_setup_socket (&handle);
|
||||
|
||||
interfaces_list_all (&handle, nl_sock);
|
||||
|
||||
|
@ -104,8 +186,6 @@ int main (int argc, char *argv[]) {
|
|||
|
||||
netlink_events_setup_loop (&handle, nl_watch);
|
||||
|
||||
manager_setup_socket (&handle);
|
||||
|
||||
g_main_loop_run (loop);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -65,6 +65,20 @@ typedef struct _IPv4 {
|
|||
struct _IPv4 *next;
|
||||
} IPv4;
|
||||
|
||||
typedef struct _WirelessAccessPoint {
|
||||
int freq;
|
||||
int essid;
|
||||
char bssid[10];
|
||||
|
||||
struct _WirelessAccessPoint *next;
|
||||
} WirelessAccessPoint;
|
||||
|
||||
typedef struct {
|
||||
int wiphy;
|
||||
|
||||
WirelessAccessPoint *scaned_aps;
|
||||
} WirelessInfo;
|
||||
|
||||
typedef struct _Interface {
|
||||
char name[IFNAMSIZ];
|
||||
int ifi_type;
|
||||
|
@ -92,6 +106,9 @@ typedef struct _Interface {
|
|||
|
||||
DHCPStateInfo dhcp_info;
|
||||
|
||||
/* Información wireless */
|
||||
WirelessInfo *wireless;
|
||||
|
||||
struct _Interface *next;
|
||||
} Interface;
|
||||
|
||||
|
@ -113,6 +130,7 @@ typedef struct {
|
|||
Routev4 *rtable_v4;
|
||||
|
||||
int netlink_sock_request;
|
||||
int netlink_sock_request_generic;
|
||||
} NetworkInadorHandle;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,611 @@
|
|||
/*
|
||||
* wireless.c
|
||||
* This file is part of Network-inador
|
||||
*
|
||||
* Copyright (C) 2018 - Félix Arreola Rodríguez
|
||||
*
|
||||
* Network-inador 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Network-inador 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 Network-inador; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_addr.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <linux/genetlink.h>
|
||||
|
||||
#include <linux/nl80211.h>
|
||||
|
||||
#include "wireless.h"
|
||||
#include "network-inador.h"
|
||||
#include "interfaces.h"
|
||||
#include "rta_aux.h"
|
||||
|
||||
static uint16_t nl80211_id = 0;
|
||||
static uint16_t scan_multicast_group_id = 0;
|
||||
|
||||
static void _wireless_find_ssid (uint8_t *ies, uint32_t ies_len, unsigned char *ssid, uint32_t *ssid_len) {
|
||||
#define WLAN_EID_SSID 0
|
||||
ssid[0] = 0;
|
||||
*ssid_len = 0;
|
||||
|
||||
while (ies_len > 2 && ies[0] != WLAN_EID_SSID) {
|
||||
ies_len -= ies[1] + 2;
|
||||
ies += ies[1] + 2;
|
||||
}
|
||||
if (ies_len < 2)
|
||||
return;
|
||||
if (ies_len < (uint32_t)(2 + ies[1]))
|
||||
return;
|
||||
|
||||
*ssid_len = ies[1];
|
||||
memcpy (ssid, ies + 2, ies[1]);
|
||||
}
|
||||
|
||||
static int _wireless_create_generic_netlink_socket (void) {
|
||||
int fd;
|
||||
struct sockaddr_nl local;
|
||||
|
||||
fd = socket (AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
|
||||
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&local, 0, sizeof(local)); /* fill-in local address information */
|
||||
local.nl_family = AF_NETLINK;
|
||||
local.nl_pid = 0;
|
||||
local.nl_groups = 0;
|
||||
|
||||
if (bind (fd, (struct sockaddr *) &local, sizeof(local)) < 0) {
|
||||
perror("cannot bind, are you root ? if yes, check netlink/rtnetlink kernel support");
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static uint16_t _wireless_parse_family_id (struct nlmsghdr *msg_ptr) {
|
||||
struct genlmsghdr *ghdr;
|
||||
struct rtattr *attribute;
|
||||
int len;
|
||||
|
||||
uint16_t n80211_family;
|
||||
|
||||
struct rtattr *nest2_attr, *nest3_attr;
|
||||
int nest2_size, nest3_size;
|
||||
int sub2_len, sub3_len;
|
||||
|
||||
ghdr = NLMSG_DATA (msg_ptr);
|
||||
len = msg_ptr->nlmsg_len - NLMSG_LENGTH (sizeof (struct genlmsghdr));
|
||||
|
||||
attribute = (struct rtattr*) (((char *) ghdr) + GENL_HDRLEN);
|
||||
|
||||
for (; RTA_OK (attribute, len); attribute = RTA_NEXT (attribute, len)) {
|
||||
//printf ("Attribute: %d\n", attribute->rta_type);
|
||||
if (attribute->rta_type == CTRL_ATTR_FAMILY_ID) {
|
||||
memcpy (&n80211_family, RTA_DATA (attribute), 2);
|
||||
//printf ("El id del nl80211 es: %hu\n", n80211_family);
|
||||
} else if (attribute->rta_type == CTRL_ATTR_MCAST_GROUPS) {
|
||||
//printf ("_____________ Descubriendo la familia nl80211. Multicast groups: \n");
|
||||
int id_multicast_group;
|
||||
char multicast_group_name[512];
|
||||
|
||||
nest2_size = attribute->rta_len;
|
||||
nest2_attr = RTA_DATA (attribute);
|
||||
|
||||
while (nest2_size > sizeof (nest2_attr)) {
|
||||
sub2_len = nest2_attr->rta_len;
|
||||
if (sub2_len > nest2_size) {
|
||||
break;
|
||||
}
|
||||
|
||||
nest3_size = nest2_attr->rta_len;
|
||||
nest3_attr = RTA_DATA (nest2_attr);
|
||||
|
||||
id_multicast_group = 0;
|
||||
multicast_group_name[0] = 0;
|
||||
|
||||
while (nest3_size > sizeof (nest3_attr)) {
|
||||
sub3_len = nest3_attr->rta_len;
|
||||
if (sub3_len > nest3_size) {
|
||||
//printf ("Los sub atributos se acabaron prematuramente\n");
|
||||
break;
|
||||
}
|
||||
//printf ("sub attributo type: %i, size: %d\n", nest3_attr->rta_type, nest3_attr->rta_len);
|
||||
if (nest3_attr->rta_type == CTRL_ATTR_MCAST_GRP_ID) {
|
||||
memcpy (&id_multicast_group, RTA_DATA (nest3_attr), sizeof (id_multicast_group));
|
||||
} else if (nest3_attr->rta_type == CTRL_ATTR_MCAST_GRP_NAME) {
|
||||
strncpy (multicast_group_name, RTA_DATA (nest3_attr), sizeof (multicast_group_name));
|
||||
}
|
||||
|
||||
nest3_size -= RTA_ALIGN (sub3_len);
|
||||
nest3_attr = (struct rtattr *) (((char *) nest3_attr) + RTA_ALIGN (sub3_len));
|
||||
}
|
||||
|
||||
if (strcmp (multicast_group_name, "scan") == 0) {
|
||||
scan_multicast_group_id = id_multicast_group;
|
||||
//printf ("ID del grupo multicast SCAN: %i\n", id_multicast_group);
|
||||
}
|
||||
|
||||
nest2_size -= RTA_ALIGN (sub2_len);
|
||||
nest2_attr = (struct rtattr *) (((char *) nest2_attr) + RTA_ALIGN (sub2_len));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return n80211_family;
|
||||
}
|
||||
|
||||
static void _wireless_parse_message_get_iface (struct nlmsghdr *msg_ptr, Interface *iface) {
|
||||
struct genlmsghdr *ghdr;
|
||||
struct rtattr *attribute;
|
||||
int len;
|
||||
int wiphy;
|
||||
|
||||
/* Anexar la estructura wireless al objeto interfaz */
|
||||
WirelessInfo *winfo;
|
||||
|
||||
winfo = (WirelessInfo *) malloc (sizeof (WirelessInfo));
|
||||
|
||||
if (winfo == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset (winfo, 0, sizeof (winfo));
|
||||
|
||||
iface->wireless = winfo;
|
||||
|
||||
ghdr = NLMSG_DATA (msg_ptr);
|
||||
len = msg_ptr->nlmsg_len - NLMSG_LENGTH (sizeof (struct genlmsghdr));
|
||||
|
||||
attribute = (struct rtattr*) (((char *) ghdr) + GENL_HDRLEN);
|
||||
|
||||
for (; RTA_OK (attribute, len); attribute = RTA_NEXT (attribute, len)) {
|
||||
printf ("Wireless Attribute: %d\n", attribute->rta_type);
|
||||
if (attribute->rta_type == NL80211_ATTR_WIPHY) {
|
||||
memcpy (&wiphy, RTA_DATA (attribute), 4);
|
||||
iface->wireless->wiphy = wiphy;
|
||||
}
|
||||
/*switch(attribute->rta_type) {
|
||||
default:
|
||||
printf ("Del interface RTA Attribute \"%hu\" no procesado\n", attribute->rta_type);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
static void _wireless_parse_scan (NetworkInadorHandle *handle, struct nlmsghdr *msg_ptr) {
|
||||
struct genlmsghdr *ghdr;
|
||||
struct rtattr *attribute;
|
||||
int len;
|
||||
int iface = -1;
|
||||
|
||||
ghdr = NLMSG_DATA (msg_ptr);
|
||||
len = msg_ptr->nlmsg_len - NLMSG_LENGTH (sizeof (struct genlmsghdr));
|
||||
|
||||
|
||||
attribute = (struct rtattr*) (((char *) ghdr) + GENL_HDRLEN);
|
||||
|
||||
for (; RTA_OK (attribute, len); attribute = RTA_NEXT (attribute, len)) {
|
||||
//printf ("Wireless scan Attribute: %d\n", attribute->rta_type);
|
||||
if (attribute->rta_type == NL80211_ATTR_IFINDEX) {
|
||||
memcpy (&iface, RTA_DATA (attribute), 4);
|
||||
}
|
||||
}
|
||||
|
||||
/* Ejecutar el GET Scan */
|
||||
if (iface != -1) {
|
||||
wireless_do_get_scan (handle, iface);
|
||||
}
|
||||
}
|
||||
|
||||
static void _wireless_parse_station (struct nlmsghdr *msg_ptr, Interface *iface) {
|
||||
struct genlmsghdr *ghdr;
|
||||
struct rtattr *attribute;
|
||||
int len;
|
||||
char bss_info[1024];
|
||||
int has_bss = 0;
|
||||
int bss_len;
|
||||
|
||||
ghdr = NLMSG_DATA (msg_ptr);
|
||||
len = msg_ptr->nlmsg_len - NLMSG_LENGTH (sizeof (struct genlmsghdr));
|
||||
|
||||
attribute = (struct rtattr*) (((char *) ghdr) + GENL_HDRLEN);
|
||||
|
||||
for (; RTA_OK (attribute, len); attribute = RTA_NEXT (attribute, len)) {
|
||||
//printf ("Wireless scan Attribute: %d\n", attribute->rta_type);
|
||||
if (attribute->rta_type == NL80211_ATTR_BSS) {
|
||||
has_bss = 1;
|
||||
bss_len = attribute->rta_len;
|
||||
|
||||
memcpy (bss_info, RTA_DATA (attribute), bss_len);
|
||||
}
|
||||
}
|
||||
|
||||
if (has_bss == 0) {
|
||||
/* No hay BSS info */
|
||||
return;
|
||||
}
|
||||
|
||||
printf ("Imprimiendo BSS Attrs:\n");
|
||||
attribute = (struct rtattr *) bss_info;
|
||||
for (; RTA_OK (attribute, bss_len); attribute = RTA_NEXT (attribute, len)) {
|
||||
|
||||
if (attribute->rta_type == NL80211_BSS_BSSID) {
|
||||
char *mac = RTA_DATA (attribute);
|
||||
//printf ("MAC access point: %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
} else if (attribute->rta_type == NL80211_BSS_INFORMATION_ELEMENTS) {
|
||||
char essid[64];
|
||||
essid[0] = 0;
|
||||
int essid_len = 0;
|
||||
_wireless_find_ssid (RTA_DATA (attribute), attribute->rta_len, essid, &essid_len);
|
||||
essid[essid_len] = 0;
|
||||
printf ("Essid: %s\n", essid);
|
||||
} else if (attribute->rta_type == NL80211_BSS_STATUS) {
|
||||
int status;
|
||||
memcpy (&status, RTA_DATA (attribute), 4);
|
||||
printf ("-> Bss estatus: %i\n", status);
|
||||
} else {
|
||||
printf ("BSS Scan Attribute: %d\n", attribute->rta_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wireless_do_get_scan (NetworkInadorHandle *handle, int ifindex) {
|
||||
printf ("DO Scan for iface: %i\n", ifindex);
|
||||
struct msghdr rtnl_msg; /* generic msghdr struct for use with sendmsg */
|
||||
struct iovec io;
|
||||
struct genlmsghdr *ghdr;
|
||||
struct rtattr *rta;
|
||||
struct sockaddr_nl kernel;
|
||||
char buffer[8192]; /* a large buffer */
|
||||
int len;
|
||||
Interface *iface;
|
||||
|
||||
/* Localizar el iface por el índice */
|
||||
iface = interfaces_locate_by_index (handle->interfaces, ifindex);
|
||||
|
||||
if (iface == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Para la respuesta */
|
||||
struct nlmsgerr *l_err;
|
||||
struct nlmsghdr *msg_ptr; /* pointer to current part */
|
||||
|
||||
struct sockaddr_nl local_nl;
|
||||
socklen_t local_size;
|
||||
|
||||
/* Recuperar el puerto local del netlink */
|
||||
local_size = sizeof (local_nl);
|
||||
getsockname (handle->netlink_sock_request_generic, (struct sockaddr *) &local_nl, &local_size);
|
||||
|
||||
memset (&rtnl_msg, 0, sizeof (rtnl_msg));
|
||||
memset (&kernel, 0, sizeof (kernel));
|
||||
memset (buffer, 0, sizeof (buffer));
|
||||
|
||||
kernel.nl_family = AF_NETLINK; /* fill-in kernel address (destination of our message) */
|
||||
kernel.nl_groups = 0;
|
||||
|
||||
msg_ptr = (struct nlmsghdr *) buffer;
|
||||
msg_ptr->nlmsg_len = NLMSG_LENGTH (sizeof (struct genlmsghdr));
|
||||
msg_ptr->nlmsg_type = nl80211_id;
|
||||
msg_ptr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP;
|
||||
msg_ptr->nlmsg_seq = global_nl_seq++;
|
||||
msg_ptr->nlmsg_pid = local_nl.nl_pid;
|
||||
|
||||
ghdr = (struct genlmsghdr *) NLMSG_DATA (msg_ptr);
|
||||
ghdr->cmd = NL80211_CMD_GET_SCAN;
|
||||
ghdr->version = 0;
|
||||
|
||||
rta_addattr_l (msg_ptr, sizeof (buffer), NL80211_ATTR_IFINDEX, &ifindex, 4);
|
||||
//rta_addattr_l (msg_ptr, sizeof (buffer), NL80211_ATTR_IFINDEX, &iface->wiphy, 4);
|
||||
|
||||
io.iov_base = buffer;
|
||||
io.iov_len = msg_ptr->nlmsg_len;
|
||||
rtnl_msg.msg_iov = &io;
|
||||
rtnl_msg.msg_iovlen = 1;
|
||||
rtnl_msg.msg_name = &kernel;
|
||||
rtnl_msg.msg_namelen = sizeof(kernel);
|
||||
|
||||
len = sendmsg (handle->netlink_sock_request_generic, (struct msghdr *) &rtnl_msg, 0);
|
||||
|
||||
/* Esperar la respuesta */
|
||||
memset (&io, 0, sizeof (io));
|
||||
memset (&rtnl_msg, 0, sizeof (rtnl_msg));
|
||||
memset (buffer, 0, sizeof (buffer));
|
||||
|
||||
io.iov_base = buffer;
|
||||
io.iov_len = sizeof (buffer);
|
||||
rtnl_msg.msg_iov = &io;
|
||||
rtnl_msg.msg_iovlen = 1;
|
||||
rtnl_msg.msg_name = &kernel;
|
||||
rtnl_msg.msg_namelen = sizeof (kernel);
|
||||
|
||||
len = recvmsg (handle->netlink_sock_request_generic, &rtnl_msg, 0);
|
||||
|
||||
if (len <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
msg_ptr = (struct nlmsghdr *) buffer;
|
||||
printf ("Procesando mensajes de solicitud de escaneo\n");
|
||||
for (; NLMSG_OK(msg_ptr, len); msg_ptr = NLMSG_NEXT(msg_ptr, len)) {
|
||||
if (msg_ptr->nlmsg_type == NLMSG_ERROR) {
|
||||
struct nlmsgerr *l_err;
|
||||
l_err = (struct nlmsgerr*) NLMSG_DATA (msg_ptr);
|
||||
printf ("DO Scan message error, num: %i\n", l_err->error);
|
||||
break;
|
||||
} else if (msg_ptr->nlmsg_type == NLMSG_DONE) {
|
||||
printf ("DO Scan, end of DUMP\n");
|
||||
break;
|
||||
} else if (msg_ptr->nlmsg_type == nl80211_id) {
|
||||
ghdr = NLMSG_DATA (msg_ptr);
|
||||
|
||||
//printf ("DO SCAN! Generic command: %i\n", ghdr->cmd);
|
||||
if (ghdr->cmd == NL80211_CMD_NEW_SCAN_RESULTS) {
|
||||
_wireless_parse_station (msg_ptr, iface);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gboolean _wireless_events_handle_read (GIOChannel *source, GIOCondition condition, gpointer data) {
|
||||
NetworkInadorHandle *handle = (NetworkInadorHandle *) data;
|
||||
int sock;
|
||||
|
||||
sock = g_io_channel_unix_get_fd (source);
|
||||
|
||||
char reply[8192]; /* a large buffer */
|
||||
struct sockaddr_nl kernel;
|
||||
int len;
|
||||
|
||||
struct iovec io;
|
||||
/* Para la respuesta */
|
||||
struct nlmsghdr *msg_ptr; /* pointer to current part */
|
||||
struct msghdr rtnl_reply; /* generic msghdr structure */
|
||||
struct iovec io_reply;
|
||||
struct genlmsghdr *ghdr;
|
||||
|
||||
/* Esperar la respuesta */
|
||||
memset(&io_reply, 0, sizeof(io_reply));
|
||||
memset(&rtnl_reply, 0, sizeof(rtnl_reply));
|
||||
|
||||
io.iov_base = reply;
|
||||
io.iov_len = sizeof (reply);
|
||||
rtnl_reply.msg_iov = &io;
|
||||
rtnl_reply.msg_iovlen = 1;
|
||||
rtnl_reply.msg_name = &kernel;
|
||||
rtnl_reply.msg_namelen = sizeof(kernel);
|
||||
|
||||
len = recvmsg(sock, &rtnl_reply, 0);
|
||||
|
||||
if (len == 0) {
|
||||
printf ("Lectura de eventos regresó 0\n");
|
||||
return FALSE;
|
||||
} else if (len < 0) {
|
||||
perror ("Error en recvmsg\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
msg_ptr = (struct nlmsghdr *) reply;
|
||||
|
||||
for (; NLMSG_OK(msg_ptr, len); msg_ptr = NLMSG_NEXT(msg_ptr, len)) {
|
||||
printf ("Msg type: %i\n", msg_ptr->nlmsg_type);
|
||||
if (msg_ptr->nlmsg_type == nl80211_id) {
|
||||
ghdr = NLMSG_DATA (msg_ptr);
|
||||
|
||||
printf ("Generic command: %i\n", ghdr->cmd);
|
||||
if (ghdr->cmd == NL80211_CMD_NEW_SCAN_RESULTS) {
|
||||
_wireless_parse_scan (handle, msg_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void wireless_init (NetworkInadorHandle *handle) {
|
||||
struct msghdr rtnl_msg; /* generic msghdr struct for use with sendmsg */
|
||||
struct iovec io;
|
||||
struct genlmsghdr *ghdr;
|
||||
struct rtattr *rta;
|
||||
struct sockaddr_nl kernel;
|
||||
char buffer[8192]; /* a large buffer */
|
||||
int len;
|
||||
GIOChannel *channel;
|
||||
|
||||
/* Para la respuesta */
|
||||
struct nlmsgerr *l_err;
|
||||
struct nlmsghdr *msg_ptr; /* pointer to current part */
|
||||
|
||||
struct sockaddr_nl local_nl;
|
||||
socklen_t local_size;
|
||||
|
||||
/* Crear un netlink de la familia generica para nuestras peticiones */
|
||||
handle->netlink_sock_request_generic = _wireless_create_generic_netlink_socket ();
|
||||
|
||||
/* Recuperar el puerto local del netlink */
|
||||
local_size = sizeof (local_nl);
|
||||
getsockname (handle->netlink_sock_request_generic, (struct sockaddr *) &local_nl, &local_size);
|
||||
|
||||
memset (&rtnl_msg, 0, sizeof (rtnl_msg));
|
||||
memset (&kernel, 0, sizeof (kernel));
|
||||
memset (buffer, 0, sizeof (buffer));
|
||||
|
||||
kernel.nl_family = AF_NETLINK; /* fill-in kernel address (destination of our message) */
|
||||
kernel.nl_groups = 0;
|
||||
|
||||
msg_ptr = (struct nlmsghdr *) buffer;
|
||||
msg_ptr->nlmsg_len = NLMSG_LENGTH (sizeof (struct genlmsghdr));
|
||||
msg_ptr->nlmsg_type = GENL_ID_CTRL;
|
||||
msg_ptr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
msg_ptr->nlmsg_seq = global_nl_seq++;
|
||||
msg_ptr->nlmsg_pid = local_nl.nl_pid;
|
||||
|
||||
ghdr = (struct genlmsghdr *) NLMSG_DATA (msg_ptr);
|
||||
ghdr->cmd = CTRL_CMD_GETFAMILY;
|
||||
ghdr->version = 1;
|
||||
|
||||
len = strlen (NL80211_GENL_NAME) + 1;
|
||||
rta_addattr_l (msg_ptr, sizeof (buffer), CTRL_ATTR_FAMILY_NAME, NL80211_GENL_NAME, len);
|
||||
|
||||
io.iov_base = buffer;
|
||||
io.iov_len = msg_ptr->nlmsg_len;
|
||||
rtnl_msg.msg_iov = &io;
|
||||
rtnl_msg.msg_iovlen = 1;
|
||||
rtnl_msg.msg_name = &kernel;
|
||||
rtnl_msg.msg_namelen = sizeof(kernel);
|
||||
|
||||
sendmsg (handle->netlink_sock_request_generic, (struct msghdr *) &rtnl_msg, 0);
|
||||
|
||||
/* Esperar la respuesta */
|
||||
memset (&io, 0, sizeof (io));
|
||||
memset (&rtnl_msg, 0, sizeof (rtnl_msg));
|
||||
memset (buffer, 0, sizeof (buffer));
|
||||
|
||||
io.iov_base = buffer;
|
||||
io.iov_len = sizeof (buffer);
|
||||
rtnl_msg.msg_iov = &io;
|
||||
rtnl_msg.msg_iovlen = 1;
|
||||
rtnl_msg.msg_name = &kernel;
|
||||
rtnl_msg.msg_namelen = sizeof (kernel);
|
||||
|
||||
/*len = recvmsg (handle->netlink_sock_request_generic, &rtnl_msg, 0);
|
||||
msg_ptr = (struct nlmsghdr *) buffer;
|
||||
_wireless_parse_family_id (msg_ptr);
|
||||
|
||||
len = recvmsg (handle->netlink_sock_request_generic, &rtnl_msg, 0);
|
||||
msg_ptr = (struct nlmsghdr *) buffer;*/
|
||||
while ((len = recvmsg(handle->netlink_sock_request_generic, &rtnl_msg, 0)) > 0) { /* read lots of data */
|
||||
msg_ptr = (struct nlmsghdr *) buffer;
|
||||
if (msg_ptr->nlmsg_type == NLMSG_DONE) break;
|
||||
if (msg_ptr->nlmsg_type == NLMSG_ERROR) break;
|
||||
|
||||
if (msg_ptr->nlmsg_type == GENL_ID_CTRL) {
|
||||
nl80211_id = _wireless_parse_family_id (msg_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Generar otro socket netlink generic para eventos */
|
||||
int sock_for_wireless_events;
|
||||
int group;
|
||||
|
||||
sock_for_wireless_events = _wireless_create_generic_netlink_socket ();
|
||||
|
||||
group = scan_multicast_group_id;
|
||||
setsockopt (sock_for_wireless_events, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &group, sizeof (group));
|
||||
|
||||
/* Instalar un GIOChannel */
|
||||
channel = g_io_channel_unix_new (sock_for_wireless_events);
|
||||
|
||||
g_io_add_watch (channel, G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP, _wireless_events_handle_read, handle);
|
||||
}
|
||||
|
||||
//void test_wireless
|
||||
void wireless_check_is_wireless_interface (NetworkInadorHandle *handle, Interface *iface) {
|
||||
struct msghdr rtnl_msg; /* generic msghdr struct for use with sendmsg */
|
||||
struct iovec io;
|
||||
struct genlmsghdr *ghdr;
|
||||
struct rtattr *rta;
|
||||
struct sockaddr_nl kernel;
|
||||
char buffer[8192]; /* a large buffer */
|
||||
int len;
|
||||
|
||||
/* Para la respuesta */
|
||||
struct nlmsgerr *l_err;
|
||||
struct nlmsghdr *msg_ptr; /* pointer to current part */
|
||||
|
||||
struct sockaddr_nl local_nl;
|
||||
socklen_t local_size;
|
||||
|
||||
/* Recuperar el puerto local del netlink */
|
||||
local_size = sizeof (local_nl);
|
||||
getsockname (handle->netlink_sock_request_generic, (struct sockaddr *) &local_nl, &local_size);
|
||||
|
||||
memset (&rtnl_msg, 0, sizeof (rtnl_msg));
|
||||
memset (&kernel, 0, sizeof (kernel));
|
||||
memset (buffer, 0, sizeof (buffer));
|
||||
|
||||
kernel.nl_family = AF_NETLINK; /* fill-in kernel address (destination of our message) */
|
||||
kernel.nl_groups = 0;
|
||||
|
||||
msg_ptr = (struct nlmsghdr *) buffer;
|
||||
msg_ptr->nlmsg_len = NLMSG_LENGTH (sizeof (struct genlmsghdr));
|
||||
msg_ptr->nlmsg_type = nl80211_id;
|
||||
msg_ptr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
msg_ptr->nlmsg_seq = global_nl_seq++;
|
||||
msg_ptr->nlmsg_pid = local_nl.nl_pid;
|
||||
|
||||
ghdr = (struct genlmsghdr *) NLMSG_DATA (msg_ptr);
|
||||
ghdr->cmd = NL80211_CMD_GET_INTERFACE;
|
||||
ghdr->version = 0;
|
||||
|
||||
rta_addattr_l (msg_ptr, sizeof (buffer), NL80211_ATTR_IFINDEX, &iface->index, 4);
|
||||
|
||||
io.iov_base = buffer;
|
||||
io.iov_len = msg_ptr->nlmsg_len;
|
||||
rtnl_msg.msg_iov = &io;
|
||||
rtnl_msg.msg_iovlen = 1;
|
||||
rtnl_msg.msg_name = &kernel;
|
||||
rtnl_msg.msg_namelen = sizeof(kernel);
|
||||
|
||||
sendmsg (handle->netlink_sock_request_generic, (struct msghdr *) &rtnl_msg, 0);
|
||||
|
||||
/* Esperar la respuesta */
|
||||
memset (&io, 0, sizeof (io));
|
||||
memset (&rtnl_msg, 0, sizeof (rtnl_msg));
|
||||
memset (buffer, 0, sizeof (buffer));
|
||||
|
||||
io.iov_base = buffer;
|
||||
io.iov_len = sizeof (buffer);
|
||||
rtnl_msg.msg_iov = &io;
|
||||
rtnl_msg.msg_iovlen = 1;
|
||||
rtnl_msg.msg_name = &kernel;
|
||||
rtnl_msg.msg_namelen = sizeof (kernel);
|
||||
|
||||
while ((len = recvmsg(handle->netlink_sock_request_generic, &rtnl_msg, 0)) > 0) { /* read lots of data */
|
||||
msg_ptr = (struct nlmsghdr *) buffer;
|
||||
if (msg_ptr->nlmsg_type == NLMSG_DONE) break;
|
||||
if (msg_ptr->nlmsg_type == NLMSG_ERROR) {
|
||||
struct nlmsgerr *l_err;
|
||||
l_err = (struct nlmsgerr*) NLMSG_DATA (msg_ptr);
|
||||
break;
|
||||
}
|
||||
|
||||
if (msg_ptr->nlmsg_type == nl80211_id) {
|
||||
_wireless_parse_message_get_iface (msg_ptr, iface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* wireless.h
|
||||
* This file is part of Network-inador
|
||||
*
|
||||
* Copyright (C) 2018 - Félix Arreola Rodríguez
|
||||
*
|
||||
* Network-inador 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Network-inador 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 Network-inador; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __WIRELESS_H__
|
||||
#define __WIRELESS_H__
|
||||
|
||||
#include "network-inador.h"
|
||||
|
||||
void wireless_init (NetworkInadorHandle *handle);
|
||||
void wireless_check_is_wireless_interface (NetworkInadorHandle *handle, Interface *iface);
|
||||
void wireless_do_get_scan (NetworkInadorHandle *handle, int ifindex);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue