/** * 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; }
/** * 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; }
/** * 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)); }
/** * 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; }
/** * 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)); }
/** * 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; }