plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

dn.c (27596B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <ip.h>
      4 #include <ctype.h>
      5 #include <bio.h>
      6 #include <ndb.h>
      7 #include <thread.h>
      8 #include "dns.h"
      9 
     10 /*
     11  *  Hash table for domain names.  The hash is based only on the
     12  *  first element of the domain name.
     13  */
     14 DN	*ht[HTLEN];
     15 
     16 
     17 static struct
     18 {
     19 	Lock	lk;
     20 	ulong	names;	/* names allocated */
     21 	ulong	oldest;	/* longest we'll leave a name around */
     22 	int	active;
     23 	int	mutex;
     24 	int	id;
     25 } dnvars;
     26 
     27 /* names of RR types */
     28 char *rrtname[Tall+2] =
     29 {
     30 	nil,
     31 	"ip",
     32 	"ns",
     33 	"md",
     34 	"mf",
     35 	"cname",
     36 	"soa",
     37 	"mb",
     38 	"mg",
     39 	"mr",
     40 	"null",
     41 	"wks",
     42 	"ptr",
     43 	"hinfo",
     44 	"minfo",
     45 	"mx",
     46 	"txt",
     47 	"rp",
     48 	nil,
     49 	nil,
     50 	nil,
     51 	nil,
     52 	nil,
     53 	nil,
     54 	"sig",
     55 	"key",
     56 	nil,
     57 	nil,
     58 	"aaaa",
     59 	nil,
     60 	nil,
     61 	nil,
     62 	nil,
     63 	nil,
     64 	nil,
     65 	nil,
     66 	nil,
     67 	"cert",
     68 	nil,
     69 	nil,
     70 
     71 /* 40 */	nil, nil, nil, nil, nil, nil, nil, nil,
     72 /* 48 */	nil, nil, nil, nil, nil, nil, nil, nil,
     73 /* 56 */	nil, nil, nil, nil, nil, nil, nil, nil,
     74 /* 64 */	nil, nil, nil, nil, nil, nil, nil, nil,
     75 /* 72 */	nil, nil, nil, nil, nil, nil, nil, nil,
     76 /* 80 */	nil, nil, nil, nil, nil, nil, nil, nil,
     77 /* 88 */	nil, nil, nil, nil, nil, nil, nil, nil,
     78 /* 96 */	nil, nil, nil, nil, nil, nil, nil, nil,
     79 /* 104 */	nil, nil, nil, nil, nil, nil, nil, nil,
     80 /* 112 */	nil, nil, nil, nil, nil, nil, nil, nil,
     81 /* 120 */	nil, nil, nil, nil, nil, nil, nil, nil,
     82 /* 128 */	nil, nil, nil, nil, nil, nil, nil, nil,
     83 /* 136 */	nil, nil, nil, nil, nil, nil, nil, nil,
     84 /* 144 */	nil, nil, nil, nil, nil, nil, nil, nil,
     85 /* 152 */	nil, nil, nil, nil, nil, nil, nil, nil,
     86 /* 160 */	nil, nil, nil, nil, nil, nil, nil, nil,
     87 /* 168 */	nil, nil, nil, nil, nil, nil, nil, nil,
     88 /* 176 */	nil, nil, nil, nil, nil, nil, nil, nil,
     89 /* 184 */	nil, nil, nil, nil, nil, nil, nil, nil,
     90 /* 192 */	nil, nil, nil, nil, nil, nil, nil, nil,
     91 /* 200 */	nil, nil, nil, nil, nil, nil, nil, nil,
     92 /* 208 */	nil, nil, nil, nil, nil, nil, nil, nil,
     93 /* 216 */	nil, nil, nil, nil, nil, nil, nil, nil,
     94 /* 224 */	nil, nil, nil, nil, nil, nil, nil, nil,
     95 /* 232 */	nil, nil, nil, nil, nil, nil, nil, nil,
     96 /* 240 */	nil, nil, nil, nil, nil, nil, nil, nil,
     97 /* 248 */	nil, nil, nil,
     98 
     99 	"ixfr",
    100 	"axfr",
    101 	"mailb",
    102 	nil,
    103 	"all",
    104 	nil
    105 };
    106 
    107 /* names of response codes */
    108 char *rname[Rmask+1] =
    109 {
    110 	"ok",
    111 	"format error",
    112 	"server failure",
    113 	"bad name",
    114 	"unimplemented",
    115 	"we don't like you"
    116 };
    117 
    118 Lock	dnlock;
    119 
    120 static int sencodefmt(Fmt*);
    121 
    122 /*
    123  *  set up a pipe to use as a lock
    124  */
    125 void
    126 dninit(void)
    127 {
    128 	fmtinstall('E', eipfmt);
    129 	fmtinstall('I', eipfmt);
    130 	fmtinstall('V', eipfmt);
    131 	fmtinstall('R', rrfmt);
    132 	fmtinstall('Q', rravfmt);
    133 	fmtinstall('H', sencodefmt);
    134 
    135 	dnvars.oldest = maxage;
    136 	dnvars.names = 0;
    137 }
    138 
    139 /*
    140  *  hash for a domain name
    141  */
    142 static ulong
    143 dnhash(char *name)
    144 {
    145 	ulong hash;
    146 	uchar *val = (uchar*)name;
    147 
    148 	for(hash = 0; *val; val++)
    149 		hash = (hash*13) + tolower(*val)-'a';
    150 	return hash % HTLEN;
    151 }
    152 
    153 /*
    154  *  lookup a symbol.  if enter is not zero and the name is
    155  *  not found, create it.
    156  */
    157 DN*
    158 dnlookup(char *name, int class, int enter)
    159 {
    160 	DN **l;
    161 	DN *dp;
    162 
    163 	l = &ht[dnhash(name)];
    164 	lock(&dnlock);
    165 	for(dp = *l; dp; dp = dp->next) {
    166 		assert(dp->magic == DNmagic);
    167 		if(dp->class == class && cistrcmp(dp->name, name) == 0){
    168 			dp->referenced = now;
    169 			unlock(&dnlock);
    170 			return dp;
    171 		}
    172 		l = &dp->next;
    173 	}
    174 	if(enter == 0){
    175 		unlock(&dnlock);
    176 		return 0;
    177 	}
    178 	dnvars.names++;
    179 	dp = emalloc(sizeof(*dp));
    180 	dp->magic = DNmagic;
    181 	dp->name = estrdup(name);
    182 	assert(dp->name != 0);
    183 	dp->class = class;
    184 	dp->rr = 0;
    185 	dp->next = 0;
    186 	dp->referenced = now;
    187 	*l = dp;
    188 	unlock(&dnlock);
    189 
    190 	return dp;
    191 }
    192 
    193 /*
    194  *  dump the cache
    195  */
    196 void
    197 dndump(char *file)
    198 {
    199 	DN *dp;
    200 	int i, fd;
    201 	RR *rp;
    202 
    203 	fd = open(file, OWRITE|OTRUNC);
    204 	if(fd < 0)
    205 		return;
    206 	lock(&dnlock);
    207 	for(i = 0; i < HTLEN; i++){
    208 		for(dp = ht[i]; dp; dp = dp->next){
    209 			fprint(fd, "%s\n", dp->name);
    210 			for(rp = dp->rr; rp; rp = rp->next)
    211 				fprint(fd, "	%R %c%c %lud/%lud\n", rp, rp->auth?'A':'U',
    212 					rp->db?'D':'N', rp->expire, rp->ttl);
    213 		}
    214 	}
    215 	unlock(&dnlock);
    216 	close(fd);
    217 }
    218 
    219 /*
    220  *  purge all records
    221  */
    222 void
    223 dnpurge(void)
    224 {
    225 	DN *dp;
    226 	RR *rp, *srp;
    227 	int i;
    228 
    229 	lock(&dnlock);
    230 
    231 	for(i = 0; i < HTLEN; i++)
    232 		for(dp = ht[i]; dp; dp = dp->next){
    233 			srp = rp = dp->rr;
    234 			dp->rr = nil;
    235 			for(; rp != nil; rp = rp->next)
    236 				rp->cached = 0;
    237 			rrfreelist(srp);
    238 		}
    239 
    240 	unlock(&dnlock);
    241 }
    242 
    243 /*
    244  *  check the age of resource records, free any that have timed out
    245  */
    246 void
    247 dnage(DN *dp)
    248 {
    249 	RR **l;
    250 	RR *rp, *next;
    251 	ulong diff;
    252 
    253 	diff = now - dp->referenced;
    254 	if(diff < Reserved)
    255 		return;
    256 
    257 	l = &dp->rr;
    258 	for(rp = dp->rr; rp; rp = next){
    259 		assert(rp->magic == RRmagic && rp->cached);
    260 		next = rp->next;
    261 		if(!rp->db)
    262 		if(rp->expire < now || diff > dnvars.oldest){
    263 			*l = next;
    264 			rp->cached = 0;
    265 			rrfree(rp);
    266 			continue;
    267 		}
    268 		l = &rp->next;
    269 	}
    270 }
    271 
    272 #define REF(x) if(x) x->refs++
    273 
    274 /*
    275  *  our target is 4000 names cached, this should be larger on large servers
    276  */
    277 #define TARGET 4000
    278 
    279 /*
    280  *  periodicly sweep for old records and remove unreferenced domain names
    281  *
    282  *  only called when all other threads are locked out
    283  */
    284 void
    285 dnageall(int doit)
    286 {
    287 	DN *dp, **l;
    288 	int i;
    289 	RR *rp;
    290 	static ulong nextage;
    291 
    292 	if(dnvars.names < TARGET && now < nextage && !doit){
    293 		dnvars.oldest = maxage;
    294 		return;
    295 	}
    296 
    297 	if(dnvars.names > TARGET)
    298 		dnvars.oldest /= 2;
    299 	nextage = now + maxage;
    300 
    301 	lock(&dnlock);
    302 
    303 	/* time out all old entries (and set refs to 0) */
    304 	for(i = 0; i < HTLEN; i++)
    305 		for(dp = ht[i]; dp; dp = dp->next){
    306 			dp->refs = 0;
    307 			dnage(dp);
    308 		}
    309 
    310 	/* mark all referenced domain names */
    311 	for(i = 0; i < HTLEN; i++)
    312 		for(dp = ht[i]; dp; dp = dp->next)
    313 			for(rp = dp->rr; rp; rp = rp->next){
    314 				REF(rp->owner);
    315 				if(rp->negative){
    316 					REF(rp->negsoaowner);
    317 					continue;
    318 				}
    319 				switch(rp->type){
    320 				case Thinfo:
    321 					REF(rp->cpu);
    322 					REF(rp->os);
    323 					break;
    324 				case Ttxt:
    325 					break;
    326 				case Tcname:
    327 				case Tmb:
    328 				case Tmd:
    329 				case Tmf:
    330 				case Tns:
    331 					REF(rp->host);
    332 					break;
    333 				case Tmg:
    334 				case Tmr:
    335 					REF(rp->mb);
    336 					break;
    337 				case Tminfo:
    338 					REF(rp->rmb);
    339 					REF(rp->mb);
    340 					break;
    341 				case Trp:
    342 					REF(rp->rmb);
    343 					REF(rp->rp);
    344 					break;
    345 				case Tmx:
    346 					REF(rp->host);
    347 					break;
    348 				case Ta:
    349 				case Taaaa:
    350 					REF(rp->ip);
    351 					break;
    352 				case Tptr:
    353 					REF(rp->ptr);
    354 					break;
    355 				case Tsoa:
    356 					REF(rp->host);
    357 					REF(rp->rmb);
    358 					break;
    359 				}
    360 			}
    361 
    362 	/* sweep and remove unreferenced domain names */
    363 	for(i = 0; i < HTLEN; i++){
    364 		l = &ht[i];
    365 		for(dp = *l; dp; dp = *l){
    366 			if(dp->rr == 0 && dp->refs == 0){
    367 				assert(dp->magic == DNmagic);
    368 				*l = dp->next;
    369 				if(dp->name)
    370 					free(dp->name);
    371 				dp->magic = ~dp->magic;
    372 				dnvars.names--;
    373 				free(dp);
    374 				continue;
    375 			}
    376 			l = &dp->next;
    377 		}
    378 	}
    379 
    380 	unlock(&dnlock);
    381 }
    382 
    383 /*
    384  *  timeout all database records (used when rereading db)
    385  */
    386 void
    387 dnagedb(void)
    388 {
    389 	DN *dp;
    390 	int i;
    391 	RR *rp;
    392 
    393 	lock(&dnlock);
    394 
    395 	/* time out all database entries */
    396 	for(i = 0; i < HTLEN; i++)
    397 		for(dp = ht[i]; dp; dp = dp->next)
    398 			for(rp = dp->rr; rp; rp = rp->next)
    399 				if(rp->db)
    400 					rp->expire = 0;
    401 
    402 	unlock(&dnlock);
    403 }
    404 
    405 /*
    406  *  mark all local db records about my area as authoritative, time out any others
    407  */
    408 void
    409 dnauthdb(void)
    410 {
    411 	DN *dp;
    412 	int i;
    413 	Area *area;
    414 	RR *rp;
    415 
    416 	lock(&dnlock);
    417 
    418 	/* time out all database entries */
    419 	for(i = 0; i < HTLEN; i++)
    420 		for(dp = ht[i]; dp; dp = dp->next){
    421 			area = inmyarea(dp->name);
    422 			for(rp = dp->rr; rp; rp = rp->next)
    423 				if(rp->db){
    424 					if(area){
    425 						if(rp->ttl < area->soarr->soa->minttl)
    426 							rp->ttl = area->soarr->soa->minttl;
    427 						rp->auth = 1;
    428 					}
    429 					if(rp->expire == 0){
    430 						rp->db = 0;
    431 						dp->referenced = now - Reserved - 1;
    432 					}
    433 				}
    434 		}
    435 
    436 	unlock(&dnlock);
    437 }
    438 
    439 /*
    440  *  keep track of other processes to know if we can
    441  *  garbage collect.  block while garbage collecting.
    442  */
    443 int
    444 getactivity(Request *req)
    445 {
    446 	int rv;
    447 
    448 	if(traceactivity) syslog(0, "dns", "get %d by %d.%d", dnvars.active, getpid(), threadid());
    449 	lock(&dnvars.lk);
    450 	while(dnvars.mutex){
    451 		unlock(&dnvars.lk);
    452 		sleep(200);
    453 		lock(&dnvars.lk);
    454 	}
    455 	rv = ++dnvars.active;
    456 	now = time(0);
    457 	req->id = ++dnvars.id;
    458 	unlock(&dnvars.lk);
    459 
    460 	return rv;
    461 }
    462 void
    463 putactivity(void)
    464 {
    465 	if(traceactivity) syslog(0, "dns", "put %d by %d.%d", dnvars.active, getpid(), threadid());
    466 	lock(&dnvars.lk);
    467 	dnvars.active--;
    468 	assert(dnvars.active >= 0); /* "dnvars.active %d", dnvars.active */;
    469 
    470 	/*
    471 	 *  clean out old entries and check for new db periodicly
    472 	 */
    473 	if(dnvars.mutex || (needrefresh == 0 && dnvars.active > 0)){
    474 		unlock(&dnvars.lk);
    475 		return;
    476 	}
    477 
    478 	/* wait till we're alone */
    479 	dnvars.mutex = 1;
    480 	while(dnvars.active > 0){
    481 		unlock(&dnvars.lk);
    482 		sleep(100);
    483 		lock(&dnvars.lk);
    484 	}
    485 	unlock(&dnvars.lk);
    486 
    487 	db2cache(needrefresh);
    488 	dnageall(0);
    489 
    490 	/* let others back in */
    491 	needrefresh = 0;
    492 	dnvars.mutex = 0;
    493 }
    494 
    495 /*
    496  *  Attach a single resource record to a domain name.
    497  *	- Avoid duplicates with already present RR's
    498  *	- Chain all RR's of the same type adjacent to one another
    499  *	- chain authoritative RR's ahead of non-authoritative ones
    500  */
    501 static void
    502 rrattach1(RR *new, int auth)
    503 {
    504 	RR **l;
    505 	RR *rp;
    506 	DN *dp;
    507 
    508 	assert(new->magic == RRmagic && !new->cached);
    509 
    510 	if(!new->db)
    511 		new->expire = new->ttl;
    512 	else
    513 		new->expire = now + Year;
    514 	dp = new->owner;
    515 	assert(dp->magic == DNmagic);
    516 	new->auth |= auth;
    517 	new->next = 0;
    518 
    519 	/*
    520 	 *  find first rr of the right type
    521 	 */
    522 	l = &dp->rr;
    523 	for(rp = *l; rp; rp = *l){
    524 		assert(rp->magic == RRmagic && rp->cached);
    525 		if(rp->type == new->type)
    526 			break;
    527 		l = &rp->next;
    528 	}
    529 
    530 	/*
    531 	 *  negative entries replace positive entries
    532 	 *  positive entries replace negative entries
    533 	 *  newer entries replace older entries with the same fields
    534 	 */
    535 	for(rp = *l; rp; rp = *l){
    536 		assert(rp->magic == RRmagic && rp->cached);
    537 		if(rp->type != new->type)
    538 			break;
    539 
    540 		if(rp->db == new->db && rp->auth == new->auth){
    541 			/* negative drives out positive and vice versa */
    542 			if(rp->negative != new->negative){
    543 				*l = rp->next;
    544 				rp->cached = 0;
    545 				rrfree(rp);
    546 				continue;
    547 			}
    548 
    549 			/* all things equal, pick the newer one */
    550 			if(rp->arg0 == new->arg0 && rp->arg1 == new->arg1){
    551 				/* new drives out old */
    552 				if(new->ttl > rp->ttl || new->expire > rp->expire){
    553 					*l = rp->next;
    554 					rp->cached = 0;
    555 					rrfree(rp);
    556 					continue;
    557 				} else {
    558 					rrfree(new);
    559 					return;
    560 				}
    561 			}
    562 
    563 			/*  Hack for pointer records.  This makes sure
    564 			 *  the ordering in the list reflects the ordering
    565 			 *  received or read from the database
    566 			 */
    567 			if(rp->type == Tptr){
    568 				if(!rp->negative && !new->negative
    569 				&& rp->ptr->ordinal > new->ptr->ordinal)
    570 					break;
    571 			}
    572 		}
    573 		l = &rp->next;
    574 	}
    575 
    576 	/*
    577 	 *  add to chain
    578 	 */
    579 	new->cached = 1;
    580 	new->next = *l;
    581 	*l = new;
    582 }
    583 
    584 /*
    585  *  Attach a list of resource records to a domain name.
    586  *	- Avoid duplicates with already present RR's
    587  *	- Chain all RR's of the same type adjacent to one another
    588  *	- chain authoritative RR's ahead of non-authoritative ones
    589  *	- remove any expired RR's
    590  */
    591 void
    592 rrattach(RR *rp, int auth)
    593 {
    594 	RR *next;
    595 
    596 	lock(&dnlock);
    597 	for(; rp; rp = next){
    598 		next = rp->next;
    599 		rp->next = 0;
    600 
    601 		/* avoid any outside spoofing */
    602 		if(cachedb && !rp->db && inmyarea(rp->owner->name))
    603 			rrfree(rp);
    604 		else
    605 			rrattach1(rp, auth);
    606 	}
    607 	unlock(&dnlock);
    608 }
    609 
    610 /*
    611  *  allocate a resource record of a given type
    612  */
    613 RR*
    614 rralloc(int type)
    615 {
    616 	RR *rp;
    617 
    618 	rp = emalloc(sizeof(*rp));
    619 	rp->magic = RRmagic;
    620 	rp->pc = getcallerpc(&type);
    621 	rp->type = type;
    622 	switch(type){
    623 	case Tsoa:
    624 		rp->soa = emalloc(sizeof(*rp->soa));
    625 		rp->soa->slaves = nil;
    626 		break;
    627 	case Tkey:
    628 		rp->key = emalloc(sizeof(*rp->key));
    629 		break;
    630 	case Tcert:
    631 		rp->cert = emalloc(sizeof(*rp->cert));
    632 		break;
    633 	case Tsig:
    634 		rp->sig = emalloc(sizeof(*rp->sig));
    635 		break;
    636 	case Tnull:
    637 		rp->null = emalloc(sizeof(*rp->null));
    638 		break;
    639 	}
    640 	rp->ttl = 0;
    641 	rp->expire = 0;
    642 	rp->next = 0;
    643 	return rp;
    644 }
    645 
    646 /*
    647  *  free a resource record and any related structs
    648  */
    649 void
    650 rrfree(RR *rp)
    651 {
    652 	DN *dp;
    653 	RR *nrp;
    654 	Txt *t;
    655 
    656 	assert(rp->magic = RRmagic);
    657 	assert(!rp->cached);
    658 
    659 	dp = rp->owner;
    660 	if(dp){
    661 		assert(dp->magic == DNmagic);
    662 		for(nrp = dp->rr; nrp; nrp = nrp->next)
    663 			assert(nrp != rp); /* "rrfree of live rr" */;
    664 	}
    665 
    666 	switch(rp->type){
    667 	case Tsoa:
    668 		freeserverlist(rp->soa->slaves);
    669 		free(rp->soa);
    670 		break;
    671 	case Tkey:
    672 		free(rp->key->data);
    673 		free(rp->key);
    674 		break;
    675 	case Tcert:
    676 		free(rp->cert->data);
    677 		free(rp->cert);
    678 		break;
    679 	case Tsig:
    680 		free(rp->sig->data);
    681 		free(rp->sig);
    682 		break;
    683 	case Tnull:
    684 		free(rp->null->data);
    685 		free(rp->null);
    686 		break;
    687 	case Ttxt:
    688 		while(rp->txt != nil){
    689 			t = rp->txt;
    690 			rp->txt = t->next;
    691 			free(t->p);
    692 			free(t);
    693 		}
    694 		break;
    695 	}
    696 
    697 	rp->magic = ~rp->magic;
    698 	free(rp);
    699 }
    700 
    701 /*
    702  *  free a list of resource records and any related structs
    703  */
    704 void
    705 rrfreelist(RR *rp)
    706 {
    707 	RR *next;
    708 
    709 	for(; rp; rp = next){
    710 		next = rp->next;
    711 		rrfree(rp);
    712 	}
    713 }
    714 
    715 extern RR**
    716 rrcopy(RR *rp, RR **last)
    717 {
    718 	RR *nrp;
    719 	SOA *soa;
    720 	Key *key;
    721 	Cert *cert;
    722 	Sig *sig;
    723 	Null *null;
    724 	Txt *t, *nt, **l;
    725 
    726 	nrp = rralloc(rp->type);
    727 	switch(rp->type){
    728 	case Ttxt:
    729 		*nrp = *rp;
    730 		l = &nrp->txt;
    731 		*l = nil;
    732 		for(t = rp->txt; t != nil; t = t->next){
    733 			nt = emalloc(sizeof(*nt));
    734 			nt->p = estrdup(t->p);
    735 			nt->next = nil;
    736 			*l = nt;
    737 			l = &nt->next;
    738 		}
    739 		break;
    740 	case Tsoa:
    741 		soa = nrp->soa;
    742 		*nrp = *rp;
    743 		nrp->soa = soa;
    744 		*nrp->soa = *rp->soa;
    745 		nrp->soa->slaves = copyserverlist(rp->soa->slaves);
    746 		break;
    747 	case Tkey:
    748 		key = nrp->key;
    749 		*nrp = *rp;
    750 		nrp->key = key;
    751 		*key = *rp->key;
    752 		key->data = emalloc(key->dlen);
    753 		memmove(key->data, rp->key->data, rp->key->dlen);
    754 		break;
    755 	case Tsig:
    756 		sig = nrp->sig;
    757 		*nrp = *rp;
    758 		nrp->sig = sig;
    759 		*sig = *rp->sig;
    760 		sig->data = emalloc(sig->dlen);
    761 		memmove(sig->data, rp->sig->data, rp->sig->dlen);
    762 		break;
    763 	case Tcert:
    764 		cert = nrp->cert;
    765 		*nrp = *rp;
    766 		nrp->cert = cert;
    767 		*cert = *rp->cert;
    768 		cert->data = emalloc(cert->dlen);
    769 		memmove(cert->data, rp->cert->data, rp->cert->dlen);
    770 		break;
    771 	case Tnull:
    772 		null = nrp->null;
    773 		*nrp = *rp;
    774 		nrp->null = null;
    775 		*null = *rp->null;
    776 		null->data = emalloc(null->dlen);
    777 		memmove(null->data, rp->null->data, rp->null->dlen);
    778 		break;
    779 	default:
    780 		*nrp = *rp;
    781 		break;
    782 	}
    783 	nrp->cached = 0;
    784 	nrp->next = 0;
    785 	*last = nrp;
    786 	return &nrp->next;
    787 }
    788 
    789 /*
    790  *  lookup a resource record of a particular type and
    791  *  class attached to a domain name.  Return copies.
    792  *
    793  *  Priority ordering is:
    794  *	db authoritative
    795  *	not timed out network authoritative
    796  *	not timed out network unauthoritative
    797  *	unauthoritative db
    798  *
    799  *  if flag NOneg is set, don't return negative cached entries.
    800  *  return nothing instead.
    801  */
    802 RR*
    803 rrlookup(DN *dp, int type, int flag)
    804 {
    805 	RR *rp, *first, **last;
    806 
    807 	assert(dp->magic == DNmagic);
    808 
    809 	first = 0;
    810 	last = &first;
    811 	lock(&dnlock);
    812 
    813 	/* try for an authoritative db entry */
    814 	for(rp = dp->rr; rp; rp = rp->next){
    815 		assert(rp->magic == RRmagic && rp->cached);
    816 		if(rp->db)
    817 		if(rp->auth)
    818 		if(tsame(type, rp->type))
    819 			last = rrcopy(rp, last);
    820 	}
    821 	if(first)
    822 		goto out;
    823 
    824 	/* try for an living authoritative network entry */
    825 	for(rp = dp->rr; rp; rp = rp->next){
    826 		if(!rp->db)
    827 		if(rp->auth)
    828 		if(rp->ttl + 60 > now)
    829 		if(tsame(type, rp->type)){
    830 			if(flag == NOneg && rp->negative)
    831 				goto out;
    832 			last = rrcopy(rp, last);
    833 		}
    834 	}
    835 	if(first)
    836 		goto out;
    837 
    838 	/* try for an living unauthoritative network entry */
    839 	for(rp = dp->rr; rp; rp = rp->next){
    840 		if(!rp->db)
    841 		if(rp->ttl + 60 > now)
    842 		if(tsame(type, rp->type)){
    843 			if(flag == NOneg && rp->negative)
    844 				goto out;
    845 			last = rrcopy(rp, last);
    846 		}
    847 	}
    848 	if(first)
    849 		goto out;
    850 
    851 	/* try for an unauthoritative db entry */
    852 	for(rp = dp->rr; rp; rp = rp->next){
    853 		if(rp->db)
    854 		if(tsame(type, rp->type))
    855 			last = rrcopy(rp, last);
    856 	}
    857 	if(first)
    858 		goto out;
    859 
    860 	/* otherwise, settle for anything we got (except for negative caches)  */
    861 	for(rp = dp->rr; rp; rp = rp->next){
    862 		if(tsame(type, rp->type)){
    863 			if(rp->negative)
    864 				goto out;
    865 			last = rrcopy(rp, last);
    866 		}
    867 	}
    868 
    869 out:
    870 	unlock(&dnlock);
    871 	unique(first);
    872 	return first;
    873 }
    874 
    875 /*
    876  *  convert an ascii RR type name to its integer representation
    877  */
    878 int
    879 rrtype(char *atype)
    880 {
    881 	int i;
    882 
    883 	for(i = 0; i <= Tall; i++)
    884 		if(rrtname[i] && strcmp(rrtname[i], atype) == 0)
    885 			return i;
    886 
    887 	/* make any a synonym for all */
    888 	if(strcmp(atype, "any") == 0)
    889 		return Tall;
    890 	return atoi(atype);
    891 }
    892 
    893 /*
    894  *  convert an integer RR type to it's ascii name
    895  */
    896 char*
    897 rrname(int type, char *buf, int len)
    898 {
    899 	char *t;
    900 
    901 	t = 0;
    902 	if(type <= Tall)
    903 		t = rrtname[type];
    904 	if(t==0){
    905 		snprint(buf, len, "%d", type);
    906 		t = buf;
    907 	}
    908 	return t;
    909 }
    910 
    911 /*
    912  *  return 0 if not a supported rr type
    913  */
    914 int
    915 rrsupported(int type)
    916 {
    917 	if(type < 0 || type >Tall)
    918 		return 0;
    919 	return rrtname[type] != 0;
    920 }
    921 
    922 /*
    923  *  compare 2 types
    924  */
    925 int
    926 tsame(int t1, int t2)
    927 {
    928 	return t1 == t2 || t1 == Tall;
    929 }
    930 
    931 /*
    932  *  Add resource records to a list, duplicate them if they are cached
    933  *  RR's since these are shared.
    934  */
    935 RR*
    936 rrcat(RR **start, RR *rp)
    937 {
    938 	RR **last;
    939 
    940 	last = start;
    941 	while(*last != 0)
    942 		last = &(*last)->next;
    943 
    944 	*last = rp;
    945 	return *start;
    946 }
    947 
    948 /*
    949  *  remove negative cache rr's from an rr list
    950  */
    951 RR*
    952 rrremneg(RR **l)
    953 {
    954 	RR **nl, *rp;
    955 	RR *first;
    956 
    957 	first = nil;
    958 	nl = &first;
    959 	while(*l != nil){
    960 		rp = *l;
    961 		if(rp->negative){
    962 			*l = rp->next;
    963 			*nl = rp;
    964 			nl = &rp->next;
    965 			*nl = nil;
    966 		} else
    967 			l = &rp->next;
    968 	}
    969 
    970 	return first;
    971 }
    972 
    973 /*
    974  *  remove rr's of a particular type from an rr list
    975  */
    976 RR*
    977 rrremtype(RR **l, int type)
    978 {
    979 	RR **nl, *rp;
    980 	RR *first;
    981 
    982 	first = nil;
    983 	nl = &first;
    984 	while(*l != nil){
    985 		rp = *l;
    986 		if(rp->type == type){
    987 			*l = rp->next;
    988 			*nl = rp;
    989 			nl = &rp->next;
    990 			*nl = nil;
    991 		} else
    992 			l = &(*l)->next;
    993 	}
    994 
    995 	return first;
    996 }
    997 
    998 /*
    999  *  print conversion for rr records
   1000  */
   1001 int
   1002 rrfmt(Fmt *f)
   1003 {
   1004 	RR *rp;
   1005 	char *strp;
   1006 	Fmt fstr;
   1007 	int rv;
   1008 	char buf[Domlen];
   1009 	Server *s;
   1010 	Txt *t;
   1011 
   1012 	fmtstrinit(&fstr);
   1013 
   1014 	rp = va_arg(f->args, RR*);
   1015 	if(rp == 0){
   1016 		fmtprint(&fstr, "<null>");
   1017 		goto out;
   1018 	}
   1019 
   1020 	fmtprint(&fstr, "%s %s", rp->owner->name,
   1021 		rrname(rp->type, buf, sizeof buf));
   1022 
   1023 	if(rp->negative){
   1024 		fmtprint(&fstr, "\tnegative - rcode %d", rp->negrcode);
   1025 		goto out;
   1026 	}
   1027 
   1028 	switch(rp->type){
   1029 	case Thinfo:
   1030 		fmtprint(&fstr, "\t%s %s", rp->cpu->name, rp->os->name);
   1031 		break;
   1032 	case Tcname:
   1033 	case Tmb:
   1034 	case Tmd:
   1035 	case Tmf:
   1036 	case Tns:
   1037 		fmtprint(&fstr, "\t%s", rp->host->name);
   1038 		break;
   1039 	case Tmg:
   1040 	case Tmr:
   1041 		fmtprint(&fstr, "\t%s", rp->mb->name);
   1042 		break;
   1043 	case Tminfo:
   1044 		fmtprint(&fstr, "\t%s %s", rp->mb->name, rp->rmb->name);
   1045 		break;
   1046 	case Tmx:
   1047 		fmtprint(&fstr, "\t%lud %s", rp->pref, rp->host->name);
   1048 		break;
   1049 	case Ta:
   1050 	case Taaaa:
   1051 		fmtprint(&fstr, "\t%s", rp->ip->name);
   1052 		break;
   1053 	case Tptr:
   1054 /*		fmtprint(&fstr, "\t%s(%lud)", rp->ptr->name, rp->ptr->ordinal); */
   1055 		fmtprint(&fstr, "\t%s", rp->ptr->name);
   1056 		break;
   1057 	case Tsoa:
   1058 		fmtprint(&fstr, "\t%s %s %lud %lud %lud %lud %lud", rp->host->name,
   1059 			rp->rmb->name, rp->soa->serial, rp->soa->refresh, rp->soa->retry,
   1060 			rp->soa->expire, rp->soa->minttl);
   1061 		for(s = rp->soa->slaves; s != nil; s = s->next)
   1062 			fmtprint(&fstr, " %s", s->name);
   1063 		break;
   1064 	case Tnull:
   1065 		fmtprint(&fstr, "\t%.*H", rp->null->dlen, rp->null->data);
   1066 		break;
   1067 	case Ttxt:
   1068 		fmtprint(&fstr, "\t");
   1069 		for(t = rp->txt; t != nil; t = t->next)
   1070 			fmtprint(&fstr, "%s", t->p);
   1071 		break;
   1072 	case Trp:
   1073 		fmtprint(&fstr, "\t%s %s", rp->rmb->name, rp->rp->name);
   1074 		break;
   1075 	case Tkey:
   1076 		fmtprint(&fstr, "\t%d %d %d", rp->key->flags, rp->key->proto,
   1077 			rp->key->alg);
   1078 		break;
   1079 	case Tsig:
   1080 		fmtprint(&fstr, "\t%d %d %d %lud %lud %lud %d %s",
   1081 			rp->sig->type, rp->sig->alg, rp->sig->labels, rp->sig->ttl,
   1082 			rp->sig->exp, rp->sig->incep, rp->sig->tag, rp->sig->signer->name);
   1083 		break;
   1084 	case Tcert:
   1085 		fmtprint(&fstr, "\t%d %d %d",
   1086 			rp->sig->type, rp->sig->tag, rp->sig->alg);
   1087 		break;
   1088 	default:
   1089 		break;
   1090 	}
   1091 out:
   1092 	strp = fmtstrflush(&fstr);
   1093 	rv = fmtstrcpy(f, strp);
   1094 	free(strp);
   1095 	return rv;
   1096 }
   1097 
   1098 /*
   1099  *  print conversion for rr records in attribute value form
   1100  */
   1101 int
   1102 rravfmt(Fmt *f)
   1103 {
   1104 	RR *rp;
   1105 	char *strp;
   1106 	Fmt fstr;
   1107 	int rv;
   1108 	Server *s;
   1109 	Txt *t;
   1110 	int quote;
   1111 
   1112 	fmtstrinit(&fstr);
   1113 
   1114 	rp = va_arg(f->args, RR*);
   1115 	if(rp == 0){
   1116 		fmtprint(&fstr, "<null>");
   1117 		goto out;
   1118 	}
   1119 
   1120 	if(rp->type == Tptr)
   1121 		fmtprint(&fstr, "ptr=%s", rp->owner->name);
   1122 	else
   1123 		fmtprint(&fstr, "dom=%s", rp->owner->name);
   1124 
   1125 	switch(rp->type){
   1126 	case Thinfo:
   1127 		fmtprint(&fstr, " cpu=%s os=%s", rp->cpu->name, rp->os->name);
   1128 		break;
   1129 	case Tcname:
   1130 		fmtprint(&fstr, " cname=%s", rp->host->name);
   1131 		break;
   1132 	case Tmb:
   1133 	case Tmd:
   1134 	case Tmf:
   1135 		fmtprint(&fstr, " mbox=%s", rp->host->name);
   1136 		break;
   1137 	case Tns:
   1138 		fmtprint(&fstr,  " ns=%s", rp->host->name);
   1139 		break;
   1140 	case Tmg:
   1141 	case Tmr:
   1142 		fmtprint(&fstr, " mbox=%s", rp->mb->name);
   1143 		break;
   1144 	case Tminfo:
   1145 		fmtprint(&fstr, " mbox=%s mbox=%s", rp->mb->name, rp->rmb->name);
   1146 		break;
   1147 	case Tmx:
   1148 		fmtprint(&fstr, " pref=%lud mx=%s", rp->pref, rp->host->name);
   1149 		break;
   1150 	case Ta:
   1151 	case Taaaa:
   1152 		fmtprint(&fstr, " ip=%s", rp->ip->name);
   1153 		break;
   1154 	case Tptr:
   1155 		fmtprint(&fstr, " dom=%s", rp->ptr->name);
   1156 		break;
   1157 	case Tsoa:
   1158 		fmtprint(&fstr, " ns=%s mbox=%s serial=%lud refresh=%lud retry=%lud expire=%lud ttl=%lud",
   1159 			rp->host->name, rp->rmb->name, rp->soa->serial,
   1160 			rp->soa->refresh, rp->soa->retry,
   1161 			rp->soa->expire, rp->soa->minttl);
   1162 		for(s = rp->soa->slaves; s != nil; s = s->next)
   1163 			fmtprint(&fstr, " dnsslave=%s", s->name);
   1164 		break;
   1165 	case Tnull:
   1166 		fmtprint(&fstr, " null=%.*H", rp->null->dlen, rp->null->data);
   1167 		break;
   1168 	case Ttxt:
   1169 		fmtprint(&fstr, " txt=");
   1170 		quote = 0;
   1171 		for(t = rp->txt; t != nil; t = t->next)
   1172 			if(strchr(t->p, ' '))
   1173 				quote = 1;
   1174 		if(quote)
   1175 			fmtprint(&fstr, "\"");
   1176 		for(t = rp->txt; t != nil; t = t->next)
   1177 			fmtprint(&fstr, "%s", t->p);
   1178 		if(quote)
   1179 			fmtprint(&fstr, "\"");
   1180 		break;
   1181 	case Trp:
   1182 		fmtprint(&fstr, " rp=%s txt=%s", rp->rmb->name, rp->rp->name);
   1183 		break;
   1184 	case Tkey:
   1185 		fmtprint(&fstr, " flags=%d proto=%d alg=%d",
   1186 			rp->key->flags, rp->key->proto, rp->key->alg);
   1187 		break;
   1188 	case Tsig:
   1189 		fmtprint(&fstr, " type=%d alg=%d labels=%d ttl=%lud exp=%lud incep=%lud tag=%d signer=%s",
   1190 			rp->sig->type, rp->sig->alg, rp->sig->labels, rp->sig->ttl,
   1191 			rp->sig->exp, rp->sig->incep, rp->sig->tag, rp->sig->signer->name);
   1192 		break;
   1193 	case Tcert:
   1194 		fmtprint(&fstr, " type=%d tag=%d alg=%d",
   1195 			rp->sig->type, rp->sig->tag, rp->sig->alg);
   1196 		break;
   1197 	default:
   1198 		break;
   1199 	}
   1200 out:
   1201 	strp = fmtstrflush(&fstr);
   1202 	rv = fmtstrcpy(f, strp);
   1203 	free(strp);
   1204 	return rv;
   1205 }
   1206 
   1207 void
   1208 warning(char *fmt, ...)
   1209 {
   1210 	char dnserr[128];
   1211 	va_list arg;
   1212 
   1213 	va_start(arg, fmt);
   1214 	vseprint(dnserr, dnserr+sizeof(dnserr), fmt, arg);
   1215 	va_end(arg);
   1216 	syslog(1, "dns", dnserr);
   1217 }
   1218 
   1219 /*
   1220  *  chasing down double free's
   1221  */
   1222 void
   1223 dncheck(void *p, int dolock)
   1224 {
   1225 	DN *dp;
   1226 	int i;
   1227 	RR *rp;
   1228 
   1229 	if(p != nil){
   1230 		dp = p;
   1231 		assert(dp->magic == DNmagic);
   1232 	}
   1233 
   1234 	if(!testing)
   1235 		return;
   1236 
   1237 	if(dolock)
   1238 		lock(&dnlock);
   1239 	for(i = 0; i < HTLEN; i++)
   1240 		for(dp = ht[i]; dp; dp = dp->next){
   1241 			assert(dp != p);
   1242 			assert(dp->magic == DNmagic);
   1243 			for(rp = dp->rr; rp; rp = rp->next){
   1244 				assert(rp->magic == RRmagic);
   1245 				assert(rp->cached);
   1246 				assert(rp->owner == dp);
   1247 			}
   1248 		}
   1249 	if(dolock)
   1250 		unlock(&dnlock);
   1251 }
   1252 
   1253 static int
   1254 rrequiv(RR *r1, RR *r2)
   1255 {
   1256 	return r1->owner == r2->owner
   1257 		&& r1->type == r2->type
   1258 		&& r1->arg0 == r2->arg0
   1259 		&& r1->arg1 == r2->arg1;
   1260 }
   1261 
   1262 void
   1263 unique(RR *rp)
   1264 {
   1265 	RR **l, *nrp;
   1266 
   1267 	for(; rp; rp = rp->next){
   1268 		l = &rp->next;
   1269 		for(nrp = *l; nrp; nrp = *l){
   1270 			if(rrequiv(rp, nrp)){
   1271 				*l = nrp->next;
   1272 				rrfree(nrp);
   1273 			} else
   1274 				l = &nrp->next;
   1275 		}
   1276 	}
   1277 }
   1278 
   1279 /*
   1280  *  true if second domain is subsumed by the first
   1281  */
   1282 int
   1283 subsume(char *higher, char *lower)
   1284 {
   1285 	int hn, ln;
   1286 
   1287 	ln = strlen(lower);
   1288 	hn = strlen(higher);
   1289 	if(ln < hn)
   1290 		return 0;
   1291 
   1292 	if(cistrcmp(lower + ln - hn, higher) != 0)
   1293 		return 0;
   1294 
   1295 	if(ln > hn && hn != 0 && lower[ln - hn - 1] != '.')
   1296 		return 0;
   1297 
   1298 	return 1;
   1299 }
   1300 
   1301 /*
   1302  *  randomize the order we return items to provide some
   1303  *  load balancing for servers.
   1304  *
   1305  *  only randomize the first class of entries
   1306  */
   1307 RR*
   1308 randomize(RR *rp)
   1309 {
   1310 	RR *first, *last, *x, *base;
   1311 	ulong n;
   1312 
   1313 	if(rp == nil || rp->next == nil)
   1314 		return rp;
   1315 
   1316 	/* just randomize addresses and mx's */
   1317 	for(x = rp; x; x = x->next)
   1318 		if(x->type != Ta && x->type != Tmx && x->type != Tns)
   1319 			return rp;
   1320 
   1321 	base = rp;
   1322 
   1323 	n = rand();
   1324 	last = first = nil;
   1325 	while(rp != nil){
   1326 		/* stop randomizing if we've moved past our class */
   1327 		if(base->auth != rp->auth || base->db != rp->db){
   1328 			last->next = rp;
   1329 			break;
   1330 		}
   1331 
   1332 		/* unchain */
   1333 		x = rp;
   1334 		rp = x->next;
   1335 		x->next = nil;
   1336 
   1337 		if(n&1){
   1338 			/* add to tail */
   1339 			if(last == nil)
   1340 				first = x;
   1341 			else
   1342 				last->next = x;
   1343 			last = x;
   1344 		} else {
   1345 			/* add to head */
   1346 			if(last == nil)
   1347 				last = x;
   1348 			x->next = first;
   1349 			first = x;
   1350 		}
   1351 
   1352 		/* reroll the dice */
   1353 		n >>= 1;
   1354 	}
   1355 	return first;
   1356 }
   1357 
   1358 static int
   1359 sencodefmt(Fmt *f)
   1360 {
   1361 	char *out;
   1362 	char *buf;
   1363 	int i, len;
   1364 	int ilen;
   1365 	int rv;
   1366 	uchar *b;
   1367 	char obuf[64];	/* rsc optimization */
   1368 
   1369 	if(!(f->flags&FmtPrec) || f->prec < 1)
   1370 		goto error;
   1371 
   1372 	b = va_arg(f->args, uchar*);
   1373 	if(b == nil)
   1374 		goto error;
   1375 
   1376 	/* if it's a printable, go for it */
   1377 	len = f->prec;
   1378 	for(i = 0; i < len; i++)
   1379 		if(!isprint(b[i]))
   1380 			break;
   1381 	if(i == len){
   1382 		if(len >= sizeof obuf)
   1383 			len = sizeof(obuf)-1;
   1384 		memmove(obuf, b, len);
   1385 		obuf[len] = 0;
   1386 		fmtstrcpy(f, obuf);
   1387 		return 0;
   1388 	}
   1389 
   1390 	ilen = f->prec;
   1391 	f->prec = 0;
   1392 	f->flags &= ~FmtPrec;
   1393 	switch(f->r){
   1394 	case '<':
   1395 		len = (8*ilen+4)/5 + 3;
   1396 		break;
   1397 	case '[':
   1398 		len = (8*ilen+5)/6 + 4;
   1399 		break;
   1400 	case 'H':
   1401 		len = 2*ilen + 1;
   1402 		break;
   1403 	default:
   1404 		goto error;
   1405 	}
   1406 
   1407 	if(len > sizeof(obuf)){
   1408 		buf = malloc(len);
   1409 		if(buf == nil)
   1410 			goto error;
   1411 	} else
   1412 		buf = obuf;
   1413 
   1414 	/* convert */
   1415 	out = buf;
   1416 	switch(f->r){
   1417 	case '<':
   1418 		rv = enc32(out, len, b, ilen);
   1419 		break;
   1420 	case '[':
   1421 		rv = enc64(out, len, b, ilen);
   1422 		break;
   1423 	case 'H':
   1424 		rv = enc16(out, len, b, ilen);
   1425 		break;
   1426 	default:
   1427 		rv = -1;
   1428 		break;
   1429 	}
   1430 	if(rv < 0)
   1431 		goto error;
   1432 
   1433 	fmtstrcpy(f, buf);
   1434 	if(buf != obuf)
   1435 		free(buf);
   1436 	return 0;
   1437 
   1438 error:
   1439 	return fmtstrcpy(f, "<encodefmt>");
   1440 
   1441 }
   1442 
   1443 void*
   1444 emalloc(int size)
   1445 {
   1446 	char *x;
   1447 
   1448 	x = mallocz(size, 1);
   1449 	if(x == nil)
   1450 		abort();
   1451 	setmalloctag(x, getcallerpc(&size));
   1452 	return x;
   1453 }
   1454 
   1455 char*
   1456 estrdup(char *s)
   1457 {
   1458 	int size;
   1459 	char *p;
   1460 
   1461 	size = strlen(s)+1;
   1462 	p = mallocz(size, 0);
   1463 	if(p == nil)
   1464 		abort();
   1465 	memmove(p, s, size);
   1466 	setmalloctag(p, getcallerpc(&s));
   1467 	return p;
   1468 }
   1469 
   1470 /*
   1471  *  create a pointer record
   1472  */
   1473 static RR*
   1474 mkptr(DN *dp, char *ptr, ulong ttl)
   1475 {
   1476 	DN *ipdp;
   1477 	RR *rp;
   1478 
   1479 	ipdp = dnlookup(ptr, Cin, 1);
   1480 
   1481 	rp = rralloc(Tptr);
   1482 	rp->ptr = dp;
   1483 	rp->owner = ipdp;
   1484 	rp->db = 1;
   1485 	if(ttl)
   1486 		rp->ttl = ttl;
   1487 	return rp;
   1488 }
   1489 
   1490 /*
   1491  *  look for all ip addresses in this network and make
   1492  *  pointer records for them.
   1493  */
   1494 void
   1495 dnptr(uchar *net, uchar *mask, char *dom, int bytes, int ttl)
   1496 {
   1497 	int i, j;
   1498 	DN *dp;
   1499 	RR *rp, *nrp, *first, **l;
   1500 	uchar ip[IPaddrlen];
   1501 	uchar nnet[IPaddrlen];
   1502 	char ptr[Domlen];
   1503 	char *p, *e;
   1504 
   1505 	l = &first;
   1506 	first = nil;
   1507 	for(i = 0; i < HTLEN; i++){
   1508 		for(dp = ht[i]; dp; dp = dp->next){
   1509 			for(rp = dp->rr; rp; rp = rp->next){
   1510 				if(rp->type != Ta || rp->negative)
   1511 					continue;
   1512 				parseip(ip, rp->ip->name);
   1513 				maskip(ip, mask, nnet);
   1514 				if(ipcmp(net, nnet) != 0)
   1515 					continue;
   1516 				p = ptr;
   1517 				e = ptr+sizeof(ptr);
   1518 				for(j = IPaddrlen-1; j >= IPaddrlen-bytes; j--)
   1519 					p = seprint(p, e, "%d.", ip[j]);
   1520 				seprint(p, e, "%s", dom);
   1521 				nrp = mkptr(dp, ptr, ttl);
   1522 				*l = nrp;
   1523 				l = &nrp->next;
   1524 			}
   1525 		}
   1526 	}
   1527 
   1528 	for(rp = first; rp != nil; rp = nrp){
   1529 		nrp = rp->next;
   1530 		rp->next = nil;
   1531 		rrattach(rp, 1);
   1532 	}
   1533 }
   1534 
   1535 void
   1536 freeserverlist(Server *s)
   1537 {
   1538 	Server *next;
   1539 
   1540 	for(; s != nil; s = next){
   1541 		next = s->next;
   1542 		free(s);
   1543 	}
   1544 }
   1545 
   1546 void
   1547 addserver(Server **l, char *name)
   1548 {
   1549 	Server *s;
   1550 
   1551 	while(*l)
   1552 		l = &(*l)->next;
   1553 	s = malloc(sizeof(Server)+strlen(name)+1);
   1554 	if(s == nil)
   1555 		return;
   1556 	s->name = (char*)(s+1);
   1557 	strcpy(s->name, name);
   1558 	s->next = nil;
   1559 	*l = s;
   1560 }
   1561 
   1562 Server*
   1563 copyserverlist(Server *s)
   1564 {
   1565 	Server *ns;
   1566 
   1567 
   1568 	for(ns = nil; s != nil; s = s->next)
   1569 		addserver(&ns, s->name);
   1570 	return ns;
   1571 }