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, ']' );
89 if( !pstr || *pstr != ']' ) {
100 } else { // assume name or v4; point at port if there
101 pstr = strchr( dstr, ':' );
106 ga_flags = AI_ADDRCONFIG; // don't return IPVx addresses unless one such address is configured
109 memset( &hint, 0, sizeof( hint ) );
110 hint.ai_family = family; // AF_INET AF_INET6... let this be 0 to select best based on addr
111 hint.ai_socktype = socktype; // SOCK_DGRAM SOCK_STREAM
112 hint.ai_protocol = proto; // IPPROTO_TCP IPPROTO_UDP
113 hint.ai_flags = ga_flags;
116 rmr_vlog( RMR_VL_DEBUG, "siaddress: calling getaddrinfo flags=%x sockty=%d proto=%d family=%d target=%s host=%s port=%s\n",
117 ga_flags, socktype, proto, family, target, dstr, pstr );
119 if( (error = getaddrinfo( dstr, pstr, &hint, &list )) ) {
120 fprintf( stderr, "sigenaddr: error from getaddrinfo: target=%s host=%s port=%s(port): error=(%d) %s\n",
121 target, dstr, pstr, error, gai_strerror( error ) );
123 *rap = (struct sockaddr *) malloc( list->ai_addrlen ); // alloc a buffer and give address to caller
124 memcpy( *rap, list->ai_addr, list->ai_addrlen );
126 rlen = list->ai_addrlen;
128 freeaddrinfo( list ); // ditch system allocated memory
137 Given a source address convert from one form to another based on type constant.
138 Type const == AC_TODOT Convert source address structure to human readable string.
139 Type const == AC_TOADDR6 Convert source string (host:port or ipv6 address [n:n...:n]:port) to an address struct
140 Type const == AC_TOADDR Convert source string (host:port or ipv4 dotted decimal address) to an address struct
142 extern int SIaddress( void *src, void **dest, int type ) {
143 struct sockaddr_in *addr; // pointer to the address
144 struct sockaddr_in6 *addr6; // ip6 has a different layout
145 unsigned char *num; // pointer at the address number
146 uint8_t* byte; // pointer at the ipv6 address byte values
147 char wbuf[256]; // work buffer
149 int rlen = 0; // return len - len of address struct or string
151 if( src == NULL || dest == NULL ) {
156 case AC_TODOT: // convert from a struct to human readable "dotted decimal"
157 addr = (struct sockaddr_in *) src;
159 if( addr->sin_family == AF_INET6 ) {
160 addr6 = (struct sockaddr_in6 *) src; // really an ip6 struct
161 byte = (uint8_t *) &addr6->sin6_addr;
162 snprintf( wbuf, sizeof( wbuf ), "[%u:%u:%u:%u:%u:%u]:%d",
163 *(byte+0), *(byte+1), *(byte+2),
164 *(byte+3), *(byte+4), *(byte+5) ,
165 (int) ntohs( addr6->sin6_port ) );
167 num = (char *) &addr->sin_addr.s_addr; // point at the long
168 snprintf( wbuf, sizeof( wbuf ), "%u.%u.%u.%u:%d", *(num+0), *(num+1), *(num+2), *(num+3), (int) ntohs(addr->sin_port) );
171 *dest = (void *) strdup( wbuf );
172 rlen = strlen( *dest );
175 case AC_TOADDR6: // from hostname:port string to address for send etc
176 return SIgenaddr( src, IPPROTO_TCP, AF_INET6, SOCK_STREAM, (struct sockaddr **) dest );
178 case AC_TOADDR: // from dotted decimal to address struct ip4
179 return SIgenaddr( src, IPPROTO_TCP, AF_INET, SOCK_STREAM, (struct sockaddr **) dest );