3 (c) 2010 Gregor Riepl <onitake@gmail.com>
5 Tethering utility for Maemo
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <netinet/in.h>
25 #define MTETHERD_DEVICE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_MTETHERD_DEVICE, MTetherDDevicePrivate))
27 G_DEFINE_TYPE(MTetherDDevice, mtetherd_device, G_TYPE_OBJECT);
29 static const guint MAX_DEVICES = 64;
30 // Host order 192.168.255.0
31 static const in_addr_t HOST_BASE_ADDRESS = 0xc0a8ff00;
32 // Host order 255.255.255.252
33 static const in_addr_t HOST_NETMASK = 0xfffffffc;
35 static const in_addr_t HOST_ROUTER = 0x00000002;
37 static const in_addr_t HOST_DHCP = 0x00000001;
39 struct _MTetherDDevicePrivate {
49 static void mtetherd_device_finalize(GObject *object) {
50 MTetherDDevice *self = MTETHERD_DEVICE(object);
52 if (self && self->priv) {
53 g_free(self->priv->interface);
54 g_free(self->priv->udi);
58 static void mtetherd_device_class_init(MTetherDDeviceClass *klass) {
59 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
61 gobject_class->finalize = mtetherd_device_finalize;
62 g_type_class_add_private(klass, sizeof(MTetherDDevicePrivate));
65 static void mtetherd_device_init(MTetherDDevice *self) {
66 self->priv = MTETHERD_DEVICE_GET_PRIVATE(self);
69 self->priv->interface = NULL;
70 self->priv->udi = NULL;
72 self->priv->netmask = 0;
73 self->priv->dhcp_start = 0;
74 self->priv->dhcp_end = 0;
78 static void mtetherd_device_set_interface(MTetherDDevice *self, const gchar *interface) {
79 if (self && self->priv) {
80 if (self->priv->interface) {
81 g_free(self->priv->interface);
84 size_t len = strlen(interface);
85 self->priv->interface = g_malloc(len + 1);
87 for (i = 0, j = 0; i < len; i++) {
88 if (g_ascii_isalnum(interface[i])) {
89 self->priv->interface[j] = interface[i];
93 self->priv->interface[j] = '\0';
98 static void mtetherd_device_set_udi(MTetherDDevice *self, const gchar *udi) {
99 if (self && self->priv) {
100 if (self->priv->udi) {
101 g_free(self->priv->udi);
104 size_t len = strlen(udi);
105 self->priv->udi = g_malloc(len + 1);
107 for (i = 0, j = 0; i < len; i++) {
108 if (g_ascii_isalnum(udi[i]) || g_ascii_ispunct(udi[i])) {
109 self->priv->udi[j] = udi[i];
113 self->priv->udi[j] = '\0';
118 void mtetherd_device_set_index(MTetherDDevice *self, guint index) {
119 if (self && self->priv) {
120 // Maximum is 63, we need four addresses per subnet
122 in_addr_t subnet = HOST_BASE_ADDRESS | (index << 2);
123 in_addr_t addr = subnet | HOST_ROUTER;
124 in_addr_t start = subnet | HOST_DHCP;
125 self->priv->addr = htonl(addr);
126 self->priv->netmask = htonl(HOST_NETMASK);
127 self->priv->dhcp_start = htonl(start);
128 self->priv->dhcp_end = htonl(addr);
130 g_warning("Invalid subnet index: %u (0..%u expected)", index, MAX_DEVICES - 1);
135 MTetherDDevice *mtetherd_device_new(const gchar *interface, const gchar *udi) {
136 MTetherDDevice *self = MTETHERD_DEVICE(g_object_new(TYPE_MTETHERD_DEVICE, NULL));
138 if (self && self->priv) {
139 mtetherd_device_set_interface(self, interface);
140 mtetherd_device_set_udi(self, udi);
146 const gchar *mtetherd_device_get_interface(MTetherDDevice *self) {
147 if (self && self->priv) {
148 return self->priv->interface;
153 gchar *mtetherd_device_get_addr(MTetherDDevice *self) {
154 if (self && self->priv) {
155 guchar a = self->priv->addr & 0xff;
156 guchar b = (self->priv->addr >> 8) & 0xff;
157 guchar c = (self->priv->addr >> 16) & 0xff;
158 guchar d = (self->priv->addr >> 24) & 0xff;
159 return g_strdup_printf("%u.%u.%u.%u", a, b, c, d);
164 gchar *mtetherd_device_get_netmask(MTetherDDevice *self) {
165 if (self && self->priv) {
166 guchar a = self->priv->netmask & 0xff;
167 guchar b = (self->priv->netmask >> 8) & 0xff;
168 guchar c = (self->priv->netmask >> 16) & 0xff;
169 guchar d = (self->priv->netmask >> 24) & 0xff;
170 return g_strdup_printf("%u.%u.%u.%u", a, b, c, d);
175 gchar *mtetherd_device_get_dhcp_start(MTetherDDevice *self) {
176 if (self && self->priv) {
177 guchar a = self->priv->dhcp_start & 0xff;
178 guchar b = (self->priv->dhcp_start >> 8) & 0xff;
179 guchar c = (self->priv->dhcp_start >> 16) & 0xff;
180 guchar d = (self->priv->dhcp_start >> 24) & 0xff;
181 return g_strdup_printf("%u.%u.%u.%u", a, b, c, d);
186 gchar *mtetherd_device_get_dhcp_end(MTetherDDevice *self) {
187 if (self && self->priv) {
188 guchar a = self->priv->dhcp_end & 0xff;
189 guchar b = (self->priv->dhcp_end >> 8) & 0xff;
190 guchar c = (self->priv->dhcp_end >> 16) & 0xff;
191 guchar d = (self->priv->dhcp_end >> 24) & 0xff;
192 return g_strdup_printf("%u.%u.%u.%u", a, b, c, d);
197 static gint mtetherd_device_list_find_index(gpointer *array, const gchar *udi) {
199 for (i = 0; i < MAX_DEVICES; i++) {
200 MTetherDDevice *device = MTETHERD_DEVICE(array[i]);
201 if (device && device->priv) {
202 if (g_strcmp0(device->priv->udi, udi) == 0) {
210 gpointer mtetherd_device_list_new() {
211 return g_malloc0(sizeof(gpointer) * MAX_DEVICES);
214 void mtetherd_device_list_free(gpointer list) {
216 gpointer *array = (gpointer *) list;
219 for (i = 0; i < MAX_DEVICES; i++) {
221 g_object_unref(G_OBJECT(array[i]));
228 MTetherDDevice *mtetherd_device_list_find(gpointer list, const gchar *udi) {
230 gpointer *array = (gpointer *) list;
232 gint index = mtetherd_device_list_find_index(array, udi);
240 gboolean mtetherd_device_list_add(gpointer list, MTetherDDevice *device) {
242 gpointer *array = (gpointer *) list;
245 for (i = 0; i < MAX_DEVICES; i++) {
247 array[i] = (gpointer) device;
255 gboolean mtetherd_device_list_remove(gpointer list, const gchar *udi) {
257 gpointer *array = (gpointer *) list;
259 gint index = mtetherd_device_list_find_index(array, udi);
261 g_object_unref(G_OBJECT(array[index]));
269 gboolean mtetherd_device_ok(const gchar *interface) {
270 if (strncmp("usb", interface, sizeof("usb")) == 0) {
273 if (strncmp("bnep", interface, sizeof("bnep")) == 0) {