dns.c revision 1ffedb586bd2fb6daa3970304fac7c5b415cd38f
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
26a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering#include <netinet/in.h>
27a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
284ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering#include <stdlib.h>
294ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering#include <string.h>
304ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering#include <stdio.h>
314f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering#include <assert.h>
324ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
335ebf655c85076f200955458673a8bbf0dd927407Lennart Poettering#include <avahi-common/domain.h>
344f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering#include <avahi-common/malloc.h>
354f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering
364ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering#include "dns.h"
374f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering#include "log.h"
384ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
394f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiDnsPacket* avahi_dns_packet_new(unsigned mtu) {
407dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    AvahiDnsPacket *p;
414f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t max_size;
42c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
43602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    if (mtu <= 0)
447dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        max_size = AVAHI_DNS_PACKET_MAX_SIZE;
45b6820898d317c29a31f97018ede6da5195d16bfbLennart Poettering    else if (mtu >= AVAHI_DNS_PACKET_EXTRA_SIZE)
46b6820898d317c29a31f97018ede6da5195d16bfbLennart Poettering        max_size = mtu - AVAHI_DNS_PACKET_EXTRA_SIZE;
47602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    else
48602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        max_size = 0;
49602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
50602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    if (max_size < AVAHI_DNS_PACKET_HEADER_SIZE)
517dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        max_size = AVAHI_DNS_PACKET_HEADER_SIZE;
52c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
534f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(p = avahi_malloc(sizeof(AvahiDnsPacket) + max_size)))
544f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return p;
554f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering
567dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    p->size = p->rindex = AVAHI_DNS_PACKET_HEADER_SIZE;
57c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    p->max_size = max_size;
584ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering    p->name_table = NULL;
59c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
607dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    memset(AVAHI_DNS_PACKET_DATA(p), 0, p->size);
61c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    return p;
62c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering}
63c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
644f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiDnsPacket* avahi_dns_packet_new_query(unsigned mtu) {
657dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    AvahiDnsPacket *p;
66c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
674f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(p = avahi_dns_packet_new(mtu)))
684f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return NULL;
694f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering
707dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_FLAGS, AVAHI_DNS_FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
71c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    return p;
72c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering}
73c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
744f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiDnsPacket* avahi_dns_packet_new_response(unsigned mtu, int aa) {
757dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    AvahiDnsPacket *p;
76c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
774f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(p = avahi_dns_packet_new(mtu)))
784f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return NULL;
794f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering
808d8c0255f0f0242a067b577747740bab1b1021eaLennart Poettering    avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_FLAGS, AVAHI_DNS_FLAGS(1, 0, aa, 0, 0, 0, 0, 0, 0, 0));
814ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return p;
824ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
834ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
844f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiDnsPacket* avahi_dns_packet_new_reply(AvahiDnsPacket* p, unsigned mtu, int copy_queries, int aa) {
85602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    AvahiDnsPacket *r;
864f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
87602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
884f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(r = avahi_dns_packet_new_response(mtu, aa)))
894f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return NULL;
90602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
91602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    if (copy_queries) {
924f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        unsigned saved_rindex;
934f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        uint32_t n;
94602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
95602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        saved_rindex = p->rindex;
96602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        p->rindex = AVAHI_DNS_PACKET_HEADER_SIZE;
97602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
98602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        for (n = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_QDCOUNT); n > 0; n--) {
99602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering            AvahiKey *k;
1004f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            int unicast_response;
101602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
102602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering            if ((k = avahi_dns_packet_consume_key(p, &unicast_response))) {
103602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering                avahi_dns_packet_append_key(r, k, unicast_response);
104602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering                avahi_key_unref(k);
105602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering            }
106602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        }
107602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
108602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        p->rindex = saved_rindex;
109602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
110602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        avahi_dns_packet_set_field(r, AVAHI_DNS_FIELD_QDCOUNT, avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_QDCOUNT));
111602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    }
112602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
113602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    avahi_dns_packet_set_field(r, AVAHI_DNS_FIELD_ID, avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_ID));
114602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
115602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    avahi_dns_packet_set_field(r, AVAHI_DNS_FIELD_FLAGS,
116602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering                               (avahi_dns_packet_get_field(r, AVAHI_DNS_FIELD_FLAGS) & ~AVAHI_DNS_FLAG_OPCODE) |
1178d8c0255f0f0242a067b577747740bab1b1021eaLennart Poettering                               (avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS) & AVAHI_DNS_FLAG_OPCODE));
118602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
119602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    return r;
120602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering}
121602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
122602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
1237dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poetteringvoid avahi_dns_packet_free(AvahiDnsPacket *p) {
1244f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1254ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1264ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering    if (p->name_table)
1274f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        avahi_hashmap_free(p->name_table);
1284ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1294f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    avahi_free(p);
1304ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
1314ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1324f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringvoid avahi_dns_packet_set_field(AvahiDnsPacket *p, unsigned idx, uint16_t v) {
1334f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1344f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(idx < AVAHI_DNS_PACKET_HEADER_SIZE);
1354ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1364f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    ((uint16_t*) AVAHI_DNS_PACKET_DATA(p))[idx] = htons(v);
1374ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
1384ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1394f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint16_t avahi_dns_packet_get_field(AvahiDnsPacket *p, unsigned idx) {
1404f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1414f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(idx < AVAHI_DNS_PACKET_HEADER_SIZE);
1424ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1434f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    return ntohs(((uint16_t*) AVAHI_DNS_PACKET_DATA(p))[idx]);
1444ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
1454ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1464f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringvoid avahi_dns_packet_inc_field(AvahiDnsPacket *p, unsigned idx) {
1474f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1484f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(idx < AVAHI_DNS_PACKET_HEADER_SIZE);
149af1ce5fe2245fba0045d2c0d70b58b700938bd2fLennart Poettering
15066142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering    avahi_dns_packet_set_field(p, idx, avahi_dns_packet_get_field(p, idx) + 1);
151af1ce5fe2245fba0045d2c0d70b58b700938bd2fLennart Poettering}
152af1ce5fe2245fba0045d2c0d70b58b700938bd2fLennart Poettering
1534f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t* avahi_dns_packet_append_name(AvahiDnsPacket *p, const char *name) {
1544f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *d, *saved_ptr = NULL;
1554f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t saved_size;
1564ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1574f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1584f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(name);
1594ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
160c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    saved_size = p->size;
1617dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    saved_ptr = avahi_dns_packet_extend(p, 0);
1624c8155fa9c85c7ece92182d0ab53f99a982a4abfLennart Poettering
1634e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering    while (*name) {
1644f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        uint8_t* prev;
1654f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        const char *pname;
1664f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        char label[64], *u;
1674f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering
1684ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1694ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering        /* Check whether we can compress this name. */
1704ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1714f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        if (p->name_table && (prev = avahi_hashmap_lookup(p->name_table, name))) {
1724f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            unsigned idx;
1734ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1744f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            assert(prev >= AVAHI_DNS_PACKET_DATA(p));
1754f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            idx = (unsigned) (prev - AVAHI_DNS_PACKET_DATA(p));
1764ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1774f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            assert(idx < p->size);
1784ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
17966142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            if (idx < 0x4000) {
1804f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering                uint16_t *t;
1814f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering                if (!(t = (uint16_t*) avahi_dns_packet_extend(p, sizeof(uint16_t))))
1824ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering                    return NULL;
1834ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1844f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering                *t = htons((0xC000 | idx));
1854c8155fa9c85c7ece92182d0ab53f99a982a4abfLennart Poettering                return saved_ptr;
1864ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering            }
1874ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering        }
1884e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering
1894e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering        pname = name;
1904ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
191a3596a5e3ec4937a220e6e60218639e2aba82701Lennart Poettering        if (!(avahi_unescape_label(&name, label, sizeof(label))))
192c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering            goto fail;
1934ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1947dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        if (!(d = avahi_dns_packet_append_string(p, label)))
1954e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering            goto fail;
1964c8155fa9c85c7ece92182d0ab53f99a982a4abfLennart Poettering
1974ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering        if (!p->name_table)
198a3596a5e3ec4937a220e6e60218639e2aba82701Lennart Poettering            /* This works only for normalized domain names */
1994f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            p->name_table = avahi_hashmap_new(avahi_string_hash, avahi_string_equal, avahi_free, NULL);
2004ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
2014f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        if (!(u = avahi_strdup(pname)))
2024f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            avahi_log_error("avahi_strdup() failed.");
2034f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        else
2044f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            avahi_hashmap_insert(p->name_table, u, d);
2054ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    }
2064ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2077dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (!(d = avahi_dns_packet_extend(p, 1)))
208c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        goto fail;
209c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
2104e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering    *d = 0;
2114ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2124c8155fa9c85c7ece92182d0ab53f99a982a4abfLennart Poettering    return saved_ptr;
213c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
214c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poetteringfail:
215c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    p->size = saved_size;
216c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    return NULL;
2174ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
2184ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2194f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t* avahi_dns_packet_append_uint16(AvahiDnsPacket *p, uint16_t v) {
2204f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *d;
2214f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
2224ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2234f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(d = avahi_dns_packet_extend(p, sizeof(uint16_t))))
224c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        return NULL;
2254ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2264f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    *((uint16_t*) d) = htons(v);
2274ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return d;
2284ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
2294ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2304f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t *avahi_dns_packet_append_uint32(AvahiDnsPacket *p, uint32_t v) {
2314f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *d;
2324f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
233c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
2344f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(d = avahi_dns_packet_extend(p, sizeof(uint32_t))))
235c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        return NULL;
236c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
2374f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    *((uint32_t*) d) = htonl(v);
23854247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
23954247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering    return d;
24054247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering}
24154247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
2424f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t *avahi_dns_packet_append_bytes(AvahiDnsPacket  *p, const void *b, size_t l) {
2434f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t* d;
24454247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
2454f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
2464f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(b);
2474f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(l);
2484aa744ffac20c7b5e18cb3b23e5dbac8221c0043Lennart Poettering
2497dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (!(d = avahi_dns_packet_extend(p, l)))
250c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        return NULL;
25154247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
252c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    memcpy(d, b, l);
25354247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering    return d;
25454247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering}
25554247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
2564f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t* avahi_dns_packet_append_string(AvahiDnsPacket *p, const char *s) {
2574f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t* d;
2584f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t k;
259a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
2604f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
2614f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(s);
262a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
263a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if ((k = strlen(s)) >= 255)
264a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        k = 255;
265a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
2667dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (!(d = avahi_dns_packet_extend(p, k+1)))
267a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        return NULL;
268a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
2694f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    *d = (uint8_t) k;
270a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    memcpy(d+1, s, k);
271a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
272a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    return d;
273a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering}
274a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
2754f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t *avahi_dns_packet_extend(AvahiDnsPacket *p, size_t l) {
2764f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *d;
2774ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2784f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
2794ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
280c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    if (p->size+l > p->max_size)
281c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        return NULL;
282c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
2837dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    d = AVAHI_DNS_PACKET_DATA(p) + p->size;
2844ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    p->size += l;
2854ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2864ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return d;
2874ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
2884ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2891ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poetteringint avahi_dns_packet_check_valid(AvahiDnsPacket *p) {
2904f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint16_t flags;
2914f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
2924ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2931ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (p->size < AVAHI_DNS_PACKET_HEADER_SIZE)
2944ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
2954ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2967dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    flags = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS);
2971ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
2981ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (flags & AVAHI_DNS_FLAG_OPCODE)
2991ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering        return -1;
3001ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
3011ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    return 0;
3021ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering}
3031ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
3041ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poetteringint avahi_dns_packet_check_valid_multicast(AvahiDnsPacket *p) {
3051ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    uint16_t flags;
3061ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    assert(p);
3074ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3081ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (avahi_dns_packet_check_valid(p) < 0)
3091ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering        return -1;
3101ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
3111ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    flags = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS);
3121ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
3131ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (flags & AVAHI_DNS_FLAG_RCODE)
3144ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
3154ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3164ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
3174ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
3184ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3191ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
3204f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_is_query(AvahiDnsPacket *p) {
3214f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
3224ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3237dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    return !(avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS) & AVAHI_DNS_FLAG_QR);
3244ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
3254ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3264f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringstatic int consume_labels(AvahiDnsPacket *p, unsigned idx, char *ret_name, size_t l) {
3274f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    int ret = 0;
3284ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    int compressed = 0;
3294ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    int first_label = 1;
3304f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p && ret_name && l);
3314ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3324ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    for (;;) {
3334f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        uint8_t n;
3344ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
33566142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering        if (idx+1 > p->size)
3364ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            return -1;
3374ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
33866142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering        n = AVAHI_DNS_PACKET_DATA(p)[idx];
3394ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3404ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        if (!n) {
34166142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            idx++;
3424ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!compressed)
3434ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                ret++;
3444ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3454ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (l < 1)
3464ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                return -1;
3474ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            *ret_name = 0;
3484ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3494ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            return ret;
3504ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3514ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        } else if (n <= 63) {
3524ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            /* Uncompressed label */
35366142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            idx++;
3544ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!compressed)
3554ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                ret++;
3564ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
35766142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            if (idx + n > p->size)
3584ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                return -1;
3594ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3604f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            if ((size_t) n + 1 > l)
3614ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                return -1;
3624ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3634ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!first_label) {
3644ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                *(ret_name++) = '.';
3654ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                l--;
3664ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            } else
3674ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                first_label = 0;
3684ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
36966142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            if (!(avahi_escape_label(AVAHI_DNS_PACKET_DATA(p) + idx, n, &ret_name, &l)))
3704e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering                return -1;
3714e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering
37266142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            idx += n;
3734ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3744ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!compressed)
3754ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                ret += n;
3764ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        } else if ((n & 0xC0) == 0xC0) {
3774ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            /* Compressed label */
3784ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
37966142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            if (idx+2 > p->size)
3804ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                return -1;
3814ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3824f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            idx = ((unsigned) (AVAHI_DNS_PACKET_DATA(p)[idx] & ~0xC0)) << 8 | AVAHI_DNS_PACKET_DATA(p)[idx+1];
3834ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3844ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!compressed)
3854ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                ret += 2;
3864ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3874ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            compressed = 1;
3884ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        } else
3894ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            return -1;
3904ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    }
3914ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
3924ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3934f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_name(AvahiDnsPacket *p, char *ret_name, size_t l) {
3944f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    int r;
3954ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3964ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    if ((r = consume_labels(p, p->rindex, ret_name, l)) < 0)
3974ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
3984ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3994ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    p->rindex += r;
4004ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
4014ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
4024ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4034f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_uint16(AvahiDnsPacket *p, uint16_t *ret_v) {
4044f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
4054f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(ret_v);
4064ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4074f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (p->rindex + sizeof(uint16_t) > p->size)
4084ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
4094ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4104f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    *ret_v = ntohs(*((uint16_t*) (AVAHI_DNS_PACKET_DATA(p) + p->rindex)));
4114f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    p->rindex += sizeof(uint16_t);
4124ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4134ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
4144ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
4154ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4164f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_uint32(AvahiDnsPacket *p, uint32_t *ret_v) {
4174f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
4184f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(ret_v);
4194ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4204f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (p->rindex + sizeof(uint32_t) > p->size)
4214ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
4224ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4234f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    *ret_v = ntohl(*((uint32_t*) (AVAHI_DNS_PACKET_DATA(p) + p->rindex)));
4244f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    p->rindex += sizeof(uint32_t);
4254ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4264ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
4274ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
4284ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4294f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_bytes(AvahiDnsPacket *p, void * ret_data, size_t l) {
4304f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
4314f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(ret_data);
4324f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(l > 0);
4334ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4344ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    if (p->rindex + l > p->size)
4354ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
4364ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4377dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    memcpy(ret_data, AVAHI_DNS_PACKET_DATA(p) + p->rindex, l);
4384ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    p->rindex += l;
4394ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4404ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
4414ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
4424ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4434f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_string(AvahiDnsPacket *p, char *ret_string, size_t l) {
4444f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t k;
445a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
4464f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
4474f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(ret_string);
4484f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(l > 0);
449a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
450a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (p->rindex >= p->size)
451a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        return -1;
452a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
4537dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    k = AVAHI_DNS_PACKET_DATA(p)[p->rindex];
454a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
455a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (p->rindex+1+k > p->size)
456a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        return -1;
457a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
458a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (l > k+1)
459a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        l = k+1;
460a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
4617dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    memcpy(ret_string, AVAHI_DNS_PACKET_DATA(p)+p->rindex+1, l-1);
462a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    ret_string[l-1] = 0;
463a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
464a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    p->rindex += 1+k;
465a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
466a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    return 0;
467a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering}
468a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
4694f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringconst void* avahi_dns_packet_get_rptr(AvahiDnsPacket *p) {
4704f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
471f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
472a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (p->rindex > p->size)
473f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering        return NULL;
474f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
4757dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    return AVAHI_DNS_PACKET_DATA(p) + p->rindex;
476f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
477f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
4784f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_skip(AvahiDnsPacket *p, size_t length) {
4794f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
4804ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4814ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    if (p->rindex + length > p->size)
4824ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
4834ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4844ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    p->rindex += length;
4854ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
4864ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
487f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
4884f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiRecord* avahi_dns_packet_consume_record(AvahiDnsPacket *p, int *ret_cache_flush) {
4894f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    char name[257], buf[257];
4904f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint16_t type, class;
4914f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint32_t ttl;
4924f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint16_t rdlength;
4937dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    AvahiRecord *r = NULL;
4944f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    const void* start;
495f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
4964f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
497f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
498c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*     avahi_log_debug("consume_record()"); */
499a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5007dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (avahi_dns_packet_consume_name(p, name, sizeof(name)) < 0 ||
5017dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        avahi_dns_packet_consume_uint16(p, &type) < 0 ||
5027dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        avahi_dns_packet_consume_uint16(p, &class) < 0 ||
5037dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        avahi_dns_packet_consume_uint32(p, &ttl) < 0 ||
5047dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        avahi_dns_packet_consume_uint16(p, &rdlength) < 0 ||
505a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        p->rindex + rdlength > p->size)
506a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        goto fail;
507a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
508c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*     avahi_log_debug("name = %s, rdlength = %u", name, rdlength); */
509b8c78f5c0da93d92aa28d3ef3757e78d03141f41Lennart Poettering
5101ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (ret_cache_flush)
5111ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering        *ret_cache_flush = !!(class & AVAHI_DNS_CACHE_FLUSH);
5127dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    class &= ~AVAHI_DNS_CACHE_FLUSH;
513a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5147dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    start = avahi_dns_packet_get_rptr(p);
515b8c78f5c0da93d92aa28d3ef3757e78d03141f41Lennart Poettering
5164f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(r = avahi_record_new_full(name, class, type, ttl)))
5174f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return NULL;
518a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
519c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering    switch (type) {
5207dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_PTR:
5217dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_CNAME:
522a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
523c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*             avahi_log_debug("ptr"); */
524a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5257dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_name(p, buf, sizeof(buf)) < 0)
526a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering                goto fail;
527a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5284f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            r->data.ptr.name = avahi_strdup(buf);
529a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
530a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
531c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
5327dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_SRV:
533a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
534c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*             avahi_log_debug("srv"); */
535a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5367dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_uint16(p, &r->data.srv.priority) < 0 ||
5377dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                avahi_dns_packet_consume_uint16(p, &r->data.srv.weight) < 0 ||
5387dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                avahi_dns_packet_consume_uint16(p, &r->data.srv.port) < 0 ||
5397dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                avahi_dns_packet_consume_name(p, buf, sizeof(buf)) < 0)
540a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering                goto fail;
541a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5424f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            r->data.srv.name = avahi_strdup(buf);
543a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
544a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5457dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_HINFO:
546a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
547c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*             avahi_log_debug("hinfo"); */
548a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5497dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_string(p, buf, sizeof(buf)) < 0)
550a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering                goto fail;
551a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5524f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            r->data.hinfo.cpu = avahi_strdup(buf);
553a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5547dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_string(p, buf, sizeof(buf)) < 0)
555a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering                goto fail;
556a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5574f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            r->data.hinfo.os = avahi_strdup(buf);
558c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
559c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
5607dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_TXT:
561a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
562c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*             avahi_log_debug("txt"); */
563c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
564a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            if (rdlength > 0) {
5657dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                r->data.txt.string_list = avahi_string_list_parse(avahi_dns_packet_get_rptr(p), rdlength);
566a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5677dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                if (avahi_dns_packet_skip(p, rdlength) < 0)
568a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering                    goto fail;
569fc174c871b4f85e558766c1ca55661fa7b1b4c9aLennart Poettering            } else
570fc174c871b4f85e558766c1ca55661fa7b1b4c9aLennart Poettering                r->data.txt.string_list = NULL;
571c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
572a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
573a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5747dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_A:
575a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
576c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*             avahi_log_debug("A"); */
577c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
5787dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_bytes(p, &r->data.a.address, sizeof(AvahiIPv4Address)) < 0)
579a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering                goto fail;
580a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
581a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
582a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5837dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_AAAA:
584a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
585c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*             avahi_log_debug("aaaa"); */
586a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5877dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_bytes(p, &r->data.aaaa.address, sizeof(AvahiIPv6Address)) < 0)
588a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering                goto fail;
589a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
590c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
591c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
592c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering        default:
5934aa744ffac20c7b5e18cb3b23e5dbac8221c0043Lennart Poettering
594c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*             avahi_log_debug("generic"); */
595a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5964aa744ffac20c7b5e18cb3b23e5dbac8221c0043Lennart Poettering            if (rdlength > 0) {
5974aa744ffac20c7b5e18cb3b23e5dbac8221c0043Lennart Poettering
5984f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering                r->data.generic.data = avahi_memdup(avahi_dns_packet_get_rptr(p), rdlength);
599a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
6007dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                if (avahi_dns_packet_skip(p, rdlength) < 0)
601a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering                    goto fail;
602a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            }
603c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
604c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
605c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering    }
606c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
6074f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering/*     avahi_log_debug("%i == %u ?", (uint8_t*) avahi_dns_packet_get_rptr(p) - (uint8_t*) start, rdlength); */
608a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
609a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    /* Check if we read enough data */
6104f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if ((const uint8_t*) avahi_dns_packet_get_rptr(p) - (const uint8_t*) start != rdlength)
611a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        goto fail;
612a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
613a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    return r;
614a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
615a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poetteringfail:
616a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (r)
6177dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        avahi_record_unref(r);
618a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
619a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    return NULL;
620f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
621f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6224f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiKey* avahi_dns_packet_consume_key(AvahiDnsPacket *p, int *ret_unicast_response) {
6234f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    char name[256];
6244f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint16_t type, class;
625f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6264f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
627f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6287dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (avahi_dns_packet_consume_name(p, name, sizeof(name)) < 0 ||
6297dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        avahi_dns_packet_consume_uint16(p, &type) < 0 ||
6307dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        avahi_dns_packet_consume_uint16(p, &class) < 0)
631f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering        return NULL;
632f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6331ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (ret_unicast_response)
6341ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering        *ret_unicast_response = !!(class & AVAHI_DNS_UNICAST_RESPONSE);
635f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6361ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    class &= ~AVAHI_DNS_UNICAST_RESPONSE;
6371ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
6387dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    return avahi_key_new(name, class, type);
639f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
640f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6414f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t* avahi_dns_packet_append_key(AvahiDnsPacket *p, AvahiKey *k, int unicast_response) {
6424f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *t;
6434f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t size;
644f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6454f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
6464f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(k);
647f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
648d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering    size = p->size;
649d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
6507dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (!(t = avahi_dns_packet_append_name(p, k->name)) ||
6517dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        !avahi_dns_packet_append_uint16(p, k->type) ||
65214f8d9beb7ef14b0aab5512345e09109bdd8cb0cLennart Poettering        !avahi_dns_packet_append_uint16(p, k->clazz | (unicast_response ? AVAHI_DNS_UNICAST_RESPONSE : 0))) {
653d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering        p->size = size;
654f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering        return NULL;
655d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering    }
656f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
657f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering    return t;
658f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
659f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6604f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t* avahi_dns_packet_append_record(AvahiDnsPacket *p, AvahiRecord *r, int cache_flush, unsigned max_ttl) {
6614f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *t, *l, *start;
6624f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t size;
663f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6644f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
6654f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(r);
66654247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
667d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering    size = p->size;
668d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
6697dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (!(t = avahi_dns_packet_append_name(p, r->key->name)) ||
6707dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        !avahi_dns_packet_append_uint16(p, r->key->type) ||
67114f8d9beb7ef14b0aab5512345e09109bdd8cb0cLennart Poettering        !avahi_dns_packet_append_uint16(p, cache_flush ? (r->key->clazz | AVAHI_DNS_CACHE_FLUSH) : (r->key->clazz &~ AVAHI_DNS_CACHE_FLUSH)) ||
672602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        !avahi_dns_packet_append_uint32(p, (max_ttl && r->ttl > max_ttl) ? max_ttl : r->ttl) ||
6737dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        !(l = avahi_dns_packet_append_uint16(p, 0)))
674d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering        goto fail;
67554247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
6767dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    start = avahi_dns_packet_extend(p, 0);
677a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
678c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering    switch (r->key->type) {
679c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
6807dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_PTR:
6817dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_CNAME :
682c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
6837dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!(avahi_dns_packet_append_name(p, r->data.ptr.name)))
684a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering                goto fail;
685c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
686a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
687a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
6887dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_SRV:
689a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
6907dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!avahi_dns_packet_append_uint16(p, r->data.srv.priority) ||
6917dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                !avahi_dns_packet_append_uint16(p, r->data.srv.weight) ||
6927dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                !avahi_dns_packet_append_uint16(p, r->data.srv.port) ||
6937dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                !avahi_dns_packet_append_name(p, r->data.srv.name))
694d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering                goto fail;
695c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
696c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
697c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
6987dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_HINFO:
6997dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!avahi_dns_packet_append_string(p, r->data.hinfo.cpu) ||
7007dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                !avahi_dns_packet_append_string(p, r->data.hinfo.os))
701a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering                goto fail;
702a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
703a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
704a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7057dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_TXT: {
706a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7074f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            uint8_t *data;
7084f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            size_t n;
709c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
71066142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            n = avahi_string_list_serialize(r->data.txt.string_list, NULL, 0);
711c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
71266142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering/*             avahi_log_debug("appending string: %u %p", n, r->data.txt.string_list); */
713a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
71466142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            if (!(data = avahi_dns_packet_extend(p, n)))
715d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering                goto fail;
716c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
71766142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            avahi_string_list_serialize(r->data.txt.string_list, data, n);
718c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
719c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering        }
720c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
721a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7227dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_A:
723a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7247dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!avahi_dns_packet_append_bytes(p, &r->data.a.address, sizeof(r->data.a.address)))
725a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering                goto fail;
726a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
727a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
728a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7297dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_AAAA:
730a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7317dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!avahi_dns_packet_append_bytes(p, &r->data.aaaa.address, sizeof(r->data.aaaa.address)))
732a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering                goto fail;
733a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
734a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
735a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
736c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering        default:
737a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
738a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            if (r->data.generic.size &&
7397dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                avahi_dns_packet_append_bytes(p, r->data.generic.data, r->data.generic.size))
740d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering                goto fail;
741a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
742a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
743c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering    }
744c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
745a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
746a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
747a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7487dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    size = avahi_dns_packet_extend(p, 0) - start;
7494f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(size <= 0xFFFF);
750a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
751c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*     avahi_log_debug("appended %u", size); */
752a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7534f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    * (uint16_t*) l = htons((uint16_t) size);
754a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
75554247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering    return t;
756d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
757d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
758d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poetteringfail:
759d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering    p->size = size;
760d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering    return NULL;
761d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering}
762d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
7634f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_is_empty(AvahiDnsPacket *p) {
7644f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
765d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
7667dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    return p->size <= AVAHI_DNS_PACKET_HEADER_SIZE;
767f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
7680a985aa6c5453fe09bf0a3a79fe66d49c698b309Lennart Poettering
7694f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringsize_t avahi_dns_packet_space(AvahiDnsPacket *p) {
7704f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
7710a985aa6c5453fe09bf0a3a79fe66d49c698b309Lennart Poettering
7724f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p->size <= p->max_size);
7730a985aa6c5453fe09bf0a3a79fe66d49c698b309Lennart Poettering
7740a985aa6c5453fe09bf0a3a79fe66d49c698b309Lennart Poettering    return p->max_size - p->size;
7750a985aa6c5453fe09bf0a3a79fe66d49c698b309Lennart Poettering}
776