123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919 |
- /**
- * lwip MDNS resolver file.
- *
- * Created on: Jul 29, 2010
- * Author: Daniel Toma
- *
- * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- /**
- * This file implements a MDNS host name and PUCK service registration.
- *-----------------------------------------------------------------------------
- * Includes
- *----------------------------------------------------------------------------*/
- #include "lwip/opt.h"
- #if LWIP_MDNS /* don't build if not configured for use in lwipopts.h */
- #include "lwip/mdns.h"
- #include "lwip/udp.h"
- #include "lwip/mem.h"
- #include "lwip/igmp.h"
- #include "osapi.h"
- #include "os_type.h"
- #include "user_interface.h"
- #include "c_string.h"
- #include "nodemcu_mdns.h"
- #if 0
- #define MDNS_DBG(...) os_printf(...)
- #else
- #define MDNS_DBG(...) do {} while (0)
- #endif
- #define MDNS_NAME_LENGTH 68 //68
- static const char* service_name_with_suffix = NULL;
- #define DNS_SD_SERVICE "_services._dns-sd._udp.local"
- #define PUCK_SERVICE_LENGTH 30
- #define PUCK_DATASHEET_SIZE 96
- #ifdef MEMLEAK_DEBUG
- static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
- #endif
- /** DNS server IP address */
- #ifndef DNS_MULTICAST_ADDRESS
- #define DNS_MULTICAST_ADDRESS ipaddr_addr("224.0.0.251") /* resolver1.opendns.com */
- #endif
- /** DNS server IP address */
- #ifndef MDNS_LOCAL
- #define MDNS_LOCAL "local" /* resolver1.opendns.com */
- #endif
- /** DNS server port address */
- #ifndef DNS_MDNS_PORT
- #define DNS_MDNS_PORT 5353
- #endif
- /** DNS maximum number of retries when asking for a name, before "timeout". */
- #ifndef DNS_MAX_RETRIES
- #define DNS_MAX_RETRIES 4
- #endif
- /** DNS resource record max. TTL (one week as default) */
- #ifndef DNS_MAX_TTL
- #define DNS_MAX_TTL 604800
- #endif
- /* DNS protocol flags */
- #define DNS_FLAG1_RESPONSE 0x84
- #define DNS_FLAG1_OPCODE_STATUS 0x10
- #define DNS_FLAG1_OPCODE_INVERSE 0x08
- #define DNS_FLAG1_OPCODE_STANDARD 0x00
- #define DNS_FLAG1_AUTHORATIVE 0x04
- #define DNS_FLAG1_TRUNC 0x02
- #define DNS_FLAG1_RD 0x01
- #define DNS_FLAG2_RA 0x80
- #define DNS_FLAG2_ERR_MASK 0x0f
- #define DNS_FLAG2_ERR_NONE 0x00
- #define DNS_FLAG2_ERR_NAME 0x03
- /* DNS protocol states */
- #define DNS_STATE_UNUSED 0
- #define DNS_STATE_NEW 1
- #define DNS_STATE_ASKING 2
- #define DNS_STATE_DONE 3
- /* MDNS registration type */
- #define MDNS_HOSTNAME_REG 0
- #define MDNS_SERVICE_REG 1
- /* MDNS registration type */
- #define MDNS_REG_ANSWER 1
- #define MDNS_SD_ANSWER 2
- #define MDNS_SERVICE_REG_ANSWER 3
- /* MDNS registration time */
- #define MDNS_HOST_TIME 120
- #define MDNS_SERVICE_TIME 3600
- /** MDNS name length with "." at the beginning and end of name*/
- #ifndef MDNS_LENGTH_ADD
- #define MDNS_LENGTH_ADD 2
- #endif
- #ifdef MDNS_MAX_NAME_LENGTH
- #undef MDNS_MAX_NAME_LENGTH
- #endif
- #define MDNS_MAX_NAME_LENGTH (256)
- PACK_STRUCT_BEGIN
- /** DNS message header */
- struct mdns_hdr {
- PACK_STRUCT_FIELD(u16_t id);
- PACK_STRUCT_FIELD(u8_t flags1);
- PACK_STRUCT_FIELD(u8_t flags2);
- PACK_STRUCT_FIELD(u16_t numquestions);
- PACK_STRUCT_FIELD(u16_t numanswers);
- PACK_STRUCT_FIELD(u16_t numauthrr);
- PACK_STRUCT_FIELD(u16_t numextrarr);
- }PACK_STRUCT_STRUCT;
- PACK_STRUCT_END
- #define SIZEOF_DNS_HDR 12
- PACK_STRUCT_BEGIN
- /** MDNS query message structure */
- struct mdns_query {
- /* MDNS query record starts with either a domain name or a pointer
- to a name already present somewhere in the packet. */PACK_STRUCT_FIELD(u16_t type);
- PACK_STRUCT_FIELD(u16_t class);
- }PACK_STRUCT_STRUCT;
- PACK_STRUCT_END
- #define SIZEOF_DNS_QUERY 4
- PACK_STRUCT_BEGIN
- /** MDNS answer message structure */
- struct mdns_answer {
- /* MDNS answer record starts with either a domain name or a pointer
- to a name already present somewhere in the packet. */PACK_STRUCT_FIELD(u16_t type);
- PACK_STRUCT_FIELD(u16_t class);
- PACK_STRUCT_FIELD(u32_t ttl);
- PACK_STRUCT_FIELD(u16_t len);
- }PACK_STRUCT_STRUCT;
- PACK_STRUCT_END
- #define SIZEOF_DNS_ANSWER 10
- PACK_STRUCT_BEGIN
- /** MDNS answer message structure */
- struct mdns_auth {
- PACK_STRUCT_FIELD(u32_t src);
- }PACK_STRUCT_STRUCT;
- PACK_STRUCT_END
- #define SIZEOF_MDNS_AUTH 4
- PACK_STRUCT_BEGIN
- /** MDNS service registration message structure */
- struct mdns_service {
- PACK_STRUCT_FIELD(u16_t prior);
- PACK_STRUCT_FIELD(u16_t weight);
- PACK_STRUCT_FIELD(u16_t port);
- }PACK_STRUCT_STRUCT;
- PACK_STRUCT_END
- #define SIZEOF_MDNS_SERVICE 6
- static os_timer_t mdns_timer;
- /* forward declarations */
- static void mdns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p,
- struct ip_addr *addr, u16_t port);
- /*-----------------------------------------------------------------------------
- * Globales
- *----------------------------------------------------------------------------*/
- /* MDNS variables */
- //static char puck_datasheet[PUCK_DATASHEET_SIZE];
- static struct udp_pcb *mdns_pcb = NULL;
- static struct nodemcu_mdns_info * ms_info = NULL;
- static struct ip_addr multicast_addr;
- static uint8 register_flag = 0;
- static uint8 mdns_flag = 0;
- static u8_t *mdns_payload;
- /**
- * Compare the "dotted" name "query" with the encoded name "response"
- * to make sure an answer from the DNS server matches the current mdns_table
- * entry (otherwise, answers might arrive late for hostname not on the list
- * any more).
- *
- * @param query hostname (not encoded) from the mdns_table
- * @param response encoded hostname in the DNS response
- * @return 0: names equal; 1: names differ
- */
- static u8_t ICACHE_FLASH_ATTR
- mdns_compare_name(unsigned char *query, unsigned char *response) {
- unsigned char n;
- do {
- n = *response++;
- /** @see RFC 1035 - 4.1.4. Message compression */
- if ((n & 0xc0) == 0xc0) {
- /* Compressed name */
- break;
- } else {
- /* Not compressed name */
- while (n > 0) {
- if ((*query) != (*response)) {
- return 1;
- }
- ++response;
- ++query;
- --n;
- };
- ++query;
- }
- } while (*response != 0);
- return 0;
- }
- static int
- mdns_namelen(u8_t *p, unsigned int maxlen) {
- u8_t *orig = p;
- while (*p && *p <= 63) {
- if (p - orig > maxlen) {
- return -1;
- }
- p += *p + 1;
- }
- if (*p >= 0xc0) {
- p += 2; // advance over the two byte pointer
- } else {
- p++; // advance over the final 0
- }
- if (p - orig > maxlen) {
- return -1;
- }
- return p - orig;
- }
- static err_t send_packet(struct pbuf *p, struct ip_addr *dst_addr, u16_t dst_port, u8_t *addr_ptr) {
- err_t err;
- /* send dns packet */
- struct netif *sta_netif = (struct netif *)eagle_lwip_getif(0x00);
- struct netif *ap_netif = (struct netif *)eagle_lwip_getif(0x01);
- if (addr_ptr) {
- if (wifi_get_opmode() == 0x02) {
- if (!ap_netif) {
- return;
- }
- memcpy(addr_ptr, &ap_netif->ip_addr, sizeof(ap_netif->ip_addr));
- } else {
- if (!sta_netif) {
- return;
- }
- memcpy(addr_ptr, &sta_netif->ip_addr, sizeof(sta_netif->ip_addr));
- }
- }
- if (dst_addr) {
- err = udp_sendto(mdns_pcb, p, dst_addr, dst_port);
- } else {
- err = udp_sendto(mdns_pcb, p, &multicast_addr, DNS_MDNS_PORT);
- if(wifi_get_opmode() == 0x03 && wifi_get_broadcast_if() == 0x03 &&\
- sta_netif != NULL && ap_netif != NULL) {
- if(netif_is_up(sta_netif) && netif_is_up(ap_netif)) {
- netif_set_default(sta_netif);
- if (addr_ptr) {
- memcpy(addr_ptr, &ap_netif->ip_addr, sizeof(ap_netif->ip_addr));
- }
- err = udp_sendto(mdns_pcb, p, &multicast_addr, DNS_MDNS_PORT);
- netif_set_default(ap_netif);
- }
- }
- }
- /* free pbuf */
- pbuf_free(p);
- return err;
- }
- /**
- * Send a mDNS packet for the service type
- *
- * @param id transaction ID in the DNS query packet
- * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
- */
- static err_t ICACHE_FLASH_ATTR
- mdns_send_service_type(u16_t id, struct ip_addr *dst_addr, u16_t dst_port) {
- err_t err;
- struct mdns_hdr *hdr;
- struct mdns_answer ans;
- struct mdns_auth auth;
- struct mdns_service serv;
- struct pbuf *p ,*p_sta;
- char *query, *nptr;
- const char *pHostname;
- struct netif * sta_netif = NULL;
- struct netif * ap_netif = NULL;
- char tmpBuf[PUCK_DATASHEET_SIZE + PUCK_SERVICE_LENGTH];
- u8_t n;
- u16_t length = 0;
- /* if here, we have either a new query or a retry on a previous query to process */
- p = pbuf_alloc(PBUF_TRANSPORT,
- SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
- if (p != NULL) {
- LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
- /* fill dns header */
- hdr = (struct mdns_hdr*) p->payload;
- os_memset(hdr, 0, SIZEOF_DNS_HDR);
- hdr->id = htons(id);
- hdr->flags1 = DNS_FLAG1_RESPONSE;
- pHostname = DNS_SD_SERVICE;
- hdr->numanswers = htons(1);
- query = (char*) hdr + SIZEOF_DNS_HDR;
- --pHostname;
- /* convert hostname into suitable query format. */
- do {
- ++pHostname;
- nptr = query;
- ++query;
- for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
- *query = *pHostname;
- ++query;
- ++n;
- }
- *nptr = n;
- } while (*pHostname != 0);
- *query++ = '\0';
- /* fill dns query */
- ans.type = htons(DNS_RRTYPE_PTR);
- ans.class = htons(DNS_RRCLASS_IN);
- ans.ttl = htonl(3600);
- ans.len = htons(os_strlen(service_name_with_suffix) + 1 +1 );
- length = 0;
- MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
- /* resize the query */
- query = query + SIZEOF_DNS_ANSWER;
- pHostname = service_name_with_suffix;
- --pHostname;
- /* convert hostname into suitable query format. */
- do {
- ++pHostname;
- nptr = query;
- ++query;
- for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
- *query = *pHostname;
- ++query;
- ++n;
- }
- *nptr = n;
- } while (*pHostname != 0);
- *query++ = '\0';
- /* resize pbuf to the exact dns query */
- pbuf_realloc(p, (query + length) - ((char*) (p->payload)));
- err = send_packet(p, dst_addr, dst_port, 0);
- } else {
- err = ERR_MEM;
- }
- return err;
- }
- /**
- * Send a mDNS service answer packet.
- *
- * @param name service name to query
- * @param id transaction ID in the DNS query packet
- * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
- */
- static err_t ICACHE_FLASH_ATTR
- mdns_send_service(struct nodemcu_mdns_info *info, u16_t id, struct ip_addr *dst_addr, u16_t dst_port) {
- err_t err;
- struct mdns_hdr *hdr;
- struct mdns_answer ans;
- struct mdns_service serv;
- struct mdns_auth auth;
- struct pbuf *p ,*p_sta;
- char *query, *nptr;
- char *query_end;
- const char *pHostname;
- const char *name = info->host_name;
- u8_t n;
- u8_t i = 0;
- u16_t length = 0;
- u8_t addr1 = 12, addr2 = 12;
- struct netif * sta_netif = NULL;
- struct netif * ap_netif = NULL;
- char tmpBuf[PUCK_DATASHEET_SIZE + PUCK_SERVICE_LENGTH];
- u16_t dns_class = dst_addr ? DNS_RRCLASS_IN : DNS_RRCLASS_FLUSH_IN;
- /* if here, we have either a new query or a retry on a previous query to process */
- p = pbuf_alloc(PBUF_TRANSPORT,
- SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
- if (p != NULL) {
- LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
- /* fill dns header */
- hdr = (struct mdns_hdr*) p->payload;
- os_memset(hdr, 0, SIZEOF_DNS_HDR);
- hdr->id = htons(id);
- hdr->flags1 = DNS_FLAG1_RESPONSE;
- hdr->numanswers = htons(4);
- query = (char*) hdr + SIZEOF_DNS_HDR;
- query_end = (char *) p->payload + p->tot_len;
- c_strlcpy(tmpBuf, service_name_with_suffix, sizeof(tmpBuf));
- pHostname = tmpBuf;
- --pHostname;
- /* convert hostname into suitable query format. */
- do {
- ++pHostname;
- nptr = query;
- ++query;
- ++addr1;
- ++addr2;
- for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
- *query = *pHostname;
- ++query;
- ++addr1;
- ++addr2;
- ++n;
- }
- *nptr = n;
- } while (*pHostname != 0);
- *query++ = '\0';
- length = sizeof(MDNS_LOCAL);
- addr1 -= length;
- length = os_strlen(service_name_with_suffix) + 1;
- addr2 -= length;
- ans.type = htons(DNS_RRTYPE_PTR);
- ans.class = htons(DNS_RRCLASS_IN);
- ans.ttl = htonl(300);
- length = os_strlen(ms_info->host_desc) + MDNS_LENGTH_ADD + 1;
- ans.len = htons(length);
- length = 0;
- MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
- /* resize the query */
- query = query + SIZEOF_DNS_ANSWER;
- int name_offset = query - (const char *) hdr;
- pHostname = ms_info->host_desc;
- --pHostname;
- /* convert hostname into suitable query format. */
- do {
- ++pHostname;
- nptr = query;
- ++query;
- for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
- *query = *pHostname;
- ++query;
- ++n;
- }
- *nptr = n;
- } while (*pHostname != 0);
- *query++ = DNS_OFFSET_FLAG;
- *query++ = DNS_DEFAULT_OFFSET;
- *query++ = 0xc0 + (name_offset >> 8);
- *query++ = name_offset & 0xff;
- /* fill the answer */
- ans.type = htons(DNS_RRTYPE_TXT);
- ans.class = htons(dns_class);
- ans.ttl = htonl(300);
- // length = os_strlen(TXT_DATA) + MDNS_LENGTH_ADD + 1;
- const char *attributes[12];
- int attr_count = 0;
- for(i = 0; i < 10 && (info->txt_data[i] != NULL); i++) {
- length += os_strlen(info->txt_data[i]);
- length++;
- attributes[attr_count++] = info->txt_data[i];
- }
- //MDNS_DBG("Found %d user attributes\n", i);
- static const char *defaults[] = { "platform=nodemcu", NULL };
- for(i = 0; defaults[i] != NULL; i++) {
- // See if this is a duplicate
- int j;
- int len = strchr(defaults[i], '=') + 1 - defaults[i];
- for (j = 0; j < attr_count; j++) {
- if (strncmp(attributes[j], defaults[i], len) == 0) {
- break;
- }
- }
- if (j == attr_count) {
- length += os_strlen(defaults[i]);
- length++;
- attributes[attr_count++] = defaults[i];
- }
- }
- //MDNS_DBG("Found %d total attributes\n", attr_count);
- ans.len = htons(length);
- MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
- query = query + SIZEOF_DNS_ANSWER;
- // Check enough space in the packet
- const char *end_of_packet = query + length + 2 + SIZEOF_DNS_ANSWER + SIZEOF_MDNS_SERVICE +
- os_strlen(ms_info->host_name) + 7 + 1 + 2 + SIZEOF_DNS_ANSWER + SIZEOF_MDNS_AUTH;
- if (query_end <= end_of_packet) {
- MDNS_DBG("Too much data to send\n");
- pbuf_free(p);
- return ERR_MEM;
- }
- //MDNS_DBG("Query=%x, query_end=%x, end_ofpacket=%x, length=%x\n", query, query_end, end_of_packet, length);
- i = 0;
- while(attributes[i] != NULL && i < attr_count) {
- pHostname = attributes[i];
- --pHostname;
- /* convert hostname into suitable query format. */
- do {
- ++pHostname;
- nptr = query;
- ++query;
- for (n = 0; *pHostname != 0; ++pHostname) {
- *query = *pHostname;
- ++query;
- ++n;
- }
- *nptr = n;
- } while (*pHostname != 0);
- i++;
- }
- // *query++ = '\0';
- // Increment by length
- *query++ = 0xc0 + (name_offset >> 8);
- *query++ = name_offset & 0xff;
- // Increment by 2
- ans.type = htons(DNS_RRTYPE_SRV);
- ans.class = htons(dns_class);
- ans.ttl = htonl(300);
- c_strlcpy(tmpBuf,ms_info->host_name, sizeof(tmpBuf));
- c_strlcat(tmpBuf, ".", sizeof(tmpBuf));
- c_strlcat(tmpBuf, MDNS_LOCAL, sizeof(tmpBuf));
- length = os_strlen(tmpBuf) + MDNS_LENGTH_ADD;
- ans.len = htons(SIZEOF_MDNS_SERVICE + length);
- length = 0;
- MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
- /* resize the query */
- query = query + SIZEOF_DNS_ANSWER;
- serv.prior = htons(0);
- serv.weight = htons(0);
- serv.port = htons(ms_info->service_port);
- MEMCPY( query, &serv, SIZEOF_MDNS_SERVICE);
- /* resize the query */
- query = query + SIZEOF_MDNS_SERVICE;
- int hostname_offset = query - (const char *) hdr;
- pHostname = tmpBuf;
- --pHostname;
- do {
- ++pHostname;
- nptr = query;
- ++query;
- for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
- *query = *pHostname;
- ++query;
- ++n;
- }
- *nptr = n;
- } while (*pHostname != 0);
- *query++ = '\0';
- // increment by strlen(service_name) + 1 + 7 + sizeof_dns_answer + sizeof_mdns_service
-
- *query++ = 0xc0 + (hostname_offset >> 8);
- *query++ = hostname_offset & 0xff;
- ans.type = htons(DNS_RRTYPE_A);
- ans.class = htons(dns_class);
- ans.ttl = htonl(300);
- ans.len = htons(DNS_IP_ADDR_LEN);
- MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
- /* resize the query */
- query = query + SIZEOF_DNS_ANSWER;
-
- // increment by strlen(service_name) + 1 + 7 + sizeof_dns_answer
-
- /* fill the payload of the mDNS message */
- /* set the local IP address */
- auth.src = 0;
- MEMCPY( query, &auth, SIZEOF_MDNS_AUTH);
- u8_t *addr_ptr = query + ((char *) &auth.src - (char *) &auth);
- /* resize the query */
- query = query + SIZEOF_MDNS_AUTH;
- //MDNS_DBG("Final ptr=%x\n", query);
- // increment by sizeof_mdns_auth
- /* set the name of the authority field.
- * The same name as the Query using the offset address*/
- /* resize pbuf to the exact dns query */
- pbuf_realloc(p, (query) - ((char*) (p->payload)));
- err = send_packet(p, dst_addr, dst_port, addr_ptr);
- } else {
- MDNS_DBG("ERR_MEM \n");
- err = ERR_MEM;
- }
- return err;
- }
- /**
- * Receive input function for DNS response packets arriving for the dns UDP pcb.
- *
- * @params see udp.h
- */
- static void ICACHE_FLASH_ATTR
- mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr,
- u16_t port) {
- u16_t i;
- struct mdns_hdr *hdr;
- u8_t nquestions;
- LWIP_UNUSED_ARG(arg);
- LWIP_UNUSED_ARG(pcb);
- struct nodemcu_mdns_info *info = (struct nodemcu_mdns_info *)arg;
- /* is the dns message too big ? */
- if (p->tot_len > DNS_MSG_SIZE) {
- LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n"));
- /* free pbuf and return */
- goto memerr1;
- }
- /* is the dns message big enough ? */
- if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) {
- LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
- /* free pbuf and return */
- goto memerr1;
- }
- /* copy dns payload inside static buffer for processing */
- if (pbuf_copy_partial(p, mdns_payload, p->tot_len, 0) == p->tot_len) {
- /* The ID in the DNS header should be our entry into the name table. */
- hdr = (struct mdns_hdr*) mdns_payload;
- i = htons(hdr->id);
- nquestions = htons(hdr->numquestions);
- //nanswers = htons(hdr->numanswers);
- /* if we have a question send an answer if necessary */
- if (nquestions > 0) {
- struct mdns_query qry;
- int namelen = mdns_namelen((u8_t *) (hdr + 1), p->tot_len);
- memcpy(&qry, namelen + (u8_t *) (hdr + 1), sizeof(qry));
- u16_t qry_type = ntohs(qry.type);
- /* MDNS_DS_DOES_NAME_CHECK */
- /* Check if the name in the "question" part match with the name of the MDNS DS service. */
- if (mdns_compare_name((unsigned char *) DNS_SD_SERVICE,
- (unsigned char *) mdns_payload + SIZEOF_DNS_HDR) == 0) {
- if (qry_type == DNS_RRTYPE_PTR || qry_type == DNS_RRTYPE_ANY) {
- mdns_send_service_type(i, addr, port);
- }
- } else if (mdns_compare_name((unsigned char *) service_name_with_suffix,
- (unsigned char *) mdns_payload + SIZEOF_DNS_HDR) == 0) {
- if (qry_type == DNS_RRTYPE_PTR || qry_type == DNS_RRTYPE_ANY) {
- mdns_send_service(info, i, addr, port);
- }
- } else {
-
- char tmpBuf[PUCK_DATASHEET_SIZE + PUCK_SERVICE_LENGTH];
- c_strlcpy(tmpBuf,ms_info->host_name, sizeof(tmpBuf));
- c_strlcat(tmpBuf, ".", sizeof(tmpBuf));
- c_strlcat(tmpBuf, MDNS_LOCAL, sizeof(tmpBuf));
- if (mdns_compare_name((unsigned char *) tmpBuf,
- (unsigned char *) mdns_payload + SIZEOF_DNS_HDR) == 0) {
- if (qry_type == DNS_RRTYPE_A || qry_type == DNS_RRTYPE_ANY) {
- mdns_send_service(info, i, addr, port);
- }
- } else {
- c_strlcpy(tmpBuf,ms_info->host_desc, sizeof(tmpBuf));
- c_strlcat(tmpBuf, ".", sizeof(tmpBuf));
- c_strlcat(tmpBuf, service_name_with_suffix, sizeof(tmpBuf));
- if (mdns_compare_name((unsigned char *) tmpBuf,
- (unsigned char *) mdns_payload + SIZEOF_DNS_HDR) == 0) {
- if (qry_type == DNS_RRTYPE_TXT || qry_type == DNS_RRTYPE_SRV || qry_type == DNS_RRTYPE_ANY) {
- mdns_send_service(info, i, addr, port);
- }
- }
- }
- }
- }
- }
- memerr1:
- /* free pbuf */
- pbuf_free(p);
- return;
- }
- static void
- mdns_free_info(struct nodemcu_mdns_info *info) {
- os_free((void *) info);
- }
- /**
- * close the UDP pcb .
- */
- void ICACHE_FLASH_ATTR
- nodemcu_mdns_close(void)
- {
- os_timer_disarm(&mdns_timer);
- if (mdns_pcb != NULL) {
- udp_remove(mdns_pcb);
- }
- if (mdns_payload) {
- os_free(mdns_payload);
- }
- mdns_payload = NULL;
- mdns_pcb = NULL;
- mdns_free_info(ms_info);
- ms_info = NULL;
- }
- static void ICACHE_FLASH_ATTR
- mdns_set_servicename(const char *name) {
- char tmpBuf[128];
- os_sprintf(tmpBuf, "_%s._tcp.local", name);
- if (service_name_with_suffix) {
- os_free(service_name_with_suffix);
- }
- service_name_with_suffix = c_strdup(tmpBuf);
- }
- static u8_t reg_counter;
- static void
- mdns_reg_handler_restart(void) {
- reg_counter = 99;
- }
- static void ICACHE_FLASH_ATTR
- mdns_reg(struct nodemcu_mdns_info *info) {
- mdns_send_service(info,0,0,0);
- if (reg_counter++ > 10) {
- mdns_send_service_type(0,0,0);
- reg_counter = 0;
- }
- }
- static struct nodemcu_mdns_info *
- mdns_dup_info(const struct nodemcu_mdns_info *info) {
- struct nodemcu_mdns_info *result;
- // calculate length
- int len = sizeof(struct nodemcu_mdns_info);
- len += c_strlen(info->host_name) + 1;
- len += c_strlen(info->host_desc) + 1;
- len += c_strlen(info->service_name) + 1;
- int i;
- for (i = 0; i < sizeof(info->txt_data) / sizeof(info->txt_data[0]) && info->txt_data[i]; i++) {
- len += c_strlen(info->txt_data[i]) + 1;
- }
- #define COPY_OVER(dest, src, p) len = c_strlen(src) + 1; memcpy(p, src, len); dest = p; p += len
- result = (struct nodemcu_mdns_info *) os_zalloc(len);
- if (result) {
- char *p = (char *) (result + 1);
- result->service_port = info->service_port;
- COPY_OVER(result->host_name, info->host_name, p);
- COPY_OVER(result->host_desc, info->host_desc, p);
- COPY_OVER(result->service_name, info->service_name, p);
- for (i = 0; i < sizeof(info->txt_data) / sizeof(info->txt_data[0]) && info->txt_data[i]; i++) {
- COPY_OVER(result->txt_data[i], info->txt_data[i], p);
- }
- }
- #undef COPY_OVER
- return result;
- }
- /**
- * Initialize the resolver: set up the UDP pcb and configure the default server
- * (NEW IP).
- *
- * returns TRUE if it worked, FALSE if it failed.
- */
- bool ICACHE_FLASH_ATTR
- nodemcu_mdns_init(struct nodemcu_mdns_info *info) {
- /* initialize default DNS server address */
- multicast_addr.addr = DNS_MULTICAST_ADDRESS;
- struct ip_info ipconfig;
- mdns_free_info(ms_info);
- ms_info = mdns_dup_info(info); // Save the passed block. We need all the data forever
- if (!ms_info) {
- return FALSE;
- }
- if (mdns_payload) {
- os_free(mdns_payload);
- }
- mdns_payload = (u8_t *) os_malloc(DNS_MSG_SIZE);
- if (!mdns_payload) {
- MDNS_DBG("Alloc fail\n");
- return FALSE;
- }
- LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
- mdns_set_servicename(ms_info->service_name);
- // get the host name as instrumentName_serialNumber for MDNS
- // set the name of the service, the same as host name
- MDNS_DBG("host_name = %s\n", ms_info->host_name);
- MDNS_DBG("server_name = %s\n", service_name_with_suffix);
- /* initialize mDNS */
- mdns_pcb = udp_new();
- if (!mdns_pcb) {
- return FALSE;
- }
- /* join to the multicast address 224.0.0.251 */
- if(wifi_get_opmode() & 0x01) {
- struct netif *sta_netif = (struct netif *)eagle_lwip_getif(0x00);
- if (sta_netif && sta_netif->ip_addr.addr && igmp_joingroup(&sta_netif->ip_addr, &multicast_addr) != ERR_OK) {
- MDNS_DBG("sta udp_join_multigrup failed!\n");
- return FALSE;
- };
- }
- if(wifi_get_opmode() & 0x02) {
- struct netif *ap_netif = (struct netif *)eagle_lwip_getif(0x01);
- if (ap_netif && ap_netif->ip_addr.addr && igmp_joingroup(&ap_netif->ip_addr, &multicast_addr) != ERR_OK) {
- MDNS_DBG("ap udp_join_multigrup failed!\n");
- return FALSE;
- };
- }
- register_flag = 1;
- /* join to any IP address at the port 5353 */
- if (udp_bind(mdns_pcb, IP_ADDR_ANY, DNS_MDNS_PORT) != ERR_OK) {
- MDNS_DBG("udp_bind failed!\n");
- return FALSE;
- };
- /*loopback function for the multicast(224.0.0.251) messages received at port 5353*/
- udp_recv(mdns_pcb, mdns_recv, ms_info);
- mdns_flag = 1;
- /*
- * Register the name of the instrument
- */
- //MDNS_DBG("About to start timer\n");
- os_timer_disarm(&mdns_timer);
- os_timer_setfn(&mdns_timer, (os_timer_func_t *)mdns_reg,ms_info);
- os_timer_arm(&mdns_timer, 1000 * 120, 1);
- /* kick off the first one right away */
- mdns_reg_handler_restart();
- mdns_reg(ms_info);
- return TRUE;
- }
- #endif /* LWIP_MDNS */
|