summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2005-03-17 15:34:46 +0000
committerLennart Poettering <lennart@poettering.net>2005-03-17 15:34:46 +0000
commit7bb43bd370e70385a4ccde06f3f4554f488aa6b3 (patch)
tree602b7a4c4a1b8a6c2594666409b1f829adc89360
parent4ba1a4b0b4488e5058af67b789187735b529075e (diff)
add code for recieving packets
git-svn-id: file:///home/lennart/svn/public/avahi/trunk@11 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe
-rw-r--r--main.c21
-rw-r--r--netlink.c2
-rw-r--r--server.c109
-rw-r--r--server.h3
-rw-r--r--socket.c66
-rw-r--r--socket.h4
6 files changed, 175 insertions, 30 deletions
diff --git a/main.c b/main.c
index b366eb5..75d03ac 100644
--- 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);
diff --git a/netlink.c b/netlink.c
index 3bc7d01..92eb44e 100644
--- 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) {
diff --git a/server.c b/server.c
index f85de45..baac24c 100644
--- 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);
}
diff --git a/server.h b/server.h
index b1cc57b..4566926 100644
--- 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;
};
diff --git a/socket.c b/socket.c
index a77f631..48cfb36 100644
--- 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;
diff --git a/socket.h b/socket.h
index 472b115..eb7013a 100644
--- 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