Exemple #1
0
static int net_multicastJoinLeave( lua_State *L, int join) {
	  size_t il;
	  ip_addr_t multicast_addr;
	  ip_addr_t if_addr;
	  const char *multicast_ip;
	  const char *if_ip;

	  NODE_DBG("net_multicastJoin is called.\n");
	  if(! lua_isstring(L,1) ) return luaL_error( L, "wrong arg type" );
	  if_ip = luaL_checklstring( L, 1, &il );
	  if (if_ip != NULL)
		 if ( if_ip[0] == '\0' || stricmp(if_ip,"any") == 0)
	     {
			 if_ip = "0.0.0.0";
			 il = 7;
	     }
	  if (if_ip == NULL || il > 15 || il < 7) return luaL_error( L, "invalid if ip" );
	  if_addr.addr = ipaddr_addr(if_ip);

	  if(! lua_isstring(L,2) ) return luaL_error( L, "wrong arg type" );
	  multicast_ip = luaL_checklstring( L, 2, &il );
	  if (multicast_ip == NULL || il > 15 || il < 7) return luaL_error( L, "invalid multicast ip" );
	  multicast_addr.addr = ipaddr_addr(multicast_ip);
	  if (join)
	  {
		  igmp_joingroup(&if_addr, &multicast_addr);
	  }
	  else
	  {
		  igmp_leavegroup(&if_addr, &multicast_addr);
	  }
	  return 0;
}
Exemple #2
0
/**
 * Join multicast groups for UDP netconns.
 * Called from netconn_join_leave_group
 *
 * @param msg the api_msg_msg pointing to the connection
 */
