mirror of /home/gitosis/repositories/libowfat.git
monster update: add tai, taia, iopause, case, and ipv6 enhanced dns
parent
ffde3478a0
commit
051de3819a
@ -0,0 +1,24 @@
|
||||
libowfat is a library of general purpose APIs extracted from Dan
|
||||
Bernstein's software, reimplemented and covered by the GNU General
|
||||
Public License Version 2 (no later versions).
|
||||
|
||||
The API has been slightly extended (for example, I provide a uint32_read
|
||||
function, and I extended the socket API to support IPv6) where I found
|
||||
it necessary or beneficial in a specific project.
|
||||
|
||||
Many of the functions I implement here have since been placed in the
|
||||
public domain, so there are other sources to get this code (except for
|
||||
my extensions obviously). The implementations here may not be as
|
||||
portable as the original versions; I tend to focus on the Single Unix
|
||||
Specification and not on some obsolete legacy systems found in the
|
||||
basements of some vintage hardware clubs.
|
||||
|
||||
I also provide man pages for many functions, mostly extracted from Dan's
|
||||
web documentation or documentation found in earlier versions of his
|
||||
software. For some reason, he abandoned man pages in favor of HTML
|
||||
recently.
|
||||
|
||||
On July 4 2002, Dan also placed his DNS routines and supporting
|
||||
low level functions in the public domain, so I copy them here instead of
|
||||
reimplementing them. http://online.securityfocus.com/archive/1/280642
|
||||
has an online version of the bugtraq posting.
|
@ -0,0 +1,21 @@
|
||||
#ifndef CASE_H
|
||||
#define CASE_H
|
||||
|
||||
/* turn upper case letters to lower case letters, ASCIIZ */
|
||||
extern void case_lowers(char *s);
|
||||
/* turn upper case letters to lower case letters, binary */
|
||||
extern void case_lowerb(char *buf,unsigned int len);
|
||||
|
||||
/* like str_diff, ignoring case */
|
||||
extern int case_diffs(const char *,const char *);
|
||||
/* like byte_diff, ignoring case */
|
||||
extern int case_diffb(const char *,unsigned int,const char *);
|
||||
|
||||
/* like str_start, ignoring case */
|
||||
extern int case_starts(const char *,const char *);
|
||||
/* alias for case_diffb? */
|
||||
extern int case_startb(const char *,unsigned int,const char *);
|
||||
|
||||
#define case_equals(s,t) (!case_diffs((s),(t)))
|
||||
|
||||
#endif
|
@ -0,0 +1,18 @@
|
||||
#include "case.h"
|
||||
|
||||
int case_diffb(register const char *s,register unsigned int len,register const char *t)
|
||||
{
|
||||
register unsigned char x;
|
||||
register unsigned char y;
|
||||
|
||||
while (len > 0) {
|
||||
--len;
|
||||
x = *s++ - 'A';
|
||||
if (x <= 'Z' - 'A') x += 'a'; else x += 'A';
|
||||
y = *t++ - 'A';
|
||||
if (y <= 'Z' - 'A') y += 'a'; else y += 'A';
|
||||
if (x != y)
|
||||
return ((int)(unsigned int) x) - ((int)(unsigned int) y);
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
#include "case.h"
|
||||
|
||||
int case_diffs(register const char *s,register const char *t)
|
||||
{
|
||||
register unsigned char x;
|
||||
register unsigned char y;
|
||||
|
||||
for (;;) {
|
||||
x = *s++ - 'A';
|
||||
if (x <= 'Z' - 'A') x += 'a'; else x += 'A';
|
||||
y = *t++ - 'A';
|
||||
if (y <= 'Z' - 'A') y += 'a'; else y += 'A';
|
||||
if (x != y) break;
|
||||
if (!x) break;
|
||||
}
|
||||
return ((int)(unsigned int) x) - ((int)(unsigned int) y);
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
#include "case.h"
|
||||
|
||||
void case_lowerb(char *s,unsigned int len) {
|
||||
unsigned char x;
|
||||
while (len > 0) {
|
||||
--len;
|
||||
x = *s - 'A';
|
||||
if (x <= 'Z' - 'A') *s = x + 'a';
|
||||
++s;
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
#include "case.h"
|
||||
|
||||
void case_lowers(char *s) {
|
||||
unsigned char x;
|
||||
for (;;) {
|
||||
if (!(x=*s)) break;
|
||||
if ((x -= 'A') <= 'Z' - 'A') *s = x + 'a';
|
||||
++s;
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
#ifndef DNS_H
|
||||
#define DNS_H
|
||||
|
||||
#include "stralloc.h"
|
||||
#include "iopause.h"
|
||||
#include "taia.h"
|
||||
|
||||
#define DNS_C_IN "\0\1"
|
||||
#define DNS_C_ANY "\0\377"
|
||||
|
||||
#define DNS_T_A "\0\1"
|
||||
#define DNS_T_NS "\0\2"
|
||||
#define DNS_T_CNAME "\0\5"
|
||||
#define DNS_T_SOA "\0\6"
|
||||
#define DNS_T_PTR "\0\14"
|
||||
#define DNS_T_HINFO "\0\15"
|
||||
#define DNS_T_MX "\0\17"
|
||||
#define DNS_T_TXT "\0\20"
|
||||
#define DNS_T_RP "\0\21"
|
||||
#define DNS_T_SIG "\0\30"
|
||||
#define DNS_T_KEY "\0\31"
|
||||
#define DNS_T_AAAA "\0\34"
|
||||
#define DNS_T_AXFR "\0\374"
|
||||
#define DNS_T_ANY "\0\377"
|
||||
|
||||
struct dns_transmit {
|
||||
char *query; /* 0, or dynamically allocated */
|
||||
unsigned int querylen;
|
||||
char *packet; /* 0, or dynamically allocated */
|
||||
unsigned int packetlen;
|
||||
int s1; /* 0, or 1 + an open file descriptor */
|
||||
int tcpstate;
|
||||
unsigned int udploop;
|
||||
unsigned int curserver;
|
||||
struct taia deadline;
|
||||
unsigned int pos;
|
||||
const char *servers;
|
||||
char localip[16];
|
||||
unsigned int scope_id;
|
||||
char qtype[2];
|
||||
} ;
|
||||
|
||||
extern void dns_random_init(const char *);
|
||||
extern unsigned int dns_random(unsigned int);
|
||||
|
||||
extern void dns_sortip(char *,unsigned int);
|
||||
extern void dns_sortip6(char *,unsigned int);
|
||||
|
||||
extern void dns_domain_free(char **);
|
||||
extern int dns_domain_copy(char **,const char *);
|
||||
extern unsigned int dns_domain_length(const char *);
|
||||
extern int dns_domain_equal(const char *,const char *);
|
||||
extern int dns_domain_suffix(const char *,const char *);
|
||||
extern unsigned int dns_domain_suffixpos(const char *,const char *);
|
||||
extern int dns_domain_fromdot(char **,const char *,unsigned int);
|
||||
extern int dns_domain_todot_cat(stralloc *,const char *);
|
||||
|
||||
extern unsigned int dns_packet_copy(const char *,unsigned int,unsigned int,char *,unsigned int);
|
||||
extern unsigned int dns_packet_getname(const char *,unsigned int,unsigned int,char **);
|
||||
extern unsigned int dns_packet_skipname(const char *,unsigned int,unsigned int);
|
||||
|
||||
extern int dns_transmit_start(struct dns_transmit *,const char *,int,const char *,const char *,const char *);
|
||||
extern void dns_transmit_free(struct dns_transmit *);
|
||||
extern void dns_transmit_io(struct dns_transmit *,iopause_fd *,struct taia *);
|
||||
extern int dns_transmit_get(struct dns_transmit *,const iopause_fd *,const struct taia *);
|
||||
|
||||
extern int dns_resolvconfip(char *);
|
||||
extern int dns_resolve(const char *,const char *);
|
||||
extern struct dns_transmit dns_resolve_tx;
|
||||
|
||||
extern int dns_ip4_packet(stralloc *,const char *,unsigned int);
|
||||
extern int dns_ip4(stralloc *,const stralloc *);
|
||||
extern int dns_ip6_packet(stralloc *,char *,unsigned int);
|
||||
extern int dns_ip6(stralloc *,stralloc *);
|
||||
extern int dns_name_packet(stralloc *,const char *,unsigned int);
|
||||
extern void dns_name4_domain(char *,const char *);
|
||||
#define DNS_NAME4_DOMAIN 31
|
||||
extern int dns_name4(stralloc *,const char *);
|
||||
extern int dns_txt_packet(stralloc *,const char *,unsigned int);
|
||||
extern int dns_txt(stralloc *,const stralloc *);
|
||||
extern int dns_mx_packet(stralloc *,const char *,unsigned int);
|
||||
extern int dns_mx(stralloc *,const stralloc *);
|
||||
|
||||
extern int dns_resolvconfrewrite(stralloc *);
|
||||
extern int dns_ip4_qualify_rules(stralloc *,stralloc *,const stralloc *,const stralloc *);
|
||||
extern int dns_ip4_qualify(stralloc *,stralloc *,const stralloc *);
|
||||
extern int dns_ip6_qualify_rules(stralloc *,stralloc *,const stralloc *,const stralloc *);
|
||||
extern int dns_ip6_qualify(stralloc *,stralloc *,const stralloc *);
|
||||
|
||||
extern int dns_name6_domain(char *,char *);
|
||||
#define DNS_NAME6_DOMAIN (4*16+10)
|
||||
|
||||
#endif
|
@ -0,0 +1,69 @@
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include "byte.h"
|
||||
#include "dns.h"
|
||||
|
||||
int dns_domain_fromdot(char **out,const char *buf,unsigned int n)
|
||||
{
|
||||
char label[63];
|
||||
unsigned int labellen = 0; /* <= sizeof label */
|
||||
char name[255];
|
||||
unsigned int namelen = 0; /* <= sizeof name */
|
||||
char ch;
|
||||
char *x;
|
||||
|
||||
errno = EPROTO;
|
||||
|
||||
for (;;) {
|
||||
if (!n) break;
|
||||
ch = *buf++; --n;
|
||||
if (ch == '.') {
|
||||
if (labellen) {
|
||||
if (namelen + labellen + 1 > sizeof name) return 0;
|
||||
name[namelen++] = labellen;
|
||||
byte_copy(name + namelen,labellen,label);
|
||||
namelen += labellen;
|
||||
labellen = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (ch == '\\') {
|
||||
if (!n) break;
|
||||
ch = *buf++; --n;
|
||||
if ((ch >= '0') && (ch <= '7')) {
|
||||
ch -= '0';
|
||||
if (n && (*buf >= '0') && (*buf <= '7')) {
|
||||
ch <<= 3;
|
||||
ch += *buf - '0';
|
||||
++buf; --n;
|
||||
if (n && (*buf >= '0') && (*buf <= '7')) {
|
||||
ch <<= 3;
|
||||
ch += *buf - '0';
|
||||
++buf; --n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (labellen >= sizeof label) return 0;
|
||||
label[labellen++] = ch;
|
||||
}
|
||||
|
||||
if (labellen) {
|
||||
if (namelen + labellen + 1 > sizeof name) return 0;
|
||||
name[namelen++] = labellen;
|
||||
byte_copy(name + namelen,labellen,label);
|
||||
namelen += labellen;
|
||||
labellen = 0;
|
||||
}
|
||||
|
||||
if (namelen + 1 > sizeof name) return 0;
|
||||
name[namelen++] = 0;
|
||||
|
||||
x = malloc(namelen);
|
||||
if (!x) return 0;
|
||||
byte_copy(x,namelen,name);
|
||||
|
||||
if (*out) free(*out);
|
||||
*out = x;
|
||||
return 1;
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
#include <stdlib.h>
|
||||
#include "case.h"
|
||||
#include "byte.h"
|
||||
#include "dns.h"
|
||||
|
||||
unsigned int dns_domain_length(const char *dn)
|
||||
{
|
||||
const char *x;
|
||||
unsigned char c;
|
||||
|
||||
x = dn;
|
||||
while ((c = *x++))
|
||||
x += (unsigned int) c;
|
||||
return x - dn;
|
||||
}
|
||||
|
||||
void dns_domain_free(char **out)
|
||||
{
|
||||
if (*out) {
|
||||
free(*out);
|
||||
*out = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int dns_domain_copy(char **out,const char *in)
|
||||
{
|
||||
unsigned int len;
|
||||
char *x;
|
||||
|
||||
len = dns_domain_length(in);
|
||||
x = malloc(len);
|
||||
if (!x) return 0;
|
||||
byte_copy(x,len,in);
|
||||
if (*out) free(*out);
|
||||
*out = x;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dns_domain_equal(const char *dn1,const char *dn2)
|
||||
{
|
||||
unsigned int len;
|
||||
|
||||
len = dns_domain_length(dn1);
|
||||
if (len != dns_domain_length(dn2)) return 0;
|
||||
|
||||
if (case_diffb(dn1,len,dn2)) return 0; /* safe since 63 < 'A' */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dns_domain_suffix(const char *big,const char *little)
|
||||
{
|
||||
unsigned char c;
|
||||
|
||||
for (;;) {
|
||||
if (dns_domain_equal(big,little)) return 1;
|
||||
c = *big++;
|
||||
if (!c) return 0;
|
||||
big += c;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int dns_domain_suffixpos(const char *big,const char *little)
|
||||
{
|
||||
const char *orig = big;
|
||||
unsigned char c;
|
||||
|
||||
for (;;) {
|
||||
if (dns_domain_equal(big,little)) return big - orig;
|
||||
c = *big++;
|
||||
if (!c) return 0;
|
||||
big += c;
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
#include "stralloc.h"
|
||||
#include "dns.h"
|
||||
|
||||
int dns_domain_todot_cat(stralloc *out,const char *d)
|
||||
{
|
||||
char ch;
|
||||
char ch2;
|
||||
unsigned char ch3;
|
||||
char buf[4];
|
||||
|
||||
if (!*d)
|
||||
return stralloc_append(out,".");
|
||||
|
||||
for (;;) {
|
||||
ch = *d++;
|
||||
while (ch--) {
|
||||
ch2 = *d++;
|
||||
if ((ch2 >= 'A') && (ch2 <= 'Z'))
|
||||
ch2 += 32;
|
||||
if (((ch2 >= 'a') && (ch2 <= 'z')) || ((ch2 >= '0') && (ch2 <= '9')) || (ch2 == '-') || (ch2 == '_')) {
|
||||
if (!stralloc_append(out,&ch2)) return 0;
|
||||
}
|
||||
else {
|
||||
ch3 = ch2;
|
||||
buf[3] = '0' + (ch3 & 7); ch3 >>= 3;
|
||||
buf[2] = '0' + (ch3 & 7); ch3 >>= 3;
|
||||
buf[1] = '0' + (ch3 & 7);
|
||||
buf[0] = '\\';
|
||||
if (!stralloc_catb(out,buf,4)) return 0;
|
||||
}
|
||||
}
|
||||
if (!*d) return 1;
|
||||
if (!stralloc_append(out,".")) return 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
#include "stralloc.h"
|
||||
#include "uint16.h"
|
||||
#include "byte.h"
|
||||
#include "dns.h"
|
||||
|
||||
int dns_ip4_packet(stralloc *out,const char *buf,unsigned int len)
|
||||
{
|
||||
unsigned int pos;
|
||||
char header[12];
|
||||
uint16 numanswers;
|
||||
uint16 datalen;
|
||||
|
||||
if (!stralloc_copys(out,"")) return -1;
|
||||
|
||||
pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return -1;
|
||||
uint16_unpack_big(header + 6,&numanswers);
|
||||
pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
|
||||
pos += 4;
|
||||
|
||||
while (numanswers--) {
|
||||
pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
|
||||
pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return -1;
|
||||
uint16_unpack_big(header + 8,&datalen);
|
||||
if (byte_equal(header,2,DNS_T_A))
|
||||
if (byte_equal(header + 2,2,DNS_C_IN))
|
||||
if (datalen == 4) {
|
||||
if (!dns_packet_copy(buf,len,pos,header,4)) return -1;
|
||||
if (!stralloc_catb(out,header,4)) return -1;
|
||||
}
|
||||
pos += datalen;
|
||||
}
|
||||
|
||||
dns_sortip(out->s,out->len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *q = 0;
|
||||
|
||||
int dns_ip4(stralloc *out,const stralloc *fqdn)
|
||||
{
|
||||
unsigned int i;
|
||||
char code;
|
||||
char ch;
|
||||
|
||||
if (!stralloc_copys(out,"")) return -1;
|
||||
code = 0;
|
||||
for (i = 0;i <= fqdn->len;++i) {
|
||||
if (i < fqdn->len)
|
||||
ch = fqdn->s[i];
|
||||
else
|
||||
ch = '.';
|
||||
|
||||
if ((ch == '[') || (ch == ']')) continue;
|
||||
if (ch == '.') {
|
||||
if (!stralloc_append(out,&code)) return -1;
|
||||
code = 0;
|
||||
continue;
|
||||
}
|
||||
if ((ch >= '0') && (ch <= '9')) {
|
||||
code *= 10;
|
||||
code += ch - '0';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!dns_domain_fromdot(&q,fqdn->s,fqdn->len)) return -1;
|
||||
if (dns_resolve(q,DNS_T_A) == -1) return -1;
|
||||
if (dns_ip4_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) == -1) return -1;
|
||||
dns_transmit_free(&dns_resolve_tx);
|
||||
dns_domain_free(&q);
|
||||
return 0;
|
||||
}
|
||||
|
||||
out->len &= ~3;
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
#include "stralloc.h"
|
||||
#include "uint16.h"
|
||||
#include "byte.h"
|
||||
#include "dns.h"
|
||||
#include "ip4.h"
|
||||
#include "ip6.h"
|
||||
|
||||
static int dns_ip6_packet_add(stralloc *out,char *buf,unsigned int len)
|
||||
{
|
||||
unsigned int pos;
|
||||
char header[16];
|
||||
uint16 numanswers;
|
||||
uint16 datalen;
|
||||
|
||||
pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return -1;
|
||||
uint16_unpack_big(header + 6,&numanswers);
|
||||
pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
|
||||
pos += 4;
|
||||
|
||||
while (numanswers--) {
|
||||
pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
|
||||
pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return -1;
|
||||
uint16_unpack_big(header + 8,&datalen);
|
||||
if (byte_equal(header,2,DNS_T_AAAA)) {
|
||||
if (byte_equal(header + 2,2,DNS_C_IN))
|
||||
if (datalen == 16) {
|
||||
if (!dns_packet_copy(buf,len,pos,header,16)) return -1;
|
||||
if (!stralloc_catb(out,header,16)) return -1;
|
||||
}
|
||||
} else if (byte_equal(header,2,DNS_T_A))
|
||||
if (byte_equal(header + 2,2,DNS_C_IN))
|
||||
if (datalen == 4) {
|
||||
byte_copy(header,12,V4mappedprefix);
|
||||
if (!dns_packet_copy(buf,len,pos,header+12,4)) return -1;
|
||||
if (!stralloc_catb(out,header,16)) return -1;
|
||||
}
|
||||
pos += datalen;
|
||||
}
|
||||
|
||||
dns_sortip6(out->s,out->len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_ip6_packet(stralloc *out,char *buf,unsigned int len) {
|
||||
if (!stralloc_copys(out,"")) return -1;
|
||||
return dns_ip6_packet_add(out,buf,len);
|
||||
}
|
||||
|
||||
static char *q = 0;
|
||||
|
||||
int dns_ip6(stralloc *out,stralloc *fqdn)
|
||||
{
|
||||
unsigned int i;
|
||||
char code;
|
||||
char ch;
|
||||
char ip[16];
|
||||
|
||||
if (!stralloc_copys(out,"")) return -1;
|
||||
if (!stralloc_readyplus(fqdn,1)) return -1;
|
||||
fqdn->s[fqdn->len]=0;
|
||||
if ((i=scan_ip6(fqdn->s,ip))) {
|
||||
if (fqdn->s[i]) return -1;
|
||||
stralloc_copyb(out,ip,16);
|
||||
return 0;
|
||||
}
|
||||
code = 0;
|
||||
for (i = 0;i <= fqdn->len;++i) {
|
||||
if (i < fqdn->len)
|
||||
ch = fqdn->s[i];
|
||||
else
|
||||
ch = '.';
|
||||
|
||||
if ((ch == '[') || (ch == ']')) continue;
|
||||
if (ch == '.') {
|
||||
if (!stralloc_append(out,&code)) return -1;
|
||||
code = 0;
|
||||
continue;
|
||||
}
|
||||
if ((ch >= '0') && (ch <= '9')) {
|
||||
code *= 10;
|
||||
code += ch - '0';
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!dns_domain_fromdot(&q,fqdn->s,fqdn->len)) return -1;
|
||||
if (!stralloc_copys(out,"")) return -1;
|
||||
if (dns_resolve(q,DNS_T_AAAA) != -1)
|
||||
if (dns_ip6_packet_add(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) != -1) {
|
||||
dns_transmit_free(&dns_resolve_tx);
|
||||
dns_domain_free(&q);
|
||||
}
|
||||
if (!dns_domain_fromdot(&q,fqdn->s,fqdn->len)) return -1;
|
||||
if (dns_resolve(q,DNS_T_A) != -1)
|
||||
if (dns_ip6_packet_add(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) != -1) {
|
||||
dns_transmit_free(&dns_resolve_tx);
|
||||
dns_domain_free(&q);
|
||||
}
|
||||
return out->a>0?0:-1;
|
||||
}
|
||||
|
||||
out->len &= ~3;
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
#include "stralloc.h"
|
||||
#include "case.h"
|
||||
#include "byte.h"
|
||||
#include "str.h"
|
||||
#include "dns.h"
|
||||
|
||||
static int doit(stralloc *work,const char *rule)
|
||||
{
|
||||
char ch;
|
||||
unsigned int colon;
|
||||
unsigned int prefixlen;
|
||||
|
||||
ch = *rule++;
|
||||
if ((ch != '?') && (ch != '=') && (ch != '*') && (ch != '-')) return 1;
|
||||
colon = str_chr(rule,':');
|
||||
if (!rule[colon]) return 1;
|
||||
|
||||
if (work->len < colon) return 1;
|
||||
prefixlen = work->len - colon;
|
||||
if ((ch == '=') && prefixlen) return 1;
|
||||
if (case_diffb(rule,colon,work->s + prefixlen)) return 1;
|
||||
if (ch == '?') {
|
||||
if (byte_chr(work->s,prefixlen,'.') < prefixlen) return 1;
|
||||
if (byte_chr(work->s,prefixlen,'[') < prefixlen) return 1;
|
||||
if (byte_chr(work->s,prefixlen,']') < prefixlen) return 1;
|
||||
}
|
||||
|
||||
work->len = prefixlen;
|
||||
if (ch == '-') work->len = 0;
|
||||
return stralloc_cats(work,rule + colon + 1);
|
||||
}
|
||||
|
||||
int dns_ip4_qualify_rules(stralloc *out,stralloc *fqdn,const stralloc *in,const stralloc *rules)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
unsigned int plus;
|
||||
unsigned int fqdnlen;
|
||||
|
||||
if (!stralloc_copy(fqdn,in)) return -1;
|
||||
|
||||
for (j = i = 0;j < rules->len;++j)
|
||||
if (!rules->s[j]) {
|
||||
if (!doit(fqdn,rules->s + i)) return -1;
|
||||
i = j + 1;
|
||||
}
|
||||
|
||||
fqdnlen = fqdn->len;
|
||||
plus = byte_chr(fqdn->s,fqdnlen,'+');
|
||||
if (plus >= fqdnlen)
|
||||
return dns_ip4(out,fqdn);
|
||||
|
||||
i = plus + 1;
|
||||
for (;;) {
|
||||
j = byte_chr(fqdn->s + i,fqdnlen - i,'+');
|
||||
byte_copy(fqdn->s + plus,j,fqdn->s + i);
|
||||
fqdn->len = plus + j;
|
||||
if (dns_ip4(out,fqdn) == -1) return -1;
|
||||
if (out->len) return 0;
|
||||
i += j;
|
||||
if (i >= fqdnlen) return 0;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
int dns_ip4_qualify(stralloc *out,stralloc *fqdn,const stralloc *in)
|
||||
{
|
||||
static stralloc rules;
|
||||
if (dns_resolvconfrewrite(&rules) == -1) return -1;
|
||||
return dns_ip4_qualify_rules(out,fqdn,in,&rules);
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
#include "stralloc.h"
|
||||
#include "case.h"
|
||||
#include "byte.h"
|
||||
#include "str.h"
|
||||
#include "dns.h"
|
||||
|
||||
static int doit(stralloc *work,const char *rule)
|
||||
{
|
||||
char ch;
|
||||
unsigned int colon;
|
||||
unsigned int prefixlen;
|
||||
|
||||
ch = *rule++;
|
||||
if ((ch != '?') && (ch != '=') && (ch != '*') && (ch != '-')) return 1;
|
||||
colon = str_chr(rule,':');
|
||||
if (!rule[colon]) return 1;
|
||||
|
||||
if (work->len < colon) return 1;
|
||||
prefixlen = work->len - colon;
|
||||
if ((ch == '=') && prefixlen) return 1;
|
||||
if (case_diffb(rule,colon,work->s + prefixlen)) return 1;
|
||||
if (ch == '?') {
|
||||
if (byte_chr(work->s,prefixlen,'.') < prefixlen) return 1;
|
||||
if (byte_chr(work->s,prefixlen,':') < prefixlen) return 1;
|
||||
if (byte_chr(work->s,prefixlen,'[') < prefixlen) return 1;
|
||||
if (byte_chr(work->s,prefixlen,']') < prefixlen) return 1;
|
||||
}
|
||||
|
||||
work->len = prefixlen;
|
||||
if (ch == '-') work->len = 0;
|
||||
return stralloc_cats(work,rule + colon + 1);
|
||||
}
|
||||
|
||||
int dns_ip6_qualify_rules(stralloc *out,stralloc *fqdn,const stralloc *in,const stralloc *rules)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
unsigned int plus;
|
||||
unsigned int fqdnlen;
|
||||
|
||||
if (!stralloc_copy(fqdn,in)) return -1;
|
||||
|
||||
for (j = i = 0;j < rules->len;++j)
|
||||
if (!rules->s[j]) {
|
||||
if (!doit(fqdn,rules->s + i)) return -1;
|
||||
i = j + 1;
|
||||
}
|
||||
|
||||
fqdnlen = fqdn->len;
|
||||
plus = byte_chr(fqdn->s,fqdnlen,'+');
|
||||
if (plus >= fqdnlen)
|
||||
return dns_ip6(out,fqdn);
|
||||
|
||||
i = plus + 1;
|
||||
for (;;) {
|
||||
j = byte_chr(fqdn->s + i,fqdnlen - i,'+');
|
||||
byte_copy(fqdn->s + plus,j,fqdn->s + i);
|
||||
fqdn->len = plus + j;
|
||||
if (dns_ip6(out,fqdn) == -1) return -1;
|
||||
if (out->len) return 0;
|
||||
i += j;
|
||||
if (i >= fqdnlen) return 0;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
int dns_ip6_qualify(stralloc *out,stralloc *fqdn,const stralloc *in)
|
||||
{
|
||||
static stralloc rules;
|
||||
if (dns_resolvconfrewrite(&rules) == -1) return -1;
|
||||
return dns_ip6_qualify_rules(out,fqdn,in,&rules);
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
#include "stralloc.h"
|
||||
#include "byte.h"
|
||||
#include "uint16.h"
|
||||
#include "dns.h"
|
||||
|
||||
static char *q = 0;
|
||||
|
||||
int dns_mx_packet(stralloc *out,const char *buf,unsigned int len)
|
||||
{
|
||||
unsigned int pos;
|
||||
char header[12];
|
||||
char pref[2];
|
||||
uint16 numanswers;
|
||||
uint16 datalen;
|
||||
|
||||
if (!stralloc_copys(out,"")) return -1;
|
||||
|
||||
pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return -1;
|
||||
uint16_unpack_big(header + 6,&numanswers);
|
||||
pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
|
||||
pos += 4;
|
||||
|
||||
while (numanswers--) {
|
||||
pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
|
||||
pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return -1;
|
||||
uint16_unpack_big(header + 8,&datalen);
|
||||
if (byte_equal(header,2,DNS_T_MX))
|
||||
if (byte_equal(header + 2,2,DNS_C_IN)) {
|
||||
if (!dns_packet_copy(buf,len,pos,pref,2)) return -1;
|
||||
if (!dns_packet_getname(buf,len,pos + 2,&q)) return -1;
|
||||
if (!stralloc_catb(out,pref,2)) return -1;
|
||||
if (!dns_domain_todot_cat(out,q)) return -1;
|
||||
if (!stralloc_0(out)) return -1;
|
||||
}
|
||||
pos += datalen;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_mx(stralloc *out,const stralloc *fqdn)
|
||||
{
|
||||
if (!dns_domain_fromdot(&q,fqdn->s,fqdn->len)) return -1;
|
||||
if (dns_resolve(q,DNS_T_MX) == -1) return -1;
|
||||
if (dns_mx_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) == -1) return -1;
|
||||
dns_transmit_free(&dns_resolve_tx);
|
||||
dns_domain_free(&q);
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
#include "stralloc.h"
|
||||
#include "uint16.h"
|
||||
#include "byte.h"
|
||||
#include "dns.h"
|
||||
#include "ip6.h"
|
||||
|
||||
static char *q = 0;
|
||||
|
||||
int dns_name_packet(stralloc *out,const char *buf,unsigned int len)
|
||||
{
|
||||
unsigned int pos;
|
||||
char header[12];
|
||||
uint16 numanswers;
|
||||
uint16 datalen;
|
||||
|
||||
if (!stralloc_copys(out,"")) return -1;
|
||||
|
||||
pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return -1;
|
||||
uint16_unpack_big(header + 6,&numanswers);
|
||||
pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
|
||||
pos += 4;
|
||||
|
||||
while (numanswers--) {
|
||||
pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
|
||||
pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return -1;
|
||||
uint16_unpack_big(header + 8,&datalen);
|
||||
if (byte_equal(header,2,DNS_T_PTR))
|
||||
if (byte_equal(header + 2,2,DNS_C_IN)) {
|
||||
if (!dns_packet_getname(buf,len,pos,&q)) return -1;
|
||||
if (!dns_domain_todot_cat(out,q)) return -1;
|
||||
return 0;
|
||||
}
|
||||
pos += datalen;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_name4(stralloc *out,const char ip[4])
|
||||
{
|
||||
char name[DNS_NAME4_DOMAIN];
|
||||
|
||||
dns_name4_domain(name,ip);
|
||||
if (dns_resolve(name,DNS_T_PTR) == -1) return -1;
|
||||
if (dns_name_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) == -1) return -1;
|
||||
dns_transmit_free(&dns_resolve_tx);
|
||||
dns_domain_free(&q);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_name6(stralloc *out,char ip[16])
|
||||
{
|
||||
char name[DNS_NAME6_DOMAIN];
|
||||
|
||||
if (ip6_isv4mapped(ip))
|
||||
return dns_name4(out,ip+12);
|
||||
dns_name6_domain(name,ip);
|
||||
if (dns_resolve(name,DNS_T_PTR) == -1) return -1;
|
||||
if (dns_name_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) == -1) return -1;
|
||||
dns_transmit_free(&dns_resolve_tx);
|
||||
dns_domain_free(&q);
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
#include "byte.h"
|
||||
#include "fmt.h"
|
||||
#include "dns.h"
|
||||
|
||||
void dns_name4_domain(char name[DNS_NAME4_DOMAIN],const char ip[4])
|
||||
{
|
||||
unsigned int namelen;
|
||||
unsigned int i;
|
||||
|
||||
namelen = 0;
|
||||
i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[3]);
|
||||
name[namelen++] = i;
|
||||
namelen += i;
|
||||
i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[2]);
|
||||
name[namelen++] = i;
|
||||
namelen += i;
|
||||
i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[1]);
|
||||
name[namelen++] = i;
|
||||
namelen += i;
|
||||
i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[0]);
|
||||
name[namelen++] = i;
|
||||
namelen += i;
|
||||
byte_copy(name + namelen,14,"\7in-addr\4arpa\0");
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
#include "byte.h"
|
||||
#include "fmt.h"
|
||||
#include "dns.h"
|
||||
|
||||
/* RFC1886:
|
||||
* 4321:0:1:2:3:4:567:89ab
|
||||
* ->
|
||||
* b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.IP6.INT.
|
||||
*/
|
||||
|
||||
static inline char tohex(char c) {
|
||||
return c>=10?c-10+'a':c+'0';
|
||||
}
|
||||
|
||||
int dns_name6_domain(char name[DNS_NAME6_DOMAIN],char ip[16])
|
||||
{
|
||||
unsigned int j;
|
||||
|
||||
for (j=0; j<16; j++) {
|
||||
name[j*4]=1;
|
||||
name[j*4+1]=tohex(ip[15-j] & 15);
|
||||
name[j*4+2]=1;
|
||||
name[j*4+3]=tohex((unsigned char)ip[15-j] >> 4);
|
||||
}
|
||||
byte_copy(name + 4*16,9,"\3ip6\3int\0");
|
||||
return 4*16+9;
|
||||
}
|
||||
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
DNS should have used LZ77 instead of its own sophomoric compression algorithm.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include "dns.h"
|
||||
|
||||
unsigned int dns_packet_copy(const char *buf,unsigned int len,unsigned int pos,char *out,unsigned int outlen)
|
||||
{
|
||||
while (outlen) {
|
||||
if (pos >= len) { errno = EPROTO; return 0; }
|
||||
*out = buf[pos++];
|
||||
++out; --outlen;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
unsigned int dns_packet_skipname(const char *buf,unsigned int len,unsigned int pos)
|
||||
{
|
||||
unsigned char ch;
|
||||
|
||||
for (;;) {
|
||||
if (pos >= len) break;
|
||||
ch = buf[pos++];
|
||||
if (ch >= 192) return pos + 1;
|
||||
if (ch >= 64) break;
|
||||
if (!ch) return pos;
|
||||
pos += ch;
|
||||
}
|
||||
|
||||
errno = EPROTO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int dns_packet_getname(const char *buf,unsigned int len,unsigned int pos,char **d)
|
||||
{
|
||||
unsigned int loop = 0;
|
||||
unsigned int state = 0;
|
||||
unsigned int firstcompress = 0;
|
||||
unsigned int where;
|
||||
unsigned char ch;
|
||||
char name[255];
|
||||
unsigned int namelen = 0;
|
||||
|
||||
for (;;) {
|
||||
if (pos >= len) goto PROTO; ch = buf[pos++];
|
||||
if (++loop >= 1000) goto PROTO;
|
||||
|
||||
if (state) {
|
||||
if (namelen + 1 > sizeof name) goto PROTO; name[namelen++] = ch;
|
||||
--state;
|
||||
}
|
||||
else {
|
||||
while (ch >= 192) {
|
||||
where = ch; where -= 192; where <<= 8;
|
||||
if (pos >= len) goto PROTO; ch = buf[pos++];
|
||||
if (!firstcompress) firstcompress = pos;
|
||||
pos = where + ch;
|
||||
if (pos >= len) goto PROTO; ch = buf[pos++];
|
||||
if (++loop >= 1000) goto PROTO;
|
||||
}
|
||||
if (ch >= 64) goto PROTO;
|
||||
if (namelen + 1 > sizeof name) goto PROTO; name[namelen++] = ch;
|
||||
if (!ch) break;
|
||||
state = ch;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dns_domain_copy(d,name)) return 0;
|
||||
|
||||
if (firstcompress) return firstcompress;
|
||||
return pos;
|
||||
|
||||
PROTO:
|
||||
errno = EPROTO;
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
#include <unistd.h>
|
||||
#include "dns.h"
|
||||
#include "taia.h"
|
||||
#include "uint32.h"
|
||||
|
||||
static uint32 seed[32];
|
||||
static uint32 in[12];
|
||||
static uint32 out[8];
|
||||
static int outleft = 0;
|
||||
|
||||
#define ROTATE(x,b) (((x) << (b)) | ((x) >> (32 - (b))))
|
||||
#define MUSH(i,b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROTATE(x,b));
|
||||
|
||||
static void surf(void)
|
||||
{
|
||||
uint32 t[12]; uint32 x; uint32 sum = 0;
|
||||
int r; int i; int loop;
|
||||
|
||||
for (i = 0;i < 12;++i) t[i] = in[i] ^ seed[12 + i];
|
||||
for (i = 0;i < 8;++i) out[i] = seed[24 + i];
|
||||
x = t[11];
|
||||
for (loop = 0;loop < 2;++loop) {
|
||||
for (r = 0;r < 16;++r) {
|
||||
sum += 0x9e3779b9;
|
||||
MUSH(0,5) MUSH(1,7) MUSH(2,9) MUSH(3,13)
|
||||
MUSH(4,5) MUSH(5,7) MUSH(6,9) MUSH(7,13)
|
||||
MUSH(8,5) MUSH(9,7) MUSH(10,9) MUSH(11,13)
|
||||
}
|
||||
for (i = 0;i < 8;++i) out[i] ^= t[i + 4];
|
||||
}
|
||||
}
|
||||
|
||||
void dns_random_init(const char data[128])
|
||||
{
|
||||
int i;
|
||||
struct taia t;
|
||||
char tpack[16];
|
||||
|
||||
for (i = 0;i < 32;++i)
|
||||
uint32_unpack(data + 4 * i,seed + i);
|
||||
|
||||
taia_now(&t);
|
||||
taia_pack(tpack,&t);
|
||||
for (i = 0;i < 4;++i)
|
||||
uint32_unpack(tpack + 4 * i,in + 4 + i);
|
||||
|
||||
in[8] = getpid();
|
||||
in[9] = getppid();
|
||||
/* more space in 10 and 11, but this is probably enough */
|
||||
}
|
||||
|
||||
unsigned int dns_random(unsigned int n)
|
||||
{
|
||||
if (!n) return 0;
|
||||
|
||||
if (!outleft) {
|
||||
if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
|
||||
surf();
|
||||
outleft = 8;
|
||||
}
|
||||
|
||||
return out[--outleft] % n;
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
#include <stdlib.h>
|
||||
#include "taia.h"
|
||||
#include "openreadclose.h"
|
||||
#include "byte.h"
|
||||
#include "ip4.h"
|
||||
#include "ip6.h"
|
||||
#include "dns.h"
|
||||
|
||||
static stralloc data = {0};
|
||||
|
||||
static int init(char ip[256])
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int iplen = 0;
|
||||
char *x;
|
||||
|
||||
x = getenv("DNSCACHEIP");
|
||||
if (x)
|
||||
while (iplen <= 60) {
|
||||
if (*x == '.')
|
||||
++x;
|
||||
else {
|
||||
i = scan_ip6(x,ip + iplen);
|
||||
if (!i) break;
|
||||
x += i;
|
||||
iplen += 16;
|
||||
}
|
||||
}
|
||||
|
||||
if (!iplen) {
|
||||
i = openreadclose("/etc/resolv.conf",&data,64);
|
||||
if (i == -1) return -1;
|
||||
if (i) {
|
||||
if (!stralloc_append(&data,"\n")) return -1;
|
||||
i = 0;
|
||||
for (j = 0;j < data.len;++j)
|
||||
if (data.s[j] == '\n') {
|
||||
if (byte_equal("nameserver ",11,data.s + i) || byte_equal("nameserver\t",11,data.s + i)) {
|
||||
i += 10;
|
||||
while ((data.s[i] == ' ') || (data.s[i] == '\t'))
|
||||
++i;
|
||||
if (iplen <= 60)
|
||||
if (scan_ip6(data.s + i,ip + iplen)) {
|
||||
iplen += 16;
|
||||
}
|
||||
}
|
||||
i = j + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!iplen) {
|
||||
byte_copy(ip,16,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1");
|
||||
iplen = 16;
|
||||
}
|
||||
byte_zero(ip + iplen,256 - iplen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ok = 0;
|
||||
static unsigned int uses;
|
||||
static struct taia deadline;
|
||||
static char ip[256]; /* defined if ok */
|
||||
|
||||
int dns_resolvconfip(char s[256])
|
||||
{
|
||||
struct taia now;
|
||||
|
||||
taia_now(&now);
|
||||
if (taia_less(&deadline,&now)) ok = 0;
|
||||
if (!uses) ok = 0;
|
||||
|
||||
if (!ok) {
|
||||
if (init(ip) == -1) return -1;
|
||||
taia_uint(&deadline,600);
|
||||
taia_add(&deadline,&now,&deadline);
|
||||
uses = 10000;
|
||||
ok = 1;
|
||||
}
|
||||
|
||||
--uses;
|
||||
byte_copy(s,256,ip);
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include "taia.h"
|
||||
#include "byte.h"
|
||||
#include "str.h"
|
||||
#include "openreadclose.h"
|
||||
#include "dns.h"
|
||||
|
||||
static stralloc data = {0};
|
||||
|
||||
static int init(stralloc *rules)
|
||||
{
|
||||
char host[256];
|
||||
const char *x;
|
||||
int i;
|
||||
int j;
|
||||
int k;
|
||||
|
||||
if (!stralloc_copys(rules,"")) return -1;
|
||||
|
||||
x = getenv("DNSREWRITEFILE");
|
||||
if (!x) x = "/etc/dnsrewrite";
|
||||
|
||||
i = openreadclose(x,&data,64);
|
||||
if (i == -1) return -1;
|
||||
|
||||
if (i) {
|
||||
if (!stralloc_append(&data,"\n")) return -1;
|
||||
i = 0;
|
||||
for (j = 0;j < data.len;++j)
|
||||
if (data.s[j] == '\n') {
|
||||
if (!stralloc_catb(rules,data.s + i,j - i)) return -1;
|
||||
while (rules->len) {
|
||||
if (rules->s[rules->len - 1] != ' ')
|
||||
if (rules->s[rules->len - 1] != '\t')
|
||||
if (rules->s[rules->len - 1] != '\r')
|
||||
break;
|
||||
--rules->len;
|
||||
}
|
||||
if (!stralloc_0(rules)) return -1;
|
||||
i = j + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
x = getenv("LOCALDOMAIN");
|
||||
if (x) {
|
||||
if (!stralloc_copys(&data,x)) return -1;
|
||||
if (!stralloc_append(&data," ")) return -1;
|
||||
if (!stralloc_copys(rules,"?:")) return -1;
|
||||
i = 0;
|
||||
for (j = 0;j < data.len;++j)
|
||||
if (data.s[j] == ' ') {
|
||||
if (!stralloc_cats(rules,"+.")) return -1;
|
||||
if (!stralloc_catb(rules,data.s + i,j - i)) return -1;
|
||||
i = j + 1;
|
||||
}
|
||||
if (!stralloc_0(rules)) return -1;
|
||||
if (!stralloc_cats(rules,"*.:")) return -1;
|
||||
if (!stralloc_0(rules)) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
i = openreadclose("/etc/resolv.conf",&data,64);
|
||||
if (i == -1) return -1;
|
||||
|
||||
if (i) {
|
||||
if (!stralloc_append(&data,"\n")) return -1;
|
||||
i = 0;
|
||||
for (j = 0;j < data.len;++j)
|
||||
if (data.s[j] == '\n') {
|
||||
if (byte_equal("search ",7,data.s + i) || byte_equal("search\t",7,data.s + i) || byte_equal("domain ",7,data.s + i) || byte_equal("domain\t",7,data.s + i)) {
|
||||
if (!stralloc_copys(rules,"?:")) return -1;
|
||||
i += 7;
|
||||
while (i < j) {
|
||||
k = byte_chr(data.s + i,j - i,' ');
|
||||
k = byte_chr(data.s + i,k,'\t');
|
||||
if (!k) { ++i; continue; }
|
||||
if (!stralloc_cats(rules,"+.")) return -1;
|
||||
if (!stralloc_catb(rules,data.s + i,k)) return -1;
|
||||
i += k;
|
||||
}
|
||||
if (!stralloc_0(rules)) return -1;
|
||||
if (!stralloc_cats(rules,"*.:")) return -1;
|
||||
if (!stralloc_0(rules)) return -1;
|
||||
return 0;
|
||||
}
|
||||
i = j + 1;
|
||||
}
|
||||
}
|
||||
|
||||
host[0] = 0;
|
||||
if (gethostname(host,sizeof host) == -1) return -1;
|
||||
host[(sizeof host) - 1] = 0;
|
||||
i = str_chr(host,'.');
|
||||
if (host[i]) {
|
||||
if (!stralloc_copys(rules,"?:")) return -1;
|
||||
if (!stralloc_cats(rules,host + i)) return -1;
|
||||
if (!stralloc_0(rules)) return -1;
|
||||
}
|
||||
if (!stralloc_cats(rules,"*.:")) return -1;
|
||||
if (!stralloc_0(rules)) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ok = 0;
|
||||
static unsigned int uses;
|
||||
static struct taia deadline;
|
||||
static stralloc rules = {0}; /* defined if ok */
|
||||
|
||||
int dns_resolvconfrewrite(stralloc *out)
|
||||
{
|
||||
struct taia now;
|
||||
|
||||
taia_now(&now);
|
||||
if (taia_less(&deadline,&now)) ok = 0;
|
||||
if (!uses) ok = 0;
|
||||
|
||||
if (!ok) {
|
||||
if (init(&rules) == -1) return -1;
|
||||
taia_uint(&deadline,600);
|
||||
taia_add(&deadline,&now,&deadline);
|
||||
uses = 10000;
|
||||
ok = 1;
|
||||
}
|
||||
|
||||
--uses;
|
||||
if (!stralloc_copy(out,&rules)) return -1;
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
#include "iopause.h"
|
||||
#include "taia.h"
|
||||
#include "byte.h"
|
||||
#include "dns.h"
|
||||
#include "ip6.h"
|
||||
|
||||
struct dns_transmit dns_resolve_tx = {0};
|
||||
|
||||
int dns_resolve(const char *q,const char qtype[2])
|
||||
{
|
||||
struct taia stamp;
|
||||