Ensure RT incremental update not applied early
[ric-plt/lib/rmr.git] / src / rmr / common / src / tools_static.c
index 3aa5c43..2d2cc22 100644 (file)
@@ -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.
@@ -29,6 +29,9 @@
 
                                        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
 */
 #include <netdb.h>
 
 // --- some protos needed for better organisation --------
-int is_this_myip( if_addrs_t* l, char* addr );
+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
        pointers in the tokens array provided.  Tokens MUST be large enough. Max is
@@ -88,9 +127,9 @@ static int uta_tokenise( char* buf, char** tokens, int max, char sep ) {
        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 
+       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.
@@ -102,7 +141,7 @@ static int uta_rmip_tokenise( char* buf, if_addrs_t* iplist, char** toks, int ma
        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;
@@ -148,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, "[WRN] 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;
        }
@@ -172,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
@@ -220,6 +260,7 @@ static int uta_lookup_rtg( uta_ctx_t* ctx ) {
 
        return ctx->rtg_addr != NULL;
 }
+#endif
 
 
 /*
@@ -284,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;
@@ -314,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;
                }
 
@@ -324,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( *octs ) {
-                               if( (tok = strchr( octs, '%' )) != NULL ) {                     // for unknown reasons some ip6 addrs have %if-name appended; truncate
-                                       *tok = 0;
+                       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( 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 );
                        }
                }
        }
@@ -366,7 +417,7 @@ 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 ) {
@@ -458,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 = <unset>\n", elist[i] );
+               }
+       }
+}
+
 #endif