Agrego manejo de IP's usando libnl3
parent
060cc47735
commit
4380abdeb7
|
@ -3,7 +3,8 @@
|
|||
bin_PROGRAMS = network-inador
|
||||
network_inador_SOURCES = main.c common.h \
|
||||
netlink-events.c netlink-events.h \
|
||||
interfaces.c interfaces.h
|
||||
interfaces.c interfaces.h \
|
||||
ip-address.c ip-address.h
|
||||
|
||||
#network_inador_CPPFLAGS = -DGAMEDATA_DIR=\"$(gamedatadir)/\" -DLOCALEDIR=\"$(localedir)\" $(AM_CPPFLAGS)
|
||||
network_inador_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" $(AM_CPPFLAGS)
|
||||
|
|
16
src/common.h
16
src/common.h
|
@ -23,6 +23,8 @@
|
|||
#ifndef __COMMON_H__
|
||||
#define __COMMON_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <linux/if.h>
|
||||
|
@ -38,6 +40,18 @@
|
|||
#define TRUE !FALSE
|
||||
#endif
|
||||
|
||||
typedef struct _IPAddr {
|
||||
sa_family_t family;
|
||||
union {
|
||||
struct in_addr sin_addr;
|
||||
struct in6_addr sin6_addr;
|
||||
};
|
||||
uint32_t prefix;
|
||||
|
||||
unsigned char flags;
|
||||
unsigned char scope;
|
||||
} IPAddr;
|
||||
|
||||
typedef struct _Interface {
|
||||
char name[IFNAMSIZ];
|
||||
int ifi_type;
|
||||
|
@ -65,7 +79,7 @@ typedef struct _Interface {
|
|||
int is_nlmon;
|
||||
int is_dummy;
|
||||
|
||||
//IPv4 *v4_address;
|
||||
GList *address;
|
||||
|
||||
//DHCPStateInfo dhcp_info;
|
||||
|
||||
|
|
|
@ -30,9 +30,10 @@
|
|||
#include <gmodule.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "interfaces.h"
|
||||
#include "ip-address.h"
|
||||
|
||||
static int _interfaces_receive_message_interface (struct nl_msg *msg, void *arg, int first_time);
|
||||
Interface * _interfaces_locate_by_index (GList *list, int index);
|
||||
|
||||
static int _interfaces_list_first_time (struct nl_msg *msg, void *arg) {
|
||||
return _interfaces_receive_message_interface (msg, arg, TRUE);
|
||||
|
@ -263,6 +264,9 @@ int interface_receive_message_dellink (struct nl_msg *msg, void *arg) {
|
|||
|
||||
handle->interfaces = g_list_remove (handle->interfaces, iface);
|
||||
|
||||
/* Antes de eliminar la interfaz, eliminar la lista ligada de todas las direcciones IP */
|
||||
g_list_free_full (iface->address, g_free);
|
||||
|
||||
g_free (iface);
|
||||
}
|
||||
|
||||
|
@ -553,5 +557,7 @@ void interfaces_init (NetworkInadorHandle *handle) {
|
|||
nl_socket_modify_cb (handle->nl_sock_route, NL_CB_VALID, NL_CB_CUSTOM, _interfaces_list_first_time, handle);
|
||||
|
||||
nl_recvmsgs_default (handle->nl_sock_route);
|
||||
|
||||
ip_address_init (handle);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,12 +23,17 @@
|
|||
#ifndef __INTERFACES_H__
|
||||
#define __INTERFACES_H__
|
||||
|
||||
#include <netlink/socket.h>
|
||||
#include <netlink/msg.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
void interfaces_init (NetworkInadorHandle *handle);
|
||||
int interface_receive_message_newlink (struct nl_msg *msg, void *arg);
|
||||
int interface_receive_message_dellink (struct nl_msg *msg, void *arg);
|
||||
|
||||
Interface * _interfaces_locate_by_index (GList *list, int index);
|
||||
|
||||
int interfaces_change_mac_address (NetworkInadorHandle *handle, int index, void *new_mac);
|
||||
int interfaces_change_mtu (NetworkInadorHandle *handle, int index, uint32_t new_mtu);
|
||||
int interfaces_change_set_up (NetworkInadorHandle *handle, int index);
|
||||
|
|
208
src/ip-address.c
208
src/ip-address.c
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* ip-address.c
|
||||
* This file is part of Network-inador
|
||||
*
|
||||
* Copyright (C) 2019, 2020 - 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 <string.h>
|
||||
|
||||
#include <netlink/socket.h>
|
||||
#include <netlink/msg.h>
|
||||
|
||||
#include <net/if_arp.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <gmodule.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "ip-address.h"
|
||||
#include "interfaces.h"
|
||||
|
||||
static IPAddr *_ip_address_search_addr (Interface *iface, sa_family_t family, void *addr_data, uint32_t prefix) {
|
||||
GList *g;
|
||||
IPAddr *addr;
|
||||
|
||||
for (g = iface->address; g != NULL; g = g->next) {
|
||||
addr = (IPAddr *) g->data;
|
||||
|
||||
if (addr->family == family) {
|
||||
if (family == AF_INET && memcmp (&addr->sin_addr, addr_data, sizeof (struct in_addr)) == 0 && addr->prefix == prefix) {
|
||||
return addr;
|
||||
} else if (family == AF_INET6 && memcmp (&addr->sin6_addr, addr_data, sizeof (struct in6_addr)) == 0 && addr->prefix == prefix) {
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ip_address_receive_message_newaddr (struct nl_msg *msg, void *arg) {
|
||||
struct nlmsghdr *reply;
|
||||
struct ifaddrmsg *addr_msg;
|
||||
int remaining;
|
||||
struct nlattr *attr;
|
||||
NetworkInadorHandle *handle = (NetworkInadorHandle *) arg;
|
||||
Interface *iface;
|
||||
int has_addr = 0;
|
||||
struct in_addr sin_addr;
|
||||
struct in6_addr sin6_addr;
|
||||
IPAddr *addr;
|
||||
|
||||
reply = nlmsg_hdr (msg);
|
||||
|
||||
if (reply->nlmsg_type != RTM_NEWADDR) return NL_SKIP;
|
||||
|
||||
addr_msg = nlmsg_data (reply);
|
||||
|
||||
iface = _interfaces_locate_by_index (handle->interfaces, addr_msg->ifa_index);
|
||||
|
||||
if (iface == NULL) {
|
||||
printf ("IP para una interfaz desconocida\n");
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
nlmsg_for_each_attr(attr, reply, sizeof (struct ifaddrmsg), remaining) {
|
||||
if (nla_type (attr) != IFA_ADDRESS) continue;
|
||||
|
||||
if (addr_msg->ifa_family == AF_INET && nla_len (attr) == 4) {
|
||||
/* IP de ipv4 */
|
||||
memcpy (&sin_addr, nla_data (attr), nla_len (attr));
|
||||
has_addr = 1;
|
||||
} else if (addr_msg->ifa_family == AF_INET6 && nla_len (attr) == 16) {
|
||||
/* IP de ipv6 */
|
||||
memcpy (&sin6_addr, nla_data (attr), nla_len (attr));
|
||||
has_addr = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (addr_msg->ifa_family == AF_INET) {
|
||||
addr = _ip_address_search_addr (iface, AF_INET, &sin_addr, addr_msg->ifa_prefixlen);
|
||||
} else if (addr_msg->ifa_family == AF_INET6) {
|
||||
addr = _ip_address_search_addr (iface, AF_INET6, &sin6_addr, addr_msg->ifa_prefixlen);
|
||||
}
|
||||
|
||||
if (addr == NULL) {
|
||||
addr = g_new0 (IPAddr, 1);
|
||||
|
||||
iface->address = g_list_append (iface->address, addr);
|
||||
|
||||
addr->family = addr_msg->ifa_family;
|
||||
if (addr->family == AF_INET) {
|
||||
memcpy (&addr->sin_addr, &sin_addr, sizeof (struct in_addr));
|
||||
} else if (addr->family == AF_INET6) {
|
||||
memcpy (&addr->sin6_addr, &sin6_addr, sizeof (struct in6_addr));
|
||||
}
|
||||
|
||||
addr->prefix = addr_msg->ifa_prefixlen;
|
||||
}
|
||||
|
||||
char buffer[2048];
|
||||
inet_ntop (addr->family, &addr->sin_addr, buffer, sizeof (buffer));
|
||||
printf ("Dirección IP %s/%d sobre interfaz: %d\n", buffer, addr->prefix, iface->index);
|
||||
|
||||
addr->flags = addr_msg->ifa_flags;
|
||||
addr->scope = addr_msg->ifa_scope;
|
||||
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
int ip_address_receive_message_deladdr (struct nl_msg *msg, void *arg) {
|
||||
struct nlmsghdr *reply;
|
||||
struct ifaddrmsg *addr_msg;
|
||||
int remaining;
|
||||
struct nlattr *attr;
|
||||
NetworkInadorHandle *handle = (NetworkInadorHandle *) arg;
|
||||
Interface *iface;
|
||||
struct in_addr sin_addr;
|
||||
struct in6_addr sin6_addr;
|
||||
IPAddr *addr = NULL;
|
||||
|
||||
reply = nlmsg_hdr (msg);
|
||||
|
||||
if (reply->nlmsg_type != RTM_DELADDR) return NL_SKIP;
|
||||
|
||||
addr_msg = nlmsg_data (reply);
|
||||
|
||||
iface = _interfaces_locate_by_index (handle->interfaces, addr_msg->ifa_index);
|
||||
|
||||
if (iface == NULL) {
|
||||
printf ("IP para una interfaz desconocida\n");
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
nlmsg_for_each_attr(attr, reply, sizeof (struct ifaddrmsg), remaining) {
|
||||
if (nla_type (attr) != IFA_ADDRESS) continue;
|
||||
|
||||
if (addr_msg->ifa_family == AF_INET && nla_len (attr) == 4) {
|
||||
/* IP de ipv4 */
|
||||
memcpy (&sin_addr, nla_data (attr), nla_len (attr));
|
||||
} else if (addr_msg->ifa_family == AF_INET6 && nla_len (attr) == 16) {
|
||||
/* IP de ipv6 */
|
||||
memcpy (&sin6_addr, nla_data (attr), nla_len (attr));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (addr_msg->ifa_family == AF_INET) {
|
||||
addr = _ip_address_search_addr (iface, AF_INET, &sin_addr, addr_msg->ifa_prefixlen);
|
||||
} else if (addr_msg->ifa_family == AF_INET6) {
|
||||
addr = _ip_address_search_addr (iface, AF_INET6, &sin6_addr, addr_msg->ifa_prefixlen);
|
||||
}
|
||||
|
||||
if (addr == NULL) {
|
||||
printf ("IP no encontrada\n");
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
/* Eliminar de la lista ligada */
|
||||
iface->address = g_list_remove (iface->address, addr);
|
||||
|
||||
g_free (addr);
|
||||
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
void ip_address_init (NetworkInadorHandle *handle) {
|
||||
/* Si es la primera vez que nos llaman, descargar una primera lista de direcciones en todas las interfaces */
|
||||
struct nl_msg * msg;
|
||||
struct ifaddrmsg addr_hdr = {
|
||||
.ifa_family = AF_UNSPEC,
|
||||
};
|
||||
int ret;
|
||||
|
||||
msg = nlmsg_alloc_simple (RTM_GETADDR, NLM_F_REQUEST | NLM_F_DUMP);
|
||||
ret = nlmsg_append (msg, &addr_hdr, sizeof (addr_hdr), NLMSG_ALIGNTO);
|
||||
|
||||
if (ret != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
nl_complete_msg (handle->nl_sock_route, msg);
|
||||
|
||||
ret = nl_send (handle->nl_sock_route, msg);
|
||||
|
||||
nlmsg_free (msg);
|
||||
|
||||
nl_socket_modify_cb (handle->nl_sock_route, NL_CB_VALID, NL_CB_CUSTOM, ip_address_receive_message_newaddr, handle);
|
||||
|
||||
nl_recvmsgs_default (handle->nl_sock_route);
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* ip-address.c
|
||||
* This file is part of Network-inador
|
||||
*
|
||||
* Copyright (C) 2019, 2020 - 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 __IP_ADDRESS_H__
|
||||
#define __IP_ADDRESS_H__
|
||||
|
||||
#include <netlink/socket.h>
|
||||
#include <netlink/msg.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
int ip_address_receive_message_newaddr (struct nl_msg *msg, void *arg);
|
||||
void ip_address_init (NetworkInadorHandle *handle);
|
||||
|
||||
#endif
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "common.h"
|
||||
#include "interfaces.h"
|
||||
#include "ip-address.h"
|
||||
|
||||
static int _netlink_events_route_dispatcher (struct nl_msg *msg, void *arg) {
|
||||
struct nlmsghdr *reply;
|
||||
|
@ -35,12 +36,20 @@ static int _netlink_events_route_dispatcher (struct nl_msg *msg, void *arg) {
|
|||
|
||||
switch (reply->nlmsg_type) {
|
||||
case RTM_NEWLINK:
|
||||
interface_receive_message_newlink (msg, arg);
|
||||
return interface_receive_message_newlink (msg, arg);
|
||||
break;
|
||||
case RTM_DELLINK:
|
||||
interface_receive_message_dellink (msg, arg);
|
||||
return interface_receive_message_dellink (msg, arg);
|
||||
break;
|
||||
case RTM_NEWADDR:
|
||||
return ip_address_receive_message_newaddr (msg, arg);
|
||||
break;
|
||||
case RTM_DELADDR:
|
||||
return ip_address_receive_message_deladdr (msg, arg);
|
||||
break;
|
||||
}
|
||||
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
static gboolean _netlink_events_handle_read (GIOChannel *source, GIOCondition condition, gpointer data) {
|
||||
|
@ -64,7 +73,7 @@ void netlink_events_setup (NetworkInadorHandle *handle) {
|
|||
}
|
||||
|
||||
nl_socket_set_nonblocking (sock_req);
|
||||
nl_socket_add_memberships (sock_req, RTNLGRP_LINK, 0);
|
||||
nl_socket_add_memberships (sock_req, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR, 0);
|
||||
nl_socket_disable_seq_check (sock_req);
|
||||
nl_socket_modify_cb (sock_req, NL_CB_VALID, NL_CB_CUSTOM, _netlink_events_route_dispatcher, handle);
|
||||
|
||||
|
|
Loading…
Reference in New Issue