Merge pull request #505 from ourairquality/mdns-responder1
mDNS-responder: ipv6 support and fixes
This commit is contained in:
		
						commit
						131da5b4f2
					
				
					 2 changed files with 340 additions and 249 deletions
				
			
		|  | @ -1,9 +1,10 @@ | |||
| /*
 | ||||
|  * Basic multicast DNS responder | ||||
|  *  | ||||
|  * Advertises the IP address, port, and characteristics of a service to other devices using multicast DNS on the same LAN, | ||||
|  * so they can find devices with addresses dynamically allocated by DHCP. See avahi, Bonjour, etc | ||||
|  * See RFC6762, RFC6763 | ||||
|  * Advertises the IP address, port, and characteristics of a service to other | ||||
|  * devices using multicast DNS on the same LAN, so they can find devices with | ||||
|  * addresses dynamically allocated by DHCP. See avahi, Bonjour, etc. See | ||||
|  * RFC6762, RFC6763 | ||||
|  * | ||||
|  * This sample code is in the public domain. | ||||
|  * | ||||
|  | @ -26,22 +27,21 @@ | |||
| #include <lwip/netdb.h> | ||||
| #include <lwip/dns.h> | ||||
| #include <lwip/prot/dns.h> | ||||
| #include <lwip/prot/iana.h> | ||||
| #include <lwip/udp.h> | ||||
| #include <lwip/igmp.h> | ||||
| #include <lwip/netif.h> | ||||
| 
 | ||||
| #include "mdnsresponder.h" | ||||
| 
 | ||||
| #if !LWIP_IGMP | ||||
| #error "LWIP_IGMP needs to be defined in lwipopts.h" | ||||
| #endif | ||||
| 
 | ||||
| #define qDebugLog             // Log activity generally
 | ||||
| #define qLogIncoming          // Log all arriving multicast packets
 | ||||
| #define qLogAllTraffic        // Log and decode all mDNS packets
 | ||||
| 
 | ||||
| #define kMDNSStackSize            800 | ||||
| 
 | ||||
| #define DNS_MULTICAST_ADDRESS   "224.0.0.251"   // RFC 6762
 | ||||
| #define DNS_MDNS_PORT           5353            // RFC 6762
 | ||||
| #define DNS_MSG_SIZE            512 | ||||
| 
 | ||||
| //-------------------------------------------------------------------
 | ||||
| 
 | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
|  | @ -120,13 +120,15 @@ typedef struct mdns_rsrc { | |||
| } mdns_rsrc; | ||||
| 
 | ||||
| static struct udp_pcb* gMDNS_pcb = NULL; | ||||
| static ip_addr_t       gMulticastAddr;      // == DNS_MULTICAST_ADDRESS
 | ||||
| static const ip_addr_t gMulticastV4Addr = DNS_MQUERY_IPV4_GROUP_INIT; | ||||
| #if LWIP_IPV6 | ||||
| #include "lwip/mld6.h" | ||||
| static const ip_addr_t gMulticastV6Addr = DNS_MQUERY_IPV6_GROUP_INIT; | ||||
| #endif | ||||
| static mdns_rsrc*      gDictP = NULL;       // RR database, linked list
 | ||||
| 
 | ||||
| //---------------------- Debug/logging utilities -------------------------
 | ||||
| 
 | ||||
| #ifdef qDebugLog | ||||
| 
 | ||||
|     // DNS field TYPE used for "Resource Records", some additions
 | ||||
|     #define DNS_RRTYPE_AAAA           28    /* IPv6 host address */ | ||||
|     #define DNS_RRTYPE_SRV            33    /* Service record */ | ||||
|  | @ -146,6 +148,7 @@ static mdns_rsrc*      gDictP = NULL;       // RR database, linked list | |||
|     #define DNS_FLAG2_RA              0x80 | ||||
|     #define DNS_FLAG2_RESMASK         0x0F | ||||
| 
 | ||||
| #ifdef qDebugLog | ||||
|     static char qstr[12]; | ||||
| 
 | ||||
|     static char* mdns_qrtype(uint16_t typ) | ||||
|  | @ -160,11 +163,11 @@ static mdns_rsrc*      gDictP = NULL;       // RR database, linked list | |||
|             case DNS_RRTYPE_NSEC : return ("NSEC "); | ||||
|             case DNS_RRTYPE_ANY  : return ("ANY"); | ||||
|         } | ||||
|         sprintf(qstr,"type %d",typ); | ||||
|         sprintf(qstr, "type %d", typ); | ||||
|         return qstr; | ||||
|     } | ||||
| 
 | ||||
|     #ifdef qLogAllTraffic | ||||
| #ifdef qLogAllTraffic | ||||
| 
 | ||||
|         static void mdns_printhex(u8_t* p, int n) | ||||
|         { | ||||
|  | @ -183,7 +186,9 @@ static mdns_rsrc*      gDictP = NULL;       // RR database, linked list | |||
| 
 | ||||
|             n = *p++; | ||||
|             cp = (char*)p; | ||||
|             for (i=0; i<n; i++) putchar(*cp++); | ||||
|             for (i = 0; i < n; i++) { | ||||
|                 putchar(*cp++); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         static char cstr[16]; | ||||
|  | @ -198,9 +203,9 @@ static mdns_rsrc*      gDictP = NULL;       // RR database, linked list | |||
|             return cstr; | ||||
|         } | ||||
| 
 | ||||
|         static u8_t* mdns_print_name(u8_t* p, struct mdns_hdr* hp) | ||||
|         // Sequence of Pascal strings, terminated by zero-length string
 | ||||
|         // Handles compression, returns ptr to next item
 | ||||
|         static u8_t* mdns_print_name(u8_t* p, struct mdns_hdr* hp) | ||||
|         { | ||||
|             char* cp = (char*)p; | ||||
|             int i, n; | ||||
|  | @ -210,17 +215,17 @@ static mdns_rsrc*      gDictP = NULL;       // RR database, linked list | |||
|                 if ((n & 0xC0) == 0xC0) { | ||||
|                     n = (n & 0x3F) << 8; | ||||
|                     n |= (u8_t)*cp++; | ||||
|                     mdns_print_name( (u8_t*)hp + n ,hp ); | ||||
|                     mdns_print_name((u8_t*)hp + n, hp); | ||||
|                     n = 0; | ||||
|                 } else if (n & 0xC0) { | ||||
|                     printf("<label $%X?>",n); | ||||
|                     n = 0; | ||||
|                 } else { | ||||
|                     for (i=0; i<n; i++) | ||||
|                     for (i = 0; i < n; i++) | ||||
|                         putchar(*cp++); | ||||
|                     if (n!=0) putchar('.'); | ||||
|                     if (n != 0) putchar('.'); | ||||
|                 } | ||||
|             } while (n>0); | ||||
|             } while (n > 0); | ||||
|             return (u8_t*)cp; | ||||
|         } | ||||
| 
 | ||||
