Line data Source code
1 : #define _GNU_SOURCE /* inet_aton */ 2 : #include <sys/socket.h> 3 : #include <netinet/in.h> 4 : #include <netdb.h> 5 : #include <net/if.h> 6 : #include <arpa/inet.h> 7 : #include <limits.h> 8 : #include <stdlib.h> 9 : #include <string.h> 10 : #include <ctype.h> 11 : #include "../../util/cstr/fd_cstr.h" 12 : #include "fd_lookup.h" 13 : 14 : int 15 : fd_lookup_ipliteral( struct address buf[ static 1 ], 16 : char const * name, 17 0 : int family ) { 18 0 : struct in_addr a4; 19 0 : struct in6_addr a6; 20 0 : if( inet_aton( name, &a4 ) > 0 ) { 21 0 : if( family == AF_INET6 ) /* wrong family */ 22 0 : return FD_EAI_NODATA; 23 0 : memcpy( &buf[0].addr, &a4, sizeof(a4) ); 24 0 : buf[0].family = AF_INET; 25 0 : buf[0].scopeid = 0; 26 0 : return 1; 27 0 : } 28 : 29 0 : char tmp[64]; 30 0 : char *p = strchr( name, '%' ), *z; 31 0 : ulong scopeid = 0; 32 0 : if( p && p-name < 64 ) { 33 0 : memcpy( tmp, name, (ulong)( p-name ) ); 34 0 : tmp[p-name] = 0; 35 0 : name = tmp; 36 0 : } 37 : 38 0 : if( inet_pton( AF_INET6, name, &a6 ) <= 0 ) 39 0 : return 0; 40 0 : if( family == AF_INET ) /* wrong family */ 41 0 : return FD_EAI_NODATA; 42 : 43 0 : memcpy( &buf[0].addr, &a6, sizeof a6 ); 44 0 : buf[0].family = AF_INET6; 45 0 : if( p ) { 46 0 : if( fd_isdigit( *++p ) ) scopeid = strtoul( p, &z, 10 ); 47 0 : else z = p-1; 48 0 : if( *z ) { 49 0 : if( !IN6_IS_ADDR_LINKLOCAL(&a6) && 50 0 : !IN6_IS_ADDR_MC_LINKLOCAL(&a6) ) 51 0 : return FD_EAI_NONAME; 52 0 : scopeid = if_nametoindex( p ); 53 0 : if( !scopeid ) return FD_EAI_NONAME; 54 0 : } 55 0 : if( scopeid > UINT_MAX ) return FD_EAI_NONAME; 56 0 : } 57 0 : buf[0].scopeid = (uint)scopeid; 58 0 : return 1; 59 0 : }