X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=src%2Frmr%2Fsi%2Fsrc%2Fsi95%2Fsiestablish.c;h=794ea0772c53c87853f55bb28ec586ce8e40dfd0;hb=11838bcf76f3614384459cb56e2ce80dea788cef;hp=846faa1c1cd66da1cd6fe9fe9ce6e905dcf8b5a8;hpb=5861625ff2eaf1bd3a69ce488bd7d14f7b402432;p=ric-plt%2Flib%2Frmr.git diff --git a/src/rmr/si/src/si95/siestablish.c b/src/rmr/si/src/si95/siestablish.c index 846faa1..794ea07 100644 --- a/src/rmr/si/src/si95/siestablish.c +++ b/src/rmr/si/src/si95/siestablish.c @@ -25,10 +25,10 @@ * Mnemonic: SIestablish * Abstract:i Prep functions that set up a socket for listening or making a * connection. -* Date: 26 March 1995 -* Author: E. Scott Daniels +* Date: 26 March 1995 +* Author: E. Scott Daniels * -* Modified: 19 Apr 1995 - To keep returned address of the port. +* Modified: 19 Apr 1995 - To keep returned address of the port. * 08 Mar 2007 - conversion for ipv6. * 12 Oct 2020 - split into connect prep and listen prep * functions. @@ -36,7 +36,7 @@ */ -#include "sisetup.h" // include the necessary setup stuff +#include "sisetup.h" // include the necessary setup stuff #include "sitransport.h" #include #include @@ -57,43 +57,39 @@ Family is one of the AF_* constants (AF_ANY, AF_INET or AF_INET6) The address should be one of these forms: - [::1]:port // v6 localhost device (loop back) - localhost:port // v4 or 6 loopback depending on /etc/hosts - 0.0.0.0:port // any interface - addr:port // an address assigned to one of the devices + [::1]:port v6 localhost device (loop back) + localhost:port v4 or 6 loopback depending on /etc/hosts + 0.0.0.0:port any interface + addr:port an address assigned to one of the devices Returns a transport struct which is the main context for the listener. */ -extern struct tp_blk *SIlisten_prep( struct ginfo_blk *gptr, int type, char* abuf, int family ) { - struct tp_blk *tptr; // pointer at new tp block - int status = SI_OK; // processing status - struct sockaddr *addr; // IP address we are requesting - int protocol; // protocol for socket call - char buf[256]; // buffer to build request address in +extern struct tp_blk *SIlisten_prep( int type, char* abuf, int family ) { + struct tp_blk *tptr; // pointer at new tp block + struct sockaddr *addr; // IP address we are requesting int optval = 0; int alen = 0; + int status = SI_OK; // processing status + int protocol; // protocol for socket call - tptr = (struct tp_blk *) SInew( TP_BLK ); // new transport info block + tptr = (struct tp_blk *) SInew( TP_BLK ); // transport info - if( tptr != NULL ) - { + if( tptr != NULL ) { addr = NULL; - switch( type ) // things specifc to tcp or udp - { - case UDP_DEVICE: - tptr->type = SOCK_DGRAM; - protocol = IPPROTO_UDP; - break; - - case TCP_DEVICE: - default: - tptr->type = SOCK_STREAM; - protocol = IPPROTO_TCP; + if( type == UDP_DEVICE ) { + tptr->type = SOCK_DGRAM; + protocol = IPPROTO_UDP; + } else { + tptr->type = SOCK_STREAM; + protocol = IPPROTO_TCP; } - alen = SIgenaddr( abuf, protocol, family, tptr->type, &addr ); // family == 0 for type that suits the address passed in + alen = SIgenaddr( abuf, protocol, family, tptr->type, &addr ); // family == 0 for type that suits the address passed in if( alen <= 0 ) { + if( addr != NULL ) { + free( addr ); // not needed, but scanners complain if we don't overtly do this + } return NULL; } @@ -107,27 +103,50 @@ extern struct tp_blk *SIlisten_prep( struct ginfo_blk *gptr, int type, char* abu status = BIND( tptr->fd, (struct sockaddr *) addr, alen ); if( status == SI_OK ) { - tptr->addr = addr; // save address + tptr->addr = addr; // save address } else { - fprintf( stderr, ">>>>> siestablish: bind failed: fam=%d type=%d pro=%d %s\n", tptr->family, tptr->type, protocol, strerror( errno ) ); + fprintf( stderr, " siestablish: bind failed: fam=%d type=%d pro=%d %s\n", tptr->family, tptr->type, protocol, strerror( errno ) ); close( tptr->fd ); } } else { - status = ! SI_OK; // force bad return later - fprintf( stderr, ">>>>> siestablish: socket not esablished: fam=%d type=%d pro=%d %s\n", tptr->family, tptr->type, protocol, strerror( errno ) ); + status = ! SI_OK; // force bad return later + fprintf( stderr, " siestablish: socket not esablished: fam=%d type=%d pro=%d %s\n", tptr->family, tptr->type, protocol, strerror( errno ) ); } - if( status != SI_OK ) { // socket or bind call failed - clean up stuff - fprintf( stderr, ">>>>> siestablish: bad state -- returning nil pointer\n" ); + if( status != SI_OK ) { // socket or bind call failed - clean up stuff + fprintf( stderr, " siestablish: bad state -- returning nil pointer\n" ); free( addr ); - SItrash( TP_BLK, tptr ); // free the trasnsport block - tptr = NULL; // set to return nothing + SItrash( TP_BLK, tptr ); // free the trasnsport block + tptr = NULL; // set to return nothing } } return tptr; } +/* + Look at the address and determine if the connect attempt to this address must + use safe_connect() rather than the system connect() call. On linux, a smart + connect is needed if the target port is >32K and is even. This makes the assumption + that the local port rage floor is 32K; we could read something in /proc, but + at this point won't bother. Returns true if we determine that it is best to + use safe_connect(). +*/ +static int need_smartc( char* abuf ) { + char* tok; + int state = 1; + int v; + + if( (tok = strchr( abuf, ':')) != NULL ) { + v = atoi( tok+1 ); + if( v < 32767 || v % 2 != 0 ) { + state = 0; + } + } + + return state; +} + /* Prep a socket to use to connect to a listener. Establish a transport block and target address in prep to connect. @@ -139,20 +158,20 @@ extern struct tp_blk *SIlisten_prep( struct ginfo_blk *gptr, int type, char* abu family of 0 (AF_ANY) is usually the best choice. */ extern struct tp_blk *SIconn_prep( struct ginfo_blk *gptr, int type, char *abuf, int family ) { - struct tp_blk *tptr; // pointer at new tp block - struct sockaddr *addr; // IP address we are requesting - int protocol; // protocol for socket call - char buf[256]; // buffer to build request address in + struct tp_blk *tptr; // pointer at new tp block + struct sockaddr *addr; // IP address we are requesting + int protocol; // protocol for socket call + char buf[256]; // buffer to build request address in int optval = 0; int alen = 0; - tptr = (struct tp_blk *) SInew( TP_BLK ); // new transport info block + tptr = (struct tp_blk *) SInew( TP_BLK ); // new transport info block if( tptr != NULL ) { addr = NULL; - switch( type ) // things specifc to tcp or udp + switch( type ) // things specifc to tcp or udp { case UDP_DEVICE: tptr->type = SOCK_DGRAM; @@ -165,11 +184,11 @@ extern struct tp_blk *SIconn_prep( struct ginfo_blk *gptr, int type, char *abuf, protocol = IPPROTO_TCP; } - alen = SIgenaddr( abuf, protocol, family, tptr->type, &addr ); // family == 0 for type that suits the address passed in - if( alen <= 0 ) - { - //fprintf( stderr, ">>>>> siconn_prep: error generating an address struct for %s(abuf) %d(proto) %d(type): %s\n", - // abuf, protocol, tptr->type, strerror( errno ) ); + alen = SIgenaddr( abuf, protocol, family, tptr->type, &addr ); // family == 0 for type that suits the address passed in + if( alen <= 0 ) { + if( addr != NULL ) { // not needed, but scanners complain if we don't overtly do this + free( addr ); + } return NULL; } @@ -179,16 +198,11 @@ extern struct tp_blk *SIconn_prep( struct ginfo_blk *gptr, int type, char *abuf, if( (tptr->fd = SOCKET( tptr->family, tptr->type, protocol )) >= SI_OK ) { optval = 1; - if( SO_REUSEPORT ) { - SETSOCKOPT( tptr->fd, SOL_SOCKET, SO_REUSEPORT, (char *)&optval, sizeof( optval) ); - } - if( gptr->tcp_flags & SI_TF_NODELAY ) { optval = 1; } else { optval = 0; } - //fprintf( stderr, ">>>>> conn_prep: setting no delay = %d\n", optval ); SETSOCKOPT( tptr->fd, SOL_TCP, TCP_NODELAY, (void *)&optval, sizeof( optval) ) ; if( gptr->tcp_flags & SI_TF_FASTACK ) { @@ -196,14 +210,15 @@ extern struct tp_blk *SIconn_prep( struct ginfo_blk *gptr, int type, char *abuf, } else { optval = 0; } - //fprintf( stderr, ">>>>> conn_prep: setting quick ack = %d\n", optval ); SETSOCKOPT( tptr->fd, SOL_TCP, TCP_QUICKACK, (void *)&optval, sizeof( optval) ) ; tptr->paddr = addr; // tuck the remote peer address away + if( need_smartc( abuf ) ) { + tptr->flags |= TPF_SAFEC; + } } else { - //fprintf( stderr, ">>>>> conn_prep: bad socket create: %s\n", strerror( errno ) ); free( addr ); - SItrash( TP_BLK, tptr ); // free the trasnsport block + SItrash( TP_BLK, tptr ); // free the trasnsport block tptr = NULL; // we'll return nil } }