X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=src%2Frmr%2Fcommon%2Fsrc%2Ftools_static.c;h=2d2cc229716d772b1ac52e53eaeb89e439c76a7a;hb=11838bcf76f3614384459cb56e2ce80dea788cef;hp=67adc854f8479221496cb9aae43e91ca33c9b6af;hpb=68d09fa5028e47e763c44c30647da31e77eda64a;p=ric-plt%2Flib%2Frmr.git diff --git a/src/rmr/common/src/tools_static.c b/src/rmr/common/src/tools_static.c index 67adc85..2d2cc22 100644 --- a/src/rmr/common/src/tools_static.c +++ b/src/rmr/common/src/tools_static.c @@ -1,8 +1,8 @@ // :vi sw=4 ts=4 noet: /* ================================================================================== - Copyright (c) 2019 Nokia - Copyright (c) 2018-2019 AT&T Intellectual Property. + Copyright (c) 2019-2021 Nokia + Copyright (c) 2018-2021 AT&T Intellectual Property. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -22,12 +22,16 @@ Mnemonic: tools_static.c Abstract: A small set of very simple tools to support Uta == RMR. uta_tokenise -- simple string tokeniser + uta_rmip_tokenise -- tokenise and remove ip addresses from the list uta_h2ip -- look up host name and return an ip address uta_lookup_rtg -- looks in env for rtg host:port uta_has_str -- searches buffer of tokens for a string uta_link2 -- establish a nanomsg connection to a host + uta_dump_env -- dump the environment variables to stdout that are + of importance to RMR. + Author: E. Scott Daniels Date: 30 November 2018 */ @@ -50,6 +54,47 @@ #include #include +// --- some protos needed for better organisation -------- +static int is_this_myip( if_addrs_t* l, char* addr ); + + +// ---------------------------------------------------------------------------------- + + +/* + A strncpy() replacement that ensures the resulting dest buffer has + a zero (nil) terminator even if the source is longer than the dest + length. + A max of len-1 bytes are copied from src to dest. The copy stops when + a zero (nil) is encountered in the src, or len-1 bytes are copied. + The string is always nil terminated. + The string length is returned. + + It is the responsiblity of the caller to ensure that dest is at + least len bytes in length. + + If either src/dest is invalid (nil) a value of -1 is returned. +*/ +static inline int zt_buf_fill( char* dest, char const* src, int len ) { + char* dp; + char const* sp; + int n; // num moved + + if( dest == NULL || src == NULL ) { + return -1; + } + + dp = dest; + sp = src; + n = 0; + while( *sp && n < len-1 ) { + *(dp++) = *(sp++); + n++; + } + + *dp = 0; + return n; +} /* Simple tokeniser. Split a null terminated string into tokens recording the @@ -77,6 +122,43 @@ static int uta_tokenise( char* buf, char** tokens, int max, char sep ) { return n; } +/* + Tokenise and remove matches. + Given a buffer of 'sep' separated tokens, and a list of things, + return up to max tokens with any tokens that matched things in + the list. Toks is the user supplied array of char* which we will + fill in (up to max) with pointers to tokens from buf. This + damages buf, so the caller must dup the string if it must be + preserved for later, original, use. The pointers returned in + toks will reference portions of bufs. + + Returns the number of tokens referenced by toks. +*/ +static int uta_rmip_tokenise( char* buf, if_addrs_t* iplist, char** toks, int max, char sep ) { + int ntoks = 0; // total toks in the original buffer + int pcount = 0; // count after prune + char** all_toks; + int i; + int j; + + + all_toks = malloc( sizeof( char * ) * max ); // refernce to all tokens; we'll prune + pcount = ntoks = uta_tokenise( buf, all_toks, max, sep ); // split them up + j = 0; + if( ntoks > 0 ) { + for( i = 0; i < ntoks; i++ ) { + if( is_this_myip( iplist, all_toks[i] ) ) { + pcount--; // ours, prune + } else { + toks[j++] = all_toks[i]; // not one of ours, keep it + } + } + } + + free( all_toks ); + return pcount; +} + /* Xlate hostname (expected to be name:port) to an IP address that nano will tolerate. We'll use the first address from the list to keep it simple. If the first character @@ -105,9 +187,9 @@ static char* uta_h2ip( char const* hname ) { *(tok++) = 0; } - hent = gethostbyname( dname ); + hent = gethostbyname( dname ); // valgrind will complain that this leaks, but we cannot free it! if( hent == NULL || hent->h_addr_list == NULL ) { - //fprintf( stderr, "[WARN] h2ip: dns lookup failed for: %s\n", dname ); + //rmr_vlog( RMR_VL_WARN, "h2ip: dns lookup failed for: %s\n", dname ); free( dname ); return NULL; } @@ -129,6 +211,7 @@ static char* uta_h2ip( char const* hname ) { } +#ifdef RTG_PUB /* Looks for the environment variable RMR_RTG_SVC which we assume to be name[:port], and does a dns lookup on the name. If the env does not have such a variable, we default to @@ -177,6 +260,7 @@ static int uta_lookup_rtg( uta_ctx_t* ctx ) { return ctx->rtg_addr != NULL; } +#endif /* @@ -241,16 +325,16 @@ static int uta_has_str( char const* buf, char const* str, char sep, int max ) { to the list so that we don't pick up entries from the rtable that are for other processes listening on different interfaces. - The ENV_BIN_IF environment variable may be either an IP address (v6 must be in + The ENV_BIN_IF environment variable may be either an IP address (v6 must be in square braces), or an interface name (e.g. eth0). */ -if_addrs_t* mk_ip_list( char* port ) { +static if_addrs_t* mk_ip_list( char* port ) { if_addrs_t* l; struct ifaddrs *ifs; // pointer to head struct ifaddrs *ele; // pointer into the list char octs[NI_MAXHOST+1]; char wbuf[NI_MAXHOST+128]; - char* fmt; + char* fmt = NULL; // address format (v4 or v6) char* envp; // at the environment var if there char* target_if = NULL; // target interface supplied by ENV_BIND_IF char* tok; @@ -271,7 +355,7 @@ if_addrs_t* mk_ip_list( char* port ) { snprintf( wbuf, sizeof( wbuf ), "%s:%s", envp, port ); // smash port onto the addr as is l->addrs[l->naddrs] = strdup( wbuf ); l->naddrs++; - if( DEBUG ) fprintf( stderr, "[INFO] rmr: using only specific bind interface when searching specific RT entries: %s\n", wbuf ); + if( DEBUG ) rmr_vlog( RMR_VL_INFO, "rmr: using only specific bind interface when searching specific RT entries: %s\n", wbuf ); return l; } @@ -281,30 +365,40 @@ if_addrs_t* mk_ip_list( char* port ) { getifaddrs( &ifs ); for( ele = ifs; ele; ele = ele->ifa_next ) { memset( octs, 0, sizeof( octs ) ); + if( DEBUG ) rmr_vlog( RMR_VL_DEBUG, "checking interface: %s\n", ele->ifa_name ); if( ele && strcmp( ele->ifa_name, "lo" ) && // do NOT capture the loopback interface address (target_if == NULL || strcmp( ele->ifa_name, target_if ) == 0 ) ) { // no target, or matches ENV_BIND_IF target - if( ele->ifa_addr->sa_family == AF_INET ) { - getnameinfo( ele->ifa_addr, sizeof( struct sockaddr_in ), octs, NI_MAXHOST, NULL, 0, NI_NUMERICHOST ); - fmt = "%s:%s"; - } else { - if( ele->ifa_addr->sa_family == AF_INET6 ) { - getnameinfo( ele->ifa_addr, sizeof( struct sockaddr_in6 ), octs, NI_MAXHOST, NULL, 0, NI_NUMERICHOST ); - fmt = "[%s]:%s"; + if( ele->ifa_addr != NULL ) { // possible for some interfaces to not have an address + if( ele->ifa_addr->sa_family == AF_INET ) { + getnameinfo( ele->ifa_addr, sizeof( struct sockaddr_in ), octs, NI_MAXHOST, NULL, 0, NI_NUMERICHOST ); + fmt = "%s:%s"; + } else { + if( ele->ifa_addr->sa_family == AF_INET6 ) { + getnameinfo( ele->ifa_addr, sizeof( struct sockaddr_in6 ), octs, NI_MAXHOST, NULL, 0, NI_NUMERICHOST ); + fmt = "[%s]:%s"; + } else { + if( DEBUG ) rmr_vlog( RMR_VL_DEBUG, "unrecognised IF family (not v4 or v6)\n" ); + continue; + } } - } - - if( *octs ) { - if( (tok = strchr( octs, '%' )) != NULL ) { // for unknown reasons some ip6 addrs have %if-name appended; truncate - *tok = 0; - } - if( l->naddrs < 128 ) { - if( DEBUG ) fprintf( stderr, "[DBUG] capture address: %s: %s\n", ele->ifa_name, octs ); - snprintf( wbuf, sizeof( wbuf ), fmt, octs, port ); // smash port onto the addr - l->addrs[l->naddrs] = strdup( wbuf ); - l->naddrs++; + if( *octs && fmt != NULL ) { // possible that we didn't recognise the format (v4 or v6), don't try if we didn't + if( (tok = strchr( octs, '%' )) != NULL ) { // for unknown reasons some ip6 addrs have %if-name appended; truncate + *tok = 0; + } + if( l->naddrs < 128 ) { + if( DEBUG ) rmr_vlog( RMR_VL_DEBUG, "capture address: %s: %s\n", ele->ifa_name, octs ); + + snprintf( wbuf, sizeof( wbuf ), fmt, octs, port ); // smash port onto the addr + l->addrs[l->naddrs] = strdup( wbuf ); + l->naddrs++; + } + } else { + if( DEBUG ) rmr_vlog( RMR_VL_DEBUG, "unrecognised or no octets octs=%x fmt=%p\n", *octs, fmt ); } + } else { + if( DEBUG ) rmr_vlog( RMR_VL_DEBUG, "no ip address for interface: %s\n", ele->ifa_name ); } } } @@ -323,15 +417,19 @@ if_addrs_t* mk_ip_list( char* port ) { do a straight search through the list. We don't expect this to ever be a higly driven functions so not bothering to optimise. */ -int is_this_myip( if_addrs_t* l, char* addr ) { +static int is_this_myip( if_addrs_t* l, char* addr ) { int i; if( l == NULL ) { return 0; } + if( addr == NULL ) { + return 0; + } + for( i = 0; i < l->naddrs; i++ ) { - if( strcmp( addr, l->addrs[i] ) == 0 ) { + if( l->addrs[i] != NULL && strcmp( addr, l->addrs[i] ) == 0 ) { return 1; } } @@ -411,4 +509,37 @@ static char* get_default_ip( if_addrs_t* iplist ) { return NULL; } +/* + Write all environment variables that we consider to be important to stderr. +*/ +static void uta_dump_env( ) { + char* token; + char* elist[] = { + ENV_BIND_IF, + ENV_RTG_PORT, + ENV_RTG_ADDR, + ENV_SEED_RT, + ENV_SEED_MEMAP, + ENV_RTG_RAW, + ENV_VERBOSE_FILE, + ENV_NAME_ONLY, + ENV_WARNINGS, + ENV_SRC_ID, + ENV_LOG_HR, + ENV_LOG_VLEVEL, + ENV_CTL_PORT, + ENV_RTREQ_FREA + }; + int i; + + for( i = 0; i < sizeof( elist ) / sizeof( char *); i ++ ) { + token = getenv( elist[i] ); + if( token != NULL ) { + rmr_vlog( RMR_VL_INFO, "dump_env: %s = '%s'\n", elist[i], token ); + } else { + rmr_vlog( RMR_VL_INFO, "dump_env: %s = \n", elist[i] ); + } + } +} + #endif