| #include <netdb.h> |
| #include <limits.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <sys/socket.h> |
| #include <netinet/in.h> |
| #include <arpa/inet.h> |
| #include "__dns.h" |
| |
| int getnameinfo(const struct sockaddr *sa, socklen_t sl, |
| char *node, socklen_t nodelen, |
| char *serv, socklen_t servlen, |
| int flags) |
| { |
| char buf[256]; |
| unsigned char reply[512]; |
| int af = sa->sa_family; |
| unsigned char *a; |
| |
| switch (af) { |
| case AF_INET: |
| a = (void *)&((struct sockaddr_in *)sa)->sin_addr; |
| if (sl != sizeof(struct sockaddr_in)) return EAI_FAMILY; |
| break; |
| case AF_INET6: |
| a = (void *)&((struct sockaddr_in6 *)sa)->sin6_addr; |
| if (sl != sizeof(struct sockaddr_in6)) return EAI_FAMILY; |
| break; |
| default: |
| return EAI_FAMILY; |
| } |
| |
| if (node && nodelen) { |
| if ((flags & NI_NUMERICHOST) |
| || __dns_query(reply, a, af, 1) <= 0 |
| || __dns_get_rr(buf, 0, 256, 1, reply, RR_PTR, 1) <= 0) |
| { |
| if (flags & NI_NAMEREQD) return EAI_NONAME; |
| inet_ntop(af, a, buf, sizeof buf); |
| } |
| if (strlen(buf) >= nodelen) return EAI_OVERFLOW; |
| strcpy(node, buf); |
| } |
| |
| if (serv && servlen) { |
| if (snprintf(buf, sizeof buf, "%d", |
| ntohs(((struct sockaddr_in *)sa)->sin_port))>=servlen) |
| return EAI_OVERFLOW; |
| strcpy(serv, buf); |
| } |
| |
| return 0; |
| } |