Ticket refs#526: TR-181: Device.IP.Interface. object

This commit is contained in:
Amin Ben Ramdhane 2019-04-26 12:02:06 +01:00
parent 9578f538c2
commit a69b9cdb51
13 changed files with 3233 additions and 168 deletions

View file

@ -264,3 +264,26 @@ icwmp_udpechoserverd_LDFLAGS = \
icwmp_udpechoserverd_LDADD = \
$(AM_LIBS) \
$(LIBUCI_LIBS)
bin_PROGRAMS += icwmp_twampd
icwmp_twampd_SOURCES = \
../twamp/twamp.c \
../twamp/twamp.h \
../twamp/twamptimestamp.c \
../twamp/twampuci.c \
../twamp/twampuci.h \
../twamp/twamplog.c \
../twamp/twamplog.h
icwmp_twampd_CFLAGS = \
$(AM_CFLAGS) \
$(LIBUCI_CFLAGS)
icwmp_twampd_LDFLAGS = \
$(AM_LDFLAGS) \
$(LIBUCI_LDFLAGS)
icwmp_twampd_LDADD = \
$(AM_LIBS) \
$(LIBUCI_LIBS)

4
config/cwmp_twamp Normal file
View file

@ -0,0 +1,4 @@
config cwmp 'twamp'
option id '1'
#Log levels: Critical=0, Warning=1, Notice=2, Info=3, Debug=4
option log_level '3'

View file

