dns.c revision 6e9695a1e6a5f6a70195b6de37448aaf9cde8e30
1ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering/* $Id$ */
2ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering
3ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering/***
4ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  This file is part of avahi.
5ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering
6ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  avahi is free software; you can redistribute it and/or modify it
7ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  under the terms of the GNU Lesser General Public License as
8ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  published by the Free Software Foundation; either version 2.1 of the
9ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  License, or (at your option) any later version.
10ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering
11ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  avahi is distributed in the hope that it will be useful, but WITHOUT
12ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  Public License for more details.
15ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering
16ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  You should have received a copy of the GNU Lesser General Public
17ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  License along with avahi; if not, write to the Free Software
18ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  USA.
20ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering***/
21ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering
22eca309458f9521a2e3276dc11a1792d5f2e227e4Lennart Poettering#ifdef HAVE_CONFIG_H
23eca309458f9521a2e3276dc11a1792d5f2e227e4Lennart Poettering#include <config.h>
24eca309458f9521a2e3276dc11a1792d5f2e227e4Lennart Poettering#endif
25eca309458f9521a2e3276dc11a1792d5f2e227e4Lennart Poettering
264ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering#include <stdlib.h>
274ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering#include <string.h>
284ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering#include <stdio.h>
294f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering#include <assert.h>
304ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
31eee711106f721fc73a1ef50348984b7a1d9cb595Sebastien Estienne#include <netinet/in.h>
32eee711106f721fc73a1ef50348984b7a1d9cb595Sebastien Estienne
33f6712902a92eb82b6c8d7e7fd0980a20a716fa0dLennart Poettering#include <avahi-common/defs.h>
345ebf655c85076f200955458673a8bbf0dd927407Lennart Poettering#include <avahi-common/domain.h>
354f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering#include <avahi-common/malloc.h>
364f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering
374ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering#include "dns.h"
384f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering#include "log.h"
394ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
404f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiDnsPacket* avahi_dns_packet_new(unsigned mtu) {
417dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    AvahiDnsPacket *p;
424f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t max_size;
43c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
44602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    if (mtu <= 0)
453073103812f0ea376582eb0ff1479945a847b361Lennart Poettering        max_size = AVAHI_DNS_PACKET_SIZE_MAX;
46b6820898d317c29a31f97018ede6da5195d16bfbLennart Poettering    else if (mtu >= AVAHI_DNS_PACKET_EXTRA_SIZE)
47b6820898d317c29a31f97018ede6da5195d16bfbLennart Poettering        max_size = mtu - AVAHI_DNS_PACKET_EXTRA_SIZE;
48602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    else
49602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        max_size = 0;
50602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
51602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    if (max_size < AVAHI_DNS_PACKET_HEADER_SIZE)
527dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        max_size = AVAHI_DNS_PACKET_HEADER_SIZE;
53c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
544f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(p = avahi_malloc(sizeof(AvahiDnsPacket) + max_size)))
554f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return p;
564f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering
577dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    p->size = p->rindex = AVAHI_DNS_PACKET_HEADER_SIZE;
58c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    p->max_size = max_size;
594ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering    p->name_table = NULL;
60943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p->data = NULL;
61c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
627dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    memset(AVAHI_DNS_PACKET_DATA(p), 0, p->size);
63c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    return p;
64c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering}
65c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
664f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiDnsPacket* avahi_dns_packet_new_query(unsigned mtu) {
677dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    AvahiDnsPacket *p;
68c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
694f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(p = avahi_dns_packet_new(mtu)))
704f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return NULL;
714f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering
727dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_FLAGS, AVAHI_DNS_FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
73c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    return p;
74c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering}
75c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
764f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiDnsPacket* avahi_dns_packet_new_response(unsigned mtu, int aa) {
777dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    AvahiDnsPacket *p;
78c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
794f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(p = avahi_dns_packet_new(mtu)))
804f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return NULL;
814f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering
828d8c0255f0f0242a067b577747740bab1b1021eaLennart Poettering    avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_FLAGS, AVAHI_DNS_FLAGS(1, 0, aa, 0, 0, 0, 0, 0, 0, 0));
834ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return p;
844ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
854ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
864f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiDnsPacket* avahi_dns_packet_new_reply(AvahiDnsPacket* p, unsigned mtu, int copy_queries, int aa) {
87602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    AvahiDnsPacket *r;
884f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
89602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
904f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(r = avahi_dns_packet_new_response(mtu, aa)))
914f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return NULL;
92602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
93602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    if (copy_queries) {
944f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        unsigned saved_rindex;
954f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        uint32_t n;
96602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
97602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        saved_rindex = p->rindex;
98602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        p->rindex = AVAHI_DNS_PACKET_HEADER_SIZE;
99602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
100602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        for (n = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_QDCOUNT); n > 0; n--) {
101602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering            AvahiKey *k;
1024f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            int unicast_response;
103602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
104602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering            if ((k = avahi_dns_packet_consume_key(p, &unicast_response))) {
105602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering                avahi_dns_packet_append_key(r, k, unicast_response);
106602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering                avahi_key_unref(k);
107602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering            }
108602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        }
109602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
110602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        p->rindex = saved_rindex;
111602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
112602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        avahi_dns_packet_set_field(r, AVAHI_DNS_FIELD_QDCOUNT, avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_QDCOUNT));
113602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    }
114602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
115602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    avahi_dns_packet_set_field(r, AVAHI_DNS_FIELD_ID, avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_ID));
116602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
117602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    avahi_dns_packet_set_field(r, AVAHI_DNS_FIELD_FLAGS,
118602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering                               (avahi_dns_packet_get_field(r, AVAHI_DNS_FIELD_FLAGS) & ~AVAHI_DNS_FLAG_OPCODE) |
1198d8c0255f0f0242a067b577747740bab1b1021eaLennart Poettering                               (avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS) & AVAHI_DNS_FLAG_OPCODE));
120602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
121602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    return r;
122602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering}
123602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
124602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
1257dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poetteringvoid avahi_dns_packet_free(AvahiDnsPacket *p) {
1264f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1274ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1284ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering    if (p->name_table)
1294f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        avahi_hashmap_free(p->name_table);
1304ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1314f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    avahi_free(p);
1324ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
1334ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1344f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringvoid avahi_dns_packet_set_field(AvahiDnsPacket *p, unsigned idx, uint16_t v) {
1354f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1364f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(idx < AVAHI_DNS_PACKET_HEADER_SIZE);
1374ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1384f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    ((uint16_t*) AVAHI_DNS_PACKET_DATA(p))[idx] = htons(v);
1394ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
1404ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1414f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint16_t avahi_dns_packet_get_field(AvahiDnsPacket *p, unsigned idx) {
1424f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1434f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(idx < AVAHI_DNS_PACKET_HEADER_SIZE);
1444ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1454f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    return ntohs(((uint16_t*) AVAHI_DNS_PACKET_DATA(p))[idx]);
1464ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
1474ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1484f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringvoid avahi_dns_packet_inc_field(AvahiDnsPacket *p, unsigned idx) {
1494f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1504f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(idx < AVAHI_DNS_PACKET_HEADER_SIZE);
151af1ce5fe2245fba0045d2c0d70b58b700938bd2fLennart Poettering
15266142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering    avahi_dns_packet_set_field(p, idx, avahi_dns_packet_get_field(p, idx) + 1);
153af1ce5fe2245fba0045d2c0d70b58b700938bd2fLennart Poettering}
154af1ce5fe2245fba0045d2c0d70b58b700938bd2fLennart Poettering
1554f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t* avahi_dns_packet_append_name(AvahiDnsPacket *p, const char *name) {
1564f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *d, *saved_ptr = NULL;
1574f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t saved_size;
1584ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1594f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1604f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(name);
1614ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
162c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    saved_size = p->size;
1637dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    saved_ptr = avahi_dns_packet_extend(p, 0);
1644c8155fa9c85c7ece92182d0ab53f99a982a4abfLennart Poettering
1654e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering    while (*name) {
1664f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        uint8_t* prev;
1674f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        const char *pname;
1684f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        char label[64], *u;
1694f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering
1704ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering        /* Check whether we can compress this name. */
1714ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1724f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        if (p->name_table && (prev = avahi_hashmap_lookup(p->name_table, name))) {
1734f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            unsigned idx;
1744ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1754f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            assert(prev >= AVAHI_DNS_PACKET_DATA(p));
1764f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            idx = (unsigned) (prev - AVAHI_DNS_PACKET_DATA(p));
1774ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1784f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            assert(idx < p->size);
1794ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
18066142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            if (idx < 0x4000) {
181973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering                uint8_t *t;
182973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering                if (!(t = (uint8_t*) avahi_dns_packet_extend(p, sizeof(uint16_t))))
1834ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering                    return NULL;
1844ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
185973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering		t[0] = (uint8_t) ((0xC000 | idx) >> 8);
186973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering		t[1] = (uint8_t) idx;
1874c8155fa9c85c7ece92182d0ab53f99a982a4abfLennart Poettering                return saved_ptr;
1884ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering            }
1894ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering        }
1904e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering
1914e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering        pname = name;
1924ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
193a3596a5e3ec4937a220e6e60218639e2aba82701Lennart Poettering        if (!(avahi_unescape_label(&name, label, sizeof(label))))
194c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering            goto fail;
1954ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1967dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        if (!(d = avahi_dns_packet_append_string(p, label)))
1974e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering            goto fail;
1984c8155fa9c85c7ece92182d0ab53f99a982a4abfLennart Poettering
1994ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering        if (!p->name_table)
200a3596a5e3ec4937a220e6e60218639e2aba82701Lennart Poettering            /* This works only for normalized domain names */
2014f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            p->name_table = avahi_hashmap_new(avahi_string_hash, avahi_string_equal, avahi_free, NULL);
2024ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
2034f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        if (!(u = avahi_strdup(pname)))
2044f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            avahi_log_error("avahi_strdup() failed.");
2054f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        else
2064f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            avahi_hashmap_insert(p->name_table, u, d);
2074ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    }
2084ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2097dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (!(d = avahi_dns_packet_extend(p, 1)))
210c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        goto fail;
211c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
2124e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering    *d = 0;
2134ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2144c8155fa9c85c7ece92182d0ab53f99a982a4abfLennart Poettering    return saved_ptr;
215c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
216c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poetteringfail:
217c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    p->size = saved_size;
218c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    return NULL;
2194ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
2204ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2214f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t* avahi_dns_packet_append_uint16(AvahiDnsPacket *p, uint16_t v) {
2224f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *d;
2234f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
2244ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2254f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(d = avahi_dns_packet_extend(p, sizeof(uint16_t))))
226c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        return NULL;
2274ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
228973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d[0] = (uint8_t) (v >> 8);
229973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d[1] = (uint8_t) v;
2304ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return d;
2314ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
2324ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2334f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t *avahi_dns_packet_append_uint32(AvahiDnsPacket *p, uint32_t v) {
2344f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *d;
2354f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
236c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
2374f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(d = avahi_dns_packet_extend(p, sizeof(uint32_t))))
238c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        return NULL;
239c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
240973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d[0] = (uint8_t) (v >> 24);
241973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d[1] = (uint8_t) (v >> 16);
242973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d[2] = (uint8_t) (v >> 8);
243973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d[3] = (uint8_t) v;
24454247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
24554247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering    return d;
24654247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering}
24754247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
2484f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t *avahi_dns_packet_append_bytes(AvahiDnsPacket  *p, const void *b, size_t l) {
2494f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t* d;
25054247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
2514f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
2524f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(b);
2534f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(l);
2544aa744ffac20c7b5e18cb3b23e5dbac8221c0043Lennart Poettering
2557dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (!(d = avahi_dns_packet_extend(p, l)))
256c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        return NULL;
25754247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
258c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    memcpy(d, b, l);
25954247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering    return d;
26054247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering}
26154247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
2624f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t* avahi_dns_packet_append_string(AvahiDnsPacket *p, const char *s) {
2634f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t* d;
2644f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t k;
265a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
2664f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
2674f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(s);
268a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
269a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if ((k = strlen(s)) >= 255)
270a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        k = 255;
271a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
2727dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (!(d = avahi_dns_packet_extend(p, k+1)))
273a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        return NULL;
274a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
2754f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    *d = (uint8_t) k;
276a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    memcpy(d+1, s, k);
277a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
278a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    return d;
279a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering}
280a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
2814f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t *avahi_dns_packet_extend(AvahiDnsPacket *p, size_t l) {
2824f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *d;
2834ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2844f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
2854ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
286c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    if (p->size+l > p->max_size)
287c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        return NULL;
288c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
2897dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    d = AVAHI_DNS_PACKET_DATA(p) + p->size;
2904ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    p->size += l;
2914ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2924ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return d;
2934ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
2944ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2951ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poetteringint avahi_dns_packet_check_valid(AvahiDnsPacket *p) {
2964f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint16_t flags;
2974f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
2984ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2991ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (p->size < AVAHI_DNS_PACKET_HEADER_SIZE)
3004ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
3014ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3027dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    flags = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS);
3031ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
3041ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (flags & AVAHI_DNS_FLAG_OPCODE)
3051ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering        return -1;
3061ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
3071ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    return 0;
3081ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering}
3091ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
3101ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poetteringint avahi_dns_packet_check_valid_multicast(AvahiDnsPacket *p) {
3111ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    uint16_t flags;
3121ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    assert(p);
3134ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3141ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (avahi_dns_packet_check_valid(p) < 0)
3151ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering        return -1;
3161ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
3171ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    flags = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS);
3181ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
3191ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (flags & AVAHI_DNS_FLAG_RCODE)
3204ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
3214ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3224ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
3234ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
3244ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3254f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_is_query(AvahiDnsPacket *p) {
3264f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
3274ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3287dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    return !(avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS) & AVAHI_DNS_FLAG_QR);
3294ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
3304ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3314f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringstatic int consume_labels(AvahiDnsPacket *p, unsigned idx, char *ret_name, size_t l) {
3324f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    int ret = 0;
3334ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    int compressed = 0;
3344ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    int first_label = 1;
3355ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd    unsigned label_ptr;
33683b432c2369d7ef4142811bea0109b6588b6f313Trent Lloyd    int i;
3374f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p && ret_name && l);
3384ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
339451be30b300b390b46738af3fd24fc942ba3158fTrent Lloyd    for (i = 0; i < AVAHI_DNS_LABELS_MAX; i++) {
3404f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        uint8_t n;
3414ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
34266142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering        if (idx+1 > p->size)
3434ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            return -1;
3444ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
34566142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering        n = AVAHI_DNS_PACKET_DATA(p)[idx];
3464ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3474ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        if (!n) {
34866142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            idx++;
3494ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!compressed)
3504ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                ret++;
3514ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3524ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (l < 1)
3534ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                return -1;
3544ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            *ret_name = 0;
3554ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3564ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            return ret;
3574ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3584ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        } else if (n <= 63) {
3594ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            /* Uncompressed label */
36066142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            idx++;
3614ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!compressed)
3624ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                ret++;
3634ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
36466142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            if (idx + n > p->size)
3654ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                return -1;
3664ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3674f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            if ((size_t) n + 1 > l)
3684ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                return -1;
3694ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3704ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!first_label) {
3714ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                *(ret_name++) = '.';
3724ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                l--;
3734ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            } else
3744ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                first_label = 0;
3754ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
376d1dd07145bb3db5c6fd77c55aea762eb79ab3b5cLennart Poettering            if (!(avahi_escape_label((char*) AVAHI_DNS_PACKET_DATA(p) + idx, n, &ret_name, &l)))
3774e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering                return -1;
3784e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering
37966142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            idx += n;
3804ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3814ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!compressed)
3824ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                ret += n;
3834ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        } else if ((n & 0xC0) == 0xC0) {
3844ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            /* Compressed label */
3854ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
38666142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            if (idx+2 > p->size)
3874ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                return -1;
3884ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3895ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd            label_ptr = ((unsigned) (AVAHI_DNS_PACKET_DATA(p)[idx] & ~0xC0)) << 8 | AVAHI_DNS_PACKET_DATA(p)[idx+1];
3905ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd
3915ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd            if ((label_ptr < AVAHI_DNS_PACKET_HEADER_SIZE) || (label_ptr >= idx))
3925ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd                return -1;
3935ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd
3945ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd            idx = label_ptr;
3954ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3964ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!compressed)
3974ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                ret += 2;
3984ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3994ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            compressed = 1;
4004ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        } else
4014ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            return -1;
4024ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    }
4036e9695a1e6a5f6a70195b6de37448aaf9cde8e30Trent Lloyd
4046e9695a1e6a5f6a70195b6de37448aaf9cde8e30Trent Lloyd    return -1;
4054ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
4064ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4074f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_name(AvahiDnsPacket *p, char *ret_name, size_t l) {
4084f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    int r;
4094ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4104ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    if ((r = consume_labels(p, p->rindex, ret_name, l)) < 0)
4114ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
4124ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4134ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    p->rindex += r;
4144ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
4154ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
4164ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4174f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_uint16(AvahiDnsPacket *p, uint16_t *ret_v) {
418973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    uint8_t *d;
419973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering
4204f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
4214f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(ret_v);
4224ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4234f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (p->rindex + sizeof(uint16_t) > p->size)
4244ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
4254ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
426973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d = (uint8_t*) (AVAHI_DNS_PACKET_DATA(p) + p->rindex);
427973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    *ret_v = (d[0] << 8) | d[1];
4284f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    p->rindex += sizeof(uint16_t);
4294ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4304ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
4314ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
4324ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4334f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_uint32(AvahiDnsPacket *p, uint32_t *ret_v) {
434973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    uint8_t* d;
435973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering
4364f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
4374f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(ret_v);
4384ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4394f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (p->rindex + sizeof(uint32_t) > p->size)
4404ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
4414ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
442973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d = (uint8_t*) (AVAHI_DNS_PACKET_DATA(p) + p->rindex);
443973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    *ret_v = (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];
4444f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    p->rindex += sizeof(uint32_t);
4454ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4464ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
4474ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
4484ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4494f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_bytes(AvahiDnsPacket *p, void * ret_data, size_t l) {
4504f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
4514f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(ret_data);
4524f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(l > 0);
4534ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4544ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    if (p->rindex + l > p->size)
4554ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
4564ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4577dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    memcpy(ret_data, AVAHI_DNS_PACKET_DATA(p) + p->rindex, l);
4584ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    p->rindex += l;
4594ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4604ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
4614ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
4624ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4634f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_string(AvahiDnsPacket *p, char *ret_string, size_t l) {
4644f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t k;
465a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
4664f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
4674f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(ret_string);
4684f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(l > 0);
469a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
470a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (p->rindex >= p->size)
471a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        return -1;
472a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
4737dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    k = AVAHI_DNS_PACKET_DATA(p)[p->rindex];
474a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
475a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (p->rindex+1+k > p->size)
476a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        return -1;
477a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
478a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (l > k+1)
479a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        l = k+1;
480a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
4817dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    memcpy(ret_string, AVAHI_DNS_PACKET_DATA(p)+p->rindex+1, l-1);
482a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    ret_string[l-1] = 0;
483a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
484a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    p->rindex += 1+k;
485a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
486a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    return 0;
487a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering}
488a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
4894f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringconst void* avahi_dns_packet_get_rptr(AvahiDnsPacket *p) {
4904f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
491f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
492a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (p->rindex > p->size)
493f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering        return NULL;
494f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
4957dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    return AVAHI_DNS_PACKET_DATA(p) + p->rindex;
496f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
497f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
4984f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_skip(AvahiDnsPacket *p, size_t length) {
4994f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
5004ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
5014ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    if (p->rindex + length > p->size)
5024ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
5034ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
5044ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    p->rindex += length;
5054ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
5064ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
507f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
508943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poetteringstatic int parse_rdata(AvahiDnsPacket *p, AvahiRecord *r, uint16_t rdlength) {
509943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    char buf[AVAHI_DOMAIN_NAME_MAX];
5104f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    const void* start;
511943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
5124f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
513943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(r);
514f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
5157dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    start = avahi_dns_packet_get_rptr(p);
516943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
517943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    switch (r->key->type) {
5187dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_PTR:
5197dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_CNAME:
520d1dd07145bb3db5c6fd77c55aea762eb79ab3b5cLennart Poettering        case AVAHI_DNS_TYPE_NS:
521a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5227dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_name(p, buf, sizeof(buf)) < 0)
523943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
524a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5254f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            r->data.ptr.name = avahi_strdup(buf);
526a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
527a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
528c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
5297dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_SRV:
530a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5317dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_uint16(p, &r->data.srv.priority) < 0 ||
5327dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                avahi_dns_packet_consume_uint16(p, &r->data.srv.weight) < 0 ||
5337dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                avahi_dns_packet_consume_uint16(p, &r->data.srv.port) < 0 ||
5347dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                avahi_dns_packet_consume_name(p, buf, sizeof(buf)) < 0)
535943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
536a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5374f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            r->data.srv.name = avahi_strdup(buf);
538a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
539a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5407dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_HINFO:
541a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5427dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_string(p, buf, sizeof(buf)) < 0)
543943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
544943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
5454f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            r->data.hinfo.cpu = avahi_strdup(buf);
546943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
5477dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_string(p, buf, sizeof(buf)) < 0)
548943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
549943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
5504f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            r->data.hinfo.os = avahi_strdup(buf);
551c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
552c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
5537dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_TXT:
554a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
555a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            if (rdlength > 0) {
55620011324500a728851e4888c890a756ecf71394bLennart Poettering                if (avahi_string_list_parse(avahi_dns_packet_get_rptr(p), rdlength, &r->data.txt.string_list) < 0)
55720011324500a728851e4888c890a756ecf71394bLennart Poettering                    return -1;
558a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5597dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                if (avahi_dns_packet_skip(p, rdlength) < 0)
560943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                    return -1;
561fc174c871b4f85e558766c1ca55661fa7b1b4c9aLennart Poettering            } else
562fc174c871b4f85e558766c1ca55661fa7b1b4c9aLennart Poettering                r->data.txt.string_list = NULL;
563c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
564a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
565a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5667dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_A:
567a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
568c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*             avahi_log_debug("A"); */
569c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
5707dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_bytes(p, &r->data.a.address, sizeof(AvahiIPv4Address)) < 0)
571943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
572a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
573a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
574a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5757dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_AAAA:
576a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
577c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*             avahi_log_debug("aaaa"); */
578a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5797dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_bytes(p, &r->data.aaaa.address, sizeof(AvahiIPv6Address)) < 0)
580943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
581a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
582c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
583c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
584c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering        default:
5854aa744ffac20c7b5e18cb3b23e5dbac8221c0043Lennart Poettering
586c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*             avahi_log_debug("generic"); */
587a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5884aa744ffac20c7b5e18cb3b23e5dbac8221c0043Lennart Poettering            if (rdlength > 0) {
5894aa744ffac20c7b5e18cb3b23e5dbac8221c0043Lennart Poettering
5904f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering                r->data.generic.data = avahi_memdup(avahi_dns_packet_get_rptr(p), rdlength);
591a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5927dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                if (avahi_dns_packet_skip(p, rdlength) < 0)
593943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                    return -1;
594a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            }
595c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
596c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
597c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering    }
598c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
599a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    /* Check if we read enough data */
6004f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if ((const uint8_t*) avahi_dns_packet_get_rptr(p) - (const uint8_t*) start != rdlength)
601943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        return -1;
602943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
603943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    return 0;
604943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering}
605943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
606943a6b93697fc0a7bcd0cc574744d7de609c189cLennart PoetteringAvahiRecord* avahi_dns_packet_consume_record(AvahiDnsPacket *p, int *ret_cache_flush) {
607943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    char name[AVAHI_DOMAIN_NAME_MAX];
608943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    uint16_t type, class;
609943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    uint32_t ttl;
610943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    uint16_t rdlength;
611943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    AvahiRecord *r = NULL;
612943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
613943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(p);
614943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
615943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (avahi_dns_packet_consume_name(p, name, sizeof(name)) < 0 ||
616943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        avahi_dns_packet_consume_uint16(p, &type) < 0 ||
617943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        avahi_dns_packet_consume_uint16(p, &class) < 0 ||
618943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        avahi_dns_packet_consume_uint32(p, &ttl) < 0 ||
619943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        avahi_dns_packet_consume_uint16(p, &rdlength) < 0 ||
620943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        p->rindex + rdlength > p->size)
621a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        goto fail;
622a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
623943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (ret_cache_flush)
624943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        *ret_cache_flush = !!(class & AVAHI_DNS_CACHE_FLUSH);
625943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    class &= ~AVAHI_DNS_CACHE_FLUSH;
626943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
627943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (!(r = avahi_record_new_full(name, class, type, ttl)))
628943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        goto fail;
629943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
630943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (parse_rdata(p, r, rdlength) < 0)
631943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        goto fail;
6327e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering
6337e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering    if (!avahi_record_is_valid(r))
6347e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering        goto fail;
635943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
636a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    return r;
637a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
638a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poetteringfail:
639a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (r)
6407dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        avahi_record_unref(r);
641a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
642a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    return NULL;
643f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
644f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6454f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiKey* avahi_dns_packet_consume_key(AvahiDnsPacket *p, int *ret_unicast_response) {
6464f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    char name[256];
6474f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint16_t type, class;
6487e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering    AvahiKey *k;
649f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6504f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
651f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6527dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (avahi_dns_packet_consume_name(p, name, sizeof(name)) < 0 ||
6537dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        avahi_dns_packet_consume_uint16(p, &type) < 0 ||
6547dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        avahi_dns_packet_consume_uint16(p, &class) < 0)
655f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering        return NULL;
656f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6571ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (ret_unicast_response)
6581ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering        *ret_unicast_response = !!(class & AVAHI_DNS_UNICAST_RESPONSE);
659f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6601ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    class &= ~AVAHI_DNS_UNICAST_RESPONSE;
6611ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
6627e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering    if (!(k = avahi_key_new(name, class, type)))
6637e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering        return NULL;
6647e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering
6657e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering    if (!avahi_key_is_valid(k)) {
6667e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering        avahi_key_unref(k);
6677e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering        return NULL;
6687e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering    }
6697e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering
6707e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering    return k;
671f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
672f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6734f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t* avahi_dns_packet_append_key(AvahiDnsPacket *p, AvahiKey *k, int unicast_response) {
6744f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *t;
6754f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t size;
676f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6774f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
6784f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(k);
679f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
680d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering    size = p->size;
681d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
6827dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (!(t = avahi_dns_packet_append_name(p, k->name)) ||
6837dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        !avahi_dns_packet_append_uint16(p, k->type) ||
68414f8d9beb7ef14b0aab5512345e09109bdd8cb0cLennart Poettering        !avahi_dns_packet_append_uint16(p, k->clazz | (unicast_response ? AVAHI_DNS_UNICAST_RESPONSE : 0))) {
685d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering        p->size = size;
686f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering        return NULL;
687d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering    }
688f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
689f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering    return t;
690f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
691f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
692943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poetteringstatic int append_rdata(AvahiDnsPacket *p, AvahiRecord *r) {
6934f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
6944f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(r);
695943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
696c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering    switch (r->key->type) {
697c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
6987dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_PTR:
699d1dd07145bb3db5c6fd77c55aea762eb79ab3b5cLennart Poettering        case AVAHI_DNS_TYPE_CNAME:
700d1dd07145bb3db5c6fd77c55aea762eb79ab3b5cLennart Poettering        case AVAHI_DNS_TYPE_NS:
701d1dd07145bb3db5c6fd77c55aea762eb79ab3b5cLennart Poettering
7027dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!(avahi_dns_packet_append_name(p, r->data.ptr.name)))
703943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
704c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
705a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
706a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7077dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_SRV:
708a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7097dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!avahi_dns_packet_append_uint16(p, r->data.srv.priority) ||
7107dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                !avahi_dns_packet_append_uint16(p, r->data.srv.weight) ||
7117dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                !avahi_dns_packet_append_uint16(p, r->data.srv.port) ||
7127dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                !avahi_dns_packet_append_name(p, r->data.srv.name))
713943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
714c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
715c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
716c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
7177dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_HINFO:
7187dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!avahi_dns_packet_append_string(p, r->data.hinfo.cpu) ||
7197dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                !avahi_dns_packet_append_string(p, r->data.hinfo.os))
720943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
721a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
722a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
723a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7247dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_TXT: {
725a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7264f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            uint8_t *data;
7274f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            size_t n;
728c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
72966142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            n = avahi_string_list_serialize(r->data.txt.string_list, NULL, 0);
730c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
73166142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            if (!(data = avahi_dns_packet_extend(p, n)))
732943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
733c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
73466142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            avahi_string_list_serialize(r->data.txt.string_list, data, n);
735c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
736c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering        }
737c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
738a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7397dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_A:
740a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7417dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!avahi_dns_packet_append_bytes(p, &r->data.a.address, sizeof(r->data.a.address)))
742943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
743a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
744a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
745a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7467dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_AAAA:
747a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7487dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!avahi_dns_packet_append_bytes(p, &r->data.aaaa.address, sizeof(r->data.aaaa.address)))
749943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
750a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
751a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
752a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
753c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering        default:
754a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
755943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering            if (r->data.generic.size)
756943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                if (avahi_dns_packet_append_bytes(p, r->data.generic.data, r->data.generic.size))
757943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                    return -1;
758a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
759a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
760c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering    }
761c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
762943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    return 0;
763943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering}
764943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
765a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
766943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poetteringuint8_t* avahi_dns_packet_append_record(AvahiDnsPacket *p, AvahiRecord *r, int cache_flush, unsigned max_ttl) {
767943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    uint8_t *t, *l, *start;
768943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    size_t size;
769943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
770943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(p);
771943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(r);
772943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
773943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    size = p->size;
774943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
775943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (!(t = avahi_dns_packet_append_name(p, r->key->name)) ||
776943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        !avahi_dns_packet_append_uint16(p, r->key->type) ||
777943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        !avahi_dns_packet_append_uint16(p, cache_flush ? (r->key->clazz | AVAHI_DNS_CACHE_FLUSH) : (r->key->clazz &~ AVAHI_DNS_CACHE_FLUSH)) ||
778943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        !avahi_dns_packet_append_uint32(p, (max_ttl && r->ttl > max_ttl) ? max_ttl : r->ttl) ||
779943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        !(l = avahi_dns_packet_append_uint16(p, 0)))
780943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        goto fail;
781943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
782943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    start = avahi_dns_packet_extend(p, 0);
783a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
784943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (append_rdata(p, r) < 0)
785943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        goto fail;
786a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7877dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    size = avahi_dns_packet_extend(p, 0) - start;
7884f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(size <= 0xFFFF);
789a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
790c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*     avahi_log_debug("appended %u", size); */
791a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
792973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    l[0] = (uint8_t) ((uint16_t) size >> 8);
793973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    l[1] = (uint8_t) ((uint16_t) size);
794a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
79554247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering    return t;
796d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
797d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
798d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poetteringfail:
799d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering    p->size = size;
800d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering    return NULL;
801d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering}
802d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
8034f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_is_empty(AvahiDnsPacket *p) {
8044f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
805d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
8067dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    return p->size <= AVAHI_DNS_PACKET_HEADER_SIZE;
807f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
8080a985aa6c5453fe09bf0a3a79fe66d49c698b309Lennart Poettering
8094f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringsize_t avahi_dns_packet_space(AvahiDnsPacket *p) {
8104f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
8110a985aa6c5453fe09bf0a3a79fe66d49c698b309Lennart Poettering
8124f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p->size <= p->max_size);
8130a985aa6c5453fe09bf0a3a79fe66d49c698b309Lennart Poettering
8140a985aa6c5453fe09bf0a3a79fe66d49c698b309Lennart Poettering    return p->max_size - p->size;
8150a985aa6c5453fe09bf0a3a79fe66d49c698b309Lennart Poettering}
816943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
817943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poetteringint avahi_rdata_parse(AvahiRecord *record, const void* rdata, size_t size) {
818943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    int ret;
819943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    AvahiDnsPacket p;
820943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
821943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(record);
822943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(rdata);
823943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
824943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.data = (void*) rdata;
825943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.max_size = p.size = size;
826943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.rindex = 0;
827943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.name_table = NULL;
828943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
829943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    ret = parse_rdata(&p, record, size);
830943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
831943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(!p.name_table);
832943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
833943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    return ret;
834943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering}
835943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
836943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poetteringsize_t avahi_rdata_serialize(AvahiRecord *record, void *rdata, size_t max_size) {
837943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    int ret;
838943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    AvahiDnsPacket p;
839943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
840943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(record);
841943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(rdata);
842943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(max_size > 0);
843943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
844943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.data = (void*) rdata;
845943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.max_size = max_size;
846943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.size = p.rindex = 0;
847943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.name_table = NULL;
848943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
849943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    ret = append_rdata(&p, record);
850943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
851943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (p.name_table)
852943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering         avahi_hashmap_free(p.name_table);
853943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
854943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (ret < 0)
855943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        return (size_t) -1;
856943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
857943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    return p.size;
858943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering}
859