Improve errors for invalid port numbers (#303)

Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
Erik Boasson 2019-11-04 19:56:53 +01:00 committed by eboasson
parent 2d8bf36f8e
commit 3da21315f2
17 changed files with 337 additions and 100 deletions

View file

@ -18,6 +18,7 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src"
ddsi_raweth.c
ddsi_ipaddr.c
ddsi_mcgroup.c
ddsi_portmapping.c
ddsi_serdata.c
ddsi_serdata_default.c
ddsi_sertopic.c
@ -69,6 +70,7 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi"
ddsi_ipaddr.h
ddsi_mcgroup.h
ddsi_plist_generic.h
ddsi_portmapping.h
ddsi_serdata.h
ddsi_sertopic.h
ddsi_serdata_default.h

View file

@ -0,0 +1,47 @@
/*
* Copyright(c) 2019 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef DDSI_PORTMAPPING_H
#define DDSI_PORTMAPPING_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#if defined (__cplusplus)
extern "C" {
#endif
enum ddsi_port {
DDSI_PORT_MULTI_DISC,
DDSI_PORT_MULTI_DATA,
DDSI_PORT_UNI_DISC,
DDSI_PORT_UNI_DATA
};
struct ddsi_portmapping {
uint32_t base;
uint32_t dg;
uint32_t pg;
uint32_t d0;
uint32_t d1;
uint32_t d2;
uint32_t d3;
};
bool ddsi_valid_portmapping (const struct ddsi_portmapping *map, uint32_t domain_id, int32_t participant_index, char *msg, size_t msgsize);
uint32_t ddsi_get_port (const struct ddsi_portmapping *map, enum ddsi_port which, uint32_t domain_id, int32_t participant_index);
#if defined (__cplusplus)
}
#endif
#endif /* DDSI_PORTMAPPING_H */

View file

@ -61,7 +61,7 @@ typedef void (*ddsi_tran_peer_locator_fn_t) (ddsi_tran_conn_t, nn_locator_t *);
typedef void (*ddsi_tran_disable_multiplexing_fn_t) (ddsi_tran_conn_t);
typedef ddsi_tran_conn_t (*ddsi_tran_accept_fn_t) (ddsi_tran_listener_t);
typedef ddsi_tran_conn_t (*ddsi_tran_create_conn_fn_t) (ddsi_tran_factory_t fact, uint32_t, ddsi_tran_qos_t);
typedef ddsi_tran_listener_t (*ddsi_tran_create_listener_fn_t) (ddsi_tran_factory_t fact, int port, ddsi_tran_qos_t);
typedef ddsi_tran_listener_t (*ddsi_tran_create_listener_fn_t) (ddsi_tran_factory_t fact, uint32_t port, ddsi_tran_qos_t);
typedef void (*ddsi_tran_release_conn_fn_t) (ddsi_tran_conn_t);
typedef void (*ddsi_tran_close_conn_fn_t) (ddsi_tran_conn_t);
typedef void (*ddsi_tran_unblock_listener_fn_t) (ddsi_tran_listener_t);
@ -70,6 +70,7 @@ typedef int (*ddsi_tran_join_mc_fn_t) (ddsi_tran_conn_t, const nn_locator_t *src
typedef int (*ddsi_tran_leave_mc_fn_t) (ddsi_tran_conn_t, const nn_locator_t *srcip, const nn_locator_t *mcip, const struct nn_interface *interf);
typedef int (*ddsi_is_mcaddr_fn_t) (ddsi_tran_factory_t tran, const nn_locator_t *loc);
typedef int (*ddsi_is_ssm_mcaddr_fn_t) (ddsi_tran_factory_t tran, const nn_locator_t *loc);
typedef int (*ddsi_is_valid_port_fn_t) (ddsi_tran_factory_t tran, uint32_t port);
enum ddsi_nearby_address_result {
DNAR_DISTANT,
@ -172,7 +173,8 @@ struct ddsi_tran_factory
ddsi_locator_from_string_fn_t m_locator_from_string_fn;
ddsi_locator_to_string_fn_t m_locator_to_string_fn;
ddsi_enumerate_interfaces_fn_t m_enumerate_interfaces_fn;
ddsi_is_valid_port_fn_t m_is_valid_port_fn;
/* Data */
int32_t m_kind;
@ -205,10 +207,17 @@ void ddsi_factory_conn_init (const struct ddsi_tran_factory *factory, ddsi_tran_
inline bool ddsi_factory_supports (const struct ddsi_tran_factory *factory, int32_t kind) {
return factory->m_supports_fn (factory, kind);
}
inline int ddsi_is_valid_port (ddsi_tran_factory_t factory, uint32_t port) {
return factory->m_is_valid_port_fn (factory, port);
}
inline ddsi_tran_conn_t ddsi_factory_create_conn (ddsi_tran_factory_t factory, uint32_t port, ddsi_tran_qos_t qos) {
if (!ddsi_is_valid_port (factory, port))
return NULL;
return factory->m_create_conn_fn (factory, port, qos);
}
inline ddsi_tran_listener_t ddsi_factory_create_listener (ddsi_tran_factory_t factory, int port, ddsi_tran_qos_t qos) {
inline ddsi_tran_listener_t ddsi_factory_create_listener (ddsi_tran_factory_t factory, uint32_t port, ddsi_tran_qos_t qos) {
if (!ddsi_is_valid_port (factory, port))
return NULL;
return factory->m_create_listener_fn (factory, port, qos);
}

View file

@ -16,6 +16,7 @@
#include "dds/ddsi/q_thread.h"
#include "dds/ddsi/q_xqos.h"
#include "dds/ddsi/q_feature_check.h"
#include "dds/ddsi/ddsi_portmapping.h"
#if defined (__cplusplus)
extern "C" {
@ -198,7 +199,6 @@ struct config
uint32_t domainId;
int participantIndex;
int maxAutoParticipantIndex;
uint32_t port_base;
char *spdpMulticastAddressString;
char *defaultMulticastAddressString;
char *assumeMulticastCapable;
@ -321,12 +321,7 @@ struct config
enum many_sockets_mode many_sockets_mode;
int assume_rti_has_pmd_endpoints;
uint32_t port_dg;
uint32_t port_pg;
uint32_t port_d0;
uint32_t port_d1;
uint32_t port_d2;
uint32_t port_d3;
struct ddsi_portmapping ports;
int monitor_port;

View file

@ -20,7 +20,7 @@ struct debug_monitor;
typedef int (*debug_monitor_cpf_t) (ddsi_tran_conn_t conn, const char *fmt, ...);
typedef int (*debug_monitor_plugin_t) (ddsi_tran_conn_t conn, debug_monitor_cpf_t cpf, void *arg);
struct debug_monitor *new_debug_monitor (struct q_globals *gv, int port);
struct debug_monitor *new_debug_monitor (struct q_globals *gv, int32_t port);
void add_debug_monitor_plugin (struct debug_monitor *dm, debug_monitor_plugin_t fn, void *arg);
void free_debug_monitor (struct debug_monitor *dm);

View file

@ -0,0 +1,126 @@
/*
* Copyright(c) 2019 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include "dds/ddsi/ddsi_portmapping.h"
#include "dds/ddsi/q_config.h"
static bool get_port_int (uint32_t *port, const struct ddsi_portmapping *map, enum ddsi_port which, uint32_t domain_id, int32_t participant_index, char *str_if_overflow, size_t strsize)
{
uint32_t off = UINT32_MAX, ppidx = UINT32_MAX;
assert (domain_id != UINT32_MAX);
assert (participant_index >= 0 || participant_index == PARTICIPANT_INDEX_NONE);
switch (which)
{
case DDSI_PORT_MULTI_DISC:
off = map->d0;
/* multicast port numbers are not affected by participant index */
ppidx = 0;
break;
case DDSI_PORT_MULTI_DATA:
off = map->d2;
/* multicast port numbers are not affected by participant index */
ppidx = 0;
break;
case DDSI_PORT_UNI_DISC:
if (participant_index == PARTICIPANT_INDEX_NONE)
{
/* participant index "none" means unicast ports get chosen by the transport */
*port = 0;
return true;
}
off = map->d1;
ppidx = (uint32_t) participant_index;
break;
case DDSI_PORT_UNI_DATA:
if (participant_index == PARTICIPANT_INDEX_NONE)
{
/* participant index "none" means unicast ports get chosen by the transport */
*port = 0;
return true;
}
off = map->d3;
ppidx = (uint32_t) participant_index;
break;
}
const uint64_t a = (uint64_t) map->dg * domain_id;
const uint64_t b = map->base + (uint64_t) map->pg * ppidx + off;
/* For the mapping to be valid, the port number must be in range of an unsigned 32 bit integer and must
not be 0 (as that is used for indicating a random port should be selected by the transport). The
transports may limit this further, but at least we won't have to worry about overflow anymore. */
*port = (uint32_t) (a + b);
if (a <= UINT32_MAX && b <= UINT32_MAX - a && *port > 0)
return true;
else
{
/* a, b < 2^64 ~ 18e18; 2^32 <= a + b < 2^65 ~ 36e18
2^32 ~ 4e9, so it can easily be split into (a+b) `div` 1e9 and (a+b) `mod` 1e9
and then the most-significant part is guaranteed to be > 0 */
const uint32_t billion = 1000000000;
const uint32_t y = (uint32_t) (a % billion) + (uint32_t) (b % billion);
const uint64_t x = (a / billion) + (b / billion) + (y / billion);
snprintf (str_if_overflow, strsize, "%"PRIu64"%09"PRIu32, x, y % billion);
return false;
}
}
static const char *portname (enum ddsi_port which)
{
const char *n = "?";
switch (which)
{
case DDSI_PORT_MULTI_DISC: n = "multicast discovery"; break;
case DDSI_PORT_MULTI_DATA: n = "multicast data"; break;
case DDSI_PORT_UNI_DISC: n = "unicast discovery"; break;
case DDSI_PORT_UNI_DATA: n = "unicast data"; break;
}
return n;
}
bool ddsi_valid_portmapping (const struct ddsi_portmapping *map, uint32_t domain_id, int32_t participant_index, char *msg, size_t msgsize)
{
DDSRT_STATIC_ASSERT (DDSI_PORT_MULTI_DISC >= 0 &&
DDSI_PORT_MULTI_DISC + 1 == DDSI_PORT_MULTI_DATA &&
DDSI_PORT_MULTI_DATA + 1 == DDSI_PORT_UNI_DISC &&
DDSI_PORT_UNI_DISC + 1 == DDSI_PORT_UNI_DATA &&
DDSI_PORT_UNI_DATA >= 0);
uint32_t dummy_port;
char str[32];
bool ok = true;
enum ddsi_port which = DDSI_PORT_MULTI_DISC;
int n = snprintf (msg, msgsize, "port number(s) of out range:");
size_t pos = (n >= 0 && (size_t) n <= msgsize) ? (size_t) n : msgsize;
do {
if (!get_port_int (&dummy_port, map, which, domain_id, participant_index, str, sizeof (str)))
{
n = snprintf (msg + pos, msgsize - pos, "%s %s %s", ok ? "" : ",", portname (which), str);
if (n >= 0 && (size_t) n <= msgsize - pos)
pos += (size_t) n;
ok = false;
}
} while (which++ != DDSI_PORT_UNI_DATA);
return ok;
}
uint32_t ddsi_get_port (const struct ddsi_portmapping *map, enum ddsi_port which, uint32_t domain_id, int32_t participant_index)
{
/* Not supposed to come here if port mapping is invalid */
uint32_t port;
char str[32];
bool ok = get_port_int (&port, map, which, domain_id, participant_index, str, sizeof (str));
assert (ok);
(void) ok;
return port;
}

View file

@ -356,6 +356,12 @@ static int ddsi_raweth_enumerate_interfaces (ddsi_tran_factory_t fact, enum tran
return ddsrt_getifaddrs(ifs, afs);
}
static int ddsi_raweth_is_valid_port (ddsi_tran_factory_t fact, uint32_t port)
{
(void) fact;
return (port >= 1 && port <= 65535);
}
int ddsi_raweth_init (struct q_globals *gv)
{
struct ddsi_tran_factory *fact = ddsrt_malloc (sizeof (*fact));
@ -377,6 +383,7 @@ int ddsi_raweth_init (struct q_globals *gv)
fact->m_locator_from_string_fn = ddsi_raweth_address_from_string;
fact->m_locator_to_string_fn = ddsi_raweth_to_string;
fact->m_enumerate_interfaces_fn = ddsi_raweth_enumerate_interfaces;
fact->m_is_valid_port_fn = ddsi_raweth_is_valid_port;
ddsi_factory_add (gv, fact);
GVLOG (DDS_LC_CONFIG, "raweth initialized\n");
return 0;

View file

@ -856,7 +856,7 @@ static ddsi_tcp_conn_t ddsi_tcp_new_conn (struct ddsi_tran_factory_tcp *fact, dd
return conn;
}
static ddsi_tran_listener_t ddsi_tcp_create_listener (ddsi_tran_factory_t fact, int port, ddsi_tran_qos_t qos)
static ddsi_tran_listener_t ddsi_tcp_create_listener (ddsi_tran_factory_t fact, uint32_t port, ddsi_tran_qos_t qos)
{
char buff[DDSI_LOCSTRLEN];
ddsrt_socket_t sock;
@ -1055,6 +1055,12 @@ static enum ddsi_nearby_address_result ddsi_tcp_is_nearby_address (ddsi_tran_fac
return ddsi_ipaddr_is_nearby_address(tran, loc, ownloc, ninterf, interf);
}
static int ddsi_tcp_is_valid_port (ddsi_tran_factory_t fact, uint32_t port)
{
(void) fact;
return (port <= 65535);
}
int ddsi_tcp_init (struct q_globals *gv)
{
struct ddsi_tran_factory_tcp *fact = ddsrt_malloc (sizeof (*fact));
@ -1079,6 +1085,7 @@ int ddsi_tcp_init (struct q_globals *gv)
fact->fact.m_is_mcaddr_fn = ddsi_tcp_is_mcaddr;
fact->fact.m_is_ssm_mcaddr_fn = ddsi_tcp_is_ssm_mcaddr;
fact->fact.m_is_nearby_address_fn = ddsi_tcp_is_nearby_address;
fact->fact.m_is_valid_port_fn = ddsi_tcp_is_valid_port;
ddsi_factory_add (gv, &fact->fact);
#if DDSRT_HAVE_IPV6

View file

@ -23,8 +23,9 @@
extern inline uint32_t ddsi_conn_type (ddsi_tran_conn_t conn);
extern inline uint32_t ddsi_conn_port (ddsi_tran_conn_t conn);
extern inline ddsi_tran_listener_t ddsi_factory_create_listener (ddsi_tran_factory_t factory, int port, ddsi_tran_qos_t qos);
extern inline ddsi_tran_listener_t ddsi_factory_create_listener (ddsi_tran_factory_t factory, uint32_t port, ddsi_tran_qos_t qos);
extern inline bool ddsi_factory_supports (const struct ddsi_tran_factory *factory, int32_t kind);
extern inline int ddsi_is_valid_port (ddsi_tran_factory_t factory, uint32_t port);
extern inline ddsrt_socket_t ddsi_conn_handle (ddsi_tran_conn_t conn);
extern inline int ddsi_conn_locator (ddsi_tran_conn_t conn, nn_locator_t * loc);
extern inline ddsrt_socket_t ddsi_tran_handle (ddsi_tran_base_t base);

View file

@ -466,6 +466,12 @@ static void ddsi_udp_fini (ddsi_tran_factory_t fact)
ddsrt_free (fact);
}
static int ddsi_udp_is_valid_port (ddsi_tran_factory_t fact, uint32_t port)
{
(void) fact;
return (port <= 65535);
}
int ddsi_udp_init (struct q_globals *gv)
{
struct ddsi_tran_factory *fact = ddsrt_malloc (sizeof (*fact));
@ -489,6 +495,7 @@ int ddsi_udp_init (struct q_globals *gv)
fact->m_locator_from_string_fn = ddsi_udp_address_from_string;
fact->m_locator_to_string_fn = ddsi_udp_locator_to_string;
fact->m_enumerate_interfaces_fn = ddsi_eth_enumerate_interfaces;
fact->m_is_valid_port_fn = ddsi_udp_is_valid_port;
#if DDSRT_HAVE_IPV6
if (gv->config.transport_selector == TRANS_UDP6)
{

View file

@ -103,25 +103,22 @@ static int add_addresses_to_addrset_1 (const struct q_globals *gv, struct addrse
if (!ddsi_is_mcaddr (gv, &loc))
{
assert (gv->config.maxAutoParticipantIndex >= 0);
for (uint32_t i = 0; i <= (uint32_t) gv->config.maxAutoParticipantIndex; i++)
for (int32_t i = 0; i <= gv->config.maxAutoParticipantIndex; i++)
{
uint32_t port = gv->config.port_base + gv->config.port_dg * gv->config.domainId + i * gv->config.port_pg + gv->config.port_d1;
loc.port = (unsigned) port;
loc.port = ddsi_get_port (&gv->config.ports, DDSI_PORT_UNI_DISC, gv->config.domainId, i);
if (i == 0)
GVLOG (DDS_LC_CONFIG, "%s", ddsi_locator_to_string(gv, buf, sizeof(buf), &loc));
else
GVLOG (DDS_LC_CONFIG, ", :%"PRIu32, port);
GVLOG (DDS_LC_CONFIG, ", :%"PRIu32, loc.port);
add_to_addrset (gv, as, &loc);
}
}
else
{
uint32_t port;
if (port_mode == -1)
port = gv->config.port_base + gv->config.port_dg * gv->config.domainId + gv->config.port_d0;
loc.port = ddsi_get_port (&gv->config.ports, DDSI_PORT_MULTI_DISC, gv->config.domainId, 0);
else
port = (uint32_t) port_mode;
loc.port = (unsigned) port;
loc.port = (uint32_t) port_mode;
GVLOG (DDS_LC_CONFIG, "%s", ddsi_locator_to_string(gv, buf, sizeof(buf), &loc));
add_to_addrset (gv, as, &loc);
}

View file

@ -166,7 +166,6 @@ DUPF(uint32);
DU(natint);
DU(natint_255);
DUPF(participantIndex);
DU(port);
DU(dyn_port);
DUPF(memsize);
DU(duration_inf);
@ -610,20 +609,20 @@ static const struct cfgelem sizing_cfgelems[] = {
};
static const struct cfgelem discovery_ports_cfgelems[] = {
{ LEAF("Base"), 1, "7400", ABSOFF(port_base), 0, uf_port, 0, pf_uint,
{ LEAF("Base"), 1, "7400", ABSOFF(ports.base), 0, uf_uint, 0, pf_uint,
BLURB("<p>This element specifies the base port number (refer to the DDSI 2.1 specification, section 9.6.1, constant PB).</p>") },
{ LEAF("DomainGain"), 1, "250", ABSOFF(port_dg), 0, uf_uint, 0, pf_uint,
{ LEAF("DomainGain"), 1, "250", ABSOFF(ports.dg), 0, uf_uint, 0, pf_uint,
BLURB("<p>This element specifies the domain gain, relating domain ids to sets of port numbers (refer to the DDSI 2.1 specification, section 9.6.1, constant DG).</p>") },
{ LEAF("ParticipantGain"), 1, "2", ABSOFF(port_pg), 0, uf_uint, 0, pf_uint,
{ LEAF("ParticipantGain"), 1, "2", ABSOFF(ports.pg), 0, uf_uint, 0, pf_uint,
BLURB("<p>This element specifies the participant gain, relating p0, articipant index to sets of port numbers (refer to the DDSI 2.1 specification, section 9.6.1, constant PG).</p>") },
{ LEAF("MulticastMetaOffset"), 1, "0", ABSOFF(port_d0), 0, uf_uint, 0, pf_uint,
{ LEAF("MulticastMetaOffset"), 1, "0", ABSOFF(ports.d0), 0, uf_uint, 0, pf_uint,
BLURB("<p>This element specifies the port number for multicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d0).</p>") },
{ LEAF("UnicastMetaOffset"), 1, "10", ABSOFF(port_d1), 0, uf_uint, 0, pf_uint,
{ LEAF("UnicastMetaOffset"), 1, "10", ABSOFF(ports.d1), 0, uf_uint, 0, pf_uint,
BLURB("<p>This element specifies the port number for unicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d1).</p>") },
{ LEAF("MulticastDataOffset"), 1, "1", ABSOFF(port_d2), 0, uf_uint, 0, pf_uint,
BLURB("<p>This element specifies the port number for multicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d2).</p>") },
{ LEAF("UnicastDataOffset"), 1, "11", ABSOFF(port_d3), 0, uf_uint, 0, pf_uint,
BLURB("<p>This element specifies the port number for unicast meta traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d3).</p>") },
{ LEAF("MulticastDataOffset"), 1, "1", ABSOFF(ports.d2), 0, uf_uint, 0, pf_uint,
BLURB("<p>This element specifies the port number for multicast data traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d2).</p>") },
{ LEAF("UnicastDataOffset"), 1, "11", ABSOFF(ports.d3), 0, uf_uint, 0, pf_uint,
BLURB("<p>This element specifies the port number for unicast data traffic (refer to the DDSI 2.1 specification, section 9.6.1, constant d3).</p>") },
END_MARKER
};
@ -1883,34 +1882,23 @@ static enum update_result uf_natint_255(struct cfgst *cfgst, void *parent, struc
static enum update_result uf_uint (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG (int first), const char *value)
{
unsigned * const elem = cfg_address (cfgst, parent, cfgelem);
uint32_t * const elem = cfg_address (cfgst, parent, cfgelem);
char *endptr;
unsigned long v = strtoul (value, &endptr, 10);
if (*value == 0 || *endptr != 0)
return cfg_error (cfgst, "%s: not a decimal integer", value);
if (v != (unsigned) v)
if (v != (uint32_t) v)
return cfg_error (cfgst, "%s: value out of range", value);
*elem = (unsigned) v;
*elem = (uint32_t) v;
return URES_SUCCESS;
}
static void pf_uint (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources)
{
unsigned const * const p = cfg_address (cfgst, parent, cfgelem);
uint32_t const * const p = cfg_address (cfgst, parent, cfgelem);
cfg_logelem (cfgst, sources, "%u", *p);
}
static enum update_result uf_port(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value)
{
int *elem = cfg_address (cfgst, parent, cfgelem);
if (uf_uint (cfgst, parent, cfgelem, first, value) != URES_SUCCESS)
return URES_ERROR;
else if (*elem < 1 || *elem > 65535)
return cfg_error (cfgst, "%s: out of range", value);
else
return URES_SUCCESS;
}
static enum update_result uf_duration_gen (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, const char *value, int64_t def_mult, int64_t min_ns, int64_t max_ns)
{
return uf_natint64_unit (cfgst, cfg_address (cfgst, parent, cfgelem), value, unittab_duration, def_mult, min_ns, max_ns);

View file

@ -346,10 +346,11 @@ static uint32_t debmon_main (void *vdm)
return 0;
}
struct debug_monitor *new_debug_monitor (struct q_globals *gv, int port)
struct debug_monitor *new_debug_monitor (struct q_globals *gv, int32_t port)
{
struct debug_monitor *dm;
/* negative port number means the feature is disabled */
if (gv->config.monitor_port < 0)
return NULL;
@ -362,7 +363,14 @@ struct debug_monitor *new_debug_monitor (struct q_globals *gv, int port)
dm->plugins = NULL;
if ((dm->tran_factory = ddsi_factory_find (gv, "tcp")) == NULL)
dm->tran_factory = ddsi_factory_find (gv, "tcp6");
dm->servsock = ddsi_factory_create_listener (dm->tran_factory, port, NULL);
if (!ddsi_is_valid_port (dm->tran_factory, (uint32_t) port))
{
GVERROR ("debug monitor port number %"PRId32" is invalid\n", port);
goto err_invalid_port;
}
dm->servsock = ddsi_factory_create_listener (dm->tran_factory, (uint32_t) port, NULL);
if (dm->servsock == NULL)
{
GVWARNING ("debmon: can't create socket\n");
@ -389,6 +397,7 @@ err_listen:
ddsrt_mutex_destroy(&dm->lock);
ddsi_listener_free(dm->servsock);
err_servsock:
err_invalid_port:
ddsrt_free(dm);
return NULL;
}

View file

@ -71,36 +71,30 @@ static void add_peer_addresses (const struct q_globals *gv, struct addrset *as,
}
}
static int make_uc_sockets (struct q_globals *gv, uint32_t * pdisc, uint32_t * pdata, int ppid)
enum make_uc_sockets_ret {
MUSRET_SUCCESS,
MUSRET_INVALID_PORTS,
MUSRET_NOSOCKET
};
static enum make_uc_sockets_ret make_uc_sockets (struct q_globals *gv, uint32_t * pdisc, uint32_t * pdata, int ppid)
{
if (gv->config.many_sockets_mode == MSM_NO_UNICAST)
{
assert (ppid == PARTICIPANT_INDEX_NONE);
*pdata = *pdisc = (uint32_t) (gv->config.port_base + gv->config.port_dg * gv->config.domainId);
*pdata = *pdisc = ddsi_get_port (&gv->config.ports, DDSI_PORT_MULTI_DISC, gv->config.domainId, ppid);
if (gv->config.allowMulticast)
{
/* FIXME: ugly hack - but we'll fix up after creating the multicast sockets */
return 0;
return MUSRET_SUCCESS;
}
}
if (ppid >= 0)
{
/* FIXME: verify port numbers are in range instead of truncating them like this */
uint32_t base = gv->config.port_base + (gv->config.port_dg * gv->config.domainId) + ((uint32_t) ppid * gv->config.port_pg);
*pdisc = base + gv->config.port_d1;
*pdata = base + gv->config.port_d3;
}
else if (ppid == PARTICIPANT_INDEX_NONE)
{
*pdata = 0;
*pdisc = 0;
}
else
{
DDS_FATAL ("make_uc_sockets: invalid participant index %d\n", ppid);
return -1;
}
*pdisc = ddsi_get_port (&gv->config.ports, DDSI_PORT_UNI_DISC, gv->config.domainId, ppid);
*pdata = ddsi_get_port (&gv->config.ports, DDSI_PORT_UNI_DATA, gv->config.domainId, ppid);
if (!ddsi_is_valid_port (gv->m_factory, *pdisc) || !ddsi_is_valid_port (gv->m_factory, *pdata))
return MUSRET_INVALID_PORTS;
gv->disc_conn_uc = ddsi_factory_create_conn (gv->m_factory, *pdisc, NULL);
if (gv->disc_conn_uc)
@ -123,13 +117,12 @@ static int make_uc_sockets (struct q_globals *gv, uint32_t * pdisc, uint32_t * p
else
{
/* Set unicast locators */
ddsi_conn_locator (gv->disc_conn_uc, &gv->loc_meta_uc);
ddsi_conn_locator (gv->data_conn_uc, &gv->loc_default_uc);
}
}
return gv->data_conn_uc ? 0 : -1;
return gv->data_conn_uc ? MUSRET_SUCCESS : MUSRET_NOSOCKET;
}
static void make_builtin_endpoint_xqos (dds_qos_t *q, const dds_qos_t *template)
@ -286,7 +279,7 @@ static int string_to_default_locator (const struct q_globals *gv, nn_locator_t *
static int set_spdp_address (struct q_globals *gv)
{
const uint32_t port = (uint32_t) (gv->config.port_base + gv->config.port_dg * gv->config.domainId + gv->config.port_d0);
const uint32_t port = ddsi_get_port (&gv->config.ports, DDSI_PORT_MULTI_DISC, gv->config.domainId, 0);
int rc = 0;
/* FIXME: FIXME: FIXME: */
gv->loc_spdp_mc.kind = NN_LOCATOR_KIND_INVALID;
@ -318,7 +311,7 @@ static int set_spdp_address (struct q_globals *gv)
static int set_default_mc_address (struct q_globals *gv)
{
const uint32_t port = (uint32_t) (gv->config.port_base + gv->config.port_dg * gv->config.domainId + gv->config.port_d2);
const uint32_t port = ddsi_get_port (&gv->config.ports, DDSI_PORT_MULTI_DATA, gv->config.domainId, 0);
int rc;
if (!gv->config.defaultMulticastAddressString)
gv->loc_default_mc = gv->loc_spdp_mc;
@ -459,6 +452,25 @@ int rtps_config_prep (struct q_globals *gv, struct cfgst *cfgst)
unsigned num_channel_threads = 0;
#endif
{
char message[256];
int32_t ppidx;
if (gv->config.participantIndex >= 0 || gv->config.participantIndex == PARTICIPANT_INDEX_NONE)
ppidx = gv->config.participantIndex;
else if (gv->config.participantIndex == PARTICIPANT_INDEX_AUTO)
ppidx = gv->config.maxAutoParticipantIndex;
else
{
assert (0);
ppidx = 0;
}
if (!ddsi_valid_portmapping (&gv->config.ports, gv->config.domainId, ppidx, message, sizeof (message)))
{
DDS_ILOG (DDS_LC_ERROR, gv->config.domainId, "Invalid port mapping: %s\n", message);
goto err_config_late_error;
}
}
/* retry_on_reject_duration default is dependent on late_ack_mode and responsiveness timeout, so fix up */
if (gv->config.whc_init_highwater_mark.isdefault)
gv->config.whc_init_highwater_mark.value = gv->config.whc_lowwater_mark;
@ -646,8 +658,13 @@ int create_multicast_sockets (struct q_globals *gv)
uint32_t port;
qos->m_multicast = 1;
/* FIXME: should check for overflow */
port = (uint32_t) (gv->config.port_base + gv->config.port_dg * gv->config.domainId + gv->config.port_d0);
port = ddsi_get_port (&gv->config.ports, DDSI_PORT_MULTI_DISC, gv->config.domainId, 0);
if (!ddsi_is_valid_port (gv->m_factory, port))
{
GVERROR ("Failed to create discovery multicast socket for domain %"PRIu32": resulting port number (%"PRIu32") is out of range\n",
gv->config.domainId, port);
goto err_disc;
}
if ((disc = ddsi_factory_create_conn (gv->m_factory, port, qos)) == NULL)
goto err_disc;
if (gv->config.many_sockets_mode == MSM_NO_UNICAST)
@ -657,16 +674,24 @@ int create_multicast_sockets (struct q_globals *gv)
}
else
{
port = (uint32_t) (gv->config.port_base + gv->config.port_dg * gv->config.domainId + gv->config.port_d2);
port = ddsi_get_port (&gv->config.ports, DDSI_PORT_MULTI_DATA, gv->config.domainId, 0);
if (!ddsi_is_valid_port (gv->m_factory, port))
{
GVERROR ("Failed to create data multicast socket for domain %"PRIu32": resulting port number (%"PRIu32") is out of range\n",
gv->config.domainId, port);
goto err_disc;
}
if ((data = ddsi_factory_create_conn (gv->m_factory, port, qos)) == NULL)
{
goto err_data;
}
}
ddsi_tran_free_qos (qos);
gv->disc_conn_mc = disc;
gv->data_conn_mc = data;
GVTRACE ("Multicast Ports: discovery %"PRIu32" data %"PRIu32" \n",
ddsi_conn_port (gv->disc_conn_mc), ddsi_conn_port (gv->data_conn_mc));
GVLOG (DDS_LC_CONFIG, "Multicast Ports: discovery %"PRIu32" data %"PRIu32" \n",
ddsi_conn_port (gv->disc_conn_mc), ddsi_conn_port (gv->data_conn_mc));
return 1;
err_data:
@ -980,7 +1005,7 @@ int rtps_init (struct q_globals *gv)
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
/* Convert address sets in partition mappings from string to address sets */
{
const uint32_t port = gv->config.port_base + gv->config.port_dg * gv->config.domainId + gv->config.port_d2;
const uint32_t port = ddsi_get_port (&gv->config.ports, DDSI_PORT_MULTI_DATA, gv->config.domainId, 0);
struct config_networkpartition_listelem *np;
for (np = gv->config.networkPartitions; np; np = np->next)
{
@ -1070,33 +1095,44 @@ int rtps_init (struct q_globals *gv)
{
if (gv->config.participantIndex >= 0 || gv->config.participantIndex == PARTICIPANT_INDEX_NONE)
{
if (make_uc_sockets (gv, &port_disc_uc, &port_data_uc, gv->config.participantIndex) < 0)
enum make_uc_sockets_ret musret = make_uc_sockets (gv, &port_disc_uc, &port_data_uc, gv->config.participantIndex);
switch (musret)
{
GVERROR ("rtps_init: failed to create unicast sockets for domain %"PRId32" participant %d\n", gv->config.domainId, gv->config.participantIndex);
goto err_unicast_sockets;
case MUSRET_SUCCESS:
break;
case MUSRET_INVALID_PORTS:
GVERROR ("Failed to create unicast sockets for domain %"PRIu32" participant index %d: resulting port numbers (%"PRIu32", %"PRIu32") are out of range\n",
gv->config.domainId, gv->config.participantIndex, port_disc_uc, port_data_uc);
goto err_unicast_sockets;
case MUSRET_NOSOCKET:
GVERROR ("rtps_init: failed to create unicast sockets for domain %"PRId32" participant index %d (ports %"PRIu32", %"PRIu32")\n", gv->config.domainId, gv->config.participantIndex, port_disc_uc, port_data_uc);
goto err_unicast_sockets;
}
}
else if (gv->config.participantIndex == PARTICIPANT_INDEX_AUTO)
{
/* try to find a free one, and update gv->config.participantIndex */
enum make_uc_sockets_ret musret = MUSRET_NOSOCKET;
int ppid;
GVLOG (DDS_LC_CONFIG, "rtps_init: trying to find a free participant index\n");
for (ppid = 0; ppid <= gv->config.maxAutoParticipantIndex; ppid++)
for (ppid = 0; ppid <= gv->config.maxAutoParticipantIndex && musret == MUSRET_NOSOCKET; ppid++)
{
int r = make_uc_sockets (gv, &port_disc_uc, &port_data_uc, ppid);
if (r == 0) /* Success! */
break;
else if (r == -1) /* Try next one */
continue;
else /* Oops! */
musret = make_uc_sockets (gv, &port_disc_uc, &port_data_uc, ppid);
switch (musret)
{
GVERROR ("rtps_init: failed to create unicast sockets for domain %"PRId32" participant %d\n", gv->config.domainId, ppid);
goto err_unicast_sockets;
case MUSRET_SUCCESS:
break;
case MUSRET_INVALID_PORTS:
GVERROR ("Failed to create unicast sockets for domain %"PRIu32" participant index %d: resulting port numbers (%"PRIu32", %"PRIu32") are out of range\n",
gv->config.domainId, ppid, port_disc_uc, port_data_uc);
goto err_unicast_sockets;
case MUSRET_NOSOCKET: /* Try next one */
break;
}
}
if (ppid > gv->config.maxAutoParticipantIndex)
{
GVERROR ("rtps_init: failed to find a free participant index for domain %"PRId32"\n", gv->config.domainId);
GVERROR ("Failed to find a free participant index for domain %"PRIu32"\n", gv->config.domainId);
goto err_unicast_sockets;
}
gv->config.participantIndex = ppid;
@ -1107,7 +1143,7 @@ int rtps_init (struct q_globals *gv)
}
GVLOG (DDS_LC_CONFIG, "rtps_init: uc ports: disc %"PRIu32" data %"PRIu32"\n", port_disc_uc, port_data_uc);
}
GVLOG (DDS_LC_CONFIG, "rtps_init: domainid %"PRId32" participantid %d\n", gv->config.domainId, gv->config.participantIndex);
GVLOG (DDS_LC_CONFIG, "rtps_init: domainid %"PRIu32" participantid %d\n", gv->config.domainId, gv->config.participantIndex);
if (gv->config.pcap_file && *gv->config.pcap_file)
{
@ -1157,9 +1193,15 @@ int rtps_init (struct q_globals *gv)
/* Must have a data_conn_uc/tev_conn/transmit_conn */
gv->data_conn_uc = ddsi_factory_create_conn (gv->m_factory, 0, NULL);
if (gv->config.tcp_port != -1)
if (gv->config.tcp_port == -1)
; /* nop */
else if (!ddsi_is_valid_port (gv->m_factory, (uint32_t) gv->config.tcp_port))
{
gv->listener = ddsi_factory_create_listener (gv->m_factory, gv->config.tcp_port, NULL);
GVERROR ("Listener port %d is out of range for transport %s\n", gv->config.tcp_port, gv->m_factory->m_typename);
}
else
{
gv->listener = ddsi_factory_create_listener (gv->m_factory, (uint32_t) gv->config.tcp_port, NULL);
if (gv->listener == NULL || ddsi_listener_listen (gv->listener) != 0)
{
GVERROR ("Failed to create %s listener\n", gv->m_factory->m_typename);