@ -61,6 +61,7 @@
#include "users.h"
#include "dsl.h"
#include "dhcpv6.h"
/* *** CWMP *** */
DMOBJ tEntry098Obj[] = {
/* OBJ, permission, addobj, delobj, browseinstobj, finform, NOTIFICATION, nextobj, leaf, linker*/
@ -128,7 +129,7 @@ DMOBJ tRoot_181_Obj[] = {
{CUSTOM_PREFIX"WiFiLife", &DMREAD, NULL, NULL, NULL, NULL, NULL, &DMNONE, X_IOPSYS_EU_WiFiLifeObj, X_IOPSYS_EU_WiFiLifeParams, NULL},
{"Bridging",&DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tBridgingObj, NULL, NULL},
{"WiFi",&DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tWifiObj, tWifiParams, NULL},
{"IP",&DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tIPObj, NULL, NULL},
{"IP",&DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tIPObj, tIPParams, NULL},
{"Ethernet", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tEthernetObj, NULL, NULL},
{"DSL",&DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDSLObj, tDSLParams, NULL},
{"ATM",&DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tAtmObj, NULL, NULL},

File diff suppressed because it is too large Load diff

View file

@ -17,14 +17,34 @@ struct ip_args
{
struct uci_section *ip_sec;
char *ip_4address;
};
struct ipv6_args
{
struct uci_section *ip_sec;
char *ip_6address;
char *ip_6mask;
char *ip_6preferred;
char *ip_6valid;
};
struct ipv6prefix_args
{
struct uci_section *ip_sec;
char *ip_6prefixaddress;
char *ip_6prefixmask;
char *ip_6prefixpreferred;
char *ip_6prefixvalid;
};
extern DMOBJ tIPObj[];
extern DMLEAF tIPParams[];
extern DMOBJ tInterfaceObj[];
extern DMLEAF tIPv4Params[];
extern DMLEAF tIPv6Params[];
extern DMLEAF tIPv6PrefixParams[];
extern DMLEAF tIPInterfaceStatsParams[];
extern DMLEAF tIPInterfaceTWAMPReflectorParams[];
extern DMLEAF tIPintParams[];
extern DMOBJ tDiagnosticObj[];
extern DMLEAF tIPDiagnosticsParams[];
@ -44,11 +64,15 @@ extern DMLEAF tIPDiagnosticsServerSelectionDiagnosticsParams[];
unsigned char get_ipv4_finform(char *refparam, struct dmctx *dmctx, void *data, char *instance);
unsigned char get_ipv6_finform(char *refparam, struct dmctx *dmctx, void *data, char *instance);
int get_linker_ip_interface(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker);
int get_linker_ipv6_prefix(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker);
int browseIPIfaceInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
int browseIfaceIPv4Inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
int browseIfaceIPv6Inst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
int browseIfaceIPv6PrefixInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
int browseIPInterfaceTWAMPReflectorInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
int browseIPDiagnosticsTraceRouteRouteHopsInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
int browseIPDiagnosticsDownloadDiagnosticsPerConnectionResultInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
int browseIPDiagnosticsUploadDiagnosticsPerConnectionResultInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
@ -59,39 +83,112 @@ int add_ipv4(char *refparam, struct dmctx *ctx, void *data, char **instancepara)
int delete_ipv4(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
int add_ipv6(char *refparam, struct dmctx *ctx, void *data, char **instancepara);
int delete_ipv6(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
int add_ipv6_prefix(char *refparam, struct dmctx *ctx, void *data, char **instance);
int delete_ipv6_prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
int addObjIPInterfaceTWAMPReflector(char *refparam, struct dmctx *ctx, void *data, char **instance);
int delObjIPInterfaceTWAMPReflector(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
int get_diag_enable_true(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_diag_enable_false(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_interface_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_interface_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_interface_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_int_lower_layer(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IP_IPv4Capable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IP_IPv4Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IP_IPv4Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IP_IPv4Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IP_IPv6Capable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IP_IPv6Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IP_IPv6Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IP_IPv6Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IP_ULAPrefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IP_ULAPrefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IP_InterfaceNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ipv4_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_ipv4_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_firewall_enabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_firewall_enabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_ipv4_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_ipv4_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_ipv4_netmask(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_ipv4_netmask(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_ipv4_addressing_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ipv6_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ipv6_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ipv6_addressing_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_diagnostics_state(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_protocolversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_repetition_number(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_block_size(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_success_count(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_failure_count(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_average_response_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_min_response_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_max_response_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_AverageResponseTimeDetailed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_MinimumResponseTimeDetailed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_MaximumResponseTimeDetailed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_ipv4_addressing_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterface_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterface_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterface_IPv4Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterface_IPv4Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterface_IPv6Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterface_IPv6Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterface_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IPInterface_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterface_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterface_Name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IPInterface_LastChange(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IPInterface_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterface_LowerLayers(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterface_Router(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterface_Router(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterface_Reset(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterface_Reset(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterface_MaxMTUSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterface_MaxMTUSize(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterface_Type(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IPInterface_Loopback(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterface_Loopback(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterface_IPv4AddressNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IPInterface_IPv6AddressNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IPInterface_IPv6PrefixNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IPInterface_TWAMPReflectorNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IPInterfaceIPv6Address_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceIPv6Address_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterfaceIPv6Address_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IPInterfaceIPv6Address_IPAddressStatus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IPInterfaceIPv6Address_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceIPv6Address_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterfaceIPv6Address_IPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceIPv6Address_IPAddress(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterfaceIPv6Address_Origin(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IPInterfaceIPv6Address_Prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceIPv6Address_Prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterfaceIPv6Address_PreferredLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceIPv6Address_PreferredLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterfaceIPv6Address_ValidLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceIPv6Address_ValidLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterfaceIPv6Prefix_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceIPv6Prefix_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterfaceIPv6Prefix_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IPInterfaceIPv6Prefix_PrefixStatus(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IPInterfaceIPv6Prefix_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceIPv6Prefix_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterfaceIPv6Prefix_Prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceIPv6Prefix_Prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterfaceIPv6Prefix_Origin(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IPInterfaceIPv6Prefix_StaticType(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceIPv6Prefix_StaticType(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterfaceIPv6Prefix_ParentPrefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceIPv6Prefix_ParentPrefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterfaceIPv6Prefix_ChildPrefixBits(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceIPv6Prefix_ChildPrefixBits(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterfaceIPv6Prefix_PreferredLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceIPv6Prefix_PreferredLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterfaceIPv6Prefix_ValidLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceIPv6Prefix_ValidLifetime(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterfaceTWAMPReflector_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceTWAMPReflector_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterfaceTWAMPReflector_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IPInterfaceTWAMPReflector_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceTWAMPReflector_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterfaceTWAMPReflector_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceTWAMPReflector_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterfaceTWAMPReflector_MaximumTTL(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceTWAMPReflector_MaximumTTL(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterfaceTWAMPReflector_IPAllowedList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceTWAMPReflector_IPAllowedList(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_IPInterfaceTWAMPReflector_PortAllowedList(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPInterfaceTWAMPReflector_PortAllowedList(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_ip_interface_statistics_tx_bytes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_interface_statistics_rx_bytes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_interface_statistics_tx_packets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
@ -100,27 +197,32 @@ int get_ip_interface_statistics_tx_errors(char *refparam, struct dmctx *ctx, voi
int get_ip_interface_statistics_rx_errors(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_interface_statistics_tx_discardpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_interface_statistics_rx_discardpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_interface_statistics_rx_multicastpackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_ip_int_lower_layer(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int set_ip_int_lower_layer(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int set_ipv4_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int set_firewall_enabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int set_ipv4_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int set_ipv4_netmask(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int set_ipv4_addressing_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int set_ipv6_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int set_ipv6_address(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int set_ipv6_addressing_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_ip_ping_diagnostics_state(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_ip_ping_diagnostics_state(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_ip_ping_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_ip_ping_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_ip_ping_protocolversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_ip_ping_protocolversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_ip_ping_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_ip_ping_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_ip_ping_repetition_number(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_ip_ping_repetition_number(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_ip_ping_timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_ip_ping_timeout(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_ip_ping_block_size(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_ip_ping_block_size(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_ip_ping_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_ip_ping_DSCP(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int set_ipv6_addressing_type(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int set_ip_interface_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
int get_ip_ping_success_count(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_failure_count(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_average_response_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_min_response_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_max_response_time(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_AverageResponseTimeDetailed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_MinimumResponseTimeDetailed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_ip_ping_MaximumResponseTimeDetailed(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IPDiagnosticsTraceRoute_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int set_IPDiagnosticsTraceRoute_DiagnosticsState(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action);
@ -292,4 +394,5 @@ int get_IPDiagnosticsServerSelectionDiagnostics_FastestHost(char *refparam, stru
int get_IPDiagnosticsServerSelectionDiagnostics_MinimumResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IPDiagnosticsServerSelectionDiagnostics_AverageResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
int get_IPDiagnosticsServerSelectionDiagnostics_MaximumResponseTime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
#endif

56
init/icwmp_twampd Normal file
View file

@ -0,0 +1,56 @@
#!/bin/sh /etc/rc.common
#TWAMP Reflector software
# Copyright (C) 2019 iopsys Software Solutions AB
#Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
START=99
STOP=10
USE_PROCD=1
PROG="/usr/sbin/icwmp_twampd"
start_service() {
local id=`uci -q get cwmp_twamp.twamp.id`
local connection=`uci show cwmp_twamp | grep "cwmp_twamp.@twamp_refector.*id=\'$id\'" | cut -d "." -f 2`
local enable=`uci -q get cwmp_twamp.$connection.enable`
local interface=`uci -q get cwmp_twamp.$connection.interface`
local port=`uci -q get cwmp_twamp.$connection.port`
local port_list=`uci -q get cwmp_twamp.$connection.port_list`
port_list=`echo $port_list | tr "," " "`
if [ "$enable" = "1" ]; then
if [ $interface = "wan" ]; then
for str in $port_list; do
if [ "${str/-}" != "$str" ] ; then
str=`echo $str | tr "-" ":"`
fi
iptables -I zone_wan_input -p udp --dport "$str" -j ACCEPT -m comment --comment "Open UDP allowed port"
iptables -I zone_wan_input -p tcp --dport "$port" -j ACCEPT -m comment --comment "Open TCP allowed port"
done
fi
procd_open_instance
procd_set_param command "$PROG"
procd_set_param respawn "3" "7" "0"
procd_close_instance
else
if [ $interface = "wan" ]; then
if [ "${str/-}" != "$str" ] ; then
str=`echo $str | tr "-" ":"`
fi
iptables -I zone_wan_input -p udp --dport "$str" -j REJECT -m comment --comment "Close UDP allowed port"
iptables -I zone_wan_input -p tcp --dport "$port" -j REJECT -m comment --comment "Close TCP allowed port"
fi
fi
}
boot() {
start
}
reload_service() {
stop
start
}
service_triggers() {
procd_add_reload_trigger cwmp_twamp
}

857
twamp/twamp.c Normal file
View file

@ -0,0 +1,857 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2019 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
* Name: Emma Mirică
* Project: TWAMP Protocol
* Class: OSS
* Email: emma.mirica@cti.pub.ro
* Contributions: stephanDB
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <time.h>
#include "twamp.h"
#include "twamplog.h"
#include "twampuci.h"
struct twamp_config cur_twamp_conf = {0};
TWAMPTimestamp ZeroT = { 0, 0 };
struct active_session {
int socket;
RequestSession req;
uint16_t server_oct;
uint32_t sid_addr;
TWAMPTimestamp sid_time;
uint32_t sid_rand;
uint32_t seq_nb;
uint32_t snd_nb;
uint32_t fw_msg;
uint32_t fw_lst_msg;
};
struct client_info {
ClientStatus status;
int socket;
struct sockaddr_in addr;
struct sockaddr_in6 addr6;
int mode;
int sess_no;
struct timeval shutdown_time;
struct active_session sessions[MAX_SESSIONS_PER_CLIENT];
};
static int fd_max = 0;
static enum Mode authmode = kModeUnauthenticated;
static int used_sockets = 0;
static fd_set read_fds;
static int socket_family = AF_INET;
static int check_ipv4_address(char *ip, char *maskstr, char *address)
{
struct sockaddr_in sa = {0};
unsigned long netaddress, maxaddress;
unsigned long mask = ~((1 << (32 - atoi(maskstr))) - 1);
inet_pton(AF_INET, address, &(sa.sin_addr));
netaddress = (ntohl(sa.sin_addr.s_addr) & mask);
sa.sin_addr.s_addr = 0;
inet_pton(AF_INET, ip, &(sa.sin_addr));
maxaddress = (ntohl(sa.sin_addr.s_addr) & mask);
if (maxaddress == netaddress)
return 1;
return 0;
}
static char *check_ipv6_address_active(char *ip)
{
unsigned char buf[sizeof(struct in6_addr)];
char str[INET6_ADDRSTRLEN], *res;
int s;
s = inet_pton(AF_INET6, ip, buf);
if (s <= 0) {
if (s == 0)
twamp_log(SCRIT, "Not in presentation format");
else
twamp_log(SCRIT, "inet_pton");
return "";
}
if (inet_ntop(AF_INET6, buf, str, INET6_ADDRSTRLEN) == NULL) {
twamp_log(SCRIT, "inet_ntop");
return "";
}
res = strdup(str);
return res;
}
static int check_ipv6_address(char *ip, char *maskstr, char *address)
{
struct sockaddr_in6 sa = {0};
unsigned long netaddress, maxaddress;
unsigned long mask = ~((1 << (128 - atoi(maskstr))) - 1);
inet_pton(AF_INET6, address, &(sa.sin6_addr));
netaddress = (ntohl(sa.sin6_addr.s6_addr) & mask);
inet_pton(AF_INET6, ip, &(sa.sin6_addr));
maxaddress = (ntohl(sa.sin6_addr.s6_addr) & mask);
if (maxaddress == netaddress)
return 1;
return 0;
}
static int check_ip_address_allowed(char *address)
{
char *pch, *spch, *ip, *mask, *str, *addr;
for (pch = strtok_r(cur_twamp_conf.ip_list, ",", &spch); pch != NULL; pch = strtok_r(NULL, ",", &spch))
{
if(strstr(pch, ".")) {
if(strstr(pch, "/")) {
ip = strtok_r(pch, "/", &str);
mask = strtok_r(NULL, "", &str);
if(check_ipv4_address(ip, mask, address))
return 1;
continue;
}
if (strcmp(pch, address) == 0)
return 1;
} else {
addr = check_ipv6_address_active(address);
if(strstr(pch, "/")) {
ip = strtok_r(pch, "/", &str);
mask = strtok_r(NULL, "", &str);
ip = check_ipv6_address_active(ip);
if(check_ipv6_address(ip, mask, addr))
return 1;
continue;
}
pch = check_ipv6_address_active(pch);
if (strcmp(pch, addr) == 0)
return 1;
}
}
return 0;
}
static int check_port_allowed(int port)
{
char *pch, *spch, *min, *max, *str;
for (pch = strtok_r(cur_twamp_conf.port_list, ",", &spch); pch != NULL; pch = strtok_r(NULL, ",", &spch))
{
if(strstr(pch, "-")) {
min = strtok_r(pch, "-", &str);
max = strtok_r(NULL, "", &str);
if(port >= atoi(min) && port <= atoi(max))
return 1;
continue;
}
if (port == atoi(pch))
return 1;
}
return 0;
}
/* The cleanup_client function will close every connection (TWAMP-Control ot TWAMP-Test that this server has with the client defined by the client_infor
* structure received as a parameter.
*/
static void cleanup_client(struct client_info *client)
{
char str_client[INET6_ADDRSTRLEN];
inet_ntop(socket_family, (socket_family == AF_INET6) ? (void*) &(client->addr6.sin6_addr) : (void*) &(client->addr.sin_addr), str_client, sizeof(str_client));
twamp_log(SINFO, "Cleanup client %s", str_client);
FD_CLR(client->socket, &read_fds);
close(client->socket);
used_sockets--;
int i;
for (i = 0; i < client->sess_no; i++)
/* If socket is -1 the session has already been closed */
if (client->sessions[i].socket > 0) {
FD_CLR(client->sessions[i].socket, &read_fds);
close(client->sessions[i].socket);
client->sessions[i].socket = -1;
used_sockets--;
}
memset(client, 0, sizeof(struct client_info));
client->status = kOffline;
}
/* The TWAMP server can only accept max_clients and it will recycle the positions for the available clients. */
static int find_empty_client(struct client_info *clients, int max_clients)
{
int i;
for (i = 0; i < max_clients; i++)
if (clients[i].status == kOffline)
return i;
return -1;
}
/* Sends a ServerGreeting message to the Control-Client after the TCP connection has been established. */
static int send_greeting(uint16_t mode_mask, struct client_info *client)
{
int socket = client->socket;
char str_client[INET6_ADDRSTRLEN]; /* String for Client IP address */
inet_ntop(socket_family, (socket_family == AF_INET6) ? (void*) &(client->addr6.sin6_addr) : (void*) &(client->addr.sin_addr), str_client, sizeof(str_client));
int i;
ServerGreeting greet;
memset(&greet, 0, sizeof(greet));
greet.Modes = htonl(client->mode & mode_mask);
for (i = 0; i < 16; i++)
greet.Challenge[i] = rand() % 16;
for (i = 0; i < 16; i++)
greet.Salt[i] = rand() % 16;
greet.Count = htonl(1 << 10);
int rv = send(socket, &greet, sizeof(greet), 0);
if (rv < 0) {
twamp_log(SCRIT,"Failed to send ServerGreeting message");
cleanup_client(client);
} else if ((authmode & 0x000F) == 0) {
twamp_log(SCRIT,"Sent ServerGreeting message with Mode 0! Abort");
cleanup_client(client);
} else {
twamp_log(SINFO,"Sent ServerGreeting message to %s", str_client);
}
return rv;
}
/* After a ServerGreeting the Control-Client should respond with a SetUpResponse. This function treats this message */
static int receive_greet_response(struct client_info *client)
{
int socket = client->socket;
char str_client[INET6_ADDRSTRLEN]; /* String for Client IP address */
inet_ntop(socket_family, (socket_family == AF_INET6)? (void*) &(client->addr6.sin6_addr) : (void*) &(client->addr.sin_addr), str_client, sizeof(str_client));
SetUpResponse resp;
memset(&resp, 0, sizeof(resp));
int rv = recv(socket, &resp, sizeof(resp), 0);
if (rv <= 32) {
twamp_log(SCRIT,"Failed to receive SetUpResponse");
cleanup_client(client);
} else {
twamp_log(SINFO, "Received SetUpResponse message from %s with mode %d", str_client, ntohl(resp.Mode));
if ((ntohl(resp.Mode) & client->mode & 0x000F) == 0) {
twamp_log(SCRIT,"The client does not support any usable Mode");
rv = 0;
}
client->mode = ntohl(resp.Mode);
}
return rv;
}
/* Sent a ServerStart message to the Control-Client to endthe TWAMP-Control session establishment phase */
static int send_start_serv(struct client_info *client, TWAMPTimestamp StartTime)
{
int socket = client->socket;
char str_client[INET6_ADDRSTRLEN];
inet_ntop(socket_family, (socket_family == AF_INET6)? (void*) &(client->addr6.sin6_addr) : (void*) &(client->addr.sin_addr), str_client, sizeof(str_client));
ServerStart msg;
memset(&msg, 0, sizeof(msg));
if ((StartTime.integer == 0) && (StartTime.fractional == 0)) {
msg.Accept = kAspectNotSupported;
} else {
msg.Accept = kOK;
}
msg.StartTime = StartTime;
int rv = send(socket, &msg, sizeof(msg), 0);
if (rv <= 0) {
twamp_log(SCRIT,"Failed to send ServerStart message");
cleanup_client(client);
} else {
client->status = kConfigured;
twamp_log(SINFO, "ServerStart message sent to %s", str_client);
if (msg.Accept == kAspectNotSupported) {
cleanup_client(client);
}
}
return rv;
}
/* Sends a StartACK for the StartSessions message */
static int send_start_ack(struct client_info *client)
{
char str_client[INET6_ADDRSTRLEN];
inet_ntop(socket_family, (socket_family == AF_INET6)? (void*) &(client->addr6.sin6_addr) : (void*) &(client->addr.sin_addr), str_client, sizeof(str_client));
StartACK ack;
memset(&ack, 0, sizeof(ack));
ack.Accept = kOK;
int rv = send(client->socket, &ack, sizeof(ack), 0);
if (rv <= 0) {
twamp_log(SCRIT,"Failed to send StartACK message");
} else
twamp_log(SINFO,"StartACK message sent to %s", str_client);
return rv;
}
/* This function treats the case when a StartSessions is received from the Control-Client to start a number of TWAMP-Test sessions */
static int receive_start_sessions(struct client_info *client)
{
int i;
int rv = send_start_ack(client);
if (rv <= 0)
return rv;
/* Now it can receive packets on the TWAMP-Test sockets */
for (i = 0; i < client->sess_no; i++) {
FD_SET(client->sessions[i].socket, &read_fds);
if (fd_max < client->sessions[i].socket)
fd_max = client->sessions[i].socket;
}
client->status = kTesting;
return rv;
}
/* This functions treats the case when a StopSessions is received from the Control-Client to end all the Test sessions. */
static int receive_stop_sessions(struct client_info *client)
{
/* If a StopSessions message was received, it can still receive Test packets until the timeout has expired */
gettimeofday(&client->shutdown_time, NULL);
return 0;
}
/* Computes the response to a RequestTWSession message */
static int send_accept_session(struct client_info *client, RequestSession * req)
{
char str_client[INET6_ADDRSTRLEN]; /* String for Client IP address */
AcceptSession acc;
memset(&acc, 0, sizeof(acc));
inet_ntop(socket_family, (socket_family == AF_INET6)? (void*) &(client->addr6.sin6_addr) : (void*) &(client->addr.sin_addr), str_client, sizeof(str_client));
/* Check if there are any slots available */
if ((used_sockets < 64) && (client->sess_no < MAX_SESSIONS_PER_CLIENT)) {
int testfd = socket(socket_family, SOCK_DGRAM, 0);
if (testfd < 0) {
twamp_log(SCRIT,"Error opening socket");
return -1;
}
int check_time = CHECK_TIMES;
if(socket_family == AF_INET6) {
struct sockaddr_in6 local_addr;
memset(&local_addr, 0, sizeof(local_addr));
local_addr.sin6_family = AF_INET6;
local_addr.sin6_addr = in6addr_any;
local_addr.sin6_port = req->ReceiverPort;
while (check_time-- && bind(testfd, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0)
local_addr.sin6_port = htons(20000 + rand() % 1000);
if (check_time > 0) {
req->ReceiverPort = local_addr.sin6_port;
}
} else {
struct sockaddr_in local_addr;
memset(&local_addr, 0, sizeof(local_addr));
local_addr.sin_family = AF_INET;
local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
local_addr.sin_port = req->ReceiverPort;
while (check_time-- && bind(testfd, (struct sockaddr *)&local_addr, sizeof(struct sockaddr)) < 0)
local_addr.sin_port = htons(20000 + rand() % 1000);
if (check_time > 0) {
req->ReceiverPort = local_addr.sin_port;
}
}
if (check_time > 0) {
acc.Accept = kOK;
acc.Port = req->ReceiverPort;
client->sessions[client->sess_no].socket = testfd;
client->sessions[client->sess_no].req = *req;
/* SID construction */
memcpy(acc.SID, &req->ReceiverAddress, 4);
TWAMPTimestamp sidtime = get_timestamp();
memcpy(&acc.SID[4], &sidtime, 8);
int k;
for (k = 0; k < 4; k++)
acc.SID[12 + k] = rand() % 256;
memcpy(&client->sessions[client->sess_no].sid_addr, &acc.SID, 4);
client->sessions[client->sess_no].sid_time = sidtime;
memcpy(&client->sessions[client->sess_no].sid_rand, &acc.SID[12], 4);
twamp_log(SINFO, "SID: 0x%04X.%04X.%04X.%04X",
ntohl(client->sessions[client->sess_no].sid_addr),
ntohl(client->sessions[client->sess_no].sid_time.integer),
ntohl(client->sessions[client->sess_no].sid_time.fractional),
ntohl(client->sessions[client->sess_no].sid_rand));
/* Set socket options */
set_socket_option(testfd, cur_twamp_conf.max_ttl);
set_socket_tos(testfd, (client->sessions[client->sess_no].req.TypePDescriptor << 2));
client->sess_no++;
} else {
twamp_log(SINFO, "kTemporaryResourceLimitation: check_time [%d]", check_time);
acc.Accept = kTemporaryResourceLimitation;
acc.Port = 0;
}
} else {
twamp_log(SINFO, "kTemporaryResourceLimitation: used_sockets [%d], sess_no [%d]", used_sockets, client->sess_no);
acc.Accept = kTemporaryResourceLimitation;
acc.Port = 0;
}
int rv = send(client->socket, &acc, sizeof(acc), 0);
return rv;
}
/* This function treats the case when a RequestTWSession is received */
static int receive_request_session(struct client_info *client, RequestSession * req)
{
char str_client[INET6_ADDRSTRLEN]; /* String for Client IP address */
if(socket_family == AF_INET6) {
inet_ntop(AF_INET6, &(client->addr6.sin6_addr), str_client, sizeof(str_client));
twamp_log(SINFO, "Server received RequestTWSession message");
} else {
char str_server[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(client->addr.sin_addr), str_client, INET_ADDRSTRLEN);
struct in_addr se_addr;
se_addr.s_addr = req->ReceiverAddress;
inet_ntop(AF_INET, &(se_addr), str_server, INET_ADDRSTRLEN);
twamp_log(SINFO, "Server %s received RequestTWSession message with port %d", str_server, ntohs(req->ReceiverPort));
}
/* Check port test packets if its allowed by PortAllowedList parameter */
if(cur_twamp_conf.port_list[0] != '\0') {
if(!check_port_allowed(ntohs(req->ReceiverPort))) {
twamp_log(SINFO, "Port %d is not allowed", ntohs(req->ReceiverPort));
return -1;
}
}
int rv = send_accept_session(client, req);
if (rv <= 0) {
twamp_log(SCRIT,"Failed to send the Accept-Session message");
}
return rv;
}
/* This function will receive a TWAMP-Test packet and will send a response. In TWAMP the Session-Sender (in our case the Control-Client, meaning the
* TWAMP-Client) is always sending TWAMP-Test packets and the Session-Reflector (Server) is receiving TWAMP-Test packets.
*/
static int receive_test_message(struct client_info *client, int session_index)
{
struct sockaddr_in addr;
struct sockaddr_in6 addr6;
socklen_t len = sizeof(addr);
char str_client[INET6_ADDRSTRLEN];
inet_ntop(socket_family, (socket_family == AF_INET6)? (void*) &(client->addr6.sin6_addr) : (void*) &(client->addr.sin_addr), str_client, sizeof(str_client));
ReflectorUPacket pack_reflect;
memset(&pack_reflect, 0, sizeof(pack_reflect));
SenderUPacket pack;
memset(&pack, 0, sizeof(pack));
/* New for recvmsg */
struct msghdr *message = malloc(sizeof(struct msghdr));
struct cmsghdr *c_msg;
char *control_buffer = malloc(TST_PKT_SIZE);
uint16_t control_length = TST_PKT_SIZE;
memset(message, 0, sizeof(*message));
message->msg_name = (socket_family == AF_INET6)? (void*)&addr6: (void*)&addr;
message->msg_namelen = len;
message->msg_iov = malloc(sizeof(struct iovec));
message->msg_iov->iov_base = &pack;
message->msg_iov->iov_len = TST_PKT_SIZE;
message->msg_iovlen = 1;
message->msg_control = control_buffer;
message->msg_controllen = control_length;
int rv = recvmsg(client->sessions[session_index].socket, message, 0);
pack_reflect.receive_time = get_timestamp();
char str_server[INET6_ADDRSTRLEN]; /* String for Client IP address */
inet_ntop(socket_family, (socket_family == AF_INET6)? (void*) &(addr6.sin6_addr) : (void*) &(addr.sin_addr), str_server, sizeof(str_server));
if (rv <= 0) {
twamp_log(SCRIT,"Failed to receive TWAMP-Test packet");
return rv;
} else if (rv < 14) {
twamp_log(SCRIT,"Short TWAMP-Test packet");
return rv;
}
/* Get TTL/TOS values from IP header */
uint8_t fw_ttl = 0;
uint8_t fw_tos = 0;
for (c_msg = CMSG_FIRSTHDR(message); c_msg; c_msg = (CMSG_NXTHDR(message, c_msg))) {
if ((c_msg->cmsg_level == IPPROTO_IP && c_msg->cmsg_type == IP_TTL) || (c_msg->cmsg_level == IPPROTO_IPV6 && c_msg->cmsg_type == IPV6_HOPLIMIT)) {
fw_ttl = *(int *)CMSG_DATA(c_msg);
} else if (c_msg->cmsg_level == IPPROTO_IP && c_msg->cmsg_type == IP_TOS) {
fw_tos = *(int *)CMSG_DATA(c_msg);
} else {
twamp_log(SINFO, "Warning, unexpected data of level %i and type %i", c_msg->cmsg_level, c_msg->cmsg_type);
}
}
twamp_log(SINFO, "Received TWAMP-Test message from %s", inet_ntoa(addr.sin_addr));
pack_reflect.seq_number = htonl(client->sessions[session_index].seq_nb++);
pack_reflect.error_estimate = htons(0x8001); // Sync = 1, Multiplier = 1
pack_reflect.sender_seq_number = pack.seq_number;
pack_reflect.sender_time = pack.time;
pack_reflect.sender_error_estimate = pack.error_estimate;
pack_reflect.sender_ttl = fw_ttl; // Copy from the IP header packet from Sender
if ((client->mode & kModeDSCPECN) == kModeDSCPECN) {
pack_reflect.sender_tos = fw_tos; // Copy from the IP header packet from Sender
}
if(socket_family == AF_INET6) {
addr.sin_port = client->sessions[session_index].req.SenderPort;
} else {
addr6.sin6_port = client->sessions[session_index].req.SenderPort;
}
/* FW Loss Calculation */
if (client->sessions[session_index].fw_msg == 0) {
client->sessions[session_index].fw_msg = 1;
/* Response packet for TOS with ECN */
if ((fw_tos & 0x03) > 0) {
uint8_t ecn_tos = (fw_tos & 0x03) - (((fw_tos & 0x2) >> 1) & (fw_tos & 0x1));
set_socket_tos(client->sessions[session_index].socket, (client->sessions[session_index].req.TypePDescriptor << 2) + ecn_tos);
}
} else {
client->sessions[session_index].fw_msg = client->sessions[session_index].fw_msg + ntohl(pack.seq_number) - client->sessions[session_index].snd_nb;
client->sessions[session_index].fw_lst_msg = client->sessions[session_index].fw_lst_msg + ntohl(pack.seq_number) - client->sessions[session_index].snd_nb - 1;
}
client->sessions[session_index].snd_nb = ntohl(pack.seq_number);
/* Response packet */
pack_reflect.time = get_timestamp();
if(socket_family == AF_INET6) {
if (rv < 41) {
rv = sendto(client->sessions[session_index].socket, &pack_reflect, 41, 0, (struct sockaddr *)&addr6, sizeof(addr6));
} else {
rv = sendto(client->sessions[session_index].socket, &pack_reflect, rv, 0, (struct sockaddr *)&addr6, sizeof(addr6));
}
} else {
if (rv < 41) {
rv = sendto(client->sessions[session_index].socket, &pack_reflect, 41, 0, (struct sockaddr *)&addr, sizeof(addr));
} else {
rv = sendto(client->sessions[session_index].socket, &pack_reflect, rv, 0, (struct sockaddr *)&addr, sizeof(addr));
}
}
if (rv <= 0) {
twamp_log(SCRIT,"Failed to send TWAMP-Test packet");
}
/* Print the FW metrics */
print_metrics_server(str_client, socket_family == AF_INET6 ? ntohs(addr6.sin6_port): ntohs(addr.sin_port), ntohs(client->sessions[session_index].req.ReceiverPort), (client->sessions[session_index].req.TypePDescriptor << 2), fw_tos, &pack_reflect);
if ((client->sessions[session_index].fw_msg % 10) == 0) {
twamp_log(SINFO,"FW Lost packets: %u/%u", client->sessions[session_index].fw_lst_msg, client->sessions[session_index].fw_msg);
twamp_log(SINFO,"FW Loss Ratio: %3.2f%%", (float)100 * client->sessions[session_index].fw_lst_msg / client->sessions[session_index].fw_msg);
//printf("FW Lost packets: %u/%u, FW Loss Ratio: %3.2f%%\n", client->sessions[session_index].fw_lst_msg, client->sessions[session_index].fw_msg, (float)100 * client->sessions[session_index].fw_lst_msg / client->sessions[session_index].fw_msg);
}
return rv;
}
int twamp_connect(void)
{
int listenfd, newsockfd;
struct client_info clients[MAX_CLIENTS];
struct sockaddr_in client_addr;
struct sockaddr_in6 client_addr6;
int rv;
/* Obtain start server time in TWAMP format */
TWAMPTimestamp StartTime = get_timestamp();
if(cur_twamp_conf.ip_version == 4)
socket_family = AF_INET;
else
socket_family = AF_INET6;
listenfd = socket(socket_family, SOCK_STREAM, 0);
if (listenfd < 0) {
twamp_log(SCRIT,"Error opening socket");
return -1;
}
int ret = setsockopt(listenfd, SOL_SOCKET, SO_BINDTODEVICE, cur_twamp_conf.device, strlen(cur_twamp_conf.device)+1);
if(ret) {
twamp_log(SCRIT,"Error on setsockopt with ret %d", ret);
return -1;
}
if(socket_family == AF_INET6) {
/* Set Server address and bind on the TWAMP port */
struct sockaddr_in6 serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin6_family = AF_INET6;
serv_addr.sin6_addr = in6addr_any;
serv_addr.sin6_port = htons(cur_twamp_conf.port);
if (bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
twamp_log(SCRIT,"Error on binding");
return -1;
}
} else {
/* Set Server address and bind on the TWAMP port */
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(cur_twamp_conf.port);
if (bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)) < 0) {
twamp_log(SCRIT,"Error on binding");
return -1;
}
}
used_sockets++;
/* Start listening on the TWAMP port for new TWAMP-Control connections */
if (listen(listenfd, MAX_CLIENTS)) {
twamp_log(SCRIT,"Error on listen");
return -1;
}
FD_ZERO(&read_fds);
FD_SET(listenfd, &read_fds);
fd_max = listenfd;
memset(clients, 0, MAX_CLIENTS * sizeof(struct client_info));
fd_set tmp_fds;
FD_ZERO(&tmp_fds);
while (1) {
tmp_fds = read_fds;
if (select(fd_max + 1, &tmp_fds, NULL, NULL, NULL) < 0) {
twamp_log(SCRIT,"Error in select");
close(listenfd);
return -1;
}
/* If an event happened on the listenfd, then a new TWAMP-Control connection is received */
if (FD_ISSET(listenfd, &tmp_fds)) {
uint32_t client_len = (socket_family == AF_INET6)? sizeof(client_addr6) : sizeof(client_addr);
if ((newsockfd = accept(listenfd, (socket_family == AF_INET6) ? (struct sockaddr *)&client_addr6 : (struct sockaddr *)&client_addr, &client_len)) < 0) {
twamp_log(SCRIT,"Error in accept");
} else {
/* Add a new client if there are any slots available */
int pos = find_empty_client(clients, MAX_CLIENTS);
uint16_t mode_mask = 0;
if (pos != -1) {
clients[pos].status = kConnected;
clients[pos].socket = newsockfd;
clients[pos].addr = client_addr;
clients[pos].addr6 = client_addr6;
clients[pos].mode = authmode;
clients[pos].sess_no = 0;
used_sockets++;
FD_SET(newsockfd, &read_fds);
if (newsockfd > fd_max)
fd_max = newsockfd;
mode_mask = 0x01FF;
}
char str_client[INET6_ADDRSTRLEN]; /* String for Client IP address */
inet_ntop(socket_family, (socket_family == AF_INET6) ? (void*) &(clients[pos].addr6.sin6_addr) : (void*) &(clients[pos].addr.sin_addr), str_client, sizeof(str_client));
twamp_log(SINFO,"Receive a TCP connection from %s", str_client);
/* Check ip test packets if its allowed by IPAllowedList parameter */
if(cur_twamp_conf.ip_list[0] != '\0') {
if(!check_ip_address_allowed(str_client)) {
twamp_log(SINFO, "IP Address %d is not allowed", str_client);
close(listenfd);
return -1;
}
}
rv = send_greeting(mode_mask, &clients[pos]);
}
}
/* Receives other packets from the established TWAMP-Control sessions */
uint8_t buffer[4096];
int i, j;
for (i = 0; i < MAX_CLIENTS; i++)
/* It can only receive TWAMP-Control messages from Online clients */
if (clients[i].status != kOffline)
if (FD_ISSET(clients[i].socket, &tmp_fds)) {
switch (clients[i].status) {
case kConnected:
/* If a TCP session has been established and a ServerGreeting has been sent, wait for the SetUpResponse and finish the TWAMP-Control setup */
rv = receive_greet_response(&clients[i]);
if (rv > 32) {
rv = send_start_serv(&clients[i], StartTime);
} else {
rv = send_start_serv(&clients[i], ZeroT);
}
break;
case kConfigured:
/* Reset the buffer to receive a new message */
memset(buffer, 0, 4096);
rv = recv(clients[i].socket, buffer, 4096, 0);
if (rv <= 0) {
cleanup_client(&clients[i]);
break;
}
/* Check the message received: It can only be StartSessions or RequestTWSession */
switch (buffer[0]) {
case kStartSessions:
rv = receive_start_sessions(&clients[i]);
break;
case kRequestTWSession:
rv = receive_request_session(&clients[i], (RequestSession *) buffer);
break;
default:
break;
}
if (rv <= 0)
cleanup_client(&clients[i]);
break;
case kTesting:
/* In this state can only receive a StopSessions msg */
memset(buffer, 0, 4096);
rv = recv(clients[i].socket, buffer, 4096, 0);
if (rv <= 0) {
cleanup_client(&clients[i]);
break;
}
if (buffer[0] == kStopSessions) {
rv = receive_stop_sessions(&clients[i]);
}
break;
default:
break;
}
}
/* Check for TWAMP-Test packets */
for (i = 0; i < MAX_CLIENTS; i++) {
struct timeval current;
gettimeofday(&current, NULL);
if (clients[i].status == kTesting) {
uint8_t has_active_test_sessions = 0;
for (j = 0; j < clients[i].sess_no; j++) {
rv = get_actual_shutdown(&current, &clients[i].shutdown_time, &clients[i].sessions[j].req.Timeout);
if (rv > 0) {
has_active_test_sessions = 1;
if (FD_ISSET(clients[i].sessions[j].socket, &tmp_fds)) {
rv = receive_test_message(&clients[i], j);
}
} else {
FD_CLR(clients[i].sessions[j].socket, &read_fds);
close(clients[i].sessions[j].socket);
used_sockets--;
clients[i].sessions[j].socket = -1;
/* print loss result */
twamp_log(SINFO, "Session: %u, FW Lost packets: %u/%u, FW Loss Ratio: %3.2f%%", j, clients[i].sessions[j].fw_lst_msg, clients[i].sessions[j].fw_msg, (float)100 * clients[i].sessions[j].fw_lst_msg / clients[i].sessions[j].fw_msg);
}
}
if (!has_active_test_sessions) {
memset(&clients[i].shutdown_time, 0, sizeof(clients[i].shutdown_time));
clients[i].sess_no = 0;
clients[i].status = kConfigured;
}
}
}
}
return 0;
}
char *get_twamp_refector_option(char *instance, char *option)
{
struct uci_section *s;
char *v, *twamp_id, *curr_interface;
dmuci_foreach_section("cwmp_twamp", "twamp_refector", s) {
twamp_id = dmuci_get_value_bysection(s, "id");
if(strcmp(twamp_id, instance) == 0)
{
v = dmuci_get_value_bysection(s, option);
return v;
}
}
v = "";
return v;
}
int twamp_init(void)
{
char *id, *interface, *value = NULL;
int a;
value = dmuci_get_value("cwmp_twamp", "twamp", "log_level");
if(value != NULL && *value != '\0') {
a = atoi(value);
cur_twamp_conf.loglevel = a;
}
else
cur_twamp_conf.loglevel = DEFAULT_LOGLEVEL;
twamp_log(SDEBUG,"TWAMP Reflector Log Level:%d", cur_twamp_conf.loglevel);
id = dmuci_get_value("cwmp_twamp", "twamp", "id");
cur_twamp_conf.enable = atoi(get_twamp_refector_option(id, "enable"));
cur_twamp_conf.interface = strdup(get_twamp_refector_option(id, "interface"));
cur_twamp_conf.device = strdup(get_twamp_refector_option(id, "device"));
cur_twamp_conf.ip_version = atoi(get_twamp_refector_option(id, "ip_version"));
cur_twamp_conf.port = atoi(get_twamp_refector_option(id, "port"));
cur_twamp_conf.max_ttl = atoi(get_twamp_refector_option(id, "max_ttl"));
cur_twamp_conf.ip_list = strdup(get_twamp_refector_option(id, "ip_list"));
cur_twamp_conf.port_list = strdup(get_twamp_refector_option(id, "port_list"));
twamp_log(SDEBUG,"TWAMP Reflector Enable: %d", cur_twamp_conf.enable);
twamp_log(SDEBUG,"TWAMP Reflector Interface: %s", cur_twamp_conf.interface);
twamp_log(SDEBUG,"TWAMP Reflector Device: %s", cur_twamp_conf.device);
twamp_log(SDEBUG,"TWAMP Reflector Port: %d", cur_twamp_conf.port);
twamp_log(SDEBUG,"TWAMP Reflector MaximumTTL: %d", cur_twamp_conf.max_ttl);
twamp_log(SDEBUG,"TWAMP Reflector IPAllowedList: %s", cur_twamp_conf.ip_list);
twamp_log(SDEBUG,"TWAMP Reflector PortAllowedList: %s", cur_twamp_conf.port_list);
return 0;
}
void twamp_exit(void)
{
free(cur_twamp_conf.interface);
free(cur_twamp_conf.device);
free(cur_twamp_conf.ip_list);
free(cur_twamp_conf.port_list);
}
int main(int argc, char *argv[])
{
dmuci_init();
twamp_init();
dmuci_fini();
twamp_log(SINFO,"START TWAMP Reflector");
twamp_connect();
twamp_exit();
twamp_log(SINFO,"EXIT TWAMP Reflector");
return 0;
}

237
twamp/twamp.h Normal file
View file

@ -0,0 +1,237 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2019 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
* Name: Emma Mirică
* Project: TWAMP Protocol
* Class: OSS
* Email: emma.mirica@cti.pub.ro
* Contributions: stephanDB
*
*/
/*
* The following logical-model will be implemented:
*
* +----------------+ +-------------------+
* | Control-Client |<--TWAMP-Control-->| Server |
* | | | |
* | Session-Sender |<--TWAMP-Test----->| Session-Reflector |
* +----------------+ +-------------------+
*
*/
#ifndef _TWAMP_H__
#define _TWAMP_H__
#include <stdlib.h>
#include <stdbool.h>
#include <inttypes.h>
#include <sys/time.h>
#define CHECK_TIMES 100
#define LOSTTIME 2 /* SECONDS - Timeout for TWAMP test packet */
#define MAX_CLIENTS 10
#define MAX_SESSIONS_PER_CLIENT 10
enum CommandNumber {
kReserved,
kForbidden,
kStartSessions,
kStopSessions,
kReserved4,
kRequestTWSession,
kExperimentation
};
enum Mode {
kModeReserved = 0,
kModeUnauthenticated = 1,
kModeAuthenticated = 2,
kModeEncrypted = 4,
kModeHybrid = 8, /* Unauthenticated test, encrypted control */
kModeIndividual = 16,
kModeReflectOctets = 32,
KModeSymmetrical = 64,
KModeIKEv2Derived = 128,
kModeDSCPECN = 256
};
enum AcceptCode {
kOK,
kFailure,
kInternalError,
kAspectNotSupported,
kPermanentResourceLimitation,
kTemporaryResourceLimitation
};
typedef enum {
kOffline = 0,
kConnected,
kConfigured,
kTesting
} ClientStatus;
typedef struct twamp_timestamp {
uint32_t integer;
uint32_t fractional;
} TWAMPTimestamp;
/*****************************************/
/* */
/* TWAMP-Control specific messages */
/* */
/*****************************************/
/* First messsage sent by the Server to the Control-Client to establish a connection */
typedef struct server_greeting {
uint8_t Unused[12];
/* Modes = bit-wise OR between Mode values
* First 23 bits MUST be zero in TWAMP (29 in first version)*/
uint32_t Modes;
uint8_t Challenge[16]; /* Random sequence of bytes generated by the server */
uint8_t Salt[16];
uint32_t Count; /* MUST be a power of 2. Minimum 1024 */
uint8_t MBZ[12];
} ServerGreeting;
/* The Control-Client's response to the Server's greeting */
typedef struct control_client_greeting_response {
uint32_t Mode; /* if 0 -> the Server does not wish to communicate */
uint8_t KeyID[80];
uint8_t Token[64];
uint8_t ClientIV[16];
} SetUpResponse;
/* The Server sends a start message to conclude the TWAMP-Control session */
typedef struct server_start {
uint8_t MBZ1[15];
uint8_t Accept; /* 0 means Continue. See 3.3 of RFC 4656 */
uint8_t ServerIV[16];
TWAMPTimestamp StartTime; /* TWAMPTimestamp; 0 if Accept is NonZero. */
uint8_t MBZ2[8];
} ServerStart;
/* The Control-Client sends a RequestSession packet for each TWAMP-Test session */
typedef struct request_session {
uint8_t Type; /* 5 / CommandNumber */
uint8_t IPVN; /* MBZ | IPVN */
uint8_t ConfSender; /* 0 */
uint8_t ConfReceiver; /* 0 */
uint32_t SlotsNo; /* 0 */
uint32_t PacketsNo; /* 0 */
uint16_t SenderPort;
uint16_t ReceiverPort;
uint32_t SenderAddress;
uint8_t MBZ1[12]; /* Sender Address Cont */
uint32_t ReceiverAddress;
uint8_t MBZ2[12]; /* Receiver Address Cont */
uint8_t SID[16]; /* 0 */
uint32_t PaddingLength;
TWAMPTimestamp StartTime;
TWAMPTimestamp Timeout;
uint32_t TypePDescriptor;
uint16_t OctetsToBeReflected;
uint16_t PadLenghtToReflect;
uint8_t MBZ3[4];
uint8_t HMAC[16];
} RequestSession;
/* The Server's response to the RequestSession packet */
typedef struct accept_session_packet {
uint8_t Accept; /* 3 if not supported */
uint8_t MBZ1;
uint16_t Port;
uint8_t SID[16]; /* Generated by server */
//uint16_t ReflectedOctets;
//uint16_t ServerOctets;
uint8_t MBZ2[8];
uint8_t HMAC[16];
} AcceptSession;
/* The Control-Client sends a StartSessions message to start all accepted TWAMP-Test sessions */
typedef struct start_message1 {
uint8_t Type; /* 2 */
uint8_t MBZ[15];
uint8_t HMAC[16];
} StartSessions;
/* When it receives a StartSessions, the Server responds with a StartACK */
typedef struct start_ack {
uint8_t Accept;
uint8_t MBZ[15];
uint8_t HMAC[16];
} StartACK;
/* The Control-Client sends a StopSessions message to stop all active TWAMP-Test sessions */
typedef struct twamp_stop {
uint8_t Type; /* 3 */
uint8_t Accept;
uint8_t MBZ1[2];
uint32_t SessionsNo;
uint8_t MBZ2[8];
uint8_t HMAC[16];
} StopSessions;
/*****************************************/
/* */
/* TWAMP-Test specific messages */
/* */
/*****************************************/
#define TST_PKT_SIZE 1472 //1472 (MTU 1514)
/* Session-Sender TWAMP-Test packet for Unauthenticated mode */
typedef struct test_packet {
uint32_t seq_number;
TWAMPTimestamp time;
uint16_t error_estimate;
uint8_t padding[TST_PKT_SIZE - 14];
} SenderUPacket;
/* Session-Reflector TWAMP-Test packet for Unauthenticated mode */
typedef struct reflector_unauth_packet {
uint32_t seq_number;
TWAMPTimestamp time;
uint16_t error_estimate;
uint8_t mbz1[2];
TWAMPTimestamp receive_time;
uint32_t sender_seq_number;
TWAMPTimestamp sender_time;
uint16_t sender_error_estimate;
uint8_t mbz2[2];
uint8_t sender_ttl;
uint8_t sender_tos;
uint8_t padding[TST_PKT_SIZE - 42];
} ReflectorUPacket;
struct twamp_config
{
bool enable;
char *interface;
char *device;
int ip_version;
int port;
int max_ttl;
char *ip_list;
char *port_list;
int loglevel;
};
extern struct twamp_config cur_twamp_conf;
void timeval_to_timestamp(const struct timeval *tv, TWAMPTimestamp * ts);
void timestamp_to_timeval(const TWAMPTimestamp * ts, struct timeval *tv);
uint64_t get_usec(const TWAMPTimestamp * ts);
TWAMPTimestamp get_timestamp();
int get_actual_shutdown(const struct timeval *tv, const struct timeval *ts, const TWAMPTimestamp * t);
void print_metrics_server(char *addr_cl, uint16_t snd_port, uint16_t rcv_port, uint8_t snd_tos, uint8_t fw_tos, const ReflectorUPacket * pack);
void set_socket_option(int socket, uint8_t ip_ttl);
void set_socket_tos(int socket, uint8_t ip_tos);
#endif /* _TWAMP_H__ */

55
twamp/twamplog.c Normal file
View file

@ -0,0 +1,55 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2019 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*/
#include <time.h>
#include <syslog.h>
#include <stdarg.h>
#include "twamplog.h"
#include "twamp.h"
#define DEBUG
static const int log_syslogmap[] = {
[SCRIT] = LOG_CRIT,
[SWARNING] = LOG_WARNING,
[SNOTICE] = LOG_NOTICE,
[SINFO] = LOG_INFO,
[SDEBUG] = LOG_DEBUG
};
static const char* log_str[] = {
[SCRIT] = "CRITICAL",
[SWARNING] = "WARNING",
[SNOTICE] = "NOTICE",
[SINFO] = "INFO",
[SDEBUG] = "DEBUG"
};
void twamp_log(int priority, const char *format, ...)
{
va_list vl;
char *log;
if (priority <= cur_twamp_conf.loglevel) {
#ifdef DEBUG
time_t t = time(NULL);
struct tm tm = *localtime(&t);
va_start(vl, format);
printf("%d-%02d-%02d %02d:%02d:%02d [twamp] %s - ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, log_str[priority]);
vprintf(format, vl);
va_end(vl);
printf("\n");
#endif
openlog("twamp", 0, LOG_DAEMON);
va_start(vl, format);
vsyslog(log_syslogmap[priority], format, vl);
va_end(vl);
closelog();
}
}

27
twamp/twamplog.h Normal file
View file

@ -0,0 +1,27 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2019 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*/
#ifndef _TWAMPLOG_H_
#define _TWAMPLOG_H_
#define DEFAULT_LOGLEVEL SINFO
enum udpechoserver_log_level_enum {
SCRIT,
SWARNING,
SNOTICE,
SINFO,
SDEBUG,
__MAX_SLOG
};
void twamp_log(int priority, const char *format, ...);
#endif /* _TWAMPLOG_H_ */

195
twamp/twamptimestamp.c Normal file
View file

@ -0,0 +1,195 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2019 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*
* Name: Emma Mirică
* Project: TWAMP Protocol
* Class: OSS
* Email: emma.mirica@cti.pub.ro
* Contributions: stephanDB
*
*/
#include <inttypes.h>
#include <sys/time.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <stdio.h>
#include "twamp.h"
#include "twamplog.h"
void timeval_to_timestamp(const struct timeval *tv, TWAMPTimestamp * ts)
{
if (!tv || !ts)
return;
/* Unix time to NTP */
ts->integer = tv->tv_sec + 2208988800uL;
ts->fractional = (uint32_t) ((double)tv->tv_usec * ((double)(1uLL << 32)
/ (double)1e6));
ts->integer = htonl(ts->integer);
ts->fractional = htonl(ts->fractional);
}
void timestamp_to_timeval(const TWAMPTimestamp * ts, struct timeval *tv)
{
if (!tv || !ts)
return;
TWAMPTimestamp ts_host_ord;
ts_host_ord.integer = ntohl(ts->integer);
ts_host_ord.fractional = ntohl(ts->fractional);
/* NTP to Unix time */
tv->tv_sec = ts_host_ord.integer - 2208988800uL;
tv->tv_usec = (uint32_t) (double)ts_host_ord.fractional * (double)1e6 / (double)(1uLL << 32);
}
TWAMPTimestamp get_timestamp()
{
struct timeval tv;
gettimeofday(&tv, NULL);
TWAMPTimestamp ts;
timeval_to_timestamp(&tv, &ts);
return ts;
}
uint64_t get_usec(const TWAMPTimestamp * ts)
{
struct timeval tv;
timestamp_to_timeval(ts, &tv);
return tv.tv_sec * 1000000 + tv.tv_usec;
}
int get_actual_shutdown(const struct timeval *tv, const struct timeval *ts,
const TWAMPTimestamp * t)
{
/* If ts is 0 then no StopSessions message was received */
if ((ts->tv_sec * 1000000 + ts->tv_usec) == 0)
return 1;
/* Else compute time difference */
uint64_t current = tv->tv_sec * 1000000 + tv->tv_usec;
uint64_t shutdown = ts->tv_sec * 1000000 + ts->tv_usec;
uint64_t timeout = get_usec(t);
/* This should be ok, as no difference is computed */
if (current > shutdown + timeout)
return 1;
return 0;
}
void print_metrics_server(char *addr_cl, uint16_t snd_port, uint16_t rcv_port,
uint8_t snd_tos, uint8_t fw_tos,
const ReflectorUPacket * pack)
{
/* Compute timestamps in usec */
uint64_t t_sender_usec1 = get_usec(&pack->sender_time);
uint64_t t_receive_usec1 = get_usec(&pack->receive_time);
uint64_t t_reflsender_usec1 = get_usec(&pack->time);
/* Compute delays */
int64_t fwd1 = t_receive_usec1 - t_sender_usec1;
int64_t intd1 = t_reflsender_usec1 - t_receive_usec1;
char sync1 = 'Y';
if (fwd1 < 0) {
sync1 = 'N';
}
/* Sequence number */
uint32_t snd_nb = ntohl(pack->sender_seq_number);
uint32_t rcv_nb = ntohl(pack->seq_number);
/* Sender TOS with ECN from FW TOS */
snd_tos = snd_tos + (fw_tos & 0x3) - (((fw_tos & 0x2) >> 1) & (fw_tos & 0x1));
/* Print different metrics */
twamp_log(SINFO,"Snd@: %s", addr_cl);
twamp_log(SINFO,"Time: %.0f", (double)t_sender_usec1 * 1e-3);
twamp_log(SINFO,"Snd#: %d", snd_nb);
twamp_log(SINFO,"Rcv#: %d", rcv_nb);
twamp_log(SINFO,"SndPt: %d", snd_port);
twamp_log(SINFO,"RcvPt: %d", rcv_port);
twamp_log(SINFO,"Sync: %c", sync1);
twamp_log(SINFO,"TTL: %d", pack->sender_ttl);
twamp_log(SINFO,"SndTOS: %d", snd_tos);
twamp_log(SINFO,"FW_TOS: %d", fw_tos);
twamp_log(SINFO,"Int D: %.3f", (double)intd1 * 1e-3);
}
void set_socket_option(int socket, uint8_t ip_ttl)
{
/* Set socket options : timeout, IPTTL, IP_RECVTTL, IP_RECVTOS */
uint8_t One = 1;
int result;
/* Set Timeout */
struct timeval timeout = { LOSTTIME, 0 }; //set timeout for 2 seconds
/* Set receive UDP message timeout value */
#ifdef SO_RCVTIMEO
result = setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO,
(char *)&timeout, sizeof(struct timeval));
if (result != 0) {
twamp_log(SDEBUG, "[PROBLEM] Cannot set the timeout value for reception.\n");
}
#else
twamp_log(SDEBUG, "No way to set the timeout value for incoming packets on that platform.\n");
#endif
/* Set IPTTL value to twamp standard: 255 */
#ifdef IP_TTL
result = setsockopt(socket, IPPROTO_IP, IP_TTL, &ip_ttl, sizeof(ip_ttl));
if (result != 0) {
twamp_log(SDEBUG, "[PROBLEM] Cannot set the TTL value for emission.\n");
}
#else
twamp_log(SDEBUG, "No way to set the TTL value for leaving packets on that platform.\n");
#endif
/* Set receive IP_TTL option */
#ifdef IP_RECVTTL
result = setsockopt(socket, IPPROTO_IP, IP_RECVTTL, &One, sizeof(One));
if (result != 0) {
twamp_log(SDEBUG, "[PROBLEM] Cannot set the socket option for TTL reception.\n");
}
#else
twamp_log(SDEBUG, "No way to ask for the TTL of incoming packets on that platform.\n");
#endif
/* Set receive IP_TOS option */
#ifdef IP_RECVTOS
result = setsockopt(socket, IPPROTO_IP, IP_RECVTOS, &One, sizeof(One));
if (result != 0) {
twamp_log(SDEBUG, "[PROBLEM] Cannot set the socket option for TOS reception.\n");
}
#else
twamp_log(SDEBUG, "No way to ask for the TOS of incoming packets on that platform.\n");
#endif
}
void set_socket_tos(int socket, uint8_t ip_tos)
{
/* Set socket options : IP_TOS */
int result;
/* Set IP TOS value */
#ifdef IP_TOS
result = setsockopt(socket, IPPROTO_IP, IP_TOS, &ip_tos, sizeof(ip_tos));
if (result != 0) {
twamp_log(SDEBUG, "[PROBLEM] Cannot set the TOS value for emission.\n");
}
#else
twamp_log(SDEBUG, "No way to set the TOS value for leaving packets on that platform.\n");
#endif
}

270
twamp/twampuci.c Normal file
View file

@ -0,0 +1,270 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2019 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*/
#include <strings.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdarg.h>
#include <errno.h>
#include <unistd.h>
#include <uci.h>
#include "twampuci.h"
struct uci_context *uci_ctx;
int dmuci_init(void)
{
uci_ctx = uci_alloc_context();
if (!uci_ctx) {
return -1;
}
return 0;
}
int dmuci_fini(void)
{
if (uci_ctx) {
uci_free_context(uci_ctx);
}
return 0;
}
static bool dmuci_validate_section(const char *str)
{
if (!*str)
return false;
for (; *str; str++) {
unsigned char c = *str;
if (isalnum(c) || c == '_')
continue;
return false;
}
return true;
}
static int dmuci_init_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *package, char *section, char *option, char *value)
{
char *last = NULL;
char *tmp;
memset(ptr, 0, sizeof(struct uci_ptr));
/* value */
if (value) {
ptr->value = value;
}
ptr->package = package;
if (!ptr->package)
goto error;
ptr->section = section;
if (!ptr->section) {
ptr->target = UCI_TYPE_PACKAGE;
goto lastval;
}
ptr->option = option;
if (!ptr->option) {
ptr->target = UCI_TYPE_SECTION;
goto lastval;
} else {
ptr->target = UCI_TYPE_OPTION;
}
lastval:
if (ptr->section && !dmuci_validate_section(ptr->section))
ptr->flags |= UCI_LOOKUP_EXTENDED;
return 0;
error:
return -1;
}
struct uci_section *dmuci_walk_section(char *package, char *section_type, struct uci_section *prev_section)
{
struct uci_ptr ptr;
struct uci_element *e;
struct uci_section *next_section;
if (section_type == NULL) {
if (prev_section) {
e = &prev_section->e;
if (e->list.next == &prev_section->package->sections)
return NULL;
e = container_of(e->list.next, struct uci_element, list);
next_section = uci_to_section(e);
return next_section;
}
else {
if (dmuci_init_ptr(uci_ctx, &ptr, package, NULL, NULL, NULL)) {
return NULL;
}
if (uci_lookup_ptr(uci_ctx, &ptr, NULL, true) != UCI_OK) {
return NULL;
}
if (ptr.p->sections.next == &ptr.p->sections)
return NULL;
e = container_of(ptr.p->sections.next, struct uci_element, list);
next_section = uci_to_section(e);
return next_section;
}
}
else {
struct uci_list *ul, *u = NULL;
struct uci_list *shead = NULL;
if (prev_section) {
ul = &prev_section->e.list;
shead = &prev_section->package->sections;
}
else {
if (dmuci_init_ptr(uci_ctx, &ptr, package, NULL, NULL, NULL)) {
return NULL;
}
if (uci_lookup_ptr(uci_ctx, &ptr, NULL, true) != UCI_OK) {
return NULL;
}
ul = &ptr.p->sections;
shead = &ptr.p->sections;
}
while (ul->next != shead) {
e = container_of(ul->next, struct uci_element, list);
next_section = uci_to_section(e);
if (strcmp(next_section->type, section_type) == 0)
return next_section;
ul = ul->next;
}
return NULL;
}
return NULL;
}
void dmuci_print_list(struct uci_list *uh, char **val, char *delimiter)
{
struct uci_element *e;
static char buffer[512];
int dlen = strlen(delimiter);
int olen = 0;
char *buf = buffer;
*buf = '\0';
uci_foreach_element(uh, e) {
if (*buf) {
strcat(buf, delimiter);
strcat(buf, e->name);
}
else {
strcpy(buf, e->name);
}
}
*val = buf;
}
struct uci_element *dmuci_lookup_list(struct uci_list *list, const char *name)
{
struct uci_element *e;
uci_foreach_element(list, e) {
if (!strcmp(e->name, name))
return e;
}
return NULL;
}
int uci_lookup_ptr_bysection(struct uci_context *ctx, struct uci_ptr *ptr, struct uci_section *section, char *option, char *value)
{
struct uci_element *e;
memset(ptr, 0, sizeof(struct uci_ptr));
ptr->package = section->package->e.name;
ptr->section = section->e.name;
ptr->option = option;
ptr->value = value;
ptr->flags |= UCI_LOOKUP_DONE;
ptr->p = section->package;
ptr->s = section;
if (ptr->option) {
e = dmuci_lookup_list(&ptr->s->options, ptr->option);
if (!e)
return UCI_OK;
ptr->o = uci_to_option(e);
ptr->last = e;
ptr->target = UCI_TYPE_OPTION;
}
else {
ptr->last = &ptr->s->e;
ptr->target = UCI_TYPE_SECTION;
}
ptr->flags |= UCI_LOOKUP_COMPLETE;
return UCI_OK;
}
char *dmuci_get_value_bysection(struct uci_section *section, char *option)
{
struct uci_ptr ptr;
char *val = "";
if (uci_lookup_ptr_bysection(uci_ctx, &ptr, section, option, NULL) != UCI_OK) {
return val;
}
if (!ptr.o)
return val;
if(ptr.o->type == UCI_TYPE_LIST) {
dmuci_print_list(&ptr.o->v.list, &val, " ");
return val;
}
if (ptr.o->v.string)
return ptr.o->v.string;
else
return val;
}
char *dmuci_get_value(char *package, char *section, char *option)
{
struct uci_ptr ptr;
char *val = "";
if (!section || !option)
return val;
if (dmuci_init_ptr(uci_ctx, &ptr, package, section, option, NULL)) {
return val;
}
if (uci_lookup_ptr(uci_ctx, &ptr, NULL, true) != UCI_OK) {
return val;
}
if (!ptr.o)
return val;
if(ptr.o->type == UCI_TYPE_LIST) {
dmuci_print_list(&ptr.o->v.list, &val, " ");
return val;
}
if (ptr.o->v.string)
return ptr.o->v.string;
else
return val;
}

33
twamp/twampuci.h Normal file
View file

@ -0,0 +1,33 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* Copyright (C) 2019 iopsys Software Solutions AB
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
*/
#ifndef _TWAMPUCI_H__
#define _TWAMPUCI_H__
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int dmuci_init(void);
int dmuci_fini(void);
struct uci_section *dmuci_walk_section(char *package, char *section_type, struct uci_section *prev_section);
void dmuci_print_list(struct uci_list *uh, char **val, char *delimiter);
struct uci_element *dmuci_lookup_list(struct uci_list *list, const char *name);
int uci_lookup_ptr_bysection(struct uci_context *ctx, struct uci_ptr *ptr, struct uci_section *section, char *option, char *value);
char *dmuci_get_value_bysection(struct uci_section *section, char *option);
char *dmuci_get_value(char *package, char *section, char *option);
#define dmuci_foreach_section(package, section_type, section) \
for (section = dmuci_walk_section(package, section_type, NULL); \
section != NULL; \
section = dmuci_walk_section(package, section_type, section))
#endif /* _TWAMPUCI_H__ */