/**
 * Join a socket into a multicast group
 * @param sock filedescriptor of socket
 * @param multicast multicast-group to join
 * @param os_if pointer to outgoing interface data for multicast
 * @param log_src logging source for error messages
 * @return -1 if an error happened, 0 otherwise
 */
int
os_fd_generic_join_mcast_recv(struct os_fd *sock,
    const struct netaddr *multicast,
    const struct os_interface *os_if,
    enum oonf_log_source log_src __attribute__((unused))) {
  struct netaddr_str buf1, buf2;
  struct ip_mreq   v4_mreq;
  struct ipv6_mreq v6_mreq;
  const char *ifname = "*";

  if (os_if) {
    ifname = os_if->name;
  }

  if (netaddr_get_address_family(multicast) == AF_INET) {
    const struct netaddr *src;

    src = os_if == NULL ? &NETADDR_IPV4_ANY : os_if->if_v4;

    OONF_DEBUG(log_src,
        "Socket on interface %s joining receiving multicast %s (src %s)\n",
        ifname, netaddr_to_string(&buf2, multicast),
        netaddr_to_string(&buf1, src));

    netaddr_to_binary(&v4_mreq.imr_multiaddr, multicast, 4);
    netaddr_to_binary(&v4_mreq.imr_interface, src, 4);

    if (setsockopt(sock->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
        &v4_mreq, sizeof(v4_mreq)) < 0) {
      OONF_WARN(log_src, "Cannot join multicast group %s (src %s) on interface %s: %s (%d)\n",
          netaddr_to_string(&buf1, multicast),
          netaddr_to_string(&buf2, src),
          ifname, strerror(errno), errno);
      return -1;
    }
  }
  else {
    int if_index;

    if_index = os_if == NULL ? 0 : os_if->index;

    OONF_DEBUG(log_src,
        "Socket on interface %s joining receiving multicast %s (if %d)\n",
        ifname, netaddr_to_string(&buf2, multicast), if_index);

    netaddr_to_binary(&v6_mreq.ipv6mr_multiaddr, multicast, 16);
    v6_mreq.ipv6mr_interface = if_index;

    if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
        &v6_mreq, sizeof(v6_mreq)) < 0) {
      OONF_WARN(log_src, "Cannot join multicast group %s on interface %s: %s (%d)\n",
          netaddr_to_string(&buf1, multicast),
          ifname,
          strerror(errno), errno);
      return -1;
    }
  }
  return 0;
}
Beispiel #2
0
/**
 * Write a DLEP IPv4/IPv6 address/subnet TLV
 * @param writer dlep writer
 * @param ip IPv4 address
 * @param add true if address should be added, false to remove it
 */
int
dlep_writer_add_ip_tlv(struct dlep_writer *writer, const struct netaddr *ip, bool add) {
  uint8_t value[18];

  value[0] = add ? DLEP_IP_ADD : DLEP_IP_REMOVE;
  netaddr_to_binary(&value[1], ip, 16);

  switch (netaddr_get_address_family(ip)) {
    case AF_INET:
      value[5] = netaddr_get_prefix_length(ip);
      if (value[5] != 32) {
        dlep_writer_add_tlv(writer, DLEP_IPV4_SUBNET_TLV, value, 6);
      }
      else {
        dlep_writer_add_tlv(writer, DLEP_IPV4_ADDRESS_TLV, value, 5);
      }
      break;
    case AF_INET6:
      value[17] = netaddr_get_prefix_length(ip);
      if (value[17] != 128) {
        dlep_writer_add_tlv(writer, DLEP_IPV6_SUBNET_TLV, value, 18);
      }
      else {
        dlep_writer_add_tlv(writer, DLEP_IPV6_ADDRESS_TLV, value, 17);
      }
      break;
    default:
      return -1;
  }
  return 0;
}
Beispiel #3
0
/**
 * Write a DLEP IPv6 address TLV
 * @param writer dlep writer
 * @param ipv6 IPv6 address
 * @param add true if address should be added, false to remove it
 */
void
dlep_writer_add_ipv6_tlv(struct dlep_writer *writer,
    const struct netaddr *ipv6, bool add) {
  uint8_t value[17];

  if (netaddr_get_address_family(ipv6) != AF_INET6) {
    return;
  }

  value[0] = add ? DLEP_IP_ADD : DLEP_IP_REMOVE;
  netaddr_to_binary(&value[1], ipv6, 16);

  dlep_writer_add_tlv(writer,
      DLEP_IPV6_ADDRESS_TLV, value, sizeof(value));
}
Beispiel #4
0
/**
 * Write a DLEP MAC address TLV
 * @param writer dlep writer
 * @param mac_lid mac address/LID
 * @return -1 if address was wrong type, 0 otherwise
 */
int
dlep_writer_add_mac_tlv(struct dlep_writer *writer, const struct oonf_layer2_neigh_key *mac_lid) {
  uint8_t value[8];

  switch (netaddr_get_address_family(&mac_lid->addr)) {
    case AF_MAC48:
    case AF_EUI64:
      break;
    default:
      return -1;
  }

  netaddr_to_binary(value, &mac_lid->addr, 8);

  dlep_writer_add_tlv(writer, DLEP_MAC_ADDRESS_TLV, value, netaddr_get_binlength(&mac_lid->addr));
  return 0;
}
Beispiel #5
0
/**
 * Write a DLEP IPv6 conpoint TLV
 * @param writer dlep writer
 * @param addr IPv6 address
 * @param port port number
 * @param tls TLS capability flag
 */
void
dlep_writer_add_ipv6_conpoint_tlv(struct dlep_writer *writer, const struct netaddr *addr, uint16_t port, bool tls) {
  uint8_t value[19];

  if (netaddr_get_address_family(addr) != AF_INET6) {
    return;
  }

  /* convert port to network byte order */
  port = htons(port);

  /* copy data into value buffer */
  value[0] = tls ? DLEP_CONNECTION_TLS : DLEP_CONNECTION_PLAIN;
  netaddr_to_binary(&value[1], addr, sizeof(value));
  memcpy(&value[17], &port, sizeof(port));

  dlep_writer_add_tlv(writer, DLEP_IPV6_CONPOINT_TLV, &value, sizeof(value));
}
Beispiel #6
0
/**
 * Write a DLEP MAC address TLV
 * @param writer dlep writer
 * @param mac mac address
 * @return -1 if address was wrong type, 0 otherwise
 */
int
dlep_writer_add_mac_tlv(struct dlep_writer *writer,
    const struct netaddr *mac) {
  uint8_t value[8];

  switch (netaddr_get_address_family(mac)) {
    case AF_MAC48:
    case AF_EUI64:
      break;
    default:
      return -1;
  }

  netaddr_to_binary(value, mac, 8);

  dlep_writer_add_tlv(writer,
      DLEP_MAC_ADDRESS_TLV, value, netaddr_get_binlength(mac));
  return 0;
}