add code for recieving packets
authorLennart Poettering <lennart@poettering.net>
Thu, 17 Mar 2005 15:34:46 +0000 (15:34 +0000)
committerLennart Poettering <lennart@poettering.net>
Thu, 17 Mar 2005 15:34:46 +0000 (15:34 +0000)
git-svn-id: file:///home/lennart/svn/public/avahi/trunk@11 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe

main.c
netlink.c
server.c
server.h
socket.c
socket.h

diff --git a/main.c b/main.c
index b366eb5..75d03ac 100644 (file)
--- a/main.c
+++ b/main.c
@@ -5,15 +5,25 @@
 #include "flx.h"
 #include "server.h"
 
-static gboolean timeout(gpointer data) {
+static gboolean quit_timeout(gpointer data) {
     g_main_loop_quit(data);
     return FALSE;
 }
 
+static gboolean send_timeout(gpointer data) {
+    flxServer *flx = data;
+    flxKey *k;
+
+    k = flx_key_new("cocaine.local.", FLX_DNS_CLASS_IN, FLX_DNS_TYPE_A);
+    flx_server_send_query(flx, 0, AF_UNSPEC, k);
+    flx_key_unref(k);
+
+    return FALSE;
+}
+
 int main(int argc, char *argv[]) {
     flxServer *flx;
     gchar *r;
-    flxKey *k;
     GMainLoop *loop = NULL;
 
     flx = flx_server_new(NULL);
@@ -22,14 +32,11 @@ int main(int argc, char *argv[]) {
 
     loop = g_main_loop_new(NULL, FALSE);
     
-    g_timeout_add(1000, timeout, loop);
+    g_timeout_add(1000*5, quit_timeout, loop);
+    g_timeout_add(1000, send_timeout, flx);
     
     g_main_loop_run(loop);
 
-    k = flx_key_new("cocaine.local.", FLX_DNS_CLASS_IN, FLX_DNS_TYPE_A);
-    flx_server_send_query(flx, 0, AF_UNSPEC, k);
-    flx_key_unref(k);
-
     g_main_loop_unref(loop);
 
     flx_server_dump(flx, stdout);
index 3bc7d01..92eb44e 100644 (file)
--- a/netlink.c
+++ b/netlink.c
@@ -60,7 +60,7 @@ static gboolean check_func(GSource *source) {
     nl = *((flxNetlink**) (((guint8*) source) + sizeof(GSource)));
     g_assert(nl);
     
-    return nl->poll_fd.revents & G_IO_IN;
+    return nl->poll_fd.revents & (G_IO_IN|G_IO_HUP|G_IO_ERR);
 }
 
 static gboolean dispatch_func(GSource *source, GSourceFunc callback, gpointer user_data) {
index f85de45..baac24c 100644 (file)
--- a/server.c
+++ b/server.c
@@ -9,6 +9,85 @@
 #include "iface.h"
 #include "socket.h"
 
+static void dispatch_packet(flxServer *s, flxDnsPacket *p, struct sockaddr *sa, gint iface, gint ttl) {
+    g_assert(s);
+    g_assert(p);
+    g_assert(sa);
+    g_assert(iface > 0);
+    
+    if (ttl != 255) {
+        flxInterface *i = flx_interface_monitor_get_interface(s->monitor, iface);
+        g_warning("Recieved packet with invalid TTL on interface '%s'.", i ? i->name : "unknown");
+        return;
+    }
+
+    if (sa->sa_family == AF_INET6) {
+        static const unsigned char ipv4_in_ipv6[] = {
+            0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00,
+            0xFF, 0xFF, 0xFF, 0xFF };
+
+        if (memcmp(((struct sockaddr_in6*) sa)->sin6_addr.s6_addr, ipv4_in_ipv6, sizeof(ipv4_in_ipv6)) == 0) {
+
+            /* This is an IPv4 address encapsulated in IPv6, so let's ignore it. */
+            return;
+        }
+    }
+
+    g_message("Recieved packet");
+
+}
+
+static gboolean work(flxServer *s) {
+    struct sockaddr_in6 sa6;
+    struct sockaddr_in sa;
+    flxDnsPacket *p;
+    gint iface = -1;
+    guint8 ttl;
+        
+    g_assert(s);
+
+    if (s->pollfd_ipv4.revents & G_IO_IN) {
+        if ((p = flx_recv_dns_packet_ipv4(s->fd_ipv4, &sa, &iface, &ttl)))
+            dispatch_packet(s, p, (struct sockaddr*) &sa, iface, ttl);
+    }
+
+    if (s->pollfd_ipv6.revents & G_IO_IN) {
+        if ((p = flx_recv_dns_packet_ipv6(s->fd_ipv6, &sa6, &iface, &ttl)))
+            dispatch_packet(s, p, (struct sockaddr*) &sa6, iface, ttl);
+    }
+
+    return TRUE;
+}
+
+static gboolean prepare_func(GSource *source, gint *timeout) {
+    g_assert(source);
+    g_assert(timeout);
+    
+    *timeout = -1;
+    return FALSE;
+}
+
+static gboolean check_func(GSource *source) {
+    flxServer* s;
+    g_assert(source);
+
+    s = *((flxServer**) (((guint8*) source) + sizeof(GSource)));
+    g_assert(s);
+    
+    return (s->pollfd_ipv4.revents | s->pollfd_ipv6.revents) & (G_IO_IN | G_IO_HUP | G_IO_ERR);
+}
+
+static gboolean dispatch_func(GSource *source, GSourceFunc callback, gpointer user_data) {
+    flxServer* s;
+    g_assert(source);
+
+    s = *((flxServer**) (((guint8*) source) + sizeof(GSource)));
+    g_assert(s);
+    
+    return work(s);
+}
+
 static void add_default_entries(flxServer *s) {
     gint length = 0;
     struct utsname utsname;
@@ -37,6 +116,15 @@ static void add_default_entries(flxServer *s) {
 flxServer *flx_server_new(GMainContext *c) {
     gchar *hn, *e;
     flxServer *s;
+    
+    static GSourceFuncs source_funcs = {
+        prepare_func,
+        check_func,
+        dispatch_func,
+        NULL,
+        NULL,
+        NULL
+    };
 
     s = g_new(flxServer, 1);
 
@@ -78,6 +166,21 @@ flxServer *flx_server_new(GMainContext *c) {
 
     add_default_entries(s);
 
+    s->source = g_source_new(&source_funcs, sizeof(GSource) + sizeof(flxServer*));
+    *((flxServer**) (((guint8*) s->source) + sizeof(GSource))) = s;
+
+    memset(&s->pollfd_ipv4, 0, sizeof(s->pollfd_ipv4));
+    s->pollfd_ipv4.fd = s->fd_ipv4;
+    s->pollfd_ipv4.events = G_IO_IN|G_IO_ERR|G_IO_HUP;
+    g_source_add_poll(s->source, &s->pollfd_ipv4);
+    
+    memset(&s->pollfd_ipv6, 0, sizeof(s->pollfd_ipv6));
+    s->pollfd_ipv6.fd = s->fd_ipv6;
+    s->pollfd_ipv6.events = G_IO_IN|G_IO_ERR|G_IO_HUP;
+    g_source_add_poll(s->source, &s->pollfd_ipv6);
+
+    g_source_attach(s->source, s->context);
+    
     return s;
 }
 
@@ -92,7 +195,6 @@ void flx_server_free(flxServer* s) {
     g_hash_table_destroy(s->rrset_by_name);
 
     flx_time_event_queue_free(s->time_event_queue);
-    g_main_context_unref(s->context);
 
     if (s->fd_ipv4 >= 0)
         close(s->fd_ipv4);
@@ -100,6 +202,11 @@ void flx_server_free(flxServer* s) {
         close(s->fd_ipv6);
     
     g_free(s->hostname);
+
+    g_source_destroy(s->source);
+    g_source_unref(s->source);
+    g_main_context_unref(s->context);
+
     g_free(s);
 }
 
index b1cc57b..4566926 100644 (file)
--- a/server.h
+++ b/server.h
@@ -45,6 +45,9 @@ struct _flxServer {
     gchar *hostname;
 
     gint fd_ipv4, fd_ipv6;
+
+    GPollFD pollfd_ipv4, pollfd_ipv6;
+    GSource *source;
 };
 
 
index a77f631..48cfb36 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -29,7 +29,7 @@ static void mdns_mcast_group_ipv4(struct sockaddr_in *ret_sa) {
 gint flx_open_socket_ipv4(void) {
     struct ip_mreqn mreq;
     struct sockaddr_in sa, local;
-    int fd = -1, ttl, yes;
+    int fd = -1, ttl, yes, no;
 
     mdns_mcast_group_ipv4(&sa);
         
@@ -39,13 +39,13 @@ gint flx_open_socket_ipv4(void) {
     }
     
     ttl = 255;
-    if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) {
+    if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) {
         g_warning("IP_MULTICAST_TTL failed: %s\n", strerror(errno));
         goto fail;
     }
 
     ttl = 255;
-    if (setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) < 0) {
+    if (setsockopt(fd, SOL_IP, IP_TTL, &ttl, sizeof(ttl)) < 0) {
         g_warning("IP_TTL failed: %s\n", strerror(errno));
         goto fail;
     }
@@ -56,6 +56,13 @@ gint flx_open_socket_ipv4(void) {
         goto fail;
     }
 
+    no = 0;
+    if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &no, sizeof(no)) < 0) {
+        g_warning("IP_MULTICAST_LOOP failed: %s\n", strerror(errno));
+        goto fail;
+    }
+
+    
     memset(&local, 0, sizeof(local));
     local.sin_family = AF_INET;
     local.sin_port = htons(MDNS_PORT);
@@ -70,19 +77,19 @@ gint flx_open_socket_ipv4(void) {
     mreq.imr_address.s_addr = htonl(INADDR_ANY);
     mreq.imr_ifindex = 0;
     
-    if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
+    if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
         g_warning("IP_ADD_MEMBERSHIP failed: %s\n", strerror(errno));
         goto fail;
     }
 
     yes = 1;
-    if (setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &yes, sizeof(yes)) < 0) {
+    if (setsockopt(fd, SOL_IP, IP_RECVTTL, &yes, sizeof(yes)) < 0) {
         g_warning("IP_RECVTTL failed: %s\n", strerror(errno));
         goto fail;
     }
 
     yes = 1;
-    if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0) {
+    if (setsockopt(fd, SOL_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0) {
         g_warning("IP_PKTINFO failed: %s\n", strerror(errno));
         goto fail;
     }
@@ -120,7 +127,7 @@ static void mdns_mcast_group_ipv6(struct sockaddr_in6 *ret_sa) {
 gint flx_open_socket_ipv6(void) {
     struct ipv6_mreq mreq;
     struct sockaddr_in6 sa, local;
-    int fd = -1, ttl, yes;
+    int fd = -1, ttl, yes, no;
 
     mdns_mcast_group_ipv6(&sa);
         
@@ -130,13 +137,13 @@ gint flx_open_socket_ipv6(void) {
     }
     
     ttl = 255;
-    if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) < 0) {
+    if (setsockopt(fd, SOL_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) < 0) {
         g_warning("IPV6_MULTICAST_HOPS failed: %s\n", strerror(errno));
         goto fail;
     }
 
     ttl = 255;
-    if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)) < 0) {
+    if (setsockopt(fd, SOL_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)) < 0) {
         g_warning("IPV6_UNICAST_HOPS failed: %s\n", strerror(errno));
         goto fail;
     }
@@ -147,6 +154,18 @@ gint flx_open_socket_ipv6(void) {
         goto fail;
     }
 
+    yes = 1;
+    if (setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, &yes, sizeof(yes)) < 0) {
+        g_warning("IPV6_V6ONLY failed: %s\n", strerror(errno));
+        goto fail;
+    }
+
+    no = 0;
+    if (setsockopt(fd, SOL_IPV6, IPV6_MULTICAST_LOOP, &no, sizeof(no)) < 0) {
+        g_warning("IPV6_MULTICAST_LOOP failed: %s\n", strerror(errno));
+        goto fail;
+    }
+
     memset(&local, 0, sizeof(local));
     local.sin6_family = AF_INET6;
     local.sin6_port = htons(MDNS_PORT);
@@ -160,19 +179,19 @@ gint flx_open_socket_ipv6(void) {
     mreq.ipv6mr_multiaddr = sa.sin6_addr;
     mreq.ipv6mr_interface = 0;
     
-    if (setsockopt(fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
+    if (setsockopt(fd, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
         g_warning("IPV6_ADD_MEMBERSHIP failed: %s\n", strerror(errno));
         goto fail;
     }
 
     yes = 1;
-    if (setsockopt(fd, IPPROTO_IPV6, IPV6_HOPLIMIT, &yes, sizeof(yes)) < 0) {
+    if (setsockopt(fd, SOL_IPV6, IPV6_HOPLIMIT, &yes, sizeof(yes)) < 0) {
         g_warning("IPV6_HOPLIMIT failed: %s\n", strerror(errno));
         goto fail;
     }
 
     yes = 1;
-    if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &yes, sizeof(yes)) < 0) {
+    if (setsockopt(fd, SOL_IPV6, IPV6_PKTINFO, &yes, sizeof(yes)) < 0) {
         g_warning("IPV6_PKTINFO failed: %s\n", strerror(errno));
         goto fail;
     }
@@ -344,7 +363,8 @@ flxDnsPacket* flx_recv_dns_packet_ipv4(gint fd, struct sockaddr_in *ret_sa, gint
         }
     }
 
-    g_assert(found_iface && found_ttl);
+    g_assert(found_iface);
+    g_assert(found_ttl);
 
     return p;
 
@@ -389,20 +409,28 @@ flxDnsPacket* flx_recv_dns_packet_ipv6(gint fd, struct sockaddr_in6 *ret_sa, gin
     p->size = (size_t) l;
     
     *ret_ttl = 0;
-        
-    for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg,cmsg)) {
-        if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IPV6_HOPLIMIT) {
+
+    g_message("pre");
+    
+    for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+        if (cmsg->cmsg_level == SOL_IPV6 && cmsg->cmsg_type == IPV6_HOPLIMIT) {
             *ret_ttl = *(uint8_t *) CMSG_DATA(cmsg);
             found_ttl = TRUE;
         }
             
-        if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IPV6_PKTINFO) {
-            *ret_iface = ((struct in_pktinfo*) CMSG_DATA(cmsg))->ipi_ifindex;
+        if (cmsg->cmsg_level == SOL_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
+            *ret_iface = ((struct in6_pktinfo*) CMSG_DATA(cmsg))->ipi6_ifindex;
             found_iface = TRUE;
         }
+
+        g_message("-- %u -- %u\n", cmsg->cmsg_level, cmsg->cmsg_type);
     }
 
-    g_assert(found_iface && found_ttl);
+    g_message("post");
+
+    g_assert(found_iface);
+    g_assert(found_ttl);
 
     return p;
 
index 472b115..eb7013a 100644 (file)
--- a/socket.h
+++ b/socket.h
@@ -11,7 +11,7 @@ gint flx_open_socket_ipv6(void);
 gint flx_send_dns_packet_ipv4(gint fd, gint iface, flxDnsPacket *p);
 gint flx_send_dns_packet_ipv6(gint fd, gint iface, flxDnsPacket *p);
 
-flxDnsPacket *flx_recv_dns_packet_ipv4(gint fd, struct sockaddr_in*ret_sa, gint *ret_iface, gint *ret_ttl);
-flxDnsPacket *flx_recv_dns_packet_ipv6(gint fd, struct sockaddr_in6*ret_sa, gint *ret_iface, gint *ret_ttl);
+flxDnsPacket *flx_recv_dns_packet_ipv4(gint fd, struct sockaddr_in*ret_sa, gint *ret_iface, guint8 *ret_ttl);
+flxDnsPacket *flx_recv_dns_packet_ipv6(gint fd, struct sockaddr_in6*ret_sa, gint *ret_iface, guint8 *ret_ttl);
 
 #endif