3 * PPP library with GLib integration
5 * Copyright (C) 2009-2011 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 #include <linux/if_tun.h>
32 #include <sys/ioctl.h>
33 #include <arpa/inet.h>
41 #define MAX_PACKET 1500
49 struct ppp_header *ppp_packet;
52 gboolean ppp_net_set_mtu(struct ppp_net *net, guint16 mtu)
57 if (net == NULL || mtu > MAX_PACKET)
62 sk = socket(AF_INET, SOCK_DGRAM, 0);
66 memset(&ifr, 0, sizeof(ifr));
67 strncpy(ifr.ifr_name, net->if_name, sizeof(ifr.ifr_name));
70 err = ioctl(sk, SIOCSIFMTU, (caddr_t) &ifr);
80 void ppp_net_process_packet(struct ppp_net *net, const guint8 *packet,
90 /* find the length of the packet to transmit */
91 len = get_host_short(&packet[2]);
92 status = g_io_channel_write_chars(net->channel, (gchar *) packet,
94 &bytes_written, NULL);
96 if (status != G_IO_STATUS_NORMAL)
101 * packets received by the tun interface need to be written to
102 * the modem. So, just read a packet, write out to the modem
104 static gboolean ppp_net_callback(GIOChannel *channel, GIOCondition cond,
107 struct ppp_net *net = (struct ppp_net *) userdata;
110 gchar *buf = (gchar *) net->ppp_packet->info;
112 if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
115 if (cond & G_IO_IN) {
116 /* leave space to add PPP protocol field */
117 status = g_io_channel_read_chars(channel, buf, net->mtu,
120 ppp_transmit(net->ppp, (guint8 *) net->ppp_packet,
123 if (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN)
129 const char *ppp_net_get_interface(struct ppp_net *net)
134 struct ppp_net *ppp_net_new(GAtPPP *ppp, int fd)
137 GIOChannel *channel = NULL;
141 net = g_try_new0(struct ppp_net, 1);
145 net->ppp_packet = ppp_packet_new(MAX_PACKET, PPP_IP_PROTO);
146 if (net->ppp_packet == NULL)
150 * If the fd value is still the default one,
151 * open the tun interface and configure it.
153 memset(&ifr, 0, sizeof(ifr));
156 /* open a tun interface */
157 fd = open("/dev/net/tun", O_RDWR);
159 ppp_debug(ppp, "Couldn't open tun device. "
160 "Do you run oFono as root and do you "
161 "have the TUN module loaded?");
165 ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
166 strcpy(ifr.ifr_name, "ppp%d");
168 err = ioctl(fd, TUNSETIFF, (void *) &ifr);
172 err = ioctl(fd, TUNGETIFF, (void *) &ifr);
177 net->if_name = strdup(ifr.ifr_name);
179 /* create a channel for reading and writing to this interface */
180 channel = g_io_channel_unix_new(fd);
184 if (!g_at_util_setup_io(channel, 0))
187 g_io_channel_set_buffered(channel, FALSE);
189 net->channel = channel;
190 net->watch = g_io_add_watch(channel,
191 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
192 ppp_net_callback, net);
195 net->mtu = MAX_PACKET;
200 g_io_channel_unref(channel);
202 g_free(net->if_name);
203 g_free(net->ppp_packet);
213 void ppp_net_free(struct ppp_net *net)
216 g_source_remove(net->watch);
220 g_io_channel_unref(net->channel);
222 g_free(net->ppp_packet);
223 g_free(net->if_name);
227 void ppp_net_suspend_interface(struct ppp_net *net)
229 if (net == NULL || net->channel == NULL)
235 g_source_remove(net->watch);
239 void ppp_net_resume_interface(struct ppp_net *net)
241 if (net == NULL || net->channel == NULL)
244 net->watch = g_io_add_watch(net->channel,
245 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
246 ppp_net_callback, net);