blob: 8319d1a6a00a0b1026b45ed321de34e188f960d6 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdbool.h>
#include <stdint.h>
#include <zircon/compiler.h>
#include "inet6.h"
#include "netifc.h"
// Start broadcasting mDNS information.
// |namegen| is `generation` parameter passed to device_id(), which determines if the device
// nodename is an old-style step-atom-yard-juicy name or a new-style fuchsia-5254-0063-5e7a name.
// This expects sole access to the netifc timer.
void mdns_start(uint32_t namegen, bool fastboot_tcp);
void mdns_poll(bool fastboot_tcp);
// Stop broadcasting mDNS information.
void mdns_stop(bool fastboot_tcp);
// Everything below this point is only available
// outside of mdns.c for testing purposes.
#define MDNS_TYPE_PTR 12
#define MDNS_TYPE_AAAA 28
#define MDNS_TYPE_SRV 33
// Indicates that name is already present in the mDNS packet, at the offset in the low byte.
#define MDNS_NAME_AT_OFFSET_FLAG (0xc000)
// A buffer used during the construction of mDNS packets.
// The various mdns_write_* calls take this as an argument.
struct mdns_buf {
// Packet data.
uint8_t data[MDNS_MAX_PKT];
// Amount of data in the packet.
size_t used;
struct mdns_header {
uint16_t id;
uint16_t flags;
uint16_t question_count;
uint16_t answer_count;
uint16_t authority_count;
uint16_t additional_count;
// Represents a part of a name. Each segment must not have a ".".
// `loc` should be set to zero every time a new packet is created.
// `next` should point to the next name segment in this name.
// e.g. "" would correspond to:
// struct mdns_name_segment google[3] = {
// {.name = "wwww", .loc = 0, .next = &google[1], },
// {.name = "google", .loc = 0, .next = &google[2], },
// {.name = "com", .loc = 0, .next = NULL, },
struct mdns_name_segment {
const char* name;
uint16_t loc;
struct mdns_name_segment* next;
struct mdns_ptr_record {
struct mdns_name_segment* name;
struct mdns_aaaa_record {
ip6_addr addr;
struct mdns_srv_record {
uint16_t priority;
uint16_t weight;
uint16_t port;
struct mdns_name_segment* target;
struct mdns_record {
struct mdns_name_segment* name;
uint16_t type;
uint16_t record_class;
uint32_t time_to_live;
union {
struct mdns_ptr_record ptr;
struct mdns_aaaa_record aaaa;
struct mdns_srv_record srv;
} data;
bool mdns_write_u16(struct mdns_buf* b, uint16_t v);
bool mdns_write_u32(struct mdns_buf* b, uint32_t v);
bool mdns_write_name(struct mdns_buf* b, struct mdns_name_segment* name);
bool mdns_write_record(struct mdns_buf* b, struct mdns_record* r);
bool mdns_write_packet(struct mdns_header* hdr, struct mdns_record* records, struct mdns_buf* pkt);
// Writes the full fastboot mDNS packet.
// Args:
// finished: true for the final mDNS packet with TTL = 0.
// tcp: true for TCP, false for UDP.
// packet_buf: packet buffer to fill.
// Returns true on success.
bool mdns_write_fastboot_packet(bool finished, bool tcp, struct mdns_buf* packet_buf);
// The default nodename, will be replaced as soon as mdns_start() is called,
// but exposed here so that tests can more easily validate behavior.
#define MDNS_DEFAULT_NODENAME_FOR_TEST "<no_nodename>"