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 ==================================================================================
23 *-----------------------------------------------------------------------------------
25 * Mnemonic: SIestablish
26 * Abstract:i Prep functions that set up a socket for listening or making a
29 * Author: E. Scott Daniels
31 * Modified: 19 Apr 1995 - To keep returned address of the port.
32 * 08 Mar 2007 - conversion for ipv6.
33 * 12 Oct 2020 - split into connect prep and listen prep
35 *-----------------------------------------------------------------------------------
39 #include "sisetup.h" // include the necessary setup stuff
40 #include "sitransport.h"
42 #include <netinet/tcp.h>
45 #define SO_REUSEPORT 0
49 Prep a socket for "listening."
50 This routine will open a socket and bind an address to it in
51 preparation for listening for connections or inbound UDP
52 datagrams. A file descriptor for the socket is captured and all
53 related information is placed into a transport provider (tp) block.
55 Type is the SI constant UDP_DEVICE or TCP_DEVICE
56 abuf points to the address that is to be bound to the socket.
57 Family is one of the AF_* constants (AF_ANY, AF_INET or AF_INET6)
59 The address should be one of these forms:
60 [::1]:port // v6 localhost device (loop back)
61 localhost:port // v4 or 6 loopback depending on /etc/hosts
62 0.0.0.0:port // any interface
63 addr:port // an address assigned to one of the devices
65 Returns a transport struct which is the main context for the listener.
67 extern struct tp_blk *SIlisten_prep( struct ginfo_blk *gptr, int type, char* abuf, int family ) {
68 struct tp_blk *tptr; // pointer at new tp block
69 int status = SI_OK; // processing status
70 struct sockaddr *addr; // IP address we are requesting
71 int protocol; // protocol for socket call
72 char buf[256]; // buffer to build request address in
76 tptr = (struct tp_blk *) SInew( TP_BLK ); // new transport info block
82 switch( type ) // things specifc to tcp or udp
85 tptr->type = SOCK_DGRAM;
86 protocol = IPPROTO_UDP;
91 tptr->type = SOCK_STREAM;
92 protocol = IPPROTO_TCP;
95 alen = SIgenaddr( abuf, protocol, family, tptr->type, &addr ); // family == 0 for type that suits the address passed in
100 tptr->family = addr->sa_family;
102 if( (tptr->fd = SOCKET( tptr->family, tptr->type, protocol )) >= SI_OK ) {
105 SETSOCKOPT(tptr->fd, SOL_SOCKET, SO_REUSEPORT, (char *)&optval, sizeof( optval) ) ;
108 status = BIND( tptr->fd, (struct sockaddr *) addr, alen );
109 if( status == SI_OK ) {
110 tptr->addr = addr; // save address
112 fprintf( stderr, ">>>>> siestablish: bind failed: fam=%d type=%d pro=%d %s\n", tptr->family, tptr->type, protocol, strerror( errno ) );
116 status = ! SI_OK; // force bad return later
117 fprintf( stderr, ">>>>> siestablish: socket not esablished: fam=%d type=%d pro=%d %s\n", tptr->family, tptr->type, protocol, strerror( errno ) );
120 if( status != SI_OK ) { // socket or bind call failed - clean up stuff
121 fprintf( stderr, ">>>>> siestablish: bad state -- returning nil pointer\n" );
123 SItrash( TP_BLK, tptr ); // free the trasnsport block
124 tptr = NULL; // set to return nothing
132 Prep a socket to use to connect to a listener.
133 Establish a transport block and target address in prep to connect.
134 Type is the SI constant UDP_DEVICE or TCP_DEVICE. The abuf pointer
135 should point to either a name:port or IP:port string. Family should
136 be 0 to select the family best suited to the address provided, or
137 any (v4 or v6) if the address is a name. If a perticular type is
138 desired family should be either AF_INET or AF_INET6. Using a
139 family of 0 (AF_ANY) is usually the best choice.
141 extern struct tp_blk *SIconn_prep( struct ginfo_blk *gptr, int type, char *abuf, int family ) {
142 struct tp_blk *tptr; // pointer at new tp block
143 struct sockaddr *addr; // IP address we are requesting
144 int protocol; // protocol for socket call
145 char buf[256]; // buffer to build request address in
149 tptr = (struct tp_blk *) SInew( TP_BLK ); // new transport info block
155 switch( type ) // things specifc to tcp or udp
158 tptr->type = SOCK_DGRAM;
159 protocol = IPPROTO_UDP;
164 tptr->type = SOCK_STREAM;
165 protocol = IPPROTO_TCP;
168 alen = SIgenaddr( abuf, protocol, family, tptr->type, &addr ); // family == 0 for type that suits the address passed in
171 //fprintf( stderr, ">>>>> siconn_prep: error generating an address struct for %s(abuf) %d(proto) %d(type): %s\n",
172 // abuf, protocol, tptr->type, strerror( errno ) );
176 tptr->family = addr->sa_family;
179 if( (tptr->fd = SOCKET( tptr->family, tptr->type, protocol )) >= SI_OK ) {
183 SETSOCKOPT( tptr->fd, SOL_SOCKET, SO_REUSEPORT, (char *)&optval, sizeof( optval) );
186 if( gptr->tcp_flags & SI_TF_NODELAY ) {
191 //fprintf( stderr, ">>>>> conn_prep: setting no delay = %d\n", optval );
192 SETSOCKOPT( tptr->fd, SOL_TCP, TCP_NODELAY, (void *)&optval, sizeof( optval) ) ;
194 if( gptr->tcp_flags & SI_TF_FASTACK ) {
199 //fprintf( stderr, ">>>>> conn_prep: setting quick ack = %d\n", optval );
200 SETSOCKOPT( tptr->fd, SOL_TCP, TCP_QUICKACK, (void *)&optval, sizeof( optval) ) ;
202 tptr->paddr = addr; // tuck the remote peer address away
204 //fprintf( stderr, ">>>>> conn_prep: bad socket create: %s\n", strerror( errno ) );
206 SItrash( TP_BLK, tptr ); // free the trasnsport block
207 tptr = NULL; // we'll return nil