Network probing connected with the packet assembly module.
authorshort <>
Thu, 20 May 2004 07:54:46 +0000 (07:54 +0000)
committershort <>
Thu, 20 May 2004 07:54:46 +0000 (07:54 +0000)
src/main.h
src/network.c
src/network.h
src/packet.c
src/packet.h

index e69de29..acc6e0a 100644 (file)
@@ -0,0 +1,32 @@
+/* $Id$
+ * Include file for UDP Gateway utility
+ * Copyright (C) 2004 Jan Kratochvil <project-udpgate@jankratochvil.net>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; exactly version 2 of June 1991 is required
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _UDPGATE_MAIN_H
+#define _UDPGATE_MAIN_H 1
+
+
+#include <glib/gtypes.h>
+
+
+G_BEGIN_DECLS
+
+G_END_DECLS
+
+
+#endif /* _UDPGATE_MAIN_H */
index c4dbfeb..e39dfc1 100644 (file)
 #include <string.h>
 #include <glib/galloca.h>
 #include <glib/gprintf.h>
+#include <glib/grand.h>
 
 #include "network.h"
+#include "packet.h"
 
 
 /* Config: */
@@ -50,6 +52,9 @@
 #define PROBE_TIMEOUT_SEC (5)
 
 
+void (*network_notify_hostip)(guint32 hostip_guint32,const gchar *hostip_string);
+
+
 struct client {
        GPollFD gpollfd;
        struct sockaddr_in sockaddr_in_from;
@@ -59,8 +64,9 @@ struct client {
 static GSource *sock_gsource;
 
 static GList *sock_client_list;        /* of 'struct client *', incl. 'master' and 'probe' */
-struct client *master; /* no 'timeout' permitted */
-struct client *probe;  /* 'timeout' permitted */
+static struct client *master;  /* no 'timeout' permitted */
+static struct client *probe;   /* 'timeout' permitted */
+static guint32 probe_unique;
 
 static gboolean write_daemon_running(pid_t pid);
 
@@ -151,6 +157,12 @@ static gboolean client_touch_timeout(struct client *client)
        g_return_val_if_fail(client!=NULL,FALSE);       /* FALSE=>should be removed */
        g_return_val_if_fail(client!=master,FALSE);     /* FALSE=>should be removed */
 
+       if (client==probe) {
+               network_stop();
+               if (network_notify_hostip)
+                       (*network_notify_hostip)(0,NULL);
+               }
+
        client_destroy(client);
 
        return FALSE;   /* GSource should be removed */
@@ -165,21 +177,21 @@ struct sockaddr_in sockaddr_in_from;
 char packet[0x10000];
 struct client *client;
 struct sockaddr_in sockaddr_in_server;
-socklen_t sockaddr_in_from_len;
+socklen_t sockaddr_in_from_length;
 
        g_return_if_fail(master!=NULL);
 
-       sockaddr_in_from_len=sizeof(sockaddr_in_from);
+       sockaddr_in_from_length=sizeof(sockaddr_in_from);
        while (-1!=(gotlen=recvfrom(
                        master->gpollfd.fd,     /* s */
                        packet, /* buf */
                        sizeof(packet), /* len */
                        0,      /* flags */
                        (struct sockaddr *)&sockaddr_in_from,   /* from */
-                       &sockaddr_in_from_len))) {      /* fromlen */
+                       &sockaddr_in_from_length))) {   /* fromlen */
 GList *clientl;
 
-               if (sockaddr_in_from_len!=sizeof(sockaddr_in_from))     /* FIXME: errors reporting */
+               if (sockaddr_in_from_length!=sizeof(sockaddr_in_from))  /* FIXME: errors reporting */
                        continue;
                /* FIXME: Performance: Ugly search... */
                for (clientl=sock_client_list;clientl;clientl=clientl->next) {
@@ -217,21 +229,55 @@ static void handle_probe(struct client *probe)
 ssize_t gotlen;
 struct sockaddr_in sockaddr_in_from;
 char packet[0x10000];
-socklen_t sockaddr_in_from_len;
+socklen_t sockaddr_in_from_length;
 
        g_return_if_fail(probe!=NULL);
 
-       sockaddr_in_from_len=sizeof(sockaddr_in_from);
+       sockaddr_in_from_length=sizeof(sockaddr_in_from);
        while (-1!=(gotlen=recvfrom(
                        master->gpollfd.fd,     /* s */
                        packet, /* buf */
                        sizeof(packet), /* len */
                        0,      /* flags */
                        (struct sockaddr *)&sockaddr_in_from,   /* from */
-                       &sockaddr_in_from_len))) {      /* fromlen */
+                       &sockaddr_in_from_length))) {   /* fromlen */
+static GHashTable *got_hash;
+static gpointer got_unique_gpointer;
+static gpointer hostip_gpointer;
+static guint32 hostip_guint32;
 
-               if (sockaddr_in_from_len!=sizeof(sockaddr_in_from))     /* FIXME: errors reporting */
+               if (sockaddr_in_from_length!=sizeof(sockaddr_in_from))  /* FIXME: errors reporting */
+                       continue;
+               if (!(got_hash=packet_disassembly(packet,gotlen)))
+                       continue;
+               if (!(g_hash_table_lookup_extended(
+                               got_hash,       /* hash_table */
+                               GUINT_TO_POINTER(PACKET_ELEM_TYPE_DATA_GUINT32),        /* lookup_key */
+                               NULL,   /* orig_key */
+                               &got_unique_gpointer))) {
+err_packet_disassembly_destroy_got_hash:
+                       packet_disassembly_destroy(got_hash);
                        continue;
+                       }
+               if (GPOINTER_TO_UINT(got_unique_gpointer)!=probe_unique)
+                       goto err_packet_disassembly_destroy_got_hash;
+               if (!(g_hash_table_lookup_extended(
+                               got_hash,       /* hash_table */
+                               GUINT_TO_POINTER(PACKET_ELEM_TYPE_CLIENT_INADDR),       /* lookup_key */
+                               NULL,   /* orig_key */
+                               &hostip_gpointer)))
+                       goto err_packet_disassembly_destroy_got_hash;
+               hostip_guint32=GPOINTER_TO_UINT(hostip_gpointer);
+               packet_disassembly_destroy(got_hash);
+
+               client_destroy(probe);
+               if (network_notify_hostip)
+                       (*network_notify_hostip)(hostip_guint32,
+                                       udpgate_printf_alloca("%d.%d.%d.%d",
+                                                       (hostip_guint32>>24U)&0xFFU,
+                                                       (hostip_guint32>>16U)&0xFFU,
+                                                       (hostip_guint32>> 8U)&0xFFU,
+                                                       (hostip_guint32>> 0U)&0xFFU));
                }
 }
 
