From 7bb43bd370e70385a4ccde06f3f4554f488aa6b3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 17 Mar 2005 15:34:46 +0000 Subject: [PATCH] add code for recieving packets git-svn-id: file:///home/lennart/svn/public/avahi/trunk@11 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- main.c | 21 ++++++++---- netlink.c | 2 +- server.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- server.h | 3 ++ socket.c | 66 ++++++++++++++++++++++++++----------- socket.h | 4 +-- 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 -- 2.7.4