|  | @ -230,10 +235,10 @@ static mdns_rsrc*      gDictP = NULL;       // RR database, linked list | |||
|             if (hdr->flags1 & DNS_FLAG1_RESP) { | ||||
|                 printf("Response, ID $%X %s ", htons(hdr->id), (hdr->flags1 & DNS_FLAG1_AUTH) ? "Auth " : "Non-auth "); | ||||
|                 if (hdr->flags2 & DNS_FLAG2_RA) printf("RA "); | ||||
|                 if ((hdr->flags2 & DNS_FLAG2_RESMASK)==0) printf("noerr"); | ||||
|                 if ((hdr->flags2 & DNS_FLAG2_RESMASK) == 0) printf("noerr"); | ||||
|                                        else printf("err %d", hdr->flags2 & DNS_FLAG2_RESMASK); | ||||
|             } else { | ||||
|                 printf("Query, ID $%X op %d", htons(hdr->id), (hdr->flags1>>4) & 0x7 ); | ||||
|                 printf("Query, ID $%X op %d", htons(hdr->id), (hdr->flags1 >> 4) & 0x7 ); | ||||
|             } | ||||
|             if (hdr->flags1 & DNS_FLAG1_RD) printf("RD "); | ||||
|             if (hdr->flags1 & DNS_FLAG1_TRUNC) printf("[TRUNC] "); | ||||
|  | @ -249,13 +254,13 @@ static mdns_rsrc*      gDictP = NULL;       // RR database, linked list | |||
|             return (u8_t*)hdr + SIZEOF_DNS_HDR; | ||||
|         } | ||||
| 
 | ||||
|         static u8_t* mdns_print_query(u8_t* p) | ||||
|         // Copy needed because it may be misaligned
 | ||||
|         static u8_t* mdns_print_query(u8_t* p) | ||||
|         { | ||||
|             struct mdns_query q; | ||||
|             uint16_t c; | ||||
| 
 | ||||
|             memcpy(&q,p,SIZEOF_DNS_QUERY); | ||||
|             memcpy(&q, p, SIZEOF_DNS_QUERY); | ||||
|             c = htons(q.class); | ||||
|             printf(" %s %s", mdns_qrtype(htons(q.type)), mdns_qclass(c & 0x7FFF) ); | ||||
|             if (c & 0x8000) printf(" unicast-req"); | ||||
|  | @ -263,8 +268,8 @@ static mdns_rsrc*      gDictP = NULL;       // RR database, linked list | |||
|             return p + SIZEOF_DNS_QUERY; | ||||
|         } | ||||
| 
 | ||||
|         static u8_t* mdns_print_answer(u8_t* p, struct mdns_hdr* hp) | ||||
|         // Copy needed because it may be misaligned
 | ||||
