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 will convert a sockaddr_in structure to a
26 * dotted decimal address, or visa versa.
27 * If type == AC_TOADDR the src string may be:
28 * xxx.xxx.xxx.xxx.portnumber or host-name.portnumber
29 * xxx.xxx.xxx.xxx.service[.protocol] or hostname;service[;protocol]
30 * if protocol is not supplied then tcp is assumed.
31 * hostname may be something like godzilla.moviemania.com
32 * Parms: src - Pointer to source buffer
33 * dest- Pointer to dest buffer pointer
34 * type- Type of conversion AC_TODOT converts sockaddr to human readable. AC_TOADDR
35 * converts character buffer to sockaddr.
37 * Date: 19 January 1995
38 * Author: E. Scott Daniels
40 * Modified: 22 Mar 1995 - To add support for ipx addresses.
41 * 18 Oct 2020 - drop old port separator (;)
43 * CAUTION: The netdb.h header file is a bit off when it sets up the
44 * hostent structure. It claims that h_addr_list is a pointer
45 * to character pointers, but it is really a pointer to a list
46 * of pointers to integers!!!
48 ***************************************************************************
50 #include "sisetup.h" // get necessary defs and other stuff
56 target: buffer with address e.g. 192.168.0.1:4444 :4444 (listen) [::1]4444
57 family: PF_INET[6] (let it be 0 to select based on addr in buffer
58 proto: IPPROTO_TCP IPPROTO_UDP
59 type: SOCK_STREAM SOCK_DGRAM
61 returns length of struct pointed to by rap (return addr blockpointer)
63 extern int SIgenaddr( char *target, int proto, int family, int socktype, struct sockaddr **rap ) {
64 struct addrinfo hint; // hints to give getaddrinfo
65 struct addrinfo *list = NULL; // list of what comes back
66 int ga_flags = 0; // flags to pass to getaddrinfo in hints
68 int rlen = 0; // length of the addr that rap points to on return
69 char *pstr; // port string
70 char *dstr; // a copy of the users target that we can destroy
71 char* fptr; // ptr we allocated and need to free (we may adjust dstr)
73 fptr = dstr = strdup( (char *) target ); // copy so we can destroy it with strtok
74 *rap = NULL; // ensure null incase something breaks
76 while( isspace( *dstr ) ) {
80 if( *dstr == ':' ) { // user passed in :port -- so we assume this is for bind
84 ga_flags = AI_PASSIVE;
86 if( *dstr == '[' ) { // strip [ and ] from v6 and point pstring if port there
88 pstr = strchr( dstr, ']' );
99 } else { // assume name or v4; point at port if there
100 pstr = strchr( dstr, ':' );
105 ga_flags = AI_ADDRCONFIG; // don't return IPVx addresses unless one such address is configured
108 memset( &hint, 0, sizeof( hint ) );
109 hint.ai_family = family; // AF_INET AF_INET6... let this be 0 to select best based on addr
110 hint.ai_socktype = socktype; // SOCK_DGRAM SOCK_STREAM
111 hint.ai_protocol = proto; // IPPORTO_TCP IPPROTO_UDP
112 hint.ai_flags = ga_flags;
115 rmr_vlog( RMR_VL_DEBUG, "siaddress: calling getaddrinfo flags=%x proto=%d family=%d target=%s host=%s port=%s\n",
116 ga_flags, proto, family, target, dstr, pstr );
118 if( (error = getaddrinfo( dstr, pstr, &hint, &list )) ) {
119 fprintf( stderr, "error from getaddrinfo: target=%s host=%s port=%s(port): error=(%d) %s\n", target, dstr, pstr, error, gai_strerror( error ) );
121 *rap = (struct sockaddr *) malloc( list->ai_addrlen ); // alloc a buffer and give address to caller
122 memcpy( *rap, list->ai_addr, list->ai_addrlen );
124 rlen = list->ai_addrlen;
126 freeaddrinfo( list ); // ditch system allocated memory
135 Given a source address convert from one form to another based on type constant.
136 Type const == AC_TODOT Convert source address structure to human readable string.
137 Type const == AC_TOADDR6 Convert source string (host:port or ipv6 address [n:n...:n]:port) to an address struct
138 Type const == AC_TOADDR Convert source string (host:port or ipv4 dotted decimal address) to an address struct
140 extern int SIaddress( void *src, void **dest, int type ) {
141 struct sockaddr_in *addr; // pointer to the address
142 unsigned char *num; // pointer at the address number
143 char wbuf[256]; // work buffer
145 int rlen = 0; // return len - len of address struct or string
148 case AC_TODOT: // convert from a struct to human readable "dotted decimal"
149 addr = (struct sockaddr_in *) src;
150 num = (char *) &addr->sin_addr.s_addr; // point at the long
152 if( addr->sin_family == AF_INET6 ) {
153 sprintf( wbuf, "[%u:%u:%u:%u:%u:%u]:%d",
154 *(num+0), *(num+1), *(num+2),
155 *(num+3), *(num+4), *(num+5) ,
156 (int) ntohs( addr->sin_port ) );
158 sprintf( wbuf, "%u.%u.%u.%u;%d", *(num+0), *(num+1), *(num+2), *(num+3), (int) ntohs(addr->sin_port) );
161 *dest = (void *) strdup( wbuf );
162 rlen = strlen( *dest );
165 case AC_TOADDR6: // from hostname;port string to address for send etc
166 return SIgenaddr( src, PF_INET6, IPPROTO_TCP, SOCK_STREAM, (struct sockaddr **) dest );
169 case AC_TOADDR: // from dotted decimal to address struct ip4
170 return SIgenaddr( src, PF_INET, IPPROTO_TCP, SOCK_STREAM, (struct sockaddr **) dest );