summaryrefslogtreecommitdiff
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
parent9c7e1db701e0e80b42bb5990e2f6839d712bb984 (diff)
downloadplan9front-b6dc4ba5a44a2ed2a68266598ceb28b7a7d51af2.tar.xz
ape: initial IPv6 support, inet_pton()/inet_ntop(), getaddrinfo()/getnameinfo()
-rw-r--r--sys/include/ape/arpa/inet.h147
-rw-r--r--sys/include/ape/netdb.h48
-rw-r--r--sys/include/ape/netinet/in.h38
-rw-r--r--sys/include/ape/sys/socket.h9
-rw-r--r--sys/src/ape/lib/bsd/_sock_ingetaddr.c72
-rw-r--r--sys/src/ape/lib/bsd/_sock_ipattr.c2
-rw-r--r--sys/src/ape/lib/bsd/_sock_srv.c2
-rw-r--r--sys/src/ape/lib/bsd/accept.c30
-rw-r--r--sys/src/ape/lib/bsd/bind.c16
-rw-r--r--sys/src/ape/lib/bsd/connect.c36
-rw-r--r--sys/src/ape/lib/bsd/gai_strerror.c34
-rw-r--r--sys/src/ape/lib/bsd/getaddrinfo.c217
-rw-r--r--sys/src/ape/lib/bsd/gethostbyname.c25
-rw-r--r--sys/src/ape/lib/bsd/getnameinfo.c126
-rw-r--r--sys/src/ape/lib/bsd/getpeername.c8
-rw-r--r--sys/src/ape/lib/bsd/getprotobyname.c3
-rw-r--r--sys/src/ape/lib/bsd/getservbyname.c6
-rw-r--r--sys/src/ape/lib/bsd/getsockname.c8
-rw-r--r--sys/src/ape/lib/bsd/in6_addr.c4
-rw-r--r--sys/src/ape/lib/bsd/inet_ntop.c54
-rw-r--r--sys/src/ape/lib/bsd/inet_pton.c79
-rw-r--r--sys/src/ape/lib/bsd/listen.c15
-rw-r--r--sys/src/ape/lib/bsd/mkfile8
-rw-r--r--sys/src/ape/lib/bsd/priv.h7
-rw-r--r--sys/src/ape/lib/bsd/socket.c13
-rw-r--r--sys/src/ape/lib/bsd/writev.c10
26 files changed, 760 insertions, 257 deletions
diff --git a/sys/include/ape/arpa/inet.h b/sys/include/ape/arpa/inet.h
index 5417eb094..260020a6a 100644
--- a/sys/include/ape/arpa/inet.h
+++ b/sys/include/ape/arpa/inet.h
@@ -1,146 +1 @@
-#ifndef __netinet_in__
-#define __netinet_in__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Copyright (c) 1982, 1986, 1990 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution is only permitted until one year after the first shipment
- * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
- * binary forms are permitted provided that: (1) source distributions retain
- * this entire copyright notice and comment, and (2) distributions including
- * binaries display the following acknowledgement: This product includes
- * software developed by the University of California, Berkeley and its
- * contributors'' in the documentation or other materials provided with the
- * distribution and in all advertising materials mentioning features or use
- * of this software. Neither the name of the University nor the names of
- * its contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * @(#)in.h 7.10 (Berkeley) 6/28/90 plus MULTICAST 1.1
- */
-
-/*
- * Constants and structures defined by the internet system,
- * Per RFC 790, September 1981.
- */
-
-/*
- * Protocols
- */
-#define IPPROTO_IP 0 /* dummy for IP */
-#define IPPROTO_ICMP 1 /* control message protocol */
-#define IPPROTO_GGP 3 /* gateway^2 (deprecated) */
-#define IPPROTO_TCP 6 /* tcp */
-#define IPPROTO_EGP 8 /* exterior gateway protocol */
-#define IPPROTO_PUP 12 /* pup */
-#define IPPROTO_UDP 17 /* user datagram protocol */
-#define IPPROTO_IDP 22 /* xns idp */
-#define IPPROTO_TP 29 /* tp-4 w/ class negotiation */
-#define IPPROTO_EON 80 /* ISO cnlp */
-
-#define IPPROTO_RAW 255 /* raw IP packet */
-#define IPPROTO_MAX 256
-
-
-/*
- * Local port number conventions:
- * Ports < IPPORT_RESERVED are reserved for
- * privileged processes (e.g. root).
- * Ports > IPPORT_USERRESERVED are reserved
- * for servers, not necessarily privileged.
- */
-#define IPPORT_RESERVED 1024
-#define IPPORT_USERRESERVED 5000
-
-/*
- * Internet address (a structure for historical reasons)
- */
-struct in_addr {
- unsigned long s_addr;
-};
-
-/*
- * Definitions of bits in internet address integers.
- * On subnets, the decomposition of addresses to host and net parts
- * is done according to subnet mask, not the masks here.
- */
-#define IN_CLASSA(i) (((long)(i) & 0x80000000) == 0)
-#define IN_CLASSA_NET 0xff000000
-#define IN_CLASSA_NSHIFT 24
-#define IN_CLASSA_HOST 0x00ffffff
-#define IN_CLASSA_MAX 128
-
-#define IN_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000)
-#define IN_CLASSB_NET 0xffff0000
-#define IN_CLASSB_NSHIFT 16
-#define IN_CLASSB_HOST 0x0000ffff
-#define IN_CLASSB_MAX 65536
-
-#define IN_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000)
-#define IN_CLASSC_NET 0xffffff00
-#define IN_CLASSC_NSHIFT 8
-#define IN_CLASSC_HOST 0x000000ff
-
-#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000)
-#define IN_MULTICAST(i) IN_CLASSD(i)
-
-#define IN_EXPERIMENTAL(i) (((long)(i) & 0xe0000000) == 0xe0000000)
-#define IN_BADCLASS(i) (((long)(i) & 0xf0000000) == 0xf0000000)
-
-#define INADDR_ANY (unsigned long)0x00000000
-#define INADDR_BROADCAST (unsigned long)0xffffffff /* must be masked */
-
-#define IN_LOOPBACKNET 127 /* official! */
-
-/*
- * Socket address, internet style.
- */
-struct sockaddr_in {
- short sin_family;
- unsigned short sin_port;
- struct in_addr sin_addr;
- char sin_zero[8];
-};
-
-/*
- * Structure used to describe IP options.
- * Used to store options internally, to pass them to a process,
- * or to restore options retrieved earlier.
- * The ip_dst is used for the first-hop gateway when using a source route
- * (this gets put into the header proper).
- */
-struct ip_opts {
- struct in_addr ip_dst; /* first hop, 0 w/o src rt */
- char ip_opts[40]; /* actually variable in size */
-};
-
-/*
- * Options for use with [gs]etsockopt at the IP level.
- * First word of comment is data type; bool is stored in int.
- */
-#define IP_OPTIONS 1 /* buf/ip_opts; set/get IP per-packet options */
-#define IP_HDRINCL 7 /* int; header is included with data (raw) */
-#define IP_TOS 8 /* int; IP type of service and precedence */
-#define IP_TTL 9 /* int; IP time to live */
-
-extern unsigned long ntohl(unsigned long x);
-extern unsigned short ntohs(unsigned short x);
-extern unsigned long htonl(unsigned long x);
-extern unsigned short htons(unsigned short x);
-extern unsigned long inet_addr(char*);
-extern char* inet_ntoa(struct in_addr);
-extern unsigned long nptohl(void*);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __netinet_in__ */
+#include <netinet/in.h>
diff --git a/sys/include/ape/netdb.h b/sys/include/ape/netdb.h
index 5885c3ab3..2f5fd7539 100644
--- a/sys/include/ape/netdb.h
+++ b/sys/include/ape/netdb.h
@@ -114,6 +114,54 @@ extern char *hstrerror(int);
#define __HOST_SVC_NOT_AVAIL 99 /* libc internal use only */
+struct addrinfo {
+ int ai_flags; /* Input flags. */
+ int ai_family; /* Protocol family for socket. */
+ int ai_socktype; /* Socket type. */
+ int ai_protocol; /* Protocol for socket. */
+ int ai_addrlen; /* Length of socket address. */
+ struct sockaddr *ai_addr; /* Socket address for socket. */
+ char *ai_canonname; /* Canonical name for service location. */
+ struct addrinfo *ai_next; /* Pointer to next in list. */
+};
+
+extern int getaddrinfo(char *, char *, struct addrinfo *, struct addrinfo **);
+extern void freeaddrinfo(struct addrinfo *);
+extern int getnameinfo(struct sockaddr *, int, char *, int, char *, int, unsigned int);
+extern char *gai_strerror(int);
+
+/* Possible values for `ai_flags' field in `addrinfo' structure. */
+#define AI_PASSIVE 0x0001 /* Socket address is intended for `bind'. */
+#define AI_CANONNAME 0x0002 /* Request for canonical name. */
+#define AI_NUMERICHOST 0x0004 /* Don't use name resolution. */
+#define AI_V4MAPPED 0x0008 /* IPv4 mapped addresses are acceptable. */
+#define AI_ALL 0x0010 /* Return IPv4 mapped and IPv6 addresses. */
+#define AI_ADDRCONFIG 0x0020 /* Use configuration of this host to choose returned address type.. */
+#define AI_NUMERICSERV 0x0400 /* Don't use name resolution. */
+
+/* getnameinfo flags */
+#define NI_NOFQDN 0x0001 /* Only the nodename portion of the FQDN is returned for local hosts. */
+#define NI_NUMERICHOST 0x0002 /* The numeric form of the node's address is returned instead of its name. */
+#define NI_NAMEREQD 0x0004 /* Return an error if the node's name cannot be located in the database. */
+#define NI_NUMERICSERV 0x0008 /* The numeric form of the service address is returned instead of its name. */
+#define NI_NUMERICSCOPE 0x0010 /* For IPv6 addresses, the numeric form of the scope identifier is returned
+ instead of its name. */
+#define NI_DGRAM 0x0020 /* Indicates that the service is a datagram service (SOCK_DGRAM). */
+
+/* Error values for `getaddrinfo' and `getnameinfo' functions. */
+#define EAI_BADFLAGS -1 /* Invalid value for `ai_flags' field */
+#define EAI_NONAME -2 /* NAME or SERVICE is unknown */
+#define EAI_AGAIN -3 /* Temporary failure in name resolution */
+#define EAI_FAIL -4 /* Non-recoverable failure in name resolution */
+#define EAI_NODATA -5 /* No address associated with NAME */
+#define EAI_FAMILY -6 /* `ai_family' not supported */
+#define EAI_SOCKTYPE -7 /* `ai_socktype' not supported */
+#define EAI_SERVICE -8 /* SERVICE not supported for `ai_socktype' */
+#define EAI_ADDRFAMILY -9 /* Address family for NAME not supported */
+#define EAI_MEMORY -10 /* Memory allocation failure */
+#define EAI_SYSTEM -11 /* System error returned in `errno' */
+#define EAI_OVERFLOW -12 /* Argument buffer overflow */
+
#ifdef __cplusplus
}
#endif
diff --git a/sys/include/ape/netinet/in.h b/sys/include/ape/netinet/in.h
index 3d04f8ee1..8444c1bcf 100644
--- a/sys/include/ape/netinet/in.h
+++ b/sys/include/ape/netinet/in.h
@@ -102,13 +102,39 @@ struct in_addr {
#define IN_LOOPBACKNET 127 /* official! */
/*
+ * IPv6 internet address.
+ */
+struct in6_addr {
+ unsigned char s6_addr[16];
+};
+
+extern struct in6_addr in6addr_any;
+extern struct in6_addr in6addr_loopback;
+
+#define IN6ADDR_ANY_INIT \
+ {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}
+
+#define IN6ADDR_LOOPBACK_INIT \
+ {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}
+
+/*
* Socket address, internet style.
*/
struct sockaddr_in {
- short sin_family;
+ short sin_family;
unsigned short sin_port;
- struct in_addr sin_addr;
- char sin_zero[8];
+ struct in_addr sin_addr;
+ char sin_zero[8];
+};
+
+struct sockaddr_in6 {
+ short sin6_family;
+ unsigned short sin6_port;
+ unsigned long sin6_flowinfo;
+ struct in6_addr sin6_addr;
+ unsigned long sin6_scope_id;
};
/*
@@ -140,6 +166,12 @@ extern unsigned long inet_addr(char*);
extern char* inet_ntoa(struct in_addr);
extern unsigned long nptohl(void*);
+extern char* inet_ntop(int af, void *src, char *dst, int size);
+extern int inet_pton(int af, char *src, void *dst);
+
+#define INET_ADDRSTRLEN 16
+#define INET6_ADDRSTRLEN 46
+
#ifdef __cplusplus
}
#endif
diff --git a/sys/include/ape/sys/socket.h b/sys/include/ape/sys/socket.h
index df7ad5849..5d60c77a7 100644
--- a/sys/include/ape/sys/socket.h
+++ b/sys/include/ape/sys/socket.h
@@ -22,6 +22,8 @@ extern "C" {
/*
* Definitions related to sockets: types, address families, options.
*/
+typedef int socklen_t;
+typedef unsigned short sa_family_t;
/*
* Types
@@ -108,7 +110,12 @@ struct linger {
*/
struct sockaddr {
unsigned short sa_family; /* address family */
- char sa_data[108];
+ char sa_data[108];
+};
+
+struct sockaddr_storage {
+ unsigned short ss_family;
+ char ss_data[108];
};
/*
diff --git a/sys/src/ape/lib/bsd/_sock_ingetaddr.c b/sys/src/ape/lib/bsd/_sock_ingetaddr.c
index 603eb9c78..c8304f0cf 100644
--- a/sys/src/ape/lib/bsd/_sock_ingetaddr.c
+++ b/sys/src/ape/lib/bsd/_sock_ingetaddr.c
@@ -15,17 +15,74 @@
#include "priv.h"
+void*
+_sock_inip(struct sockaddr *a)
+{
+ switch(a->sa_family){
+ case AF_INET:
+ return &((struct sockaddr_in*)a)->sin_addr;
+ case AF_INET6:
+ return &((struct sockaddr_in6*)a)->sin6_addr;
+ }
+ return 0;
+}
+
+int
+_sock_inport(struct sockaddr *a)
+{
+ switch(a->sa_family){
+ case AF_INET:
+ return ntohs(((struct sockaddr_in*)a)->sin_port);
+ case AF_INET6:
+ return ntohs(((struct sockaddr_in6*)a)->sin6_port);
+ }
+ return 0;
+}
+
+int
+_sock_inaddr(int af, char *ip, char *port, void *a, int *alen)
+{
+ int len;
+
+ len = 0;
+ if(af == AF_INET){
+ struct sockaddr_in *in = a;
+
+ len = sizeof(*in);
+ memset(in, 0, len);
+ in->sin_family = af;
+ if(port != 0 && *port != 0)
+ in->sin_port = htons(atoi(port));
+ if(ip != 0 && *ip != 0)
+ inet_pton(af, ip, &in->sin_addr);
+ } else if(af == AF_INET6){
+ struct sockaddr_in6 *in = a;
+
+ len = sizeof(*in);
+ memset(in, 0, len);
+ in->sin6_family = af;
+ if(port != 0 && *port != 0)
+ in->sin6_port = htons(atoi(port));
+ if(ip != 0 && *ip != 0)
+ inet_pton(af, ip, &in->sin6_addr);
+ }
+ if(alen != 0)
+ *alen = len;
+ return len;
+}
+
void
-_sock_ingetaddr(Rock *r, struct sockaddr_in *ip, int *alen, char *a)
+_sock_ingetaddr(Rock *r, void *a, int *alen, char *file)
{
+ char name[Ctlsize], *p;
int n, fd;
- char *p;
- char name[Ctlsize];
+ if(r->domain != PF_INET && r->domain != PF_INET6)
+ return;
/* get remote address */
strcpy(name, r->ctl);
p = strrchr(name, '/');
- strcpy(p+1, a);
+ strcpy(p+1, file);
fd = open(name, O_RDONLY);
if(fd >= 0){
n = read(fd, name, sizeof(name)-1);
@@ -34,14 +91,9 @@ _sock_ingetaddr(Rock *r, struct sockaddr_in *ip, int *alen, char *a)
p = strchr(name, '!');
if(p){
*p++ = 0;
- ip->sin_family = AF_INET;
- ip->sin_port = htons(atoi(p));
- ip->sin_addr.s_addr = inet_addr(name);
- if(alen)
- *alen = sizeof(struct sockaddr_in);
+ _sock_inaddr(r->domain, name, p, a, alen);
}
}
close(fd);
}
-
}
diff --git a/sys/src/ape/lib/bsd/_sock_ipattr.c b/sys/src/ape/lib/bsd/_sock_ipattr.c
index b9b0c8ac8..882ae1663 100644
--- a/sys/src/ape/lib/bsd/_sock_ipattr.c
+++ b/sys/src/ape/lib/bsd/_sock_ipattr.c
@@ -27,6 +27,8 @@ _sock_ipattr(char *name)
alpha = 1;
else if(*p == '.')
dot = 1;
+ else if(*p == ':')
+ return Tip;
else
return Tsys;
}
diff --git a/sys/src/ape/lib/bsd/_sock_srv.c b/sys/src/ape/lib/bsd/_sock_srv.c
index 1f2988d03..22346d3c4 100644
--- a/sys/src/ape/lib/bsd/_sock_srv.c
+++ b/sys/src/ape/lib/bsd/_sock_srv.c
@@ -44,12 +44,10 @@ _sock_srv(char *path, int fd)
sfd = creat(msg, 0666);
if(sfd < 0){
close(fd);
- _syserrno();
return -1;
}
snprintf(msg, sizeof msg, "%d", fd);
if(write(sfd, msg, strlen(msg)) < 0){
- _syserrno();
close(sfd);
close(fd);
return -1;
diff --git a/sys/src/ape/lib/bsd/accept.c b/sys/src/ape/lib/bsd/accept.c
index 483e4c6ed..4f6203652 100644
--- a/sys/src/ape/lib/bsd/accept.c
+++ b/sys/src/ape/lib/bsd/accept.c
@@ -20,7 +20,6 @@ accept(int fd, void *a, int *alen)
{
int n, nfd, cfd;
Rock *r, *nr;
- struct sockaddr_in *ip;
char name[Ctlsize];
char file[8+Ctlsize+1];
char *p, *net;
@@ -33,6 +32,7 @@ accept(int fd, void *a, int *alen)
switch(r->domain){
case PF_INET:
+ case PF_INET6:
switch(r->stype){
case SOCK_DGRAM:
net = "udp";
@@ -40,41 +40,35 @@ accept(int fd, void *a, int *alen)
case SOCK_STREAM:
net = "tcp";
break;
+ case SOCK_RDM:
+ net = "il";
+ break;
}
/* get control file name from listener process */
n = read(fd, name, sizeof(name)-1);
- if(n <= 0){
- _syserrno();
+ if(n <= 0)
return -1;
- }
name[n] = 0;
cfd = open(name, O_RDWR);
- if(cfd < 0){
- _syserrno();
+ if(cfd < 0)
return -1;
- }
nfd = _sock_data(cfd, net, r->domain, r->stype, r->protocol, &nr);
- if(nfd < 0){
- _syserrno();
+ if(nfd < 0)
return -1;
- }
if(write(fd, "OK", 2) < 0){
close(nfd);
- _syserrno();
return -1;
}
-
/* get remote address */
- ip = (struct sockaddr_in*)&nr->raddr;
- _sock_ingetaddr(nr, ip, &n, "remote");
- if(a){
- memmove(a, ip, sizeof(struct sockaddr_in));
- *alen = sizeof(struct sockaddr_in);
+ _sock_ingetaddr(nr, &nr->raddr, &n, "remote");
+ if(a != 0){
+ if(n > 0)
+ memmove(a, &nr->raddr, n);
+ *alen = n;
}
-
return nfd;
case PF_UNIX:
if(r->other >= 0){
diff --git a/sys/src/ape/lib/bsd/bind.c b/sys/src/ape/lib/bsd/bind.c
index 040c62fa0..902fbcd46 100644
--- a/sys/src/ape/lib/bsd/bind.c
+++ b/sys/src/ape/lib/bsd/bind.c
@@ -24,10 +24,9 @@
int
bind(int fd, void *a, int alen)
{
- int n, len, cfd;
+ int n, len, cfd, port;
Rock *r;
char msg[128];
- struct sockaddr_in *lip;
/* assign the address */
r = _sock_findrock(fd, 0);
@@ -42,7 +41,7 @@ bind(int fd, void *a, int alen)
memmove(&r->addr, a, alen);
/* the rest is IP sepecific */
- if (r->domain != PF_INET)
+ if (r->domain != PF_INET && r->domain != PF_INET6)
return 0;
cfd = open(r->ctl, O_RDWR);
@@ -50,9 +49,9 @@ bind(int fd, void *a, int alen)
errno = EBADF;
return -1;
}
- lip = (struct sockaddr_in*)&r->addr;
- if(lip->sin_port > 0)
- snprintf(msg, sizeof msg, "bind %d", ntohs(lip->sin_port));
+ port = _sock_inport(&r->addr);
+ if(port > 0)
+ snprintf(msg, sizeof msg, "bind %d", port);
else
strcpy(msg, "bind *");
n = write(cfd, msg, strlen(msg));
@@ -62,9 +61,8 @@ bind(int fd, void *a, int alen)
return -1;
}
close(cfd);
-
- if(lip->sin_port <= 0)
- _sock_ingetaddr(r, lip, &len, "local");
+ if(port <= 0)
+ _sock_ingetaddr(r, &r->addr, 0, "local");
return 0;
}
diff --git a/sys/src/ape/lib/bsd/connect.c b/sys/src/ape/lib/bsd/connect.c
index 3f7dcd6b4..ebc63182a 100644
--- a/sys/src/ape/lib/bsd/connect.c
+++ b/sys/src/ape/lib/bsd/connect.c
@@ -21,7 +21,7 @@ connect(int fd, void *a, int alen)
Rock *r;
int n, cfd, nfd;
char msg[8+256+1], file[8+256+1];
- struct sockaddr_in *lip, *rip;
+ struct sockaddr *sa;
struct sockaddr_un *runix;
static int vers;
@@ -34,35 +34,35 @@ connect(int fd, void *a, int alen)
errno = ENAMETOOLONG;
return -1;
}
+ sa = (struct sockaddr*)a;
+ if(sa->sa_family != r->domain){
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
memmove(&r->raddr, a, alen);
switch(r->domain){
case PF_INET:
+ case PF_INET6:
/* set up a tcp or udp connection */
cfd = open(r->ctl, O_RDWR);
- if(cfd < 0){
- _syserrno();
+ if(cfd < 0)
return -1;
- }
- rip = a;
- lip = (struct sockaddr_in*)&r->addr;
- if(lip->sin_port)
+ if(_sock_inport(&r->addr) > 0) {
snprintf(msg, sizeof msg, "connect %s!%d%s %d",
- inet_ntoa(rip->sin_addr), ntohs(rip->sin_port),
+ inet_ntop(sa->sa_family, _sock_inip(sa), file, sizeof(file)),
+ _sock_inport(sa),
r->reserved ? "!r" : "",
- ntohs(lip->sin_port));
- else
+ _sock_inport(&r->addr));
+ } else {
snprintf(msg, sizeof msg, "connect %s!%d%s",
- inet_ntoa(rip->sin_addr), ntohs(rip->sin_port),
+ inet_ntop(sa->sa_family, _sock_inip(sa), file, sizeof(file)),
+ _sock_inport(sa),
r->reserved ? "!r" : "");
- n = write(cfd, msg, strlen(msg));
- if(n < 0){
- _syserrno();
- close(cfd);
- return -1;
}
+ n = write(cfd, msg, strlen(msg));
close(cfd);
- return 0;
+ return (n < 0) ? -1 : 0;
case PF_UNIX:
/* null terminate the address */
if(alen == sizeof(r->raddr))
@@ -87,12 +87,10 @@ connect(int fd, void *a, int alen)
_sock_srvname(file, runix->sun_path);
nfd = open(file, O_RDWR);
if(nfd < 0){
- _syserrno();
unlink(msg);
return -1;
}
if(write(nfd, msg, strlen(msg)) < 0){
- _syserrno();
close(nfd);
unlink(msg);
return -1;
diff --git a/sys/src/ape/lib/bsd/gai_strerror.c b/sys/src/ape/lib/bsd/gai_strerror.c
new file mode 100644
index 000000000..bcb1f8e70
--- /dev/null
+++ b/sys/src/ape/lib/bsd/gai_strerror.c
@@ -0,0 +1,34 @@
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+char*
+gai_strerror(int err)
+{
+ static char *tab[] = {
+ /* 0 */ "No error",
+ /* EAI_BADFLAGS */ "Invalid value for `ai_flags' field",
+ /* EAI_NONAME */ "NAME or SERVICE is unknown",
+ /* EAI_AGAIN */ "Temporary failure in name resolution",
+ /* EAI_FAIL */ "Non-recoverable failure in name resolution",
+ /* EAI_NODATA */ "No address associated with NAME",
+ /* EAI_FAMILY */ "`ai_family' not supported",
+ /* EAI_SOCKTYPE */ "`ai_socktype' not supported",
+ /* EAI_SERVICE */ "SERVICE not supported for `ai_socktype'",
+ /* EAI_ADDRFAMILY */ "Address family for NAME not supported",
+ /* EAI_MEMORY */ "Memory allocation failure",
+ /* EAI_SYSTEM */ "System error returned in `errno'",
+ /* EAI_OVERFLOW */ "Argument buffer overflow",
+ };
+
+ err = -err;
+ if(err < 0 || err >= (sizeof(tab)/sizeof(tab[0])))
+ return "Unknown error";
+ return tab[err];
+}
diff --git a/sys/src/ape/lib/bsd/getaddrinfo.c b/sys/src/ape/lib/bsd/getaddrinfo.c
new file mode 100644
index 000000000..158f22f62
--- /dev/null
+++ b/sys/src/ape/lib/bsd/getaddrinfo.c
@@ -0,0 +1,217 @@
+/* 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"
+
+/* for malloc/free */
+#include <stdlib.h>
+
+void
+freeaddrinfo(struct addrinfo *res)
+{
+ struct addrinfo *info;
+
+ while((info = res) != 0){
+ res = res->ai_next;
+ free(info->ai_canonname);
+ free(info->ai_addr);
+ free(info);
+ }
+}
+
+static int
+sockfamily(char *addr)
+{
+ if(strchr(addr, ':') != 0)
+ return AF_INET6;
+ else
+ return AF_INET;
+}
+
+static int
+sockproto(char *proto)
+{
+ if(strcmp(proto, "tcp") == 0)
+ return SOCK_STREAM;
+ if(strcmp(proto, "udp") == 0)
+ return SOCK_DGRAM;
+ if(strcmp(proto, "il") == 0)
+ return SOCK_RDM;
+ return 0;
+}
+
+static int
+filladdrinfo(char *s, struct addrinfo *a, struct addrinfo *h)
+{
+ struct sockaddr sa;
+ char *p, *q;
+
+ if(*s != '/')
+ return 1;
+ if((q = strchr(s, ' ')) == 0)
+ return 1;
+ while(*q == ' ')
+ *q++ = 0;
+ if((p = strrchr(s+1, '/')) == 0)
+ return 1;
+ *p = 0;
+ if((p = strrchr(s+1, '/')) == 0)
+ return 1;
+ *p++ = 0;
+ if(*p == 0)
+ return 1;
+
+ if((a->ai_socktype = sockproto(p)) == 0)
+ return 1;
+ if((p = strchr(q, '!')) != 0){
+ *p++ = 0;
+ a->ai_family = sockfamily(q);
+ } else{
+ p = q;
+ q = 0;
+ if((a->ai_family = h->ai_family) == 0)
+ a->ai_family = AF_INET;
+ }
+ if((a->ai_socktype == SOCK_RDM || h->ai_socktype != 0)
+ && (a->ai_socktype != h->ai_socktype))
+ return 1;
+ if(h->ai_family != 0 && a->ai_family != h->ai_family)
+ return 1;
+ if(_sock_inaddr(a->ai_family, q, p, &sa, &a->ai_addrlen) <= 0)
+ return 1;
+ if((a->ai_addr = malloc(a->ai_addrlen)) == 0)
+ return EAI_MEMORY;
+ memmove(a->ai_addr, &sa, a->ai_addrlen);
+ return 0;
+}
+
+int
+getaddrinfo(char *node, char *serv, struct addrinfo *hints, struct addrinfo **res)
+{
+ static struct addrinfo nohints;
+ struct addrinfo *a, *head, **tail;
+ char buf[1024], *proto;
+ int n, fd, err;
+
+ if(res != 0)
+ *res = 0;
+
+ if(hints == 0)
+ hints = &nohints;
+
+ proto = "net";
+ switch(hints->ai_family){
+ default:
+ return EAI_FAMILY;
+ case AF_INET:
+ case AF_INET6:
+ switch(hints->ai_socktype){
+ default:
+ return EAI_SOCKTYPE;
+ case SOCK_STREAM:
+ proto = "tcp";
+ break;
+ case SOCK_DGRAM:
+ proto = "udp";
+ break;
+ case SOCK_RDM:
+ proto = "il";
+ break;
+ case 0:
+ break;
+ }
+ break;
+ case AF_UNSPEC:
+ break;
+ }
+ if(serv == 0){
+ if(node == 0)
+ return EAI_NONAME;
+ serv = "0";
+ }
+ if(node == 0){
+ if(hints->ai_flags & AI_PASSIVE)
+ node = "*";
+ else if(hints->ai_family == AF_INET6)
+ node = "::1";
+ else
+ node = "127.0.0.1";
+ }
+
+ if((fd = open("/net/cs", O_RDWR)) < 0)
+ return EAI_SYSTEM;
+
+ snprintf(buf, sizeof(buf), "%s!%s!%s", proto, node, serv);
+ n = strlen(buf);
+ if(write(fd, buf, n) != n){
+ close(fd);
+ return EAI_AGAIN;
+ }
+ lseek(fd, 0, 0);
+
+ head = 0;
+ tail = &head;
+ for(;;){
+ if((n = read(fd, buf, sizeof(buf)-1)) <= 0)
+ break;
+ buf[n] = '\0';
+ if((a = malloc(sizeof(*a))) == 0){
+ freeaddrinfo(head);
+ close(fd);
+ return EAI_MEMORY;
+ }
+ memset(a, 0, sizeof(*a));
+ if((err = filladdrinfo(buf, a, hints)) != 0){
+ freeaddrinfo(a);
+ if(err < 0){
+ freeaddrinfo(head);
+ close(fd);
+ return err;
+ }
+ } else {
+ *tail = a;
+ tail = &a->ai_next;
+ }
+ }
+ close(fd);
+
+ if(head == 0)
+ return EAI_NODATA;
+
+ if((hints->ai_flags & AI_CANONNAME) != 0 && (hints->ai_flags & AI_NUMERICHOST) == 0){
+ n = _sock_ipattr(node);
+ if(n != Tsys && n != Tdom){
+ if(getnameinfo(head->ai_addr, head->ai_addrlen, buf, sizeof(buf), 0, 0, NI_NAMEREQD) == 0)
+ node = buf;
+ else
+ node = 0;
+ }
+ if(node != 0){
+ n = strlen(node)+1;
+ if((head->ai_canonname = malloc(n)) == 0){
+ freeaddrinfo(head);
+ return EAI_MEMORY;
+ }
+ memmove(head->ai_canonname, node, n);
+ }
+ }
+
+ if(res != 0)
+ *res = head;
+ else
+ freeaddrinfo(head);
+
+ return 0;
+}
diff --git a/sys/src/ape/lib/bsd/gethostbyname.c b/sys/src/ape/lib/bsd/gethostbyname.c
index 749798510..9393865fb 100644
--- a/sys/src/ape/lib/bsd/gethostbyname.c
+++ b/sys/src/ape/lib/bsd/gethostbyname.c
@@ -29,7 +29,7 @@ struct hostent*
gethostbyname(char *name)
{
int i, t, fd, m;
- char *p, *bp;
+ char *p, *k, *bp;
int nn, na;
unsigned long x;
static struct hostent h;
@@ -44,7 +44,6 @@ gethostbyname(char *name)
/* connect to server */
fd = open("/net/cs", O_RDWR);
if(fd < 0){
- _syserrno();
h_errno = NO_RECOVERY;
return 0;
}
@@ -64,8 +63,8 @@ gethostbyname(char *name)
/* query the server */
if(write(fd, buf, strlen(buf)) < 0){
- _syserrno();
h_errno = TRY_AGAIN;
+ close(fd);
return 0;
}
lseek(fd, 0, 0);
@@ -81,19 +80,26 @@ gethostbyname(char *name)
/* parse the reply */
nn = na = 0;
for(bp = buf;;){
- p = strchr(bp, '=');
+ k = bp;
+ p = strchr(k, '=');
if(p == 0)
break;
*p++ = 0;
- if(strcmp(bp, "dom") == 0){
+ for(bp = p; *bp && *bp != ' '; bp++)
+ ;
+ if(*bp)
+ *bp++ = 0;
+ if(strcmp(k, "dom") == 0){
if(h.h_name == 0)
h.h_name = p;
if(nn < Nname)
nptr[nn++] = p;
- } else if(strcmp(bp, "sys") == 0){
+ } else if(strcmp(k, "sys") == 0){
if(nn < Nname)
nptr[nn++] = p;
- } else if(strcmp(bp, "ip") == 0){
+ } else if(strcmp(k, "ip") == 0){
+ if(strchr(p, ':') != 0)
+ continue; /* ignore ipv6 addresses */
x = inet_addr(p);
x = ntohl(x);
if(na < Nname){
@@ -105,11 +111,6 @@ gethostbyname(char *name)
na++;
}
}
- while(*p && *p != ' ')
- p++;
- if(*p)
- *p++ = 0;
- bp = p;
}
if(nn+na == 0){
h_errno = HOST_NOT_FOUND;
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;
+}
diff --git a/sys/src/ape/lib/bsd/getpeername.c b/sys/src/ape/lib/bsd/getpeername.c
index e4dd3109c..55b4f8eb3 100644
--- a/sys/src/ape/lib/bsd/getpeername.c
+++ b/sys/src/ape/lib/bsd/getpeername.c
@@ -20,7 +20,6 @@ getpeername(int fd, struct sockaddr *addr, int *alen)
{
Rock *r;
int i;
- struct sockaddr_in *rip;
struct sockaddr_un *runix;
r = _sock_findrock(fd, 0);
@@ -31,10 +30,13 @@ getpeername(int fd, struct sockaddr *addr, int *alen)
switch(r->domain){
case PF_INET:
- rip = (struct sockaddr_in*)&r->raddr;
- memmove(addr, rip, sizeof(struct sockaddr_in));
+ memmove(addr, &r->raddr, sizeof(struct sockaddr_in));
*alen = sizeof(struct sockaddr_in);
break;
+ case PF_INET6:
+ memmove(addr, &r->raddr, sizeof(struct sockaddr_in6));
+ *alen = sizeof(struct sockaddr_in6);
+ break;
case PF_UNIX:
runix = (struct sockaddr_un*)&r->raddr;
i = &runix->sun_path[strlen(runix->sun_path)] - (char*)runix;
diff --git a/sys/src/ape/lib/bsd/getprotobyname.c b/sys/src/ape/lib/bsd/getprotobyname.c
index f88d70148..bd13a0cc5 100644
--- a/sys/src/ape/lib/bsd/getprotobyname.c
+++ b/sys/src/ape/lib/bsd/getprotobyname.c
@@ -35,7 +35,6 @@ struct protoent *getprotobyname(const char *name) {
/* connect to server */
fd = open("/net/cs", O_RDWR);
if(fd < 0){
- _syserrno();
h_errno = NO_RECOVERY;
return 0;
}
@@ -45,8 +44,8 @@ struct protoent *getprotobyname(const char *name) {
/* query the server */
if(write(fd, buf, strlen(buf)) < 0){
- _syserrno();
h_errno = TRY_AGAIN;
+ close(fd);
return 0;
}
lseek(fd, 0, 0);
diff --git a/sys/src/ape/lib/bsd/getservbyname.c b/sys/src/ape/lib/bsd/getservbyname.c
index 0212d5403..5ad73b220 100644
--- a/sys/src/ape/lib/bsd/getservbyname.c
+++ b/sys/src/ape/lib/bsd/getservbyname.c
@@ -43,10 +43,8 @@ getservbyname(char *name, char *proto)
/* connect to server */
fd = open("/net/cs", O_RDWR);
- if(fd < 0){
- _syserrno();
+ if(fd < 0)
return 0;
- }
/* construct the query, always expect an ip# back */
if(num)
@@ -56,7 +54,7 @@ getservbyname(char *name, char *proto)
/* query the server */
if(write(fd, buf, strlen(buf)) < 0){
- _syserrno();
+ close(fd);
return 0;
}
lseek(fd, 0, 0);
diff --git a/sys/src/ape/lib/bsd/getsockname.c b/sys/src/ape/lib/bsd/getsockname.c
index aa22d3217..cdf149779 100644
--- a/sys/src/ape/lib/bsd/getsockname.c
+++ b/sys/src/ape/lib/bsd/getsockname.c
@@ -20,7 +20,6 @@ getsockname(int fd, struct sockaddr *addr, int *alen)
{
Rock *r;
int i;
- struct sockaddr_in *lip;
struct sockaddr_un *lunix;
r = _sock_findrock(fd, 0);
@@ -31,14 +30,15 @@ getsockname(int fd, struct sockaddr *addr, int *alen)
switch(r->domain){
case PF_INET:
- lip = (struct sockaddr_in*)addr;
- _sock_ingetaddr(r, lip, alen, "local");
+ case PF_INET6:
+ _sock_ingetaddr(r, addr, alen, "local");
break;
case PF_UNIX:
lunix = (struct sockaddr_un*)&r->addr;
i = &lunix->sun_path[strlen(lunix->sun_path)] - (char*)lunix;
memmove(addr, lunix, i);
- *alen = i;
+ if(alen != 0)
+ *alen = i;
break;
default:
errno = EAFNOSUPPORT;
diff --git a/sys/src/ape/lib/bsd/in6_addr.c b/sys/src/ape/lib/bsd/in6_addr.c
new file mode 100644
index 000000000..324593a32
--- /dev/null
+++ b/sys/src/ape/lib/bsd/in6_addr.c
@@ -0,0 +1,4 @@
+#include <netinet/in.h>
+
+struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
diff --git a/sys/src/ape/lib/bsd/inet_ntop.c b/sys/src/ape/lib/bsd/inet_ntop.c
new file mode 100644
index 000000000..0f9c9e2b0
--- /dev/null
+++ b/sys/src/ape/lib/bsd/inet_ntop.c
@@ -0,0 +1,54 @@
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <errno.h>
+
+char*
+inet_ntop(int af, void *src, char *dst, int size)
+{
+ unsigned char *p;
+ char *t, *e;
+ int i;
+
+ if(af == AF_INET){
+ if(size < INET_ADDRSTRLEN){
+ errno = ENOSPC;
+ return 0;
+ }
+ p = (unsigned char*)&(((struct in_addr*)src)->s_addr);
+ snprintf(dst, size, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+ return dst;
+ }
+
+ if(af != AF_INET6){
+ errno = EAFNOSUPPORT;
+ return 0;
+ }
+ if(size < INET6_ADDRSTRLEN){
+ errno = ENOSPC;
+ return 0;
+ }
+
+ p = (unsigned char*)((struct in6_addr*)src)->s6_addr;
+ t = dst;
+ e = t + size;
+ for(i=0; i<16; i += 2){
+ unsigned int w;
+
+ if(i > 0)
+ *t++ = ':';
+ w = p[i]<<8 | p[i+1];
+ snprintf(t, e - t, "%x", w);
+ t += strlen(t);
+ }
+ return dst;
+}
diff --git a/sys/src/ape/lib/bsd/inet_pton.c b/sys/src/ape/lib/bsd/inet_pton.c
new file mode 100644
index 000000000..863124b00
--- /dev/null
+++ b/sys/src/ape/lib/bsd/inet_pton.c
@@ -0,0 +1,79 @@
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <errno.h>
+
+static int
+ipcharok(int c)
+{
+ return c == ':' || isascii(c) && isxdigit(c);
+}
+
+static int
+delimchar(int c)
+{
+ if(c == '\0')
+ return 1;
+ if(c == ':' || isascii(c) && isalnum(c))
+ return 0;
+ return 1;
+}
+
+int
+inet_pton(int af, char *src, void *dst)
+{
+ int i, elipsis = 0;
+ unsigned char *to;
+ unsigned long x;
+ char *p, *op;
+
+ if(af == AF_INET){
+ ((struct in_addr*)dst)->s_addr = inet_addr(src);
+ return 1;
+ }
+
+ if(af != AF_INET6){
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+
+ to = ((struct in6_addr*)dst)->s6_addr;
+ memset(to, 0, 16);
+
+ p = src;
+ for(i = 0; i < 16 && ipcharok(*p); i+=2){
+ op = p;
+ x = strtoul(p, &p, 16);
+
+ if(x != (unsigned short)x || *p != ':' && !delimchar(*p))
+ return 0; /* parse error */
+
+ to[i] = x>>8;
+ to[i+1] = x;
+ if(*p == ':'){
+ if(*++p == ':'){ /* :: is elided zero short(s) */
+ if (elipsis)
+ return 0; /* second :: */
+ elipsis = i+2;
+ p++;
+ }
+ } else if (p == op) /* strtoul made no progress? */
+ break;
+ }
+ if (p == src || !delimchar(*p))
+ return 0; /* parse error */
+ if(i < 16){
+ memmove(&to[elipsis+16-i], &to[elipsis], i-elipsis);
+ memset(&to[elipsis], 0, 16-i);
+ }
+ return 1;
+}
diff --git a/sys/src/ape/lib/bsd/listen.c b/sys/src/ape/lib/bsd/listen.c
index c5bf19069..b0408cd19 100644
--- a/sys/src/ape/lib/bsd/listen.c
+++ b/sys/src/ape/lib/bsd/listen.c
@@ -47,6 +47,9 @@ listenproc(Rock *r, int fd)
case SOCK_STREAM:
net = "tcp";
break;
+ case SOCK_RDM:
+ net = "il";
+ break;
}
strcpy(listen, r->ctl);
@@ -118,9 +121,8 @@ listen(fd, backlog)
int backlog;
{
Rock *r;
- int n, cfd;
+ int n, cfd, port;
char msg[128];
- struct sockaddr_in *lip;
struct sockaddr_un *lunix;
r = _sock_findrock(fd, 0);
@@ -131,20 +133,20 @@ listen(fd, backlog)
switch(r->domain){
case PF_INET:
+ case PF_INET6:
cfd = open(r->ctl, O_RDWR);
if(cfd < 0){
errno = EBADF;
return -1;
}
- lip = (struct sockaddr_in*)&r->addr;
- if(lip->sin_port >= 0) {
+ port = _sock_inport(&r->addr);
+ if(port >= 0) {
if(write(cfd, "bind 0", 6) < 0) {
errno = EGREG;
close(cfd);
return -1;
}
- snprintf(msg, sizeof msg, "announce %d",
- ntohs(lip->sin_port));
+ snprintf(msg, sizeof msg, "announce %d", port);
}
else
strcpy(msg, "announce *");
@@ -164,7 +166,6 @@ listen(fd, backlog)
}
lunix = (struct sockaddr_un*)&r->addr;
if(_sock_srv(lunix->sun_path, r->other) < 0){
- _syserrno();
r->other = -1;
return -1;
}
diff --git a/sys/src/ape/lib/bsd/mkfile b/sys/src/ape/lib/bsd/mkfile
index 3034e13a4..5f95c9b02 100644
--- a/sys/src/ape/lib/bsd/mkfile
+++ b/sys/src/ape/lib/bsd/mkfile
@@ -9,10 +9,13 @@ OFILES=\
connect.$O\
endhostent.$O\
ffs.$O\
+ gai_strerror.$O\
+ getaddrinfo.$O\
getdtablesize.$O\
- gethostbyname.$O\
gethostbyaddr.$O\
+ gethostbyname.$O\
gethostname.$O\
+ getnameinfo.$O\
getopt.$O\
getpeername.$O\
getprotobyname.$O\
@@ -20,8 +23,11 @@ OFILES=\
getservbyname.$O\
getsockname.$O\
gettimeofday.$O\
+ in6_addr.$O\
inet_addr.$O\
inet_ntoa.$O\
+ inet_ntop.$O\
+ inet_pton.$O\
ioctl.$O\
listen.$O\
lstat.$O\
diff --git a/sys/src/ape/lib/bsd/priv.h b/sys/src/ape/lib/bsd/priv.h
index f99fc5673..7004f3cc6 100644
--- a/sys/src/ape/lib/bsd/priv.h
+++ b/sys/src/ape/lib/bsd/priv.h
@@ -41,6 +41,7 @@ extern void _sock_srvname(char*, char*);
extern int _sock_srv(char*, int);
extern int _sock_data(int, char*, int, int, int, Rock**);
extern int _sock_ipattr(char*);
-extern void _sock_ingetaddr(Rock*, struct sockaddr_in*, int*, char*);
-
-extern void _syserrno(void);
+extern void* _sock_inip(struct sockaddr*);
+extern int _sock_inport(struct sockaddr*);
+extern int _sock_inaddr(int, char*, char*, void*, int*);
+extern void _sock_ingetaddr(Rock*, void*, int*, char*);
diff --git a/sys/src/ape/lib/bsd/socket.c b/sys/src/ape/lib/bsd/socket.c
index d14b35386..3cf8c6632 100644
--- a/sys/src/ape/lib/bsd/socket.c
+++ b/sys/src/ape/lib/bsd/socket.c
@@ -125,6 +125,7 @@ socket(int domain, int stype, int protocol)
switch(domain){
case PF_INET:
+ case PF_INET6:
/* get a free network directory */
switch(stype){
case SOCK_DGRAM:
@@ -135,20 +136,20 @@ socket(int domain, int stype, int protocol)
net = "tcp";
cfd = open("/net/tcp/clone", O_RDWR);
break;
+ case SOCK_RDM:
+ net = "il";
+ cfd = open("/net/il/clone", O_RDWR);
+ break;
default:
errno = EPROTONOSUPPORT;
return -1;
}
- if(cfd < 0){
- _syserrno();
+ if(cfd < 0)
return -1;
- }
return _sock_data(cfd, net, domain, stype, protocol, 0);
case PF_UNIX:
- if(pipe(pfd) < 0){
- _syserrno();
+ if(pipe(pfd) < 0)
return -1;
- }
r = _sock_newrock(pfd[0]);
if(r == 0){
close(pfd[0]);
diff --git a/sys/src/ape/lib/bsd/writev.c b/sys/src/ape/lib/bsd/writev.c
index fbb36b692..5de967743 100644
--- a/sys/src/ape/lib/bsd/writev.c
+++ b/sys/src/ape/lib/bsd/writev.c
@@ -33,12 +33,10 @@ writev(int fd, struct iovec *v, int ent)
f += i;
i = write(fd, buf, sizeof(buf));
if(i < 0){
- if(written > 0){
+ if(written > 0)
return written;
- }else{
- _syserrno();
+ else
return -1;
- }
}
written += i;
if(i != sizeof(buf)) {
@@ -51,10 +49,8 @@ writev(int fd, struct iovec *v, int ent)
if(i > 0){
n = write(fd, buf, i);
if(n < 0){
- if(written == 0){
- _syserrno();
+ if(written == 0)
return -1;
- }
} else
written += n;
}