mdns.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136
  1. /**
  2. * lwip MDNS resolver file.
  3. *
  4. * Created on: Jul 29, 2010
  5. * Author: Daniel Toma
  6. *
  7. * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. The name of the author may not be used to endorse or promote
  18. * products derived from this software without specific prior
  19. * written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
  22. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  23. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  25. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  27. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  28. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  29. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  30. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. /**
  34. * This file implements a MDNS host name and PUCK service registration.
  35. *-----------------------------------------------------------------------------
  36. * Includes
  37. *----------------------------------------------------------------------------*/
  38. #include "lwip/opt.h"
  39. #if LWIP_MDNS /* don't build if not configured for use in lwipopts.h */
  40. #include "lwip/mdns.h"
  41. #include "lwip/puck_def.h"
  42. #include "lwip/udp.h"
  43. #include "lwip/mem.h"
  44. #include "lwip/igmp.h"
  45. #include "osapi.h"
  46. #include "os_type.h"
  47. #include "user_interface.h"
  48. #ifdef MEMLEAK_DEBUG
  49. static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
  50. #endif
  51. /** DNS server IP address */
  52. #ifndef DNS_MULTICAST_ADDRESS
  53. #define DNS_MULTICAST_ADDRESS ipaddr_addr("224.0.0.251") /* resolver1.opendns.com */
  54. #endif
  55. /** DNS server IP address */
  56. #ifndef MDNS_LOCAL
  57. #define MDNS_LOCAL "local" /* resolver1.opendns.com */
  58. #endif
  59. /** DNS server port address */
  60. #ifndef DNS_MDNS_PORT
  61. #define DNS_MDNS_PORT 5353
  62. #endif
  63. /** DNS maximum number of retries when asking for a name, before "timeout". */
  64. #ifndef DNS_MAX_RETRIES
  65. #define DNS_MAX_RETRIES 4
  66. #endif
  67. /** DNS resource record max. TTL (one week as default) */
  68. #ifndef DNS_MAX_TTL
  69. #define DNS_MAX_TTL 604800
  70. #endif
  71. /* DNS protocol flags */
  72. #define DNS_FLAG1_RESPONSE 0x84
  73. #define DNS_FLAG1_OPCODE_STATUS 0x10
  74. #define DNS_FLAG1_OPCODE_INVERSE 0x08
  75. #define DNS_FLAG1_OPCODE_STANDARD 0x00
  76. #define DNS_FLAG1_AUTHORATIVE 0x04
  77. #define DNS_FLAG1_TRUNC 0x02
  78. #define DNS_FLAG1_RD 0x01
  79. #define DNS_FLAG2_RA 0x80
  80. #define DNS_FLAG2_ERR_MASK 0x0f
  81. #define DNS_FLAG2_ERR_NONE 0x00
  82. #define DNS_FLAG2_ERR_NAME 0x03
  83. /* DNS protocol states */
  84. #define DNS_STATE_UNUSED 0
  85. #define DNS_STATE_NEW 1
  86. #define DNS_STATE_ASKING 2
  87. #define DNS_STATE_DONE 3
  88. /* MDNS registration type */
  89. #define MDNS_HOSTNAME_REG 0
  90. #define MDNS_SERVICE_REG 1
  91. /* MDNS registration type */
  92. #define MDNS_REG_ANSWER 1
  93. #define MDNS_SD_ANSWER 2
  94. #define MDNS_SERVICE_REG_ANSWER 3
  95. /* MDNS registration time */
  96. #define MDNS_HOST_TIME 120
  97. #define MDNS_SERVICE_TIME 3600
  98. /** MDNS name length with "." at the beginning and end of name*/
  99. #ifndef MDNS_LENGTH_ADD
  100. #define MDNS_LENGTH_ADD 2
  101. #endif
  102. #ifdef MDNS_MAX_NAME_LENGTH
  103. #undef MDNS_MAX_NAME_LENGTH
  104. #endif
  105. #define MDNS_MAX_NAME_LENGTH (256)
  106. PACK_STRUCT_BEGIN
  107. /** DNS message header */
  108. struct mdns_hdr {
  109. PACK_STRUCT_FIELD(u16_t id);
  110. PACK_STRUCT_FIELD(u8_t flags1);
  111. PACK_STRUCT_FIELD(u8_t flags2);
  112. PACK_STRUCT_FIELD(u16_t numquestions);
  113. PACK_STRUCT_FIELD(u16_t numanswers);
  114. PACK_STRUCT_FIELD(u16_t numauthrr);
  115. PACK_STRUCT_FIELD(u16_t numextrarr);
  116. }PACK_STRUCT_STRUCT;
  117. PACK_STRUCT_END
  118. #define SIZEOF_DNS_HDR 12
  119. PACK_STRUCT_BEGIN
  120. /** MDNS query message structure */
  121. struct mdns_query {
  122. /* MDNS query record starts with either a domain name or a pointer
  123. to a name already present somewhere in the packet. */PACK_STRUCT_FIELD(u16_t type);
  124. PACK_STRUCT_FIELD(u16_t class);
  125. }PACK_STRUCT_STRUCT;
  126. PACK_STRUCT_END
  127. #define SIZEOF_DNS_QUERY 4
  128. PACK_STRUCT_BEGIN
  129. /** MDNS answer message structure */
  130. struct mdns_answer {
  131. /* MDNS answer record starts with either a domain name or a pointer
  132. to a name already present somewhere in the packet. */PACK_STRUCT_FIELD(u16_t type);
  133. PACK_STRUCT_FIELD(u16_t class);
  134. PACK_STRUCT_FIELD(u32_t ttl);
  135. PACK_STRUCT_FIELD(u16_t len);
  136. }PACK_STRUCT_STRUCT;
  137. PACK_STRUCT_END
  138. #define SIZEOF_DNS_ANSWER 10
  139. PACK_STRUCT_BEGIN
  140. /** MDNS answer message structure */
  141. struct mdns_auth {
  142. PACK_STRUCT_FIELD(u32_t src);
  143. }PACK_STRUCT_STRUCT;
  144. PACK_STRUCT_END
  145. #define SIZEOF_MDNS_AUTH 4
  146. PACK_STRUCT_BEGIN
  147. /** MDNS service registration message structure */
  148. struct mdns_service {
  149. PACK_STRUCT_FIELD(u16_t prior);
  150. PACK_STRUCT_FIELD(u16_t weight);
  151. PACK_STRUCT_FIELD(u16_t port);
  152. }PACK_STRUCT_STRUCT;
  153. PACK_STRUCT_END
  154. #define SIZEOF_MDNS_SERVICE 6
  155. uint16 PUCK_PORT ;
  156. os_timer_t mdns_timer;
  157. /* forward declarations */
  158. static void mdns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p,
  159. struct ip_addr *addr, u16_t port);
  160. /*-----------------------------------------------------------------------------
  161. * Globales
  162. *----------------------------------------------------------------------------*/
  163. /* MDNS variables */
  164. static char host_name[MDNS_NAME_LENGTH];
  165. static char service_name[MDNS_NAME_LENGTH];
  166. static char server_name[MDNS_NAME_LENGTH];
  167. //static char puck_datasheet[PUCK_DATASHEET_SIZE];
  168. static struct udp_pcb *mdns_pcb = NULL;
  169. static struct mdns_info * ms_info = NULL;
  170. static struct ip_addr multicast_addr;
  171. static struct ip_addr host_addr;
  172. static uint8 register_flag = 0;
  173. static uint8 mdns_flag = 0;
  174. //#if (DNS_USES_STATIC_BUF == 1)
  175. static u8_t mdns_payload[DNS_MSG_SIZE];
  176. //#endif /* (MDNS_USES_STATIC_BUF == 1) */
  177. /*
  178. * Function to set the UDP pcb used to send the mDNS packages
  179. */
  180. void ICACHE_FLASH_ATTR
  181. getPcb(struct udp_pcb *pcb) {
  182. mdns_pcb = pcb;
  183. }
  184. #if DNS_DOES_NAME_CHECK
  185. /**
  186. * Compare the "dotted" name "query" with the encoded name "response"
  187. * to make sure an answer from the DNS server matches the current mdns_table
  188. * entry (otherwise, answers might arrive late for hostname not on the list
  189. * any more).
  190. *
  191. * @param query hostname (not encoded) from the mdns_table
  192. * @param response encoded hostname in the DNS response
  193. * @return 0: names equal; 1: names differ
  194. */
  195. static u8_t ICACHE_FLASH_ATTR
  196. mdns_compare_name(unsigned char *query, unsigned char *response) {
  197. unsigned char n;
  198. do {
  199. n = *response++;
  200. /** @see RFC 1035 - 4.1.4. Message compression */
  201. if ((n & 0xc0) == 0xc0) {
  202. /* Compressed name */
  203. break;
  204. } else {
  205. /* Not compressed name */
  206. while (n > 0) {
  207. if ((*query) != (*response)) {
  208. return 1;
  209. }
  210. ++response;
  211. ++query;
  212. --n;
  213. };
  214. ++query;
  215. }
  216. } while (*response != 0);
  217. return 0;
  218. }
  219. #endif /* DNS_DOES_NAME_CHECK */
  220. /**
  221. * Send a mDNS answer packet.
  222. *
  223. * @param type of answer hostname and service registration or service
  224. * @param name to query
  225. * @param id transaction ID in the DNS query packet
  226. * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
  227. */
  228. static err_t ICACHE_FLASH_ATTR
  229. mdns_answer(u16_t type, const char* name, u8_t id) {
  230. err_t err;
  231. struct mdns_hdr *hdr;
  232. struct mdns_answer ans;
  233. struct mdns_auth auth;
  234. struct mdns_service serv;
  235. struct pbuf *p ,*p_sta;
  236. char *query, *nptr;
  237. const char *pHostname;
  238. struct netif * sta_netif = NULL;
  239. struct netif * ap_netif = NULL;
  240. static char tmpBuf[PUCK_DATASHEET_SIZE + PUCK_SERVICE_LENGTH];
  241. u8_t n;
  242. u16_t length = 0;
  243. /* if here, we have either a new query or a retry on a previous query to process */
  244. p = pbuf_alloc(PBUF_TRANSPORT,
  245. SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
  246. if (p != NULL) {
  247. LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
  248. /* fill dns header */
  249. hdr = (struct mdns_hdr*) p->payload;
  250. os_memset(hdr, 0, SIZEOF_DNS_HDR);
  251. hdr->id = htons(id);
  252. hdr->flags1 = DNS_FLAG1_RESPONSE;
  253. if (type == MDNS_SD_ANSWER) {
  254. pHostname = DNS_SD_SERVICE;
  255. hdr->numanswers = htons(1);
  256. } else if (type == MDNS_SERVICE_REG_ANSWER) {
  257. pHostname = PUCK_SERVICE;
  258. hdr->numanswers = htons(type);
  259. } else {
  260. pHostname = name;
  261. hdr->numanswers = htons(type);
  262. }
  263. query = (char*) hdr + SIZEOF_DNS_HDR;
  264. --pHostname;
  265. /* convert hostname into suitable query format. */
  266. do {
  267. ++pHostname;
  268. nptr = query;
  269. ++query;
  270. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  271. *query = *pHostname;
  272. ++query;
  273. ++n;
  274. }
  275. *nptr = n;
  276. } while (*pHostname != 0);
  277. *query++ = '\0';
  278. /* fill dns query */
  279. if (type == MDNS_REG_ANSWER) {
  280. ans.type = htons(DNS_RRTYPE_A);
  281. ans.class = htons(DNS_RRCLASS_IN);
  282. ans.ttl = htonl(MDNS_SERVICE_TIME);
  283. ans.len = htons(DNS_IP_ADDR_LEN);
  284. length = DNS_IP_ADDR_LEN;
  285. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  286. /* resize the query */
  287. query = query + SIZEOF_DNS_ANSWER;
  288. /* set the local IP address */
  289. auth.src = host_addr.addr;
  290. MEMCPY( query, &auth, SIZEOF_MDNS_AUTH);
  291. }
  292. if (type == MDNS_SD_ANSWER) {
  293. ans.type = htons(DNS_RRTYPE_PTR);
  294. ans.class = htons(DNS_RRCLASS_IN);
  295. ans.ttl = htonl(300);
  296. ans.len = htons(os_strlen(PUCK_SERVICE) + 1 +1 );
  297. length = 0;
  298. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  299. /* resize the query */
  300. query = query + SIZEOF_DNS_ANSWER;
  301. pHostname = PUCK_SERVICE;
  302. --pHostname;
  303. /* convert hostname into suitable query format. */
  304. do {
  305. ++pHostname;
  306. nptr = query;
  307. ++query;
  308. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  309. *query = *pHostname;
  310. ++query;
  311. ++n;
  312. }
  313. *nptr = n;
  314. } while (*pHostname != 0);
  315. *query++ = '\0';
  316. }
  317. if (type == MDNS_SERVICE_REG_ANSWER) {
  318. ans.type = htons(DNS_RRTYPE_PTR);
  319. ans.class = htons(DNS_RRCLASS_IN);
  320. ans.ttl = htonl(MDNS_SERVICE_TIME);
  321. os_strcpy(tmpBuf, name);
  322. os_strcat(tmpBuf, ".");
  323. os_strcat(tmpBuf, PUCK_SERVICE);
  324. length = os_strlen(tmpBuf) + MDNS_LENGTH_ADD;
  325. ans.len = htons(length);
  326. length = 0;
  327. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  328. /* resize the query */
  329. query = query + SIZEOF_DNS_ANSWER;
  330. pHostname = tmpBuf;
  331. --pHostname;
  332. /* convert hostname into suitable query format. */
  333. do {
  334. ++pHostname;
  335. nptr = query;
  336. ++query;
  337. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  338. *query = *pHostname;
  339. ++query;
  340. ++n;
  341. }
  342. *nptr = n;
  343. } while (*pHostname != 0);
  344. *query++ = '\0';
  345. /* Service query*/
  346. pHostname = name;
  347. --pHostname;
  348. /* convert hostname into suitable query format. */
  349. do {
  350. ++pHostname;
  351. nptr = query;
  352. ++query;
  353. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  354. *query = *pHostname;
  355. ++query;
  356. ++n;
  357. }
  358. *nptr = n;
  359. } while (*pHostname != 0);
  360. /* Add to the service name the service local
  361. * pointing to the beginning of the mDNS message*/
  362. *query++ = DNS_OFFSET_FLAG;
  363. *query++ = DNS_DEFAULT_OFFSET;
  364. /* fill the query */
  365. ans.type = htons(DNS_RRTYPE_SRV);
  366. ans.class = htons(DNS_RRCLASS_FLUSH_IN);
  367. ans.ttl = htonl(MDNS_SERVICE_TIME);
  368. os_strcpy(tmpBuf, host_name);
  369. os_strcat(tmpBuf, ".");
  370. os_strcat(tmpBuf, MDNS_LOCAL);
  371. length = os_strlen(tmpBuf) + MDNS_LENGTH_ADD;
  372. ans.len = htons(SIZEOF_MDNS_SERVICE + length);
  373. length = 0;
  374. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  375. /* resize the query */
  376. query = query + SIZEOF_DNS_ANSWER;
  377. /* fill the service properties */
  378. serv.prior = htons(0);
  379. serv.weight = htons(0);
  380. serv.port = htons(PUCK_PORT);
  381. MEMCPY( query, &serv, SIZEOF_MDNS_SERVICE);
  382. /* resize the query */
  383. query = query + SIZEOF_MDNS_SERVICE;
  384. pHostname = tmpBuf;
  385. --pHostname;
  386. /* convert hostname into suitable query format. */
  387. do {
  388. ++pHostname;
  389. nptr = query;
  390. ++query;
  391. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  392. *query = *pHostname;
  393. ++query;
  394. ++n;
  395. }
  396. *nptr = n;
  397. } while (*pHostname != 0);
  398. *query++ = '\0';
  399. /* TXT answer */
  400. pHostname = name;
  401. --pHostname;
  402. /* convert hostname into suitable query format. */
  403. do {
  404. ++pHostname;
  405. nptr = query;
  406. ++query;
  407. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  408. *query = *pHostname;
  409. ++query;
  410. ++n;
  411. }
  412. *nptr = n;
  413. } while (*pHostname != 0);
  414. /* Add to the service name the service local
  415. * pointing to the beginning of the mDNS message*/
  416. *query++ = DNS_OFFSET_FLAG;
  417. *query++ = DNS_DEFAULT_OFFSET;
  418. /* fill the answer */
  419. ans.type = htons(DNS_RRTYPE_TXT);
  420. ans.class = htons(DNS_RRCLASS_IN);
  421. ans.ttl = htonl(MDNS_SERVICE_TIME);
  422. length = sizeof(SERVICE_DESCRIPTION);
  423. ans.len = htons(length);
  424. length = 0;
  425. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  426. /* resize the query */
  427. query = query + SIZEOF_DNS_ANSWER;
  428. pHostname = SERVICE_DESCRIPTION;
  429. --pHostname;
  430. /* convert hostname into suitable query format. */
  431. do {
  432. ++pHostname;
  433. nptr = query;
  434. ++query;
  435. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  436. *query = *pHostname;
  437. ++query;
  438. ++n;
  439. }
  440. *nptr = n;
  441. } while (*pHostname != 0);
  442. *query++ = '\0';
  443. }
  444. /* resize pbuf to the exact dns query */
  445. pbuf_realloc(p, (query + length) - ((char*) (p->payload)));
  446. /* send dns packet */
  447. /*add by tzx for AP + STA MDNS begin------*/
  448. sta_netif = (struct netif *)eagle_lwip_getif(0x00);
  449. ap_netif = (struct netif *)eagle_lwip_getif(0x01);
  450. if(wifi_get_opmode() == 0x03 && wifi_get_broadcast_if() == 0x03 &&\
  451. sta_netif != NULL && ap_netif != NULL) {
  452. if(netif_is_up(sta_netif) && netif_is_up(ap_netif)) {
  453. p_sta = pbuf_alloc(PBUF_TRANSPORT,
  454. SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
  455. if (pbuf_copy (p_sta,p) != ERR_OK) {
  456. os_printf("mdns_answer copying to new pbuf failed\n");
  457. return -1;
  458. }
  459. netif_set_default(sta_netif);
  460. err = udp_sendto(mdns_pcb, p_sta, &multicast_addr, DNS_MDNS_PORT);
  461. pbuf_free(p_sta);
  462. netif_set_default(ap_netif);
  463. }
  464. }
  465. /*add by tzx for AP + STA MDNS end------*/
  466. err = udp_sendto(mdns_pcb, p, &multicast_addr, DNS_MDNS_PORT);
  467. /* free pbuf */
  468. pbuf_free(p);
  469. } else {
  470. err = ERR_MEM;
  471. }
  472. return err;
  473. }
  474. /**
  475. * Send a mDNS service answer packet.
  476. *
  477. * @param name service name to query
  478. * @param id transaction ID in the DNS query packet
  479. * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
  480. */
  481. static err_t ICACHE_FLASH_ATTR
  482. mdns_send_service(struct mdns_info *info, u8_t id) {
  483. err_t err;
  484. struct mdns_hdr *hdr;
  485. struct mdns_answer ans;
  486. struct mdns_service serv;
  487. struct mdns_auth auth;
  488. struct pbuf *p ,*p_sta;
  489. char *query, *nptr;
  490. const char *pHostname;
  491. char *device_info;
  492. const char *name = info->host_name;
  493. u8_t n;
  494. u8_t i = 0;
  495. u16_t length = 0;
  496. u8_t addr1 = 12, addr2 = 12;
  497. struct netif * sta_netif = NULL;
  498. struct netif * ap_netif = NULL;
  499. static char tmpBuf[PUCK_DATASHEET_SIZE + PUCK_SERVICE_LENGTH];
  500. /* if here, we have either a new query or a retry on a previous query to process */
  501. p = pbuf_alloc(PBUF_TRANSPORT,
  502. SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
  503. if (p != NULL) {
  504. LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
  505. /* fill dns header */
  506. hdr = (struct mdns_hdr*) p->payload;
  507. os_memset(hdr, 0, SIZEOF_DNS_HDR);
  508. hdr->id = htons(id);
  509. hdr->flags1 = DNS_FLAG1_RESPONSE;
  510. hdr->numanswers = htons(4);
  511. query = (char*) hdr + SIZEOF_DNS_HDR;
  512. os_strcpy(tmpBuf, PUCK_SERVICE);
  513. pHostname = tmpBuf;
  514. --pHostname;
  515. /* convert hostname into suitable query format. */
  516. do {
  517. ++pHostname;
  518. nptr = query;
  519. ++query;
  520. ++addr1;
  521. ++addr2;
  522. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  523. *query = *pHostname;
  524. ++query;
  525. ++addr1;
  526. ++addr2;
  527. ++n;
  528. }
  529. *nptr = n;
  530. } while (*pHostname != 0);
  531. *query++ = '\0';
  532. length = sizeof(MDNS_LOCAL);
  533. addr1 -= length;
  534. length = os_strlen(PUCK_SERVICE) + 1;
  535. addr2 -= length;
  536. ans.type = htons(DNS_RRTYPE_PTR);
  537. ans.class = htons(DNS_RRCLASS_IN);
  538. ans.ttl = htonl(300);
  539. os_strcpy(tmpBuf, name);
  540. length = os_strlen(tmpBuf) + MDNS_LENGTH_ADD + 1;
  541. ans.len = htons(length);
  542. length = 0;
  543. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  544. /* resize the query */
  545. query = query + SIZEOF_DNS_ANSWER;
  546. pHostname = tmpBuf;
  547. --pHostname;
  548. /* convert hostname into suitable query format. */
  549. do {
  550. ++pHostname;
  551. nptr = query;
  552. ++query;
  553. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  554. *query = *pHostname;
  555. ++query;
  556. ++n;
  557. }
  558. *nptr = n;
  559. } while (*pHostname != 0);
  560. *query++ = DNS_OFFSET_FLAG;
  561. *query++ = DNS_DEFAULT_OFFSET;
  562. pHostname = name;
  563. --pHostname;
  564. /* convert hostname into suitable query format. */
  565. do {
  566. ++pHostname;
  567. nptr = query;
  568. ++query;
  569. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  570. *query = *pHostname;
  571. ++query;
  572. ++n;
  573. }
  574. *nptr = n;
  575. } while (*pHostname != 0);
  576. //*query++ = '\0';
  577. *query++ = DNS_OFFSET_FLAG;
  578. *query++ = DNS_DEFAULT_OFFSET;
  579. /* fill the answer */
  580. ans.type = htons(DNS_RRTYPE_TXT);
  581. ans.class = htons(DNS_RRCLASS_FLUSH_IN);
  582. ans.ttl = htonl(300);
  583. // length = os_strlen(TXT_DATA) + MDNS_LENGTH_ADD + 1;
  584. device_info = (char *)os_zalloc(50);
  585. ets_sprintf(device_info,"vendor = %s","Espressif");
  586. for(i = 0; i < 10 &&(info->txt_data[i] != NULL);i++) {
  587. length += os_strlen(info->txt_data[i]);
  588. length++;
  589. }
  590. length += os_strlen(device_info)+ 1 ;
  591. ans.len = htons(length);
  592. length = 0;
  593. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  594. query = query + SIZEOF_DNS_ANSWER;
  595. pHostname = device_info;
  596. --pHostname;
  597. /* convert hostname into suitable query format. */
  598. do {
  599. ++pHostname;
  600. nptr = query;
  601. ++query;
  602. for (n = 0; *pHostname != 0; ++pHostname) {
  603. *query = *pHostname;
  604. ++query;
  605. ++n;
  606. }
  607. *nptr = n;
  608. } while (*pHostname != 0);
  609. i = 0;
  610. while(info->txt_data[i] != NULL && i < 10) {
  611. pHostname = info->txt_data[i];
  612. --pHostname;
  613. /* convert hostname into suitable query format. */
  614. do {
  615. ++pHostname;
  616. nptr = query;
  617. ++query;
  618. for (n = 0; *pHostname != 0; ++pHostname) {
  619. *query = *pHostname;
  620. ++query;
  621. ++n;
  622. }
  623. *nptr = n;
  624. } while (*pHostname != 0);
  625. i++;
  626. }
  627. // *query++ = '\0';
  628. os_free(device_info);
  629. os_strcpy(tmpBuf, name);
  630. pHostname = tmpBuf;
  631. --pHostname;
  632. do {
  633. ++pHostname;
  634. nptr = query;
  635. ++query;
  636. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  637. *query = *pHostname;
  638. ++query;
  639. ++n;
  640. }
  641. *nptr = n;
  642. } while (*pHostname != 0);
  643. *query++ = DNS_OFFSET_FLAG;
  644. *query++ = DNS_DEFAULT_OFFSET;
  645. ans.type = htons(DNS_RRTYPE_SRV);
  646. ans.class = htons(DNS_RRCLASS_FLUSH_IN);
  647. ans.ttl = htonl(300);
  648. os_strcpy(tmpBuf,service_name);
  649. os_strcat(tmpBuf, ".");
  650. os_strcat(tmpBuf, MDNS_LOCAL);
  651. length = os_strlen(tmpBuf) + MDNS_LENGTH_ADD;
  652. ans.len = htons(SIZEOF_MDNS_SERVICE + length);
  653. length = 0;
  654. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  655. /* resize the query */
  656. query = query + SIZEOF_DNS_ANSWER;
  657. serv.prior = htons(0);
  658. serv.weight = htons(0);
  659. serv.port = htons(PUCK_PORT);
  660. MEMCPY( query, &serv, SIZEOF_MDNS_SERVICE);
  661. /* resize the query */
  662. query = query + SIZEOF_MDNS_SERVICE;
  663. pHostname = tmpBuf;
  664. --pHostname;
  665. do {
  666. ++pHostname;
  667. nptr = query;
  668. ++query;
  669. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  670. *query = *pHostname;
  671. ++query;
  672. ++n;
  673. }
  674. *nptr = n;
  675. } while (*pHostname != 0);
  676. *query++ = '\0';
  677. /* set the name of the authority field.
  678. * The same name as the Query using the offset address*/
  679. os_strcpy(tmpBuf,service_name);
  680. os_strcat(tmpBuf, ".");
  681. os_strcat(tmpBuf, MDNS_LOCAL);
  682. pHostname = tmpBuf;
  683. --pHostname;
  684. do {
  685. ++pHostname;
  686. nptr = query;
  687. ++query;
  688. for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
  689. *query = *pHostname;
  690. ++query;
  691. ++n;
  692. }
  693. *nptr = n;
  694. } while (*pHostname != 0);
  695. *query++ = '\0';
  696. /* set the name of the authority field.
  697. * The same name as the Query using the offset address*/
  698. //*query++ = DNS_OFFSET_FLAG;
  699. //*query++ = DNS_DEFAULT_OFFSET;
  700. ans.type = htons(DNS_RRTYPE_A);
  701. ans.class = htons(DNS_RRCLASS_FLUSH_IN);
  702. ans.ttl = htonl(300);
  703. ans.len = htons(DNS_IP_ADDR_LEN);
  704. MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
  705. /* resize the query */
  706. query = query + SIZEOF_DNS_ANSWER;
  707. /* fill the payload of the mDNS message */
  708. /* set the local IP address */
  709. auth.src = host_addr.addr; //ipAddr;
  710. MEMCPY( query, &auth, SIZEOF_MDNS_AUTH);
  711. /* resize the query */
  712. query = query + SIZEOF_MDNS_AUTH;
  713. /* set the name of the authority field.
  714. * The same name as the Query using the offset address*/
  715. /* resize pbuf to the exact dns query */
  716. pbuf_realloc(p, (query) - ((char*) (p->payload)));
  717. /* send dns packet */
  718. sta_netif = (struct netif *)eagle_lwip_getif(0x00);
  719. ap_netif = (struct netif *)eagle_lwip_getif(0x01);
  720. if(wifi_get_opmode() == 0x03 && wifi_get_broadcast_if() == 0x03 &&\
  721. sta_netif != NULL && ap_netif != NULL) {
  722. if(netif_is_up(sta_netif) && netif_is_up(ap_netif)) {
  723. p_sta = pbuf_alloc(PBUF_TRANSPORT,
  724. SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
  725. if (pbuf_copy (p_sta,p) != ERR_OK) {
  726. os_printf("mdns_send_service copying to new pbuf failed\n");
  727. return -1;
  728. }
  729. netif_set_default(sta_netif);
  730. err = udp_sendto(mdns_pcb, p_sta, &multicast_addr, DNS_MDNS_PORT);
  731. pbuf_free(p_sta);
  732. netif_set_default(ap_netif);
  733. }
  734. }
  735. err = udp_sendto(mdns_pcb, p, &multicast_addr, DNS_MDNS_PORT);
  736. /* free pbuf */
  737. pbuf_free(p);
  738. } else {
  739. os_printf("ERR_MEM \n");
  740. err = ERR_MEM;
  741. }
  742. return err;
  743. }
  744. /**
  745. * Receive input function for DNS response packets arriving for the dns UDP pcb.
  746. *
  747. * @params see udp.h
  748. */
  749. static void ICACHE_FLASH_ATTR
  750. mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr,
  751. u16_t port) {
  752. u8_t i;
  753. struct mdns_hdr *hdr;
  754. u8_t nquestions;
  755. LWIP_UNUSED_ARG(arg);
  756. LWIP_UNUSED_ARG(pcb);
  757. LWIP_UNUSED_ARG(addr);
  758. LWIP_UNUSED_ARG(port);
  759. struct mdns_info *info = (struct mdns_info *)arg;
  760. /* is the dns message too big ? */
  761. if (p->tot_len > DNS_MSG_SIZE) {
  762. LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n"));
  763. /* free pbuf and return */
  764. goto memerr1;
  765. }
  766. /* is the dns message big enough ? */
  767. if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) {
  768. LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
  769. /* free pbuf and return */
  770. goto memerr1;
  771. }
  772. /* copy dns payload inside static buffer for processing */
  773. if (pbuf_copy_partial(p, mdns_payload, p->tot_len, 0) == p->tot_len) {
  774. /* The ID in the DNS header should be our entry into the name table. */
  775. hdr = (struct mdns_hdr*) mdns_payload;
  776. i = htons(hdr->id);
  777. if (i < DNS_TABLE_SIZE) {
  778. nquestions = htons(hdr->numquestions);
  779. //nanswers = htons(hdr->numanswers);
  780. /* if we have a question send an answer if necessary */
  781. if (nquestions > 0) {
  782. /* MDNS_DS_DOES_NAME_CHECK */
  783. /* Check if the name in the "question" part match with the name of the MDNS DS service. */
  784. if (mdns_compare_name((unsigned char *) DNS_SD_SERVICE,
  785. (unsigned char *) mdns_payload + SIZEOF_DNS_HDR) == 0) {
  786. /* respond with the puck service*/
  787. mdns_answer(MDNS_SD_ANSWER, PUCK_SERVICE, 0);
  788. } else if (mdns_compare_name((unsigned char *) PUCK_SERVICE,
  789. (unsigned char *) mdns_payload + SIZEOF_DNS_HDR) == 0) {
  790. /* respond with the puck service*/
  791. mdns_send_service(info, 0);
  792. } else
  793. goto memerr2;
  794. }
  795. }
  796. }
  797. goto memerr2;
  798. memerr2:
  799. os_memset(mdns_payload , 0 ,DNS_MSG_SIZE);
  800. memerr1:
  801. /* free pbuf */
  802. pbuf_free(p);
  803. return;
  804. }
  805. /**
  806. * close the UDP pcb .
  807. */
  808. void ICACHE_FLASH_ATTR
  809. mdns_close(void)
  810. {
  811. uint8 text_index = 0;
  812. if (mdns_pcb != NULL && ms_info != NULL) {
  813. udp_remove(mdns_pcb);
  814. for(text_index = 0;text_index < 10;text_index++) {
  815. if(ms_info->txt_data[text_index] != NULL) {
  816. os_free(ms_info->txt_data[text_index]);
  817. ms_info->txt_data[text_index] = NULL;
  818. }
  819. }
  820. if (ms_info->host_name != NULL) {
  821. os_free(ms_info->host_name);
  822. ms_info->host_name = NULL;
  823. }
  824. if (ms_info->server_name != NULL) {
  825. os_free(ms_info->server_name);
  826. ms_info->server_name = NULL;
  827. }
  828. os_free(ms_info);
  829. mdns_pcb = NULL;
  830. ms_info = NULL;
  831. }
  832. }
  833. void ICACHE_FLASH_ATTR
  834. mdns_set_name(const char *name)
  835. {
  836. //strcpy(host_name, name);
  837. os_strcpy(service_name, name);
  838. }
  839. void ICACHE_FLASH_ATTR
  840. mdns_enable(void)
  841. {
  842. if(mdns_flag == 0) {
  843. udp_recv(mdns_pcb, mdns_recv, NULL);
  844. }
  845. }
  846. void ICACHE_FLASH_ATTR
  847. mdns_disable(void)
  848. {
  849. if (mdns_flag == 1) {
  850. udp_recv(mdns_pcb, NULL, NULL);
  851. }
  852. }
  853. /**
  854. * close the UDP pcb .
  855. */
  856. char* ICACHE_FLASH_ATTR
  857. mdns_get_hostname(void) {
  858. //strcpy(host_name, name);
  859. char *name = host_name;
  860. if (host_name[0] != 0 ) {
  861. return name;
  862. } else {
  863. return ("Espressif");
  864. }
  865. }
  866. void ICACHE_FLASH_ATTR
  867. mdns_set_hostname(char *name) {
  868. if (name == NULL) {
  869. os_strncpy(host_name, "Espressif", os_strlen("Espressif")+3);
  870. return;
  871. }
  872. if (os_strlen(name) + 3 <= MDNS_NAME_LENGTH ){
  873. os_strncpy(host_name, name, os_strlen(name) );
  874. // os_memset(host_name + os_strlen(host_name) ,0x00,3);
  875. } else {
  876. os_strncpy(host_name, name, MDNS_NAME_LENGTH);
  877. }
  878. }
  879. void ICACHE_FLASH_ATTR
  880. mdns_set_servername(const char *name) {
  881. if (name == NULL) {
  882. PUCK_SERVICE = "_Espressif._tcp._local";
  883. }else {
  884. os_sprintf(server_name ,"_%s._tcp.local",name);
  885. PUCK_SERVICE = server_name;
  886. }
  887. }
  888. char* ICACHE_FLASH_ATTR
  889. mdns_get_servername(void) {
  890. char *name = PUCK_SERVICE;
  891. if (name == NULL) {
  892. PUCK_SERVICE = "_Espressif._tcp._local";
  893. }
  894. return name;
  895. }
  896. void ICACHE_FLASH_ATTR
  897. mdns_server_unregister(void) {
  898. struct ip_addr ap_host_addr;
  899. struct ip_info ipconfig;
  900. if(register_flag == 1){
  901. if (igmp_leavegroup(&host_addr, &multicast_addr) != ERR_OK) {
  902. os_printf("sta udp_leave_multigrup failed!\n");
  903. return;
  904. };
  905. if(wifi_get_opmode() == 0x03 || wifi_get_opmode() == 0x02) {
  906. wifi_get_ip_info(SOFTAP_IF, &ipconfig);
  907. ap_host_addr.addr = ipconfig.ip.addr;
  908. if (igmp_leavegroup(&ap_host_addr, &multicast_addr) != ERR_OK) {
  909. os_printf("ap udp_join_multigrup failed!\n");
  910. return;
  911. };
  912. }
  913. register_flag = 0;
  914. }
  915. }
  916. void ICACHE_FLASH_ATTR
  917. mdns_server_register(void) {
  918. if (register_flag == 1) {
  919. os_printf("mdns server is already registered !\n");
  920. return;
  921. } else if (igmp_joingroup(&host_addr, &multicast_addr) != ERR_OK) {
  922. os_printf("udp_join_multigrup failed!\n");
  923. return;
  924. };
  925. register_flag = 1;
  926. }
  927. void ICACHE_FLASH_ATTR
  928. mdns_reg(struct mdns_info *info) {
  929. static uint8 i = 0;
  930. if (i <= 3) {
  931. mdns_send_service(info,0);
  932. i++;
  933. } else {
  934. os_timer_disarm(&mdns_timer);
  935. }
  936. }
  937. /**
  938. * Initialize the resolver: set up the UDP pcb and configure the default server
  939. * (NEW IP).
  940. */
  941. void ICACHE_FLASH_ATTR
  942. mdns_init(struct mdns_info *info) {
  943. /* initialize default DNS server address */
  944. multicast_addr.addr = DNS_MULTICAST_ADDRESS;
  945. struct ip_addr ap_host_addr;
  946. struct ip_info ipconfig;
  947. uint8 text_index = 0;
  948. ms_info = (struct mdns_info *)os_zalloc(sizeof(struct mdns_info));
  949. if (ms_info != NULL) {
  950. os_memcpy(ms_info,info,sizeof(struct mdns_info));
  951. ms_info->host_name = (char *)os_zalloc(os_strlen(info->host_name)+1);
  952. os_memcpy(ms_info->host_name,info->host_name,os_strlen(info->host_name));
  953. ms_info->server_name = (char *)os_zalloc(os_strlen(info->server_name)+1);
  954. os_memcpy(ms_info->server_name,info->server_name,os_strlen(info->server_name));
  955. for(text_index = 0;text_index < 10;text_index++) {
  956. if(info->txt_data[text_index] != NULL) {
  957. ms_info->txt_data[text_index] = (char *)os_zalloc(os_strlen(info->txt_data[text_index])+1);
  958. os_memcpy(ms_info->txt_data[text_index],info->txt_data[text_index],os_strlen(info->txt_data[text_index]));
  959. } else {
  960. break;
  961. }
  962. }
  963. } else {
  964. os_printf("ms_info alloc failed\n");
  965. return;
  966. }
  967. if (ms_info->ipAddr == 0) {
  968. os_printf("mdns ip error!\n ");
  969. return;
  970. }
  971. host_addr.addr = ms_info->ipAddr ;
  972. LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
  973. //get the datasheet from PUCK
  974. mdns_set_hostname(ms_info->host_name);
  975. mdns_set_servername(ms_info->server_name);
  976. mdns_set_name(ms_info->host_name);
  977. // get the host name as instrumentName_serialNumber for MDNS
  978. // set the name of the service, the same as host name
  979. os_printf("host_name = %s\n", host_name);
  980. os_printf("server_name = %s\n", PUCK_SERVICE);
  981. if (ms_info->server_port == 0)
  982. {
  983. PUCK_PORT = 80;
  984. } else {
  985. PUCK_PORT = ms_info->server_port;
  986. }
  987. /* initialize mDNS */
  988. mdns_pcb = udp_new();
  989. if (mdns_pcb != NULL) {
  990. /* join to the multicast address 224.0.0.251 */
  991. if(wifi_get_opmode() == 0x03 || wifi_get_opmode() == 0x01) {
  992. if (igmp_joingroup(&host_addr, &multicast_addr) != ERR_OK) {
  993. os_printf("sta udp_join_multigrup failed!\n");
  994. return;
  995. };
  996. }
  997. if(wifi_get_opmode() == 0x03 || wifi_get_opmode() == 0x02) {
  998. wifi_get_ip_info(SOFTAP_IF, &ipconfig);
  999. ap_host_addr.addr = ipconfig.ip.addr;
  1000. if (igmp_joingroup(&ap_host_addr, &multicast_addr) != ERR_OK) {
  1001. os_printf("ap udp_join_multigrup failed!\n");
  1002. return;
  1003. };
  1004. }
  1005. register_flag = 1;
  1006. /* join to any IP address at the port 5353 */
  1007. if (udp_bind(mdns_pcb, IP_ADDR_ANY, DNS_MDNS_PORT) != ERR_OK) {
  1008. os_printf("udp_bind failed!\n");
  1009. return;
  1010. };
  1011. /*loopback function for the multicast(224.0.0.251) messages received at port 5353*/
  1012. // mdns_enable();
  1013. udp_recv(mdns_pcb, mdns_recv, ms_info);
  1014. mdns_flag = 1;
  1015. /*
  1016. * Register the name of the instrument
  1017. */
  1018. os_timer_disarm(&mdns_timer);
  1019. os_timer_setfn(&mdns_timer, (os_timer_func_t *)mdns_reg,ms_info);
  1020. os_timer_arm(&mdns_timer, 1000, 1);
  1021. }
  1022. }
  1023. #endif /* LWIP_MDNS */