@@ -240,7 +286,7 @@ static void handle_client(struct client *client)
 ssize_t gotlen;
 struct sockaddr_in sockaddr_in_from;
 char packet [0x10000];
-socklen_t sockaddr_in_from_len;
+socklen_t sockaddr_in_from_length;
 
        g_return_if_fail(client!=NULL);
        g_return_if_fail(master!=NULL);
@@ -251,8 +297,8 @@ socklen_t sockaddr_in_from_len;
                        sizeof(packet), /* len */
                        0,      /* flags */
                        (struct sockaddr *)&sockaddr_in_from,   /* from */
-                       &sockaddr_in_from_len))) {      /* fromlen */
-               if (sockaddr_in_from_len!=sizeof(sockaddr_in_from))     /* FIXME: errors reporting */
+                       &sockaddr_in_from_length))) {   /* fromlen */
+               if (sockaddr_in_from_length!=sizeof(sockaddr_in_from))  /* FIXME: errors reporting */
                        continue;
                client_touch(client);
                /* FIXME: errors checking */
@@ -404,8 +450,11 @@ static void client_destroy(struct client *client)
                master=NULL;
                g_assert(client->timeout_id==0);
                }
-       else
+       else {
+               if (client==probe)
+                       probe=NULL;
                client_timeout_remove(client);
+               }
 
        g_source_remove_poll(sock_gsource,&client->gpollfd);
        sock_client_list=g_list_remove(sock_client_list,client);
@@ -413,31 +462,43 @@ static void client_destroy(struct client *client)
        g_free(client);
 }
 
-static gboolean probe_send(struct client *probe)
+static gboolean probe_send(struct client *probe,gint port_local)
 {
 struct sockaddr_in sockaddr_in_server;
+GHashTable *probe_hash;
+gpointer packet;
+size_t packet_length;
 
        g_return_val_if_fail(probe!=NULL,FALSE);
 
+       probe_unique=g_random_int();
+
+       probe_hash=g_hash_table_new(
+                       g_int_hash,     /* hash_func */
+                       g_int_equal);   /* key_equal_func */
+       g_hash_table_insert(probe_hash,GUINT_TO_POINTER(PACKET_ELEM_TYPE_CLIENT_PORT) ,GUINT_TO_POINTER(port_local));
+       g_hash_table_insert(probe_hash,GUINT_TO_POINTER(PACKET_ELEM_TYPE_DATA_GUINT32),GUINT_TO_POINTER(probe_unique));
+       packet=packet_assembly(&packet_length,probe_hash);
+       g_hash_table_destroy(probe_hash);
+       if (!packet)
+               return FALSE;
+
        UDPGATE_MEMZERO(&sockaddr_in_server);
        sockaddr_in_server.sin_family=AF_INET;
        sockaddr_in_server.sin_port=htons(PROBE_PORT);
        sockaddr_in_server.sin_addr.s_addr=htonl(PROBE_INADDR);
        /* FIXME: errors checking */
-#if 0
        sendto(
                        probe->gpollfd.fd,      /* s */
                        packet, /* msg */
-                       gotlen, /* len */
+                       packet_length,  /* len */
                        0,      /* flags */
                        (struct sockaddr *)&sockaddr_in_server, /* to */
                        sizeof(sockaddr_in_server));    /* tolen */
-#endif
 
        return TRUE;
 }
 
