summaryrefslogtreecommitdiffstats
path: root/gatchat
diff options
context:
space:
mode:
Diffstat (limited to 'gatchat')
-rw-r--r--gatchat/gatppp.c27
-rw-r--r--gatchat/ppp.h4
-rw-r--r--gatchat/ppp_net.c82
3 files changed, 50 insertions, 63 deletions
diff --git a/gatchat/gatppp.c b/gatchat/gatppp.c
index dc26f29c..de631322 100644
--- a/gatchat/gatppp.c
+++ b/gatchat/gatppp.c
@@ -172,7 +172,9 @@ static void ppp_recv(GAtPPP *ppp, struct frame_buffer *frame)
switch (protocol) {
case PPP_IP_PROTO:
- ppp_net_process_packet(ppp->net, packet);
+ /* If network is up & open, process the packet, if not, drop */
+ if (ppp->net)
+ ppp_net_process_packet(ppp->net, packet);
break;
case LCP_PROTOCOL:
pppcp_process_packet(ppp->lcp, packet);
@@ -407,20 +409,24 @@ void ppp_auth_notify(GAtPPP *ppp, gboolean success)
void ppp_net_up_notify(GAtPPP *ppp, const char *ip,
const char *dns1, const char *dns2)
{
- /* bring network phase up */
- ppp_net_open(ppp->net);
+ ppp->net = ppp_net_new(ppp);
if (ppp->connect_cb == NULL)
return;
- ppp->connect_cb(G_AT_PPP_CONNECT_SUCCESS,
- ppp_net_get_interface(ppp->net),
- ip, dns1, dns2, ppp->connect_data);
+ if (ppp->net == NULL)
+ ppp->connect_cb(G_AT_PPP_CONNECT_FAIL, NULL,
+ NULL, NULL, NULL, ppp->connect_data);
+ else
+ ppp->connect_cb(G_AT_PPP_CONNECT_SUCCESS,
+ ppp_net_get_interface(ppp->net),
+ ip, dns1, dns2, ppp->connect_data);
}
void ppp_net_down_notify(GAtPPP *ppp)
{
- ppp_net_close(ppp->net);
+ ppp_net_free(ppp->net);
+ ppp->net = NULL;
}
void ppp_set_recv_accm(GAtPPP *ppp, guint32 accm)
@@ -569,7 +575,9 @@ void g_at_ppp_unref(GAtPPP *ppp)
lcp_free(ppp->lcp);
ppp_chap_free(ppp->chap);
ipcp_free(ppp->ipcp);
- ppp_net_free(ppp->net);
+
+ if (ppp->net)
+ ppp_net_free(ppp->net);
g_free(ppp);
}
@@ -611,9 +619,6 @@ GAtPPP *g_at_ppp_new(GIOChannel *modem)
/* initialize IPCP state */
ppp->ipcp = ipcp_new(ppp);
- /* intialize the network state */
- ppp->net = ppp_net_new(ppp);
-
/* start listening for packets from the modem */
ppp->read_watch = g_io_add_watch_full(modem, G_PRIORITY_DEFAULT,
G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
diff --git a/gatchat/ppp.h b/gatchat/ppp.h
index 867dcc7a..a7b13313 100644
--- a/gatchat/ppp.h
+++ b/gatchat/ppp.h
@@ -101,8 +101,6 @@ void ppp_chap_process_packet(struct ppp_chap *chap, guint8 *new_packet);
/* TUN / Network related functions */
struct ppp_net *ppp_net_new(GAtPPP *ppp);
-void ppp_net_open(struct ppp_net *net);
+const char *ppp_net_get_interface(struct ppp_net *net);
void ppp_net_process_packet(struct ppp_net *net, guint8 *packet);
-void ppp_net_close(struct ppp_net *net);
void ppp_net_free(struct ppp_net *net);
-const char *ppp_net_get_interface(struct ppp_net *net);
diff --git a/gatchat/ppp_net.c b/gatchat/ppp_net.c
index 8b2fc8dd..8d1a5d48 100644
--- a/gatchat/ppp_net.c
+++ b/gatchat/ppp_net.c
@@ -55,13 +55,6 @@ void ppp_net_process_packet(struct ppp_net *net, guint8 *packet)
gsize bytes_written;
guint16 len;
- /*
- * since ppp_net_open can fail, we need to make sure
- * channel is valid
- */
- if (net->channel == NULL)
- return;
-
/* find the length of the packet to transmit */
len = get_host_short(&packet[2]);
status = g_io_channel_write_chars(net->channel, (gchar *) packet,
@@ -99,81 +92,72 @@ static gboolean ppp_net_callback(GIOChannel *channel, GIOCondition cond,
return TRUE;
}
-void ppp_net_close(struct ppp_net *net)
+const char *ppp_net_get_interface(struct ppp_net *net)
{
- g_source_remove(net->watch);
- g_io_channel_unref(net->channel);
+ return net->if_name;
}
-void ppp_net_open(struct ppp_net *net)
+struct ppp_net *ppp_net_new(GAtPPP *ppp)
{
+ struct ppp_net *net;
int fd;
struct ifreq ifr;
- GIOChannel *channel;
+ GIOChannel *channel = NULL;
int err;
+ net = g_try_new0(struct ppp_net, 1);
if (net == NULL)
- return;
+ return NULL;
/* open a tun interface */
fd = open("/dev/net/tun", O_RDWR);
- if (fd < 0) {
- g_printerr("error opening tun\n");
- return;
- }
+ if (fd < 0)
+ goto error;
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
strcpy(ifr.ifr_name, "ppp%d");
+
err = ioctl(fd, TUNSETIFF, (void *)&ifr);
- if (err < 0) {
- g_printerr("error %d setting ifr\n", err);
- close(fd);
- return;
- }
+ if (err < 0)
+ goto error;
+
net->if_name = strdup(ifr.ifr_name);
/* create a channel for reading and writing to this interface */
channel = g_io_channel_unix_new(fd);
- if (!channel) {
- g_printerr("Error creating I/O Channel to TUN device\n");
- close(fd);
- return;
- }
- if (!g_at_util_setup_io(channel, G_IO_FLAG_NONBLOCK)) {
- g_io_channel_unref(channel);
- return;
- }
- net->channel = channel;
+ if (channel == NULL)
+ goto error;
+
+ if (!g_at_util_setup_io(channel, G_IO_FLAG_NONBLOCK))
+ goto error;
+
g_io_channel_set_buffered(channel, FALSE);
+
+ net->channel = channel;
net->watch = g_io_add_watch(channel,
G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
ppp_net_callback, net);
-}
-
-const char *ppp_net_get_interface(struct ppp_net *net)
-{
- return net->if_name;
-}
+ net->ppp = ppp;
-struct ppp_net *ppp_net_new(GAtPPP *ppp)
-{
- struct ppp_net *net;
+ return net;
- net = g_try_new0(struct ppp_net, 1);
- if (net == NULL)
- return NULL;
+error:
+ if (channel)
+ g_io_channel_unref(channel);
- net->ppp = ppp;
+ if (fd >= 0)
+ close(fd);
- return net;
+ g_free(net);
+ return NULL;
}
void ppp_net_free(struct ppp_net *net)
{
- /* cleanup tun interface */
- ppp_net_close(net);
+ g_source_remove(net->watch);
+ g_io_channel_unref(net->channel);
- /* free self */
+ g_free(net->if_name);
g_free(net);
}