void
do_join_leave_group(struct api_msg_msg *msg)
{
    if (ERR_IS_FATAL(msg->conn->last_err)) {
        msg->err = msg->conn->last_err;
    } else {
        if (msg->conn->pcb.tcp != NULL) {
            if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
#if LWIP_UDP
                if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
                    msg->err = igmp_joingroup(msg->msg.jl.netif_addr, msg->msg.jl.multiaddr);
                } else {
                    msg->err = igmp_leavegroup(msg->msg.jl.netif_addr, msg->msg.jl.multiaddr);
                }
#endif /* LWIP_UDP */
#if (LWIP_TCP || LWIP_RAW)
            } else {
                msg->err = ERR_VAL;
#endif /* (LWIP_TCP || LWIP_RAW) */
            }
        } else {
            msg->err = ERR_CONN;
        }
    }
    TCPIP_APIMSG_ACK(msg);
}
err_t simple_discovery_init(struct netif *netif)
{
    err_t ret;

    struct udp_pcb *pcb = udp_new();
    if (pcb == NULL)
        return ERR_MEM;

#if LWIP_IGMP
    struct ip_addr ipgroup;
    IP4_ADDR(&ipgroup, 224, 0, 0, 178);
    if ((ret = igmp_joingroup(IP_ADDR_ANY, &ipgroup)) != ERR_OK)
        goto error_exit;
#endif

    if ((ret = udp_bind(pcb, IP_ADDR_ANY, SIMPLE_DISCOVERY_PORT)) != ERR_OK)
        goto error_exit;

    udp_recv(pcb, recv, netif);

    return ERR_OK;

error_exit:
    udp_remove(pcb);
    return ret;

}
NetUdpSocketErr LwipNetUdpSocket::bind(const Host& me)
{
  err_t err;

  if(!m_pPcb)
    return NETUDPSOCKET_MEM; //NetUdpSocket was not properly initialised, should destroy it & retry

  #if LWIP_IGMP //Multicast support enabled
  if(me.getIp().isMulticast())
  {
    DBG("This is a multicast addr, joining multicast group\r\n");
    m_multicastGroup = me.getIp();
    ip_addr_t multicastGroupAddr = m_multicastGroup.getStruct();
    err = igmp_joingroup(IP_ADDR_ANY, &multicastGroupAddr);
    if(err)
      return NETUDPSOCKET_IF; //Could not find or create group
  }
  #endif

  err = udp_bind( (udp_pcb*) m_pPcb, IP_ADDR_ANY, me.getPort()); //IP_ADDR_ANY : Bind the connection to all local addresses
  if(err)
    return NETUDPSOCKET_INUSE;

  //Setup callback
  udp_recv( (udp_pcb*) m_pPcb, LwipNetUdpSocket::sRecvCb, (void*) this );

  return NETUDPSOCKET_OK;
}
Exemple #5
0
/******************************************************************************
 * FunctionName : espconn_igmp_join
 * Description  : join a multicast group
 * Parameters   : host_ip -- the ip address of udp server
 * 				  multicast_ip -- multicast ip given by user
 * Returns      : none
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_igmp_join(ip_addr_t *host_ip, ip_addr_t *multicast_ip)
{
    if (igmp_joingroup(host_ip, multicast_ip) != ERR_OK) {
        LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("udp_join_multigrup failed!\n"));
        return -1;
    };

    /* join to any IP address at the port  */
    return ESPCONN_OK;
}
err_t mdns_responder_init(const struct mdns_service *services,
                          int num_services,
                          const char *txt_records[])
{
    err_t ret;

    memset(&mdns_state, 0, sizeof(mdns_state));
    mdns_state.netif = &gs_net_if;

    setup_hostnames(&mdns_state, &gs_net_if);
    setup_txt_records(&mdns_state, txt_records);

    mdns_state.services = services;
    mdns_state.num_services = num_services;

    struct ip_addr ipgroup;
    IP4_ADDR(&ipgroup, 224, 0, 0, 251);

    mdns_state.sendpcb = udp_new();
    if (mdns_state.sendpcb == NULL)
        return ERR_MEM;

    struct udp_pcb *pcb = udp_new();
    if (pcb == NULL) {
        udp_remove(mdns_state.sendpcb);
        return ERR_MEM;
    }

    if ((ret = igmp_joingroup(IP_ADDR_ANY, &ipgroup)) != ERR_OK)
        return ret;

    ip_set_option(pcb, SOF_REUSEADDR);
    ip_set_option(mdns_state.sendpcb, SOF_REUSEADDR);

    if ((ret = udp_bind(pcb, IP_ADDR_ANY, MDNS_PORT)) != ERR_OK)
        goto error_exit;

    udp_recv(pcb, recv, &mdns_state);

    if ((ret = udp_bind(mdns_state.sendpcb, 0, MDNS_PORT)) != ERR_OK)
        goto error_exit;

    if ((ret = udp_connect(mdns_state.sendpcb, &ipgroup, MDNS_PORT)) != ERR_OK)
        goto error_exit;

    return ERR_OK;

error_exit:
    udp_remove(pcb);
    udp_remove(mdns_state.sendpcb);
    return ret;

}
STATIC mp_obj_t lwip_socket_setsockopt(size_t n_args, const mp_obj_t *args) {
    (void)n_args; // always 4
    lwip_socket_obj_t *socket = args[0];

    int opt = mp_obj_get_int(args[2]);
    if (opt == 20) {
        if (args[3] == mp_const_none) {
            socket->callback = MP_OBJ_NULL;
        } else {
            socket->callback = args[3];
        }
        return mp_const_none;
    }

    switch (opt) {
        // level: SOL_SOCKET
        case SOF_REUSEADDR: {
            mp_int_t val = mp_obj_get_int(args[3]);
            // Options are common for UDP and TCP pcb's.
            if (val) {
                ip_set_option(socket->pcb.tcp, SOF_REUSEADDR);
            } else {
                ip_reset_option(socket->pcb.tcp, SOF_REUSEADDR);
            }
            break;
        }

        // level: IPPROTO_IP
        case IP_ADD_MEMBERSHIP: {
            mp_buffer_info_t bufinfo;
            mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
            if (bufinfo.len != sizeof(ip_addr_t) * 2) {
                mp_raise_ValueError(NULL);
            }

            // POSIX setsockopt has order: group addr, if addr, lwIP has it vice-versa
            err_t err = igmp_joingroup((ip_addr_t*)bufinfo.buf + 1, bufinfo.buf);
            if (err != ERR_OK) {
                mp_raise_OSError(error_lookup_table[-err]);
            }
            break;
        }

        default:
            printf("Warning: lwip.setsockopt() not implemented\n");
    }
    return mp_const_none;
}
Exemple #8
0
int
netx_change_group(struct netxsocket_s *rlpsock, ip4addr_t localGroup, int operation)
{
    struct ip_addr addr;

    UNUSED_ARG(rlpsock);

    if (!is_multicast(localGroup)) return -1;

    /* result = ERR_OK which is defined as zero so return value is consistent */
    addr.addr = localGroup;
    if (operation == NETI_JOINGROUP)
        return igmp_joingroup(&netxf_default->ip_addr, &addr);
    else
        return igmp_leavegroup(&netxf_default->ip_addr, &addr);
}
Exemple #9
0
static int netdev_imsfioctl(FAR struct socket *psock, int cmd, struct ip_msfilter *imsf)
{
  FAR struct uip_driver_s *dev;
  int ret = OK;

  nvdbg("cmd: %d\n", cmd);

  /* Find the network device associated with the device name
   * in the request data.
   */

  dev = netdev_findbyname(imsf->imsf_name);
  if (!dev)
    {
      ret = -EINVAL;
      goto errout;
    }

  /* Execute the command */

  switch (cmd)
    {
      case SIOCSIPMSFILTER:  /* Set source filter content */
        {
          if (imsf->imsf_fmode == MCAST_INCLUDE)
            {
              ret = igmp_joingroup(dev, &imsf->imsf_multiaddr);
            }
          else
            {
              DEBUGASSERT(imsf->imsf_fmode == MCAST_EXCLUDE);
              ret = igmp_leavegroup(dev, &imsf->imsf_multiaddr);
            }
        }
        break;

      case SIOCGIPMSFILTER:  /* Retrieve source filter addresses */
      default:
        ret = -EINVAL;
        break;
    }

errout:
  return ret;
}
Exemple #10
0
bool MDNSResponder::begin(const char* hostname){
  // Open the MDNS socket if it isn't already open.

  size_t n = strlen(hostname);
  if (n > 63) { // max size for a single label.
    return false;
  }

  // Copy in hostname characters as lowercase
  _hostName = hostname;
  _hostName.toLowerCase();

  // If instance name is not already set copy hostname to instance name
  if (_instanceName.equals("") ) _instanceName=hostname; 

  // Open the MDNS socket if it isn't already open.
  if (!_conn) {
    uint32_t ourIp = _getOurIp();
    if(ourIp == 0){
      return false;
    }

    ip_addr_t ifaddr;
    ifaddr.addr = ourIp;
    ip_addr_t multicast_addr;
    multicast_addr.addr = (uint32_t) MDNS_MULTICAST_ADDR;

    if (igmp_joingroup(&ifaddr, &multicast_addr)!= ERR_OK) {
      return false;
    }

    _conn = new UdpContext;
    _conn->ref();

    if (!_conn->listen(*IP_ADDR_ANY, MDNS_PORT)) {
      return false;
    }
    _conn->setMulticastInterface(ifaddr);
    _conn->setMulticastTTL(MDNS_MULTICAST_TTL);
    _conn->onRx(std::bind(&MDNSResponder::update, this));
    _conn->connect(multicast_addr, MDNS_PORT);
  }
  return true;
}
Exemple #11
0
/**
 * Join multicast groups for UDP netconns.
 * Called from netconn_join_leave_group
 *
 * @param msg the api_msg_msg pointing to the connection
 */
