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);
+}
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);
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);
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;
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;
}
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);
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);
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;
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;
/* 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 */
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)
}
}
-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;
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;
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);
/* 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;
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) {
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) {
#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);
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);
}
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);
}
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));
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));
#include "dns.h"
+#define FLX_MDNS_PORT 5353
+
+
+
gint flx_open_socket_ipv4(void);
gint flx_open_socket_ipv6(void);