ape: initial IPv6 support, inet_pton()/inet_ntop(), getaddrinfo()/getnameinfo()
This commit is contained in:
parent
9c7e1db701
commit
b6dc4ba5a4
26 changed files with 762 additions and 259 deletions
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -101,6 +101,24 @@ 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.
|
||||
*/
|
||||
|
@ -111,6 +129,14 @@ struct sockaddr_in {
|
|||
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;
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure used to describe IP options.
|
||||
* Used to store options internally, to pass them to a process,
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -111,6 +113,11 @@ struct sockaddr {
|
|||
char sa_data[108];
|
||||
};
|
||||
|
||||
struct sockaddr_storage {
|
||||
unsigned short ss_family;
|
||||
char ss_data[108];
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure used by kernel to pass protocol
|
||||
* information in raw sockets.
|
||||
|
|
|
@ -15,17 +15,74 @@
|
|||
|
||||
#include "priv.h"
|
||||
|
||||
void
|
||||
_sock_ingetaddr(Rock *r, struct sockaddr_in *ip, int *alen, char *a)
|
||||
void*
|
||||
_sock_inip(struct sockaddr *a)
|
||||
{
|
||||
int n, fd;
|
||||
char *p;
|
||||
char name[Ctlsize];
|
||||
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, void *a, int *alen, char *file)
|
||||
{
|
||||
char name[Ctlsize], *p;
|
||||
int n, fd;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@ _sock_ipattr(char *name)
|
|||
alpha = 1;
|
||||
else if(*p == '.')
|
||||
dot = 1;
|
||||
else if(*p == ':')
|
||||
return Tip;
|
||||
else
|
||||
return Tsys;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
34
sys/src/ape/lib/bsd/gai_strerror.c
Normal file
34
sys/src/ape/lib/bsd/gai_strerror.c
Normal file
|
@ -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];
|
||||
}
|
217
sys/src/ape/lib/bsd/getaddrinfo.c
Normal file
217
sys/src/ape/lib/bsd/getaddrinfo.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
|
126
sys/src/ape/lib/bsd/getnameinfo.c
Normal file
126
sys/src/ape/lib/bsd/getnameinfo.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,13 +30,14 @@ 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);
|
||||
if(alen != 0)
|
||||
*alen = i;
|
||||
break;
|
||||
default:
|
||||
|
|
4
sys/src/ape/lib/bsd/in6_addr.c
Normal file
4
sys/src/ape/lib/bsd/in6_addr.c
Normal file
|
@ -0,0 +1,4 @@
|
|||
#include <netinet/in.h>
|
||||
|
||||
struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
|
||||
struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
|
54
sys/src/ape/lib/bsd/inet_ntop.c
Normal file
54
sys/src/ape/lib/bsd/inet_ntop.c
Normal file
|
@ -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;
|
||||
}
|
79
sys/src/ape/lib/bsd/inet_pton.c
Normal file
79
sys/src/ape/lib/bsd/inet_pton.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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\
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -33,13 +33,11 @@ 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)) {
|
||||
return written;
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue