summaryrefslogtreecommitdiff
path: root/sys/src/ape/lib/bsd/getnameinfo.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2013-03-31 18:52:45 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2013-03-31 18:52:45 +0200
commitb6dc4ba5a44a2ed2a68266598ceb28b7a7d51af2 (patch)
treeb2af773db48a3606bd078055db925dbba6d4ffaa /sys/src/ape/lib/bsd/getnameinfo.c
parent9c7e1db701e0e80b42bb5990e2f6839d712bb984 (diff)
ape: initial IPv6 support, inet_pton()/inet_ntop(), getaddrinfo()/getnameinfo()
Diffstat (limited to 'sys/src/ape/lib/bsd/getnameinfo.c')
-rw-r--r--sys/src/ape/lib/bsd/getnameinfo.c126
1 files changed, 126 insertions, 0 deletions
diff --git a/sys/src/ape/lib/bsd/getnameinfo.c b/sys/src/ape/lib/bsd/getnameinfo.c
new file mode 100644
index 000000000..70db2c246
--- /dev/null
+++ b/sys/src/ape/lib/bsd/getnameinfo.c
@@ -0,0 +1,126 @@
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include "priv.h"
+
+static int
+netquery(char *buf, int nbuf)
+{
+ int fd, i, n;
+
+ if((fd = open("/net/cs", O_RDWR)) < 0)
+ return EAI_SYSTEM;
+ n = strlen(buf);
+ if(write(fd, buf, n) != n){
+ close(fd);
+ return EAI_NONAME;
+ }
+ lseek(fd, 0, 0);
+ for(i = 0; i < nbuf-1; i += n){
+ n = read(fd, buf+i, nbuf - 1 - i);
+ if(n <= 0)
+ break;
+ buf[i+n++] = ' ';
+ }
+ close(fd);
+ buf[i] = 0;
+ return i;
+}
+
+int
+getnameinfo(struct sockaddr *sa, int salen,
+ char *host, int hostlen,
+ char *serv, int servlen,
+ unsigned int flags)
+{
+ char buf[8*1024], *b, *p;
+ int err;
+
+ if(sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
+ return EAI_FAMILY;
+
+ if(host != 0 && hostlen > 0){
+ if(inet_ntop(sa->sa_family, _sock_inip(sa), host, hostlen) == 0)
+ return EAI_SYSTEM;
+
+ if((flags & NI_NUMERICHOST) == 0){
+ snprintf(buf, sizeof(buf), "!ip=%s", host);
+ if((err = netquery(buf, sizeof(buf))) < 0){
+ if((flags & NI_NAMEREQD) != 0)
+ return err;
+ } else {
+ char *sys, *dom;
+
+ sys = dom = 0;
+ for(b = buf;;){
+ if((p = strchr(b, '=')) == 0)
+ break;
+ *p++ = 0;
+ if(strcmp(b, "sys") == 0)
+ sys = p;
+ else if(strcmp(b, "dom") == 0)
+ dom = p;
+ while(*p && *p != ' ')
+ p++;
+ while(*p == ' ')
+ *p++ = 0;
+ b = p;
+ }
+ if(sys == 0){
+ if(dom == 0 && (flags & NI_NAMEREQD) != 0)
+ return EAI_NONAME;
+ if(dom != 0 && (flags & NI_NOFQDN) != 0){
+ if((p = strchr(dom, '.')) != 0)
+ *p = 0;
+ }
+ sys = dom;
+ }
+ snprintf(host, hostlen, "%s", sys);
+ }
+ }
+ }
+
+ if(serv != 0 && servlen > 0){
+ snprintf(serv, servlen, "%d", _sock_inport(sa));
+ if((flags & NI_NUMERICSERV) == 0){
+ snprintf(buf, sizeof(buf), "!port=%s", serv);
+ if(netquery(buf, sizeof(buf)) > 0){
+ char *tcp, *udp;
+
+ tcp = udp = 0;
+ for(b = buf;;){
+ if((p = strchr(b, '=')) == 0)
+ break;
+ *p++ = 0;
+ if(strcmp(b, "tcp") == 0)
+ tcp = p;
+ else if(strcmp(b, "udp") == 0)
+ udp = p;
+ while(*p && *p != ' ')
+ p++;
+ while(*p == ' ')
+ *p++ = 0;
+ b = p;
+ }
+ if(udp != 0 && (flags & NI_DGRAM) != 0)
+ snprintf(serv, servlen, "%s", udp);
+ else if(tcp != 0)
+ snprintf(serv, servlen, "%s", tcp);
+ }
+ }
+ }
+
+ return 0;
+}