-
 gboolean network_start(gint port)
 {
 pid_t daemon_pid;
@@ -468,7 +529,7 @@ err_sock_gsource_destroy:
        /* Setup 'probe': */
        if (!(probe=client_new()))
                goto err_sock_gsource_destroy;
-       probe_send(probe);
+       probe_send(probe,port);
        client_touch(probe);    /* timeout */
 
        write_daemon_running(getpid());
index 9d621fc..05f5cb6 100644 (file)
@@ -31,6 +31,7 @@ G_BEGIN_DECLS
 pid_t is_daemon_running(void);
 gboolean network_start(gint port);
 gboolean network_stop(void);
+void (*network_notify_hostip)(guint32 hostip_guint32,const gchar *hostip_string);
 
 G_END_DECLS
 
index 2f38371..82dbecb 100644 (file)
@@ -76,7 +76,7 @@ static void packet_assembly_data_string(GString *gstring,const gchar *string)
 {
 size_t string_length;
 #ifndef G_DISABLE_ASSERT
-size_t gstring_len_orig;
+size_t gstring_length_orig;
 #endif /* !G_DISABLE_ASSERT */
 
        g_return_if_fail(gstring!=NULL);
@@ -85,11 +85,11 @@ size_t gstring_len_orig;
        string_length=strlen(string);
        packet_assembly_guint32(gstring,string_length);
 #ifndef G_DISABLE_ASSERT
-       gstring_len_orig=gstring->len;
+       gstring_length_orig=gstring->len;
 #endif /* !G_DISABLE_ASSERT */
        g_string_append(gstring,string);
 #ifndef G_DISABLE_ASSERT
-       g_assert(gstring_len_orig+string_length==gstring->len);
+       g_assert(gstring_length_orig+string_length==gstring->len);
 #endif /* !G_DISABLE_ASSERT */
 }
 
@@ -118,11 +118,11 @@ guint32 elem_type_uint32;
                }
 }
 
-void *packet_assembly(size_t *packet_len_pointer,GHashTable *values)
+void *packet_assembly(size_t *packet_length_pointer,GHashTable *values)
 {
 GString *gstring;
 
-       g_return_val_if_fail(packet_len_pointer!=NULL,NULL);
+       g_return_val_if_fail(packet_length_pointer!=NULL,NULL);
        g_return_val_if_fail(values!=NULL,NULL);
 
        gstring=g_string_new(NULL);
@@ -135,7 +135,7 @@ GString *gstring;
                        (GHFunc)packet_assembly_foreach,        /* func */
                        gstring);       /* user_data */
 
-       *packet_len_pointer=gstring->len;
+       *packet_length_pointer=gstring->len;
        return g_string_free(gstring,
                        FALSE); /* free_segment */
 }
@@ -260,7 +260,7 @@ guint16 value_guint16;
        return TRUE;
 }
 
-GHashTable *packet_disassembly(gconstpointer packet,size_t packet_len)
+GHashTable *packet_disassembly(gconstpointer packet,size_t packet_length)
 {
 GHashTable *r;
 gconstpointer packet_end;
@@ -273,7 +273,7 @@ GSList *items;
                        g_int_equal,    /* key_equal_func */
                        NULL,   /* key_destroy_func */
                        packet_disassembly_value_destroy_func); /* value_destroy_func */
-       packet_end=packet+packet_len;
+       packet_end=packet+packet_length;
 
        if (packet+strlen(PACKET_HEADER)>packet_end) {
 err_g_hash_table_destroy_r:
index bb7f564..a5726db 100644 (file)
@@ -38,8 +38,8 @@ enum packet_elem_type {
        PACKET_ELEM_TYPE_DATA_GUINT32   =(0x04|PACKET_ELEM_ATTR_MANDATORY),     /* user data (e.g. unique id) */
        };
 
-gpointer packet_assembly(size_t *packet_len_pointer,GHashTable *values);
-GHashTable *packet_disassembly(gconstpointer packet,size_t packet_len);
+gpointer packet_assembly(size_t *packet_length_pointer,GHashTable *values);
+GHashTable *packet_disassembly(gconstpointer packet,size_t packet_length);
 void packet_disassembly_destroy(GHashTable *hash);
 
 G_END_DECLS