github.com/afumu/libc@v0.0.6/musl/src/network/getnameinfo.c (about)

     1  #include <netdb.h>
     2  #include <limits.h>
     3  #include <string.h>
     4  #include <stdio.h>
     5  #include <stdlib.h>
     6  #include <sys/socket.h>
     7  #include <netinet/in.h>
     8  #include <arpa/inet.h>
     9  #include <net/if.h>
    10  #include <ctype.h>
    11  #include <resolv.h>
    12  #include "lookup.h"
    13  #include "stdio_impl.h"
    14  
    15  #define PTR_MAX (64 + sizeof ".in-addr.arpa")
    16  #define RR_PTR 12
    17  
    18  static char *itoa(char *p, unsigned x) {
    19  	p += 3*sizeof(int);
    20  	*--p = 0;
    21  	do {
    22  		*--p = '0' + x % 10;
    23  		x /= 10;
    24  	} while (x);
    25  	return p;
    26  }
    27  
    28  static void mkptr4(char *s, const unsigned char *ip)
    29  {
    30  	sprintf(s, "%d.%d.%d.%d.in-addr.arpa",
    31  		ip[3], ip[2], ip[1], ip[0]);
    32  }
    33  
    34  static void mkptr6(char *s, const unsigned char *ip)
    35  {
    36  	static const char xdigits[] = "0123456789abcdef";
    37  	int i;
    38  	for (i=15; i>=0; i--) {
    39  		*s++ = xdigits[ip[i]&15]; *s++ = '.';
    40  		*s++ = xdigits[ip[i]>>4]; *s++ = '.';
    41  	}
    42  	strcpy(s, "ip6.arpa");
    43  }
    44  
    45  static void reverse_hosts(char *buf, const unsigned char *a, unsigned scopeid, int family)
    46  {
    47  	char line[512], *p, *z;
    48  	unsigned char _buf[1032], atmp[16];
    49  	struct address iplit;
    50  	//TODO FILE _f, *f = __fopen_rb_ca("/etc/hosts", &_f, _buf, sizeof _buf);
    51  	FILE *f = fopen("/etc/hosts", "rb");
    52  	if (!f) return;
    53  	if (family == AF_INET) {
    54  		memcpy(atmp+12, a, 4);
    55  		memcpy(atmp, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
    56  		a = atmp;
    57  	}
    58  	while (fgets(line, sizeof line, f)) {
    59  		if ((p=strchr(line, '#'))) *p++='\n', *p=0;
    60  
    61  		for (p=line; *p && !isspace(*p); p++);
    62  		*p++ = 0;
    63  		if (__lookup_ipliteral(&iplit, line, AF_UNSPEC)<=0)
    64  			continue;
    65  
    66  		if (iplit.family == AF_INET) {
    67  			memcpy(iplit.addr+12, iplit.addr, 4);
    68  			memcpy(iplit.addr, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
    69  			iplit.scopeid = 0;
    70  		}
    71  
    72  		if (memcmp(a, iplit.addr, 16) || iplit.scopeid != scopeid)
    73  			continue;
    74  			
    75  		for (; *p && isspace(*p); p++);
    76  		for (z=p; *z && !isspace(*z); z++);
    77  		*z = 0;
    78  		if (z-p < 256) {
    79  			memcpy(buf, p, z-p+1);
    80  			break;
    81  		}
    82  	}
    83  	//TODO __fclose_ca(f);
    84  	fclose(f);
    85  }
    86  
    87  static void reverse_services(char *buf, int port, int dgram)
    88  {
    89  	abort(); //TODO-
    90  	// unsigned long svport;
    91  	// char line[128], *p, *z;
    92  	// unsigned char _buf[1032];
    93  	// FILE _f, *f = __fopen_rb_ca("/etc/services", &_f, _buf, sizeof _buf);
    94  	// if (!f) return;
    95  	// while (fgets(line, sizeof line, f)) {
    96  	// 	if ((p=strchr(line, '#'))) *p++='\n', *p=0;
    97  
    98  	// 	for (p=line; *p && !isspace(*p); p++);
    99  	// 	if (!*p) continue;
   100  	// 	*p++ = 0;
   101  	// 	svport = strtoul(p, &z, 10);
   102  
   103  	// 	if (svport != port || z==p) continue;
   104  	// 	if (dgram && strncmp(z, "/udp", 4)) continue;
   105  	// 	if (!dgram && strncmp(z, "/tcp", 4)) continue;
   106  	// 	if (p-line > 32) continue;
   107  
   108  	// 	memcpy(buf, line, p-line);
   109  	// 	break;
   110  	// }
   111  	// __fclose_ca(f);
   112  }
   113  
   114  static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet)
   115  {
   116  	abort(); //TODO-
   117  	// if (rr != RR_PTR) return 0;
   118  	// if (__dn_expand(packet, (const unsigned char *)packet + 512,
   119  	//     data, c, 256) <= 0)
   120  	// 	*(char *)c = 0;
   121  	// return 0;
   122  	
   123  }
   124  
   125  int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl,
   126  	char *restrict node, socklen_t nodelen,
   127  	char *restrict serv, socklen_t servlen,
   128  	int flags)
   129  {
   130  	char ptr[PTR_MAX];
   131  	char buf[256], num[3*sizeof(int)+1];
   132  	int af = sa->sa_family;
   133  	unsigned char *a;
   134  	unsigned scopeid;
   135  
   136  	switch (af) {
   137  	case AF_INET:
   138  		a = (void *)&((struct sockaddr_in *)sa)->sin_addr;
   139  		if (sl < sizeof(struct sockaddr_in)) return EAI_FAMILY;
   140  		mkptr4(ptr, a);
   141  		scopeid = 0;
   142  		break;
   143  	case AF_INET6:
   144  		a = (void *)&((struct sockaddr_in6 *)sa)->sin6_addr;
   145  		if (sl < sizeof(struct sockaddr_in6)) return EAI_FAMILY;
   146  		if (memcmp(a, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12))
   147  			mkptr6(ptr, a);
   148  		else
   149  			mkptr4(ptr, a+12);
   150  		scopeid = ((struct sockaddr_in6 *)sa)->sin6_scope_id;
   151  		break;
   152  	default:
   153  		return EAI_FAMILY;
   154  	}
   155  
   156  	if (node && nodelen) {
   157  		buf[0] = 0;
   158  		if (!(flags & NI_NUMERICHOST)) {
   159  			reverse_hosts(buf, a, scopeid, af);
   160  		}
   161  		if (!*buf && !(flags & NI_NUMERICHOST)) {
   162  			abort(); //TODO-
   163  			// unsigned char query[18+PTR_MAX], reply[512];
   164  			// int qlen = __res_mkquery(0, ptr, 1, RR_PTR,
   165  			// 	0, 0, 0, query, sizeof query);
   166  			// query[3] = 0; /* don't need AD flag */
   167  			// int rlen = __res_send(query, qlen, reply, sizeof reply);
   168  			// buf[0] = 0;
   169  			// if (rlen > 0)
   170  			// 	__dns_parse(reply, rlen, dns_parse_callback, buf);
   171  		}
   172  		if (!*buf) {
   173  			if (flags & NI_NAMEREQD) return EAI_NONAME;
   174  			inet_ntop(af, a, buf, sizeof buf);
   175  			if (scopeid) {
   176  				abort(); //TODO-
   177  				// char *p = 0, tmp[IF_NAMESIZE+1];
   178  				// if (!(flags & NI_NUMERICSCOPE) &&
   179  				//     (IN6_IS_ADDR_LINKLOCAL(a) ||
   180  				//      IN6_IS_ADDR_MC_LINKLOCAL(a)))
   181  				// 	p = if_indextoname(scopeid, tmp+1);
   182  				// if (!p)
   183  				// 	p = itoa(num, scopeid);
   184  				// *--p = '%';
   185  				// strcat(buf, p);
   186  			}
   187  		}
   188  		if (strlen(buf) >= nodelen) return EAI_OVERFLOW;
   189  		strcpy(node, buf);
   190  	}
   191  
   192  	if (serv && servlen) {
   193  		char *p = buf;
   194  		int port = ntohs(((struct sockaddr_in *)sa)->sin_port);
   195  		buf[0] = 0;
   196  		if (!(flags & NI_NUMERICSERV))
   197  			reverse_services(buf, port, flags & NI_DGRAM);
   198  		if (!*p)
   199  			p = itoa(num, port);
   200  		if (strlen(p) >= servlen)
   201  			return EAI_OVERFLOW;
   202  		strcpy(serv, p);
   203  	}
   204  
   205  	return 0;
   206  }