mdns_networking.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /*
  2. * MDNS Server Networking
  3. *
  4. */
  5. #include <string.h>
  6. #include "mdns_networking.h"
  7. #include "esp_log.h"
  8. extern mdns_server_t * _mdns_server;
  9. /*
  10. * MDNS Server Networking
  11. *
  12. */
  13. static const char *TAG = "MDNS_Networking";
  14. static struct udp_pcb * _pcb_main = NULL;
  15. static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport);
  16. /**
  17. * @brief Low level UDP PCB Initialize
  18. */
  19. static esp_err_t _udp_pcb_main_init()
  20. {
  21. if(_pcb_main) {
  22. return ESP_OK;
  23. }
  24. _pcb_main = udp_new();
  25. if (!_pcb_main) {
  26. return ESP_ERR_NO_MEM;
  27. }
  28. if (udp_bind(_pcb_main, IP_ANY_TYPE, MDNS_SERVICE_PORT) != 0) {
  29. udp_remove(_pcb_main);
  30. _pcb_main = NULL;
  31. return ESP_ERR_INVALID_STATE;
  32. }
  33. _pcb_main->mcast_ttl = 1;
  34. _pcb_main->remote_port = MDNS_SERVICE_PORT;
  35. ip_addr_copy(_pcb_main->remote_ip, ip_addr_any_type);
  36. udp_recv(_pcb_main, &_udp_recv, _mdns_server);
  37. return ESP_OK;
  38. }
  39. /**
  40. * @brief Low level UDP PCB Free
  41. */
  42. static void _udp_pcb_main_deinit()
  43. {
  44. if(_pcb_main){
  45. udp_recv(_pcb_main, NULL, NULL);
  46. udp_disconnect(_pcb_main);
  47. udp_remove(_pcb_main);
  48. _pcb_main = NULL;
  49. }
  50. }
  51. /**
  52. * @brief Low level UDP Multicast membership control
  53. */
  54. static esp_err_t _udp_join_group(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, bool join)
  55. {
  56. struct netif * netif = NULL;
  57. void * nif = NULL;
  58. if (!tcpip_adapter_is_netif_up(tcpip_if)) {
  59. // Network interface went down before event propagated, skipping IGMP config
  60. return ESP_ERR_INVALID_STATE;
  61. }
  62. esp_err_t err = tcpip_adapter_get_netif(tcpip_if, &nif);
  63. if (err) {
  64. return ESP_ERR_INVALID_ARG;
  65. }
  66. netif = (struct netif *)nif;
  67. if (ip_protocol == MDNS_IP_PROTOCOL_V4) {
  68. ip_addr_t multicast_addr;
  69. IP_ADDR4(&multicast_addr, 224, 0, 0, 251);
  70. if(join){
  71. if (igmp_joingroup_netif(netif, (const struct ip4_addr *)&multicast_addr.u_addr.ip4)) {
  72. return ESP_ERR_INVALID_STATE;
  73. }
  74. } else {
  75. if (igmp_leavegroup_netif(netif, (const struct ip4_addr *)&multicast_addr.u_addr.ip4)) {
  76. return ESP_ERR_INVALID_STATE;
  77. }
  78. }
  79. } else {
  80. ip_addr_t multicast_addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000);
  81. if(join){
  82. if (mld6_joingroup_netif(netif, &(multicast_addr.u_addr.ip6))) {
  83. return ESP_ERR_INVALID_STATE;
  84. }
  85. } else {
  86. if (mld6_leavegroup_netif(netif, &(multicast_addr.u_addr.ip6))) {
  87. return ESP_ERR_INVALID_STATE;
  88. }
  89. }
  90. }
  91. return ESP_OK;
  92. }
  93. /**
  94. * @brief the receive callback of the raw udp api. Packets are received here
  95. *
  96. */
  97. static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport)
  98. {
  99. uint8_t i;
  100. while (pb != NULL) {
  101. struct pbuf * this_pb = pb;
  102. pb = pb->next;
  103. this_pb->next = NULL;
  104. mdns_rx_packet_t * packet = (mdns_rx_packet_t *)malloc(sizeof(mdns_rx_packet_t));
  105. if (!packet) {
  106. HOOK_MALLOC_FAILED;
  107. //missed packet - no memory
  108. pbuf_free(this_pb);
  109. continue;
  110. }
  111. packet->tcpip_if = TCPIP_ADAPTER_IF_MAX;
  112. packet->pb = this_pb;
  113. packet->src_port = rport;
  114. memcpy(&packet->src, raddr, sizeof(ip_addr_t));
  115. packet->dest.type = packet->src.type;
  116. if (packet->src.type == IPADDR_TYPE_V4) {
  117. packet->ip_protocol = MDNS_IP_PROTOCOL_V4;
  118. struct ip_hdr * iphdr = (struct ip_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP_HLEN);
  119. packet->dest.u_addr.ip4.addr = iphdr->dest.addr;
  120. } else {
  121. packet->ip_protocol = MDNS_IP_PROTOCOL_V6;
  122. struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP6_HLEN);
  123. memcpy(&packet->dest.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16);
  124. }
  125. packet->multicast = ip_addr_ismulticast(&(packet->dest));
  126. //lwip does not return the proper pcb if you have more than one for the same multicast address (but different interfaces)
  127. struct netif * netif = NULL;
  128. void * nif = NULL;
  129. struct udp_pcb * pcb = NULL;
  130. for (i=0; i<TCPIP_ADAPTER_IF_MAX; i++) {
  131. pcb = _mdns_server->interfaces[i].pcbs[packet->ip_protocol].pcb;
  132. tcpip_adapter_get_netif (i, &nif);
  133. netif = (struct netif *)nif;
  134. if (pcb && netif && netif == ip_current_input_netif ()) {
  135. if (packet->src.type == IPADDR_TYPE_V4) {
  136. 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)) {
  137. //packet source is not in the same subnet
  138. pcb = NULL;
  139. break;
  140. }
  141. }
  142. packet->tcpip_if = i;
  143. break;
  144. }
  145. pcb = NULL;
  146. }
  147. if (!pcb || !_mdns_server || !_mdns_server->action_queue
  148. || _mdns_send_rx_action(packet) != ESP_OK) {
  149. pbuf_free(this_pb);
  150. free(packet);
  151. }
  152. }
  153. }
  154. /**
  155. * @brief Check if any of the interfaces is up
  156. */
  157. static bool _udp_pcb_is_in_use(){
  158. int i, p;
  159. for (i=0; i<TCPIP_ADAPTER_IF_MAX; i++) {
  160. for (p=0; p<MDNS_IP_PROTOCOL_MAX; p++) {
  161. if(_mdns_server->interfaces[i].pcbs[p].pcb){
  162. return true;
  163. }
  164. }
  165. }
  166. return false;
  167. }
  168. /**
  169. * @brief Stop PCB Main code
  170. */
  171. static void _udp_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
  172. {
  173. if (!_mdns_server) {
  174. return;
  175. }
  176. mdns_pcb_t * _pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol];
  177. if (_pcb->pcb) {
  178. free(_pcb->probe_services);
  179. _pcb->state = PCB_OFF;
  180. _pcb->pcb = NULL;
  181. _pcb->probe_ip = false;
  182. _pcb->probe_services = NULL;
  183. _pcb->probe_services_len = 0;
  184. _pcb->probe_running = false;
  185. _pcb->failed_probes = 0;
  186. _udp_join_group(tcpip_if, ip_protocol, false);
  187. if(!_udp_pcb_is_in_use()) {
  188. _udp_pcb_main_deinit();
  189. }
  190. }
  191. }
  192. /**
  193. * @brief Start PCB Main code
  194. */
  195. static esp_err_t _udp_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
  196. {
  197. if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb) {
  198. return ESP_ERR_INVALID_STATE;
  199. }
  200. esp_err_t err = _udp_join_group(tcpip_if, ip_protocol, true);
  201. if(err){
  202. return err;
  203. }
  204. err = _udp_pcb_main_init();
  205. if(err){
  206. return err;
  207. }
  208. _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb = _pcb_main;
  209. _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].failed_probes = 0;
  210. return ESP_OK;
  211. }
  212. typedef struct {
  213. struct tcpip_api_call_data call;
  214. tcpip_adapter_if_t tcpip_if;
  215. mdns_ip_protocol_t ip_protocol;
  216. struct pbuf *pbt;
  217. const ip_addr_t *ip;
  218. uint16_t port;
  219. esp_err_t err;
  220. } mdns_api_call_t;
  221. /**
  222. * @brief Start PCB from LwIP thread
  223. */
  224. static err_t _mdns_pcb_init_api(struct tcpip_api_call_data *api_call_msg)
  225. {
  226. mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg;
  227. msg->err = _udp_pcb_init(msg->tcpip_if, msg->ip_protocol);
  228. return msg->err;
  229. }
  230. /**
  231. * @brief Stop PCB from LwIP thread
  232. */
  233. static err_t _mdns_pcb_deinit_api(struct tcpip_api_call_data *api_call_msg)
  234. {
  235. mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg;
  236. _udp_pcb_deinit(msg->tcpip_if, msg->ip_protocol);
  237. msg->err = ESP_OK;
  238. return ESP_OK;
  239. }
  240. /*
  241. * Non-static functions below are
  242. * - _mdns prefixed
  243. * - commented in mdns_networking.h header
  244. */
  245. esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
  246. {
  247. mdns_api_call_t msg = {
  248. .tcpip_if = tcpip_if,
  249. .ip_protocol = ip_protocol
  250. };
  251. tcpip_api_call(_mdns_pcb_init_api, &msg.call);
  252. return msg.err;
  253. }
  254. esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
  255. {
  256. mdns_api_call_t msg = {
  257. .tcpip_if = tcpip_if,
  258. .ip_protocol = ip_protocol
  259. };
  260. tcpip_api_call(_mdns_pcb_deinit_api, &msg.call);
  261. return msg.err;
  262. }
  263. static err_t _mdns_udp_pcb_write_api(struct tcpip_api_call_data *api_call_msg)
  264. {
  265. void * nif = NULL;
  266. mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg;
  267. mdns_pcb_t * _pcb = &_mdns_server->interfaces[msg->tcpip_if].pcbs[msg->ip_protocol];
  268. esp_err_t err = tcpip_adapter_get_netif(msg->tcpip_if, &nif);
  269. if (err) {
  270. msg->err = err;
  271. return err;
  272. }
  273. err = udp_sendto_if (_pcb->pcb, msg->pbt, msg->ip, msg->port, (struct netif *)nif);
  274. pbuf_free(msg->pbt);
  275. msg->err = err;
  276. return err;
  277. }
  278. 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)
  279. {
  280. struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
  281. if (pbt == NULL) {
  282. return 0;
  283. }
  284. memcpy((uint8_t *)pbt->payload, data, len);
  285. mdns_api_call_t msg = {
  286. .tcpip_if = tcpip_if,
  287. .ip_protocol = ip_protocol,
  288. .pbt = pbt,
  289. .ip = ip,
  290. .port = port
  291. };
  292. tcpip_api_call(_mdns_udp_pcb_write_api, &msg.call);
  293. if (msg.err) {
  294. return 0;
  295. }
  296. return len;
  297. }