void
lwip_netconn_do_join_leave_group(struct api_msg_msg *msg)
{ 
  if (ERR_IS_FATAL(msg->conn->last_err)) {
    msg->err = msg->conn->last_err;
  } else {
    if (msg->conn->pcb.tcp != NULL) {
      if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
#if LWIP_UDP
#if LWIP_IPV6 && LWIP_IPV6_MLD
        if (PCB_ISIPV6(msg->conn->pcb.udp)) {
          if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
            msg->err = mld6_joingroup(ipX_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)),
              ipX_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr)));
          } else {
            msg->err = mld6_leavegroup(ipX_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)),
              ipX_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr)));
          }
        }
        else
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
        {
#if LWIP_IGMP
          if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
            msg->err = igmp_joingroup(ipX_2_ip(API_EXPR_REF(msg->msg.jl.netif_addr)),
              ipX_2_ip(API_EXPR_REF(msg->msg.jl.multiaddr)));
          } else {
            msg->err = igmp_leavegroup(ipX_2_ip(API_EXPR_REF(msg->msg.jl.netif_addr)),
              ipX_2_ip(API_EXPR_REF(msg->msg.jl.multiaddr)));
          }
#endif /* LWIP_IGMP */
        }
#endif /* LWIP_UDP */
#if (LWIP_TCP || LWIP_RAW)
      } else {
        msg->err = ERR_VAL;
#endif /* (LWIP_TCP || LWIP_RAW) */
      }
    } else {
      msg->err = ERR_CONN;
    }
  }
  TCPIP_APIMSG_ACK(msg);
}
Exemple #12
0
bool MDNSResponder::begin(const char* domain){
  // Open the MDNS socket if it isn't already open.

  size_t n = strlen(domain);
  if (n > 255) { // Can only handle domains that are 255 chars in length.
    return false;
  }

  // Copy in domain characters as lowercase
  for (int i = 0; i < n; ++i)
    _hostName[i] = tolower(domain[i]);
  _hostName[n] = '\0';

  os_strcpy(_boardName, ARDUINO_BOARD);

  // Open the MDNS socket if it isn't already open.
  if (!_conn) {
    uint32_t ourIp = _getOurIp();
    if(ourIp == 0){
      return false;
    }

    ip_addr_t ifaddr;
    ifaddr.addr = ourIp;
    ip_addr_t multicast_addr;
    multicast_addr.addr = (uint32_t) MDNS_MULTICAST_ADDR;

    if (igmp_joingroup(&ifaddr, &multicast_addr)!= ERR_OK) {
      return false;
    }

    _conn = new UdpContext;
    _conn->ref();

    if (!_conn->listen(*IP_ADDR_ANY, MDNS_PORT)) {
      return false;
    }
    _conn->setMulticastInterface(ifaddr);
    _conn->setMulticastTTL(MDNS_MULTICAST_TTL);
    _conn->onRx(std::bind(&MDNSResponder::update, this));
    _conn->connect(multicast_addr, MDNS_PORT);
  }
  return true;
}
Exemple #13
0
uint8_t WiFiUDP::beginMulticast(IPAddress interfaceAddr, IPAddress multicast, uint16_t port)
{
    if (_ctx) {
        _ctx->unref();
        _ctx = 0;
    }

    if (igmp_joingroup(interfaceAddr, multicast)!= ERR_OK) {
        return 0;
    }

    _ctx = new UdpContext;
    _ctx->ref();
    ip_addr_t addr = IPADDR4_INIT(INADDR_ANY);
    if (!_ctx->listen(&addr, port)) {
        return 0;
    }

    return 1;
}
Exemple #14
0
bool LLMNRResponder::_restart() {
    if (_conn) {
        _conn->unref();
        _conn = 0;
    }

    ip_addr_t multicast_addr;
    multicast_addr.addr = (uint32_t)LLMNR_MULTICAST_ADDR;

    if (igmp_joingroup(IP_ADDR_ANY, &multicast_addr) != ERR_OK)
        return false;

    _conn = new UdpContext;
    _conn->ref();

    if (!_conn->listen(*IP_ADDR_ANY, LLMNR_PORT))
        return false;

    _conn->setMulticastTTL(LLMNR_MULTICAST_TTL);
    _conn->onRx(std::bind(&LLMNRResponder::_process_packet, this));
    _conn->connect(multicast_addr, LLMNR_PORT);
}
Exemple #15
0
STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) {
    (void)n_args; // always 4
    socket_obj_t *self = MP_OBJ_TO_PTR(args[0]);

    int opt = mp_obj_get_int(args[2]);

    switch (opt) {
        // level: SOL_SOCKET
        case SO_REUSEADDR: {
            int val = mp_obj_get_int(args[3]);
            int ret = lwip_setsockopt_r(self->fd, SOL_SOCKET, opt, &val, sizeof(int));
            if (ret != 0) {
                exception_from_errno(errno);
            }
            break;
        }

        // level: IPPROTO_IP
        case IP_ADD_MEMBERSHIP: {
            mp_buffer_info_t bufinfo;
            mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
            if (bufinfo.len != sizeof(ip4_addr_t) * 2) {
                mp_raise_ValueError(NULL);
            }

            // POSIX setsockopt has order: group addr, if addr, lwIP has it vice-versa
            err_t err = igmp_joingroup((const ip4_addr_t*)bufinfo.buf + 1, bufinfo.buf);
            if (err != ERR_OK) {
                mp_raise_OSError(-err);
            }
            break;
        }

        default:
            mp_printf(&mp_plat_print, "Warning: lwip.setsockopt() option not implemented\n");
    }

    return mp_const_none;
}
static int netdev_imsfioctl(FAR struct socket *psock, int cmd,
                            FAR struct ip_msfilter *imsf)
{
  FAR struct net_driver_s *dev;
  int ret = -EINVAL;

  nvdbg("cmd: %d\n", cmd);

  /* Execute the command */

  switch (cmd)
    {
      case SIOCSIPMSFILTER:  /* Set source filter content */
        {
          dev = netdev_imsfdev(imsf);
          if (dev)
            {
              if (imsf->imsf_fmode == MCAST_INCLUDE)
                {
                  ret = igmp_joingroup(dev, &imsf->imsf_multiaddr);
                }
              else
                {
                  DEBUGASSERT(imsf->imsf_fmode == MCAST_EXCLUDE);
                  ret = igmp_leavegroup(dev, &imsf->imsf_multiaddr);
                }
            }
        }
        break;

      case SIOCGIPMSFILTER:  /* Retrieve source filter addresses */
      default:
        ret = -ENOTTY;
        break;
    }

  return ret;
}
Exemple #17
0
uint8_t WiFiUDP::beginMulticast(IPAddress interfaceAddr, IPAddress multicast, uint16_t port)
{
    if (_ctx) {
        _ctx->unref();
        _ctx = 0;
    }

    ip_addr_t ifaddr;
    ifaddr.addr = (uint32_t) interfaceAddr;
    ip_addr_t multicast_addr;
    multicast_addr.addr = (uint32_t) multicast;

    if (igmp_joingroup(&ifaddr, &multicast_addr)!= ERR_OK) {
        return 0;
    }

    _ctx = new UdpContext;
    _ctx->ref();
    if (!_ctx->listen(*IP_ADDR_ANY, port)) {
        return 0;
    }

    return 1;
}
Exemple #18
0
bool MDNSResponder::_listen() {
	// Open the MDNS socket if it isn't already open.
	if (!_conn) {
		uint32_t ourIp = _getOurIp();
		if (ourIp == 0) {
#ifdef MDNS_DEBUG_RX
			Serial.println("MDNS: no IP address to listen on");
#endif
			return false;
		}
#ifdef MDNS_DEBUG_RX
		Serial.print("MDNS listening on IP: ");
		Serial.println(IPAddress(ourIp));
#endif
		ip_addr_t ifaddr;
		ifaddr.addr = ourIp;
		ip_addr_t multicast_addr;
		multicast_addr.addr = (uint32_t)MDNS_MULTICAST_ADDR;

		if (igmp_joingroup(&ifaddr, &multicast_addr) != ERR_OK) {
			return false;
		}

		_conn = new UdpContext;
		_conn->ref();

		if (!_conn->listen(*IP_ADDR_ANY, MDNS_PORT)) {
			return false;
		}
		_conn->setMulticastInterface(ifaddr);
		_conn->setMulticastTTL(MDNS_MULTICAST_TTL);
		_conn->onRx(std::bind(&MDNSResponder::update, this));
		_conn->connect(multicast_addr, MDNS_PORT);
	}
	return true;
}
Exemple #19
0
struct in_multi * 
in_addmulti(ip_addr *ap, struct net *netp, int addrtype)
{
   struct in_multi *inm = (struct in_multi *)NULL;
   int error;

   /* check for good addr. */
   if ((ap == (ip_addr *)NULL) || (*ap == 0))
      return ((struct in_multi *)NULL);  

   ENTER_CRIT_SECTION(netp);

   /* See if address already in list. */
#ifdef IP_V6
   if(addrtype == 6)
      inm = v6_lookup_mcast((ip6_addr*)ap, netp);
#endif
#ifdef IP_V4
   if(addrtype != 6)
      inm = lookup_mcast(*ap, netp);
#endif

   if (inm != (struct in_multi *)NULL) 
   {
      /* Found it; just increment the reference count. */
      ++inm->inm_refcount;
   }
   else
   {
      /*
       * New address; allocate a new multicast record
       * and link it into the interface's multicast list.
       */
      inm = (struct in_multi *)INM_ALLOC(sizeof(*inm));

      if (inm == (struct in_multi *)NULL) 
      {
         EXIT_CRIT_SECTION(netp);
         return ((struct in_multi *)NULL);
      }
#ifdef IP_V6
      if(addrtype == 6)
         IP6CPY(&inm->ip6addr, (struct in6_addr *)ap);
#endif
#ifdef IP_V4
      if(addrtype != 6)
         inm->inm_addr = *ap;
#endif
      inm->inm_netp = netp;
      inm->inm_refcount = 1;
      inm->inm_next = netp->mc_list;
      netp->mc_list = inm;

      /*
       * If net has a multicast address registration routine then ask
       * the network driver to update its multicast reception
       * filter appropriately for the new address.
       */
      if(netp->n_mcastlist)
         error = netp->n_mcastlist(inm);
      else
         error = 0;
#if defined (IGMP_V1) || defined (IGMP_V2)
      /*
       * Let IGMP know that we have joined a new IP multicast group.
       */
      if (inm->inm_addr) igmp_joingroup(inm);
#endif      
   }

   EXIT_CRIT_SECTION(netp);
   USE_ARG(error);

   return (inm);
}
Exemple #20
0
/**
  * @brief  Start all of the UDP stuff
  * @param  netPath network object
  * @param  ptpClock PTP clock object
  * @retval Boolean success
  */
