1*5d5fbe79SDavid van MoolenbroekMulticast DNS for lwIP 2*5d5fbe79SDavid van Moolenbroek 3*5d5fbe79SDavid van MoolenbroekAuthor: Erik Ekman 4*5d5fbe79SDavid van Moolenbroek 5*5d5fbe79SDavid van Moolenbroek 6*5d5fbe79SDavid van MoolenbroekNote! The MDNS responder does not have all features required by the standards. 7*5d5fbe79SDavid van MoolenbroekSee notes in src/apps/mdns/mdns.c for what is left. It is however usable in normal 8*5d5fbe79SDavid van Moolenbroekcases - but watch out if many devices on the same network try to use the same 9*5d5fbe79SDavid van Moolenbroekhost/service instance names. 10*5d5fbe79SDavid van Moolenbroek 11*5d5fbe79SDavid van Moolenbroek 12*5d5fbe79SDavid van MoolenbroekHow to enable: 13*5d5fbe79SDavid van Moolenbroek============== 14*5d5fbe79SDavid van Moolenbroek 15*5d5fbe79SDavid van MoolenbroekMDNS support does not depend on DNS. 16*5d5fbe79SDavid van MoolenbroekMDNS supports using IPv4 only, v6 only, or v4+v6. 17*5d5fbe79SDavid van Moolenbroek 18*5d5fbe79SDavid van MoolenbroekTo enable MDNS responder, set 19*5d5fbe79SDavid van Moolenbroek LWIP_MDNS_RESPONDER = 1 20*5d5fbe79SDavid van Moolenbroekin lwipopts.h and add src/apps/mdns/mdns.c to your list of files to build. 21*5d5fbe79SDavid van Moolenbroek 22*5d5fbe79SDavid van MoolenbroekThe max number of services supported per netif is defined by MDNS_MAX_SERVICES, 23*5d5fbe79SDavid van Moolenbroekdefault is 1. 24*5d5fbe79SDavid van Moolenbroek 25*5d5fbe79SDavid van MoolenbroekIncrease MEMP_NUM_UDP_PCB by 1. MDNS needs one PCB. 26*5d5fbe79SDavid van MoolenbroekIncrease LWIP_NUM_NETIF_CLIENT_DATA by 1 (MDNS needs one entry on netif). 27*5d5fbe79SDavid van Moolenbroek 28*5d5fbe79SDavid van MoolenbroekMDNS with IPv4 requires LWIP_IGMP = 1, and preferably LWIP_AUTOIP = 1. 29*5d5fbe79SDavid van MoolenbroekMDNS with IPv6 requires LWIP_IPV6_MLD = 1, and that a link-local address is 30*5d5fbe79SDavid van Moolenbroekgenerated. 31*5d5fbe79SDavid van Moolenbroek 32*5d5fbe79SDavid van MoolenbroekThe MDNS code puts its structs on the stack where suitable to reduce dynamic 33*5d5fbe79SDavid van Moolenbroekmemory allocation. It may use up to 1kB of stack. 34*5d5fbe79SDavid van Moolenbroek 35*5d5fbe79SDavid van MoolenbroekMDNS needs a strncasecmp() implementation. If you have one, define 36*5d5fbe79SDavid van MoolenbroekLWIP_MDNS_STRNCASECMP to it. Otherwise the code will provide an implementation 37*5d5fbe79SDavid van Moolenbroekfor you. 38*5d5fbe79SDavid van Moolenbroek 39*5d5fbe79SDavid van Moolenbroek 40*5d5fbe79SDavid van MoolenbroekHow to use: 41*5d5fbe79SDavid van Moolenbroek=========== 42*5d5fbe79SDavid van Moolenbroek 43*5d5fbe79SDavid van MoolenbroekCall mdns_resp_init() during system initialization. 44*5d5fbe79SDavid van MoolenbroekThis opens UDP sockets on port 5353 for IPv4 and IPv6. 45*5d5fbe79SDavid van Moolenbroek 46*5d5fbe79SDavid van Moolenbroek 47*5d5fbe79SDavid van MoolenbroekTo start responding on a netif, run 48*5d5fbe79SDavid van Moolenbroek mdns_resp_add_netif(struct netif *netif, char *hostname, u32_t dns_ttl) 49*5d5fbe79SDavid van Moolenbroek 50*5d5fbe79SDavid van MoolenbroekThe hostname will be copied. If this returns successfully, the netif will join 51*5d5fbe79SDavid van Moolenbroekthe multicast groups and any MDNS/legacy DNS requests sent unicast or multicast 52*5d5fbe79SDavid van Moolenbroekto port 5353 will be handled: 53*5d5fbe79SDavid van Moolenbroek- <hostname>.local type A, AAAA or ANY returns relevant IP addresses 54*5d5fbe79SDavid van Moolenbroek- Reverse lookups (PTR in-addr.arpa, ip6.arpa) of netif addresses 55*5d5fbe79SDavid van Moolenbroek returns <hostname>.local 56*5d5fbe79SDavid van MoolenbroekAnswers will use the supplied TTL (in seconds) 57*5d5fbe79SDavid van MoolenbroekMDNS allows UTF-8 names, but it is recommended to stay within ASCII, 58*5d5fbe79SDavid van Moolenbroeksince the default case-insensitive comparison assumes this. 59*5d5fbe79SDavid van Moolenbroek 60*5d5fbe79SDavid van MoolenbroekIt is recommended to call this function after an IPv4 address has been set, 61*5d5fbe79SDavid van Moolenbroeksince there is currently no check if the v4 address is valid. 62*5d5fbe79SDavid van Moolenbroek 63*5d5fbe79SDavid van MoolenbroekCall mdns_resp_netif_settings_changed() every time the IP address 64*5d5fbe79SDavid van Moolenbroekon the netif has changed. 65*5d5fbe79SDavid van Moolenbroek 66*5d5fbe79SDavid van MoolenbroekTo stop responding on a netif, run 67*5d5fbe79SDavid van Moolenbroek mdns_resp_remove_netif(struct netif *netif) 68*5d5fbe79SDavid van Moolenbroek 69*5d5fbe79SDavid van Moolenbroek 70*5d5fbe79SDavid van MoolenbroekAdding services: 71*5d5fbe79SDavid van Moolenbroek================ 72*5d5fbe79SDavid van Moolenbroek 73*5d5fbe79SDavid van MoolenbroekThe netif first needs to be registered. Then run 74*5d5fbe79SDavid van Moolenbroek mdns_resp_add_service(struct netif *netif, char *name, char *service, 75*5d5fbe79SDavid van Moolenbroek u16_t proto, u16_t port, u32_t dns_ttl, 76*5d5fbe79SDavid van Moolenbroek service_get_txt_fn_t txt_fn, void *txt_userdata); 77*5d5fbe79SDavid van Moolenbroek 78*5d5fbe79SDavid van MoolenbroekThe name and service pointers will be copied. Name refers to the name of the 79*5d5fbe79SDavid van Moolenbroekservice instance, and service is the type of service, like _http 80*5d5fbe79SDavid van Moolenbroekproto can be DNSSD_PROTO_UDP or DNSSD_PROTO_TCP which represent _udp and _tcp. 81*5d5fbe79SDavid van MoolenbroekIf this call returns successfully, the following queries will be answered: 82*5d5fbe79SDavid van Moolenbroek- _services._dns-sd._udp.local type PTR returns <service>.<proto>.local 83*5d5fbe79SDavid van Moolenbroek- <service>.<proto>.local type PTR returns <name>.<service>.<proto>.local 84*5d5fbe79SDavid van Moolenbroek- <name>.<service>.<proto>.local type SRV returns hostname and port of service 85*5d5fbe79SDavid van Moolenbroek- <name>.<service>.<proto>.local type TXT builds text strings by calling txt_fn 86*5d5fbe79SDavid van Moolenbroek with the supplied userdata. The callback adds strings to the reply by calling 87*5d5fbe79SDavid van Moolenbroek mdns_resp_add_service_txtitem(struct mdns_service *service, char *txt, 88*5d5fbe79SDavid van Moolenbroek int txt_len). Example callback method: 89*5d5fbe79SDavid van Moolenbroek 90*5d5fbe79SDavid van Moolenbroek static void srv_txt(struct mdns_service *service, void *txt_userdata) 91*5d5fbe79SDavid van Moolenbroek { 92*5d5fbe79SDavid van Moolenbroek res = mdns_resp_add_service_txtitem(service, "path=/", 6); 93*5d5fbe79SDavid van Moolenbroek LWIP_ERROR("mdns add service txt failed\n", (res == ERR_OK), return); 94*5d5fbe79SDavid van Moolenbroek } 95*5d5fbe79SDavid van Moolenbroek 96*5d5fbe79SDavid van Moolenbroek Since a hostname struct is used for TXT storage each single item can be max 97*5d5fbe79SDavid van Moolenbroek 63 bytes long, and the total max length (including length bytes for each 98*5d5fbe79SDavid van Moolenbroek item) is 255 bytes. 99*5d5fbe79SDavid van Moolenbroek 100*5d5fbe79SDavid van MoolenbroekIf your device runs a webserver on port 80, an example call might be: 101*5d5fbe79SDavid van Moolenbroek 102*5d5fbe79SDavid van Moolenbroek mdns_resp_add_service(netif, "myweb", "_http" 103*5d5fbe79SDavid van Moolenbroek DNSSD_PROTO_TCP, 80, 3600, srv_txt, NULL); 104*5d5fbe79SDavid van Moolenbroek 105*5d5fbe79SDavid van Moolenbroekwhich will publish myweb._http._tcp.local for any hosts looking for web servers, 106*5d5fbe79SDavid van Moolenbroekand point them to <hostname>.local:80 107*5d5fbe79SDavid van Moolenbroek 108*5d5fbe79SDavid van MoolenbroekRelevant information will be sent as additional records to reduce number of 109*5d5fbe79SDavid van Moolenbroekrequests required from a client. 110*5d5fbe79SDavid van Moolenbroek 111*5d5fbe79SDavid van MoolenbroekRemoving services is currently not supported. Services are removed when the 112*5d5fbe79SDavid van Moolenbroeknetif is removed. 113*5d5fbe79SDavid van Moolenbroek 114