mdns_networking.c 9.3 KB

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