Boolean netInit(NetPath *netPath, PtpClock *ptpClock)
{

    struct ip_addr interfaceAddr;

    struct in_addr netAddr;
    char addrStr[NET_ADDRESS_LENGTH];

    DBG("netInit\n");

    /* find a network interface */
    interfaceAddr.addr = findIface(ptpClock->rtOpts->ifaceName, ptpClock->portUuidField, netPath);

    if (!(interfaceAddr.addr))
    {

        goto fail01;
    }

    /* Open lwIP raw udp interfaces for the event port. */
    netPath->eventPcb = udp_new();

    if (NULL == netPath->eventPcb)
    {
        ERROR("netInit: Failed to open Event UDP PCB\n");
        goto fail02;
    }

    /* Open lwIP raw udp interfaces for the general port. */
    netPath->generalPcb = udp_new();

    if (NULL == netPath->generalPcb)
    {
        ERROR("netInit: Failed to open General UDP PCB\n");
        goto fail03;
    }

    /* Initialize the buffer queues. */
    netQInit(&netPath->eventQ);

    netQInit(&netPath->generalQ);

    /* Configure network (broadcast/unicast) addresses. */
    netPath->unicastAddr = 0; /* disable unicast */

    /*Init General multicast IP address*/
    memcpy(addrStr, DEFAULT_PTP_DOMAIN_ADDRESS, NET_ADDRESS_LENGTH);

    if (!inet_aton(addrStr, &netAddr))
    {
        ERROR("netInit: failed to encode multi-cast address: %s\n", addrStr);
        goto fail04;
    }

    netPath->multicastAddr = netAddr.s_addr;

    /* join multicast group (for receiving) on specified interface */
    igmp_joingroup(&interfaceAddr, (struct ip_addr *)&netAddr);


    /*Init Peer multicast IP address*/
    memcpy(addrStr, PEER_PTP_DOMAIN_ADDRESS, NET_ADDRESS_LENGTH);

    if (!inet_aton(addrStr, &netAddr))
    {
        ERROR("netInit: failed to encode peer multi-cast address: %s\n", addrStr);
        goto fail04;
    }

    netPath->peerMulticastAddr = netAddr.s_addr;

    /* join peer multicast group (for receiving) on specified interface */
    igmp_joingroup(&interfaceAddr, (struct ip_addr *)&netAddr);


    /* multicast send only on specified interface */
    netPath->eventPcb->multicast_ip.addr = netPath->multicastAddr;
    netPath->generalPcb->multicast_ip.addr = netPath->multicastAddr;

    /* Establish the appropriate UDP bindings/connections for events. */
    udp_recv(netPath->eventPcb, netRecvEventCallback, netPath);
    udp_bind(netPath->eventPcb, IP_ADDR_ANY, PTP_EVENT_PORT);
    /*  udp_connect(netPath->eventPcb, &netAddr, PTP_EVENT_PORT); */

    /* Establish the appropriate UDP bindings/connections for general. */
    udp_recv(netPath->generalPcb, netRecvGeneralCallback, netPath);
    udp_bind(netPath->generalPcb, IP_ADDR_ANY, PTP_GENERAL_PORT);
    /*  udp_connect(netPath->generalPcb, &netAddr, PTP_GENERAL_PORT); */

    /* Return a success code. */
    return TRUE;

    /*
    fail05:
        udp_disconnect(netPath->eventPcb);
        udp_disconnect(netPath->generalPcb);
    */
fail04:
    udp_remove(netPath->generalPcb);
fail03:
    udp_remove(netPath->eventPcb);
fail02:
fail01:
    return FALSE;
}
Exemple #21
0
static nsapi_error_t mbed_lwip_setsockopt(nsapi_stack_t *stack, nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen)
{
    struct lwip_socket *s = (struct lwip_socket *)handle;

    switch (optname) {
#if LWIP_TCP
        case NSAPI_KEEPALIVE:
            if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) {
                return NSAPI_ERROR_UNSUPPORTED;
            }

            s->conn->pcb.tcp->so_options |= SOF_KEEPALIVE;
            return 0;

        case NSAPI_KEEPIDLE:
            if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) {
                return NSAPI_ERROR_UNSUPPORTED;
            }

            s->conn->pcb.tcp->keep_idle = *(int*)optval;
            return 0;

        case NSAPI_KEEPINTVL:
            if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) {
                return NSAPI_ERROR_UNSUPPORTED;
            }

            s->conn->pcb.tcp->keep_intvl = *(int*)optval;
            return 0;
