From 844f6b5a8213018c3d42b5ef924b61cf3eafcdbb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 6 May 2005 00:21:04 +0000 Subject: [PATCH] some preliminary work for adding legacy unicast and unicast response support git-svn-id: file:///home/lennart/svn/public/avahi/trunk@45 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- address.c | 11 +++++++++++ address.h | 1 + dns.c | 13 ++++++------ dns.h | 4 ++-- main.c | 2 +- psched.c | 4 ++-- rr.h | 3 ++- server.c | 59 +++++++++++++++++++++++++++++++++++++------------------ socket.c | 11 +++++------ socket.h | 4 ++++ 10 files changed, 75 insertions(+), 37 deletions(-) diff --git a/address.c b/address.c index dffd3ee..d0fc101 100644 --- a/address.c +++ b/address.c @@ -113,3 +113,14 @@ flxAddress *flx_address_from_sockaddr(const struct sockaddr* sa, flxAddress *ret return ret_addr; } + +guint16 flx_port_from_sockaddr(const struct sockaddr* sa) { + g_assert(sa); + + g_assert(sa->sa_family == AF_INET || sa->sa_family == AF_INET6); + + if (sa->sa_family == AF_INET) + return ntohs(((struct sockaddr_in*) sa)->sin_port); + else + return ntohs(((struct sockaddr_in6*) sa)->sin6_port); +} diff --git a/address.h b/address.h index 66b3b1f..8d8f2f6 100644 --- a/address.h +++ b/address.h @@ -31,6 +31,7 @@ gchar *flx_address_snprint(char *ret_s, guint length, const flxAddress *a); flxAddress *flx_address_parse(const char *s, guchar family, flxAddress *ret_addr); flxAddress *flx_address_from_sockaddr(const struct sockaddr* sa, flxAddress *ret_addr); +guint16 flx_port_from_sockaddr(const struct sockaddr* sa); gchar* flx_reverse_lookup_name_ipv4(const flxIPv4Address *a); gchar* flx_reverse_lookup_name_ipv6_arpa(const flxIPv6Address *a); diff --git a/dns.c b/dns.c index 3f50827..55ae42a 100644 --- a/dns.c +++ b/dns.c @@ -478,13 +478,12 @@ flxRecord* flx_dns_packet_consume_record(flxDnsPacket *p, gboolean *ret_cache_fl flx_dns_packet_consume_uint32(p, &ttl) < 0 || flx_dns_packet_consume_uint16(p, &rdlength) < 0 || p->rindex + rdlength > p->size) - goto fail; /* g_message("name = %s, rdlength = %u", name, rdlength); */ *ret_cache_flush = !!(class & FLX_DNS_CACHE_FLUSH); - class &= ~ FLX_DNS_CACHE_FLUSH; + class &= ~FLX_DNS_CACHE_FLUSH; start = flx_dns_packet_get_rptr(p); @@ -595,23 +594,25 @@ fail: return NULL; } -flxKey* flx_dns_packet_consume_key(flxDnsPacket *p) { +flxKey* flx_dns_packet_consume_key(flxDnsPacket *p, gboolean *ret_unicast_response) { gchar name[256]; guint16 type, class; g_assert(p); + g_assert(ret_unicast_response); if (flx_dns_packet_consume_name(p, name, sizeof(name)) < 0 || flx_dns_packet_consume_uint16(p, &type) < 0 || flx_dns_packet_consume_uint16(p, &class) < 0) return NULL; - class &= ~ FLX_DNS_CACHE_FLUSH; + *ret_unicast_response = !!(class & FLX_DNS_UNICAST_RESPONSE); + class &= ~FLX_DNS_UNICAST_RESPONSE; return flx_key_new(name, class, type); } -guint8* flx_dns_packet_append_key(flxDnsPacket *p, flxKey *k) { +guint8* flx_dns_packet_append_key(flxDnsPacket *p, flxKey *k, gboolean unicast_response) { guint8 *t; guint size; @@ -622,7 +623,7 @@ guint8* flx_dns_packet_append_key(flxDnsPacket *p, flxKey *k) { if (!(t = flx_dns_packet_append_name(p, k->name)) || !flx_dns_packet_append_uint16(p, k->type) || - !flx_dns_packet_append_uint16(p, k->class)) { + !flx_dns_packet_append_uint16(p, k->class | (unicast_response ? FLX_DNS_UNICAST_RESPONSE : 0))) { p->size = size; return NULL; } diff --git a/dns.h b/dns.h index 9a692c4..af9bd59 100644 --- a/dns.h +++ b/dns.h @@ -30,7 +30,7 @@ guint8 *flx_dns_packet_append_uint16(flxDnsPacket *p, guint16 v); guint8 *flx_dns_packet_append_uint32(flxDnsPacket *p, guint32 v); guint8 *flx_dns_packet_append_name(flxDnsPacket *p, const gchar *name); guint8 *flx_dns_packet_append_bytes(flxDnsPacket *p, gconstpointer, guint l); -guint8* flx_dns_packet_append_key(flxDnsPacket *p, flxKey *k); +guint8* flx_dns_packet_append_key(flxDnsPacket *p, flxKey *k, gboolean unicast_response); guint8* flx_dns_packet_append_record(flxDnsPacket *p, flxRecord *r, gboolean cache_flush); guint8* flx_dns_packet_append_string(flxDnsPacket *p, const gchar *s); @@ -41,7 +41,7 @@ gint flx_dns_packet_consume_uint16(flxDnsPacket *p, guint16 *ret_v); gint flx_dns_packet_consume_uint32(flxDnsPacket *p, guint32 *ret_v); gint flx_dns_packet_consume_name(flxDnsPacket *p, gchar *ret_name, guint l); gint flx_dns_packet_consume_bytes(flxDnsPacket *p, gpointer ret_data, guint l); -flxKey* flx_dns_packet_consume_key(flxDnsPacket *p); +flxKey* flx_dns_packet_consume_key(flxDnsPacket *p, gboolean *ret_unicast_response); flxRecord* flx_dns_packet_consume_record(flxDnsPacket *p, gboolean *ret_cache_flush); gint flx_dns_packet_consume_string(flxDnsPacket *p, gchar *ret_string, guint l); diff --git a/main.c b/main.c index efb6172..5725162 100644 --- a/main.c +++ b/main.c @@ -67,7 +67,7 @@ int main(int argc, char *argv[]) { g_main_loop_unref(loop); /* flx_subscription_free(s); */ - flx_entry_group_free(g); + /* flx_entry_group_free(g); */ flx_server_free(flx); return 0; diff --git a/psched.c b/psched.c index 1c43164..dcad5bb 100644 --- a/psched.c +++ b/psched.c @@ -111,7 +111,7 @@ static guint8* packet_add_query_job(flxPacketScheduler *s, flxDnsPacket *p, flxQ g_assert(p); g_assert(qj); - if ((d = flx_dns_packet_append_key(p, qj->key))) { + if ((d = flx_dns_packet_append_key(p, qj->key, FALSE))) { GTimeVal tv; qj->done = 1; @@ -603,7 +603,7 @@ static guint8* packet_add_probe_query(flxPacketScheduler *s, flxDnsPacket *p, fl /* Create the probe query */ k = flx_key_new(pj->record->key->name, pj->record->key->class, FLX_DNS_TYPE_ANY); - ret = flx_dns_packet_append_key(p, k); + ret = flx_dns_packet_append_key(p, k, FALSE); g_assert(ret); /* Mark this job for addition to the packet */ diff --git a/rr.h b/rr.h index 465c328..6521961 100644 --- a/rr.h +++ b/rr.h @@ -22,7 +22,8 @@ enum { enum { FLX_DNS_CLASS_IN = 0x01, - FLX_DNS_CACHE_FLUSH = 0x8000 + FLX_DNS_CACHE_FLUSH = 0x8000, + FLX_DNS_UNICAST_RESPONSE = 0x8000 }; #define FLX_DEFAULT_TTL (120*60) diff --git a/server.c b/server.c index 5cdf56d..dff3968 100644 --- a/server.c +++ b/server.c @@ -77,7 +77,7 @@ static void cleanup_dead(flxServer *s) { } } -static void handle_query_key(flxServer *s, flxKey *k, flxInterface *i, const flxAddress *a) { +static void handle_query_key(flxServer *s, flxKey *k, flxInterface *i, const flxAddress *a, guint16 port, gboolean legacy_unicast, gboolean unicast_response) { flxEntry *e; gchar *txt; @@ -141,7 +141,6 @@ static void incoming_probe(flxServer *s, flxRecord *record, flxInterface *i) { t = flx_record_to_string(record); /* g_message("PROBE: [%s]", t); */ - for (e = g_hash_table_lookup(s->entries_by_key, record->key); e; e = n) { n = e->by_key_next; @@ -164,7 +163,7 @@ static void incoming_probe(flxServer *s, flxRecord *record, flxInterface *i) { g_free(t); } -static void handle_query(flxServer *s, flxDnsPacket *p, flxInterface *i, const flxAddress *a) { +static void handle_query(flxServer *s, flxDnsPacket *p, flxInterface *i, const flxAddress *a, guint16 port, gboolean legacy_unicast) { guint n; g_assert(s); @@ -175,17 +174,18 @@ static void handle_query(flxServer *s, flxDnsPacket *p, flxInterface *i, const f /* Handle the questions */ for (n = flx_dns_packet_get_field(p, FLX_DNS_FIELD_QDCOUNT); n > 0; n --) { flxKey *key; + gboolean unicast_response = FALSE; - if (!(key = flx_dns_packet_consume_key(p))) { + if (!(key = flx_dns_packet_consume_key(p, &unicast_response))) { g_warning("Packet too short (1)"); return; } - handle_query_key(s, key, i, a); + handle_query_key(s, key, i, a, port, legacy_unicast, unicast_response); flx_key_unref(key); } - /* Known Answer Suppresion */ + /* Known Answer Suppression */ for (n = flx_dns_packet_get_field(p, FLX_DNS_FIELD_ANCOUNT); n > 0; n --) { flxRecord *record; gboolean unique = FALSE; @@ -320,36 +320,30 @@ static void handle_response(flxServer *s, flxDnsPacket *p, flxInterface *i, cons static void dispatch_packet(flxServer *s, flxDnsPacket *p, struct sockaddr *sa, gint iface, gint ttl) { flxInterface *i; flxAddress a; + guint16 port; g_assert(s); g_assert(p); g_assert(sa); g_assert(iface > 0); - g_message("new packet recieved."); - if (!(i = flx_interface_monitor_get_interface(s->monitor, iface, sa->sa_family))) { g_warning("Recieved packet from invalid interface."); return; } - if (ttl != 255) { - g_warning("Recieved packet with invalid TTL on interface '%s.%i'.", i->hardware->name, i->protocol); - if (!s->ignore_bad_ttl) - return; - } + g_message("new packet recieved on interface '%s.%i'.", i->hardware->name, i->protocol); if (sa->sa_family == AF_INET6) { - static const unsigned char ipv4_in_ipv6[] = { + static const guint8 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. */ - /* This is an IPv4 address encapsulated in IPv6, so let's ignore it. */ + if (memcmp(((struct sockaddr_in6*) sa)->sin6_addr.s6_addr, ipv4_in_ipv6, sizeof(ipv4_in_ipv6)) == 0) return; - } } if (flx_dns_packet_check_valid(p) < 0) { @@ -357,19 +351,46 @@ static void dispatch_packet(flxServer *s, flxDnsPacket *p, struct sockaddr *sa, return; } + port = flx_port_from_sockaddr(sa); flx_address_from_sockaddr(sa, &a); if (flx_dns_packet_is_query(p)) { + gboolean legacy_unicast = FALSE; if (flx_dns_packet_get_field(p, FLX_DNS_FIELD_QDCOUNT) == 0 || flx_dns_packet_get_field(p, FLX_DNS_FIELD_ARCOUNT) != 0) { g_warning("Invalid query packet."); return; } - - handle_query(s, p, i, &a); + + if (port != FLX_MDNS_PORT) { + /* Legacy Unicast */ + + if ((flx_dns_packet_get_field(p, FLX_DNS_FIELD_ANCOUNT) != 0 || + flx_dns_packet_get_field(p, FLX_DNS_FIELD_NSCOUNT) != 0)) { + g_warning("Invalid legacy unicast query packet."); + return; + } + + legacy_unicast = TRUE; + } + + handle_query(s, p, i, &a, port, legacy_unicast); + g_message("Handled query"); } else { + + if (port != FLX_MDNS_PORT) { + g_warning("Recieved repsonse with invalid source port %u on interface '%s.%i'", port, i->hardware->name, i->protocol); + return; + } + + if (ttl != 255) { + g_warning("Recieved response with invalid TTL %u on interface '%s.%i'.", ttl, i->hardware->name, i->protocol); + if (!s->ignore_bad_ttl) + return; + } + if (flx_dns_packet_get_field(p, FLX_DNS_FIELD_QDCOUNT) != 0 || flx_dns_packet_get_field(p, FLX_DNS_FIELD_ANCOUNT) == 0 || flx_dns_packet_get_field(p, FLX_DNS_FIELD_NSCOUNT) != 0) { diff --git a/socket.c b/socket.c index 48a5d4b..8f50291 100644 --- a/socket.c +++ b/socket.c @@ -13,8 +13,7 @@ #include "dns.h" #include "util.h" - -#define MDNS_PORT 5353 +#include "socket.h" static void mdns_mcast_group_ipv4(struct sockaddr_in *ret_sa) { g_assert(ret_sa); @@ -22,7 +21,7 @@ static void mdns_mcast_group_ipv4(struct sockaddr_in *ret_sa) { memset(ret_sa, 0, sizeof(struct sockaddr_in)); ret_sa->sin_family = AF_INET; - ret_sa->sin_port = htons(MDNS_PORT); + ret_sa->sin_port = htons(FLX_MDNS_PORT); inet_pton(AF_INET, "224.0.0.251", &ret_sa->sin_addr); } @@ -33,7 +32,7 @@ static void mdns_mcast_group_ipv6(struct sockaddr_in6 *ret_sa) { memset(ret_sa, 0, sizeof(struct sockaddr_in6)); ret_sa->sin6_family = AF_INET6; - ret_sa->sin6_port = htons(MDNS_PORT); + ret_sa->sin6_port = htons(FLX_MDNS_PORT); inet_pton(AF_INET6, "ff02::fb", &ret_sa->sin6_addr); } @@ -149,7 +148,7 @@ gint flx_open_socket_ipv4(void) { memset(&local, 0, sizeof(local)); local.sin_family = AF_INET; - local.sin_port = htons(MDNS_PORT); + local.sin_port = htons(FLX_MDNS_PORT); if (bind(fd, (struct sockaddr*) &local, sizeof(local)) < 0) { g_warning("bind() failed: %s\n", strerror(errno)); @@ -230,7 +229,7 @@ gint flx_open_socket_ipv6(void) { memset(&local, 0, sizeof(local)); local.sin6_family = AF_INET6; - local.sin6_port = htons(MDNS_PORT); + local.sin6_port = htons(FLX_MDNS_PORT); if (bind(fd, (struct sockaddr*) &local, sizeof(local)) < 0) { g_warning("bind() failed: %s\n", strerror(errno)); diff --git a/socket.h b/socket.h index 61d17a5..5548a70 100644 --- a/socket.h +++ b/socket.h @@ -5,6 +5,10 @@ #include "dns.h" +#define FLX_MDNS_PORT 5353 + + + gint flx_open_socket_ipv4(void); gint flx_open_socket_ipv6(void); -- 2.39.5