Agrego funciones básicas de wireless

* Agrego manejo de señal de cierre del proceso
master
Félix Arreola Rodríguez 2019-02-16 18:13:15 -06:00
parent 969415b70c
commit 3aedf1869e
6 changed files with 759 additions and 8 deletions

View File

@ -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)

View File

@ -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 */

View File

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

View File

@ -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

611
src/wireless.c 100644
View File

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

32
src/wireless.h 100644
View File

@ -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