#endif

        case NSAPI_REUSEADDR:
            if (optlen != sizeof(int)) {
                return NSAPI_ERROR_UNSUPPORTED;
            }

            if (*(int *)optval) {
                ip_set_option(s->conn->pcb.ip, SOF_REUSEADDR);
            } else {
                ip_reset_option(s->conn->pcb.ip, SOF_REUSEADDR);
            }
            return 0;

        case NSAPI_ADD_MEMBERSHIP:
        case NSAPI_DROP_MEMBERSHIP: {
            if (optlen != sizeof(nsapi_ip_mreq_t)) {
                return NSAPI_ERROR_PARAMETER;
            }
            err_t igmp_err;
            const nsapi_ip_mreq_t *imr = optval;

            /* Check interface address type matches group, or is unspecified */
            if (imr->imr_interface.version != NSAPI_UNSPEC && imr->imr_interface.version != imr->imr_multiaddr.version) {
                return NSAPI_ERROR_PARAMETER;
            }

            ip_addr_t if_addr;
            ip_addr_t multi_addr;

            /* Convert the group address */
            if (!convert_mbed_addr_to_lwip(&multi_addr, &imr->imr_multiaddr)) {
                return NSAPI_ERROR_PARAMETER;
            }

            /* Convert the interface address, or make sure it's the correct sort of "any" */
            if (imr->imr_interface.version != NSAPI_UNSPEC) {
                if (!convert_mbed_addr_to_lwip(&if_addr, &imr->imr_interface)) {
                    return NSAPI_ERROR_PARAMETER;
                }
            } else {
                ip_addr_set_any(IP_IS_V6(&if_addr), &if_addr);
            }

            igmp_err = ERR_USE; // Maps to NSAPI_ERROR_UNSUPPORTED
            int32_t member_pair_index = find_multicast_member(s, imr);

            if (optname == NSAPI_ADD_MEMBERSHIP) {
                if (!s->multicast_memberships) {
                    // First multicast join on this socket, allocate space for membership tracking
                    s->multicast_memberships = malloc(sizeof(nsapi_ip_mreq_t) * LWIP_SOCKET_MAX_MEMBERSHIPS);
                    if (!s->multicast_memberships) {
                        return NSAPI_ERROR_NO_MEMORY;
                    }
                } else if(s->multicast_memberships_count == LWIP_SOCKET_MAX_MEMBERSHIPS) {
                    return NSAPI_ERROR_NO_MEMORY;
                }

                if (member_pair_index != -1) {
                    return NSAPI_ERROR_ADDRESS_IN_USE;
                }

                member_pair_index = next_free_multicast_member(s, 0);

                sys_prot_t prot = sys_arch_protect();

                #if LWIP_IPV4
                if (IP_IS_V4(&if_addr)) {
                    igmp_err = igmp_joingroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr));
                }
                #endif
                #if LWIP_IPV6
                if (IP_IS_V6(&if_addr)) {
                    igmp_err = mld6_joingroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr));
                }
                #endif

                sys_arch_unprotect(prot);

                if (igmp_err == ERR_OK) {
                    set_multicast_member_registry_bit(s, member_pair_index);
                    s->multicast_memberships[member_pair_index] = *imr;
                    s->multicast_memberships_count++;
                }
            } else {
                if (member_pair_index == -1) {
                    return NSAPI_ERROR_NO_ADDRESS;
                }

                clear_multicast_member_registry_bit(s, member_pair_index);
                s->multicast_memberships_count--;

                sys_prot_t prot = sys_arch_protect();

                #if LWIP_IPV4
                if (IP_IS_V4(&if_addr)) {
                    igmp_err = igmp_leavegroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr));
                }
                #endif
                #if LWIP_IPV6
                if (IP_IS_V6(&if_addr)) {
                    igmp_err = mld6_leavegroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr));
                }
                #endif

                sys_arch_unprotect(prot);
            }

            return mbed_lwip_err_remap(igmp_err);
         }

        default:
            return NSAPI_ERROR_UNSUPPORTED;
    }
}