mirror of git://git.sysmocom.de/ofono
gisi: Adapt and refactor netlink module
Adapt to using new modem API and clean up naming and coding conventions.
This commit is contained in:
parent
ee2a8bbc69
commit
7cd90666be
118
gisi/netlink.c
118
gisi/netlink.c
|
@ -71,35 +71,15 @@
|
||||||
|
|
||||||
#define SIZE_NLMSG (16384)
|
#define SIZE_NLMSG (16384)
|
||||||
|
|
||||||
struct _GPhonetNetlink {
|
struct _GIsiPhonetNetlink {
|
||||||
GPhonetNetlinkFunc callback;
|
GIsiModem *modem;
|
||||||
|
GIsiPhonetNetlinkFunc callback;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
guint watch;
|
guint watch;
|
||||||
unsigned interface;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline GIsiModem *make_modem(unsigned idx)
|
|
||||||
{
|
|
||||||
return (void *)(uintptr_t)idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GSList *netlink_list;
|
static GSList *netlink_list;
|
||||||
|
|
||||||
GPhonetNetlink *g_pn_netlink_by_modem(GIsiModem *idx)
|
|
||||||
{
|
|
||||||
GSList *m;
|
|
||||||
unsigned index = g_isi_modem_index(idx);
|
|
||||||
|
|
||||||
for (m = netlink_list; m; m = m->next) {
|
|
||||||
GPhonetNetlink *self = m->data;
|
|
||||||
|
|
||||||
if (index == self->interface)
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bring_up(unsigned ifindex)
|
static void bring_up(unsigned ifindex)
|
||||||
{
|
{
|
||||||
struct ifreq req = { .ifr_ifindex = ifindex, };
|
struct ifreq req = { .ifr_ifindex = ifindex, };
|
||||||
|
@ -115,7 +95,7 @@ error:
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int netlink_socket(void)
|
static int pn_netlink_socket(void)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
int bufsize = SIZE_NLMSG;
|
int bufsize = SIZE_NLMSG;
|
||||||
|
@ -133,7 +113,7 @@ static int netlink_socket(void)
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void g_pn_nl_addr(GPhonetNetlink *self, struct nlmsghdr *nlh)
|
static void pn_netlink_addr(GIsiPhonetNetlink *self, struct nlmsghdr *nlh)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
uint8_t local = 0xff;
|
uint8_t local = 0xff;
|
||||||
|
@ -149,7 +129,7 @@ static void g_pn_nl_addr(GPhonetNetlink *self, struct nlmsghdr *nlh)
|
||||||
if (ifa->ifa_family != AF_PHONET)
|
if (ifa->ifa_family != AF_PHONET)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (ifa->ifa_index != self->interface)
|
if (ifa->ifa_index != g_isi_modem_index(self->modem))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (rta = IFA_RTA(ifa); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
|
for (rta = IFA_RTA(ifa); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
|
||||||
|
@ -161,14 +141,14 @@ static void g_pn_nl_addr(GPhonetNetlink *self, struct nlmsghdr *nlh)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void g_pn_nl_link(GPhonetNetlink *self, struct nlmsghdr *nlh)
|
static void pn_netlink_link(GIsiPhonetNetlink *self, struct nlmsghdr *nlh)
|
||||||
{
|
{
|
||||||
const struct ifinfomsg *ifi;
|
const struct ifinfomsg *ifi;
|
||||||
const struct rtattr *rta;
|
const struct rtattr *rta;
|
||||||
int len;
|
int len;
|
||||||
const char *ifname = NULL;
|
const char *ifname = NULL;
|
||||||
GIsiModem *idx = NULL;
|
GIsiPhonetLinkState st;
|
||||||
GPhonetLinkState st;
|
unsigned interface;
|
||||||
|
|
||||||
ifi = NLMSG_DATA(nlh);
|
ifi = NLMSG_DATA(nlh);
|
||||||
len = IFA_PAYLOAD(nlh);
|
len = IFA_PAYLOAD(nlh);
|
||||||
|
@ -176,11 +156,10 @@ static void g_pn_nl_link(GPhonetNetlink *self, struct nlmsghdr *nlh)
|
||||||
if (ifi->ifi_type != ARPHRD_PHONET)
|
if (ifi->ifi_type != ARPHRD_PHONET)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (self->interface != 0 && self->interface != (unsigned)ifi->ifi_index)
|
interface = g_isi_modem_index(self->modem);
|
||||||
|
if (interface != 0 && interface != (unsigned)ifi->ifi_index)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
idx = make_modem(ifi->ifi_index);
|
|
||||||
|
|
||||||
#define UP (IFF_UP | IFF_LOWER_UP | IFF_RUNNING)
|
#define UP (IFF_UP | IFF_LOWER_UP | IFF_RUNNING)
|
||||||
|
|
||||||
if (nlh->nlmsg_type == RTM_DELLINK)
|
if (nlh->nlmsg_type == RTM_DELLINK)
|
||||||
|
@ -197,15 +176,15 @@ static void g_pn_nl_link(GPhonetNetlink *self, struct nlmsghdr *nlh)
|
||||||
ifname = RTA_DATA(rta);
|
ifname = RTA_DATA(rta);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ifname && idx)
|
if (ifname && self->modem)
|
||||||
self->callback(idx, st, ifname, self->opaque);
|
self->callback(self->modem, st, ifname, self->opaque);
|
||||||
|
|
||||||
#undef UP
|
#undef UP
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parser Netlink messages */
|
/* Parser Netlink messages */
|
||||||
static gboolean g_pn_nl_process(GIOChannel *channel, GIOCondition cond,
|
static gboolean pn_netlink_process(GIOChannel *channel, GIOCondition cond,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
struct nlmsghdr nlh;
|
struct nlmsghdr nlh;
|
||||||
|
@ -216,7 +195,7 @@ static gboolean g_pn_nl_process(GIOChannel *channel, GIOCondition cond,
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
struct nlmsghdr *nlh;
|
struct nlmsghdr *nlh;
|
||||||
int fd = g_io_channel_unix_get_fd(channel);
|
int fd = g_io_channel_unix_get_fd(channel);
|
||||||
GPhonetNetlink *self = data;
|
GIsiPhonetNetlink *self = data;
|
||||||
|
|
||||||
if (cond & (G_IO_NVAL|G_IO_HUP))
|
if (cond & (G_IO_NVAL|G_IO_HUP))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -232,7 +211,8 @@ static gboolean g_pn_nl_process(GIOChannel *channel, GIOCondition cond,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (nlh = &resp.nlh; NLMSG_OK(nlh, (size_t)ret);
|
for (nlh = &resp.nlh; NLMSG_OK(nlh, (size_t)ret);
|
||||||
nlh = NLMSG_NEXT(nlh, ret)) {
|
nlh = NLMSG_NEXT(nlh, ret)) {
|
||||||
|
|
||||||
if (nlh->nlmsg_type == NLMSG_DONE)
|
if (nlh->nlmsg_type == NLMSG_DONE)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -246,11 +226,11 @@ static gboolean g_pn_nl_process(GIOChannel *channel, GIOCondition cond,
|
||||||
}
|
}
|
||||||
case RTM_NEWADDR:
|
case RTM_NEWADDR:
|
||||||
case RTM_DELADDR:
|
case RTM_DELADDR:
|
||||||
g_pn_nl_addr(self, nlh);
|
pn_netlink_addr(self, nlh);
|
||||||
break;
|
break;
|
||||||
case RTM_NEWLINK:
|
case RTM_NEWLINK:
|
||||||
case RTM_DELLINK:
|
case RTM_DELLINK:
|
||||||
g_pn_nl_link(self, nlh);
|
pn_netlink_link(self, nlh);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
continue;
|
continue;
|
||||||
|
@ -260,7 +240,7 @@ static gboolean g_pn_nl_process(GIOChannel *channel, GIOCondition cond,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dump current links */
|
/* Dump current links */
|
||||||
static int g_pn_netlink_getlink(int fd)
|
static int pn_netlink_getlink(int fd)
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
struct nlmsghdr nlh;
|
struct nlmsghdr nlh;
|
||||||
|
@ -285,21 +265,35 @@ static int g_pn_netlink_getlink(int fd)
|
||||||
(struct sockaddr *)&addr, sizeof(addr));
|
(struct sockaddr *)&addr, sizeof(addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
GPhonetNetlink *g_pn_netlink_start(GIsiModem *idx,
|
GIsiPhonetNetlink *g_isi_pn_netlink_by_modem(GIsiModem *modem)
|
||||||
GPhonetNetlinkFunc callback,
|
{
|
||||||
void *data)
|
GSList *m;
|
||||||
|
|
||||||
|
for (m = netlink_list; m; m = m->next) {
|
||||||
|
GIsiPhonetNetlink *self = m->data;
|
||||||
|
|
||||||
|
if (g_isi_modem_index(modem) == g_isi_modem_index(self->modem))
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
GIsiPhonetNetlink *g_isi_pn_netlink_start(GIsiModem *modem,
|
||||||
|
GIsiPhonetNetlinkFunc cb,
|
||||||
|
void *data)
|
||||||
{
|
{
|
||||||
GIOChannel *chan;
|
GIOChannel *chan;
|
||||||
GPhonetNetlink *self;
|
GIsiPhonetNetlink *self;
|
||||||
int fd;
|
int fd;
|
||||||
unsigned group = RTNLGRP_LINK;
|
unsigned group = RTNLGRP_LINK;
|
||||||
unsigned interface = g_isi_modem_index(idx);
|
unsigned interface;
|
||||||
|
|
||||||
fd = netlink_socket();
|
fd = pn_netlink_socket();
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
self = calloc(1, sizeof(*self));
|
self = g_try_new0(GIsiPhonetNetlink, 1);
|
||||||
if (self == NULL)
|
if (self == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
@ -309,23 +303,25 @@ GPhonetNetlink *g_pn_netlink_start(GIsiModem *idx,
|
||||||
&group, sizeof(group)))
|
&group, sizeof(group)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
interface = g_isi_modem_index(modem);
|
||||||
if (interface)
|
if (interface)
|
||||||
bring_up(interface);
|
bring_up(interface);
|
||||||
|
|
||||||
g_pn_netlink_getlink(fd);
|
pn_netlink_getlink(fd);
|
||||||
|
|
||||||
chan = g_io_channel_unix_new(fd);
|
chan = g_io_channel_unix_new(fd);
|
||||||
if (chan == NULL)
|
if (chan == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
g_io_channel_set_close_on_unref(chan, TRUE);
|
g_io_channel_set_close_on_unref(chan, TRUE);
|
||||||
g_io_channel_set_encoding(chan, NULL, NULL);
|
g_io_channel_set_encoding(chan, NULL, NULL);
|
||||||
g_io_channel_set_buffered(chan, FALSE);
|
g_io_channel_set_buffered(chan, FALSE);
|
||||||
|
|
||||||
self->callback = callback;
|
self->callback = cb;
|
||||||
self->opaque = data;
|
self->opaque = data;
|
||||||
self->interface = interface;
|
self->modem = modem;
|
||||||
self->watch = g_io_add_watch(chan, G_IO_IN|G_IO_ERR|G_IO_HUP,
|
self->watch = g_io_add_watch(chan, G_IO_IN|G_IO_ERR|G_IO_HUP,
|
||||||
g_pn_nl_process, self);
|
pn_netlink_process, self);
|
||||||
g_io_channel_unref(chan);
|
g_io_channel_unref(chan);
|
||||||
|
|
||||||
netlink_list = g_slist_prepend(netlink_list, self);
|
netlink_list = g_slist_prepend(netlink_list, self);
|
||||||
|
@ -338,16 +334,16 @@ error:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void g_pn_netlink_stop(GPhonetNetlink *self)
|
void g_isi_pn_netlink_stop(GIsiPhonetNetlink *self)
|
||||||
{
|
{
|
||||||
if (self) {
|
if (self) {
|
||||||
netlink_list = g_slist_remove(netlink_list, self);
|
netlink_list = g_slist_remove(netlink_list, self);
|
||||||
g_source_remove(self->watch);
|
g_source_remove(self->watch);
|
||||||
free(self);
|
g_free(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int netlink_getack(int fd)
|
static int pn_netlink_getack(int fd)
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
struct nlmsghdr nlh;
|
struct nlmsghdr nlh;
|
||||||
|
@ -380,7 +376,7 @@ static int netlink_getack(int fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set local address */
|
/* Set local address */
|
||||||
static int netlink_setaddr(uint32_t ifa_index, uint8_t ifa_local)
|
static int pn_netlink_setaddr(uint32_t ifa_index, uint8_t ifa_local)
|
||||||
{
|
{
|
||||||
struct ifaddrmsg *ifa;
|
struct ifaddrmsg *ifa;
|
||||||
struct rtattr *rta;
|
struct rtattr *rta;
|
||||||
|
@ -411,23 +407,23 @@ static int netlink_setaddr(uint32_t ifa_index, uint8_t ifa_local)
|
||||||
rta->rta_len = RTA_LENGTH(1);
|
rta->rta_len = RTA_LENGTH(1);
|
||||||
*(uint8_t *)RTA_DATA(rta) = ifa_local;
|
*(uint8_t *)RTA_DATA(rta) = ifa_local;
|
||||||
|
|
||||||
fd = netlink_socket();
|
fd = pn_netlink_socket();
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
if (sendto(fd, &req, reqlen, 0, (void *)&addr, sizeof(addr)) == -1)
|
if (sendto(fd, &req, reqlen, 0, (void *)&addr, sizeof(addr)) == -1)
|
||||||
error = -errno;
|
error = -errno;
|
||||||
else
|
else
|
||||||
error = netlink_getack(fd);
|
error = pn_netlink_getack(fd);
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
int g_pn_netlink_set_address(GIsiModem *idx, uint8_t local)
|
int g_isi_pn_netlink_set_address(GIsiModem *modem, uint8_t local)
|
||||||
{
|
{
|
||||||
uint32_t ifindex = g_isi_modem_index(idx);
|
uint32_t ifindex = g_isi_modem_index(modem);
|
||||||
|
|
||||||
if (ifindex == 0)
|
if (ifindex == 0)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -435,5 +431,5 @@ int g_pn_netlink_set_address(GIsiModem *idx, uint8_t local)
|
||||||
if (local != PN_DEV_PC && local != PN_DEV_SOS)
|
if (local != PN_DEV_PC && local != PN_DEV_SOS)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
return netlink_setaddr(ifindex, local);
|
return pn_netlink_setaddr(ifindex, local);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,45 +22,42 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <gisi/modem.h>
|
#include <gisi/modem.h>
|
||||||
|
|
||||||
#ifndef __GPHONET_NETLINK_H
|
#ifndef __GISI_PN_NETLINK_H
|
||||||
#define __GPHONET_NETLINK_H
|
#define __GISI_PN_NETLINK_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct _GPhonetNetlink;
|
struct _GIsiPhonetNetlink;
|
||||||
typedef struct _GPhonetNetlink GPhonetNetlink;
|
typedef struct _GIsiPhonetNetlink GIsiPhonetNetlink;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PN_LINK_REMOVED,
|
PN_LINK_REMOVED,
|
||||||
PN_LINK_DOWN,
|
PN_LINK_DOWN,
|
||||||
PN_LINK_UP
|
PN_LINK_UP
|
||||||
} GPhonetLinkState;
|
} GIsiPhonetLinkState;
|
||||||
|
|
||||||
enum {
|
typedef enum {
|
||||||
PN_DEV_PC = 0x10, /* PC Suite */
|
PN_DEV_PC = 0x10, /* PC Suite */
|
||||||
PN_DEV_HOST = 0x00, /* Modem */
|
PN_DEV_HOST = 0x00, /* Modem */
|
||||||
PN_DEV_SOS = 0x6C, /* Symbian or Linux */
|
PN_DEV_SOS = 0x6C, /* Symbian or Linux */
|
||||||
};
|
} GIsiPhonetDevice;
|
||||||
|
|
||||||
typedef void (*GPhonetNetlinkFunc)(GIsiModem *idx,
|
typedef void (*GIsiPhonetNetlinkFunc)(GIsiModem *modem, GIsiPhonetLinkState st,
|
||||||
GPhonetLinkState st,
|
char const *iface, void *data);
|
||||||
char const *iface,
|
|
||||||
void *data);
|
|
||||||
|
|
||||||
GPhonetNetlink *g_pn_netlink_by_modem(GIsiModem *idx);
|
GIsiPhonetNetlink *g_isi_pn_netlink_by_modem(GIsiModem *modem);
|
||||||
|
|
||||||
GPhonetNetlink *g_pn_netlink_start(GIsiModem *idx,
|
GIsiPhonetNetlink *g_isi_pn_netlink_start(GIsiModem *idx,
|
||||||
GPhonetNetlinkFunc callback,
|
GIsiPhonetNetlinkFunc cb,
|
||||||
void *data);
|
void *data);
|
||||||
|
|
||||||
void g_pn_netlink_stop(GPhonetNetlink *self);
|
void g_isi_pn_netlink_stop(GIsiPhonetNetlink *self);
|
||||||
|
int g_isi_pn_netlink_set_address(GIsiModem *modem, uint8_t local);
|
||||||
int g_pn_netlink_set_address(GIsiModem *, uint8_t local);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __GPHONET_NETLINK_H */
|
#endif /* __GISI_PN_NETLINK_H */
|
||||||
|
|
Loading…
Reference in New Issue