3 * MDNS Server Networking
7 #include "mdns_networking.h"
10 extern mdns_server_t * _mdns_server;
13 * MDNS Server Networking
18 * @brief the receive callback of the raw udp api. Packets are received here
21 static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport)
26 struct pbuf * this_pb = pb;
30 mdns_rx_packet_t * packet = (mdns_rx_packet_t *)malloc(sizeof(mdns_rx_packet_t));
32 //missed packet - no memory
37 packet->tcpip_if = TCPIP_ADAPTER_IF_MAX;
39 packet->src_port = rport;
40 memcpy(&packet->src, raddr, sizeof(ip_addr_t));
41 packet->dest.type = packet->src.type;
43 if (packet->src.type == IPADDR_TYPE_V4) {
44 packet->ip_protocol = MDNS_IP_PROTOCOL_V4;
45 struct ip_hdr * iphdr = (struct ip_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP_HLEN);
46 packet->dest.u_addr.ip4.addr = iphdr->dest.addr;
48 packet->ip_protocol = MDNS_IP_PROTOCOL_V6;
49 struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP6_HLEN);
50 memcpy(&packet->dest.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16);
52 packet->multicast = ip_addr_ismulticast(&(packet->dest));
54 //lwip does not return the proper pcb if you have more than one for the same multicast address (but different interfaces)
55 struct netif * netif = NULL;
57 struct udp_pcb * pcb = NULL;
58 for (i=0; i<TCPIP_ADAPTER_IF_MAX; i++) {
59 pcb = _mdns_server->interfaces[i].pcbs[packet->ip_protocol].pcb;
60 tcpip_adapter_get_netif (i, &nif);
61 netif = (struct netif *)nif;
62 if (pcb && netif && netif == ip_current_input_netif ()) {
63 if (packet->src.type == IPADDR_TYPE_V4) {
64 if ((packet->src.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr) != (netif->ip_addr.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr)) {
65 //packet source is not in the same subnet
76 if (!pcb || !_mdns_server || !_mdns_server->action_queue
77 || _mdns_send_rx_action(packet) != ESP_OK) {
86 * @brief Stop PCB Main code
88 static void _udp_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
93 mdns_pcb_t * _pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol];
95 _pcb->state = PCB_OFF;
96 udp_recv(_pcb->pcb, NULL, NULL);
97 udp_disconnect(_pcb->pcb);
98 udp_remove(_pcb->pcb);
99 free(_pcb->probe_services);
101 _pcb->probe_ip = false;
102 _pcb->probe_services = NULL;
103 _pcb->probe_services_len = 0;
104 _pcb->probe_running = false;
105 _pcb->failed_probes = 0;
110 * @brief Start PCB V4
112 static esp_err_t _udp_pcb_v4_init(tcpip_adapter_if_t tcpip_if)
114 tcpip_adapter_ip_info_t if_ip_info;
116 if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb) {
117 return ESP_ERR_INVALID_STATE;
120 if (tcpip_adapter_get_ip_info(tcpip_if, &if_ip_info) || if_ip_info.ip.addr == 0) {
121 return ESP_ERR_INVALID_ARG;
124 ip_addr_t interface_addr = IPADDR4_INIT(if_ip_info.ip.addr);
126 ip_addr_t multicast_addr;
127 IP_ADDR4(&multicast_addr, 224, 0, 0, 251);
129 if (igmp_joingroup((const struct ip4_addr *)&interface_addr.u_addr.ip4, (const struct ip4_addr *)&multicast_addr.u_addr.ip4)) {
130 return ESP_ERR_INVALID_STATE;
133 struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V4);
135 return ESP_ERR_NO_MEM;
138 if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) {
140 return ESP_ERR_INVALID_STATE;
144 pcb->remote_port = MDNS_SERVICE_PORT;
145 ip_addr_copy(pcb->multicast_ip, interface_addr);
146 ip_addr_copy(pcb->remote_ip, multicast_addr);
148 _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb = pcb;
149 _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].failed_probes = 0;
150 udp_recv(pcb, &_udp_recv, _mdns_server);
156 * @brief Start PCB V6
158 static esp_err_t _udp_pcb_v6_init(tcpip_adapter_if_t tcpip_if)
160 ip_addr_t multicast_addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000);
161 ip_addr_t interface_addr;
162 interface_addr.type = IPADDR_TYPE_V6;
164 if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb) {
165 return ESP_ERR_INVALID_STATE;
168 if (tcpip_adapter_get_ip6_linklocal(tcpip_if, &interface_addr.u_addr.ip6)) {
169 return ESP_ERR_INVALID_ARG;
172 if (mld6_joingroup(&(interface_addr.u_addr.ip6), &(multicast_addr.u_addr.ip6))) {
173 return ESP_ERR_INVALID_STATE;
176 struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V6);
178 return ESP_ERR_NO_MEM;
181 if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) {
183 return ESP_ERR_INVALID_STATE;
186 pcb->remote_port = MDNS_SERVICE_PORT;
187 ip_addr_copy(pcb->remote_ip, multicast_addr);
189 _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb = pcb;
190 _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].failed_probes = 0;
191 udp_recv(pcb, &_udp_recv, _mdns_server);
197 * @brief Start PCB Main code
199 static esp_err_t _udp_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
201 if (ip_protocol == MDNS_IP_PROTOCOL_V4) {
202 return _udp_pcb_v4_init(tcpip_if);
203 } else if (ip_protocol == MDNS_IP_PROTOCOL_V6) {
204 return _udp_pcb_v6_init(tcpip_if);
206 return ESP_ERR_INVALID_ARG;
210 struct tcpip_api_call_data call;
211 tcpip_adapter_if_t tcpip_if;
212 mdns_ip_protocol_t ip_protocol;
217 * @brief Start PCB from LwIP thread
219 static err_t _mdns_pcb_init_api(struct tcpip_api_call_data *api_call_msg)
221 mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg;
222 msg->err = _udp_pcb_init(msg->tcpip_if, msg->ip_protocol);
227 * @brief Stop PCB from LwIP thread
229 static err_t _mdns_pcb_deinit_api(struct tcpip_api_call_data *api_call_msg)
231 mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg;
232 _udp_pcb_deinit(msg->tcpip_if, msg->ip_protocol);
238 * Non-static functions below are
240 * - commented in mdns_networking.h header
242 esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
244 mdns_api_call_t msg = {
245 .tcpip_if = tcpip_if,
246 .ip_protocol = ip_protocol
248 tcpip_api_call(_mdns_pcb_init_api, (struct tcpip_api_call_data*)&msg);
252 esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
254 mdns_api_call_t msg = {
255 .tcpip_if = tcpip_if,
256 .ip_protocol = ip_protocol
258 tcpip_api_call(_mdns_pcb_deinit_api, (struct tcpip_api_call_data*)&msg);
262 size_t _mdns_udp_pcb_write(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len)
264 struct netif * netif = NULL;
266 esp_err_t err = tcpip_adapter_get_netif(tcpip_if, &nif);
267 netif = (struct netif *)nif;
272 struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
276 memcpy((uint8_t *)pbt->payload, data, len);
278 err = udp_sendto_if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb, pbt, ip, port, netif);