along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <string.h>
#include <netinet/in.h>
#include "net.h"
-#define MTETHERD_DEVICE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), MTETHERD_DEVICE_TYPE_BAR, MTetherDDevicePrivate))
+#define MTETHERD_DEVICE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_MTETHERD_DEVICE, MTetherDDevicePrivate))
+
+G_DEFINE_TYPE(MTetherDDevice, mtetherd_device, G_TYPE_OBJECT);
+
+// Host order 192.168.255.0
+static const in_addr_t HOST_BASE_ADDRESS = 0xc0a8ff00;
+// Host order 255.255.255.252
+static const in_addr_t HOST_NETMASK = 0xfffffffc;
+// Host order 0.0.0.2
+static const in_addr_t HOST_ROUTER = 0x00000002;
+// Host order 0.0.0.1
+static const in_addr_t HOST_DHCP = 0x00000001;
struct _MTetherDDevicePrivate {
- char *interface;
- char *udi;
- struct in_addr addr;
- struct in_addr netmask;
- struct in_addr dhcp_start;
- struct in_addr dhcp_end;
+ gchar *interface;
+ gchar *udi;
+ // Network order
+ in_addr_t addr;
+ in_addr_t netmask;
+ in_addr_t dhcp_start;
+ in_addr_t dhcp_end;
};
-static void mtetherd_device_bar_finalize(MTetherDDevice *self) {
- self->priv = MTETHERD_DEVICE_GET_PRIVATE(self);
+static void mtetherd_device_finalize(GObject *object) {
+ MTetherDDevice *self = MTETHERD_DEVICE(object);
+
+ if (self && self->priv) {
+ g_free(self->priv->interface);
+ g_free(self->priv->udi);
+ }
}
static void mtetherd_device_class_init(MTetherDDeviceClass *klass) {
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
- gobject_class->finalize = mtetherd_device_bar_finalize;
+ gobject_class->finalize = mtetherd_device_finalize;
g_type_class_add_private(klass, sizeof(MTetherDDevicePrivate));
}
-static void mtetherd_device_bar_init(MTetherDDevice *self) {
+static void mtetherd_device_init(MTetherDDevice *self) {
self->priv = MTETHERD_DEVICE_GET_PRIVATE(self);
+ if (self->priv) {
+ self->priv->interface = NULL;
+ self->priv->udi = NULL;
+ self->priv->addr = 0;
+ self->priv->netmask = 0;
+ self->priv->dhcp_start = 0;
+ self->priv->dhcp_end = 0;
+ }
+}
+
+static void mtetherd_device_set_interface(MTetherDDevice *self, const gchar *interface) {
+ if (self) {
+ if (self->priv->interface) {
+ g_free(self->priv->interface);
+ }
+ if (interface) {
+ size_t len = strlen(interface);
+ self->priv->interface = g_malloc(len + 1);
+ size_t i, j;
+ for (i = 0, j = 0; i < len; i++) {
+ if (g_ascii_isalnum(interface[i])) {
+ self->priv->interface[j] = interface[i];
+ j++;
+ }
+ }
+ self->priv->interface[j] = '\0';
+ }
+ }
+}
+
+static void mtetherd_device_set_udi(MTetherDDevice *self, const gchar *udi) {
+ if (self) {
+ if (self->priv->udi) {
+ g_free(self->priv->udi);
+ }
+ if (udi) {
+ size_t len = strlen(udi);
+ self->priv->udi = g_malloc(len + 1);
+ size_t i, j;
+ for (i = 0, j = 0; i < len; i++) {
+ if (g_ascii_isalnum(udi[i]) || g_ascii_ispunct(udi[i])) {
+ self->priv->udi[j] = udi[i];
+ j++;
+ }
+ }
+ self->priv->udi[j] = '\0';
+ }
+ }
+}
+
+static void mtetherd_device_set_index(MTetherDDevice *self, guint index) {
+ if (self && self->priv) {
+ // Maximum is 63, we need four addresses per subnet
+ if (index < 64) {
+ in_addr_t subnet = HOST_BASE_ADDRESS | (index << 2);
+ in_addr_t addr = subnet | HOST_ROUTER;
+ in_addr_t start = subnet | HOST_DHCP;
+ self->priv->addr = htonl(addr);
+ self->priv->netmask = htonl(HOST_NETMASK);
+ self->priv->dhcp_start = htonl(start);
+ self->priv->dhcp_end = htonl(addr);
+ } else {
+ g_warning("Invalid subnet index: %u (0..63 expected)", index);
+ }
+ }
+}
+
+MTetherDDevice *mtetherd_device_new(const gchar *interface, const gchar *udi, guint index) {
+ MTetherDDevice *self = MTETHERD_DEVICE(g_object_new(TYPE_MTETHERD_DEVICE, NULL));
+
+ if (self && self->priv) {
+ mtetherd_device_set_interface(self, interface);
+ mtetherd_device_set_udi(self, udi);
+ mtetherd_device_set_index(self, index);
+ }
+
+ return self;
+}
+
+static gint mtetherd_device_find_udi(gconstpointer a, gconstpointer b) {
+ const MTetherDDevice *self = MTETHERD_DEVICE(a);
+ const gchar *udi = (const gchar *) b;
+ if (self && udi) {
+ if (g_strcmp0(self->priv->udi, udi) == 0) {
+ return 0;
+ }
+ }
+ return -1;
+}
+
+MTetherDDevice *mtetherd_device_find(GList *list, const gchar *udi) {
+ GList *entry = g_list_find_custom(list, udi, mtetherd_device_find_udi);
+ if (entry) {
+ return MTETHERD_DEVICE(entry->data);
+ }
+ return NULL;
}