gisi: Adapt and refactor netlink module

Adapt to using new modem API and clean up naming and coding
conventions.
This commit is contained in:
Aki Niemi 2010-11-14 18:28:12 +02:00
parent ee2a8bbc69
commit 7cd90666be
2 changed files with 73 additions and 80 deletions

View File

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

View File

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