Implemented network device class
[mtetherd] / net.c
1 /*
2   mtetherd
3   (c) 2010 Gregor Riepl <onitake@gmail.com>
4   
5   Tethering utility for Maemo
6   
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.
11   
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.
16   
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/>.
19 */
20
21 #include <string.h>
22 #include <netinet/in.h>
23 #include "net.h"
24
25 #define MTETHERD_DEVICE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_MTETHERD_DEVICE, MTetherDDevicePrivate))
26
27 G_DEFINE_TYPE(MTetherDDevice, mtetherd_device, G_TYPE_OBJECT);
28
29 // Host order 192.168.255.0
30 static const in_addr_t HOST_BASE_ADDRESS = 0xc0a8ff00;
31 // Host order 255.255.255.252
32 static const in_addr_t HOST_NETMASK = 0xfffffffc;
33 // Host order 0.0.0.2
34 static const in_addr_t HOST_ROUTER = 0x00000002;
35 // Host order 0.0.0.1
36 static const in_addr_t HOST_DHCP = 0x00000001;
37
38 struct _MTetherDDevicePrivate {
39         gchar *interface;
40         gchar *udi;
41         // Network order
42         in_addr_t addr;
43         in_addr_t netmask;
44         in_addr_t dhcp_start;
45         in_addr_t dhcp_end;
46 };
47
48 static void mtetherd_device_finalize(GObject *object) {
49         MTetherDDevice *self = MTETHERD_DEVICE(object);
50
51         if (self && self->priv) {
52                 g_free(self->priv->interface);
53                 g_free(self->priv->udi);
54         }
55 }
56
57 static void mtetherd_device_class_init(MTetherDDeviceClass *klass) {
58         GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
59
60         gobject_class->finalize = mtetherd_device_finalize;
61         g_type_class_add_private(klass, sizeof(MTetherDDevicePrivate));
62 }
63
64 static void mtetherd_device_init(MTetherDDevice *self) {
65         self->priv = MTETHERD_DEVICE_GET_PRIVATE(self);
66         
67         if (self->priv) {
68                 self->priv->interface = NULL;
69                 self->priv->udi = NULL;
70                 self->priv->addr = 0;
71                 self->priv->netmask = 0;
72                 self->priv->dhcp_start = 0;
73                 self->priv->dhcp_end = 0;
74         }
75 }
76
77 static void mtetherd_device_set_interface(MTetherDDevice *self, const gchar *interface) {
78         if (self) {
79                 if (self->priv->interface) {
80                         g_free(self->priv->interface);
81                 }
82                 if (interface) {
83                         size_t len = strlen(interface);
84                         self->priv->interface = g_malloc(len + 1);
85                         size_t i, j;
86                         for (i = 0, j = 0; i < len; i++) {
87                                 if (g_ascii_isalnum(interface[i])) {
88                                         self->priv->interface[j] = interface[i];
89                                         j++;
90                                 }
91                         }
92                         self->priv->interface[j] = '\0';
93                 }
94         }
95 }
96
97 static void mtetherd_device_set_udi(MTetherDDevice *self, const gchar *udi) {
98         if (self) {
99                 if (self->priv->udi) {
100                         g_free(self->priv->udi);
101                 }
102                 if (udi) {
103                         size_t len = strlen(udi);
104                         self->priv->udi = g_malloc(len + 1);
105                         size_t i, j;
106                         for (i = 0, j = 0; i < len; i++) {
107                                 if (g_ascii_isalnum(udi[i]) || g_ascii_ispunct(udi[i])) {
108                                         self->priv->udi[j] = udi[i];
109                                         j++;
110                                 }
111                         }
112                         self->priv->udi[j] = '\0';
113                 }
114         }
115 }
116
117 static void mtetherd_device_set_index(MTetherDDevice *self, guint index) {
118         if (self && self->priv) {
119                 // Maximum is 63, we need four addresses per subnet
120                 if (index < 64) {
121                         in_addr_t subnet = HOST_BASE_ADDRESS | (index << 2);
122                         in_addr_t addr = subnet | HOST_ROUTER;
123                         in_addr_t start = subnet | HOST_DHCP;
124                         self->priv->addr = htonl(addr);
125                         self->priv->netmask = htonl(HOST_NETMASK);
126                         self->priv->dhcp_start = htonl(start);
127                         self->priv->dhcp_end = htonl(addr);
128                 } else {
129                         g_warning("Invalid subnet index: %u (0..63 expected)", index);
130                 }
131         }
132 }
133
134 MTetherDDevice *mtetherd_device_new(const gchar *interface, const gchar *udi, guint index) {
135         MTetherDDevice *self = MTETHERD_DEVICE(g_object_new(TYPE_MTETHERD_DEVICE, NULL));
136
137         if (self && self->priv) {
138                 mtetherd_device_set_interface(self, interface);
139                 mtetherd_device_set_udi(self, udi);
140                 mtetherd_device_set_index(self, index);
141         }
142         
143         return self;
144 }
145
146 static gint mtetherd_device_find_udi(gconstpointer a, gconstpointer b) {
147         const MTetherDDevice *self = MTETHERD_DEVICE(a);
148         const gchar *udi = (const gchar *) b;
149         
150         if (self && udi) {
151                 if (g_strcmp0(self->priv->udi, udi) == 0) {
152                         return 0;
153                 }
154         }
155         return -1;
156 }
157
158 MTetherDDevice *mtetherd_device_find(GList *list, const gchar *udi) {
159         GList *entry = g_list_find_custom(list, udi, mtetherd_device_find_udi);
160         if (entry) {
161                 return MTETHERD_DEVICE(entry->data);
162         }
163         return NULL;
164 }
165