|         static u8_t* mdns_print_answer(u8_t* p, struct mdns_hdr* hp) | ||||
|         { | ||||
|             struct mdns_answer ans; | ||||
|             u16_t rrlen, atype, rrClass;; | ||||
|  | @ -278,23 +283,23 @@ static mdns_rsrc*      gDictP = NULL;       // RR database, linked list | |||
|                 printf("cache-flush "); | ||||
|             if (rrlen > 0) { | ||||
|                 u8_t* rp = p + SIZEOF_DNS_ANSWER; | ||||
|                 if (atype==DNS_RRTYPE_A && rrlen==4) { | ||||
|                 if (atype == DNS_RRTYPE_A && rrlen == 4) { | ||||
|                     printf("%d.%d.%d.%d\n",rp[0],rp[1],rp[2],rp[3]); | ||||
|                 } else if (atype==DNS_RRTYPE_PTR) { | ||||
|                 } else if (atype == DNS_RRTYPE_PTR) { | ||||
|                     mdns_print_name(rp, hp); | ||||
|                     printf("\n"); | ||||
|                 } else if (atype==DNS_RRTYPE_TXT) { | ||||
|                 } else if (atype == DNS_RRTYPE_TXT) { | ||||
|                     mdns_print_pstr(rp); | ||||
|                     printf("\n"); | ||||
|                 } else if (atype==DNS_RRTYPE_SRV && rrlen > SIZEOF_DNS_RR_SRV) { | ||||
|                 } else if (atype == DNS_RRTYPE_SRV && rrlen > SIZEOF_DNS_RR_SRV) { | ||||
|                     struct mdns_rr_srv srvRR; | ||||
|                     memcpy(&srvRR,rp,SIZEOF_DNS_RR_SRV); | ||||
|                     printf("prio %d, weight %d, port %d, target ", srvRR.prio, srvRR.weight, srvRR.port); | ||||
|                     memcpy(&srvRR, rp, SIZEOF_DNS_RR_SRV); | ||||
|                     printf("prio %d, weight %d, port %d, target ", srvRR.prio, srvRR.weight, ntohs(srvRR.port)); | ||||
|                     mdns_print_name(rp + SIZEOF_DNS_RR_SRV, hp); | ||||
|                     printf("\n"); | ||||
|                 } else { | ||||
|                     printf("%db:",rrlen); | ||||
|                     mdns_printhex(rp,rrlen); | ||||
|                     printf("%db:", rrlen); | ||||
|                     mdns_printhex(rp, rrlen); | ||||
|                 } | ||||
|             } else | ||||
|                 printf("\n"); | ||||
|  | @ -304,50 +309,49 @@ static mdns_rsrc*      gDictP = NULL;       // RR database, linked list | |||
|         static int mdns_print_msg(u8_t* msgP, int msgLen) | ||||
|         { | ||||
|             int i; | ||||
|             u8_t*    tp; | ||||
|             u8_t*     limP = msgP + msgLen; | ||||
|             u8_t *tp; | ||||
|             u8_t *limP = msgP + msgLen; | ||||
|             struct mdns_hdr* hdr; | ||||
| 
 | ||||
|             hdr = (struct mdns_hdr*) msgP; | ||||
|             tp = mdns_print_header(hdr); | ||||
|             for (i=0; i<htons(hdr->numquestions); i++) { | ||||
|                 printf(" Q%d: ",i+1); | ||||
|                 tp = mdns_print_name(tp,hdr); | ||||
|             for (i = 0; i < htons(hdr->numquestions); i++) { | ||||
|                 printf(" Q%d: ", i + 1); | ||||
|                 tp = mdns_print_name(tp, hdr); | ||||
|                 tp = mdns_print_query(tp); | ||||
|                 if (tp > limP) return 0; | ||||
|             } | ||||
| 
 | ||||
|             for (i=0; i<htons(hdr->numanswers); i++) { | ||||
|                 printf(" A%d: ",i+1); | ||||
|                 tp = mdns_print_name(tp,hdr); | ||||
|                 tp = mdns_print_answer(tp,hdr); | ||||
|             for (i = 0; i < htons(hdr->numanswers); i++) { | ||||
|                 printf(" A%d: ", i + 1); | ||||
|                 tp = mdns_print_name(tp, hdr); | ||||
|                 tp = mdns_print_answer(tp, hdr); | ||||
|                 if (tp > limP) return 0; | ||||
|             } | ||||
| 
 | ||||
|             for (i=0; i<htons(hdr->numauthrr); i++) { | ||||
|                 printf(" AuRR%d: ",i+1); | ||||
|                 tp = mdns_print_name(tp,hdr); | ||||
|                 tp = mdns_print_answer(tp,hdr); | ||||
|             for (i = 0; i < htons(hdr->numauthrr); i++) { | ||||
|                 printf(" AuRR%d: ", i + 1); | ||||
|                 tp = mdns_print_name(tp, hdr); | ||||
|                 tp = mdns_print_answer(tp, hdr); | ||||
|                 if (tp > limP) return 0; | ||||
|             } | ||||
| 
 | ||||
|             for (i=0; i<htons(hdr->numextrarr); i++) { | ||||
|                 printf(" ExRR%d: ",i+1); | ||||
|                 tp = mdns_print_name(tp,hdr); | ||||
|                 tp = mdns_print_answer(tp,hdr); | ||||
|             for (i = 0; i < htons(hdr->numextrarr); i++) { | ||||
|                 printf(" ExRR%d: ", i + 1); | ||||
|                 tp = mdns_print_name(tp, hdr); | ||||
|                 tp = mdns_print_answer(tp, hdr); | ||||
|                 if (tp > limP) return 0; | ||||
|             } | ||||
|             return 1; | ||||
|         } | ||||
|     #endif | ||||
| 
 | ||||
| #endif // qLogAllTraffic
 | ||||
| #endif // qDebugLog
 | ||||
| 
 | ||||
| //---------------------------------------------------------------------------
 | ||||
| 
 | ||||
| static u8_t* mdns_labels2str(u8_t* hdrP, u8_t* p, char* qStr) | ||||
| // Convert a DNS domain name label sequence into C string with . seperators
 | ||||
| // Handles compression
 | ||||
| static u8_t* mdns_labels2str(u8_t* hdrP, u8_t* p, char* qStr) | ||||
| { | ||||
|     int i, n; | ||||
| 
 | ||||
|  | @ -362,51 +366,51 @@ static u8_t* mdns_labels2str(u8_t* hdrP, u8_t* p, char* qStr) | |||
|             printf(">>> mdns_labels2str,label $%X?",n); | ||||
|             return p; | ||||
|         } else { | ||||
|             for (i=0; i<n; i++) | ||||
|             for (i = 0; i < n; i++) | ||||
|                 *qStr++ = *p++; | ||||
|             if (n==0) *qStr++ = 0; | ||||
|             if (n == 0) *qStr++ = 0; | ||||
|                  else *qStr++ = '.'; | ||||
|         } | ||||
|     } while (n>0); | ||||
|     return p; | ||||
| } | ||||
| 
 | ||||
| static int mdns_str2labels(const char* name, u8_t* lseq, int max) | ||||
| // Encode a <string>.<string>.<string> as a sequence of labels, return length
 | ||||
| static int mdns_str2labels(const char* name, u8_t* lseq, int max) | ||||
| { | ||||
|     int i,n,sdx,idx = 0; | ||||
|     int i, n, sdx, idx = 0; | ||||
|     int lc = 0; | ||||
| 
 | ||||
|     do { | ||||
|         sdx = idx; | ||||
|         while (name[idx] != '.' && name[idx] != 0) idx++; | ||||
|         n = idx-sdx; | ||||
|         *lseq++ = n; | ||||
|         lc++; | ||||
|         if (lc+n > max) { | ||||
|             printf(">>> mdns_str2labels: oversize (%d)\n",lc+n); | ||||
|         n = idx - sdx; | ||||
|         if (lc + 1 + n > max) { | ||||
|             printf(">>> mdns_str2labels: oversize (%d)\n", lc + 1 + n); | ||||
|             return 0; | ||||
|         } | ||||
|         for (i=0; i<n; i++)  | ||||
|             *lseq++ = name[sdx+i]; | ||||
|         *lseq++ = n; | ||||
|         lc++; | ||||
|         for (i = 0; i < n; i++) | ||||
|             *lseq++ = name[sdx + i]; | ||||
|         lc += n; | ||||
|         if (name[idx]=='.') | ||||
|         if (name[idx] == '.') | ||||
|             idx++; | ||||
|     } while (n>0); | ||||
|     } while (n > 0); | ||||
|     return lc; | ||||
| } | ||||
| 
 | ||||
| static u8_t* mdns_get_question(u8_t* hdrP, u8_t* qp, char* qStr, uint16_t* qClass, uint16_t* qType, u8_t* qUnicast) | ||||
| // Unpack a DNS question RR at qp, return pointer to next RR
 | ||||
| static u8_t* mdns_get_question(u8_t* hdrP, u8_t* qp, char* qStr, uint16_t* qClass, uint16_t* qType, u8_t* qUnicast) | ||||
| { | ||||
|     struct mdns_query qr; | ||||
|     uint16_t cls; | ||||
| 
 | ||||
|     qp = mdns_labels2str(hdrP, qp, qStr); | ||||
|     memcpy(&qr,qp,SIZEOF_DNS_QUERY); | ||||
|     memcpy(&qr, qp, SIZEOF_DNS_QUERY); | ||||
|     *qType = htons(qr.type); | ||||
|     cls = htons(qr.class); | ||||
|     *qUnicast = cls>>15; | ||||
|     *qUnicast = cls >> 15; | ||||
|     *qClass = cls & 0x7FFF; | ||||
|     return qp + SIZEOF_DNS_QUERY; | ||||
| } | ||||
|  | @ -414,8 +418,8 @@ static u8_t* mdns_get_question(u8_t* hdrP, u8_t* qp, char* qStr, uint16_t* qClas | |||
| //---------------------------------------------------------------------------
 | ||||
| 
 | ||||
| 
 | ||||
| static void mdns_add_response(const char* vKey, u16_t vType, u32_t ttl, const void* dataP, u16_t vDataSize) | ||||
| // Add a record to the RR database list
 | ||||
| static void mdns_add_response(const char* vKey, u16_t vType, u32_t ttl, const void* dataP, u16_t vDataSize) | ||||
| { | ||||
|     mdns_rsrc* rsrcP; | ||||
|     int keyLen, recSize; | ||||
|  | @ -423,9 +427,9 @@ static void mdns_add_response(const char* vKey, u16_t vType, u32_t ttl, const vo | |||
|     keyLen = strlen(vKey) + 1; | ||||
|     recSize = sizeof(mdns_rsrc) - kDummyDataSize + keyLen + vDataSize; | ||||
|     rsrcP = (mdns_rsrc*)malloc(recSize); | ||||
|     if (rsrcP==NULL) | ||||
|     if (rsrcP == NULL) { | ||||
|         printf(">>> mdns_add_response: couldn't alloc %d\n",recSize); | ||||
|     else { | ||||
|     } else { | ||||
|         rsrcP->rType = vType; | ||||
|         rsrcP->rTTL = ttl; | ||||
|         rsrcP->rKeySize = keyLen; | ||||
|  | @ -434,20 +438,21 @@ static void mdns_add_response(const char* vKey, u16_t vType, u32_t ttl, const vo | |||
|         memcpy(&rsrcP->rData[keyLen], dataP, vDataSize); | ||||
|         rsrcP->rNext = gDictP; | ||||
|         gDictP = rsrcP; | ||||
|         #ifdef qDebugLog | ||||
|             printf("mDNS added RR '%s' %s, %d bytes\n", vKey, mdns_qrtype(vType), vDataSize); | ||||
|         #endif | ||||
| #ifdef qDebugLog | ||||
|         printf("mDNS added RR '%s' %s, %d bytes\n", vKey, mdns_qrtype(vType), vDataSize); | ||||
| #endif | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void mdns_add_PTR(const char* rKey, u32_t ttl, const char* nmStr) | ||||
| { | ||||
|     int nl; | ||||
|     size_t nl; | ||||
|     u8_t lBuff[kMaxNameSize]; | ||||
| 
 | ||||
|     nl = mdns_str2labels(nmStr,lBuff,sizeof(lBuff)); | ||||
|     if (nl>0) | ||||
|     nl = mdns_str2labels(nmStr, lBuff, sizeof(lBuff)); | ||||
|     if (nl > 0) { | ||||
|         mdns_add_response(rKey, DNS_RRTYPE_PTR, ttl, lBuff, nl); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void mdns_add_SRV(const char* rKey, u32_t ttl, u16_t rPort, const char* targName) | ||||
|  | @ -463,91 +468,101 @@ void mdns_add_SRV(const char* rKey, u32_t ttl, u16_t rPort, const char* targName | |||
|     temp.srvRR.prio = 0; | ||||
|     temp.srvRR.weight = 0; | ||||
|     temp.srvRR.port = htons(rPort); | ||||
|     nl = mdns_str2labels(targName,temp.lBuff,sizeof(temp.lBuff)); | ||||
|     if (nl>0) | ||||
|     nl = mdns_str2labels(targName, temp.lBuff, sizeof(temp.lBuff)); | ||||
|     if (nl > 0) | ||||
|         mdns_add_response(rKey, DNS_RRTYPE_SRV, ttl, &temp, SIZEOF_DNS_RR_SRV + nl); | ||||
| } | ||||
| 
 | ||||
| void mdns_add_TXT(const char* rKey, u32_t ttl, const char* txStr) | ||||
| // Single TXT str, can be concatenated
 | ||||
| void mdns_add_TXT(const char* rKey, u32_t ttl, const char* txStr) | ||||
| { | ||||
|     char pstr[256]; | ||||
|     u16_t n = strlen(txStr); | ||||
|     if (n > 255) | ||||
|     if (n > 255) { | ||||
|         printf(">>> mdns_add_TXT oversize (%d)\n",n); | ||||
|     else { | ||||
|         pstr[0] = n; | ||||
|         memcpy(&pstr[1],txStr,n); | ||||
|         mdns_add_response(rKey, DNS_RRTYPE_TXT, ttl, txStr, n+1); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     char *pstr = malloc(n + 1); | ||||
|     pstr[0] = n; | ||||
|     memcpy(&pstr[1], txStr, n); | ||||
|     mdns_add_response(rKey, DNS_RRTYPE_TXT, ttl, pstr, n + 1); | ||||
|     free(pstr); | ||||
| } | ||||
| 
 | ||||
| void mdns_add_A(const char* rKey, u32_t ttl, ip_addr_t addr) | ||||
| void mdns_add_A(const char* rKey, u32_t ttl, const ip4_addr_t *addr) | ||||
| { | ||||
|     mdns_add_response(rKey, DNS_RRTYPE_A, ttl, &addr, sizeof(addr)); | ||||
|     mdns_add_response(rKey, DNS_RRTYPE_A, ttl, addr, sizeof(ip4_addr_t)); | ||||
| } | ||||
| 
 | ||||
| #if LWIP_IPV6 | ||||
| void mdns_add_AAAA(const char* rKey, u32_t ttl, const ip6_addr_t *addr) | ||||
| { | ||||
|     mdns_add_response(rKey, DNS_RRTYPE_AAAA, ttl, addr, sizeof(addr->addr)); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| void mdns_add_facility( const char* instanceName,   // Friendly name, need not be unique
 | ||||
|                         const char* serviceName,    // Must be "name", e.g. "hap" or "http"
 | ||||
|                         const char* serviceName,    // Must be "_name", e.g. "_hap" or "_http"
 | ||||
|                         const char* addText,        // Must be <key>=<value>
 | ||||
|                         mdns_flags  flags,          // TCP or UDP
 | ||||
|                         u16_t onPort,               // port number
 | ||||
|                         u32_t ttl                   // seconds
 | ||||
|                       ) | ||||
| { | ||||
|     char key[64]; | ||||
|     char fullName[128]; | ||||
|     char devName[96]; | ||||
|     struct ip_info ipInfo; | ||||
|     size_t key_len = strlen(serviceName) + 12; | ||||
|     char *key = malloc(key_len + 1); | ||||
|     size_t full_name_len = strlen(instanceName) + 1 + key_len; | ||||
|     char *fullName = malloc(full_name_len + 1); | ||||
|     size_t dev_name_len = strlen(instanceName) + 7; | ||||
|     char *devName = malloc(dev_name_len + 1); | ||||
| 
 | ||||
|     #ifdef qDebugLog | ||||
|         printf("\nmDNS advertising instance %s protocol %s text %s on port %d %s TTL %d secs\n", | ||||
|                 instanceName, serviceName, addText, onPort, (flags & mdns_UDP) ? "UDP" : "TCP", ttl); | ||||
|     #endif | ||||
| #ifdef qDebugLog | ||||
|     printf("\nmDNS advertising instance %s protocol %s", instanceName, serviceName); | ||||
|     if (addText) { | ||||
|         printf(" text %s", addText); | ||||
|     } | ||||
|     printf(" on port %d %s TTL %d secs\n", onPort, (flags & mdns_UDP) ? "UDP" : "TCP", ttl); | ||||
| #endif | ||||
| 
 | ||||
|     snprintf(key, sizeof(key), "%s.%s.local.", serviceName, (flags & mdns_UDP) ? "_udp" :"_tcp"); | ||||
|     snprintf(fullName, sizeof(fullName), "%s.%s", instanceName, key); | ||||
|     snprintf(devName, sizeof(devName), "%s.local.", instanceName); | ||||
| 
 | ||||
|     if (!sdk_wifi_get_ip_info(STATION_IF,&ipInfo)) | ||||
|         ipInfo.ip.addr = IPADDR_NONE; | ||||
|     snprintf(key, key_len + 1, "%s.%s.local.", serviceName, (flags & mdns_UDP) ? "_udp" :"_tcp"); | ||||
|     snprintf(fullName, full_name_len + 1, "%s.%s", instanceName, key); | ||||
|     snprintf(devName, dev_name_len + 1, "%s.local.", instanceName); | ||||
| 
 | ||||
|     // Order has significance for extraRR feature
 | ||||
|     mdns_add_TXT(fullName, ttl, addText); | ||||
|     mdns_add_A(devName, ttl, ipInfo.ip); | ||||
|     if (addText) { | ||||
|         mdns_add_TXT(fullName, ttl, addText); | ||||
|     } | ||||
| 
 | ||||
| #if LWIP_IPV6 | ||||
|     const ip6_addr_t addr6 = { {0ul, 0ul, 0ul, 0ul} }; | ||||
|     mdns_add_AAAA(devName, ttl, &addr6); | ||||
| #endif | ||||
| 
 | ||||
|     const ip4_addr_t addr4 = { 0 }; | ||||
|     mdns_add_A(devName, ttl, &addr4); | ||||
| 
 | ||||
|     mdns_add_SRV(fullName, ttl, onPort, devName); | ||||
|     mdns_add_PTR(key, ttl, fullName); | ||||
| 
 | ||||
|     // Optional, makes us browsable
 | ||||
|     if (flags & mdns_Browsable) | ||||
|         mdns_add_PTR("_services._dns-sd._udp.local.",ttl,key); | ||||
| } | ||||
| 
 | ||||
| static void mdns_update_ipaddr(struct ip_info* ipInfo) | ||||
| // IP address has been defined/changed: update any A records with the new IP
 | ||||
| { | ||||
|     mdns_rsrc* rp = gDictP; | ||||
|     while (rp != NULL) { | ||||
|         if (rp->rType==DNS_RRTYPE_A) { | ||||
|             #ifdef qDebugLog | ||||
|                 printf("Updating A record for '%s' to %d.%d.%d.%d\n", rp->rData, | ||||
|                     ip4_addr1(&ipInfo->ip), ip4_addr2(&ipInfo->ip), ip4_addr3(&ipInfo->ip), ip4_addr4(&ipInfo->ip)); | ||||
|             #endif | ||||
|             memcpy(&rp->rData[rp->rKeySize], &ipInfo->ip, sizeof(ip_addr_t)); | ||||
|         } | ||||
|         rp = rp->rNext; | ||||
|     if (flags & mdns_Browsable) { | ||||
|         mdns_add_PTR("_services._dns-sd._udp.local.", ttl, key); | ||||
|     } | ||||
| 
 | ||||
|     free(key); | ||||
|     free(fullName); | ||||
|     free(devName); | ||||
| } | ||||
| 
 | ||||
| static mdns_rsrc* mdns_match(const char* qstr, u16_t qType) | ||||
| { | ||||
|     mdns_rsrc* rp = gDictP; | ||||
|     while (rp != NULL) { | ||||
|         if (rp->rType==qType || qType==DNS_RRTYPE_ANY) { | ||||
|             if (strcasecmp(rp->rData,qstr)==0) { | ||||
|                 #ifdef qDebugLog | ||||
|                     printf(" - matched '%s' %s\n",qstr,mdns_qrtype(rp->rType)); | ||||
|                 #endif | ||||
|        if (rp->rType == qType || qType == DNS_RRTYPE_ANY) { | ||||
|             if (strcasecmp(rp->rData, qstr) == 0) { | ||||
| #ifdef qDebugLog | ||||
|                 printf(" - matched '%s' %s\n", qstr, mdns_qrtype(rp->rType)); | ||||
| #endif | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|  | @ -556,11 +571,22 @@ static mdns_rsrc* mdns_match(const char* qstr, u16_t qType) | |||
|     return rp; | ||||
| } | ||||
| 
 | ||||
| static int mdns_add_to_answer(mdns_rsrc* rsrcP, u8_t* resp, int respLen) | ||||
| // Create answer RR and append to resp[respLen], return new length
 | ||||
| static int mdns_add_to_answer(mdns_rsrc* rsrcP, u8_t* resp, int respLen) | ||||
| { | ||||
|     // Key is stored as C str, convert to labels
 | ||||
|     respLen += mdns_str2labels(rsrcP->rData, &resp[respLen], DNS_MSG_SIZE-respLen); | ||||
|     size_t rem = MDNS_RESPONDER_REPLY_SIZE - respLen; | ||||
|     size_t len = mdns_str2labels(rsrcP->rData, &resp[respLen], rem); | ||||
|     if (len == 0) { | ||||
|         // Overflow, skip this answer.
 | ||||
|         return respLen; | ||||
|     } | ||||
|     if ((len + SIZEOF_DNS_ANSWER + rsrcP->rDataSize) > rem) { | ||||
|         // Overflow, skip this answer.
 | ||||
|         printf(">>> mdns_add_to_answer: oversize (%d)\n", len + SIZEOF_DNS_ANSWER + rsrcP->rDataSize); | ||||
|         return respLen; | ||||
|     } | ||||
|     respLen += len; | ||||
| 
 | ||||
|     // Answer fields: may be misaligned, so build and memcpy
 | ||||
|     struct mdns_answer ans; | ||||
|  | @ -580,29 +606,43 @@ static int mdns_add_to_answer(mdns_rsrc* rsrcP, u8_t* resp, int respLen) | |||
| 
 | ||||
| //---------------------------------------------------------------------------
 | ||||
| 
 | ||||
| static void mdns_send_mcast(u8_t* msgP, int nBytes) | ||||
| // Send UDP to multicast address
 | ||||
| static void mdns_send_mcast(const ip_addr_t *addr, u8_t* msgP, int nBytes) | ||||
| { | ||||
|     struct pbuf* p; | ||||
|     err_t err; | ||||
| 
 | ||||
| #ifdef qLogAllTraffic | ||||
|     mdns_print_msg(msgP, nBytes); | ||||
| #endif | ||||
| 
 | ||||
|     p = pbuf_alloc(PBUF_TRANSPORT, nBytes, PBUF_RAM); | ||||
|     if (p) { | ||||
|         memcpy(p->payload, msgP, nBytes); | ||||
|         err = udp_sendto(gMDNS_pcb, p, &gMulticastAddr, DNS_MDNS_PORT); | ||||
|         if (err==ERR_OK) { | ||||
|             #ifdef qDebugLog | ||||
|                 printf(" - responded with %d bytes err %d\n",nBytes,err); | ||||
|             #endif | ||||
|         const ip_addr_t *dest_addr; | ||||
|         if (IP_IS_V6_VAL(*addr)) { | ||||
| #if LWIP_IPV6 | ||||
|             dest_addr = &gMulticastV6Addr; | ||||
| #endif | ||||
|         } else { | ||||
|             dest_addr = &gMulticastV4Addr; | ||||
|         } | ||||
|         struct netif *netif = ip_current_input_netif(); | ||||
|         err = udp_sendto_if(gMDNS_pcb, p, dest_addr, LWIP_IANA_PORT_MDNS, netif); | ||||
|         if (err == ERR_OK) { | ||||
| #ifdef qDebugLog | ||||
|             printf(" - responded with %d bytes err %d\n", nBytes, err); | ||||
| #endif | ||||
|         } else | ||||
|             printf(">>> mdns_send failed %d\n",err); | ||||
|             printf(">>> mdns_send failed %d\n", err); | ||||
|         pbuf_free(p); | ||||
|     } else | ||||
|         printf(">>> mdns_send: alloc failed[%d]\n",nBytes); | ||||
|     } else { | ||||
|         printf(">>> mdns_send: alloc failed[%d]\n", nBytes); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void mdns_reply(struct mdns_hdr* hdrP) | ||||
|      | ||||
| // Message has passed tests, may want to send an answer
 | ||||
| static void mdns_reply(const ip_addr_t *addr, struct mdns_hdr* hdrP) | ||||
| { | ||||
|     int i, nquestions, respLen; | ||||
|     struct mdns_hdr* rHdr; | ||||
|  | @ -611,9 +651,9 @@ static void mdns_reply(struct mdns_hdr* hdrP) | |||
|     u8_t* qp; | ||||
|     u8_t* mdns_response; | ||||
| 
 | ||||
|     mdns_response = malloc(DNS_MSG_SIZE); | ||||
|     if (mdns_response==NULL) { | ||||
|         printf(">>> mdns_reply could not alloc %d\n",DNS_MSG_SIZE); | ||||
|     mdns_response = malloc(MDNS_RESPONDER_REPLY_SIZE); | ||||
|     if (mdns_response == NULL) { | ||||
|         printf(">>> mdns_reply could not alloc %d\n", MDNS_RESPONDER_REPLY_SIZE); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|  | @ -632,25 +672,63 @@ static void mdns_reply(struct mdns_hdr* hdrP) | |||
|     qp = qBase + SIZEOF_DNS_HDR; | ||||
|     nquestions = htons(hdrP->numquestions); | ||||
| 
 | ||||
|     for (i=0; i<nquestions; i++) { | ||||
|     for (i = 0; i < nquestions; i++) { | ||||
|         char  qStr[kMaxQStr]; | ||||
|         u16_t qClass, qType; | ||||
|         u8_t  qUnicast; | ||||
|         mdns_rsrc* rsrcP; | ||||
| 
 | ||||
|         qp = mdns_get_question(qBase, qp, qStr, &qClass, &qType, &qUnicast); | ||||
|         if (qClass==DNS_RRCLASS_IN || qClass==DNS_RRCLASS_ANY) { | ||||
|         if (qClass == DNS_RRCLASS_IN || qClass == DNS_RRCLASS_ANY) { | ||||
|             rsrcP = mdns_match(qStr, qType); | ||||
|             if (rsrcP) { | ||||
|                 respLen = mdns_add_to_answer(rsrcP, mdns_response, respLen); | ||||
|                 rHdr->numanswers = htons( htons(rHdr->numanswers) + 1 ); | ||||
| #if LWIP_IPV6 | ||||
|                 if (rsrcP->rType == DNS_RRTYPE_AAAA) { | ||||
|                     // Emit an answer for each ipv6 address.
 | ||||
|                     struct netif *netif = ip_current_input_netif(); | ||||
|                     for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { | ||||
|                         if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { | ||||
|                             const ip6_addr_t *addr6 = netif_ip6_addr(netif, i); | ||||
| #ifdef qDebugLog | ||||
|                             char addr6_str[IP6ADDR_STRLEN_MAX]; | ||||
|                             ip6addr_ntoa_r(addr6, addr6_str, IP6ADDR_STRLEN_MAX); | ||||
|                             printf("Updating AAAA record for '%s' to %s\n", rsrcP->rData, addr6_str); | ||||
| #endif | ||||
|                             memcpy(&rsrcP->rData[rsrcP->rKeySize], addr6, sizeof(addr6->addr)); | ||||
|                             size_t new_len = mdns_add_to_answer(rsrcP, mdns_response, respLen); | ||||
|                             if (new_len > respLen) { | ||||
|                                 rHdr->numanswers = htons(htons(rHdr->numanswers) + 1); | ||||
|                                 respLen = new_len; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     continue; | ||||
|                 } | ||||
| #endif | ||||
| 
 | ||||
|                 if (rsrcP->rType == DNS_RRTYPE_A) { | ||||
|                     struct netif *netif = ip_current_input_netif(); | ||||
| #ifdef qDebugLog | ||||
|                     char addr4_str[IP4ADDR_STRLEN_MAX]; | ||||
|                     ip4addr_ntoa_r(netif_ip4_addr(netif), addr4_str, IP4ADDR_STRLEN_MAX); | ||||
|                     printf("Updating A record for '%s' to %s\n", rsrcP->rData, addr4_str); | ||||
| #endif | ||||
|                     memcpy(&rsrcP->rData[rsrcP->rKeySize], netif_ip4_addr(netif), sizeof(ip4_addr_t)); | ||||
|                 } | ||||
| 
 | ||||
|                 size_t new_len = mdns_add_to_answer(rsrcP, mdns_response, respLen); | ||||
|                 if (new_len > respLen) { | ||||
|                     rHdr->numanswers = htons(htons(rHdr->numanswers) + 1); | ||||
|                     respLen = new_len; | ||||
|                 } | ||||
| 
 | ||||
|                 // Extra RR logic: if SRV follows PTR, or A follows SRV, volunteer it in extraRR
 | ||||
|                 // Not required, but could do more here, see RFC6763 s12
 | ||||
|                 if (qType==DNS_RRTYPE_PTR) { | ||||
|                     if (rsrcP->rNext && rsrcP->rNext->rType==DNS_RRTYPE_SRV) | ||||
|                 if (qType == DNS_RRTYPE_PTR) { | ||||
|                     if (rsrcP->rNext && rsrcP->rNext->rType == DNS_RRTYPE_SRV) | ||||
|                         extra = rsrcP->rNext; | ||||
|                 } else if (qType==DNS_RRTYPE_SRV) { | ||||
|                     if (rsrcP->rNext && rsrcP->rNext->rType==DNS_RRTYPE_A) | ||||
|                 } else if (qType == DNS_RRTYPE_SRV) { | ||||
|                     if (rsrcP->rNext && rsrcP->rNext->rType == DNS_RRTYPE_A) | ||||
|                         extra = rsrcP->rNext; | ||||
|                 } | ||||
|             } | ||||
|  | @ -659,16 +737,29 @@ static void mdns_reply(struct mdns_hdr* hdrP) | |||
| 
 | ||||
|     if (respLen > SIZEOF_DNS_HDR) { | ||||
|         if (extra) { | ||||
|             respLen = mdns_add_to_answer(extra, mdns_response, respLen); | ||||
|             rHdr->numextrarr = htons( htons(rHdr->numextrarr) + 1 ); | ||||
|             if (extra->rType == DNS_RRTYPE_A) { | ||||
|                 struct netif *netif = ip_current_input_netif(); | ||||
| #ifdef qDebugLog | ||||
|                 char addr4_str[IP4ADDR_STRLEN_MAX]; | ||||
|                 ip4addr_ntoa_r(netif_ip4_addr(netif), addr4_str, IP4ADDR_STRLEN_MAX); | ||||
|                 printf("Updating A record for '%s' to %s\n", extra->rData, addr4_str); | ||||
| #endif | ||||
|                 memcpy(&extra->rData[extra->rKeySize], netif_ip4_addr(netif), sizeof(ip4_addr_t)); | ||||
|             } | ||||
|             size_t new_len = mdns_add_to_answer(extra, mdns_response, respLen); | ||||
|             if (new_len > respLen) { | ||||
|                 rHdr->numextrarr = htons(htons(rHdr->numextrarr) + 1); | ||||
|                 respLen = new_len; | ||||
|             } | ||||
|         } | ||||
|         mdns_send_mcast(mdns_response, respLen); | ||||
|         mdns_send_mcast(addr, mdns_response, respLen); | ||||
|     } | ||||
| 
 | ||||
|     free(mdns_response); | ||||
| } | ||||
| 
 | ||||
| static void mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) | ||||
| // Callback from udp_recv
 | ||||
| static void mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) | ||||
| { | ||||
|     UNUSED_ARG(pcb); | ||||
|     UNUSED_ARG(port); | ||||
|  | @ -676,30 +767,32 @@ static void mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t | |||
|     u8_t* mdns_payload; | ||||
|     int   plen; | ||||
| 
 | ||||
|     // Sanity checks on size
 | ||||
|     plen = p->tot_len; | ||||
|     if (plen > DNS_MSG_SIZE) { | ||||
| #ifdef qLogIncoming | ||||
|     char addr_str[IPADDR_STRLEN_MAX]; | ||||
|     ipaddr_ntoa_r(addr, addr_str, IPADDR_STRLEN_MAX); | ||||
|     printf("\n\nmDNS IPv%d got %d bytes from %s\n", IP_IS_V6(addr) ? 6 : 4, plen, addr_str); | ||||
| #endif | ||||
| 
 | ||||
|     // Sanity checks on size
 | ||||
|     if (plen > MDNS_RESPONDER_REPLY_SIZE) { | ||||
|         printf(">>> mdns_recv: pbuf too big\n"); | ||||
|     } else if (plen < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + 1 + SIZEOF_DNS_ANSWER + 1)) { | ||||
|         printf(">>> mdns_recv: pbuf too small\n"); | ||||
|     } else { | ||||
|         #ifdef qLogIncoming | ||||
|             printf("\n\nmDNS got %d bytes from %d.%d.%d.%d\n",plen, ip4_addr1(addr), ip4_addr2(addr), ip4_addr3(addr), ip4_addr4(addr)); | ||||
|         #endif | ||||
|         mdns_payload = malloc(plen); | ||||
|         if (!mdns_payload) | ||||
|         if (!mdns_payload) { | ||||
|             printf(">>> mdns_recv, could not alloc %d\n",plen); | ||||
|         else { | ||||
|         } else { | ||||
|             if (pbuf_copy_partial(p, mdns_payload, plen, 0) == plen) { | ||||
|                 struct mdns_hdr* hdrP = (struct mdns_hdr*) mdns_payload; | ||||
| 
 | ||||
|                 #ifdef qLogAllTraffic | ||||
|                     mdns_print_msg(mdns_payload, plen); | ||||
|                 #endif | ||||
| #ifdef qLogAllTraffic | ||||
|                 mdns_print_msg(mdns_payload, plen); | ||||
| #endif | ||||
| 
 | ||||
|                 if ( (hdrP->flags1 & (DNS_FLAG1_RESP + DNS_FLAG1_OPMASK + DNS_FLAG1_TRUNC) ) == 0 | ||||
|                      && hdrP->numquestions > 0 ) | ||||
|                     mdns_reply(hdrP); | ||||
|                     mdns_reply(addr, hdrP); | ||||
|             } | ||||
|             free(mdns_payload); | ||||
|         } | ||||
|  | @ -707,92 +800,82 @@ static void mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t | |||
|     pbuf_free(p); | ||||
| } | ||||
| 
 | ||||
| static void mdns_start() | ||||
| // If we are in station mode and have an IP address, start a multicast UDP receive
 | ||||
| void mdns_init() | ||||
| { | ||||
|     struct ip_info ipInfo; | ||||
|     err_t err; | ||||
| 
 | ||||
|     if (sdk_wifi_get_opmode() != STATION_MODE) { | ||||
|         printf(">>> mDNS_start: wifi opmode not station\n"); | ||||
|         return; | ||||
|     } | ||||
|     struct netif *station_netif = sdk_system_get_netif(STATION_IF); | ||||
| 
 | ||||
|     if (!sdk_wifi_get_ip_info(STATION_IF,&ipInfo)) { | ||||
|         printf(">>> mDNS_start: no IP addr\n"); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     mdns_update_ipaddr(&ipInfo); | ||||
| 
 | ||||
|     // Start IGMP on the netif for our interface: this isn't done for us
 | ||||
|     struct netif* nfp = netif_list; | ||||
|     while (nfp!=NULL) {         | ||||
|         if ( ip_addr_cmp(&ipInfo.ip, &(nfp->ip_addr)) ) { | ||||
|             if (!(nfp->flags & NETIF_FLAG_IGMP)) { | ||||
|                 nfp->flags |= NETIF_FLAG_IGMP; | ||||
|                 err = igmp_start(nfp); | ||||
|                 if (err != ERR_OK) { | ||||
|                     printf(">>> mDNS_start: igmp_start on %c%c failed %d\n",nfp->name[0], nfp->name[1],err); | ||||
|                     return; | ||||
|                 }  | ||||
|             }  | ||||
|     if (station_netif) { | ||||
|         // Start IGMP on the netif for our interface: this isn't done for us
 | ||||
|         if (!(station_netif->flags & NETIF_FLAG_IGMP)) { | ||||
|             station_netif->flags |= NETIF_FLAG_IGMP; | ||||
|             err = igmp_start(station_netif); | ||||
|             if (err != ERR_OK) { | ||||
|                 printf(">>> mDNS_init: igmp_start on %c%c failed %d\n", station_netif->name[0], station_netif->name[1],err); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         nfp = nfp->next; | ||||
| 
 | ||||
|         if ((err = igmp_joingroup_netif(station_netif, ip_2_ip4(&gMulticastV4Addr))) != ERR_OK) { | ||||
|             printf(">>> mDNS_init: igmp_join failed %d\n",err); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
| #if LWIP_IPV6 | ||||
|         if ((err = mld6_joingroup_netif(station_netif, ip_2_ip6(&gMulticastV6Addr))) != ERR_OK) { | ||||
|             printf(">>> mDNS_init: igmp_join failed %d\n",err); | ||||
|             return; | ||||
|         } | ||||
| #endif | ||||
|     } | ||||
| 
 | ||||
|     gMDNS_pcb = udp_new(); | ||||
|     struct netif *softap_netif = sdk_system_get_netif(SOFTAP_IF); | ||||
|     if (softap_netif) { | ||||
|         if (softap_netif == NULL) { | ||||
|             printf(">>> mDNS_init: wifi opmode not softap\n"); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // Start IGMP on the netif for our interface: this isn't done for us
 | ||||
|         if (!(softap_netif->flags & NETIF_FLAG_IGMP)) { | ||||
|             softap_netif->flags |= NETIF_FLAG_IGMP; | ||||
|             err = igmp_start(softap_netif); | ||||
|             if (err != ERR_OK) { | ||||
|                 printf(">>> mDNS_init: igmp_start on %c%c failed %d\n", softap_netif->name[0], softap_netif->name[1],err); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if ((err = igmp_joingroup_netif(softap_netif, ip_2_ip4(&gMulticastV4Addr))) != ERR_OK) { | ||||
|             printf(">>> mDNS_init: igmp_join failed %d\n",err); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
| #if LWIP_IPV6 | ||||
|         if ((err = mld6_joingroup_netif(softap_netif, ip_2_ip6(&gMulticastV6Addr))) != ERR_OK) { | ||||
|             printf(">>> mDNS_init: igmp_join failed %d\n",err); | ||||
|             return; | ||||
|         } | ||||
| #endif | ||||
|     } | ||||
| 
 | ||||
|     if (station_netif == NULL && softap_netif == NULL) { | ||||
|         printf(">>> mDNS_init: wifi opmode none\n"); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     gMDNS_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); | ||||
|     if (!gMDNS_pcb) { | ||||
|         printf(">>> mDNS_start: udp_new failed\n"); | ||||
|         printf(">>> mDNS_init: udp_new failed\n"); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if ((err=igmp_joingroup(&ipInfo.ip, &gMulticastAddr)) != ERR_OK) { | ||||
|         printf(">>> mDNS_start: igmp_join failed %d\n",err); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if ((err=udp_bind(gMDNS_pcb, IP_ADDR_ANY, DNS_MDNS_PORT)) != ERR_OK) { | ||||
|         printf(">>> mDNS_start: udp_bind failed %d\n",err); | ||||
|     if ((err = udp_bind(gMDNS_pcb, IP_ANY_TYPE, LWIP_IANA_PORT_MDNS)) != ERR_OK) { | ||||
|         printf(">>> mDNS_init: udp_bind failed %d\n",err); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     udp_recv(gMDNS_pcb, mdns_recv, NULL); | ||||
| } | ||||
| 
 | ||||
| static void mdns_close() | ||||
| { | ||||
|     udp_remove(gMDNS_pcb); | ||||
|     gMDNS_pcb = NULL; | ||||
|     #ifdef qDebugLog | ||||
|         printf("Closing mDNS\n"); | ||||
|     #endif | ||||
| } | ||||
| 
 | ||||
| static void mdns_task(void *pvParameters) | ||||
| { | ||||
|     uint8_t hasIP = 0; | ||||
|     uint8_t status; | ||||
|     UNUSED_ARG(pvParameters); | ||||
| 
 | ||||
|     ipaddr_aton(DNS_MULTICAST_ADDRESS, &gMulticastAddr); | ||||
|     // Wait until we have joined AP and are assigned an IP
 | ||||
|     while (1) { | ||||
|         status = (sdk_wifi_station_get_connect_status() == STATION_GOT_IP); | ||||
|         if (status != hasIP) { | ||||
|             if (status) mdns_start(); | ||||
|                    else mdns_close(); | ||||
|             hasIP = status; | ||||
|         } | ||||
|         vTaskDelayMs(status ? 1000 : 100); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void mdns_init() | ||||
| { | ||||
|     #if LWIP_IGMP | ||||
|         xTaskCreate(mdns_task, "MDNS", kMDNSStackSize, NULL, 2, NULL); | ||||
|     #else | ||||
|         #error "LWIP_IGMP needs to be defined in lwipopts.h" | ||||
|     #endif | ||||
| } | ||||
|  |  | |||
|  | @ -1,20 +1,25 @@ | |||
| #ifndef __MDNSRESPONDER_H__ | ||||
| #define __MDNSRESPONDER_H__ | ||||
| 
 | ||||
| #include <lwip/ip_addr.h> | ||||
| 
 | ||||
| /*
 | ||||
|  * Basic multicast DNS responder | ||||
|  * | ||||
|  * Advertises the IP address, port, and characteristics of a service to other devices using multicast DNS on the same LAN, | ||||
|  * so they can find devices with addresses dynamically allocated by DHCP. See avahi, Bonjour, etc | ||||
|  * See RFC6762, RFC6763 | ||||
|  * Advertises the IP address, port, and characteristics of a service to other | ||||
|  * devices using multicast DNS on the same LAN, so they can find devices with | ||||
|  * addresses dynamically allocated by DHCP. See avahi, Bonjour, etc See RFC6762, | ||||
|  * RFC6763 | ||||
|  * | ||||
|  * This sample code is in the public domain. | ||||
|  * | ||||
|  * by M J A Hamel 2016 | ||||
|  */ | ||||
| 
 | ||||
| #ifndef __MDNSRESPONDER_H__ | ||||
| #define __MDNSRESPONDER_H__ | ||||
| 
 | ||||
| #include <lwip/ip_addr.h> | ||||
| 
 | ||||
| /* The default maximum reply size, increase as necessary. */ | ||||
| #ifndef MDNS_RESPONDER_REPLY_SIZE | ||||
| #define MDNS_RESPONDER_REPLY_SIZE      320 | ||||
| #endif | ||||
| 
 | ||||
| // Starts the mDNS responder task, call first
 | ||||
| void mdns_init(); | ||||
|  | @ -42,7 +47,10 @@ void mdns_add_facility( const char* instanceName,   // Short user-friendly insta | |||
| void mdns_add_PTR(const char* rKey, u32_t ttl, const char* nameStr); | ||||
| void mdns_add_SRV(const char* rKey, u32_t ttl, u16_t rPort, const char* targname); | ||||
| void mdns_add_TXT(const char* rKey, u32_t ttl, const char* txtStr); | ||||
| void mdns_add_A  (const char* rKey, u32_t ttl, ip_addr_t addr); | ||||
| void mdns_add_A  (const char* rKey, u32_t ttl, const ip4_addr_t *addr); | ||||
| #if LWIP_IPV6 | ||||
| void mdns_add_AAAA(const char* rKey, u32_t ttl, const ip6_addr_t *addr); | ||||
| #endif | ||||
| 
 | ||||
| /* Sample usage, advertising a secure web service
 | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue