X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=src%2Frmr%2Fsi%2Fsrc%2Fsi95%2Fsiterm.c;h=ce4874882dfc562ab3c6385b7b1adc3f88dbd834;hb=69d7bfd7bbe046dda3afa50e0362448d60301258;hp=8b732f6daa2db1eeebb1ae1396cf94a7aa221878;hpb=5861625ff2eaf1bd3a69ce488bd7d14f7b402432;p=ric-plt%2Flib%2Frmr.git diff --git a/src/rmr/si/src/si95/siterm.c b/src/rmr/si/src/si95/siterm.c index 8b732f6..ce48748 100644 --- a/src/rmr/si/src/si95/siterm.c +++ b/src/rmr/si/src/si95/siterm.c @@ -23,7 +23,7 @@ * Mnemonic: SIterm * Abstract: Manage the transport provider block information relating to * the need to terminate the session. The block is left in the -* list; it is unsafe to clean the lsit up outside of the SIwait +* list; it is unsafe to clean the lsit up outside of the SIwait * thread. When safe, the SIrm_tpb() function can be called to * do the rest of the work that was originally done by SIterm. * @@ -32,19 +32,47 @@ * ************************************************************************** */ -#include "sisetup.h" // get the setup stuff +#include "sisetup.h" // get the setup stuff #include "sitransport.h" + +/* + Abort the connection in such a way that there is no resulting time-wait state. + This should be used cautiously but is needed for situations like when the Linux + connect() system call manages to connect us to ourselves through the even number + port bug. + + This needs a real file desc as there may not yet be a transport block when + the connection may need to be aborted. For this reason, the function name is + lower case indicating that user programmes are discouraged from using this + function directly. +*/ +extern void siabort_conn( int fd ) { + struct linger opt_val; // value passed as option to set call + + opt_val.l_onoff = 1; // MUST set linger on with a zero len timeout + opt_val.l_linger = 0; + + setsockopt( fd, SOL_SOCKET, SO_LINGER, &opt_val, sizeof( opt_val ) ); // disable linger to prevent time-wait + CLOSE( fd ); // close will now abort and not result in time-wait (do NOT use shutdown() first!) +} + /* Close the FD and mark the transport block as unusable/closed. Removal of the block from the list is safe only from the siwait - thread. + thread. If the abort flag is set in the transport block, then the + connection is aborted (reset). */ extern void SIterm( struct ginfo_blk* gptr, struct tp_blk *tpptr ) { if( tpptr != NULL ) { if( tpptr->fd >= 0 ) { - CLOSE( tpptr->fd ); + if( tpptr->flags & TPF_ABORT ) { + siabort_conn( tpptr->fd ); + } else { + CLOSE( tpptr->fd ); + } + if( tpptr->fd < MAX_FDS ) { gptr->tp_map[tpptr->fd] = NULL; // drop reference } @@ -57,25 +85,25 @@ extern void SIterm( struct ginfo_blk* gptr, struct tp_blk *tpptr ) { /* It is safe to remove the block from the list; if it was in the list - in the first place. + in the first place. */ extern void SIrm_tpb( struct ginfo_blk *gptr, struct tp_blk *tpptr ) { if( tpptr != NULL ) { if( tpptr->prev != NULL || tpptr->next != NULL ) { // in the list - if( tpptr->prev != NULL ) { // remove from the list - tpptr->prev->next = tpptr->next; // point previous at the next + if( tpptr->prev != NULL ) { // remove from the list + tpptr->prev->next = tpptr->next; // point previous at the next } else { - gptr->tplist = tpptr->next; // this was head, make next new head + gptr->tplist = tpptr->next; // this was head, make next new head } - + if( tpptr->next != NULL ) { - tpptr->next->prev = tpptr->prev; // point next one back behind this one + tpptr->next->prev = tpptr->prev; // point next one back behind this one } } - free( tpptr->addr ); // release the address bufers + free( tpptr->addr ); // release the address bufers free( tpptr->paddr ); - free( tpptr ); // and release the block + free( tpptr ); // and release the block } }