Initial implementation of namesys/dns.c
This commit is contained in:
parent
ac4cc8feaa
commit
a21330af43
2 changed files with 228 additions and 2 deletions
|
@ -8,12 +8,16 @@
|
||||||
NULL,
|
NULL,
|
||||||
"ErrAllocFailed",
|
"ErrAllocFailed",
|
||||||
"ErrNULLPointer",
|
"ErrNULLPointer",
|
||||||
|
"ErrPipe",
|
||||||
|
"ErrPoll",
|
||||||
"Could not publish name."
|
"Could not publish name."
|
||||||
"Could not resolve name.",
|
"Could not resolve name.",
|
||||||
"Could not resolve name (recursion limit exceeded).",
|
"Could not resolve name (recursion limit exceeded).",
|
||||||
"expired record",
|
"expired record",
|
||||||
"unrecognized validity type",
|
"unrecognized validity type",
|
||||||
"not a valid proquint string"
|
"not a valid proquint string",
|
||||||
|
"not a valid domain name",
|
||||||
|
"not a valid dnslink entry"
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
extern char *ErrNamesys;
|
extern char *ErrNamesys;
|
||||||
|
@ -22,12 +26,16 @@
|
||||||
enum {
|
enum {
|
||||||
ErrAllocFailed = 1,
|
ErrAllocFailed = 1,
|
||||||
ErrNULLPointer,
|
ErrNULLPointer,
|
||||||
|
ErrPipe,
|
||||||
|
ErrPoll,
|
||||||
ErrPublishFailed,
|
ErrPublishFailed,
|
||||||
ErrResolveFailed,
|
ErrResolveFailed,
|
||||||
ErrResolveRecursion,
|
ErrResolveRecursion,
|
||||||
ErrExpiredRecord,
|
ErrExpiredRecord,
|
||||||
ErrUnrecognizedValidity,
|
ErrUnrecognizedValidity,
|
||||||
ErrInvalidProquint
|
ErrInvalidProquint,
|
||||||
|
ErrInvalidDomain,
|
||||||
|
ErrInvalidDNSLink
|
||||||
} NamesysErrs;
|
} NamesysErrs;
|
||||||
|
|
||||||
typedef struct s_resolvers {
|
typedef struct s_resolvers {
|
||||||
|
@ -73,4 +81,9 @@
|
||||||
int IsExtendedTLD (char *s);
|
int IsExtendedTLD (char *s);
|
||||||
int IsTLD (char *s);
|
int IsTLD (char *s);
|
||||||
int IsDomain (char *s);
|
int IsDomain (char *s);
|
||||||
|
|
||||||
|
int DNSResolverResolveOnce (DNSResolver *r, char **path, char *name);
|
||||||
|
int workDomain (int output, DNSResolver *r, char *name);
|
||||||
|
int parseEntry (char **Path, char *txt);
|
||||||
|
int tryParseDnsLink (char **Path, char *txt);
|
||||||
#endif //NAMESYS_H
|
#endif //NAMESYS_H
|
||||||
|
|
213
namesys/dns.c
Normal file
213
namesys/dns.c
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include "ipfs/cid/cid.h"
|
||||||
|
#include "ipfs/path/path.h"
|
||||||
|
#include "ipfs/namesys/namesys.h"
|
||||||
|
|
||||||
|
/*type LookupTXTFunc func(name string) (txt []string, err error)
|
||||||
|
|
||||||
|
// DNSResolver implements a Resolver on DNS domains
|
||||||
|
type DNSResolver struct {
|
||||||
|
lookupTXT LookupTXTFunc
|
||||||
|
// TODO: maybe some sort of caching?
|
||||||
|
// cache would need a timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDNSResolver constructs a name resolver using DNS TXT records.
|
||||||
|
func NewDNSResolver() Resolver {
|
||||||
|
return &DNSResolver{lookupTXT: net.LookupTXT}
|
||||||
|
}
|
||||||
|
|
||||||
|
// newDNSResolver constructs a name resolver using DNS TXT records,
|
||||||
|
// returning a resolver instead of NewDNSResolver's Resolver.
|
||||||
|
func newDNSResolver() resolver {
|
||||||
|
return &DNSResolver{lookupTXT: net.LookupTXT}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve implements Resolver.
|
||||||
|
func (r *DNSResolver) Resolve(ctx context.Context, name string) (path.Path, error) {
|
||||||
|
return r.ResolveN(ctx, name, DefaultDepthLimit)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResolveN implements Resolver.
|
||||||
|
func (r *DNSResolver) ResolveN(ctx context.Context, name string, depth int) (path.Path, error) {
|
||||||
|
return resolve(ctx, r, name, depth, "/ipns/")
|
||||||
|
}
|
||||||
|
|
||||||
|
type lookupRes struct {
|
||||||
|
path path.Path
|
||||||
|
error error
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// resolveOnce implements resolver.
|
||||||
|
// TXT records for a given domain name should contain a b58
|
||||||
|
// encoded multihash.
|
||||||
|
int DNSResolverResolveOnce (char **path, char *name)
|
||||||
|
{
|
||||||
|
char **segments, *domain, *dnslink, buf[500], dlprefix[] = "_dnslink.";
|
||||||
|
int p1[2], p2[2], r, c=2;
|
||||||
|
struct pollfd event[2], *e;
|
||||||
|
|
||||||
|
segments = SplitN(name, "/", 2);
|
||||||
|
domain = segments[0];
|
||||||
|
|
||||||
|
*path = NULL;
|
||||||
|
|
||||||
|
if (!IsDomain(domain)) {
|
||||||
|
return ErrInvalidDomain;
|
||||||
|
}
|
||||||
|
//log.Infof("DNSResolver resolving %s", domain);
|
||||||
|
|
||||||
|
if (pipe(p1) || pipe(p2)) {
|
||||||
|
return ErrPipe;
|
||||||
|
}
|
||||||
|
|
||||||
|
dnslink = malloc(strlen(domain) + sizeof(dlprefix));
|
||||||
|
if (!dnslink) {
|
||||||
|
return ErrAllocFailed;
|
||||||
|
}
|
||||||
|
strcpy (dnslink, dlprefix);
|
||||||
|
strcat (dnslink, domain);
|
||||||
|
|
||||||
|
r = fork();
|
||||||
|
switch(r) {
|
||||||
|
case -1:
|
||||||
|
return ErrPipe;
|
||||||
|
case 0: // child
|
||||||
|
close(p1[STDIN_FILENO]); // we don't need to read at child process.
|
||||||
|
return workDomain (p1[STDOUT_FILENO], r, domain);
|
||||||
|
}
|
||||||
|
close(p1[STDOUT_FILENO]); // we don't need to write at main process.
|
||||||
|
r = fork();
|
||||||
|
switch(r) {
|
||||||
|
case -1:
|
||||||
|
return ErrPipe;
|
||||||
|
case 0: // child
|
||||||
|
close(p2[STDIN_FILENO]); // we don't need to read at child process.
|
||||||
|
return workDomain (p2[STDOUT_FILENO], r, dnslink);
|
||||||
|
}
|
||||||
|
close(p2[STDOUT_FILENO]); // we don't need to write at main process.
|
||||||
|
|
||||||
|
memset(&event, 0, sizeof(struct pollfd));
|
||||||
|
event[0].fd = p1[STDIN_FILENO];
|
||||||
|
event[0].events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
|
||||||
|
event[1].fd = p2[STDIN_FILENO];
|
||||||
|
event[1].events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
|
||||||
|
e = event;
|
||||||
|
|
||||||
|
do {
|
||||||
|
r = poll(e, c, -1);
|
||||||
|
if (r == -1) {
|
||||||
|
return ErrPoll;
|
||||||
|
}
|
||||||
|
for (r = 0 ; r < c ; r++) {
|
||||||
|
if (e[r].revents & POLLIN) {
|
||||||
|
r = read(e[r].fd, buf, sizeof(buf));
|
||||||
|
if (r > 0) {
|
||||||
|
buf[r] = '\0';
|
||||||
|
*path = malloc(r+1);
|
||||||
|
if (*path) {
|
||||||
|
strcpy(*path, buf);
|
||||||
|
}
|
||||||
|
} else if (r <= 0) {
|
||||||
|
return ErrPoll;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (event[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
|
||||||
|
event[0].events = 0;
|
||||||
|
e++; c--;
|
||||||
|
wait(&r);
|
||||||
|
}
|
||||||
|
if (event[1].revents & (POLLERR | POLLHUP | POLLNVAL)) {
|
||||||
|
event[1].events = 0;
|
||||||
|
c--;
|
||||||
|
wait(&r);
|
||||||
|
}
|
||||||
|
} while (c); // wait for child process finish.
|
||||||
|
|
||||||
|
if (!*path) {
|
||||||
|
return ErrResolveFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SegmentsLength (segments) > 1) {
|
||||||
|
name = *path + strlen(*path) - 1;
|
||||||
|
while (*name == '/') {
|
||||||
|
*name-- = '\0';
|
||||||
|
}
|
||||||
|
name = *path;
|
||||||
|
*path = PathFromSegments (name, segments+1);
|
||||||
|
free (name);
|
||||||
|
if (!*path) {
|
||||||
|
return ErrResolveFailed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreeSegments (&segments);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int workDomain (int output, DNSResolver *r, char *name)
|
||||||
|
{
|
||||||
|
char **txt, *path;
|
||||||
|
int i, err = r->lookupTXT(&txt, name);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0 ; txt[i] ; i++) {
|
||||||
|
err = parseEntry (&path, txt[i]);
|
||||||
|
if (!err) {
|
||||||
|
err = (write (output, path, strlen(path)) != strlen(path));
|
||||||
|
free (path);
|
||||||
|
if (err) {
|
||||||
|
return ErrPipe;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ErrResolveFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
int parseEntry (char **path, char *txt)
|
||||||
|
{
|
||||||
|
char buf[500];
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = ParseCidToPath(buf, txt); // bare IPFS multihashes
|
||||||
|
if (! err) {
|
||||||
|
*path = malloc(strlen(buf) + 1);
|
||||||
|
if (!*path) {
|
||||||
|
return ErrAllocFailed;
|
||||||
|
}
|
||||||
|
strcpy(*path, buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return tryParseDnsLink(path, txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tryParseDnsLink(char **path, char *txt)
|
||||||
|
{
|
||||||
|
char **parts = SplitN(txt, "=", 2), buf[500];
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (SegmentsLength(parts) == 2 && strcmp(parts[0], "dnslink")==0) {
|
||||||
|
err = ParsePath(buf, parts[1]);
|
||||||
|
if (err == 0) {
|
||||||
|
*parts = malloc(strlen(buf) + 1);
|
||||||
|
if (! *parts) {
|
||||||
|
return ErrAllocFailed;
|
||||||
|
}
|
||||||
|
strcpy(*parts, buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
return ErrInvalidDNSLink;
|
||||||
|
}
|
Loading…
Reference in a new issue