| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- /*
- * MDNS Server Networking
- *
- */
- #include <string.h>
- #include "mdns_networking.h"
- #include "esp_log.h"
- #include "esp_netif_net_stack.h"
- extern mdns_server_t * _mdns_server;
- /*
- * MDNS Server Networking
- *
- */
- static const char *TAG = "MDNS_Networking";
- static struct udp_pcb * _pcb_main = NULL;
- static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport);
- /**
- * @brief Low level UDP PCB Initialize
- */
- static esp_err_t _udp_pcb_main_init(void)
- {
- if(_pcb_main) {
- return ESP_OK;
- }
- _pcb_main = udp_new();
- if (!_pcb_main) {
- return ESP_ERR_NO_MEM;
- }
- if (udp_bind(_pcb_main, IP_ANY_TYPE, MDNS_SERVICE_PORT) != 0) {
- udp_remove(_pcb_main);
- _pcb_main = NULL;
- return ESP_ERR_INVALID_STATE;
- }
- _pcb_main->mcast_ttl = 255;
- _pcb_main->remote_port = MDNS_SERVICE_PORT;
- ip_addr_copy(_pcb_main->remote_ip, *(IP_ANY_TYPE));
- udp_recv(_pcb_main, &_udp_recv, _mdns_server);
- return ESP_OK;
- }
- /**
- * @brief Low level UDP PCB Free
- */
- static void _udp_pcb_main_deinit(void)
- {
- if(_pcb_main){
- udp_recv(_pcb_main, NULL, NULL);
- udp_disconnect(_pcb_main);
- udp_remove(_pcb_main);
- _pcb_main = NULL;
- }
- }
- /**
- * @brief Low level UDP Multicast membership control
- */
- static esp_err_t _udp_join_group(mdns_if_t if_inx, mdns_ip_protocol_t ip_protocol, bool join)
- {
- struct netif * netif = NULL;
- esp_netif_t *tcpip_if = _mdns_get_esp_netif(if_inx);
- if (!esp_netif_is_netif_up(tcpip_if)) {
- // Network interface went down before event propagated, skipping IGMP config
- return ESP_ERR_INVALID_STATE;
- }
- netif = esp_netif_get_netif_impl(tcpip_if);
- assert(netif);
- if (ip_protocol == MDNS_IP_PROTOCOL_V4) {
- ip4_addr_t multicast_addr;
- IP4_ADDR(&multicast_addr, 224, 0, 0, 251);
- if(join){
- if (igmp_joingroup_netif(netif, &multicast_addr)) {
- return ESP_ERR_INVALID_STATE;
- }
- } else {
- if (igmp_leavegroup_netif(netif, &multicast_addr)) {
- return ESP_ERR_INVALID_STATE;
- }
- }
- }
- #if CONFIG_LWIP_IPV6
- else {
- ip_addr_t multicast_addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000);
- if(join){
- if (mld6_joingroup_netif(netif, &(multicast_addr.u_addr.ip6))) {
- return ESP_ERR_INVALID_STATE;
- }
- } else {
- if (mld6_leavegroup_netif(netif, &(multicast_addr.u_addr.ip6))) {
- return ESP_ERR_INVALID_STATE;
- }
- }
- }
- #endif
- return ESP_OK;
- }
- /**
- * @brief the receive callback of the raw udp api. Packets are received here
- *
- */
- static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport)
- {
- uint8_t i;
- while (pb != NULL) {
- struct pbuf * this_pb = pb;
- pb = pb->next;
- this_pb->next = NULL;
- mdns_rx_packet_t * packet = (mdns_rx_packet_t *)malloc(sizeof(mdns_rx_packet_t));
- if (!packet) {
- HOOK_MALLOC_FAILED;
- //missed packet - no memory
- pbuf_free(this_pb);
- continue;
- }
- packet->tcpip_if = MDNS_IF_MAX;
- packet->pb = this_pb;
- packet->src_port = rport;
- #if CONFIG_LWIP_IPV6
- packet->src.type = raddr->type;
- memcpy(&packet->src.u_addr, &raddr->u_addr, sizeof(raddr->u_addr));
- #else
- packet->src.type = IPADDR_TYPE_V4;
- memcpy(&packet->src.u_addr.ip4, &raddr->addr, sizeof(ip_addr_t));
- #endif
- packet->dest.type = packet->src.type;
- if (packet->src.type == IPADDR_TYPE_V4) {
- packet->ip_protocol = MDNS_IP_PROTOCOL_V4;
- struct ip_hdr * iphdr = (struct ip_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP_HLEN);
- packet->dest.u_addr.ip4.addr = iphdr->dest.addr;
- packet->multicast = ip4_addr_ismulticast(&(packet->dest.u_addr.ip4));
- }
- #if CONFIG_LWIP_IPV6
- else {
- packet->ip_protocol = MDNS_IP_PROTOCOL_V6;
- struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP6_HLEN);
- memcpy(&packet->dest.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16);
- packet->multicast = ip6_addr_ismulticast(&(packet->dest.u_addr.ip6));
- }
- #endif
- //lwip does not return the proper pcb if you have more than one for the same multicast address (but different interfaces)
- struct netif * netif = NULL;
- struct udp_pcb * pcb = NULL;
- for (i=0; i<MDNS_IF_MAX; i++) {
- pcb = _mdns_server->interfaces[i].pcbs[packet->ip_protocol].pcb;
- netif = esp_netif_get_netif_impl(_mdns_get_esp_netif(i));
- if (pcb && netif && netif == ip_current_input_netif ()) {
- if (packet->src.type == IPADDR_TYPE_V4) {
- #if CONFIG_LWIP_IPV6
- 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)) {
- #else
- if ((packet->src.u_addr.ip4.addr & netif->netmask.addr) != (netif->ip_addr.addr & netif->netmask.addr)) {
- #endif //packet source is not in the same subnet
- pcb = NULL;
- break;
- }
- }
- packet->tcpip_if = i;
- break;
- }
- pcb = NULL;
- }
- if (!pcb || !_mdns_server || !_mdns_server->action_queue
- || _mdns_send_rx_action(packet) != ESP_OK) {
- pbuf_free(this_pb);
- free(packet);
- }
- }
- }
- /**
- * @brief Check if any of the interfaces is up
- */
- static bool _udp_pcb_is_in_use(void){
- int i, p;
- for (i=0; i<MDNS_IF_MAX; i++) {
- for (p=0; p<MDNS_IP_PROTOCOL_MAX; p++) {
- if(_mdns_server->interfaces[i].pcbs[p].pcb){
- return true;
- }
- }
- }
- return false;
- }
- /**
- * @brief Stop PCB Main code
- */
- static void _udp_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
- {
- if (!_mdns_server) {
- return;
- }
- mdns_pcb_t * _pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol];
- if (_pcb->pcb) {
- free(_pcb->probe_services);
- _pcb->state = PCB_OFF;
- _pcb->pcb = NULL;
- _pcb->probe_ip = false;
- _pcb->probe_services = NULL;
- _pcb->probe_services_len = 0;
- _pcb->probe_running = false;
- _pcb->failed_probes = 0;
- _udp_join_group(tcpip_if, ip_protocol, false);
- if(!_udp_pcb_is_in_use()) {
- _udp_pcb_main_deinit();
- }
- }
- }
- /**
- * @brief Start PCB Main code
- */
- static esp_err_t _udp_pcb_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
- {
- if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb) {
- return ESP_ERR_INVALID_STATE;
- }
- esp_err_t err = _udp_join_group(tcpip_if, ip_protocol, true);
- if(err){
- return err;
- }
- err = _udp_pcb_main_init();
- if(err){
- return err;
- }
- _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb = _pcb_main;
- _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].failed_probes = 0;
- return ESP_OK;
- }
- typedef struct {
- struct tcpip_api_call_data call;
- mdns_if_t tcpip_if;
- mdns_ip_protocol_t ip_protocol;
- struct pbuf *pbt;
- const ip_addr_t *ip;
- uint16_t port;
- esp_err_t err;
- } mdns_api_call_t;
- /**
- * @brief Start PCB from LwIP thread
- */
- static err_t _mdns_pcb_init_api(struct tcpip_api_call_data *api_call_msg)
- {
- mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg;
- msg->err = _udp_pcb_init(msg->tcpip_if, msg->ip_protocol);
- return msg->err;
- }
- /**
- * @brief Stop PCB from LwIP thread
- */
- static err_t _mdns_pcb_deinit_api(struct tcpip_api_call_data *api_call_msg)
- {
- mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg;
- _udp_pcb_deinit(msg->tcpip_if, msg->ip_protocol);
- msg->err = ESP_OK;
- return ESP_OK;
- }
- /*
- * Non-static functions below are
- * - _mdns prefixed
- * - commented in mdns_networking.h header
- */
- esp_err_t _mdns_pcb_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
- {
- mdns_api_call_t msg = {
- .tcpip_if = tcpip_if,
- .ip_protocol = ip_protocol
- };
- tcpip_api_call(_mdns_pcb_init_api, &msg.call);
- return msg.err;
- }
- esp_err_t _mdns_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol)
- {
- mdns_api_call_t msg = {
- .tcpip_if = tcpip_if,
- .ip_protocol = ip_protocol
- };
- tcpip_api_call(_mdns_pcb_deinit_api, &msg.call);
- return msg.err;
- }
- static err_t _mdns_udp_pcb_write_api(struct tcpip_api_call_data *api_call_msg)
- {
- void * nif = NULL;
- mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg;
- mdns_pcb_t * _pcb = &_mdns_server->interfaces[msg->tcpip_if].pcbs[msg->ip_protocol];
- nif = esp_netif_get_netif_impl(_mdns_get_esp_netif(msg->tcpip_if));
- if (!nif) {
- pbuf_free(msg->pbt);
- msg->err = ERR_IF;
- return ERR_IF;
- }
- esp_err_t err = udp_sendto_if (_pcb->pcb, msg->pbt, msg->ip, msg->port, (struct netif *)nif);
- pbuf_free(msg->pbt);
- msg->err = err;
- return err;
- }
- 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)
- {
- struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
- if (pbt == NULL) {
- return 0;
- }
- memcpy((uint8_t *)pbt->payload, data, len);
- mdns_api_call_t msg = {
- .tcpip_if = tcpip_if,
- .ip_protocol = ip_protocol,
- .pbt = pbt,
- .ip = (ip_addr_t *)ip,
- .port = port
- };
- tcpip_api_call(_mdns_udp_pcb_write_api, &msg.call);
- if (msg.err) {
- return 0;
- }
- return len;
- }
|