1 // vim: noet sw=4 ts=4:
3 ==================================================================================
4 Copyright (c) 2020 Nokia
5 Copyright (c) 2020 AT&T Intellectual Property.
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
11 http://www.apache.org/licenses/LICENSE-2.0
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18 ==================================================================================
22 ******************************************************************************
25 * Abstract: This routine allows the user application to close a port
26 * associated with a file descriptor. The port is unbound from
27 * the transport providor even if it is marked as a listen
28 * port. If the fd passed in is less than 0 this routine assumes
29 * that the UDP port opened during init is to be closed (user never
30 * receives a fd on this one).
31 * Parms: gptr - The pointer to the ginfo block (SIHANDLE to the user)
33 * Returns: SI_OK if all goes well, SI_ERROR with SIerrno set if there is
35 * Date: 3 February 1995
36 * Author: E. Scott Daniels
38 * Modified:i 19 Feb 1995 - To set TP blk to drain if output pending.
39 * 10 May 1995 - To change SOCK_RAW to SOCK_DGRAM
40 * 22 Feb 2002 - To accept TCP_LISTEN_PORT or UDP_PORT as fd
41 ******************************************************************************
45 extern int SIclose( struct ginfo_blk *gptr, int fd ) {
46 struct tp_blk *tpptr; // pointer into tp list
47 int status = SI_ERROR; // status of processing
50 if( fd >= 0 ) { // if caller knew the fd number
51 if( fd < MAX_FDS ) { // straight from map if possible
52 tpptr = gptr->tp_map[fd];
54 // future: need to lock the list or switch to gmax hash
55 for( tpptr = gptr->tplist; tpptr != NULL && tpptr->fd != fd; tpptr = tpptr->next ); // find the tppblock to close
57 } else { // user did not know the fd - find first Listener or UDP tp blk
58 if( fd == TCP_LISTEN_PORT ) { // close first tcp listen port; else first udp
59 for( tpptr = gptr->tplist; tpptr != NULL && !(tpptr->flags&& TPF_LISTENFD); tpptr = tpptr->next );
61 for( tpptr = gptr->tplist; tpptr != NULL && tpptr->type != SOCK_DGRAM; tpptr = tpptr->next );
66 if( tpptr->squeue == NULL ) { // if nothing is queued to send...
67 tpptr->flags |= TPF_UNBIND; // ensure port is unbound from tp
68 tpptr->flags |= TPF_DELETE;
71 setsockopt(tpptr->fd, SOL_SOCKET, SO_LINGER, (char *)&x, sizeof( x ) ) ;
74 SIterm( gptr, tpptr ); // close the fd and mark the block as deletable
76 tpptr->flags |= TPF_DRAIN; // stuff on queue, must drain before closing
79 status = SI_OK; // give caller a good status
80 } // end if we found a tpptr
83 return status; // send the status back to the caller