From c5544522f6409095627dc3d1129560195ab4ec40 Mon Sep 17 00:00:00 2001 From: Trent Lloyd Date: Sat, 4 Jun 2005 18:56:52 +0000 Subject: * Split out a fair bit of avahi-core into avahi-common for use by the client library git-svn-id: file:///home/lennart/svn/public/avahi/trunk@98 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- Makefile.am | 2 +- avahi-common/Makefile.am | 81 +++++ avahi-common/address.c | 166 +++++++++ avahi-common/address.h | 62 ++++ avahi-common/alternative-test.c | 48 +++ avahi-common/alternative.c | 81 +++++ avahi-common/alternative.h | 39 +++ avahi-common/dns-test.c | 60 ++++ avahi-common/dns.c | 744 ++++++++++++++++++++++++++++++++++++++++ avahi-common/dns.h | 105 ++++++ avahi-common/domain-test.c | 48 +++ avahi-common/rr.c | 551 +++++++++++++++++++++++++++++ avahi-common/rr.h | 140 ++++++++ avahi-common/strlst-test.c | 85 +++++ avahi-common/strlst.c | 245 +++++++++++++ avahi-common/strlst.h | 53 +++ avahi-common/util.c | 428 +++++++++++++++++++++++ avahi-common/util.h | 57 +++ avahi-core.pc.in | 2 +- avahi-core/Makefile.am | 51 +-- avahi-core/address.c | 166 --------- avahi-core/address.h | 62 ---- avahi-core/alternative-test.c | 48 --- avahi-core/alternative.c | 81 ----- avahi-core/alternative.h | 39 --- avahi-core/avahi-reflector.c | 1 - avahi-core/avahi-test.c | 1 - avahi-core/core.h | 5 +- avahi-core/dns-test.c | 60 ---- avahi-core/dns.c | 744 ---------------------------------------- avahi-core/dns.h | 105 ------ avahi-core/domain-test.c | 48 --- avahi-core/rr.c | 551 ----------------------------- avahi-core/rr.h | 140 -------- avahi-core/strlst-test.c | 85 ----- avahi-core/strlst.c | 245 ------------- avahi-core/strlst.h | 53 --- avahi-core/util.c | 428 ----------------------- avahi-core/util.h | 57 --- avahi-discover/Makefile.am | 2 +- avahi-discover/main.c | 2 +- configure.ac | 2 +- daemon/Makefile.am | 4 +- doxygen/doxygen.conf.in | 2 +- 44 files changed, 3009 insertions(+), 2970 deletions(-) create mode 100644 avahi-common/Makefile.am create mode 100644 avahi-common/address.c create mode 100644 avahi-common/address.h create mode 100644 avahi-common/alternative-test.c create mode 100644 avahi-common/alternative.c create mode 100644 avahi-common/alternative.h create mode 100644 avahi-common/dns-test.c create mode 100644 avahi-common/dns.c create mode 100644 avahi-common/dns.h create mode 100644 avahi-common/domain-test.c create mode 100644 avahi-common/rr.c create mode 100644 avahi-common/rr.h create mode 100644 avahi-common/strlst-test.c create mode 100644 avahi-common/strlst.c create mode 100644 avahi-common/strlst.h create mode 100644 avahi-common/util.c create mode 100644 avahi-common/util.h delete mode 100644 avahi-core/address.c delete mode 100644 avahi-core/address.h delete mode 100644 avahi-core/alternative-test.c delete mode 100644 avahi-core/alternative.c delete mode 100644 avahi-core/alternative.h delete mode 100644 avahi-core/dns-test.c delete mode 100644 avahi-core/dns.c delete mode 100644 avahi-core/dns.h delete mode 100644 avahi-core/domain-test.c delete mode 100644 avahi-core/rr.c delete mode 100644 avahi-core/rr.h delete mode 100644 avahi-core/strlst-test.c delete mode 100644 avahi-core/strlst.c delete mode 100644 avahi-core/strlst.h delete mode 100644 avahi-core/util.c delete mode 100644 avahi-core/util.h diff --git a/Makefile.am b/Makefile.am index 26124a8..6606f65 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,7 +18,7 @@ # USA. EXTRA_DIST = bootstrap.sh LICENSE doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in libtool.m4 -SUBDIRS = avahi-core avahi-discover +SUBDIRS = avahi-common avahi-core avahi-discover pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = avahi-core.pc diff --git a/avahi-common/Makefile.am b/avahi-common/Makefile.am new file mode 100644 index 0000000..8c58757 --- /dev/null +++ b/avahi-common/Makefile.am @@ -0,0 +1,81 @@ +# $Id: Makefile.am 90 2005-05-23 16:15:12Z lennart $ +# +# This file is part of avahi. +# +# avahi is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# avahi is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +# License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with avahi; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA. + +AM_CFLAGS=-I$(top_srcdir) -D_GNU_SOURCE + +# GLIB 2.0 +AM_CFLAGS+=$(GLIB20_CFLAGS) +AM_LDADD=$(GLIB20_LIBS) + +# This cool debug trap works on i386/gcc only +AM_CFLAGS+='-DDEBUG_TRAP=__asm__("int $$3")' + +avahi_commonincludedir=$(includedir)/avahi-common + +avahi_commoninclude_HEADERS = + strlst.h \ + address.h \ + alternative.h \ + rr.h \ + util.h \ + dns.h + +noinst_PROGRAMS = \ + strlst-test \ + dns-test \ + domain-test \ + alternative-test + +lib_LTLIBRARIES = \ + libavahi-common.la + +libavahi_common_la_SOURCES = \ + address.c address.h \ + strlst.c strlst.h \ + alternative.c alternative.h \ + rr.c rr.h \ + dns.c dns.h \ + util.c util.h + +strlst_test_SOURCES = \ + strlst.c strlst.h \ + strlst-test.c +strlst_test_CFLAGS = $(AM_CFLAGS) +strlst_test_LDADD = $(AM_LDADD) + +dns_test_SOURCES = \ + util.c util.h \ + dns.c dns.h \ + rr.c rr.h \ + strlst.c strlst \ + dns-test.c +dns_test_CFLAGS = $(AM_CFLAGS) +dns_test_LDADD = $(AM_LDADD) + +alternative_test_SOURCES = \ + alternative.c alternative.h \ + alternative-test.c +alternative_test_CFLAGS = $(AM_CFLAGS) +alternative_test_LDADD = $(AM_LDADD) + +domain_test_SOURCES = \ + util.c util.h \ + domain-test.c +domain_test_CFLAGS = $(AM_CFLAGS) +domain_test_LDADD = $(AM_LDADD) diff --git a/avahi-common/address.c b/avahi-common/address.c new file mode 100644 index 0000000..3484707 --- /dev/null +++ b/avahi-common/address.c @@ -0,0 +1,166 @@ +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "address.h" + +guint avahi_address_get_size(const AvahiAddress *a) { + g_assert(a); + + if (a->family == AF_INET) + return 4; + else if (a->family == AF_INET6) + return 16; + + return 0; +} + +gint avahi_address_cmp(const AvahiAddress *a, const AvahiAddress *b) { + g_assert(a); + g_assert(b); + + if (a->family != b->family) + return -1; + + return memcmp(a->data.data, b->data.data, avahi_address_get_size(a)); +} + +gchar *avahi_address_snprint(char *s, guint length, const AvahiAddress *a) { + g_assert(s); + g_assert(length); + g_assert(a); + return (gchar*) inet_ntop(a->family, a->data.data, s, length); +} + +gchar* avahi_reverse_lookup_name_ipv4(const AvahiIPv4Address *a) { + guint32 n = ntohl(a->address); + g_assert(a); + + return g_strdup_printf("%u.%u.%u.%u.in-addr.arpa", n & 0xFF, (n >> 8) & 0xFF, (n >> 16) & 0xFF, n >> 24); +} + +static gchar *reverse_lookup_name_ipv6(const AvahiIPv6Address *a, const gchar *suffix) { + + return g_strdup_printf("%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%s", + a->address[15] & 0xF, + a->address[15] >> 4, + a->address[14] & 0xF, + a->address[14] >> 4, + a->address[13] & 0xF, + a->address[13] >> 4, + a->address[12] & 0xF, + a->address[12] >> 4, + a->address[11] & 0xF, + a->address[11] >> 4, + a->address[10] & 0xF, + a->address[10] >> 4, + a->address[9] & 0xF, + a->address[9] >> 4, + a->address[8] & 0xF, + a->address[8] >> 4, + a->address[7] & 0xF, + a->address[7] >> 4, + a->address[6] & 0xF, + a->address[6] >> 4, + a->address[5] & 0xF, + a->address[5] >> 4, + a->address[4] & 0xF, + a->address[4] >> 4, + a->address[3] & 0xF, + a->address[3] >> 4, + a->address[2] & 0xF, + a->address[2] >> 4, + a->address[1] & 0xF, + a->address[1] >> 4, + a->address[0] & 0xF, + a->address[0] >> 4, + suffix); +} + +gchar *avahi_reverse_lookup_name_ipv6_arpa(const AvahiIPv6Address *a) { + return reverse_lookup_name_ipv6(a, "ip6.arpa"); +} + +gchar *avahi_reverse_lookup_name_ipv6_int(const AvahiIPv6Address *a) { + return reverse_lookup_name_ipv6(a, "ip6.int"); +} + +AvahiAddress *avahi_address_parse(const char *s, guchar family, AvahiAddress *ret_addr) { + g_assert(ret_addr); + g_assert(s); + + if (inet_pton(family, s, ret_addr->data.data) < 0) + return NULL; + + ret_addr->family = family; + + return ret_addr; +} + +AvahiAddress *avahi_address_from_sockaddr(const struct sockaddr* sa, AvahiAddress *ret_addr) { + g_assert(sa); + g_assert(ret_addr); + + g_assert(sa->sa_family == AF_INET || sa->sa_family == AF_INET6); + + ret_addr->family = sa->sa_family; + + if (sa->sa_family == AF_INET) + memcpy(&ret_addr->data.ipv4, &((struct sockaddr_in*) sa)->sin_addr, sizeof(ret_addr->data.ipv4)); + else + memcpy(&ret_addr->data.ipv6, &((struct sockaddr_in6*) sa)->sin6_addr, sizeof(ret_addr->data.ipv6)); + + return ret_addr; +} + +guint16 avahi_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); +} + +gboolean avahi_address_is_ipv4_in_ipv6(const AvahiAddress *a) { + static const guint8 ipv4_in_ipv6[] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF }; + + g_assert(a); + + if (a->family != AF_INET6) + return FALSE; + + return memcmp(a->data.ipv6.address, ipv4_in_ipv6, sizeof(ipv4_in_ipv6)) == 0; +} + diff --git a/avahi-common/address.h b/avahi-common/address.h new file mode 100644 index 0000000..22cb74b --- /dev/null +++ b/avahi-common/address.h @@ -0,0 +1,62 @@ +#ifndef fooaddresshfoo +#define fooaddresshfoo + +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include +#include + +typedef struct { + guint32 address; +} AvahiIPv4Address; + +typedef struct { + guint8 address[16]; +} AvahiIPv6Address; + +typedef struct { + guchar family; + + union { + AvahiIPv6Address ipv6; + AvahiIPv4Address ipv4; + guint8 data[1]; + } data; +} AvahiAddress; + +guint avahi_address_get_size(const AvahiAddress *a); +gint avahi_address_cmp(const AvahiAddress *a, const AvahiAddress *b); + +gchar *avahi_address_snprint(char *ret_s, guint length, const AvahiAddress *a); + +AvahiAddress *avahi_address_parse(const char *s, guchar family, AvahiAddress *ret_addr); + +AvahiAddress *avahi_address_from_sockaddr(const struct sockaddr* sa, AvahiAddress *ret_addr); +guint16 avahi_port_from_sockaddr(const struct sockaddr* sa); + +gchar* avahi_reverse_lookup_name_ipv4(const AvahiIPv4Address *a); +gchar* avahi_reverse_lookup_name_ipv6_arpa(const AvahiIPv6Address *a); +gchar* avahi_reverse_lookup_name_ipv6_int(const AvahiIPv6Address *a); + +gboolean avahi_address_is_ipv4_in_ipv6(const AvahiAddress *a); + +#endif diff --git a/avahi-common/alternative-test.c b/avahi-common/alternative-test.c new file mode 100644 index 0000000..9e26d24 --- /dev/null +++ b/avahi-common/alternative-test.c @@ -0,0 +1,48 @@ +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "alternative.h" + +int main(int argc, char *argv[]) { + gchar *r = NULL; + gint i, k; + + for (k = 0; k < 2; k++) { + + for (i = 0; i < 20; i++) { + gchar *n; + + n = i == 0 ? g_strdup("gurke") : (k ? avahi_alternative_service_name(r) : avahi_alternative_host_name(r)); + g_free(r); + r = n; + + printf("%s\n", r); + } + } + + g_free(r); +} diff --git a/avahi-common/alternative.c b/avahi-common/alternative.c new file mode 100644 index 0000000..c9a0f48 --- /dev/null +++ b/avahi-common/alternative.c @@ -0,0 +1,81 @@ +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "alternative.h" + +gchar * avahi_alternative_host_name(const gchar *s) { + const gchar *p, *e = NULL; + gchar *c, *r; + gint n; + + g_assert(s); + + for (p = s; *p; p++) + if (!isdigit(*p)) + e = p+1; + + if (e && *e) + n = atoi(e)+1; + else + n = 2; + + c = e ? g_strndup(s, e-s) : g_strdup(s); + r = g_strdup_printf("%s%i", c, n); + g_free(c); + + return r; + +} + +gchar *avahi_alternative_service_name(const gchar *s) { + const gchar *e; + g_assert(s); + + if ((e = strstr(s, " #"))) { + const gchar *n, *p; + e += 2; + + while ((n = strstr(e, " #"))) + e = n + 2; + + for (p = e; *p; p++) + if (!isdigit(*p)) { + e = NULL; + break; + } + } + + if (e) { + gchar *r, *c = g_strndup(s, e-s); + r = g_strdup_printf("%s%i", c, atoi(e)+1); + g_free(c); + return r; + } else + return g_strdup_printf("%s #2", s); +} diff --git a/avahi-common/alternative.h b/avahi-common/alternative.h new file mode 100644 index 0000000..3aed5b2 --- /dev/null +++ b/avahi-common/alternative.h @@ -0,0 +1,39 @@ +#ifndef fooalternativehfoo +#define fooalternativehfoo + +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +/** Find an alternative for the specified host name. If called with an + * original host name, "2" is appended, Afterwards the number is + * increased on each call. (i.e. "foo" becomes "foo2" becomes "foo3" + * and so on.)*/ +gchar *avahi_alternative_host_name(const gchar *s); + +/** Find an alternative for the specified service name. If called with + an original service name, " #2" is appended. Afterwards the number + is increased on each call (i.e. "foo" becomes "foo #2" becomes + "foo #3" and so on.)*/ +gchar *avahi_alternative_service_name(const gchar *s); + +#endif diff --git a/avahi-common/dns-test.c b/avahi-common/dns-test.c new file mode 100644 index 0000000..aa36f2a --- /dev/null +++ b/avahi-common/dns-test.c @@ -0,0 +1,60 @@ +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "dns.h" +#include "util.h" + +int main(int argc, char *argv[]) { + gchar t[256], *a, *b, *c, *d; + AvahiDnsPacket *p; + + p = avahi_dns_packet_new(0); + + avahi_dns_packet_append_name(p, a = "hello.hello.hello.de."); + avahi_dns_packet_append_name(p, b = "this is a test.hello.de."); + avahi_dns_packet_append_name(p, c = "this\\.is\\.a\\.test\\.with\\.dots.hello.de."); + avahi_dns_packet_append_name(p, d = "this\\\\is another\\ \\test.hello.de."); + + avahi_hexdump(AVAHI_DNS_PACKET_DATA(p), p->size); + + avahi_dns_packet_consume_name(p, t, sizeof(t)); + g_message(">%s<", t); + g_assert(avahi_domain_equal(a, t)); + + avahi_dns_packet_consume_name(p, t, sizeof(t)); + g_message(">%s<", t); + g_assert(avahi_domain_equal(b, t)); + + avahi_dns_packet_consume_name(p, t, sizeof(t)); + g_message(">%s<", t); + g_assert(avahi_domain_equal(c, t)); + + avahi_dns_packet_consume_name(p, t, sizeof(t)); + g_message(">%s<", t); + g_assert(avahi_domain_equal(d, t)); + + avahi_dns_packet_free(p); + return 0; +} diff --git a/avahi-common/dns.c b/avahi-common/dns.c new file mode 100644 index 0000000..9e19c9e --- /dev/null +++ b/avahi-common/dns.c @@ -0,0 +1,744 @@ +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include + +#include "dns.h" +#include "util.h" + +AvahiDnsPacket* avahi_dns_packet_new(guint mtu) { + AvahiDnsPacket *p; + guint max_size; + + if (mtu <= 0) + max_size = AVAHI_DNS_PACKET_MAX_SIZE; + else if (mtu >= AVAHI_DNS_PACKET_EXTRA_SIZE) + max_size = mtu - AVAHI_DNS_PACKET_EXTRA_SIZE; + else + max_size = 0; + + if (max_size < AVAHI_DNS_PACKET_HEADER_SIZE) + max_size = AVAHI_DNS_PACKET_HEADER_SIZE; + + p = g_malloc(sizeof(AvahiDnsPacket) + max_size); + p->size = p->rindex = AVAHI_DNS_PACKET_HEADER_SIZE; + p->max_size = max_size; + p->name_table = NULL; + + memset(AVAHI_DNS_PACKET_DATA(p), 0, p->size); + return p; +} + +AvahiDnsPacket* avahi_dns_packet_new_query(guint mtu) { + AvahiDnsPacket *p; + + p = avahi_dns_packet_new(mtu); + avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_FLAGS, AVAHI_DNS_FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); + return p; +} + +AvahiDnsPacket* avahi_dns_packet_new_response(guint mtu, gboolean aa) { + AvahiDnsPacket *p; + + p = avahi_dns_packet_new(mtu); + avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_FLAGS, AVAHI_DNS_FLAGS(1, 0, aa, 0, 0, 0, 0, 0, 0, 0)); + return p; +} + +AvahiDnsPacket* avahi_dns_packet_new_reply(AvahiDnsPacket* p, guint mtu, gboolean copy_queries, gboolean aa) { + AvahiDnsPacket *r; + g_assert(p); + + r = avahi_dns_packet_new_response(mtu, aa); + + if (copy_queries) { + guint n, saved_rindex; + + saved_rindex = p->rindex; + p->rindex = AVAHI_DNS_PACKET_HEADER_SIZE; + + for (n = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_QDCOUNT); n > 0; n--) { + AvahiKey *k; + gboolean unicast_response; + + if ((k = avahi_dns_packet_consume_key(p, &unicast_response))) { + avahi_dns_packet_append_key(r, k, unicast_response); + avahi_key_unref(k); + } + } + + p->rindex = saved_rindex; + + avahi_dns_packet_set_field(r, AVAHI_DNS_FIELD_QDCOUNT, avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_QDCOUNT)); + } + + avahi_dns_packet_set_field(r, AVAHI_DNS_FIELD_ID, avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_ID)); + + avahi_dns_packet_set_field(r, AVAHI_DNS_FIELD_FLAGS, + (avahi_dns_packet_get_field(r, AVAHI_DNS_FIELD_FLAGS) & ~AVAHI_DNS_FLAG_OPCODE) | + (avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS) & AVAHI_DNS_FLAG_OPCODE)); + + return r; +} + + +void avahi_dns_packet_free(AvahiDnsPacket *p) { + g_assert(p); + + if (p->name_table) + g_hash_table_destroy(p->name_table); + + g_free(p); +} + +void avahi_dns_packet_set_field(AvahiDnsPacket *p, guint index, guint16 v) { + g_assert(p); + g_assert(index < AVAHI_DNS_PACKET_HEADER_SIZE); + + ((guint16*) AVAHI_DNS_PACKET_DATA(p))[index] = g_htons(v); +} + +guint16 avahi_dns_packet_get_field(AvahiDnsPacket *p, guint index) { + g_assert(p); + g_assert(index < AVAHI_DNS_PACKET_HEADER_SIZE); + + return g_ntohs(((guint16*) AVAHI_DNS_PACKET_DATA(p))[index]); +} + +void avahi_dns_packet_inc_field(AvahiDnsPacket *p, guint index) { + g_assert(p); + + avahi_dns_packet_set_field(p, index, avahi_dns_packet_get_field(p, index) + 1); +} + +guint8* avahi_dns_packet_append_name(AvahiDnsPacket *p, const gchar *name) { + guint8 *d, *saved_ptr = NULL; + guint saved_size; + + g_assert(p); + g_assert(name); + + saved_size = p->size; + saved_ptr = avahi_dns_packet_extend(p, 0); + + while (*name) { + guint8* prev; + const gchar *pname; + gchar label[64]; + + /* Check whether we can compress this name. */ + + if (p->name_table && (prev = g_hash_table_lookup(p->name_table, name))) { + guint index; + + g_assert(prev >= AVAHI_DNS_PACKET_DATA(p)); + index = (guint) (prev - AVAHI_DNS_PACKET_DATA(p)); + + g_assert(index < p->size); + + if (index < 0x4000) { + guint16 *t; + if (!(t = (guint16*) avahi_dns_packet_extend(p, sizeof(guint16)))) + return NULL; + + *t = g_htons((0xC000 | index)); + return saved_ptr; + } + } + + pname = name; + + if (!(avahi_unescape_label(&name, label, sizeof(label)))) + goto fail; + + if (!(d = avahi_dns_packet_append_string(p, label))) + goto fail; + + if (!p->name_table) + /* This works only for normalized domain names */ + p->name_table = g_hash_table_new_full((GHashFunc) g_str_hash, (GEqualFunc) g_str_equal, g_free, NULL); + + g_hash_table_insert(p->name_table, g_strdup(pname), d); + } + + if (!(d = avahi_dns_packet_extend(p, 1))) + goto fail; + + *d = 0; + + return saved_ptr; + +fail: + p->size = saved_size; + return NULL; +} + +guint8* avahi_dns_packet_append_uint16(AvahiDnsPacket *p, guint16 v) { + guint8 *d; + g_assert(p); + + if (!(d = avahi_dns_packet_extend(p, sizeof(guint16)))) + return NULL; + + *((guint16*) d) = g_htons(v); + return d; +} + +guint8 *avahi_dns_packet_append_uint32(AvahiDnsPacket *p, guint32 v) { + guint8 *d; + g_assert(p); + + if (!(d = avahi_dns_packet_extend(p, sizeof(guint32)))) + return NULL; + + *((guint32*) d) = g_htonl(v); + + return d; +} + +guint8 *avahi_dns_packet_append_bytes(AvahiDnsPacket *p, gconstpointer b, guint l) { + guint8* d; + + g_assert(p); + g_assert(b); + g_assert(l); + + if (!(d = avahi_dns_packet_extend(p, l))) + return NULL; + + memcpy(d, b, l); + return d; +} + +guint8* avahi_dns_packet_append_string(AvahiDnsPacket *p, const gchar *s) { + guint8* d; + guint k; + + g_assert(p); + g_assert(s); + + if ((k = strlen(s)) >= 255) + k = 255; + + if (!(d = avahi_dns_packet_extend(p, k+1))) + return NULL; + + *d = (guint8) k; + memcpy(d+1, s, k); + + return d; +} + +guint8 *avahi_dns_packet_extend(AvahiDnsPacket *p, guint l) { + guint8 *d; + + g_assert(p); + + if (p->size+l > p->max_size) + return NULL; + + d = AVAHI_DNS_PACKET_DATA(p) + p->size; + p->size += l; + + return d; +} + +gint avahi_dns_packet_check_valid(AvahiDnsPacket *p) { + guint16 flags; + g_assert(p); + + if (p->size < 12) + return -1; + + flags = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS); + + if (flags & AVAHI_DNS_FLAG_OPCODE || flags & AVAHI_DNS_FLAG_RCODE) + return -1; + + return 0; +} + +gint avahi_dns_packet_is_query(AvahiDnsPacket *p) { + g_assert(p); + + return !(avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS) & AVAHI_DNS_FLAG_QR); +} + +static gint consume_labels(AvahiDnsPacket *p, guint index, gchar *ret_name, guint l) { + gint ret = 0; + int compressed = 0; + int first_label = 1; + g_assert(p && ret_name && l); + + for (;;) { + guint8 n; + + if (index+1 > p->size) + return -1; + + n = AVAHI_DNS_PACKET_DATA(p)[index]; + + if (!n) { + index++; + if (!compressed) + ret++; + + if (l < 1) + return -1; + *ret_name = 0; + + return ret; + + } else if (n <= 63) { + /* Uncompressed label */ + index++; + if (!compressed) + ret++; + + if (index + n > p->size) + return -1; + + if ((guint) n + 1 > l) + return -1; + + if (!first_label) { + *(ret_name++) = '.'; + l--; + } else + first_label = 0; + + if (!(avahi_escape_label(AVAHI_DNS_PACKET_DATA(p) + index, n, &ret_name, &l))) + return -1; + + index += n; + + if (!compressed) + ret += n; + } else if ((n & 0xC0) == 0xC0) { + /* Compressed label */ + + if (index+2 > p->size) + return -1; + + index = ((guint) (AVAHI_DNS_PACKET_DATA(p)[index] & ~0xC0)) << 8 | AVAHI_DNS_PACKET_DATA(p)[index+1]; + + if (!compressed) + ret += 2; + + compressed = 1; + } else + return -1; + } +} + +gint avahi_dns_packet_consume_name(AvahiDnsPacket *p, gchar *ret_name, guint l) { + gint r; + + if ((r = consume_labels(p, p->rindex, ret_name, l)) < 0) + return -1; + + p->rindex += r; + return 0; +} + +gint avahi_dns_packet_consume_uint16(AvahiDnsPacket *p, guint16 *ret_v) { + g_assert(p); + g_assert(ret_v); + + if (p->rindex + sizeof(guint16) > p->size) + return -1; + + *ret_v = g_ntohs(*((guint16*) (AVAHI_DNS_PACKET_DATA(p) + p->rindex))); + p->rindex += sizeof(guint16); + + return 0; +} + +gint avahi_dns_packet_consume_uint32(AvahiDnsPacket *p, guint32 *ret_v) { + g_assert(p); + g_assert(ret_v); + + if (p->rindex + sizeof(guint32) > p->size) + return -1; + + *ret_v = g_ntohl(*((guint32*) (AVAHI_DNS_PACKET_DATA(p) + p->rindex))); + p->rindex += sizeof(guint32); + + return 0; +} + +gint avahi_dns_packet_consume_bytes(AvahiDnsPacket *p, gpointer ret_data, guint l) { + g_assert(p); + g_assert(ret_data); + g_assert(l > 0); + + if (p->rindex + l > p->size) + return -1; + + memcpy(ret_data, AVAHI_DNS_PACKET_DATA(p) + p->rindex, l); + p->rindex += l; + + return 0; +} + +gint avahi_dns_packet_consume_string(AvahiDnsPacket *p, gchar *ret_string, guint l) { + guint k; + + g_assert(p); + g_assert(ret_string); + g_assert(l > 0); + + if (p->rindex >= p->size) + return -1; + + k = AVAHI_DNS_PACKET_DATA(p)[p->rindex]; + + if (p->rindex+1+k > p->size) + return -1; + + if (l > k+1) + l = k+1; + + memcpy(ret_string, AVAHI_DNS_PACKET_DATA(p)+p->rindex+1, l-1); + ret_string[l-1] = 0; + + + p->rindex += 1+k; + + return 0; + +} + +gconstpointer avahi_dns_packet_get_rptr(AvahiDnsPacket *p) { + g_assert(p); + + if (p->rindex > p->size) + return NULL; + + return AVAHI_DNS_PACKET_DATA(p) + p->rindex; +} + +gint avahi_dns_packet_skip(AvahiDnsPacket *p, guint length) { + g_assert(p); + + if (p->rindex + length > p->size) + return -1; + + p->rindex += length; + return 0; +} + +AvahiRecord* avahi_dns_packet_consume_record(AvahiDnsPacket *p, gboolean *ret_cache_flush) { + gchar name[257], buf[257]; + guint16 type, class; + guint32 ttl; + guint16 rdlength; + AvahiRecord *r = NULL; + gconstpointer start; + + g_assert(p); + g_assert(ret_cache_flush); + +/* g_message("consume_record()"); */ + + if (avahi_dns_packet_consume_name(p, name, sizeof(name)) < 0 || + avahi_dns_packet_consume_uint16(p, &type) < 0 || + avahi_dns_packet_consume_uint16(p, &class) < 0 || + avahi_dns_packet_consume_uint32(p, &ttl) < 0 || + avahi_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 & AVAHI_DNS_CACHE_FLUSH); + class &= ~AVAHI_DNS_CACHE_FLUSH; + + start = avahi_dns_packet_get_rptr(p); + + r = avahi_record_new_full(name, class, type); + + switch (type) { + case AVAHI_DNS_TYPE_PTR: + case AVAHI_DNS_TYPE_CNAME: + +/* g_message("ptr"); */ + + if (avahi_dns_packet_consume_name(p, buf, sizeof(buf)) < 0) + goto fail; + + r->data.ptr.name = g_strdup(buf); + break; + + + case AVAHI_DNS_TYPE_SRV: + +/* g_message("srv"); */ + + if (avahi_dns_packet_consume_uint16(p, &r->data.srv.priority) < 0 || + avahi_dns_packet_consume_uint16(p, &r->data.srv.weight) < 0 || + avahi_dns_packet_consume_uint16(p, &r->data.srv.port) < 0 || + avahi_dns_packet_consume_name(p, buf, sizeof(buf)) < 0) + goto fail; + + r->data.srv.name = g_strdup(buf); + break; + + case AVAHI_DNS_TYPE_HINFO: + +/* g_message("hinfo"); */ + + if (avahi_dns_packet_consume_string(p, buf, sizeof(buf)) < 0) + goto fail; + + r->data.hinfo.cpu = g_strdup(buf); + + if (avahi_dns_packet_consume_string(p, buf, sizeof(buf)) < 0) + goto fail; + + r->data.hinfo.os = g_strdup(buf); + break; + + case AVAHI_DNS_TYPE_TXT: + +/* g_message("txt"); */ + + if (rdlength > 0) { + r->data.txt.string_list = avahi_string_list_parse(avahi_dns_packet_get_rptr(p), rdlength); + + if (avahi_dns_packet_skip(p, rdlength) < 0) + goto fail; + } else + r->data.txt.string_list = NULL; + + break; + + case AVAHI_DNS_TYPE_A: + +/* g_message("A"); */ + + if (avahi_dns_packet_consume_bytes(p, &r->data.a.address, sizeof(AvahiIPv4Address)) < 0) + goto fail; + + break; + + case AVAHI_DNS_TYPE_AAAA: + +/* g_message("aaaa"); */ + + if (avahi_dns_packet_consume_bytes(p, &r->data.aaaa.address, sizeof(AvahiIPv6Address)) < 0) + goto fail; + + break; + + default: + +/* g_message("generic"); */ + + if (rdlength > 0) { + + r->data.generic.data = g_memdup(avahi_dns_packet_get_rptr(p), rdlength); + + if (avahi_dns_packet_skip(p, rdlength) < 0) + goto fail; + } + + break; + } + +/* g_message("%i == %u ?", (guint8*) avahi_dns_packet_get_rptr(p) - (guint8*) start, rdlength); */ + + /* Check if we read enough data */ + if ((guint8*) avahi_dns_packet_get_rptr(p) - (guint8*) start != rdlength) + goto fail; + + r->ttl = ttl; + + return r; + +fail: + if (r) + avahi_record_unref(r); + + return NULL; +} + +AvahiKey* avahi_dns_packet_consume_key(AvahiDnsPacket *p, gboolean *ret_unicast_response) { + gchar name[256]; + guint16 type, class; + + g_assert(p); + g_assert(ret_unicast_response); + + if (avahi_dns_packet_consume_name(p, name, sizeof(name)) < 0 || + avahi_dns_packet_consume_uint16(p, &type) < 0 || + avahi_dns_packet_consume_uint16(p, &class) < 0) + return NULL; + + *ret_unicast_response = !!(class & AVAHI_DNS_UNICAST_RESPONSE); + class &= ~AVAHI_DNS_UNICAST_RESPONSE; + + return avahi_key_new(name, class, type); +} + +guint8* avahi_dns_packet_append_key(AvahiDnsPacket *p, AvahiKey *k, gboolean unicast_response) { + guint8 *t; + guint size; + + g_assert(p); + g_assert(k); + + size = p->size; + + if (!(t = avahi_dns_packet_append_name(p, k->name)) || + !avahi_dns_packet_append_uint16(p, k->type) || + !avahi_dns_packet_append_uint16(p, k->class | (unicast_response ? AVAHI_DNS_UNICAST_RESPONSE : 0))) { + p->size = size; + return NULL; + } + + return t; +} + +guint8* avahi_dns_packet_append_record(AvahiDnsPacket *p, AvahiRecord *r, gboolean cache_flush, guint max_ttl) { + guint8 *t, *l, *start; + guint size; + + g_assert(p); + g_assert(r); + + size = p->size; + + if (!(t = avahi_dns_packet_append_name(p, r->key->name)) || + !avahi_dns_packet_append_uint16(p, r->key->type) || + !avahi_dns_packet_append_uint16(p, cache_flush ? (r->key->class | AVAHI_DNS_CACHE_FLUSH) : (r->key->class &~ AVAHI_DNS_CACHE_FLUSH)) || + !avahi_dns_packet_append_uint32(p, (max_ttl && r->ttl > max_ttl) ? max_ttl : r->ttl) || + !(l = avahi_dns_packet_append_uint16(p, 0))) + goto fail; + + start = avahi_dns_packet_extend(p, 0); + + switch (r->key->type) { + + case AVAHI_DNS_TYPE_PTR: + case AVAHI_DNS_TYPE_CNAME : + + if (!(avahi_dns_packet_append_name(p, r->data.ptr.name))) + goto fail; + + break; + + case AVAHI_DNS_TYPE_SRV: + + if (!avahi_dns_packet_append_uint16(p, r->data.srv.priority) || + !avahi_dns_packet_append_uint16(p, r->data.srv.weight) || + !avahi_dns_packet_append_uint16(p, r->data.srv.port) || + !avahi_dns_packet_append_name(p, r->data.srv.name)) + goto fail; + + break; + + case AVAHI_DNS_TYPE_HINFO: + if (!avahi_dns_packet_append_string(p, r->data.hinfo.cpu) || + !avahi_dns_packet_append_string(p, r->data.hinfo.os)) + goto fail; + + break; + + case AVAHI_DNS_TYPE_TXT: { + + guint8 *data; + guint size; + + size = avahi_string_list_serialize(r->data.txt.string_list, NULL, 0); + +/* g_message("appending string: %u %p", size, r->data.txt.string_list); */ + + if (!(data = avahi_dns_packet_extend(p, size))) + goto fail; + + avahi_string_list_serialize(r->data.txt.string_list, data, size); + break; + } + + + case AVAHI_DNS_TYPE_A: + + if (!avahi_dns_packet_append_bytes(p, &r->data.a.address, sizeof(r->data.a.address))) + goto fail; + + break; + + case AVAHI_DNS_TYPE_AAAA: + + if (!avahi_dns_packet_append_bytes(p, &r->data.aaaa.address, sizeof(r->data.aaaa.address))) + goto fail; + + break; + + default: + + if (r->data.generic.size && + avahi_dns_packet_append_bytes(p, r->data.generic.data, r->data.generic.size)) + goto fail; + + break; + } + + + + + size = avahi_dns_packet_extend(p, 0) - start; + g_assert(size <= 0xFFFF); + +/* g_message("appended %u", size); */ + + * (guint16*) l = g_htons((guint16) size); + + return t; + + +fail: + p->size = size; + return NULL; +} + +gboolean avahi_dns_packet_is_empty(AvahiDnsPacket *p) { + g_assert(p); + + return p->size <= AVAHI_DNS_PACKET_HEADER_SIZE; +} + +guint avahi_dns_packet_space(AvahiDnsPacket *p) { + g_assert(p); + + g_assert(p->size <= p->max_size); + + return p->max_size - p->size; +} diff --git a/avahi-common/dns.h b/avahi-common/dns.h new file mode 100644 index 0000000..03d9798 --- /dev/null +++ b/avahi-common/dns.h @@ -0,0 +1,105 @@ +#ifndef foodnshfoo +#define foodnshfoo + +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include "rr.h" + +#define AVAHI_DNS_PACKET_MAX_SIZE 9000 +#define AVAHI_DNS_PACKET_HEADER_SIZE 12 +#define AVAHI_DNS_PACKET_EXTRA_SIZE 48 + +typedef struct AvahiDnsPacket { + guint size, rindex, max_size; + GHashTable *name_table; /* for name compression */ +} AvahiDnsPacket; + +#define AVAHI_DNS_PACKET_DATA(p) (((guint8*) p) + sizeof(AvahiDnsPacket)) + +AvahiDnsPacket* avahi_dns_packet_new(guint mtu); +AvahiDnsPacket* avahi_dns_packet_new_query(guint mtu); +AvahiDnsPacket* avahi_dns_packet_new_response(guint mtu, gboolean aa); + +AvahiDnsPacket* avahi_dns_packet_new_reply(AvahiDnsPacket* p, guint mtu, gboolean copy_queries, gboolean aa); + +void avahi_dns_packet_free(AvahiDnsPacket *p); +void avahi_dns_packet_set_field(AvahiDnsPacket *p, guint index, guint16 v); +guint16 avahi_dns_packet_get_field(AvahiDnsPacket *p, guint index); +void avahi_dns_packet_inc_field(AvahiDnsPacket *p, guint index); + +guint8 *avahi_dns_packet_extend(AvahiDnsPacket *p, guint l); + +guint8 *avahi_dns_packet_append_uint16(AvahiDnsPacket *p, guint16 v); +guint8 *avahi_dns_packet_append_uint32(AvahiDnsPacket *p, guint32 v); +guint8 *avahi_dns_packet_append_name(AvahiDnsPacket *p, const gchar *name); +guint8 *avahi_dns_packet_append_bytes(AvahiDnsPacket *p, gconstpointer, guint l); +guint8* avahi_dns_packet_append_key(AvahiDnsPacket *p, AvahiKey *k, gboolean unicast_response); +guint8* avahi_dns_packet_append_record(AvahiDnsPacket *p, AvahiRecord *r, gboolean cache_flush, guint max_ttl); +guint8* avahi_dns_packet_append_string(AvahiDnsPacket *p, const gchar *s); + +gint avahi_dns_packet_is_query(AvahiDnsPacket *p); +gint avahi_dns_packet_check_valid(AvahiDnsPacket *p); + +gint avahi_dns_packet_consume_uint16(AvahiDnsPacket *p, guint16 *ret_v); +gint avahi_dns_packet_consume_uint32(AvahiDnsPacket *p, guint32 *ret_v); +gint avahi_dns_packet_consume_name(AvahiDnsPacket *p, gchar *ret_name, guint l); +gint avahi_dns_packet_consume_bytes(AvahiDnsPacket *p, gpointer ret_data, guint l); +AvahiKey* avahi_dns_packet_consume_key(AvahiDnsPacket *p, gboolean *ret_unicast_response); +AvahiRecord* avahi_dns_packet_consume_record(AvahiDnsPacket *p, gboolean *ret_cache_flush); +gint avahi_dns_packet_consume_string(AvahiDnsPacket *p, gchar *ret_string, guint l); + +gconstpointer avahi_dns_packet_get_rptr(AvahiDnsPacket *p); + +gint avahi_dns_packet_skip(AvahiDnsPacket *p, guint length); + +gboolean avahi_dns_packet_is_empty(AvahiDnsPacket *p); +guint avahi_dns_packet_space(AvahiDnsPacket *p); + +#define AVAHI_DNS_FIELD_ID 0 +#define AVAHI_DNS_FIELD_FLAGS 1 +#define AVAHI_DNS_FIELD_QDCOUNT 2 +#define AVAHI_DNS_FIELD_ANCOUNT 3 +#define AVAHI_DNS_FIELD_NSCOUNT 4 +#define AVAHI_DNS_FIELD_ARCOUNT 5 + +#define AVAHI_DNS_FLAG_QR (1 << 15) +#define AVAHI_DNS_FLAG_OPCODE (15 << 11) +#define AVAHI_DNS_FLAG_RCODE (15) +#define AVAHI_DNS_FLAG_TC (1 << 9) +#define AVAHI_DNS_FLAG_AA (1 << 10) + +#define AVAHI_DNS_FLAGS(qr, opcode, aa, tc, rd, ra, z, ad, cd, rcode) \ + (((guint16) !!qr << 15) | \ + ((guint16) (opcode & 15) << 11) | \ + ((guint16) !!aa << 10) | \ + ((guint16) !!tc << 9) | \ + ((guint16) !!rd << 8) | \ + ((guint16) !!ra << 7) | \ + ((guint16) !!ad << 5) | \ + ((guint16) !!cd << 4) | \ + ((guint16) (rd & 15))) + + +#endif + diff --git a/avahi-common/domain-test.c b/avahi-common/domain-test.c new file mode 100644 index 0000000..240f960 --- /dev/null +++ b/avahi-common/domain-test.c @@ -0,0 +1,48 @@ +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "util.h" + +int main(int argc, char *argv[]) { + gchar *s; + + g_message("host name: %s", s = avahi_get_host_name()); + g_free(s); + + g_message("%s", s = avahi_normalize_name("foo.foo.")); + g_free(s); + + g_message("%s", s = avahi_normalize_name("\\f\\o\\\\o\\..\\f\\ \\o\\o.")); + g_free(s); + + g_message("%i", avahi_domain_equal("\\aaa bbb\\.cccc\\\\.dee.fff.", "aaa\\ bbb\\.cccc\\\\.dee.fff")); + g_message("%i", avahi_domain_equal("\\A", "a")); + + g_message("%i", avahi_domain_equal("a", "aaa")); + + g_message("%u = %u", avahi_domain_hash("\\Aaaab\\\\."), avahi_domain_hash("aaaa\\b\\\\")); + + return 0; +} diff --git a/avahi-common/rr.c b/avahi-common/rr.c new file mode 100644 index 0000000..c7f7d2c --- /dev/null +++ b/avahi-common/rr.c @@ -0,0 +1,551 @@ +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "util.h" +#include "rr.h" +#include "dns.h" + +AvahiKey *avahi_key_new(const gchar *name, guint16 class, guint16 type) { + AvahiKey *k; + g_assert(name); + + k = g_new(AvahiKey, 1); + k->ref = 1; + k->name = avahi_normalize_name(name); + k->class = class; + k->type = type; + +/* g_message("%p %% ref=1", k); */ + + return k; +} + +AvahiKey *avahi_key_ref(AvahiKey *k) { + g_assert(k); + g_assert(k->ref >= 1); + + k->ref++; + +/* g_message("%p ++ ref=%i", k, k->ref); */ + + return k; +} + +void avahi_key_unref(AvahiKey *k) { + g_assert(k); + g_assert(k->ref >= 1); + +/* g_message("%p -- ref=%i", k, k->ref-1); */ + + if ((--k->ref) <= 0) { + g_free(k->name); + g_free(k); + } +} + +AvahiRecord *avahi_record_new(AvahiKey *k) { + AvahiRecord *r; + + g_assert(k); + + r = g_new(AvahiRecord, 1); + r->ref = 1; + r->key = avahi_key_ref(k); + + memset(&r->data, 0, sizeof(r->data)); + + r->ttl = AVAHI_DEFAULT_TTL; + + return r; +} + +AvahiRecord *avahi_record_new_full(const gchar *name, guint16 class, guint16 type) { + AvahiRecord *r; + AvahiKey *k; + + g_assert(name); + + k = avahi_key_new(name, class, type); + r = avahi_record_new(k); + avahi_key_unref(k); + + return r; +} + +AvahiRecord *avahi_record_ref(AvahiRecord *r) { + g_assert(r); + g_assert(r->ref >= 1); + + r->ref++; + return r; +} + +void avahi_record_unref(AvahiRecord *r) { + g_assert(r); + g_assert(r->ref >= 1); + + if ((--r->ref) <= 0) { + switch (r->key->type) { + + case AVAHI_DNS_TYPE_SRV: + g_free(r->data.srv.name); + break; + + case AVAHI_DNS_TYPE_PTR: + case AVAHI_DNS_TYPE_CNAME: + g_free(r->data.ptr.name); + break; + + case AVAHI_DNS_TYPE_HINFO: + g_free(r->data.hinfo.cpu); + g_free(r->data.hinfo.os); + break; + + case AVAHI_DNS_TYPE_TXT: + avahi_string_list_free(r->data.txt.string_list); + break; + + case AVAHI_DNS_TYPE_A: + case AVAHI_DNS_TYPE_AAAA: + break; + + default: + g_free(r->data.generic.data); + } + + avahi_key_unref(r->key); + g_free(r); + } +} + +const gchar *avahi_dns_class_to_string(guint16 class) { + if (class & AVAHI_DNS_CACHE_FLUSH) + return "FLUSH"; + + if (class == AVAHI_DNS_CLASS_IN) + return "IN"; + + return NULL; +} + +const gchar *avahi_dns_type_to_string(guint16 type) { + switch (type) { + case AVAHI_DNS_TYPE_CNAME: + return "CNAME"; + case AVAHI_DNS_TYPE_A: + return "A"; + case AVAHI_DNS_TYPE_AAAA: + return "AAAA"; + case AVAHI_DNS_TYPE_PTR: + return "PTR"; + case AVAHI_DNS_TYPE_HINFO: + return "HINFO"; + case AVAHI_DNS_TYPE_TXT: + return "TXT"; + case AVAHI_DNS_TYPE_SRV: + return "SRV"; + case AVAHI_DNS_TYPE_ANY: + return "ANY"; + default: + return NULL; + } +} + + +gchar *avahi_key_to_string(const AvahiKey *k) { + g_assert(k); + g_assert(k->ref >= 1); + + return g_strdup_printf("%s\t%s\t%s", + k->name, + avahi_dns_class_to_string(k->class), + avahi_dns_type_to_string(k->type)); +} + +gchar *avahi_record_to_string(const AvahiRecord *r) { + gchar *p, *s; + char buf[257], *t = NULL, *d = NULL; + + g_assert(r); + g_assert(r->ref >= 1); + + switch (r->key->type) { + case AVAHI_DNS_TYPE_A: + inet_ntop(AF_INET, &r->data.a.address.address, t = buf, sizeof(buf)); + break; + + case AVAHI_DNS_TYPE_AAAA: + inet_ntop(AF_INET6, &r->data.aaaa.address.address, t = buf, sizeof(buf)); + break; + + case AVAHI_DNS_TYPE_PTR: + case AVAHI_DNS_TYPE_CNAME : + + t = r->data.ptr.name; + break; + + case AVAHI_DNS_TYPE_TXT: + t = d = avahi_string_list_to_string(r->data.txt.string_list); + break; + + case AVAHI_DNS_TYPE_HINFO: + + snprintf(t = buf, sizeof(buf), "\"%s\" \"%s\"", r->data.hinfo.cpu, r->data.hinfo.os); + break; + + case AVAHI_DNS_TYPE_SRV: + + snprintf(t = buf, sizeof(buf), "%u %u %u %s", + r->data.srv.priority, + r->data.srv.weight, + r->data.srv.port, + r->data.srv.name); + + break; + } + + p = avahi_key_to_string(r->key); + s = g_strdup_printf("%s %s ; ttl=%u", p, t ? t : "", r->ttl); + g_free(p); + g_free(d); + + return s; +} + +gboolean avahi_key_equal(const AvahiKey *a, const AvahiKey *b) { + g_assert(a); + g_assert(b); + + if (a == b) + return TRUE; + +/* g_message("equal: %p %p", a, b); */ + + return avahi_domain_equal(a->name, b->name) && + a->type == b->type && + a->class == b->class; +} + +gboolean avahi_key_pattern_match(const AvahiKey *pattern, const AvahiKey *k) { + g_assert(pattern); + g_assert(k); + +/* g_message("equal: %p %p", a, b); */ + + g_assert(!avahi_key_is_pattern(k)); + + if (pattern == k) + return TRUE; + + return avahi_domain_equal(pattern->name, k->name) && + (pattern->type == k->type || pattern->type == AVAHI_DNS_TYPE_ANY) && + pattern->class == k->class; +} + +gboolean avahi_key_is_pattern(const AvahiKey *k) { + g_assert(k); + + return k->type == AVAHI_DNS_TYPE_ANY; +} + + +guint avahi_key_hash(const AvahiKey *k) { + g_assert(k); + + return + avahi_domain_hash(k->name) + + k->type + + k->class; +} + +static gboolean rdata_equal(const AvahiRecord *a, const AvahiRecord *b) { + g_assert(a); + g_assert(b); + g_assert(a->key->type == b->key->type); + +/* t = avahi_record_to_string(a); */ +/* g_message("comparing %s", t); */ +/* g_free(t); */ + +/* t = avahi_record_to_string(b); */ +/* g_message("and %s", t); */ +/* g_free(t); */ + + + switch (a->key->type) { + case AVAHI_DNS_TYPE_SRV: + return + a->data.srv.priority == b->data.srv.priority && + a->data.srv.weight == b->data.srv.weight && + a->data.srv.port == b->data.srv.port && + avahi_domain_equal(a->data.srv.name, b->data.srv.name); + + case AVAHI_DNS_TYPE_PTR: + case AVAHI_DNS_TYPE_CNAME: + return avahi_domain_equal(a->data.ptr.name, b->data.ptr.name); + + case AVAHI_DNS_TYPE_HINFO: + return + !g_utf8_collate(a->data.hinfo.cpu, b->data.hinfo.cpu) && + !g_utf8_collate(a->data.hinfo.os, b->data.hinfo.os); + + case AVAHI_DNS_TYPE_TXT: + return avahi_string_list_equal(a->data.txt.string_list, b->data.txt.string_list); + + case AVAHI_DNS_TYPE_A: + return memcmp(&a->data.a.address, &b->data.a.address, sizeof(AvahiIPv4Address)) == 0; + + case AVAHI_DNS_TYPE_AAAA: + return memcmp(&a->data.aaaa.address, &b->data.aaaa.address, sizeof(AvahiIPv6Address)) == 0; + + default: + return a->data.generic.size == b->data.generic.size && + (a->data.generic.size == 0 || memcmp(a->data.generic.data, b->data.generic.data, a->data.generic.size) == 0); + } + +} + +gboolean avahi_record_equal_no_ttl(const AvahiRecord *a, const AvahiRecord *b) { + g_assert(a); + g_assert(b); + + if (a == b) + return TRUE; + + return + avahi_key_equal(a->key, b->key) && + rdata_equal(a, b); +} + + +AvahiRecord *avahi_record_copy(AvahiRecord *r) { + AvahiRecord *copy; + + copy = g_new(AvahiRecord, 1); + copy->ref = 1; + copy->key = avahi_key_ref(r->key); + copy->ttl = r->ttl; + + switch (r->key->type) { + case AVAHI_DNS_TYPE_PTR: + case AVAHI_DNS_TYPE_CNAME: + copy->data.ptr.name = g_strdup(r->data.ptr.name); + break; + + case AVAHI_DNS_TYPE_SRV: + copy->data.srv.priority = r->data.srv.priority; + copy->data.srv.weight = r->data.srv.weight; + copy->data.srv.port = r->data.srv.port; + copy->data.srv.name = g_strdup(r->data.srv.name); + break; + + case AVAHI_DNS_TYPE_HINFO: + copy->data.hinfo.os = g_strdup(r->data.hinfo.os); + copy->data.hinfo.cpu = g_strdup(r->data.hinfo.cpu); + break; + + case AVAHI_DNS_TYPE_TXT: + copy->data.txt.string_list = avahi_string_list_copy(r->data.txt.string_list); + break; + + case AVAHI_DNS_TYPE_A: + copy->data.a.address = r->data.a.address; + break; + + case AVAHI_DNS_TYPE_AAAA: + copy->data.aaaa.address = r->data.aaaa.address; + break; + + default: + copy->data.generic.data = g_memdup(r->data.generic.data, r->data.generic.size); + copy->data.generic.size = r->data.generic.size; + break; + + } + + return copy; +} + + +guint avahi_key_get_estimate_size(AvahiKey *k) { + g_assert(k); + + return strlen(k->name)+1+4; +} + +guint avahi_record_get_estimate_size(AvahiRecord *r) { + guint n; + g_assert(r); + + n = avahi_key_get_estimate_size(r->key) + 4 + 2; + + switch (r->key->type) { + case AVAHI_DNS_TYPE_PTR: + case AVAHI_DNS_TYPE_CNAME: + n += strlen(r->data.ptr.name) + 1; + break; + + case AVAHI_DNS_TYPE_SRV: + n += 6 + strlen(r->data.srv.name) + 1; + break; + + case AVAHI_DNS_TYPE_HINFO: + n += strlen(r->data.hinfo.os) + 1 + strlen(r->data.hinfo.cpu) + 1; + break; + + case AVAHI_DNS_TYPE_TXT: + n += avahi_string_list_serialize(r->data.txt.string_list, NULL, 0); + break; + + case AVAHI_DNS_TYPE_A: + n += sizeof(AvahiIPv4Address); + break; + + case AVAHI_DNS_TYPE_AAAA: + n += sizeof(AvahiIPv6Address); + break; + + default: + n += r->data.generic.size; + } + + return n; +} + +static gint lexicographical_memcmp(gconstpointer a, size_t al, gconstpointer b, size_t bl) { + size_t c; + gint ret; + + g_assert(a); + g_assert(b); + + c = al < bl ? al : bl; + if ((ret = memcmp(a, b, c))) + return ret; + + if (al == bl) + return 0; + else + return al == c ? 1 : -1; +} + +static gint uint16_cmp(guint16 a, guint16 b) { + return a == b ? 0 : (a < b ? -1 : 1); +} + +gint avahi_record_lexicographical_compare(AvahiRecord *a, AvahiRecord *b) { + gint r; +/* gchar *t1, *t2; */ + + g_assert(a); + g_assert(b); + +/* t1 = avahi_record_to_string(a); */ +/* t2 = avahi_record_to_string(b); */ +/* g_message("lexicocmp: %s %s", t1, t2); */ +/* g_free(t1); */ +/* g_free(t2); */ + + if (a == b) + return 0; + + if ((r = uint16_cmp(a->key->class, b->key->class)) || + (r = uint16_cmp(a->key->type, b->key->type))) + return r; + + switch (a->key->type) { + + case AVAHI_DNS_TYPE_PTR: + case AVAHI_DNS_TYPE_CNAME: + return avahi_binary_domain_cmp(a->data.ptr.name, b->data.ptr.name); + + case AVAHI_DNS_TYPE_SRV: { + if ((r = uint16_cmp(a->data.srv.priority, b->data.srv.priority)) == 0 && + (r = uint16_cmp(a->data.srv.weight, b->data.srv.weight)) == 0 && + (r = uint16_cmp(a->data.srv.port, b->data.srv.port)) == 0) + r = avahi_binary_domain_cmp(a->data.srv.name, b->data.srv.name); + + return r; + } + + case AVAHI_DNS_TYPE_HINFO: { + + if ((r = strcmp(a->data.hinfo.cpu, b->data.hinfo.cpu)) || + (r = strcmp(a->data.hinfo.os, b->data.hinfo.os))) + return r; + + return 0; + + } + + case AVAHI_DNS_TYPE_TXT: { + + guint8 *ma, *mb; + guint asize, bsize; + + ma = g_new(guint8, asize = avahi_string_list_serialize(a->data.txt.string_list, NULL, 0)); + mb = g_new(guint8, bsize = avahi_string_list_serialize(b->data.txt.string_list, NULL, 0)); + avahi_string_list_serialize(a->data.txt.string_list, ma, asize); + avahi_string_list_serialize(b->data.txt.string_list, mb, bsize); + + if (asize && bsize) + r = lexicographical_memcmp(ma, asize, mb, bsize); + else if (asize && !bsize) + r = 1; + else if (!asize && bsize) + r = -1; + else + r = 0; + + g_free(ma); + g_free(mb); + + return r; + } + + case AVAHI_DNS_TYPE_A: + return memcmp(&a->data.a.address, &b->data.a.address, sizeof(AvahiIPv4Address)); + + case AVAHI_DNS_TYPE_AAAA: + return memcmp(&a->data.aaaa.address, &b->data.aaaa.address, sizeof(AvahiIPv6Address)); + + default: + return lexicographical_memcmp(a->data.generic.data, a->data.generic.size, + b->data.generic.data, b->data.generic.size); + } + +} + +gboolean avahi_record_is_goodbye(AvahiRecord *r) { + g_assert(r); + + return r->ttl == 0; +} diff --git a/avahi-common/rr.h b/avahi-common/rr.h new file mode 100644 index 0000000..404cc21 --- /dev/null +++ b/avahi-common/rr.h @@ -0,0 +1,140 @@ +#ifndef foorrhfoo +#define foorrhfoo + +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +#include +#include + +enum { + AVAHI_DNS_TYPE_A = 0x01, + AVAHI_DNS_TYPE_NS = 0x02, + AVAHI_DNS_TYPE_CNAME = 0x05, + AVAHI_DNS_TYPE_SOA = 0x06, + AVAHI_DNS_TYPE_PTR = 0x0C, + AVAHI_DNS_TYPE_HINFO = 0x0D, + AVAHI_DNS_TYPE_MX = 0x0F, + AVAHI_DNS_TYPE_TXT = 0x10, + AVAHI_DNS_TYPE_AAAA = 0x1C, + AVAHI_DNS_TYPE_SRV = 0x21, + AVAHI_DNS_TYPE_ANY = 0xFF +}; + +enum { + AVAHI_DNS_CLASS_IN = 0x01, + AVAHI_DNS_CACHE_FLUSH = 0x8000, + AVAHI_DNS_UNICAST_RESPONSE = 0x8000 +}; + +#define AVAHI_DEFAULT_TTL (120*60) + +typedef struct { + guint ref; + gchar *name; + guint16 class; + guint16 type; +} AvahiKey; + +typedef struct { + guint ref; + AvahiKey *key; + + guint32 ttl; + + union { + struct { + gpointer data; + guint16 size; + } generic; + + struct { + guint16 priority; + guint16 weight; + guint16 port; + gchar *name; + } srv; + + struct { + gchar *name; + } ptr; /* and cname */ + + struct { + gchar *cpu; + gchar *os; + } hinfo; + + struct { + AvahiStringList *string_list; + } txt; + + struct { + AvahiIPv4Address address; + } a; + + struct { + AvahiIPv6Address address; + } aaaa; + + } data; + +} AvahiRecord; + +AvahiKey *avahi_key_new(const gchar *name, guint16 class, guint16 type); +AvahiKey *avahi_key_ref(AvahiKey *k); +void avahi_key_unref(AvahiKey *k); + +gboolean avahi_key_equal(const AvahiKey *a, const AvahiKey *b); /* Treat AVAHI_DNS_CLASS_ANY like any other type */ +gboolean avahi_key_pattern_match(const AvahiKey *pattern, const AvahiKey *k); /* If pattern.type is AVAHI_DNS_CLASS_ANY, k.type is ignored */ + +gboolean avahi_key_is_pattern(const AvahiKey *k); + +guint avahi_key_hash(const AvahiKey *k); + +AvahiRecord *avahi_record_new(AvahiKey *k); +AvahiRecord *avahi_record_new_full(const gchar *name, guint16 class, guint16 type); +AvahiRecord *avahi_record_ref(AvahiRecord *r); +void avahi_record_unref(AvahiRecord *r); + +const gchar *avahi_dns_class_to_string(guint16 class); +const gchar *avahi_dns_type_to_string(guint16 type); + +gchar *avahi_key_to_string(const AvahiKey *k); /* g_free() the result! */ +gchar *avahi_record_to_string(const AvahiRecord *r); /* g_free() the result! */ + +gboolean avahi_record_equal_no_ttl(const AvahiRecord *a, const AvahiRecord *b); + +AvahiRecord *avahi_record_copy(AvahiRecord *r); + +/* returns a maximum estimate for the space that is needed to store + * this key in a DNS packet */ +guint avahi_key_get_estimate_size(AvahiKey *k); + +/* ditto */ +guint avahi_record_get_estimate_size(AvahiRecord *r); + +gint avahi_record_lexicographical_compare(AvahiRecord *a, AvahiRecord *b); + +gboolean avahi_record_is_goodbye(AvahiRecord *r); + +#endif diff --git a/avahi-common/strlst-test.c b/avahi-common/strlst-test.c new file mode 100644 index 0000000..afc13b1 --- /dev/null +++ b/avahi-common/strlst-test.c @@ -0,0 +1,85 @@ +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "strlst.h" + +int main(int argc, char *argv[]) { + gchar *t; + guint8 data[1024]; + AvahiStringList *a = NULL, *b; + guint size, n; + + a = avahi_string_list_new("prefix", "a", "b", NULL); + + a = avahi_string_list_add(a, "start"); + a = avahi_string_list_add(a, "foo"); + a = avahi_string_list_add(a, "bar"); + a = avahi_string_list_add(a, "quux"); + a = avahi_string_list_add_arbitrary(a, (guint8*) "null\0null", 9); + a = avahi_string_list_add(a, "end"); + + t = avahi_string_list_to_string(a); + printf("--%s--\n", t); + g_free(t); + + size = avahi_string_list_serialize(a, data, sizeof(data)); + + printf("%u\n", size); + + for (t = (gchar*) data, n = 0; n < size; n++, t++) { + if (*t <= 32) + printf("(%u)", *t); + else + printf("%c", *t); + } + + printf("\n"); + + b = avahi_string_list_parse(data, size); + + g_assert(avahi_string_list_equal(a, b)); + + t = avahi_string_list_to_string(b); + printf("--%s--\n", t); + g_free(t); + + avahi_string_list_free(b); + + b = avahi_string_list_copy(a); + + g_assert(avahi_string_list_equal(a, b)); + + t = avahi_string_list_to_string(b); + printf("--%s--\n", t); + g_free(t); + + avahi_string_list_free(a); + avahi_string_list_free(b); + + return 0; +} diff --git a/avahi-common/strlst.c b/avahi-common/strlst.c new file mode 100644 index 0000000..866618f --- /dev/null +++ b/avahi-common/strlst.c @@ -0,0 +1,245 @@ +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "strlst.h" + +AvahiStringList *avahi_string_list_add_arbitrary(AvahiStringList *l, const guint8*text, guint size) { + AvahiStringList *n; + + g_assert(text); + + n = g_malloc(sizeof(AvahiStringList) + size); + n->next = l; + memcpy(n->text, text, n->size = size); + + return n; +} + +AvahiStringList *avahi_string_list_add(AvahiStringList *l, const gchar *text) { + g_assert(text); + + return avahi_string_list_add_arbitrary(l, (const guint8*) text, strlen(text)); +} + +AvahiStringList *avahi_string_list_parse(gconstpointer data, guint size) { + AvahiStringList *r = NULL; + const guint8 *c; + g_assert(data); + + c = data; + for (;;) { + guint k; + + if (size < 1) + break; + + k = *(c++); + r = avahi_string_list_add_arbitrary(r, c, k); + c += k; + + size -= 1 + k; + } + + return r; +} + +void avahi_string_list_free(AvahiStringList *l) { + AvahiStringList *n; + + while (l) { + n = l->next; + g_free(l); + l = n; + } +} + +static AvahiStringList* string_list_reverse(AvahiStringList *l) { + AvahiStringList *r = NULL, *n; + + while (l) { + n = l->next; + l->next = r; + r = l; + l = n; + } + + return r; +} + +gchar* avahi_string_list_to_string(AvahiStringList *l) { + AvahiStringList *n; + guint s = 0; + gchar *t, *e; + + l = string_list_reverse(l); + + for (n = l; n; n = n->next) { + if (n != l) + s ++; + + s += n->size+2; + } + + t = e = g_new(gchar, s+1); + + for (n = l; n; n = n->next) { + if (n != l) + *(e++) = ' '; + + *(e++) = '"'; + strncpy(e, (gchar*) n->text, n->size); + e[n->size] = 0; + e = strchr(e, 0); + *(e++) = '"'; + + g_assert(e); + } + + l = string_list_reverse(l); + + *e = 0; + + return t; +} + +guint avahi_string_list_serialize(AvahiStringList *l, gpointer data, guint size) { + guint used = 0; + + if (data) { + guint8 *c; + AvahiStringList *n; + + g_assert(data); + + l = string_list_reverse(l); + c = data; + + for (n = l; n; n = n->next) { + guint k; + if (size < 1) + break; + + k = n->size; + if (k > 255) + k = 255; + + if (k > size-1) + k = size-1; + + *(c++) = k; + memcpy(c, n->text, k); + c += k; + + used += 1+ k; + } + + l = string_list_reverse(l); + } else { + AvahiStringList *n; + + for (n = l; n; n = n->next) { + guint k; + + k = n->size; + if (k > 255) + k = 255; + + used += 1+k; + } + } + + return used; +} + +gboolean avahi_string_list_equal(AvahiStringList *a, AvahiStringList *b) { + + for (;;) { + if (!a && !b) + return TRUE; + + if (!a || !b) + return FALSE; + + if (a->size != b->size) + return FALSE; + + if (a->size != 0 && memcmp(a->text, b->text, a->size) != 0) + return FALSE; + + a = a->next; + b = b->next; + } +} + +AvahiStringList *avahi_string_list_add_many(AvahiStringList *r, ...) { + va_list va; + + va_start(va, r); + r = avahi_string_list_add_many_va(r, va); + va_end(va); + + return r; +} + +AvahiStringList *avahi_string_list_add_many_va(AvahiStringList *r, va_list va) { + const gchar *txt; + + while ((txt = va_arg(va, const gchar*))) + r = avahi_string_list_add(r, txt); + + return r; +} + + +AvahiStringList *avahi_string_list_new(const gchar *txt, ...) { + va_list va; + AvahiStringList *r = NULL; + + if (txt) { + r = avahi_string_list_add(r, txt); + + va_start(va, txt); + r = avahi_string_list_add_many_va(r, va); + va_end(va); + } + + return r; +} + +AvahiStringList *avahi_string_list_new_va(va_list va) { + return avahi_string_list_add_many_va(NULL, va); +} + +AvahiStringList *avahi_string_list_copy(AvahiStringList *l) { + AvahiStringList *r = NULL; + + for (; l; l = l->next) + r = avahi_string_list_add_arbitrary(r, l->text, l->size); + + return string_list_reverse(r); +} diff --git a/avahi-common/strlst.h b/avahi-common/strlst.h new file mode 100644 index 0000000..80dfc2c --- /dev/null +++ b/avahi-common/strlst.h @@ -0,0 +1,53 @@ +#ifndef footxtlisthfoo +#define footxtlisthfoo + +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +typedef struct AvahiStringList { + struct AvahiStringList *next; + guint size; + guint8 text[1]; +} AvahiStringList; + +AvahiStringList *avahi_string_list_new(const gchar *txt, ...); +AvahiStringList *avahi_string_list_new_va(va_list va); + +void avahi_string_list_free(AvahiStringList *l); + +AvahiStringList *avahi_string_list_add(AvahiStringList *l, const gchar *text); +AvahiStringList *avahi_string_list_add_arbitrary(AvahiStringList *l, const guint8 *text, guint size); +AvahiStringList *avahi_string_list_add_many(AvahiStringList *r, ...); +AvahiStringList *avahi_string_list_add_many_va(AvahiStringList *r, va_list va); + +gchar* avahi_string_list_to_string(AvahiStringList *l); + +guint avahi_string_list_serialize(AvahiStringList *l, gpointer data, guint size); +AvahiStringList *avahi_string_list_parse(gconstpointer data, guint size); + +gboolean avahi_string_list_equal(AvahiStringList *a, AvahiStringList *b); + +AvahiStringList *avahi_string_list_copy(AvahiStringList *l); + +#endif + diff --git a/avahi-common/util.c b/avahi-common/util.c new file mode 100644 index 0000000..a41475a --- /dev/null +++ b/avahi-common/util.c @@ -0,0 +1,428 @@ +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" + +gchar *avahi_get_host_name(void) { +#ifdef HOST_NAME_MAX + char t[HOST_NAME_MAX]; +#else + char t[256]; +#endif + gethostname(t, sizeof(t)); + t[sizeof(t)-1] = 0; + return avahi_normalize_name(t); +} + +static gchar *unescape_uneeded(const gchar *src, gchar *ret_dest, size_t size) { + gboolean escaped = FALSE; + + g_assert(src); + g_assert(ret_dest); + g_assert(size > 0); + + for (; *src; src++) { + + if (!escaped && *src == '\\') + escaped = TRUE; + else if (escaped && (*src == '.' || *src == '\\')) { + + if ((size -= 2) <= 1) break; + + *(ret_dest++) = '\\'; + *(ret_dest++) = *src; + escaped = FALSE; + } else { + if (--size <= 1) break; + + *(ret_dest++) = *src; + escaped = FALSE; + } + + } + + *ret_dest = 0; + + return ret_dest; +} + +gchar *avahi_normalize_name(const gchar *s) { + gchar tmp[256]; + gchar *n, *t; + guint l; + g_assert(s); + + unescape_uneeded(s, tmp, sizeof(tmp)); + + n = g_utf8_normalize(tmp, -1, G_NORMALIZE_DEFAULT); + + if ((l = strlen(n)) == 0) { + g_free(n); + return g_strdup("."); + } + + if (n[l-1] == '.') + return n; + + t = g_strdup_printf("%s.", n); + g_free(n); + return t; +} + +gint avahi_timeval_compare(const GTimeVal *a, const GTimeVal *b) { + g_assert(a); + g_assert(b); + + if (a->tv_sec < b->tv_sec) + return -1; + + if (a->tv_sec > b->tv_sec) + return 1; + + if (a->tv_usec < b->tv_usec) + return -1; + + if (a->tv_usec > b->tv_usec) + return 1; + + return 0; +} + +glong avahi_timeval_diff(const GTimeVal *a, const GTimeVal *b) { + g_assert(a); + g_assert(b); + + if (avahi_timeval_compare(a, b) < 0) + return avahi_timeval_diff(b, a); + + return ((glong) a->tv_sec - b->tv_sec)*1000000 + a->tv_usec - b->tv_usec; +} + + +gint avahi_set_cloexec(gint fd) { + gint n; + + g_assert(fd >= 0); + + if ((n = fcntl(fd, F_GETFD)) < 0) + return -1; + + if (n & FD_CLOEXEC) + return 0; + + return fcntl(fd, F_SETFD, n|FD_CLOEXEC); +} + +gint avahi_set_nonblock(gint fd) { + gint n; + + g_assert(fd >= 0); + + if ((n = fcntl(fd, F_GETFL)) < 0) + return -1; + + if (n & O_NONBLOCK) + return 0; + + return fcntl(fd, F_SETFL, n|O_NONBLOCK); +} + +gint avahi_wait_for_write(gint fd) { + fd_set fds; + gint r; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + + if ((r = select(fd+1, NULL, &fds, NULL, NULL)) < 0) { + g_message("select() failed: %s", strerror(errno)); + + return -1; + } + + g_assert(r > 0); + + return 0; +} + +GTimeVal *avahi_elapse_time(GTimeVal *tv, guint msec, guint jitter) { + g_assert(tv); + + g_get_current_time(tv); + + if (msec) + g_time_val_add(tv, msec*1000); + + if (jitter) + g_time_val_add(tv, g_random_int_range(0, jitter) * 1000); + + return tv; +} + +glong avahi_age(const GTimeVal *a) { + GTimeVal now; + + g_assert(a); + + g_get_current_time(&now); + + return avahi_timeval_diff(&now, a); +} + +/* Read the first label from string *name, unescape "\" and write it to dest */ +gchar *avahi_unescape_label(const gchar **name, gchar *dest, guint size) { + guint i = 0; + gchar *d; + + g_assert(dest); + g_assert(size > 0); + g_assert(name); + + if (!**name) + return NULL; + + d = dest; + + for (;;) { + if (i >= size) + return NULL; + + if (**name == '.') { + (*name)++; + break; + } + + if (**name == 0) + break; + + if (**name == '\\') { + (*name) ++; + + if (**name == 0) + break; + } + + *(d++) = *((*name) ++); + i++; + } + + g_assert(i < size); + + *d = 0; + + return dest; +} + +/* Escape "\" and ".", append \0 */ +gchar *avahi_escape_label(const guint8* src, guint src_length, gchar **ret_name, guint *ret_size) { + gchar *r; + + g_assert(src); + g_assert(ret_name); + g_assert(*ret_name); + g_assert(ret_size); + g_assert(*ret_size > 0); + + r = *ret_name; + + while (src_length > 0) { + if (*src == '.' || *src == '\\') { + if (*ret_size < 3) + return NULL; + + *((*ret_name) ++) = '\\'; + (*ret_size) --; + } + + if (*ret_size < 2) + return NULL; + + *((*ret_name)++) = *src; + (*ret_size) --; + + src_length --; + src++; + } + + **ret_name = 0; + + return r; +} + +static gint utf8_strcasecmp(const gchar *a, const gchar *b) { + gchar *ta, *tb; + gint r; + + g_assert(a); + g_assert(b); + + ta = g_utf8_casefold(a, -1); + tb = g_utf8_casefold(b, -1); + r = g_utf8_collate(ta, tb); + g_free(ta); + g_free(tb); + + return r; +} + +gboolean avahi_domain_equal(const gchar *a, const gchar *b) { + g_assert(a); + g_assert(b); + + if (a == b) + return TRUE; + + for (;;) { + gchar ca[65], cb[65], *pa, *pb; + + pa = avahi_unescape_label(&a, ca, sizeof(ca)); + pb = avahi_unescape_label(&b, cb, sizeof(cb)); + + if (!pa && !pb) + return TRUE; + else if ((pa && !pb) || (!pa && pb)) + return FALSE; + + if (utf8_strcasecmp(pa, pb)) + return FALSE; + } + + return TRUE; +} + +gint avahi_binary_domain_cmp(const gchar *a, const gchar *b) { + g_assert(a); + g_assert(b); + + if (a == b) + return 0; + + for (;;) { + gchar ca[65], cb[65], *pa, *pb; + gint r; + + pa = avahi_unescape_label(&a, ca, sizeof(ca)); + pb = avahi_unescape_label(&b, cb, sizeof(cb)); + + if (!pa && !pb) + return 0; + else if (pa && !pb) + return 1; + else if (!pa && pb) + return -1; + + if ((r = strcmp(pa, pb))) + return r; + } +} + +void avahi_hexdump(gconstpointer p, guint size) { + const guint8 *c = p; + g_assert(p); + + printf("Dumping %u bytes from %p:\n", size, p); + + while (size > 0) { + guint i; + + for (i = 0; i < 16; i++) { + if (i < size) + printf("%02x ", c[i]); + else + printf(" "); + } + + for (i = 0; i < 16; i++) { + if (i < size) + printf("%c", c[i] >= 32 && c[i] < 127 ? c[i] : '.'); + else + printf(" "); + } + + printf("\n"); + + c += 16; + + if (size <= 16) + break; + + size -= 16; + } +} + +guint avahi_domain_hash(const gchar *s) { + guint hash = 0; + + for (;;) { + gchar c[65], *n, *m; + + if (!avahi_unescape_label(&s, c, sizeof(c))) + return hash; + + if (!c[0]) + continue; + + n = g_utf8_normalize(c, -1, G_NORMALIZE_DEFAULT); + m = g_utf8_strdown(n, -1); + + hash += g_str_hash(m); + + g_free(m); + g_free(n); + } +} + +gchar *avahi_format_mac_address(const guint8* mac, guint size) { + gchar *r, *t; + guint i; + static const gchar hex[] = "0123456789abcdef"; + + t = r = g_new(gchar, size > 0 ? size*3 : 1); + + if (size <= 0) { + *r = 0; + return r; + } + + for (i = 0; i < size; i++) { + *(t++) = hex[*mac >> 4]; + *(t++) = hex[*mac & 0xF]; + *(t++) = ':'; + + mac++; + } + + *(--t) = 0; + return r; +} diff --git a/avahi-common/util.h b/avahi-common/util.h new file mode 100644 index 0000000..68d367c --- /dev/null +++ b/avahi-common/util.h @@ -0,0 +1,57 @@ +#ifndef fooutilhfoo +#define fooutilhfoo + +/* $Id$ */ + +/*** + This file is part of avahi. + + avahi is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + avahi is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General + Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with avahi; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#include + +gchar *avahi_normalize_name(const gchar *s); /* g_free() the result! */ +gchar *avahi_get_host_name(void); /* g_free() the result! */ + +gint avahi_timeval_compare(const GTimeVal *a, const GTimeVal *b); +glong avahi_timeval_diff(const GTimeVal *a, const GTimeVal *b); + +gint avahi_set_cloexec(gint fd); +gint avahi_set_nonblock(gint fd); +gint avahi_wait_for_write(gint fd); + +GTimeVal *avahi_elapse_time(GTimeVal *tv, guint msec, guint jitter); + +glong avahi_age(const GTimeVal *a); + +gboolean avahi_domain_equal(const gchar *a, const gchar *b); +gint avahi_binary_domain_cmp(const gchar *a, const gchar *b); + +void avahi_hexdump(gconstpointer p, guint size); + +/* Read the first label from the textual domain name *name, unescape + * it and write it to dest, *name is changed to point to the next label*/ +gchar *avahi_unescape_label(const gchar **name, gchar *dest, guint size); + +/* Escape the domain name in *src and write it to *ret_name */ +gchar *avahi_escape_label(const guint8* src, guint src_length, gchar **ret_name, guint *ret_size); + +guint avahi_domain_hash(const gchar *s); + +gchar *avahi_format_mac_address(const guint8* mac, guint size); + +#endif diff --git a/avahi-core.pc.in b/avahi-core.pc.in index 442c867..1dcbb8a 100644 --- a/avahi-core.pc.in +++ b/avahi-core.pc.in @@ -6,5 +6,5 @@ includedir=${prefix}/include Name: avahi-core Description: Avahi Embeddable Multicast DNS Engine Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lavahi-core +Libs: -L${libdir} -lavahi-core -lavahi-common Cflags: -D_REENTRANT -I${includedir} diff --git a/avahi-core/Makefile.am b/avahi-core/Makefile.am index afc958c..b692fcc 100644 --- a/avahi-core/Makefile.am +++ b/avahi-core/Makefile.am @@ -21,30 +21,24 @@ AM_CFLAGS=-I$(top_srcdir) -D_GNU_SOURCE # GLIB 2.0 AM_CFLAGS+=$(GLIB20_CFLAGS) -AM_LDADD=$(GLIB20_LIBS) +AM_LDADD=$(GLIB20_LIBS) ../avahi-common/libavahi-common.la + +AM_CFLAGS+=-I$(top_srcdir)/avahi-common # This cool debug trap works on i386/gcc only AM_CFLAGS+='-DDEBUG_TRAP=__asm__("int $$3")' -avahiincludedir=$(includedir)/avahi-core +avahiincludedir=$(includedir)/avahi-core -avahiinclude_HEADERS = \ - rr.h \ - address.h \ - strlst.h \ - core.h \ - alternative.h +avahiinclude_HEADERS = + core.h lib_LTLIBRARIES = \ libavahi-core.la noinst_PROGRAMS = \ - dns-test \ - domain-test \ prioq-test \ - strlst-test \ avahi-test \ - alternative-test \ conformance-test \ avahi-reflector @@ -53,21 +47,15 @@ libavahi_core_la_SOURCES = \ iface.c iface.h \ netlink.c netlink.h \ server.c server.h \ - address.c address.h \ - util.c util.h \ prioq.c prioq.h \ cache.c cache.h\ - rr.c rr.h \ - dns.c dns.h \ socket.c socket.h \ response-sched.c response-sched.h \ query-sched.c query-sched.h \ probe-sched.c probe-sched.h \ announce.c announce.h \ browse.c browse.h \ - strlst.c strlst.h \ rrlist.c rrlist.h \ - alternative.c alternative.h \ resolve-host-name.c \ resolve-address.c \ browse-domain.c \ @@ -81,39 +69,12 @@ prioq_test_SOURCES = \ prioq_test_CFLAGS = $(AM_CFLAGS) prioq_test_LDADD = $(AM_LDADD) -strlst_test_SOURCES = \ - strlst-test.c \ - strlst.c strlst.h -strlst_test_CFLAGS = $(AM_CFLAGS) -strlst_test_LDADD = $(AM_LDADD) - -domain_test_SOURCES = \ - domain-test.c \ - util.c util.h -domain_test_CFLAGS = $(AM_CFLAGS) -domain_test_LDADD = $(AM_LDADD) - -dns_test_SOURCES = \ - dns-test.c \ - util.c util.h \ - dns.c dns.h \ - rr.c rr.h \ - strlst.c strlst.h -dns_test_CFLAGS = $(AM_CFLAGS) -dns_test_LDADD = $(AM_LDADD) - avahi_test_SOURCES = \ avahi-test.c \ $(libavahi_core_la_SOURCES) avahi_test_CFLAGS = $(AM_CFLAGS) avahi_test_LDADD = $(AM_LDADD) -alternative_test_SOURCES = \ - alternative-test.c \ - alternative.c alternative.h -alternative_test_CFLAGS = $(AM_CFLAGS) -alternative_test_LDADD = $(AM_LDADD) - conformance_test_SOURCES = \ conformance-test.c \ $(libavahi_core_la_SOURCES) diff --git a/avahi-core/address.c b/avahi-core/address.c deleted file mode 100644 index 3484707..0000000 --- a/avahi-core/address.c +++ /dev/null @@ -1,166 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of avahi. - - avahi is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - avahi is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General - Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with avahi; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include "address.h" - -guint avahi_address_get_size(const AvahiAddress *a) { - g_assert(a); - - if (a->family == AF_INET) - return 4; - else if (a->family == AF_INET6) - return 16; - - return 0; -} - -gint avahi_address_cmp(const AvahiAddress *a, const AvahiAddress *b) { - g_assert(a); - g_assert(b); - - if (a->family != b->family) - return -1; - - return memcmp(a->data.data, b->data.data, avahi_address_get_size(a)); -} - -gchar *avahi_address_snprint(char *s, guint length, const AvahiAddress *a) { - g_assert(s); - g_assert(length); - g_assert(a); - return (gchar*) inet_ntop(a->family, a->data.data, s, length); -} - -gchar* avahi_reverse_lookup_name_ipv4(const AvahiIPv4Address *a) { - guint32 n = ntohl(a->address); - g_assert(a); - - return g_strdup_printf("%u.%u.%u.%u.in-addr.arpa", n & 0xFF, (n >> 8) & 0xFF, (n >> 16) & 0xFF, n >> 24); -} - -static gchar *reverse_lookup_name_ipv6(const AvahiIPv6Address *a, const gchar *suffix) { - - return g_strdup_printf("%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%s", - a->address[15] & 0xF, - a->address[15] >> 4, - a->address[14] & 0xF, - a->address[14] >> 4, - a->address[13] & 0xF, - a->address[13] >> 4, - a->address[12] & 0xF, - a->address[12] >> 4, - a->address[11] & 0xF, - a->address[11] >> 4, - a->address[10] & 0xF, - a->address[10] >> 4, - a->address[9] & 0xF, - a->address[9] >> 4, - a->address[8] & 0xF, - a->address[8] >> 4, - a->address[7] & 0xF, - a->address[7] >> 4, - a->address[6] & 0xF, - a->address[6] >> 4, - a->address[5] & 0xF, - a->address[5] >> 4, - a->address[4] & 0xF, - a->address[4] >> 4, - a->address[3] & 0xF, - a->address[3] >> 4, - a->address[2] & 0xF, - a->address[2] >> 4, - a->address[1] & 0xF, - a->address[1] >> 4, - a->address[0] & 0xF, - a->address[0] >> 4, - suffix); -} - -gchar *avahi_reverse_lookup_name_ipv6_arpa(const AvahiIPv6Address *a) { - return reverse_lookup_name_ipv6(a, "ip6.arpa"); -} - -gchar *avahi_reverse_lookup_name_ipv6_int(const AvahiIPv6Address *a) { - return reverse_lookup_name_ipv6(a, "ip6.int"); -} - -AvahiAddress *avahi_address_parse(const char *s, guchar family, AvahiAddress *ret_addr) { - g_assert(ret_addr); - g_assert(s); - - if (inet_pton(family, s, ret_addr->data.data) < 0) - return NULL; - - ret_addr->family = family; - - return ret_addr; -} - -AvahiAddress *avahi_address_from_sockaddr(const struct sockaddr* sa, AvahiAddress *ret_addr) { - g_assert(sa); - g_assert(ret_addr); - - g_assert(sa->sa_family == AF_INET || sa->sa_family == AF_INET6); - - ret_addr->family = sa->sa_family; - - if (sa->sa_family == AF_INET) - memcpy(&ret_addr->data.ipv4, &((struct sockaddr_in*) sa)->sin_addr, sizeof(ret_addr->data.ipv4)); - else - memcpy(&ret_addr->data.ipv6, &((struct sockaddr_in6*) sa)->sin6_addr, sizeof(ret_addr->data.ipv6)); - - return ret_addr; -} - -guint16 avahi_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); -} - -gboolean avahi_address_is_ipv4_in_ipv6(const AvahiAddress *a) { - static const guint8 ipv4_in_ipv6[] = { - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF }; - - g_assert(a); - - if (a->family != AF_INET6) - return FALSE; - - return memcmp(a->data.ipv6.address, ipv4_in_ipv6, sizeof(ipv4_in_ipv6)) == 0; -} - diff --git a/avahi-core/address.h b/avahi-core/address.h deleted file mode 100644 index 22cb74b..0000000 --- a/avahi-core/address.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef fooaddresshfoo -#define fooaddresshfoo - -/* $Id$ */ - -/*** - This file is part of avahi. - - avahi is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - avahi is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General - Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with avahi; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#include -#include - -typedef struct { - guint32 address; -} AvahiIPv4Address; - -typedef struct { - guint8 address[16]; -} AvahiIPv6Address; - -typedef struct { - guchar family; - - union { - AvahiIPv6Address ipv6; - AvahiIPv4Address ipv4; - guint8 data[1]; - } data; -} AvahiAddress; - -guint avahi_address_get_size(const AvahiAddress *a); -gint avahi_address_cmp(const AvahiAddress *a, const AvahiAddress *b); - -gchar *avahi_address_snprint(char *ret_s, guint length, const AvahiAddress *a); - -AvahiAddress *avahi_address_parse(const char *s, guchar family, AvahiAddress *ret_addr); - -AvahiAddress *avahi_address_from_sockaddr(const struct sockaddr* sa, AvahiAddress *ret_addr); -guint16 avahi_port_from_sockaddr(const struct sockaddr* sa); - -gchar* avahi_reverse_lookup_name_ipv4(const AvahiIPv4Address *a); -gchar* avahi_reverse_lookup_name_ipv6_arpa(const AvahiIPv6Address *a); -gchar* avahi_reverse_lookup_name_ipv6_int(const AvahiIPv6Address *a); - -gboolean avahi_address_is_ipv4_in_ipv6(const AvahiAddress *a); - -#endif diff --git a/avahi-core/alternative-test.c b/avahi-core/alternative-test.c deleted file mode 100644 index 9e26d24..0000000 --- a/avahi-core/alternative-test.c +++ /dev/null @@ -1,48 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of avahi. - - avahi is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - avahi is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General - Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with avahi; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "alternative.h" - -int main(int argc, char *argv[]) { - gchar *r = NULL; - gint i, k; - - for (k = 0; k < 2; k++) { - - for (i = 0; i < 20; i++) { - gchar *n; - - n = i == 0 ? g_strdup("gurke") : (k ? avahi_alternative_service_name(r) : avahi_alternative_host_name(r)); - g_free(r); - r = n; - - printf("%s\n", r); - } - } - - g_free(r); -} diff --git a/avahi-core/alternative.c b/avahi-core/alternative.c deleted file mode 100644 index c9a0f48..0000000 --- a/avahi-core/alternative.c +++ /dev/null @@ -1,81 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of avahi. - - avahi is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - avahi is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General - Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with avahi; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "alternative.h" - -gchar * avahi_alternative_host_name(const gchar *s) { - const gchar *p, *e = NULL; - gchar *c, *r; - gint n; - - g_assert(s); - - for (p = s; *p; p++) - if (!isdigit(*p)) - e = p+1; - - if (e && *e) - n = atoi(e)+1; - else - n = 2; - - c = e ? g_strndup(s, e-s) : g_strdup(s); - r = g_strdup_printf("%s%i", c, n); - g_free(c); - - return r; - -} - -gchar *avahi_alternative_service_name(const gchar *s) { - const gchar *e; - g_assert(s); - - if ((e = strstr(s, " #"))) { - const gchar *n, *p; - e += 2; - - while ((n = strstr(e, " #"))) - e = n + 2; - - for (p = e; *p; p++) - if (!isdigit(*p)) { - e = NULL; - break; - } - } - - if (e) { - gchar *r, *c = g_strndup(s, e-s); - r = g_strdup_printf("%s%i", c, atoi(e)+1); - g_free(c); - return r; - } else - return g_strdup_printf("%s #2", s); -} diff --git a/avahi-core/alternative.h b/avahi-core/alternative.h deleted file mode 100644 index 3aed5b2..0000000 --- a/avahi-core/alternative.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef fooalternativehfoo -#define fooalternativehfoo - -/* $Id$ */ - -/*** - This file is part of avahi. - - avahi is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - avahi is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General - Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with avahi; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#include - -/** Find an alternative for the specified host name. If called with an - * original host name, "2" is appended, Afterwards the number is - * increased on each call. (i.e. "foo" becomes "foo2" becomes "foo3" - * and so on.)*/ -gchar *avahi_alternative_host_name(const gchar *s); - -/** Find an alternative for the specified service name. If called with - an original service name, " #2" is appended. Afterwards the number - is increased on each call (i.e. "foo" becomes "foo #2" becomes - "foo #3" and so on.)*/ -gchar *avahi_alternative_service_name(const gchar *s); - -#endif diff --git a/avahi-core/avahi-reflector.c b/avahi-core/avahi-reflector.c index e10c43c..60e19b6 100644 --- a/avahi-core/avahi-reflector.c +++ b/avahi-core/avahi-reflector.c @@ -29,7 +29,6 @@ #include #include -#include int main(int argc, char*argv[]) { AvahiServer *server; diff --git a/avahi-core/avahi-test.c b/avahi-core/avahi-test.c index 269b64c..63c9f08 100644 --- a/avahi-core/avahi-test.c +++ b/avahi-core/avahi-test.c @@ -29,7 +29,6 @@ #include #include -#include static AvahiEntryGroup *group = NULL; static AvahiServer *server = NULL; diff --git a/avahi-core/core.h b/avahi-core/core.h index 961399e..6e8d9dd 100644 --- a/avahi-core/core.h +++ b/avahi-core/core.h @@ -34,8 +34,9 @@ typedef struct AvahiEntry AvahiEntry; /** A group of locally registered DNS RRs */ typedef struct AvahiEntryGroup AvahiEntryGroup; -#include -#include +#include +#include +#include /** States of a server object */ typedef enum { diff --git a/avahi-core/dns-test.c b/avahi-core/dns-test.c deleted file mode 100644 index aa36f2a..0000000 --- a/avahi-core/dns-test.c +++ /dev/null @@ -1,60 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of avahi. - - avahi is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - avahi is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General - Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with avahi; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "dns.h" -#include "util.h" - -int main(int argc, char *argv[]) { - gchar t[256], *a, *b, *c, *d; - AvahiDnsPacket *p; - - p = avahi_dns_packet_new(0); - - avahi_dns_packet_append_name(p, a = "hello.hello.hello.de."); - avahi_dns_packet_append_name(p, b = "this is a test.hello.de."); - avahi_dns_packet_append_name(p, c = "this\\.is\\.a\\.test\\.with\\.dots.hello.de."); - avahi_dns_packet_append_name(p, d = "this\\\\is another\\ \\test.hello.de."); - - avahi_hexdump(AVAHI_DNS_PACKET_DATA(p), p->size); - - avahi_dns_packet_consume_name(p, t, sizeof(t)); - g_message(">%s<", t); - g_assert(avahi_domain_equal(a, t)); - - avahi_dns_packet_consume_name(p, t, sizeof(t)); - g_message(">%s<", t); - g_assert(avahi_domain_equal(b, t)); - - avahi_dns_packet_consume_name(p, t, sizeof(t)); - g_message(">%s<", t); - g_assert(avahi_domain_equal(c, t)); - - avahi_dns_packet_consume_name(p, t, sizeof(t)); - g_message(">%s<", t); - g_assert(avahi_domain_equal(d, t)); - - avahi_dns_packet_free(p); - return 0; -} diff --git a/avahi-core/dns.c b/avahi-core/dns.c deleted file mode 100644 index 9e19c9e..0000000 --- a/avahi-core/dns.c +++ /dev/null @@ -1,744 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of avahi. - - avahi is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - avahi is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General - Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with avahi; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include -#include -#include - -#include "dns.h" -#include "util.h" - -AvahiDnsPacket* avahi_dns_packet_new(guint mtu) { - AvahiDnsPacket *p; - guint max_size; - - if (mtu <= 0) - max_size = AVAHI_DNS_PACKET_MAX_SIZE; - else if (mtu >= AVAHI_DNS_PACKET_EXTRA_SIZE) - max_size = mtu - AVAHI_DNS_PACKET_EXTRA_SIZE; - else - max_size = 0; - - if (max_size < AVAHI_DNS_PACKET_HEADER_SIZE) - max_size = AVAHI_DNS_PACKET_HEADER_SIZE; - - p = g_malloc(sizeof(AvahiDnsPacket) + max_size); - p->size = p->rindex = AVAHI_DNS_PACKET_HEADER_SIZE; - p->max_size = max_size; - p->name_table = NULL; - - memset(AVAHI_DNS_PACKET_DATA(p), 0, p->size); - return p; -} - -AvahiDnsPacket* avahi_dns_packet_new_query(guint mtu) { - AvahiDnsPacket *p; - - p = avahi_dns_packet_new(mtu); - avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_FLAGS, AVAHI_DNS_FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); - return p; -} - -AvahiDnsPacket* avahi_dns_packet_new_response(guint mtu, gboolean aa) { - AvahiDnsPacket *p; - - p = avahi_dns_packet_new(mtu); - avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_FLAGS, AVAHI_DNS_FLAGS(1, 0, aa, 0, 0, 0, 0, 0, 0, 0)); - return p; -} - -AvahiDnsPacket* avahi_dns_packet_new_reply(AvahiDnsPacket* p, guint mtu, gboolean copy_queries, gboolean aa) { - AvahiDnsPacket *r; - g_assert(p); - - r = avahi_dns_packet_new_response(mtu, aa); - - if (copy_queries) { - guint n, saved_rindex; - - saved_rindex = p->rindex; - p->rindex = AVAHI_DNS_PACKET_HEADER_SIZE; - - for (n = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_QDCOUNT); n > 0; n--) { - AvahiKey *k; - gboolean unicast_response; - - if ((k = avahi_dns_packet_consume_key(p, &unicast_response))) { - avahi_dns_packet_append_key(r, k, unicast_response); - avahi_key_unref(k); - } - } - - p->rindex = saved_rindex; - - avahi_dns_packet_set_field(r, AVAHI_DNS_FIELD_QDCOUNT, avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_QDCOUNT)); - } - - avahi_dns_packet_set_field(r, AVAHI_DNS_FIELD_ID, avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_ID)); - - avahi_dns_packet_set_field(r, AVAHI_DNS_FIELD_FLAGS, - (avahi_dns_packet_get_field(r, AVAHI_DNS_FIELD_FLAGS) & ~AVAHI_DNS_FLAG_OPCODE) | - (avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS) & AVAHI_DNS_FLAG_OPCODE)); - - return r; -} - - -void avahi_dns_packet_free(AvahiDnsPacket *p) { - g_assert(p); - - if (p->name_table) - g_hash_table_destroy(p->name_table); - - g_free(p); -} - -void avahi_dns_packet_set_field(AvahiDnsPacket *p, guint index, guint16 v) { - g_assert(p); - g_assert(index < AVAHI_DNS_PACKET_HEADER_SIZE); - - ((guint16*) AVAHI_DNS_PACKET_DATA(p))[index] = g_htons(v); -} - -guint16 avahi_dns_packet_get_field(AvahiDnsPacket *p, guint index) { - g_assert(p); - g_assert(index < AVAHI_DNS_PACKET_HEADER_SIZE); - - return g_ntohs(((guint16*) AVAHI_DNS_PACKET_DATA(p))[index]); -} - -void avahi_dns_packet_inc_field(AvahiDnsPacket *p, guint index) { - g_assert(p); - - avahi_dns_packet_set_field(p, index, avahi_dns_packet_get_field(p, index) + 1); -} - -guint8* avahi_dns_packet_append_name(AvahiDnsPacket *p, const gchar *name) { - guint8 *d, *saved_ptr = NULL; - guint saved_size; - - g_assert(p); - g_assert(name); - - saved_size = p->size; - saved_ptr = avahi_dns_packet_extend(p, 0); - - while (*name) { - guint8* prev; - const gchar *pname; - gchar label[64]; - - /* Check whether we can compress this name. */ - - if (p->name_table && (prev = g_hash_table_lookup(p->name_table, name))) { - guint index; - - g_assert(prev >= AVAHI_DNS_PACKET_DATA(p)); - index = (guint) (prev - AVAHI_DNS_PACKET_DATA(p)); - - g_assert(index < p->size); - - if (index < 0x4000) { - guint16 *t; - if (!(t = (guint16*) avahi_dns_packet_extend(p, sizeof(guint16)))) - return NULL; - - *t = g_htons((0xC000 | index)); - return saved_ptr; - } - } - - pname = name; - - if (!(avahi_unescape_label(&name, label, sizeof(label)))) - goto fail; - - if (!(d = avahi_dns_packet_append_string(p, label))) - goto fail; - - if (!p->name_table) - /* This works only for normalized domain names */ - p->name_table = g_hash_table_new_full((GHashFunc) g_str_hash, (GEqualFunc) g_str_equal, g_free, NULL); - - g_hash_table_insert(p->name_table, g_strdup(pname), d); - } - - if (!(d = avahi_dns_packet_extend(p, 1))) - goto fail; - - *d = 0; - - return saved_ptr; - -fail: - p->size = saved_size; - return NULL; -} - -guint8* avahi_dns_packet_append_uint16(AvahiDnsPacket *p, guint16 v) { - guint8 *d; - g_assert(p); - - if (!(d = avahi_dns_packet_extend(p, sizeof(guint16)))) - return NULL; - - *((guint16*) d) = g_htons(v); - return d; -} - -guint8 *avahi_dns_packet_append_uint32(AvahiDnsPacket *p, guint32 v) { - guint8 *d; - g_assert(p); - - if (!(d = avahi_dns_packet_extend(p, sizeof(guint32)))) - return NULL; - - *((guint32*) d) = g_htonl(v); - - return d; -} - -guint8 *avahi_dns_packet_append_bytes(AvahiDnsPacket *p, gconstpointer b, guint l) { - guint8* d; - - g_assert(p); - g_assert(b); - g_assert(l); - - if (!(d = avahi_dns_packet_extend(p, l))) - return NULL; - - memcpy(d, b, l); - return d; -} - -guint8* avahi_dns_packet_append_string(AvahiDnsPacket *p, const gchar *s) { - guint8* d; - guint k; - - g_assert(p); - g_assert(s); - - if ((k = strlen(s)) >= 255) - k = 255; - - if (!(d = avahi_dns_packet_extend(p, k+1))) - return NULL; - - *d = (guint8) k; - memcpy(d+1, s, k); - - return d; -} - -guint8 *avahi_dns_packet_extend(AvahiDnsPacket *p, guint l) { - guint8 *d; - - g_assert(p); - - if (p->size+l > p->max_size) - return NULL; - - d = AVAHI_DNS_PACKET_DATA(p) + p->size; - p->size += l; - - return d; -} - -gint avahi_dns_packet_check_valid(AvahiDnsPacket *p) { - guint16 flags; - g_assert(p); - - if (p->size < 12) - return -1; - - flags = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS); - - if (flags & AVAHI_DNS_FLAG_OPCODE || flags & AVAHI_DNS_FLAG_RCODE) - return -1; - - return 0; -} - -gint avahi_dns_packet_is_query(AvahiDnsPacket *p) { - g_assert(p); - - return !(avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS) & AVAHI_DNS_FLAG_QR); -} - -static gint consume_labels(AvahiDnsPacket *p, guint index, gchar *ret_name, guint l) { - gint ret = 0; - int compressed = 0; - int first_label = 1; - g_assert(p && ret_name && l); - - for (;;) { - guint8 n; - - if (index+1 > p->size) - return -1; - - n = AVAHI_DNS_PACKET_DATA(p)[index]; - - if (!n) { - index++; - if (!compressed) - ret++; - - if (l < 1) - return -1; - *ret_name = 0; - - return ret; - - } else if (n <= 63) { - /* Uncompressed label */ - index++; - if (!compressed) - ret++; - - if (index + n > p->size) - return -1; - - if ((guint) n + 1 > l) - return -1; - - if (!first_label) { - *(ret_name++) = '.'; - l--; - } else - first_label = 0; - - if (!(avahi_escape_label(AVAHI_DNS_PACKET_DATA(p) + index, n, &ret_name, &l))) - return -1; - - index += n; - - if (!compressed) - ret += n; - } else if ((n & 0xC0) == 0xC0) { - /* Compressed label */ - - if (index+2 > p->size) - return -1; - - index = ((guint) (AVAHI_DNS_PACKET_DATA(p)[index] & ~0xC0)) << 8 | AVAHI_DNS_PACKET_DATA(p)[index+1]; - - if (!compressed) - ret += 2; - - compressed = 1; - } else - return -1; - } -} - -gint avahi_dns_packet_consume_name(AvahiDnsPacket *p, gchar *ret_name, guint l) { - gint r; - - if ((r = consume_labels(p, p->rindex, ret_name, l)) < 0) - return -1; - - p->rindex += r; - return 0; -} - -gint avahi_dns_packet_consume_uint16(AvahiDnsPacket *p, guint16 *ret_v) { - g_assert(p); - g_assert(ret_v); - - if (p->rindex + sizeof(guint16) > p->size) - return -1; - - *ret_v = g_ntohs(*((guint16*) (AVAHI_DNS_PACKET_DATA(p) + p->rindex))); - p->rindex += sizeof(guint16); - - return 0; -} - -gint avahi_dns_packet_consume_uint32(AvahiDnsPacket *p, guint32 *ret_v) { - g_assert(p); - g_assert(ret_v); - - if (p->rindex + sizeof(guint32) > p->size) - return -1; - - *ret_v = g_ntohl(*((guint32*) (AVAHI_DNS_PACKET_DATA(p) + p->rindex))); - p->rindex += sizeof(guint32); - - return 0; -} - -gint avahi_dns_packet_consume_bytes(AvahiDnsPacket *p, gpointer ret_data, guint l) { - g_assert(p); - g_assert(ret_data); - g_assert(l > 0); - - if (p->rindex + l > p->size) - return -1; - - memcpy(ret_data, AVAHI_DNS_PACKET_DATA(p) + p->rindex, l); - p->rindex += l; - - return 0; -} - -gint avahi_dns_packet_consume_string(AvahiDnsPacket *p, gchar *ret_string, guint l) { - guint k; - - g_assert(p); - g_assert(ret_string); - g_assert(l > 0); - - if (p->rindex >= p->size) - return -1; - - k = AVAHI_DNS_PACKET_DATA(p)[p->rindex]; - - if (p->rindex+1+k > p->size) - return -1; - - if (l > k+1) - l = k+1; - - memcpy(ret_string, AVAHI_DNS_PACKET_DATA(p)+p->rindex+1, l-1); - ret_string[l-1] = 0; - - - p->rindex += 1+k; - - return 0; - -} - -gconstpointer avahi_dns_packet_get_rptr(AvahiDnsPacket *p) { - g_assert(p); - - if (p->rindex > p->size) - return NULL; - - return AVAHI_DNS_PACKET_DATA(p) + p->rindex; -} - -gint avahi_dns_packet_skip(AvahiDnsPacket *p, guint length) { - g_assert(p); - - if (p->rindex + length > p->size) - return -1; - - p->rindex += length; - return 0; -} - -AvahiRecord* avahi_dns_packet_consume_record(AvahiDnsPacket *p, gboolean *ret_cache_flush) { - gchar name[257], buf[257]; - guint16 type, class; - guint32 ttl; - guint16 rdlength; - AvahiRecord *r = NULL; - gconstpointer start; - - g_assert(p); - g_assert(ret_cache_flush); - -/* g_message("consume_record()"); */ - - if (avahi_dns_packet_consume_name(p, name, sizeof(name)) < 0 || - avahi_dns_packet_consume_uint16(p, &type) < 0 || - avahi_dns_packet_consume_uint16(p, &class) < 0 || - avahi_dns_packet_consume_uint32(p, &ttl) < 0 || - avahi_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 & AVAHI_DNS_CACHE_FLUSH); - class &= ~AVAHI_DNS_CACHE_FLUSH; - - start = avahi_dns_packet_get_rptr(p); - - r = avahi_record_new_full(name, class, type); - - switch (type) { - case AVAHI_DNS_TYPE_PTR: - case AVAHI_DNS_TYPE_CNAME: - -/* g_message("ptr"); */ - - if (avahi_dns_packet_consume_name(p, buf, sizeof(buf)) < 0) - goto fail; - - r->data.ptr.name = g_strdup(buf); - break; - - - case AVAHI_DNS_TYPE_SRV: - -/* g_message("srv"); */ - - if (avahi_dns_packet_consume_uint16(p, &r->data.srv.priority) < 0 || - avahi_dns_packet_consume_uint16(p, &r->data.srv.weight) < 0 || - avahi_dns_packet_consume_uint16(p, &r->data.srv.port) < 0 || - avahi_dns_packet_consume_name(p, buf, sizeof(buf)) < 0) - goto fail; - - r->data.srv.name = g_strdup(buf); - break; - - case AVAHI_DNS_TYPE_HINFO: - -/* g_message("hinfo"); */ - - if (avahi_dns_packet_consume_string(p, buf, sizeof(buf)) < 0) - goto fail; - - r->data.hinfo.cpu = g_strdup(buf); - - if (avahi_dns_packet_consume_string(p, buf, sizeof(buf)) < 0) - goto fail; - - r->data.hinfo.os = g_strdup(buf); - break; - - case AVAHI_DNS_TYPE_TXT: - -/* g_message("txt"); */ - - if (rdlength > 0) { - r->data.txt.string_list = avahi_string_list_parse(avahi_dns_packet_get_rptr(p), rdlength); - - if (avahi_dns_packet_skip(p, rdlength) < 0) - goto fail; - } else - r->data.txt.string_list = NULL; - - break; - - case AVAHI_DNS_TYPE_A: - -/* g_message("A"); */ - - if (avahi_dns_packet_consume_bytes(p, &r->data.a.address, sizeof(AvahiIPv4Address)) < 0) - goto fail; - - break; - - case AVAHI_DNS_TYPE_AAAA: - -/* g_message("aaaa"); */ - - if (avahi_dns_packet_consume_bytes(p, &r->data.aaaa.address, sizeof(AvahiIPv6Address)) < 0) - goto fail; - - break; - - default: - -/* g_message("generic"); */ - - if (rdlength > 0) { - - r->data.generic.data = g_memdup(avahi_dns_packet_get_rptr(p), rdlength); - - if (avahi_dns_packet_skip(p, rdlength) < 0) - goto fail; - } - - break; - } - -/* g_message("%i == %u ?", (guint8*) avahi_dns_packet_get_rptr(p) - (guint8*) start, rdlength); */ - - /* Check if we read enough data */ - if ((guint8*) avahi_dns_packet_get_rptr(p) - (guint8*) start != rdlength) - goto fail; - - r->ttl = ttl; - - return r; - -fail: - if (r) - avahi_record_unref(r); - - return NULL; -} - -AvahiKey* avahi_dns_packet_consume_key(AvahiDnsPacket *p, gboolean *ret_unicast_response) { - gchar name[256]; - guint16 type, class; - - g_assert(p); - g_assert(ret_unicast_response); - - if (avahi_dns_packet_consume_name(p, name, sizeof(name)) < 0 || - avahi_dns_packet_consume_uint16(p, &type) < 0 || - avahi_dns_packet_consume_uint16(p, &class) < 0) - return NULL; - - *ret_unicast_response = !!(class & AVAHI_DNS_UNICAST_RESPONSE); - class &= ~AVAHI_DNS_UNICAST_RESPONSE; - - return avahi_key_new(name, class, type); -} - -guint8* avahi_dns_packet_append_key(AvahiDnsPacket *p, AvahiKey *k, gboolean unicast_response) { - guint8 *t; - guint size; - - g_assert(p); - g_assert(k); - - size = p->size; - - if (!(t = avahi_dns_packet_append_name(p, k->name)) || - !avahi_dns_packet_append_uint16(p, k->type) || - !avahi_dns_packet_append_uint16(p, k->class | (unicast_response ? AVAHI_DNS_UNICAST_RESPONSE : 0))) { - p->size = size; - return NULL; - } - - return t; -} - -guint8* avahi_dns_packet_append_record(AvahiDnsPacket *p, AvahiRecord *r, gboolean cache_flush, guint max_ttl) { - guint8 *t, *l, *start; - guint size; - - g_assert(p); - g_assert(r); - - size = p->size; - - if (!(t = avahi_dns_packet_append_name(p, r->key->name)) || - !avahi_dns_packet_append_uint16(p, r->key->type) || - !avahi_dns_packet_append_uint16(p, cache_flush ? (r->key->class | AVAHI_DNS_CACHE_FLUSH) : (r->key->class &~ AVAHI_DNS_CACHE_FLUSH)) || - !avahi_dns_packet_append_uint32(p, (max_ttl && r->ttl > max_ttl) ? max_ttl : r->ttl) || - !(l = avahi_dns_packet_append_uint16(p, 0))) - goto fail; - - start = avahi_dns_packet_extend(p, 0); - - switch (r->key->type) { - - case AVAHI_DNS_TYPE_PTR: - case AVAHI_DNS_TYPE_CNAME : - - if (!(avahi_dns_packet_append_name(p, r->data.ptr.name))) - goto fail; - - break; - - case AVAHI_DNS_TYPE_SRV: - - if (!avahi_dns_packet_append_uint16(p, r->data.srv.priority) || - !avahi_dns_packet_append_uint16(p, r->data.srv.weight) || - !avahi_dns_packet_append_uint16(p, r->data.srv.port) || - !avahi_dns_packet_append_name(p, r->data.srv.name)) - goto fail; - - break; - - case AVAHI_DNS_TYPE_HINFO: - if (!avahi_dns_packet_append_string(p, r->data.hinfo.cpu) || - !avahi_dns_packet_append_string(p, r->data.hinfo.os)) - goto fail; - - break; - - case AVAHI_DNS_TYPE_TXT: { - - guint8 *data; - guint size; - - size = avahi_string_list_serialize(r->data.txt.string_list, NULL, 0); - -/* g_message("appending string: %u %p", size, r->data.txt.string_list); */ - - if (!(data = avahi_dns_packet_extend(p, size))) - goto fail; - - avahi_string_list_serialize(r->data.txt.string_list, data, size); - break; - } - - - case AVAHI_DNS_TYPE_A: - - if (!avahi_dns_packet_append_bytes(p, &r->data.a.address, sizeof(r->data.a.address))) - goto fail; - - break; - - case AVAHI_DNS_TYPE_AAAA: - - if (!avahi_dns_packet_append_bytes(p, &r->data.aaaa.address, sizeof(r->data.aaaa.address))) - goto fail; - - break; - - default: - - if (r->data.generic.size && - avahi_dns_packet_append_bytes(p, r->data.generic.data, r->data.generic.size)) - goto fail; - - break; - } - - - - - size = avahi_dns_packet_extend(p, 0) - start; - g_assert(size <= 0xFFFF); - -/* g_message("appended %u", size); */ - - * (guint16*) l = g_htons((guint16) size); - - return t; - - -fail: - p->size = size; - return NULL; -} - -gboolean avahi_dns_packet_is_empty(AvahiDnsPacket *p) { - g_assert(p); - - return p->size <= AVAHI_DNS_PACKET_HEADER_SIZE; -} - -guint avahi_dns_packet_space(AvahiDnsPacket *p) { - g_assert(p); - - g_assert(p->size <= p->max_size); - - return p->max_size - p->size; -} diff --git a/avahi-core/dns.h b/avahi-core/dns.h deleted file mode 100644 index 03d9798..0000000 --- a/avahi-core/dns.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef foodnshfoo -#define foodnshfoo - -/* $Id$ */ - -/*** - This file is part of avahi. - - avahi is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - avahi is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General - Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with avahi; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#include - -#include "rr.h" - -#define AVAHI_DNS_PACKET_MAX_SIZE 9000 -#define AVAHI_DNS_PACKET_HEADER_SIZE 12 -#define AVAHI_DNS_PACKET_EXTRA_SIZE 48 - -typedef struct AvahiDnsPacket { - guint size, rindex, max_size; - GHashTable *name_table; /* for name compression */ -} AvahiDnsPacket; - -#define AVAHI_DNS_PACKET_DATA(p) (((guint8*) p) + sizeof(AvahiDnsPacket)) - -AvahiDnsPacket* avahi_dns_packet_new(guint mtu); -AvahiDnsPacket* avahi_dns_packet_new_query(guint mtu); -AvahiDnsPacket* avahi_dns_packet_new_response(guint mtu, gboolean aa); - -AvahiDnsPacket* avahi_dns_packet_new_reply(AvahiDnsPacket* p, guint mtu, gboolean copy_queries, gboolean aa); - -void avahi_dns_packet_free(AvahiDnsPacket *p); -void avahi_dns_packet_set_field(AvahiDnsPacket *p, guint index, guint16 v); -guint16 avahi_dns_packet_get_field(AvahiDnsPacket *p, guint index); -void avahi_dns_packet_inc_field(AvahiDnsPacket *p, guint index); - -guint8 *avahi_dns_packet_extend(AvahiDnsPacket *p, guint l); - -guint8 *avahi_dns_packet_append_uint16(AvahiDnsPacket *p, guint16 v); -guint8 *avahi_dns_packet_append_uint32(AvahiDnsPacket *p, guint32 v); -guint8 *avahi_dns_packet_append_name(AvahiDnsPacket *p, const gchar *name); -guint8 *avahi_dns_packet_append_bytes(AvahiDnsPacket *p, gconstpointer, guint l); -guint8* avahi_dns_packet_append_key(AvahiDnsPacket *p, AvahiKey *k, gboolean unicast_response); -guint8* avahi_dns_packet_append_record(AvahiDnsPacket *p, AvahiRecord *r, gboolean cache_flush, guint max_ttl); -guint8* avahi_dns_packet_append_string(AvahiDnsPacket *p, const gchar *s); - -gint avahi_dns_packet_is_query(AvahiDnsPacket *p); -gint avahi_dns_packet_check_valid(AvahiDnsPacket *p); - -gint avahi_dns_packet_consume_uint16(AvahiDnsPacket *p, guint16 *ret_v); -gint avahi_dns_packet_consume_uint32(AvahiDnsPacket *p, guint32 *ret_v); -gint avahi_dns_packet_consume_name(AvahiDnsPacket *p, gchar *ret_name, guint l); -gint avahi_dns_packet_consume_bytes(AvahiDnsPacket *p, gpointer ret_data, guint l); -AvahiKey* avahi_dns_packet_consume_key(AvahiDnsPacket *p, gboolean *ret_unicast_response); -AvahiRecord* avahi_dns_packet_consume_record(AvahiDnsPacket *p, gboolean *ret_cache_flush); -gint avahi_dns_packet_consume_string(AvahiDnsPacket *p, gchar *ret_string, guint l); - -gconstpointer avahi_dns_packet_get_rptr(AvahiDnsPacket *p); - -gint avahi_dns_packet_skip(AvahiDnsPacket *p, guint length); - -gboolean avahi_dns_packet_is_empty(AvahiDnsPacket *p); -guint avahi_dns_packet_space(AvahiDnsPacket *p); - -#define AVAHI_DNS_FIELD_ID 0 -#define AVAHI_DNS_FIELD_FLAGS 1 -#define AVAHI_DNS_FIELD_QDCOUNT 2 -#define AVAHI_DNS_FIELD_ANCOUNT 3 -#define AVAHI_DNS_FIELD_NSCOUNT 4 -#define AVAHI_DNS_FIELD_ARCOUNT 5 - -#define AVAHI_DNS_FLAG_QR (1 << 15) -#define AVAHI_DNS_FLAG_OPCODE (15 << 11) -#define AVAHI_DNS_FLAG_RCODE (15) -#define AVAHI_DNS_FLAG_TC (1 << 9) -#define AVAHI_DNS_FLAG_AA (1 << 10) - -#define AVAHI_DNS_FLAGS(qr, opcode, aa, tc, rd, ra, z, ad, cd, rcode) \ - (((guint16) !!qr << 15) | \ - ((guint16) (opcode & 15) << 11) | \ - ((guint16) !!aa << 10) | \ - ((guint16) !!tc << 9) | \ - ((guint16) !!rd << 8) | \ - ((guint16) !!ra << 7) | \ - ((guint16) !!ad << 5) | \ - ((guint16) !!cd << 4) | \ - ((guint16) (rd & 15))) - - -#endif - diff --git a/avahi-core/domain-test.c b/avahi-core/domain-test.c deleted file mode 100644 index 240f960..0000000 --- a/avahi-core/domain-test.c +++ /dev/null @@ -1,48 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of avahi. - - avahi is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - avahi is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General - Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with avahi; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "util.h" - -int main(int argc, char *argv[]) { - gchar *s; - - g_message("host name: %s", s = avahi_get_host_name()); - g_free(s); - - g_message("%s", s = avahi_normalize_name("foo.foo.")); - g_free(s); - - g_message("%s", s = avahi_normalize_name("\\f\\o\\\\o\\..\\f\\ \\o\\o.")); - g_free(s); - - g_message("%i", avahi_domain_equal("\\aaa bbb\\.cccc\\\\.dee.fff.", "aaa\\ bbb\\.cccc\\\\.dee.fff")); - g_message("%i", avahi_domain_equal("\\A", "a")); - - g_message("%i", avahi_domain_equal("a", "aaa")); - - g_message("%u = %u", avahi_domain_hash("\\Aaaab\\\\."), avahi_domain_hash("aaaa\\b\\\\")); - - return 0; -} diff --git a/avahi-core/rr.c b/avahi-core/rr.c deleted file mode 100644 index c7f7d2c..0000000 --- a/avahi-core/rr.c +++ /dev/null @@ -1,551 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of avahi. - - avahi is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - avahi is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General - Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with avahi; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include "util.h" -#include "rr.h" -#include "dns.h" - -AvahiKey *avahi_key_new(const gchar *name, guint16 class, guint16 type) { - AvahiKey *k; - g_assert(name); - - k = g_new(AvahiKey, 1); - k->ref = 1; - k->name = avahi_normalize_name(name); - k->class = class; - k->type = type; - -/* g_message("%p %% ref=1", k); */ - - return k; -} - -AvahiKey *avahi_key_ref(AvahiKey *k) { - g_assert(k); - g_assert(k->ref >= 1); - - k->ref++; - -/* g_message("%p ++ ref=%i", k, k->ref); */ - - return k; -} - -void avahi_key_unref(AvahiKey *k) { - g_assert(k); - g_assert(k->ref >= 1); - -/* g_message("%p -- ref=%i", k, k->ref-1); */ - - if ((--k->ref) <= 0) { - g_free(k->name); - g_free(k); - } -} - -AvahiRecord *avahi_record_new(AvahiKey *k) { - AvahiRecord *r; - - g_assert(k); - - r = g_new(AvahiRecord, 1); - r->ref = 1; - r->key = avahi_key_ref(k); - - memset(&r->data, 0, sizeof(r->data)); - - r->ttl = AVAHI_DEFAULT_TTL; - - return r; -} - -AvahiRecord *avahi_record_new_full(const gchar *name, guint16 class, guint16 type) { - AvahiRecord *r; - AvahiKey *k; - - g_assert(name); - - k = avahi_key_new(name, class, type); - r = avahi_record_new(k); - avahi_key_unref(k); - - return r; -} - -AvahiRecord *avahi_record_ref(AvahiRecord *r) { - g_assert(r); - g_assert(r->ref >= 1); - - r->ref++; - return r; -} - -void avahi_record_unref(AvahiRecord *r) { - g_assert(r); - g_assert(r->ref >= 1); - - if ((--r->ref) <= 0) { - switch (r->key->type) { - - case AVAHI_DNS_TYPE_SRV: - g_free(r->data.srv.name); - break; - - case AVAHI_DNS_TYPE_PTR: - case AVAHI_DNS_TYPE_CNAME: - g_free(r->data.ptr.name); - break; - - case AVAHI_DNS_TYPE_HINFO: - g_free(r->data.hinfo.cpu); - g_free(r->data.hinfo.os); - break; - - case AVAHI_DNS_TYPE_TXT: - avahi_string_list_free(r->data.txt.string_list); - break; - - case AVAHI_DNS_TYPE_A: - case AVAHI_DNS_TYPE_AAAA: - break; - - default: - g_free(r->data.generic.data); - } - - avahi_key_unref(r->key); - g_free(r); - } -} - -const gchar *avahi_dns_class_to_string(guint16 class) { - if (class & AVAHI_DNS_CACHE_FLUSH) - return "FLUSH"; - - if (class == AVAHI_DNS_CLASS_IN) - return "IN"; - - return NULL; -} - -const gchar *avahi_dns_type_to_string(guint16 type) { - switch (type) { - case AVAHI_DNS_TYPE_CNAME: - return "CNAME"; - case AVAHI_DNS_TYPE_A: - return "A"; - case AVAHI_DNS_TYPE_AAAA: - return "AAAA"; - case AVAHI_DNS_TYPE_PTR: - return "PTR"; - case AVAHI_DNS_TYPE_HINFO: - return "HINFO"; - case AVAHI_DNS_TYPE_TXT: - return "TXT"; - case AVAHI_DNS_TYPE_SRV: - return "SRV"; - case AVAHI_DNS_TYPE_ANY: - return "ANY"; - default: - return NULL; - } -} - - -gchar *avahi_key_to_string(const AvahiKey *k) { - g_assert(k); - g_assert(k->ref >= 1); - - return g_strdup_printf("%s\t%s\t%s", - k->name, - avahi_dns_class_to_string(k->class), - avahi_dns_type_to_string(k->type)); -} - -gchar *avahi_record_to_string(const AvahiRecord *r) { - gchar *p, *s; - char buf[257], *t = NULL, *d = NULL; - - g_assert(r); - g_assert(r->ref >= 1); - - switch (r->key->type) { - case AVAHI_DNS_TYPE_A: - inet_ntop(AF_INET, &r->data.a.address.address, t = buf, sizeof(buf)); - break; - - case AVAHI_DNS_TYPE_AAAA: - inet_ntop(AF_INET6, &r->data.aaaa.address.address, t = buf, sizeof(buf)); - break; - - case AVAHI_DNS_TYPE_PTR: - case AVAHI_DNS_TYPE_CNAME : - - t = r->data.ptr.name; - break; - - case AVAHI_DNS_TYPE_TXT: - t = d = avahi_string_list_to_string(r->data.txt.string_list); - break; - - case AVAHI_DNS_TYPE_HINFO: - - snprintf(t = buf, sizeof(buf), "\"%s\" \"%s\"", r->data.hinfo.cpu, r->data.hinfo.os); - break; - - case AVAHI_DNS_TYPE_SRV: - - snprintf(t = buf, sizeof(buf), "%u %u %u %s", - r->data.srv.priority, - r->data.srv.weight, - r->data.srv.port, - r->data.srv.name); - - break; - } - - p = avahi_key_to_string(r->key); - s = g_strdup_printf("%s %s ; ttl=%u", p, t ? t : "", r->ttl); - g_free(p); - g_free(d); - - return s; -} - -gboolean avahi_key_equal(const AvahiKey *a, const AvahiKey *b) { - g_assert(a); - g_assert(b); - - if (a == b) - return TRUE; - -/* g_message("equal: %p %p", a, b); */ - - return avahi_domain_equal(a->name, b->name) && - a->type == b->type && - a->class == b->class; -} - -gboolean avahi_key_pattern_match(const AvahiKey *pattern, const AvahiKey *k) { - g_assert(pattern); - g_assert(k); - -/* g_message("equal: %p %p", a, b); */ - - g_assert(!avahi_key_is_pattern(k)); - - if (pattern == k) - return TRUE; - - return avahi_domain_equal(pattern->name, k->name) && - (pattern->type == k->type || pattern->type == AVAHI_DNS_TYPE_ANY) && - pattern->class == k->class; -} - -gboolean avahi_key_is_pattern(const AvahiKey *k) { - g_assert(k); - - return k->type == AVAHI_DNS_TYPE_ANY; -} - - -guint avahi_key_hash(const AvahiKey *k) { - g_assert(k); - - return - avahi_domain_hash(k->name) + - k->type + - k->class; -} - -static gboolean rdata_equal(const AvahiRecord *a, const AvahiRecord *b) { - g_assert(a); - g_assert(b); - g_assert(a->key->type == b->key->type); - -/* t = avahi_record_to_string(a); */ -/* g_message("comparing %s", t); */ -/* g_free(t); */ - -/* t = avahi_record_to_string(b); */ -/* g_message("and %s", t); */ -/* g_free(t); */ - - - switch (a->key->type) { - case AVAHI_DNS_TYPE_SRV: - return - a->data.srv.priority == b->data.srv.priority && - a->data.srv.weight == b->data.srv.weight && - a->data.srv.port == b->data.srv.port && - avahi_domain_equal(a->data.srv.name, b->data.srv.name); - - case AVAHI_DNS_TYPE_PTR: - case AVAHI_DNS_TYPE_CNAME: - return avahi_domain_equal(a->data.ptr.name, b->data.ptr.name); - - case AVAHI_DNS_TYPE_HINFO: - return - !g_utf8_collate(a->data.hinfo.cpu, b->data.hinfo.cpu) && - !g_utf8_collate(a->data.hinfo.os, b->data.hinfo.os); - - case AVAHI_DNS_TYPE_TXT: - return avahi_string_list_equal(a->data.txt.string_list, b->data.txt.string_list); - - case AVAHI_DNS_TYPE_A: - return memcmp(&a->data.a.address, &b->data.a.address, sizeof(AvahiIPv4Address)) == 0; - - case AVAHI_DNS_TYPE_AAAA: - return memcmp(&a->data.aaaa.address, &b->data.aaaa.address, sizeof(AvahiIPv6Address)) == 0; - - default: - return a->data.generic.size == b->data.generic.size && - (a->data.generic.size == 0 || memcmp(a->data.generic.data, b->data.generic.data, a->data.generic.size) == 0); - } - -} - -gboolean avahi_record_equal_no_ttl(const AvahiRecord *a, const AvahiRecord *b) { - g_assert(a); - g_assert(b); - - if (a == b) - return TRUE; - - return - avahi_key_equal(a->key, b->key) && - rdata_equal(a, b); -} - - -AvahiRecord *avahi_record_copy(AvahiRecord *r) { - AvahiRecord *copy; - - copy = g_new(AvahiRecord, 1); - copy->ref = 1; - copy->key = avahi_key_ref(r->key); - copy->ttl = r->ttl; - - switch (r->key->type) { - case AVAHI_DNS_TYPE_PTR: - case AVAHI_DNS_TYPE_CNAME: - copy->data.ptr.name = g_strdup(r->data.ptr.name); - break; - - case AVAHI_DNS_TYPE_SRV: - copy->data.srv.priority = r->data.srv.priority; - copy->data.srv.weight = r->data.srv.weight; - copy->data.srv.port = r->data.srv.port; - copy->data.srv.name = g_strdup(r->data.srv.name); - break; - - case AVAHI_DNS_TYPE_HINFO: - copy->data.hinfo.os = g_strdup(r->data.hinfo.os); - copy->data.hinfo.cpu = g_strdup(r->data.hinfo.cpu); - break; - - case AVAHI_DNS_TYPE_TXT: - copy->data.txt.string_list = avahi_string_list_copy(r->data.txt.string_list); - break; - - case AVAHI_DNS_TYPE_A: - copy->data.a.address = r->data.a.address; - break; - - case AVAHI_DNS_TYPE_AAAA: - copy->data.aaaa.address = r->data.aaaa.address; - break; - - default: - copy->data.generic.data = g_memdup(r->data.generic.data, r->data.generic.size); - copy->data.generic.size = r->data.generic.size; - break; - - } - - return copy; -} - - -guint avahi_key_get_estimate_size(AvahiKey *k) { - g_assert(k); - - return strlen(k->name)+1+4; -} - -guint avahi_record_get_estimate_size(AvahiRecord *r) { - guint n; - g_assert(r); - - n = avahi_key_get_estimate_size(r->key) + 4 + 2; - - switch (r->key->type) { - case AVAHI_DNS_TYPE_PTR: - case AVAHI_DNS_TYPE_CNAME: - n += strlen(r->data.ptr.name) + 1; - break; - - case AVAHI_DNS_TYPE_SRV: - n += 6 + strlen(r->data.srv.name) + 1; - break; - - case AVAHI_DNS_TYPE_HINFO: - n += strlen(r->data.hinfo.os) + 1 + strlen(r->data.hinfo.cpu) + 1; - break; - - case AVAHI_DNS_TYPE_TXT: - n += avahi_string_list_serialize(r->data.txt.string_list, NULL, 0); - break; - - case AVAHI_DNS_TYPE_A: - n += sizeof(AvahiIPv4Address); - break; - - case AVAHI_DNS_TYPE_AAAA: - n += sizeof(AvahiIPv6Address); - break; - - default: - n += r->data.generic.size; - } - - return n; -} - -static gint lexicographical_memcmp(gconstpointer a, size_t al, gconstpointer b, size_t bl) { - size_t c; - gint ret; - - g_assert(a); - g_assert(b); - - c = al < bl ? al : bl; - if ((ret = memcmp(a, b, c))) - return ret; - - if (al == bl) - return 0; - else - return al == c ? 1 : -1; -} - -static gint uint16_cmp(guint16 a, guint16 b) { - return a == b ? 0 : (a < b ? -1 : 1); -} - -gint avahi_record_lexicographical_compare(AvahiRecord *a, AvahiRecord *b) { - gint r; -/* gchar *t1, *t2; */ - - g_assert(a); - g_assert(b); - -/* t1 = avahi_record_to_string(a); */ -/* t2 = avahi_record_to_string(b); */ -/* g_message("lexicocmp: %s %s", t1, t2); */ -/* g_free(t1); */ -/* g_free(t2); */ - - if (a == b) - return 0; - - if ((r = uint16_cmp(a->key->class, b->key->class)) || - (r = uint16_cmp(a->key->type, b->key->type))) - return r; - - switch (a->key->type) { - - case AVAHI_DNS_TYPE_PTR: - case AVAHI_DNS_TYPE_CNAME: - return avahi_binary_domain_cmp(a->data.ptr.name, b->data.ptr.name); - - case AVAHI_DNS_TYPE_SRV: { - if ((r = uint16_cmp(a->data.srv.priority, b->data.srv.priority)) == 0 && - (r = uint16_cmp(a->data.srv.weight, b->data.srv.weight)) == 0 && - (r = uint16_cmp(a->data.srv.port, b->data.srv.port)) == 0) - r = avahi_binary_domain_cmp(a->data.srv.name, b->data.srv.name); - - return r; - } - - case AVAHI_DNS_TYPE_HINFO: { - - if ((r = strcmp(a->data.hinfo.cpu, b->data.hinfo.cpu)) || - (r = strcmp(a->data.hinfo.os, b->data.hinfo.os))) - return r; - - return 0; - - } - - case AVAHI_DNS_TYPE_TXT: { - - guint8 *ma, *mb; - guint asize, bsize; - - ma = g_new(guint8, asize = avahi_string_list_serialize(a->data.txt.string_list, NULL, 0)); - mb = g_new(guint8, bsize = avahi_string_list_serialize(b->data.txt.string_list, NULL, 0)); - avahi_string_list_serialize(a->data.txt.string_list, ma, asize); - avahi_string_list_serialize(b->data.txt.string_list, mb, bsize); - - if (asize && bsize) - r = lexicographical_memcmp(ma, asize, mb, bsize); - else if (asize && !bsize) - r = 1; - else if (!asize && bsize) - r = -1; - else - r = 0; - - g_free(ma); - g_free(mb); - - return r; - } - - case AVAHI_DNS_TYPE_A: - return memcmp(&a->data.a.address, &b->data.a.address, sizeof(AvahiIPv4Address)); - - case AVAHI_DNS_TYPE_AAAA: - return memcmp(&a->data.aaaa.address, &b->data.aaaa.address, sizeof(AvahiIPv6Address)); - - default: - return lexicographical_memcmp(a->data.generic.data, a->data.generic.size, - b->data.generic.data, b->data.generic.size); - } - -} - -gboolean avahi_record_is_goodbye(AvahiRecord *r) { - g_assert(r); - - return r->ttl == 0; -} diff --git a/avahi-core/rr.h b/avahi-core/rr.h deleted file mode 100644 index c620695..0000000 --- a/avahi-core/rr.h +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef foorrhfoo -#define foorrhfoo - -/* $Id$ */ - -/*** - This file is part of avahi. - - avahi is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - avahi is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General - Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with avahi; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#include - -#include -#include - -enum { - AVAHI_DNS_TYPE_A = 0x01, - AVAHI_DNS_TYPE_NS = 0x02, - AVAHI_DNS_TYPE_CNAME = 0x05, - AVAHI_DNS_TYPE_SOA = 0x06, - AVAHI_DNS_TYPE_PTR = 0x0C, - AVAHI_DNS_TYPE_HINFO = 0x0D, - AVAHI_DNS_TYPE_MX = 0x0F, - AVAHI_DNS_TYPE_TXT = 0x10, - AVAHI_DNS_TYPE_AAAA = 0x1C, - AVAHI_DNS_TYPE_SRV = 0x21, - AVAHI_DNS_TYPE_ANY = 0xFF -}; - -enum { - AVAHI_DNS_CLASS_IN = 0x01, - AVAHI_DNS_CACHE_FLUSH = 0x8000, - AVAHI_DNS_UNICAST_RESPONSE = 0x8000 -}; - -#define AVAHI_DEFAULT_TTL (120*60) - -typedef struct { - guint ref; - gchar *name; - guint16 class; - guint16 type; -} AvahiKey; - -typedef struct { - guint ref; - AvahiKey *key; - - guint32 ttl; - - union { - struct { - gpointer data; - guint16 size; - } generic; - - struct { - guint16 priority; - guint16 weight; - guint16 port; - gchar *name; - } srv; - - struct { - gchar *name; - } ptr; /* and cname */ - - struct { - gchar *cpu; - gchar *os; - } hinfo; - - struct { - AvahiStringList *string_list; - } txt; - - struct { - AvahiIPv4Address address; - } a; - - struct { - AvahiIPv6Address address; - } aaaa; - - } data; - -} AvahiRecord; - -AvahiKey *avahi_key_new(const gchar *name, guint16 class, guint16 type); -AvahiKey *avahi_key_ref(AvahiKey *k); -void avahi_key_unref(AvahiKey *k); - -gboolean avahi_key_equal(const AvahiKey *a, const AvahiKey *b); /* Treat AVAHI_DNS_CLASS_ANY like any other type */ -gboolean avahi_key_pattern_match(const AvahiKey *pattern, const AvahiKey *k); /* If pattern.type is AVAHI_DNS_CLASS_ANY, k.type is ignored */ - -gboolean avahi_key_is_pattern(const AvahiKey *k); - -guint avahi_key_hash(const AvahiKey *k); - -AvahiRecord *avahi_record_new(AvahiKey *k); -AvahiRecord *avahi_record_new_full(const gchar *name, guint16 class, guint16 type); -AvahiRecord *avahi_record_ref(AvahiRecord *r); -void avahi_record_unref(AvahiRecord *r); - -const gchar *avahi_dns_class_to_string(guint16 class); -const gchar *avahi_dns_type_to_string(guint16 type); - -gchar *avahi_key_to_string(const AvahiKey *k); /* g_free() the result! */ -gchar *avahi_record_to_string(const AvahiRecord *r); /* g_free() the result! */ - -gboolean avahi_record_equal_no_ttl(const AvahiRecord *a, const AvahiRecord *b); - -AvahiRecord *avahi_record_copy(AvahiRecord *r); - -/* returns a maximum estimate for the space that is needed to store - * this key in a DNS packet */ -guint avahi_key_get_estimate_size(AvahiKey *k); - -/* ditto */ -guint avahi_record_get_estimate_size(AvahiRecord *r); - -gint avahi_record_lexicographical_compare(AvahiRecord *a, AvahiRecord *b); - -gboolean avahi_record_is_goodbye(AvahiRecord *r); - -#endif diff --git a/avahi-core/strlst-test.c b/avahi-core/strlst-test.c deleted file mode 100644 index afc13b1..0000000 --- a/avahi-core/strlst-test.c +++ /dev/null @@ -1,85 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of avahi. - - avahi is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - avahi is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General - Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with avahi; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "strlst.h" - -int main(int argc, char *argv[]) { - gchar *t; - guint8 data[1024]; - AvahiStringList *a = NULL, *b; - guint size, n; - - a = avahi_string_list_new("prefix", "a", "b", NULL); - - a = avahi_string_list_add(a, "start"); - a = avahi_string_list_add(a, "foo"); - a = avahi_string_list_add(a, "bar"); - a = avahi_string_list_add(a, "quux"); - a = avahi_string_list_add_arbitrary(a, (guint8*) "null\0null", 9); - a = avahi_string_list_add(a, "end"); - - t = avahi_string_list_to_string(a); - printf("--%s--\n", t); - g_free(t); - - size = avahi_string_list_serialize(a, data, sizeof(data)); - - printf("%u\n", size); - - for (t = (gchar*) data, n = 0; n < size; n++, t++) { - if (*t <= 32) - printf("(%u)", *t); - else - printf("%c", *t); - } - - printf("\n"); - - b = avahi_string_list_parse(data, size); - - g_assert(avahi_string_list_equal(a, b)); - - t = avahi_string_list_to_string(b); - printf("--%s--\n", t); - g_free(t); - - avahi_string_list_free(b); - - b = avahi_string_list_copy(a); - - g_assert(avahi_string_list_equal(a, b)); - - t = avahi_string_list_to_string(b); - printf("--%s--\n", t); - g_free(t); - - avahi_string_list_free(a); - avahi_string_list_free(b); - - return 0; -} diff --git a/avahi-core/strlst.c b/avahi-core/strlst.c deleted file mode 100644 index 866618f..0000000 --- a/avahi-core/strlst.c +++ /dev/null @@ -1,245 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of avahi. - - avahi is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - avahi is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General - Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with avahi; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "strlst.h" - -AvahiStringList *avahi_string_list_add_arbitrary(AvahiStringList *l, const guint8*text, guint size) { - AvahiStringList *n; - - g_assert(text); - - n = g_malloc(sizeof(AvahiStringList) + size); - n->next = l; - memcpy(n->text, text, n->size = size); - - return n; -} - -AvahiStringList *avahi_string_list_add(AvahiStringList *l, const gchar *text) { - g_assert(text); - - return avahi_string_list_add_arbitrary(l, (const guint8*) text, strlen(text)); -} - -AvahiStringList *avahi_string_list_parse(gconstpointer data, guint size) { - AvahiStringList *r = NULL; - const guint8 *c; - g_assert(data); - - c = data; - for (;;) { - guint k; - - if (size < 1) - break; - - k = *(c++); - r = avahi_string_list_add_arbitrary(r, c, k); - c += k; - - size -= 1 + k; - } - - return r; -} - -void avahi_string_list_free(AvahiStringList *l) { - AvahiStringList *n; - - while (l) { - n = l->next; - g_free(l); - l = n; - } -} - -static AvahiStringList* string_list_reverse(AvahiStringList *l) { - AvahiStringList *r = NULL, *n; - - while (l) { - n = l->next; - l->next = r; - r = l; - l = n; - } - - return r; -} - -gchar* avahi_string_list_to_string(AvahiStringList *l) { - AvahiStringList *n; - guint s = 0; - gchar *t, *e; - - l = string_list_reverse(l); - - for (n = l; n; n = n->next) { - if (n != l) - s ++; - - s += n->size+2; - } - - t = e = g_new(gchar, s+1); - - for (n = l; n; n = n->next) { - if (n != l) - *(e++) = ' '; - - *(e++) = '"'; - strncpy(e, (gchar*) n->text, n->size); - e[n->size] = 0; - e = strchr(e, 0); - *(e++) = '"'; - - g_assert(e); - } - - l = string_list_reverse(l); - - *e = 0; - - return t; -} - -guint avahi_string_list_serialize(AvahiStringList *l, gpointer data, guint size) { - guint used = 0; - - if (data) { - guint8 *c; - AvahiStringList *n; - - g_assert(data); - - l = string_list_reverse(l); - c = data; - - for (n = l; n; n = n->next) { - guint k; - if (size < 1) - break; - - k = n->size; - if (k > 255) - k = 255; - - if (k > size-1) - k = size-1; - - *(c++) = k; - memcpy(c, n->text, k); - c += k; - - used += 1+ k; - } - - l = string_list_reverse(l); - } else { - AvahiStringList *n; - - for (n = l; n; n = n->next) { - guint k; - - k = n->size; - if (k > 255) - k = 255; - - used += 1+k; - } - } - - return used; -} - -gboolean avahi_string_list_equal(AvahiStringList *a, AvahiStringList *b) { - - for (;;) { - if (!a && !b) - return TRUE; - - if (!a || !b) - return FALSE; - - if (a->size != b->size) - return FALSE; - - if (a->size != 0 && memcmp(a->text, b->text, a->size) != 0) - return FALSE; - - a = a->next; - b = b->next; - } -} - -AvahiStringList *avahi_string_list_add_many(AvahiStringList *r, ...) { - va_list va; - - va_start(va, r); - r = avahi_string_list_add_many_va(r, va); - va_end(va); - - return r; -} - -AvahiStringList *avahi_string_list_add_many_va(AvahiStringList *r, va_list va) { - const gchar *txt; - - while ((txt = va_arg(va, const gchar*))) - r = avahi_string_list_add(r, txt); - - return r; -} - - -AvahiStringList *avahi_string_list_new(const gchar *txt, ...) { - va_list va; - AvahiStringList *r = NULL; - - if (txt) { - r = avahi_string_list_add(r, txt); - - va_start(va, txt); - r = avahi_string_list_add_many_va(r, va); - va_end(va); - } - - return r; -} - -AvahiStringList *avahi_string_list_new_va(va_list va) { - return avahi_string_list_add_many_va(NULL, va); -} - -AvahiStringList *avahi_string_list_copy(AvahiStringList *l) { - AvahiStringList *r = NULL; - - for (; l; l = l->next) - r = avahi_string_list_add_arbitrary(r, l->text, l->size); - - return string_list_reverse(r); -} diff --git a/avahi-core/strlst.h b/avahi-core/strlst.h deleted file mode 100644 index 80dfc2c..0000000 --- a/avahi-core/strlst.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef footxtlisthfoo -#define footxtlisthfoo - -/* $Id$ */ - -/*** - This file is part of avahi. - - avahi is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - avahi is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General - Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with avahi; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#include - -typedef struct AvahiStringList { - struct AvahiStringList *next; - guint size; - guint8 text[1]; -} AvahiStringList; - -AvahiStringList *avahi_string_list_new(const gchar *txt, ...); -AvahiStringList *avahi_string_list_new_va(va_list va); - -void avahi_string_list_free(AvahiStringList *l); - -AvahiStringList *avahi_string_list_add(AvahiStringList *l, const gchar *text); -AvahiStringList *avahi_string_list_add_arbitrary(AvahiStringList *l, const guint8 *text, guint size); -AvahiStringList *avahi_string_list_add_many(AvahiStringList *r, ...); -AvahiStringList *avahi_string_list_add_many_va(AvahiStringList *r, va_list va); - -gchar* avahi_string_list_to_string(AvahiStringList *l); - -guint avahi_string_list_serialize(AvahiStringList *l, gpointer data, guint size); -AvahiStringList *avahi_string_list_parse(gconstpointer data, guint size); - -gboolean avahi_string_list_equal(AvahiStringList *a, AvahiStringList *b); - -AvahiStringList *avahi_string_list_copy(AvahiStringList *l); - -#endif - diff --git a/avahi-core/util.c b/avahi-core/util.c deleted file mode 100644 index a41475a..0000000 --- a/avahi-core/util.c +++ /dev/null @@ -1,428 +0,0 @@ -/* $Id$ */ - -/*** - This file is part of avahi. - - avahi is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - avahi is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General - Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with avahi; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "util.h" - -gchar *avahi_get_host_name(void) { -#ifdef HOST_NAME_MAX - char t[HOST_NAME_MAX]; -#else - char t[256]; -#endif - gethostname(t, sizeof(t)); - t[sizeof(t)-1] = 0; - return avahi_normalize_name(t); -} - -static gchar *unescape_uneeded(const gchar *src, gchar *ret_dest, size_t size) { - gboolean escaped = FALSE; - - g_assert(src); - g_assert(ret_dest); - g_assert(size > 0); - - for (; *src; src++) { - - if (!escaped && *src == '\\') - escaped = TRUE; - else if (escaped && (*src == '.' || *src == '\\')) { - - if ((size -= 2) <= 1) break; - - *(ret_dest++) = '\\'; - *(ret_dest++) = *src; - escaped = FALSE; - } else { - if (--size <= 1) break; - - *(ret_dest++) = *src; - escaped = FALSE; - } - - } - - *ret_dest = 0; - - return ret_dest; -} - -gchar *avahi_normalize_name(const gchar *s) { - gchar tmp[256]; - gchar *n, *t; - guint l; - g_assert(s); - - unescape_uneeded(s, tmp, sizeof(tmp)); - - n = g_utf8_normalize(tmp, -1, G_NORMALIZE_DEFAULT); - - if ((l = strlen(n)) == 0) { - g_free(n); - return g_strdup("."); - } - - if (n[l-1] == '.') - return n; - - t = g_strdup_printf("%s.", n); - g_free(n); - return t; -} - -gint avahi_timeval_compare(const GTimeVal *a, const GTimeVal *b) { - g_assert(a); - g_assert(b); - - if (a->tv_sec < b->tv_sec) - return -1; - - if (a->tv_sec > b->tv_sec) - return 1; - - if (a->tv_usec < b->tv_usec) - return -1; - - if (a->tv_usec > b->tv_usec) - return 1; - - return 0; -} - -glong avahi_timeval_diff(const GTimeVal *a, const GTimeVal *b) { - g_assert(a); - g_assert(b); - - if (avahi_timeval_compare(a, b) < 0) - return avahi_timeval_diff(b, a); - - return ((glong) a->tv_sec - b->tv_sec)*1000000 + a->tv_usec - b->tv_usec; -} - - -gint avahi_set_cloexec(gint fd) { - gint n; - - g_assert(fd >= 0); - - if ((n = fcntl(fd, F_GETFD)) < 0) - return -1; - - if (n & FD_CLOEXEC) - return 0; - - return fcntl(fd, F_SETFD, n|FD_CLOEXEC); -} - -gint avahi_set_nonblock(gint fd) { - gint n; - - g_assert(fd >= 0); - - if ((n = fcntl(fd, F_GETFL)) < 0) - return -1; - - if (n & O_NONBLOCK) - return 0; - - return fcntl(fd, F_SETFL, n|O_NONBLOCK); -} - -gint avahi_wait_for_write(gint fd) { - fd_set fds; - gint r; - - FD_ZERO(&fds); - FD_SET(fd, &fds); - - if ((r = select(fd+1, NULL, &fds, NULL, NULL)) < 0) { - g_message("select() failed: %s", strerror(errno)); - - return -1; - } - - g_assert(r > 0); - - return 0; -} - -GTimeVal *avahi_elapse_time(GTimeVal *tv, guint msec, guint jitter) { - g_assert(tv); - - g_get_current_time(tv); - - if (msec) - g_time_val_add(tv, msec*1000); - - if (jitter) - g_time_val_add(tv, g_random_int_range(0, jitter) * 1000); - - return tv; -} - -glong avahi_age(const GTimeVal *a) { - GTimeVal now; - - g_assert(a); - - g_get_current_time(&now); - - return avahi_timeval_diff(&now, a); -} - -/* Read the first label from string *name, unescape "\" and write it to dest */ -gchar *avahi_unescape_label(const gchar **name, gchar *dest, guint size) { - guint i = 0; - gchar *d; - - g_assert(dest); - g_assert(size > 0); - g_assert(name); - - if (!**name) - return NULL; - - d = dest; - - for (;;) { - if (i >= size) - return NULL; - - if (**name == '.') { - (*name)++; - break; - } - - if (**name == 0) - break; - - if (**name == '\\') { - (*name) ++; - - if (**name == 0) - break; - } - - *(d++) = *((*name) ++); - i++; - } - - g_assert(i < size); - - *d = 0; - - return dest; -} - -/* Escape "\" and ".", append \0 */ -gchar *avahi_escape_label(const guint8* src, guint src_length, gchar **ret_name, guint *ret_size) { - gchar *r; - - g_assert(src); - g_assert(ret_name); - g_assert(*ret_name); - g_assert(ret_size); - g_assert(*ret_size > 0); - - r = *ret_name; - - while (src_length > 0) { - if (*src == '.' || *src == '\\') { - if (*ret_size < 3) - return NULL; - - *((*ret_name) ++) = '\\'; - (*ret_size) --; - } - - if (*ret_size < 2) - return NULL; - - *((*ret_name)++) = *src; - (*ret_size) --; - - src_length --; - src++; - } - - **ret_name = 0; - - return r; -} - -static gint utf8_strcasecmp(const gchar *a, const gchar *b) { - gchar *ta, *tb; - gint r; - - g_assert(a); - g_assert(b); - - ta = g_utf8_casefold(a, -1); - tb = g_utf8_casefold(b, -1); - r = g_utf8_collate(ta, tb); - g_free(ta); - g_free(tb); - - return r; -} - -gboolean avahi_domain_equal(const gchar *a, const gchar *b) { - g_assert(a); - g_assert(b); - - if (a == b) - return TRUE; - - for (;;) { - gchar ca[65], cb[65], *pa, *pb; - - pa = avahi_unescape_label(&a, ca, sizeof(ca)); - pb = avahi_unescape_label(&b, cb, sizeof(cb)); - - if (!pa && !pb) - return TRUE; - else if ((pa && !pb) || (!pa && pb)) - return FALSE; - - if (utf8_strcasecmp(pa, pb)) - return FALSE; - } - - return TRUE; -} - -gint avahi_binary_domain_cmp(const gchar *a, const gchar *b) { - g_assert(a); - g_assert(b); - - if (a == b) - return 0; - - for (;;) { - gchar ca[65], cb[65], *pa, *pb; - gint r; - - pa = avahi_unescape_label(&a, ca, sizeof(ca)); - pb = avahi_unescape_label(&b, cb, sizeof(cb)); - - if (!pa && !pb) - return 0; - else if (pa && !pb) - return 1; - else if (!pa && pb) - return -1; - - if ((r = strcmp(pa, pb))) - return r; - } -} - -void avahi_hexdump(gconstpointer p, guint size) { - const guint8 *c = p; - g_assert(p); - - printf("Dumping %u bytes from %p:\n", size, p); - - while (size > 0) { - guint i; - - for (i = 0; i < 16; i++) { - if (i < size) - printf("%02x ", c[i]); - else - printf(" "); - } - - for (i = 0; i < 16; i++) { - if (i < size) - printf("%c", c[i] >= 32 && c[i] < 127 ? c[i] : '.'); - else - printf(" "); - } - - printf("\n"); - - c += 16; - - if (size <= 16) - break; - - size -= 16; - } -} - -guint avahi_domain_hash(const gchar *s) { - guint hash = 0; - - for (;;) { - gchar c[65], *n, *m; - - if (!avahi_unescape_label(&s, c, sizeof(c))) - return hash; - - if (!c[0]) - continue; - - n = g_utf8_normalize(c, -1, G_NORMALIZE_DEFAULT); - m = g_utf8_strdown(n, -1); - - hash += g_str_hash(m); - - g_free(m); - g_free(n); - } -} - -gchar *avahi_format_mac_address(const guint8* mac, guint size) { - gchar *r, *t; - guint i; - static const gchar hex[] = "0123456789abcdef"; - - t = r = g_new(gchar, size > 0 ? size*3 : 1); - - if (size <= 0) { - *r = 0; - return r; - } - - for (i = 0; i < size; i++) { - *(t++) = hex[*mac >> 4]; - *(t++) = hex[*mac & 0xF]; - *(t++) = ':'; - - mac++; - } - - *(--t) = 0; - return r; -} diff --git a/avahi-core/util.h b/avahi-core/util.h deleted file mode 100644 index 68d367c..0000000 --- a/avahi-core/util.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef fooutilhfoo -#define fooutilhfoo - -/* $Id$ */ - -/*** - This file is part of avahi. - - avahi is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - avahi is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General - Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with avahi; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -***/ - -#include - -gchar *avahi_normalize_name(const gchar *s); /* g_free() the result! */ -gchar *avahi_get_host_name(void); /* g_free() the result! */ - -gint avahi_timeval_compare(const GTimeVal *a, const GTimeVal *b); -glong avahi_timeval_diff(const GTimeVal *a, const GTimeVal *b); - -gint avahi_set_cloexec(gint fd); -gint avahi_set_nonblock(gint fd); -gint avahi_wait_for_write(gint fd); - -GTimeVal *avahi_elapse_time(GTimeVal *tv, guint msec, guint jitter); - -glong avahi_age(const GTimeVal *a); - -gboolean avahi_domain_equal(const gchar *a, const gchar *b); -gint avahi_binary_domain_cmp(const gchar *a, const gchar *b); - -void avahi_hexdump(gconstpointer p, guint size); - -/* Read the first label from the textual domain name *name, unescape - * it and write it to dest, *name is changed to point to the next label*/ -gchar *avahi_unescape_label(const gchar **name, gchar *dest, guint size); - -/* Escape the domain name in *src and write it to *ret_name */ -gchar *avahi_escape_label(const guint8* src, guint src_length, gchar **ret_name, guint *ret_size); - -guint avahi_domain_hash(const gchar *s); - -gchar *avahi_format_mac_address(const guint8* mac, guint size); - -#endif diff --git a/avahi-discover/Makefile.am b/avahi-discover/Makefile.am index 9eca34d..8a5da9a 100644 --- a/avahi-discover/Makefile.am +++ b/avahi-discover/Makefile.am @@ -32,4 +32,4 @@ avahi_discover_SOURCES = \ main.c avahi_discover_CFLAGS = $(AM_CFLAGS) -avahi_discover_LDADD = $(AM_LDADD) ../avahi-core/libavahi-core.la +avahi_discover_LDADD = $(AM_LDADD) ../avahi-core/libavahi-core.la ../avahi-common/libavahi-common.la diff --git a/avahi-discover/main.c b/avahi-discover/main.c index de15a44..997c8a0 100644 --- a/avahi-discover/main.c +++ b/avahi-discover/main.c @@ -3,7 +3,7 @@ #include #include #include -#include +#include struct ServiceType; diff --git a/configure.ac b/configure.ac index ca6a5e0..721be81 100644 --- a/configure.ac +++ b/configure.ac @@ -86,5 +86,5 @@ if test "x$GCC" = "xyes" ; then rm -f conftest.o fi -AC_CONFIG_FILES([Makefile avahi-core.pc doxygen/Makefile doxygen/doxygen.conf avahi-core/Makefile daemon/Makefile avahi-discover/Makefile]) +AC_CONFIG_FILES([Makefile avahi-core.pc doxygen/Makefile doxygen/doxygen.conf avahi-common/Makefile avahi-core/Makefile daemon/Makefile avahi-discover/Makefile]) AC_OUTPUT diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 7f2bc9b..8bf007d 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -37,6 +37,4 @@ avahi_SOURCES = \ main.c avahi_CFLAGS = $(AM_CFLAGS) -avahi_LDADD = $(AM_LDADD) ../avahi-core/libavahi-core.la - - +avahi_LDADD = $(AM_LDADD) ../avahi-core/libavahi-core.la ../avahi-common/libavahi-common.la diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in index cf0e378..28ddd0b 100644 --- a/doxygen/doxygen.conf.in +++ b/doxygen/doxygen.conf.in @@ -417,7 +417,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../avahi-core/core.h ../avahi-core/address.h ../avahi-core/rr.h ../avahi-core/strlst.h ../avahi-core/alternative.h +INPUT = ../avahi-core/core.h ../avahi-common/address.h ../avahi-common/rr.h ../avahi-common/strlst.h ../avahi-common/alternative.h # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -- cgit