X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=src%2Frmr%2Fcommon%2Fsrc%2Ftools_static.c;h=b4245cdab3f669b66fc55d446ebdfbac40df31fa;hb=9c923bcc9322c22220b574671c7b46f10008c614;hp=8e615af6dd52dca18a34ac447a84af5dcb51293e;hpb=68c1ab2191d9959fde0bd275a560f7c9cf6df485;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 8e615af..b4245cd 100644 --- a/src/rmr/common/src/tools_static.c +++ b/src/rmr/common/src/tools_static.c @@ -22,6 +22,7 @@ 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 @@ -50,6 +51,11 @@ #include #include +// --- some protos needed for better organisation -------- +int is_this_myip( if_addrs_t* l, char* addr ); + + +// ---------------------------------------------------------------------------------- /* Simple tokeniser. Split a null terminated string into tokens recording the @@ -77,6 +83,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 @@ -107,7 +150,7 @@ static char* uta_h2ip( char const* hname ) { hent = gethostbyname( dname ); 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; } @@ -237,9 +280,12 @@ static int uta_has_str( char const* buf, char const* str, char sep, int max ) { that could be in the route table. If the environment variable which limits the binding of our listen port - to a single interface (ENV_BIND_IF) then ONLY that address is added to - the list so that we don't pick up entries from the rtable that are for other + to a single interface (ENV_BIND_IF) then ONLY that interface/address is added + 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 + square braces), or an interface name (e.g. eth0). */ if_addrs_t* mk_ip_list( char* port ) { if_addrs_t* l; @@ -249,7 +295,8 @@ if_addrs_t* mk_ip_list( char* port ) { char wbuf[NI_MAXHOST+128]; char* fmt; char* envp; // at the environment var if there - + char* target_if = NULL; // target interface supplied by ENV_BIND_IF + char* tok; if( (l = (if_addrs_t *) malloc( sizeof( if_addrs_t ) )) == NULL ) { @@ -263,30 +310,42 @@ if_addrs_t* mk_ip_list( char* port ) { } if( (envp = getenv( ENV_BIND_IF )) != NULL ) { - 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 ); - return l; + if( isdigit( *envp ) || *envp == '[' ) { // ip address given and not device name + 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 ) rmr_vlog( RMR_VL_INFO, "rmr: using only specific bind interface when searching specific RT entries: %s\n", wbuf ); + return l; + } + + target_if = envp; // device name given, suss it out below } getifaddrs( &ifs ); for( ele = ifs; ele; ele = ele->ifa_next ) { - *octs = 0; - - if( ele && strcmp( ele->ifa_name, "lo" ) ) { - 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"; + memset( octs, 0, sizeof( octs ) ); + 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 != 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"; + } } } 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 ) 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++; @@ -316,8 +375,12 @@ int is_this_myip( if_addrs_t* l, char* addr ) { 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; } } @@ -380,4 +443,21 @@ static int has_myip( char const* buf, if_addrs_t* list, char sep, int max ) { return rc; } +/* + Given a list manager block, return the default IP address. + For now, that is just the first address on the list which + easily could be non-deterministic and change with each restart + of the application if a specific interface is not provided via + the environment variable (ENV_BIND_IF) and if there is more than + one device available on the container/physical host. +*/ +static char* get_default_ip( if_addrs_t* iplist ) { + + if( iplist != NULL && iplist->naddrs > 0 && iplist->addrs != NULL ) { + return strdup( iplist->addrs[0] ); + } + + return NULL; +} + #endif