conclusion

This commit is contained in:
pommicket 2022-02-20 13:18:21 -08:00
parent 0f97a589b8
commit 9bc8a11afe
1069 changed files with 48694 additions and 11 deletions

View file

@ -0,0 +1,267 @@
#include <stdint.h>
#include <netdb.h>
#include <stdio.h>
#include <fcntl.h>
#include <limits.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <time.h>
#include <ctype.h>
#include <unistd.h>
#include "__dns.h"
#include "stdio_impl.h"
#define TIMEOUT 5
#define RETRY 1
#define PACKET_MAX 512
#define PTR_MAX (64 + sizeof ".in-addr.arpa")
int __dns_doqueries(unsigned char *dest, const char *name, int *rr, int rrcnt)
{
time_t t0 = time(0);
int fd;
FILE *f, _f;
unsigned char _buf[64];
char line[64], *s, *z;
union {
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
} sa = {0}, ns[3] = {{0}};
socklen_t sl;
int nns;
int family;
unsigned char q[280] = "", *r = dest;
int ql;
int rlen;
int got = 0, failed = 0;
int errcode = EAI_AGAIN;
int i, j;
struct timeval tv;
fd_set fds;
int id;
/* Construct query template - RR and ID will be filled later */
if (strlen(name)-1 >= 254U) return -1;
q[2] = q[5] = 1;
strcpy((char *)q+13, name);
for (i=13; q[i]; i=j+1) {
for (j=i; q[j] && q[j] != '.'; j++);
if (j-i-1u > 62u) return -1;
q[i-1] = j-i;
}
q[i+3] = 1;
ql = i+4;
/* Make a reasonably unpredictable id */
gettimeofday(&tv, 0);
id = tv.tv_usec + tv.tv_usec/256 & 0xffff;
/* Get nameservers from resolv.conf, fallback to localhost */
f = __fopen_rb_ca("/etc/resolv.conf", &_f, _buf, sizeof _buf);
if (f) for (nns=0; nns<3 && fgets(line, sizeof line, f); ) {
if (strncmp(line, "nameserver", 10) || !isspace(line[10]))
continue;
for (s=line+11; isspace(*s); s++);
for (z=s; *z && !isspace(*z); z++);
*z=0;
if (__ipparse(ns+nns, family, s) < 0) continue;
ns[nns].sin.sin_port = htons(53);
family = ns[nns++].sin.sin_family;
sl = family==AF_INET6 ? sizeof sa.sin6 : sizeof sa.sin;
}
if (f) __fclose_ca(f);
if (!nns) {
ns[0].sin.sin_family = AF_INET;
ns[0].sin.sin_port = htons(53);
nns=1;
sl = sizeof sa.sin;
}
/* Get local address and open/bind a socket */
sa.sin.sin_family = family;
fd = socket(family, SOCK_DGRAM, 0);
if (bind(fd, (void *)&sa, sl) < 0) {
close(fd);
return -1;
}
/* Nonblocking to work around Linux UDP select bug */
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
/* Loop until we timeout; break early on success */
for (; time(0)-t0 < TIMEOUT; ) {
/* Query all configured namservers in parallel */
for (i=0; i<rrcnt; i++) if (rr[i]) for (j=0; j<nns; j++) {
q[0] = id+i >> 8;
q[1] = id+i;
q[ql-3] = rr[i];
sendto(fd, q, ql, MSG_NOSIGNAL, (void *)&ns[j], sl);
}
/* Wait for a response, or until time to retry */
FD_ZERO(&fds);
FD_SET(fd, &fds);
tv.tv_sec = RETRY;
tv.tv_usec = 0;
if (select(fd+1, &fds, 0, 0, &tv) <= 0) continue;
/* Process any and all replies */
while (got+failed < rrcnt && (rlen = recvfrom(fd, r, 512, 0,
(void *)&sa, (socklen_t[1]){sl})) >= 2)
{
/* Ignore replies from addresses we didn't send to */
for (i=0; i<nns; i++) if (!memcmp(ns+i, &sa, sl)) break;
if (i==nns) continue;
/* Compute index of the query from id */
i = r[0]*256+r[1] - id & 0xffff;
if ((unsigned)i >= rrcnt || !rr[i]) continue;
/* Interpret the result code */
switch (r[3] & 15) {
case 0:
got++;
break;
case 3:
if (1) errcode = EAI_NONAME; else
default:
errcode = EAI_FAIL;
failed++;
}
/* Mark this record as answered */
rr[i] = 0;
r += 512;
}
/* Check to see if we have answers to all queries */
if (got+failed == rrcnt) break;
}
close(fd);
/* Return the number of results, or an error code if none */
if (got) return got;
return errcode;
}
static void mkptr4(char *s, const unsigned char *ip)
{
sprintf(s, "%d.%d.%d.%d.in-addr.arpa",
ip[3], ip[2], ip[1], ip[0]);
}
static void mkptr6(char *s, const unsigned char *ip)
{
static const char xdigits[] = "0123456789abcdef";
int i;
for (i=15; i>=0; i--) {
*s++ = xdigits[ip[i]&15]; *s++ = '.';
*s++ = xdigits[ip[i]>>4]; *s++ = '.';
}
strcpy(s, "ip6.arpa");
}
int __dns_query(unsigned char *r, const void *a, int family, int ptr)
{
char buf[PTR_MAX];
int rr[2], rrcnt = 1;
if (ptr) {
if (family == AF_INET6) mkptr6(buf, a);
else mkptr4(buf, a);
rr[0] = RR_PTR;
a = buf;
} else if (family == AF_INET6) {
rr[0] = RR_AAAA;
} else {
rr[0] = RR_A;
if (family != AF_INET) rr[rrcnt++] = RR_AAAA;
}
return __dns_doqueries(r, a, rr, rrcnt);
}
#define BITOP(a,b,op) \
((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
static int decname(char *s, const unsigned char *b, const unsigned char *p)
{
/* Remember jump destinations to detect loops and abort */
size_t seen[PACKET_MAX/8/sizeof(size_t)] = { 0 };
char *sz = s + HOST_NAME_MAX;
const unsigned char *pz = b+512;
for (;;) {
if (p>=pz) return -1;
else if (*p&0xc0) {
int j = (p[0]&1) | p[1];
if (BITOP(seen, j, &)) return -1;
BITOP(seen, j, |=);
p = b + j;
} else if (*p) {
if (p+*p+1>=pz || s+*p>=sz) return -1;
memcpy(s, p+1, *p);
s += *p+1;
p += *p+1;
s[-1] = *p ? '.' : 0;
} else return 0;
}
}
int __dns_get_rr(void *dest, size_t stride, size_t maxlen, size_t limit, const unsigned char *r, int rr, int dec)
{
int qdcount, ancount;
const unsigned char *p;
char tmp[256];
int found = 0;
int len;
if ((r[3]&15)) return 0;
p = r+12;
qdcount = r[4]*256 + r[5];
ancount = r[6]*256 + r[7];
if (qdcount+ancount > 64) return -1;
while (qdcount--) {
while (p-r < 512 && *p-1U < 127) p++;
if (*p>193 || (*p==193 && p[1]>254) || p>r+506)
return -1;
p += 5 + !!*p;
}
while (ancount--) {
while (p-r < 512 && *p-1U < 127) p++;
if (*p>193 || (*p==193 && p[1]>254) || p>r+506)
return -1;
p += 1 + !!*p;
len = p[8]*256 + p[9];
if (p+len > r+512) return -1;
if (p[1]==rr && len <= maxlen) {
if (dec && decname(tmp, r, p+10)<0) return -1;
if (dest && limit) {
if (dec) strcpy(dest, tmp);
else memcpy(dest, p+10, len);
dest = (char *)dest + stride;
limit--;
}
found++;
}
p += 10 + len;
}
return found;
}
int __dns_count_addrs(const unsigned char *r, int cnt)
{
int found=0, res, i;
static const int p[2][2] = { { 4, RR_A }, { 16, RR_AAAA } };
while (cnt--) for (i=0; i<2; i++) {
res = __dns_get_rr(0, 0, p[i][0], -1, r, p[i][1], 0);
if (res < 0) return res;
found += res;
r += 512;
}
return found;
}

View file

@ -0,0 +1,14 @@
#include <stddef.h>
#define RR_A 1
#define RR_CNAME 5
#define RR_PTR 12
#define RR_AAAA 28
int __dns_count_addrs(const unsigned char *, int);
int __dns_get_rr(void *, size_t, size_t, size_t, const unsigned char *, int, int);
int __dns_query(unsigned char *, const void *, int, int);
int __ipparse(void *, int, const char *);
int __dns_doqueries(unsigned char *, const char *, int *, int);

View file

@ -0,0 +1,40 @@
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "__dns.h"
#include <stdio.h>
int __ipparse(void *dest, int family, const char *s)
{
unsigned char *d = dest;
unsigned long a[16] = { 0 };
const char *z;
int i;
if (family == AF_INET6) goto not_v4;
for (i=0; i<4 && *s; i++) {
a[i] = strtoul(s, (char **)&z, 0);
if (z==s || (*z && *z != '.')) goto not_v4;
s=z+1;
}
switch (i) {
case 0:
a[1] = a[0] & 0xffffff;
a[0] >>= 24;
case 1:
a[2] = a[1] & 0xffff;
a[1] >>= 16;
case 2:
a[3] = a[2] & 0xff;
a[2] >>= 8;
}
((struct sockaddr_in *)d)->sin_family = AF_INET;
d = (void *)&((struct sockaddr_in *)d)->sin_addr;
for (i=0; i<4; i++) d[i] = a[i];
return 0;
not_v4:
return -1;
}

View file

@ -0,0 +1,12 @@
#include <sys/socket.h>
#include "syscall.h"
#include "libc.h"
int accept(int fd, struct sockaddr *addr, socklen_t *len)
{
int ret;
CANCELPT_BEGIN;
ret = socketcall(accept, fd, addr, len, 0, 0, 0);
CANCELPT_END;
return ret;
}

View file

@ -0,0 +1,7 @@
#include <sys/socket.h>
#include "syscall.h"
int bind(int fd, const struct sockaddr *addr, socklen_t len)
{
return socketcall(bind, fd, addr, len, 0, 0, 0);
}

View file

@ -0,0 +1,12 @@
#include <sys/socket.h>
#include "syscall.h"
#include "libc.h"
int connect(int fd, const struct sockaddr *addr, socklen_t len)
{
int ret;
CANCELPT_BEGIN;
ret = socketcall(connect, fd, addr, len, 0, 0, 0);
CANCELPT_END;
return ret;
}

View file

@ -0,0 +1,28 @@
#include <resolv.h>
#include <string.h>
#define BITOP(a,b,op) \
((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
int dn_expand(unsigned char *b, unsigned char *pz, unsigned char *p, unsigned char *s, int outlen)
{
/* Remember jump destinations to detect loops and abort */
size_t seen[512/8/sizeof(size_t)] = { 0 };
unsigned char *sz = s + outlen;
if (pz-b > 512) return -1;
for (;;) {
if (p>=pz) return -1;
else if (*p&0xc0) {
int j = (p[0]&1) | p[1];
if (BITOP(seen, j, &)) return -1;
BITOP(seen, j, |=);
p = b + j;
} else if (*p) {
if (p+*p+1>=pz || s+*p>=sz) return -1;
memcpy(s, p+1, *p);
s += *p+1;
p += *p+1;
s[-1] = *p ? '.' : 0;
} else return 0;
}
}

View file

@ -0,0 +1,26 @@
#include "libc.h"
void sethostent(int x)
{
}
void *gethostent()
{
return 0;
}
void endhostent(void)
{
}
weak_alias(sethostent, setnetent);
weak_alias(gethostent, getnetent);
weak_alias(endhostent, endnetent);
weak_alias(sethostent, setservent);
weak_alias(gethostent, getservent);
weak_alias(endhostent, endservent);
weak_alias(sethostent, setprotoent);
weak_alias(gethostent, getprotoent);
weak_alias(endhostent, endprotoent);

View file

@ -0,0 +1,7 @@
#include <stdlib.h>
#include <netdb.h>
void freeaddrinfo(struct addrinfo *p)
{
free(p);
}

View file

@ -0,0 +1,21 @@
#include <netdb.h>
static const char msgs[] =
"Invalid flags\0"
"Name does not resolve\0"
"Try again\0"
"Non-recoverable error\0"
"Unrecognized address family or invalid length\0"
"Unrecognized socket type\0"
"Unrecognized service\0"
"Out of memory\0"
"System error\0"
"Overflow\0"
"\0Unknown error";
const char *gai_strerror(int ecode)
{
const char *s;
for (s=msgs, ecode++; ecode && *s; ecode++, s++) for (; *s; s++);
return *s ? s : s+1;
}

View file

@ -0,0 +1,224 @@
#include <stdlib.h>
#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include "__dns.h"
#include "stdio_impl.h"
static int is_valid(const char *host)
{
const unsigned char *s;
if (strlen(host)-1 > 254 || mbstowcs(0, host, 0) > 255) return 0;
for (s=host; *s>=0x80 || *s=='.' || *s=='-' || isalnum(*s); s++);
return !*s;
}
#if 0
static int have_af(int family)
{
struct sockaddr_in6 sin6 = { .sin6_family = family };
socklen_t sl = family == AF_INET
? sizeof(struct sockaddr_in)
: sizeof(struct sockaddr_in6);
int sock = socket(family, SOCK_STREAM, 0);
int have = !bind(sock, (void *)&sin6, sl);
close(sock);
return have;
}
#endif
#include <stdlib.h>
#include <netdb.h>
union sa {
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
};
struct aibuf {
struct addrinfo ai;
union sa sa;
};
/* Extra slots needed for storing canonical name */
#define EXTRA ((256+sizeof(struct aibuf)-1)/sizeof(struct aibuf))
int getaddrinfo(const char *host, const char *serv, const struct addrinfo *hint, struct addrinfo **res)
{
int flags = hint ? hint->ai_flags : 0;
int family = hint ? hint->ai_family : AF_UNSPEC;
int type = hint ? hint->ai_socktype : 0;
int proto = hint ? hint->ai_protocol : 0;
unsigned long port = 0;
struct aibuf *buf;
union sa sa = {{0}};
unsigned char reply[1024];
int i, j;
//char hostbuf[256];
char line[512];
FILE *f, _f;
unsigned char _buf[64];
char *z;
int result;
int cnt;
if (host && strlen(host)>255) return EAI_NONAME;
if (serv && strlen(serv)>32) return EAI_SERVICE;
if (type && !proto)
proto = type==SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP;
if (!type && proto)
type = proto==IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
if (serv) {
port = strtoul(serv, &z, 0);
if (!*z && port > 65535) return EAI_SERVICE;
if (!port) {
if (flags & AI_NUMERICSERV) return EAI_SERVICE;
//f = fopen("/etc/services", "rb");
return EAI_SERVICE;
}
port = htons(port);
}
if (!host) {
if (family == AF_UNSPEC) family = AF_INET;
buf = calloc(sizeof *buf, 1+EXTRA);
if (!buf) return EAI_MEMORY;
buf->ai.ai_protocol = proto;
buf->ai.ai_socktype = type;
buf->ai.ai_addr = (void *)&buf->sa;
buf->ai.ai_addrlen = family==AF_INET6 ? sizeof sa.sin6 : sizeof sa.sin;
buf->ai.ai_family = family;
buf->sa.sin.sin_family = family;
buf->sa.sin.sin_port = port;
if (!(flags & AI_PASSIVE)) {
if (family == AF_INET) {
0[(uint8_t*)&buf->sa.sin.sin_addr.s_addr]=127;
3[(uint8_t*)&buf->sa.sin.sin_addr.s_addr]=1;
} else buf[0].sa.sin6.sin6_addr.s6_addr[15] = 1;
}
*res = &buf->ai;
return 0;
}
/* Try as a numeric address */
if (__ipparse(&sa, family, host) >= 0) {
buf = calloc(sizeof *buf, 1+EXTRA);
if (!buf) return EAI_MEMORY;
family = sa.sin.sin_family;
buf->ai.ai_protocol = proto;
buf->ai.ai_socktype = type;
buf->ai.ai_addr = (void *)&buf->sa;
buf->ai.ai_addrlen = family==AF_INET6 ? sizeof sa.sin6 : sizeof sa.sin;
buf->ai.ai_family = family;
buf->sa = sa;
buf->sa.sin.sin_port = port;
*res = &buf->ai;
return 0;
}
if (flags & AI_NUMERICHOST) return EAI_NONAME;
f = __fopen_rb_ca("/etc/hosts", &_f, _buf, sizeof _buf);
if (f) while (fgets(line, sizeof line, f)) {
char *p;
size_t l = strlen(host);
if ((p=strchr(line, '#'))) *p++='\n', *p=0;
for(p=line+1; (p=strstr(p, host)) &&
(!isspace(p[-1]) || !isspace(p[l])); p++);
if (!p) continue;
__fclose_ca(f);
/* Isolate IP address to parse */
for (p=line; *p && !isspace(*p); p++);
*p++ = 0;
if (__ipparse(&sa, family, line) < 0) return EAI_NONAME;
/* Allocate and fill result buffer */
buf = calloc(sizeof *buf, 1+EXTRA);
if (!buf) return EAI_MEMORY;
family = sa.sin.sin_family;
buf->ai.ai_protocol = proto;
buf->ai.ai_socktype = type;
buf->ai.ai_addr = (void *)&buf->sa;
buf->ai.ai_addrlen = family==AF_INET6 ? sizeof sa.sin6 : sizeof sa.sin;
buf->ai.ai_family = family;
buf->sa = sa;
buf->sa.sin.sin_port = port;
/* Extract first name as canonical name */
for (; *p && isspace(*p); p++);
buf->ai.ai_canonname = (void *)(buf+1);
snprintf(buf->ai.ai_canonname, 256, "%s", p);
for (p=buf->ai.ai_canonname; *p && !isspace(*p); p++);
*p = 0;
if (!is_valid(buf->ai.ai_canonname))
buf->ai.ai_canonname = 0;
*res = &buf->ai;
return 0;
}
if (f) __fclose_ca(f);
#if 0
f = __fopen_rb_ca("/etc/resolv.conf", &_f, _buf, sizeof _buf);
if (f) while (fgets(line, sizeof line, f)) {
if (!isspace(line[10]) || (strncmp(line, "search", 6)
&& strncmp(line, "domain", 6))) continue;
}
if (f) __fclose_ca(f);
#endif
/* Perform one or more DNS queries for host */
memset(reply, 0, sizeof reply);
result = __dns_query(reply, host, family, 0);
if (result < 0) return result;
cnt = __dns_count_addrs(reply, result);
if (cnt <= 0) return EAI_NONAME;
buf = calloc(sizeof *buf, cnt+EXTRA);
if (!buf) return EAI_MEMORY;
i = 0;
if (family != AF_INET6) {
j = __dns_get_rr(&buf[i].sa.sin.sin_addr, sizeof *buf, 4, cnt-i, reply, RR_A, 0);
while (j--) buf[i++].sa.sin.sin_family = AF_INET;
}
if (family != AF_INET) {
j = __dns_get_rr(&buf[i].sa.sin6.sin6_addr, sizeof *buf, 16, cnt-i, reply, RR_AAAA, 0);
while (j--) buf[i++].sa.sin.sin_family = AF_INET6;
}
if (result>1) {
j = __dns_get_rr(&buf[i].sa.sin.sin_addr, sizeof *buf, 4, cnt-i, reply+512, RR_A, 0);
while (j--) buf[i++].sa.sin.sin_family = AF_INET;
j = __dns_get_rr(&buf[i].sa.sin6.sin6_addr, sizeof *buf, 16, cnt-i, reply+512, RR_AAAA, 0);
while (j--) buf[i++].sa.sin.sin_family = AF_INET6;
}
if (__dns_get_rr((void *)&buf[cnt], 0, 256, 1, reply, RR_CNAME, 1) < 0)
strcpy((void *)&buf[cnt], host);
for (i=0; i<cnt; i++) {
buf[i].ai.ai_protocol = proto;
buf[i].ai.ai_socktype = type;
buf[i].ai.ai_addr = (void *)&buf[i].sa;
buf[i].ai.ai_addrlen = buf[i].sa.sin.sin_family==AF_INET6
? sizeof sa.sin6 : sizeof sa.sin;
buf[i].ai.ai_family = buf[i].sa.sin.sin_family;
buf[i].sa.sin.sin_port = port;
buf[i].ai.ai_next = &buf[i+1].ai;
buf[i].ai.ai_canonname = (void *)&buf[cnt];
}
buf[cnt-1].ai.ai_next = 0;
*res = &buf->ai;
return 0;
}

View file

@ -0,0 +1,15 @@
#define _GNU_SOURCE
#include <netdb.h>
#include <string.h>
#include <netinet/in.h>
struct hostent *gethostbyaddr(const void *a, socklen_t l, int af)
{
static struct hostent h;
static long buf[512/sizeof(long)];
struct hostent *res;
if (gethostbyaddr_r(a, l, af, &h,
(void *)buf, sizeof buf, &res, &h_errno)) return 0;
return &h;
}

View file

@ -0,0 +1,71 @@
#define _GNU_SOURCE
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <netinet/in.h>
#include <errno.h>
#include <inttypes.h>
int gethostbyaddr_r(const void *a, socklen_t l, int af,
struct hostent *h, char *buf, size_t buflen,
struct hostent **res, int *err)
{
union {
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
} sa = { .sin.sin_family = af };
socklen_t sl = af==AF_INET6 ? sizeof sa.sin6 : sizeof sa.sin;
int i;
/* Load address argument into sockaddr structure */
if (af==AF_INET6 && l==16) memcpy(&sa.sin6.sin6_addr, a, 16);
else if (af==AF_INET && l==4) memcpy(&sa.sin.sin_addr, a, 4);
else {
*err = NO_RECOVERY;
return -1;
}
/* Align buffer and check for space for pointers and ip address */
i = (uintptr_t)buf & sizeof(char *)-1;
if (!i) i = sizeof(char *);
if (buflen <= 5*sizeof(char *)-i + l) {
errno = ERANGE;
return -1;
}
buf += sizeof(char *)-i;
buflen -= 5*sizeof(char *)-i + l;
h->h_addr_list = (void *)buf;
buf += 2*sizeof(char *);
h->h_aliases = (void *)buf;
buf += 2*sizeof(char *);
h->h_addr_list[0] = buf;
memcpy(h->h_addr_list[0], a, l);
buf += l;
h->h_addr_list[1] = 0;
h->h_aliases[0] = buf;
h->h_aliases[1] = 0;
switch (getnameinfo((void *)&sa, sl, buf, buflen, 0, 0, 0)) {
case EAI_AGAIN:
*err = TRY_AGAIN;
return -1;
case EAI_OVERFLOW:
errno = ERANGE;
default:
case EAI_MEMORY:
case EAI_SYSTEM:
case EAI_FAIL:
*err = NO_RECOVERY;
return -1;
case 0:
break;
}
h->h_addrtype = af;
h->h_name = h->h_aliases[0];
*res = h;
return 0;
}

View file

@ -0,0 +1,63 @@
#define _GNU_SOURCE
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <netinet/in.h>
struct hostent *gethostbyname(const char *name)
{
return gethostbyname2(name, AF_INET);
}
#if 0
struct hostent *gethostbyname(const char *name)
{
static struct hostent h;
static char *h_aliases[3];
static char h_canon[256];
static char *h_addr_list[10];
static char h_addr_data[10][4];
static const struct addrinfo hint = {
.ai_family = AF_INET, .ai_flags = AI_CANONNAME
};
struct addrinfo *ai, *p;
int i;
switch (getaddrinfo(name, 0, &hint, &ai)) {
case EAI_NONAME:
h_errno = HOST_NOT_FOUND;
break;
case EAI_AGAIN:
h_errno = TRY_AGAIN;
break;
case EAI_FAIL:
h_errno = NO_RECOVERY;
break;
default:
case EAI_MEMORY:
case EAI_SYSTEM:
h_errno = NO_DATA;
break;
case 0:
break;
}
strcpy(h_canon, ai->ai_canonname);
h.h_name = h_canon;
h.h_aliases = h_aliases;
h.h_aliases[0] = h_canon;
h.h_aliases[1] = strcmp(h_canon, name) ? (char *)name : 0;
h.h_length = 4;
h.h_addr_list = h_addr_list;
for (i=0, p=ai; i<sizeof h_addr_data/4 && p; i++, p=p->ai_next) {
h.h_addr_list[i] = h_addr_data[i];
memcpy(h.h_addr_list[i],
&((struct sockaddr_in *)p->ai_addr)->sin_addr, 4);
}
h.h_addr_list[i] = 0;
h.h_addrtype = AF_INET;
freeaddrinfo(ai);
return &h;
}
#endif

View file

@ -0,0 +1,16 @@
#define _GNU_SOURCE
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <netinet/in.h>
struct hostent *gethostbyname2(const char *name, int af)
{
static struct hostent h;
static long buf[512/sizeof(long)];
struct hostent *res;
if (gethostbyname2_r(name, af, &h,
(void *)buf, sizeof buf, &res, &h_errno)) return 0;
return &h;
}

View file

@ -0,0 +1,99 @@
#define _GNU_SOURCE
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <netinet/in.h>
#include <errno.h>
#include <inttypes.h>
int gethostbyname2_r(const char *name, int af,
struct hostent *h, char *buf, size_t buflen,
struct hostent **res, int *err)
{
struct addrinfo hint = {
.ai_family = af==AF_INET6 ? af : AF_INET,
.ai_flags = AI_CANONNAME
};
struct addrinfo *ai, *p;
int i;
size_t need;
const char *canon;
af = hint.ai_family;
/* Align buffer */
i = (uintptr_t)buf & sizeof(char *)-1;
if (i) {
if (buflen < sizeof(char *)-i) {
errno = ERANGE;
return -1;
}
buf += sizeof(char *)-i;
buflen -= sizeof(char *)-i;
}
getaddrinfo(name, 0, &hint, &ai);
switch (getaddrinfo(name, 0, &hint, &ai)) {
case EAI_NONAME:
*err = HOST_NOT_FOUND;
return -1;
case EAI_AGAIN:
*err = TRY_AGAIN;
return -1;
default:
case EAI_MEMORY:
case EAI_SYSTEM:
case EAI_FAIL:
*err = NO_RECOVERY;
return -1;
case 0:
break;
}
h->h_addrtype = af;
h->h_length = af==AF_INET6 ? 16 : 4;
canon = ai->ai_canonname ? ai->ai_canonname : name;
need = 4*sizeof(char *);
for (i=0, p=ai; p; i++, p=p->ai_next)
need += sizeof(char *) + h->h_length;
need += strlen(name)+1;
need += strlen(canon)+1;
if (need > buflen) {
freeaddrinfo(ai);
errno = ERANGE;
return -1;
}
h->h_aliases = (void *)buf;
buf += 3*sizeof(char *);
h->h_addr_list = (void *)buf;
buf += (i+1)*sizeof(char *);
h->h_name = h->h_aliases[0] = buf;
strcpy(h->h_name, canon);
buf += strlen(h->h_name)+1;
if (strcmp(h->h_name, name)) {
h->h_aliases[1] = buf;
strcpy(h->h_aliases[1], name);
buf += strlen(h->h_aliases[1])+1;
} else h->h_aliases[1] = 0;
h->h_aliases[2] = 0;
for (i=0, p=ai; p; i++, p=p->ai_next) {
h->h_addr_list[i] = (void *)buf;
buf += h->h_length;
memcpy(h->h_addr_list[i],
&((struct sockaddr_in *)p->ai_addr)->sin_addr,
h->h_length);
}
h->h_addr_list[i] = 0;
*res = h;
freeaddrinfo(ai);
return 0;
}

View file

@ -0,0 +1,11 @@
#define _GNU_SOURCE
#include <sys/socket.h>
#include <netdb.h>
int gethostbyname_r(const char *name,
struct hostent *h, char *buf, size_t buflen,
struct hostent **res, int *err)
{
return gethostbyname2_r(name, AF_INET, h, buf, buflen, res, err);
}

View file

@ -0,0 +1,54 @@
#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;
}

View file

@ -0,0 +1,7 @@
#include <sys/socket.h>
#include "syscall.h"
int getpeername(int fd, struct sockaddr *addr, socklen_t *len)
{
return socketcall(getpeername, fd, addr, len, 0, 0, 0);
}

View file

@ -0,0 +1,12 @@
#define _GNU_SOURCE
#include <netdb.h>
struct servent *getservbyname(const char *name, const char *prots)
{
static struct servent se;
static long buf[32/sizeof(long)];
struct servent *res;
if (getservbyname_r(name, prots, &se, (void *)buf, sizeof buf, &res))
return 0;
return &se;
}

View file

@ -0,0 +1,41 @@
#define _GNU_SOURCE
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <inttypes.h>
#include <errno.h>
#include <string.h>
int getservbyname_r(const char *name, const char *prots,
struct servent *se, char *buf, size_t buflen, struct servent **res)
{
struct addrinfo *ai, hint = { .ai_family = AF_INET };
int i;
/* Align buffer */
i = (uintptr_t)buf & sizeof(char *)-1;
if (!i) i = sizeof(char *);
if (buflen < 3*sizeof(char *)-i) {
errno = ERANGE;
return -1;
}
buf += sizeof(char *)-i;
buflen -= sizeof(char *)-i;
if (!strcmp(prots, "tcp")) hint.ai_protocol = IPPROTO_TCP;
else if (!strcmp(prots, "udp")) hint.ai_protocol = IPPROTO_UDP;
else return -1;
if (getaddrinfo(0, name, &hint, &ai) < 0) return -1;
se->s_name = (char *)name;
se->s_aliases = (void *)buf;
se->s_aliases[0] = se->s_name;
se->s_aliases[1] = 0;
se->s_port = ((struct sockaddr_in *)ai->ai_addr)->sin_port;
se->s_proto = (char *)prots;
freeaddrinfo(ai);
*res = se;
return 0;
}

View file

@ -0,0 +1,12 @@
#define _GNU_SOURCE
#include <netdb.h>
struct servent *getservbyport(int port, const char *prots)
{
static struct servent se;
static long buf[32/sizeof(long)];
struct servent *res;
if (getservbyport_r(port, prots, &se, (void *)buf, sizeof buf, &res))
return 0;
return &se;
}

View file

@ -0,0 +1,43 @@
#define _GNU_SOURCE
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <inttypes.h>
#include <errno.h>
#include <string.h>
int getservbyport_r(int port, const char *prots,
struct servent *se, char *buf, size_t buflen, struct servent **res)
{
int i;
struct sockaddr_in sin = {
.sin_family = AF_INET,
.sin_port = port,
};
/* Align buffer */
i = (uintptr_t)buf & sizeof(char *)-1;
if (!i) i = sizeof(char *);
if (buflen < 3*sizeof(char *)-i) {
errno = ERANGE;
return -1;
}
buf += sizeof(char *)-i;
buflen -= sizeof(char *)-i;
if (strcmp(prots, "tcp") && strcmp(prots, "udp")) return -1;
se->s_port = port;
se->s_proto = (char *)prots;
se->s_aliases = (void *)buf;
buf += 2*sizeof(char *);
buflen -= 2*sizeof(char *);
se->s_aliases[1] = 0;
se->s_aliases[0] = se->s_name = buf;
if (getnameinfo((void *)&sin, sizeof sin, 0, 0, buf, buflen,
strcmp(prots, "udp") ? 0 : NI_DGRAM) < 0) return -1;
*res = se;
return 0;
}

View file

@ -0,0 +1,7 @@
#include <sys/socket.h>
#include "syscall.h"
int getsockname(int fd, struct sockaddr *addr, socklen_t *len)
{
return socketcall(getsockname, fd, addr, len, 0, 0, 0);
}

View file

@ -0,0 +1,7 @@
#include <sys/socket.h>
#include "syscall.h"
int getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen)
{
return socketcall(getsockopt, fd, level, optname, optval, optlen, 0);
}

View file

@ -0,0 +1 @@
int h_errno;

View file

@ -0,0 +1,16 @@
#define _GNU_SOURCE
#include <netdb.h>
static const char msgs[] =
"Host not found\0"
"Try again\0"
"Non-recoverable error\0"
"Address not available\0"
"\0Unknown error";
const char *hstrerror(int ecode)
{
const char *s;
for (s=msgs, ecode--; ecode && *s; ecode--, s++) for (; *s; s++);
return *s ? s : s+1;
}

View file

@ -0,0 +1,10 @@
#include <netinet/in.h>
uint32_t htonl(uint32_t n)
{
union {
uint8_t b[4];
uint32_t i;
} u = { { n>>24, n>>16, n>>8, n } };
return u.i;
}

View file

@ -0,0 +1,10 @@
#include <netinet/in.h>
uint16_t htons(uint16_t n)
{
union {
uint8_t b[2];
uint16_t s;
} u = { { n>>8, n } };
return u.s;
}

View file

@ -0,0 +1,3 @@
#include <netinet/in.h>
const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;

View file

@ -0,0 +1,3 @@
#include <netinet/in.h>
const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;

View file

@ -0,0 +1,11 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "__dns.h"
in_addr_t inet_addr(const char *p)
{
struct sockaddr_in sin;
if (__ipparse(&sin, AF_INET, p)) return -1;
return sin.sin_addr.s_addr;
}

View file

@ -0,0 +1,7 @@
#include <sys/socket.h>
#include <arpa/inet.h>
int inet_aton(const char *cp, struct in_addr *inp)
{
return inet_pton(AF_INET, cp, (void *)inp) > 0;
}

View file

@ -0,0 +1,10 @@
#include <arpa/inet.h>
#include <stdio.h>
char *inet_ntoa(struct in_addr in)
{
static char buf[16];
unsigned char *a = (void *)&in;
snprintf(buf, sizeof buf, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
return buf;
}

View file

@ -0,0 +1,48 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
const char *inet_ntop(int af, const void *a0, char *s, socklen_t l)
{
const unsigned char *a = a0;
int i, j, max, best;
char buf[100];
switch (af) {
case AF_INET:
if (snprintf(s, l, "%d.%d.%d.%d", a[0],a[1],a[2],a[3]) < l)
return s;
break;
case AF_INET6:
memset(buf, 'x', sizeof buf);
buf[sizeof buf-1]=0;
snprintf(buf, sizeof buf,
"%.0x%x:%.0x%x:%.0x%x:%.0x%x:%.0x%x:%.0x%x:%.0x%x:%.0x%x",
a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],
a[8],a[9],a[10],a[11],a[12],a[13],a[14],a[15]);
/* Replace longest /(^0|:)[:0]{2,}/ with "::" */
for (i=best=0, max=2; buf[i]; i++) {
if (i && buf[i] != ':') continue;
j = strspn(buf+i, ":0");
if (j>max) best=i, max=j;
}
if (max>2) {
buf[best] = buf[best+1] = ':';
strcpy(buf+best+2, buf+best+max);
}
if (strlen(buf) < l) {
strcpy(s, buf);
return s;
}
break;
default:
errno = EAFNOSUPPORT;
return 0;
}
errno = ENOSPC;
return 0;
}

View file

@ -0,0 +1,31 @@
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include "__dns.h"
int inet_pton(int af, const char *s, void *a0)
{
unsigned char *a = a0;
const char *z;
unsigned long x;
int i;
/* Reimplement this because inet_pton cannot accept special v4 forms */
if (af==AF_INET) {
for (i=0; i<4 && *s; i++) {
a[i] = x = strtoul(s, (char **)&z, 10);
if (!isdigit(*s) || z==s || (*z && *z != '.') || x>255)
return 0;
s=z+1;
}
return 0;
} else if (af==AF_INET6) {
return !__ipparse(a, AF_INET6, s);
}
errno = EAFNOSUPPORT;
return 0;
}

View file

@ -0,0 +1,7 @@
#include <sys/socket.h>
#include "syscall.h"
int listen(int fd, int backlog)
{
return socketcall(listen, fd, backlog, 0, 0, 0, 0);
}

View file

@ -0,0 +1,10 @@
#include <netinet/in.h>
uint32_t ntohl(uint32_t n)
{
union {
uint32_t i;
uint8_t b[4];
} u = { n };
return (u.b[0]<<24) | (u.b[1]<<16) | (u.b[2]<<8) | u.b[3];
}

View file

@ -0,0 +1,10 @@
#include <netinet/in.h>
uint16_t ntohs(uint16_t n)
{
union {
uint16_t s;
uint8_t b[2];
} u = { n };
return (u.b[0]<<8) | u.b[1];
}

View file

@ -0,0 +1,58 @@
#include <netdb.h>
#include <stdio.h>
#include <string.h>
/* do we really need all these?? */
static int idx;
static const unsigned char protos[][6] = {
"\000ip",
"\001icmp",
"\002igmp",
"\003ggp",
"\006tcp",
"\014pup",
"\021udp",
"\026idp",
"\377raw"
"\0\0"
};
void endprotoent(void)
{
idx = 0;
}
void setprotoent(int stayopen)
{
idx = 0;
}
struct protoent *getprotoent(void)
{
static struct protoent p;
static const char *aliases;
if (!protos[idx][1]) return NULL;
p.p_proto = protos[idx][0];
p.p_name = (char *)protos[idx++]+1;
p.p_aliases = (char **)&aliases;
return &p;
}
struct protoent *getprotobyname(const char *name)
{
struct protoent *p;
endprotoent();
do p = getprotoent();
while (p && strcmp(name, p->p_name));
return p;
}
struct protoent *getprotobynumber(int num)
{
struct protoent *p;
endprotoent();
do p = getprotoent();
while (p && p->p_proto != num);
return p;
}

View file

@ -0,0 +1,8 @@
#include <sys/socket.h>
#include "syscall.h"
#include "libc.h"
ssize_t recv(int fd, void *buf, size_t len, int flags)
{
return recvfrom(fd, buf, len, flags, 0, 0);
}

View file

@ -0,0 +1,12 @@
#include <sys/socket.h>
#include "syscall.h"
#include "libc.h"
ssize_t recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *alen)
{
ssize_t r;
CANCELPT_BEGIN;
r = socketcall(recvfrom, fd, buf, len, flags, addr, alen);
CANCELPT_END;
return r;
}

View file

@ -0,0 +1,12 @@
#include <sys/socket.h>
#include "syscall.h"
#include "libc.h"
ssize_t recvmsg(int fd, struct msghdr *msg, int flags)
{
ssize_t r;
CANCELPT_BEGIN;
r = socketcall(recvmsg, fd, msg, flags, 0, 0, 0);
CANCELPT_END;
return r;
}

View file

@ -0,0 +1,4 @@
int res_init()
{
return 0;
}

View file

@ -0,0 +1,20 @@
#include <netdb.h>
#include "__dns.h"
int res_query(const char *name, int class, int type, unsigned char *dest, int len)
{
if (class != 1 || len < 512)
return -1;
switch(__dns_doqueries(dest, name, &type, 1)) {
case EAI_NONAME:
h_errno = HOST_NOT_FOUND;
return -1;
case EAI_AGAIN:
h_errno = TRY_AGAIN;
return -1;
case EAI_FAIL:
h_errno = NO_RECOVERY;
return -1;
}
return 512;
}

View file

@ -0,0 +1,8 @@
#include <sys/socket.h>
#include "syscall.h"
#include "libc.h"
ssize_t send(int fd, const void *buf, size_t len, int flags)
{
return sendto(fd, buf, len, flags, 0, 0);
}

View file

@ -0,0 +1,12 @@
#include <sys/socket.h>
#include "syscall.h"
#include "libc.h"
ssize_t sendmsg(int fd, const struct msghdr *msg, int flags)
{
ssize_t r;
CANCELPT_BEGIN;
r = socketcall(sendmsg, fd, msg, flags, 0, 0, 0);
CANCELPT_END;
return r;
}

View file

@ -0,0 +1,12 @@
#include <sys/socket.h>
#include "syscall.h"
#include "libc.h"
ssize_t sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t alen)
{
ssize_t r;
CANCELPT_BEGIN;
r = socketcall(sendto, fd, buf, len, flags, addr, alen);
CANCELPT_END;
return r;
}

