]> granicus.if.org Git - esp-idf/blob - components/mdns/mdns_networking.c
Merge branch 'feature/task_wdt_add_timestamp' into 'master'
[esp-idf] / components / mdns / mdns_networking.c
1
2 /*
3  * MDNS Server Networking
4  * 
5  */
6 #include <string.h>
7 #include "mdns_networking.h"
8
9
10 extern mdns_server_t * _mdns_server;
11
12 /*
13  * MDNS Server Networking
14  *
15  */
16
17 /**
18  * @brief  the receive callback of the raw udp api. Packets are received here
19  *
20  */
21 static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport)
22 {
23
24     uint8_t i;
25     while (pb != NULL) {
26         struct pbuf * this_pb = pb;
27         pb = pb->next;
28         this_pb->next = NULL;
29
30         mdns_rx_packet_t * packet = (mdns_rx_packet_t *)malloc(sizeof(mdns_rx_packet_t));
31         if (!packet) {
32             //missed packet - no memory
33             pbuf_free(this_pb);
34             continue;
35         }
36
37         packet->tcpip_if = TCPIP_ADAPTER_IF_MAX;
38         packet->pb = this_pb;
39         packet->src_port = rport;
40         memcpy(&packet->src, raddr, sizeof(ip_addr_t));
41         packet->dest.type = packet->src.type;
42
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;
47         } else {
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);
51         }
52         packet->multicast = ip_addr_ismulticast(&(packet->dest));
53
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;
56         void * nif = 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
66                         pcb = NULL;
67                         break;
68                     }
69                 }
70                 packet->tcpip_if = i;
71                 break;
72             }
73             pcb = NULL;
74         }
75
76         if (!pcb || !_mdns_server || !_mdns_server->action_queue
77           || _mdns_send_rx_action(packet) != ESP_OK) {
78             pbuf_free(this_pb);
79             free(packet);
80         }
81     }
82
83 }
84
85 /**
86  * @brief  Stop PCB Main code
87  */
88 static void _udp_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
89 {
90     if (!_mdns_server) {
91         return;
92     }
93     mdns_pcb_t * _pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol];
94     if (_pcb->pcb) {
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);
100         _pcb->pcb = NULL;
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;
106     }
107 }
108
109 /**
110  * @brief  Start PCB V4
111  */
112 static esp_err_t _udp_pcb_v4_init(tcpip_adapter_if_t tcpip_if)
113 {
114     tcpip_adapter_ip_info_t if_ip_info;
115
116     if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb) {
117         return ESP_ERR_INVALID_STATE;
118     }
119
120     if (tcpip_adapter_get_ip_info(tcpip_if, &if_ip_info) || if_ip_info.ip.addr == 0) {
121         return ESP_ERR_INVALID_ARG;
122     }
123
124     ip_addr_t interface_addr = IPADDR4_INIT(if_ip_info.ip.addr);
125
126     ip_addr_t multicast_addr;
127     IP_ADDR4(&multicast_addr, 224, 0, 0, 251);
128
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;
131     }
132
133     struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V4);
134     if (!pcb) {
135         return ESP_ERR_NO_MEM;
136     }
137
138     if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) {
139         udp_remove(pcb);
140         return ESP_ERR_INVALID_STATE;
141     }
142
143     pcb->mcast_ttl = 1;
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);
147
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);
151
152     return ESP_OK;
153 }
154
155 /**
156  * @brief  Start PCB V6
157  */
158 static esp_err_t _udp_pcb_v6_init(tcpip_adapter_if_t tcpip_if)
159 {
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;
163
164     if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb) {
165         return ESP_ERR_INVALID_STATE;
166     }
167
168     if (tcpip_adapter_get_ip6_linklocal(tcpip_if, &interface_addr.u_addr.ip6)) {
169         return ESP_ERR_INVALID_ARG;
170     }
171
172     if (mld6_joingroup(&(interface_addr.u_addr.ip6), &(multicast_addr.u_addr.ip6))) {
173         return ESP_ERR_INVALID_STATE;
174     }
175
176     struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V6);
177     if (!pcb) {
178         return ESP_ERR_NO_MEM;
179     }
180
181     if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) {
182         udp_remove(pcb);
183         return ESP_ERR_INVALID_STATE;
184     }
185
186     pcb->remote_port = MDNS_SERVICE_PORT;
187     ip_addr_copy(pcb->remote_ip, multicast_addr);
188
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);
192
193     return ESP_OK;
194 }
195
196 /**
197  * @brief  Start PCB Main code
198  */
199 static esp_err_t _udp_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
200 {
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);
205     }
206     return ESP_ERR_INVALID_ARG;
207 }
208
209 typedef struct {
210     struct tcpip_api_call_data call;
211     tcpip_adapter_if_t tcpip_if;
212     mdns_ip_protocol_t ip_protocol;
213     esp_err_t err;
214 } mdns_api_call_t;
215
216 /**
217  * @brief  Start PCB from LwIP thread
218  */
219 static err_t _mdns_pcb_init_api(struct tcpip_api_call_data *api_call_msg)
220 {
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);
223     return msg->err;
224 }
225
226 /**
227  * @brief  Stop PCB from LwIP thread
228  */
229 static err_t _mdns_pcb_deinit_api(struct tcpip_api_call_data *api_call_msg)
230 {
231     mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg;
232     _udp_pcb_deinit(msg->tcpip_if, msg->ip_protocol);
233     msg->err = ESP_OK;
234     return ESP_OK;
235 }
236
237 /*
238  * Non-static functions below are
239  *  - _mdns prefixed
240  *  - commented in mdns_networking.h header
241  */
242 esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
243 {
244     mdns_api_call_t msg = {
245         .tcpip_if = tcpip_if,
246         .ip_protocol = ip_protocol
247     };
248     tcpip_api_call(_mdns_pcb_init_api, (struct tcpip_api_call_data*)&msg);
249     return msg.err;
250 }
251
252 esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
253 {
254     mdns_api_call_t msg = {
255         .tcpip_if = tcpip_if,
256         .ip_protocol = ip_protocol
257     };
258     tcpip_api_call(_mdns_pcb_deinit_api, (struct tcpip_api_call_data*)&msg);
259     return msg.err;
260 }
261
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)
263 {
264     struct netif * netif = NULL;
265     void * nif = NULL;
266     esp_err_t err = tcpip_adapter_get_netif(tcpip_if, &nif);
267     netif = (struct netif *)nif;
268     if (err) {
269         return 0;
270     }
271
272     struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
273     if (pbt == NULL) {
274         return 0;
275     }
276     memcpy((uint8_t *)pbt->payload, data, len);
277
278     err = udp_sendto_if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb, pbt, ip, port, netif);
279     pbuf_free(pbt);
280     if (err) {
281         return 0;
282     }
283     return len;
284 }