mirror of
https://dev.iopsys.eu/bbf/icwmp.git
synced 2026-03-11 03:28:31 +01:00
Ticket refs#526: TR-181: Device.IP.Interface. object
This commit is contained in:
parent
9578f538c2
commit
a69b9cdb51
13 changed files with 3233 additions and 168 deletions
|
|
@ -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
4
config/cwmp_twamp
Normal 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'
|
||||
|
|
@ -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},
|
||||
|
|
|
|||
1462
dm/dmtree/tr181/ip.c
1462
dm/dmtree/tr181/ip.c
File diff suppressed because it is too large
Load diff
|
|
@ -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
56
init/icwmp_twampd
Normal 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
857
twamp/twamp.c
Normal 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(¤t, 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(¤t, &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
237
twamp/twamp.h
Normal 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
55
twamp/twamplog.c
Normal 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
27
twamp/twamplog.h
Normal 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
195
twamp/twamptimestamp.c
Normal 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
270
twamp/twampuci.c
Normal 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
33
twamp/twampuci.h
Normal 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__ */
|
||||
Loading…
Add table
Reference in a new issue