View file

@ -0,0 +1,16 @@
#include <netdb.h>
#include <stdio.h>
#include <string.h>
void endservent(void)
{
}
void setservent(int stayopen)
{
}
struct servent *getservent(void)
{
return 0;
}

View file

@ -0,0 +1,7 @@
#include <sys/socket.h>
#include "syscall.h"
int setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen)
{
return socketcall(setsockopt, fd, level, optname, optval, optlen, 0);
}

View file

@ -0,0 +1,7 @@
#include <sys/socket.h>
#include "syscall.h"
int shutdown(int fd, int how)
{
return socketcall(shutdown, fd, how, 0, 0, 0, 0);
}

View file

@ -0,0 +1,10 @@
#include <sys/socket.h>
#include <sys/ioctl.h>
int sockatmark(int s)
{
int ret;
if (ioctl(s, SIOCATMARK, &ret) < 0)
return -1;
return ret;
}

View file

@ -0,0 +1,7 @@
#include <sys/socket.h>
#include "syscall.h"
int socket(int domain, int type, int protocol)
{
return socketcall(socket, domain, type, protocol, 0, 0, 0);
}

View file

@ -0,0 +1,7 @@
#include <sys/socket.h>
#include "syscall.h"
int socketpair(int domain, int type, int protocol, int fd[2])
{
return socketcall(socketpair, domain, type, protocol, fd, 0, 0);
}