Browse Source

Plan 9 from Bell Labs 2007-03-05

David du Colombier 17 years ago
parent
commit
c797dee57f

+ 37 - 40
dist/replica/_plan9.db

@@ -22,21 +22,21 @@
 386/bin/acid - 775 sys sys 1172808055 401961
 386/bin/acme - 775 sys sys 1168402263 432256
 386/bin/ape - 20000000775 sys sys 1016944144 0
-386/bin/ape/basename - 775 sys sys 1136656314 132873
+386/bin/ape/basename - 775 sys sys 1173039777 134719
 386/bin/ape/cc - 775 sys sys 1168402263 70642
-386/bin/ape/diff - 775 sys sys 1136656316 349768
-386/bin/ape/diff3 - 775 sys sys 1136656317 188256
-386/bin/ape/dirname - 775 sys sys 1136656318 132652
-386/bin/ape/expr - 775 sys sys 1136656319 142294
-386/bin/ape/kill - 775 sys sys 1136656321 138223
-386/bin/ape/make - 775 sys sys 1136656322 209115
-386/bin/ape/patch - 775 sys sys 1136656324 302559
+386/bin/ape/diff - 775 sys sys 1173039778 352264
+386/bin/ape/diff3 - 775 sys sys 1173039779 190364
+386/bin/ape/dirname - 775 sys sys 1173039779 134498
+386/bin/ape/expr - 775 sys sys 1173039780 144138
+386/bin/ape/kill - 775 sys sys 1173039781 140067
+386/bin/ape/make - 775 sys sys 1173039781 211605
+386/bin/ape/patch - 775 sys sys 1173039782 305848
 386/bin/ape/psh - 775 sys sys 1042220689 34
-386/bin/ape/sed - 775 sys sys 1136656324 158325
-386/bin/ape/sh - 775 sys sys 1136656327 477237
+386/bin/ape/sed - 775 sys sys 1173039783 160183
+386/bin/ape/sh - 775 sys sys 1173039783 481732
 386/bin/ape/stty - 775 sys sys 1148500571 41080
 386/bin/ape/tar - 775 sys sys 1168402264 62184
-386/bin/ape/uname - 775 sys sys 1143741925 134338
+386/bin/ape/uname - 775 sys sys 1173039784 134895
 386/bin/aquarela - 775 sys sys 1169612017 332788
 386/bin/ar - 775 sys sys 1168402265 113774
 386/bin/archfs - 775 sys sys 1168402265 147070
@@ -110,8 +110,8 @@
 386/bin/aux/lines - 775 sys sys 1168402281 60716
 386/bin/aux/listen - 775 sys sys 1168402281 108803
 386/bin/aux/listen1 - 775 sys sys 1168402281 94721
-386/bin/aux/lpdaemon - 775 sys sys 1136656330 168286
-386/bin/aux/lpdsend - 775 sys sys 1136656330 155124
+386/bin/aux/lpdaemon - 775 sys sys 1173039785 170710
+386/bin/aux/lpdsend - 775 sys sys 1173039785 157339
 386/bin/aux/lpsend - 775 sys sys 1148500596 52590
 386/bin/aux/mapd - 775 sys sys 1168402282 191082
 386/bin/aux/mkflashfs - 775 sys sys 1168402282 67590
@@ -157,7 +157,7 @@
 386/bin/aux/write - 775 sys sys 1085077011 4188
 386/bin/aux/zerotrunc - 775 sys sys 1108268388 3891
 386/bin/awd - 775 sys sys 1168402289 58975
-386/bin/awk - 775 sys sys 1142013480 324428
+386/bin/awk - 775 sys sys 1173039786 324980
 386/bin/basename - 775 sys sys 1148500606 37919
 386/bin/bc - 775 sys sys 1168402290 82001
 386/bin/bind - 775 sys sys 1168402290 59805
@@ -186,7 +186,7 @@
 386/bin/col - 775 sys sys 1172029864 64995
 386/bin/colors - 775 sys sys 1168402296 150967
 386/bin/comm - 775 sys sys 1168402296 61586
-386/bin/compress - 775 sys sys 1159212097 166928
+386/bin/compress - 775 sys sys 1173039787 166944
 386/bin/con - 775 sys sys 1168402297 78486
 386/bin/cp - 775 sys sys 1168402297 63454
 386/bin/cpp - 775 sys sys 1168402297 150459
@@ -223,7 +223,7 @@
 386/bin/du - 775 sys sys 1168402304 74244
 386/bin/echo - 775 sys sys 1168402304 57592
 386/bin/ed - 775 sys sys 1168402304 93272
-386/bin/eqn - 775 sys sys 1141927235 244405
+386/bin/eqn - 775 sys sys 1173039787 244858
 386/bin/execnet - 775 sys sys 1168402305 178216
 386/bin/exportfs - 775 sys sys 1168402305 162550
 386/bin/ext2srv - 775 sys sys 1168402306 179893
@@ -264,10 +264,10 @@
 386/bin/games/sudoku - 775 sys sys 1117249746 171666
 386/bin/getmap - 775 sys sys 1168402311 65423
 386/bin/gif - 775 sys sys 1168402312 158555
-386/bin/grap - 775 sys sys 1136656337 280496
+386/bin/grap - 775 sys sys 1173039788 282722
 386/bin/graph - 775 sys sys 1168402312 129250
 386/bin/grep - 775 sys sys 1168402312 79569
-386/bin/gs - 775 sys sys 1137468663 13275174
+386/bin/gs - 775 sys sys 1173039815 13278932
 386/bin/gunzip - 775 sys sys 1168402313 80523
 386/bin/gview - 775 sys sys 1168402313 238983
 386/bin/gzip - 775 sys sys 1168402313 84984
@@ -285,7 +285,7 @@
 386/bin/iostats - 775 sys sys 1168402317 100378
 386/bin/ip - 20000000775 sys sys 1016920851 0
 386/bin/ip/dhcpclient - 775 sys sys 1168402317 94377
-386/bin/ip/dhcpd - 775 sys sys 1169612024 151139
+386/bin/ip/dhcpd - 775 sys sys 1172980949 151301
 386/bin/ip/dhcpleases - 775 sys sys 1169612024 86533
 386/bin/ip/ftpd - 775 sys sys 1169612025 170706
 386/bin/ip/gizzard - 775 sys sys 1081480408 101521
@@ -534,7 +534,7 @@
 386/lib - 20000000775 sys sys 1016826328 0
 386/lib/ape - 20000000775 sys sys 1070519112 0
 386/lib/ape/lib9.a - 664 sys sys 1135531447 6906
-386/lib/ape/libap.a - 664 sys sys 1146156977 819888
+386/lib/ape/libap.a - 664 sys sys 1173039817 819938
 386/lib/ape/libbsd.a - 664 sys sys 1146156978 183900
 386/lib/ape/libdraw.a - 664 sys sys 1155491760 621772
 386/lib/ape/libfmt.a - 664 sys sys 1146156980 156706
@@ -7269,7 +7269,7 @@ sys/man - 20000000775 sys sys 1041446473 0
 sys/man/1 - 20000000775 sys sys 1158800370 0
 sys/man/1/0intro - 664 sys sys 1101668050 9625
 sys/man/1/2a - 664 sys sys 1158281866 1196
-sys/man/1/2c - 664 sys sys 1168702903 9195
+sys/man/1/2c - 664 sys sys 1173026977 9204
 sys/man/1/2l - 664 sys sys 1158281887 4376
 sys/man/1/INDEX - 664 sys sys 1141357442 3040
 sys/man/1/INDEX.html - 664 sys sys 1141352366 16517
@@ -8517,7 +8517,7 @@ sys/src/ape/lib/ap/arm/strcmp.s - 664 sys sys 1172956230 1010
 sys/src/ape/lib/ap/arm/strcpy.s - 664 sys sys 1172955904 885
 sys/src/ape/lib/ap/arm/tas.s - 664 sys sys 1014921992 61
 sys/src/ape/lib/ap/arm/vlop.s - 664 sys sys 1172955903 262
-sys/src/ape/lib/ap/arm/vlrt.c - 664 sys sys 1014921992 8983
+sys/src/ape/lib/ap/arm/vlrt.c - 664 sys sys 1173026824 8947
 sys/src/ape/lib/ap/extraobjs - 775 sys sys 1014921988 1356
 sys/src/ape/lib/ap/gen - 20000000775 sys sys 1048644320 0
 sys/src/ape/lib/ap/gen/_assert.c - 664 sys sys 1014921987 347
@@ -8679,7 +8679,7 @@ sys/src/ape/lib/ap/plan9/getpwnam.c - 664 sys sys 1014921984 507
 sys/src/ape/lib/ap/plan9/getpwuid.c - 664 sys sys 1014921984 527
 sys/src/ape/lib/ap/plan9/getuid.c - 664 sys sys 1014921984 199
 sys/src/ape/lib/ap/plan9/isatty.c - 664 sys sys 1014921984 471
-sys/src/ape/lib/ap/plan9/kill.c - 664 sys sys 1071872236 874
+sys/src/ape/lib/ap/plan9/kill.c - 664 sys sys 1173022765 911
 sys/src/ape/lib/ap/plan9/lib.h - 664 sys sys 1072835434 2071
 sys/src/ape/lib/ap/plan9/link.c - 664 sys sys 1014921984 168
 sys/src/ape/lib/ap/plan9/lseek.c - 664 sys sys 1038237526 358
@@ -12663,30 +12663,28 @@ sys/src/cmd/mtime.c - 664 sys sys 1036172302 450
 sys/src/cmd/mug.c - 664 sys sys 1157143847 24888
 sys/src/cmd/mv.c - 664 sys sys 1163029439 4682
 sys/src/cmd/ndb - 20000000775 sys sys 1080135004 0
-sys/src/cmd/ndb/convDNS2M.c - 664 sys sys 1119276409 6866
-sys/src/cmd/ndb/convM2DNS.c - 664 sys sys 1060612175 7248
+sys/src/cmd/ndb/convDNS2M.c - 664 sys sys 1173059857 6856
+sys/src/cmd/ndb/convM2DNS.c - 664 sys sys 1173060986 10495
 sys/src/cmd/ndb/cs.c - 664 sys sys 1163208617 33080
-sys/src/cmd/ndb/csgetval.c - 664 sys sys 957402051 1051
 sys/src/cmd/ndb/csquery.c - 664 sys sys 1014926159 1062
-sys/src/cmd/ndb/dblookup.c - 664 sys sys 1143759343 18249
-sys/src/cmd/ndb/dn.c - 664 sys sys 1144952605 28763
-sys/src/cmd/ndb/dnarea.c - 664 sys sys 1121977162 2128
-sys/src/cmd/ndb/dnnotify.c - 664 sys sys 1144952605 3066
-sys/src/cmd/ndb/dnresolve.c - 664 sys sys 1166760856 15351
-sys/src/cmd/ndb/dns.c - 664 sys sys 1147098969 15309
-sys/src/cmd/ndb/dns.h - 664 sys sys 1144969092 10171
-sys/src/cmd/ndb/dnsdebug.c - 664 sys sys 1144952604 8492
-sys/src/cmd/ndb/dnserver.c - 664 sys sys 1143759353 3982
+sys/src/cmd/ndb/dblookup.c - 664 sys sys 1173060354 18199
+sys/src/cmd/ndb/dn.c - 664 sys sys 1173060793 31773
+sys/src/cmd/ndb/dnarea.c - 664 sys sys 1173059947 2517
+sys/src/cmd/ndb/dnnotify.c - 664 sys sys 1173059885 3155
+sys/src/cmd/ndb/dnresolve.c - 664 sys sys 1173061785 16701
+sys/src/cmd/ndb/dns.c - 664 sys sys 1173061211 15603
+sys/src/cmd/ndb/dns.h - 664 sys sys 1173059802 9841
+sys/src/cmd/ndb/dnsdebug.c - 664 sys sys 1173060595 8633
+sys/src/cmd/ndb/dnserver.c - 664 sys sys 1173060400 4449
 sys/src/cmd/ndb/dnsquery.c - 664 sys sys 1120564714 2198
-sys/src/cmd/ndb/dnstcp.c - 664 sys sys 1144952604 7349
-sys/src/cmd/ndb/dnudpserver.c - 664 sys sys 1144969092 5337
+sys/src/cmd/ndb/dnstcp.c - 664 sys sys 1173061127 7677
+sys/src/cmd/ndb/dnudpserver.c - 664 sys sys 1173061278 5659
 sys/src/cmd/ndb/ipquery.c - 664 sys sys 1124711426 773
 sys/src/cmd/ndb/mkdb.c - 664 sys sys 957402054 2886
-sys/src/cmd/ndb/mkfile - 664 sys sys 1055701930 1877
+sys/src/cmd/ndb/mkfile - 664 sys sys 1173059600 1984
 sys/src/cmd/ndb/mkhash.c - 664 sys sys 1014926160 2899
 sys/src/cmd/ndb/mkhosts.c - 664 sys sys 957402054 4294
 sys/src/cmd/ndb/query.c - 664 sys sys 1078840016 1120
-sys/src/cmd/ndb/time.c - 664 sys sys 957402055 321
 sys/src/cmd/netstat.c - 664 sys sys 1128255434 4086
 sys/src/cmd/news.c - 664 sys sys 1014926614 3778
 sys/src/cmd/nfs.c - 664 sys sys 1050068720 31096
@@ -15682,4 +15680,3 @@ usr/glenda/lib/profile - 664 glenda glenda 1105128663 890
 usr/glenda/readme.acme - 664 glenda glenda 1019860628 4753
 usr/glenda/readme.rio - 664 glenda glenda 1019860628 6370
 usr/glenda/tmp - 20000000775 glenda glenda 1018802620 0
-386/bin/ip/dhcpd - 775 sys sys 1172980949 151301

+ 36 - 38
dist/replica/plan9.db

@@ -22,21 +22,21 @@
 386/bin/acid - 775 sys sys 1172808055 401961
 386/bin/acme - 775 sys sys 1168402263 432256
 386/bin/ape - 20000000775 sys sys 1016944144 0
-386/bin/ape/basename - 775 sys sys 1136656314 132873
+386/bin/ape/basename - 775 sys sys 1173039777 134719
 386/bin/ape/cc - 775 sys sys 1168402263 70642
-386/bin/ape/diff - 775 sys sys 1136656316 349768
-386/bin/ape/diff3 - 775 sys sys 1136656317 188256
-386/bin/ape/dirname - 775 sys sys 1136656318 132652
-386/bin/ape/expr - 775 sys sys 1136656319 142294
-386/bin/ape/kill - 775 sys sys 1136656321 138223
-386/bin/ape/make - 775 sys sys 1136656322 209115
-386/bin/ape/patch - 775 sys sys 1136656324 302559
+386/bin/ape/diff - 775 sys sys 1173039778 352264
+386/bin/ape/diff3 - 775 sys sys 1173039779 190364
+386/bin/ape/dirname - 775 sys sys 1173039779 134498
+386/bin/ape/expr - 775 sys sys 1173039780 144138
+386/bin/ape/kill - 775 sys sys 1173039781 140067
+386/bin/ape/make - 775 sys sys 1173039781 211605
+386/bin/ape/patch - 775 sys sys 1173039782 305848
 386/bin/ape/psh - 775 sys sys 1042220689 34
-386/bin/ape/sed - 775 sys sys 1136656324 158325
-386/bin/ape/sh - 775 sys sys 1136656327 477237
+386/bin/ape/sed - 775 sys sys 1173039783 160183
+386/bin/ape/sh - 775 sys sys 1173039783 481732
 386/bin/ape/stty - 775 sys sys 1148500571 41080
 386/bin/ape/tar - 775 sys sys 1168402264 62184
-386/bin/ape/uname - 775 sys sys 1143741925 134338
+386/bin/ape/uname - 775 sys sys 1173039784 134895
 386/bin/aquarela - 775 sys sys 1169612017 332788
 386/bin/ar - 775 sys sys 1168402265 113774
 386/bin/archfs - 775 sys sys 1168402265 147070
@@ -110,8 +110,8 @@
 386/bin/aux/lines - 775 sys sys 1168402281 60716
 386/bin/aux/listen - 775 sys sys 1168402281 108803
 386/bin/aux/listen1 - 775 sys sys 1168402281 94721
-386/bin/aux/lpdaemon - 775 sys sys 1136656330 168286
-386/bin/aux/lpdsend - 775 sys sys 1136656330 155124
+386/bin/aux/lpdaemon - 775 sys sys 1173039785 170710
+386/bin/aux/lpdsend - 775 sys sys 1173039785 157339
 386/bin/aux/lpsend - 775 sys sys 1148500596 52590
 386/bin/aux/mapd - 775 sys sys 1168402282 191082
 386/bin/aux/mkflashfs - 775 sys sys 1168402282 67590
@@ -157,7 +157,7 @@
 386/bin/aux/write - 775 sys sys 1085077011 4188
 386/bin/aux/zerotrunc - 775 sys sys 1108268388 3891
 386/bin/awd - 775 sys sys 1168402289 58975
-386/bin/awk - 775 sys sys 1142013480 324428
+386/bin/awk - 775 sys sys 1173039786 324980
 386/bin/basename - 775 sys sys 1148500606 37919
 386/bin/bc - 775 sys sys 1168402290 82001
 386/bin/bind - 775 sys sys 1168402290 59805
@@ -186,7 +186,7 @@
 386/bin/col - 775 sys sys 1172029864 64995
 386/bin/colors - 775 sys sys 1168402296 150967
 386/bin/comm - 775 sys sys 1168402296 61586
-386/bin/compress - 775 sys sys 1159212097 166928
+386/bin/compress - 775 sys sys 1173039787 166944
 386/bin/con - 775 sys sys 1168402297 78486
 386/bin/cp - 775 sys sys 1168402297 63454
 386/bin/cpp - 775 sys sys 1168402297 150459
@@ -223,7 +223,7 @@
 386/bin/du - 775 sys sys 1168402304 74244
 386/bin/echo - 775 sys sys 1168402304 57592
 386/bin/ed - 775 sys sys 1168402304 93272
-386/bin/eqn - 775 sys sys 1141927235 244405
+386/bin/eqn - 775 sys sys 1173039787 244858
 386/bin/execnet - 775 sys sys 1168402305 178216
 386/bin/exportfs - 775 sys sys 1168402305 162550
 386/bin/ext2srv - 775 sys sys 1168402306 179893
@@ -264,10 +264,10 @@
 386/bin/games/sudoku - 775 sys sys 1117249746 171666
 386/bin/getmap - 775 sys sys 1168402311 65423
 386/bin/gif - 775 sys sys 1168402312 158555
-386/bin/grap - 775 sys sys 1136656337 280496
+386/bin/grap - 775 sys sys 1173039788 282722
 386/bin/graph - 775 sys sys 1168402312 129250
 386/bin/grep - 775 sys sys 1168402312 79569
-386/bin/gs - 775 sys sys 1137468663 13275174
+386/bin/gs - 775 sys sys 1173039815 13278932
 386/bin/gunzip - 775 sys sys 1168402313 80523
 386/bin/gview - 775 sys sys 1168402313 238983
 386/bin/gzip - 775 sys sys 1168402313 84984
@@ -534,7 +534,7 @@
 386/lib - 20000000775 sys sys 1016826328 0
 386/lib/ape - 20000000775 sys sys 1070519112 0
 386/lib/ape/lib9.a - 664 sys sys 1135531447 6906
-386/lib/ape/libap.a - 664 sys sys 1146156977 819888
+386/lib/ape/libap.a - 664 sys sys 1173039817 819938
 386/lib/ape/libbsd.a - 664 sys sys 1146156978 183900
 386/lib/ape/libdraw.a - 664 sys sys 1155491760 621772
 386/lib/ape/libfmt.a - 664 sys sys 1146156980 156706
@@ -7269,7 +7269,7 @@ sys/man - 20000000775 sys sys 1041446473 0
 sys/man/1 - 20000000775 sys sys 1158800370 0
 sys/man/1/0intro - 664 sys sys 1101668050 9625
 sys/man/1/2a - 664 sys sys 1158281866 1196
-sys/man/1/2c - 664 sys sys 1168702903 9195
+sys/man/1/2c - 664 sys sys 1173026977 9204
 sys/man/1/2l - 664 sys sys 1158281887 4376
 sys/man/1/INDEX - 664 sys sys 1141357442 3040
 sys/man/1/INDEX.html - 664 sys sys 1141352366 16517
@@ -8517,7 +8517,7 @@ sys/src/ape/lib/ap/arm/strcmp.s - 664 sys sys 1172956230 1010
 sys/src/ape/lib/ap/arm/strcpy.s - 664 sys sys 1172955904 885
 sys/src/ape/lib/ap/arm/tas.s - 664 sys sys 1014921992 61
 sys/src/ape/lib/ap/arm/vlop.s - 664 sys sys 1172955903 262
-sys/src/ape/lib/ap/arm/vlrt.c - 664 sys sys 1014921992 8983
+sys/src/ape/lib/ap/arm/vlrt.c - 664 sys sys 1173026824 8947
 sys/src/ape/lib/ap/extraobjs - 775 sys sys 1014921988 1356
 sys/src/ape/lib/ap/gen - 20000000775 sys sys 1048644320 0
 sys/src/ape/lib/ap/gen/_assert.c - 664 sys sys 1014921987 347
@@ -8679,7 +8679,7 @@ sys/src/ape/lib/ap/plan9/getpwnam.c - 664 sys sys 1014921984 507
 sys/src/ape/lib/ap/plan9/getpwuid.c - 664 sys sys 1014921984 527
 sys/src/ape/lib/ap/plan9/getuid.c - 664 sys sys 1014921984 199
 sys/src/ape/lib/ap/plan9/isatty.c - 664 sys sys 1014921984 471
-sys/src/ape/lib/ap/plan9/kill.c - 664 sys sys 1071872236 874
+sys/src/ape/lib/ap/plan9/kill.c - 664 sys sys 1173022765 911
 sys/src/ape/lib/ap/plan9/lib.h - 664 sys sys 1072835434 2071
 sys/src/ape/lib/ap/plan9/link.c - 664 sys sys 1014921984 168
 sys/src/ape/lib/ap/plan9/lseek.c - 664 sys sys 1038237526 358
@@ -12663,30 +12663,28 @@ sys/src/cmd/mtime.c - 664 sys sys 1036172302 450
 sys/src/cmd/mug.c - 664 sys sys 1157143847 24888
 sys/src/cmd/mv.c - 664 sys sys 1163029439 4682
 sys/src/cmd/ndb - 20000000775 sys sys 1080135004 0
-sys/src/cmd/ndb/convDNS2M.c - 664 sys sys 1119276409 6866
-sys/src/cmd/ndb/convM2DNS.c - 664 sys sys 1060612175 7248
+sys/src/cmd/ndb/convDNS2M.c - 664 sys sys 1173059857 6856
+sys/src/cmd/ndb/convM2DNS.c - 664 sys sys 1173060986 10495
 sys/src/cmd/ndb/cs.c - 664 sys sys 1163208617 33080
-sys/src/cmd/ndb/csgetval.c - 664 sys sys 957402051 1051
 sys/src/cmd/ndb/csquery.c - 664 sys sys 1014926159 1062
-sys/src/cmd/ndb/dblookup.c - 664 sys sys 1143759343 18249
-sys/src/cmd/ndb/dn.c - 664 sys sys 1144952605 28763
-sys/src/cmd/ndb/dnarea.c - 664 sys sys 1121977162 2128
-sys/src/cmd/ndb/dnnotify.c - 664 sys sys 1144952605 3066
-sys/src/cmd/ndb/dnresolve.c - 664 sys sys 1166760856 15351
-sys/src/cmd/ndb/dns.c - 664 sys sys 1147098969 15309
-sys/src/cmd/ndb/dns.h - 664 sys sys 1144969092 10171
-sys/src/cmd/ndb/dnsdebug.c - 664 sys sys 1144952604 8492
-sys/src/cmd/ndb/dnserver.c - 664 sys sys 1143759353 3982
+sys/src/cmd/ndb/dblookup.c - 664 sys sys 1173060354 18199
+sys/src/cmd/ndb/dn.c - 664 sys sys 1173060793 31773
+sys/src/cmd/ndb/dnarea.c - 664 sys sys 1173059947 2517
+sys/src/cmd/ndb/dnnotify.c - 664 sys sys 1173059885 3155
+sys/src/cmd/ndb/dnresolve.c - 664 sys sys 1173061785 16701
+sys/src/cmd/ndb/dns.c - 664 sys sys 1173061211 15603
+sys/src/cmd/ndb/dns.h - 664 sys sys 1173059802 9841
+sys/src/cmd/ndb/dnsdebug.c - 664 sys sys 1173060595 8633
+sys/src/cmd/ndb/dnserver.c - 664 sys sys 1173060400 4449
 sys/src/cmd/ndb/dnsquery.c - 664 sys sys 1120564714 2198
-sys/src/cmd/ndb/dnstcp.c - 664 sys sys 1144952604 7349
-sys/src/cmd/ndb/dnudpserver.c - 664 sys sys 1144969092 5337
+sys/src/cmd/ndb/dnstcp.c - 664 sys sys 1173061127 7677
+sys/src/cmd/ndb/dnudpserver.c - 664 sys sys 1173061278 5659
 sys/src/cmd/ndb/ipquery.c - 664 sys sys 1124711426 773
 sys/src/cmd/ndb/mkdb.c - 664 sys sys 957402054 2886
-sys/src/cmd/ndb/mkfile - 664 sys sys 1055701930 1877
+sys/src/cmd/ndb/mkfile - 664 sys sys 1173059600 1984
 sys/src/cmd/ndb/mkhash.c - 664 sys sys 1014926160 2899
 sys/src/cmd/ndb/mkhosts.c - 664 sys sys 957402054 4294
 sys/src/cmd/ndb/query.c - 664 sys sys 1078840016 1120
-sys/src/cmd/ndb/time.c - 664 sys sys 957402055 321
 sys/src/cmd/netstat.c - 664 sys sys 1128255434 4086
 sys/src/cmd/news.c - 664 sys sys 1014926614 3778
 sys/src/cmd/nfs.c - 664 sys sys 1050068720 31096

+ 38 - 0
dist/replica/plan9.log

@@ -47632,3 +47632,41 @@
 1172961006 2 c sys/man/2/lock - 664 sys sys 1172959628 4693
 1172961006 3 c sys/man/8/dhcpd - 664 sys sys 1172959497 5572
 1172982606 0 c 386/bin/ip/dhcpd - 775 sys sys 1172980949 151301
+1173024004 0 c sys/src/ape/lib/ap/plan9/kill.c - 664 sys sys 1173022765 911
+1173027606 0 c sys/man/1/2c - 664 sys sys 1173026977 9204
+1173027606 1 c sys/src/ape/lib/ap/arm/vlrt.c - 664 sys sys 1173026824 8947
+1173040206 0 c 386/bin/awk - 775 sys sys 1173039786 324980
+1173040206 1 c 386/bin/eqn - 775 sys sys 1173039787 244858
+1173040206 2 c 386/bin/grap - 775 sys sys 1173039788 282722
+1173040206 3 c 386/bin/gs - 775 sys sys 1173039815 13278932
+1173040206 4 c 386/bin/ape/basename - 775 sys sys 1173039777 134719
+1173040206 5 c 386/bin/ape/diff - 775 sys sys 1173039778 352264
+1173040206 6 c 386/bin/ape/diff3 - 775 sys sys 1173039779 190364
+1173040206 7 c 386/bin/ape/dirname - 775 sys sys 1173039779 134498
+1173040206 8 c 386/bin/ape/expr - 775 sys sys 1173039780 144138
+1173040206 9 c 386/bin/ape/kill - 775 sys sys 1173039781 140067
+1173040206 10 c 386/bin/ape/make - 775 sys sys 1173039781 211605
+1173040206 11 c 386/bin/ape/patch - 775 sys sys 1173039782 305848
+1173040206 12 c 386/bin/ape/sed - 775 sys sys 1173039783 160183
+1173040206 13 c 386/bin/ape/sh - 775 sys sys 1173039783 481732
+1173040206 14 c 386/bin/ape/uname - 775 sys sys 1173039784 134895
+1173040206 15 c 386/bin/aux/lpdaemon - 775 sys sys 1173039785 170710
+1173040206 16 c 386/bin/aux/lpdsend - 775 sys sys 1173039785 157339
+1173040206 17 c 386/bin/compress - 775 sys sys 1173039787 166944
+1173040206 18 c 386/lib/ape/libap.a - 664 sys sys 1173039817 819938
+1173060006 0 c sys/src/cmd/ndb/convDNS2M.c - 664 sys sys 1173059857 6856
+1173060006 1 c sys/src/cmd/ndb/dnarea.c - 664 sys sys 1173059947 2517
+1173060006 2 c sys/src/cmd/ndb/dnnotify.c - 664 sys sys 1173059885 3155
+1173060006 3 c sys/src/cmd/ndb/dns.h - 664 sys sys 1173059802 9841
+1173060006 4 c sys/src/cmd/ndb/mkfile - 664 sys sys 1173059600 1984
+1173061807 0 c sys/src/cmd/ndb/convM2DNS.c - 664 sys sys 1173060986 10495
+1173061807 1 c sys/src/cmd/ndb/dblookup.c - 664 sys sys 1173060354 18199
+1173061807 2 c sys/src/cmd/ndb/dn.c - 664 sys sys 1173060793 31773
+1173061807 3 c sys/src/cmd/ndb/dnresolve.c - 664 sys sys 1173061785 16701
+1173061807 4 c sys/src/cmd/ndb/dns.c - 664 sys sys 1173061211 15603
+1173061807 5 c sys/src/cmd/ndb/dnsdebug.c - 664 sys sys 1173060595 8633
+1173061807 6 c sys/src/cmd/ndb/dnserver.c - 664 sys sys 1173060400 4449
+1173061807 7 c sys/src/cmd/ndb/dnstcp.c - 664 sys sys 1173061127 7677
+1173061807 8 c sys/src/cmd/ndb/dnudpserver.c - 664 sys sys 1173061278 5659
+1173061807 9 d sys/src/cmd/ndb/time.c - 664 sys sys 957402055 0
+1173061807 10 d sys/src/cmd/ndb/csgetval.c - 664 sys sys 957402051 0

+ 1 - 1
sys/man/1/2c

@@ -34,7 +34,7 @@ Motorola MC68000
 Motorola MC68020
 .TP
 .B "5c arm
-ARM 7500
+little-endian ARM
 .TP
 .B "6c amd64
 AMD64 and compatibles (e.g., Intel EM64T)

+ 112 - 80
sys/man/8/ndb

@@ -1,6 +1,6 @@
 .TH NDB 8
 .SH NAME
-query, mkhash, mkdb, cs, csquery, dns, dnsquery, ipquery, dnsdebug, mkhosts \- network database
+query, ipquery, mkhash, mkdb, mkhosts, cs, csquery, dns, dnsquery, dnsdebug \- network database
 .SH SYNOPSIS
 .B ndb/query
 [
@@ -19,6 +19,15 @@ query, mkhash, mkdb, cs, csquery, dns, dnsquery, ipquery, dnsdebug, mkhosts \- n
 .B ndb/mkhash
 .I "file attr"
 .br
+.B ndb/mkdb
+.br
+.B ndb/mkhosts
+[
+.I domain
+[
+.I dbfile
+] ]
+.br
 .B ndb/cs
 [
 .B -n
@@ -43,11 +52,17 @@ query, mkhash, mkdb, cs, csquery, dns, dnsquery, ipquery, dnsdebug, mkhosts \- n
 .br
 .B ndb/dns
 [
-.B -rRsn
+.B -nrRs
+] [
+.B -a
+maxage
 ] [
 .B -f
 .I dbfile
 ] [
+.B -N
+.I target
+] [
 .B -x
 .I netmtpt
 ] [
@@ -60,16 +75,16 @@ query, mkhash, mkdb, cs, csquery, dns, dnsquery, ipquery, dnsdebug, mkhosts \- n
 .B ndb/dnsdebug
 [
 .B -rx
-]
-[ [
+] [
+.B -f
+.I dbfile
+] [ [
 .BI @ server
 ]
 .I domain-name
 [
 .I type
 ] ]
-.br
-.B ndb/mkdb
 .SH DESCRIPTION
 The network database holds administrative information used by
 network programs such as
@@ -105,7 +120,7 @@ with entries of attribute type
 and
 value
 .IR value .
-.PP
+.SS "Database maintenance"
 .I Ndb/mkhash
 creates a hash file for all entries with attribute
 .I attr
@@ -115,6 +130,41 @@ The hash files are used by
 .I ndb/query
 and by the ndb library routines.
 .PP
+.I Ndb/mkdb
+is used in concert with
+.IR awk (1)
+scripts to convert
+uucp systems files and IP host files
+into database files.
+It is very specific to the situation at Murray Hill.
+.PP
+When the database files change underfoot,
+.I ndb/cs
+and
+.I ndb/dns
+track them properly.  Nonetheless, to keep the database searches efficient
+it is necessary to run
+.I ndb/mkhash
+whenever the files are modified.
+It may be profitable to control this by a frequent
+.IR cron (8)
+job.
+.PP
+.I Ndb/mkhosts
+generates a BSD style 
+.BR hosts ,
+.BR hosts.txt ,
+and
+.B hosts.equiv
+files from an ndb data base file specified on the
+command line (default
+.BR /lib/ndb/local ).
+For local reasons the files are called
+.BR hosts.1127 ,
+.BR astro.txt ,
+and
+.BR hosts.equiv .
+.SS "Connection service"
 .I Ndb/cs
 is a server used by
 .IR dial (2)
@@ -142,12 +192,12 @@ supplies the name of the data base file to use,
 default
 .BR /lib/ndb/local .
 .TP
+.B -n
+causes cs to do nothing but set the system name.
+.TP
 .B -x
 specifies the mount point of the
 network.
-.TP
-.B -n
-causes cs to do nothing but set the system name.
 .PP
 .I Ndb/csquery
 can be used to query
@@ -170,7 +220,7 @@ were successfully translated
 The
 .B -s
 flag sets exit status without printing any results.
-.PP
+.SS "Domain name service"
 .I Ndb/dns
 is a server used by
 .I ndb/cs
@@ -182,28 +232,27 @@ By default
 serves only requests written to
 .BR /net/dns .
 The options are:
+.TP -a
+sets the maximum time in seconds that an unreferenced
+domain name will remain cached.
+The default is one hour (3600).
 .TP
 .B -f
 supplies the name of the data base file to use,
 default
 .BR /lib/ndb/local .
 .TP
-.B -x
-specifies the mount point of the
-network.
-.TP
-.B -s
-also cache DNS answers in memory,
-and answer domain requests sent to UDP port 53.
-.TP
 .B -n
 whenever a zone that we serve changes, send UDP NOTIFY
-messages to any dns slaves for that zone.
+messages to any dns slaves for that zone
+(see the
+.L dnsslave
+attribute below).
 .TP
-.B -z
-whenever we receive a UDP NOTIFY message, run
-.I program
-with the domain name of the area as its argument.
+.B -N
+sets the goal for the number of domain names cached to
+.I target
+rather than the default of 4,000.
 .TP
 .B -r
 send `recursive' queries, asking the other servers
@@ -211,7 +260,20 @@ to complete lookups.
 .TP
 .B -R
 ignore the `recursive' bit on incoming requests.
-do not complete lookups on behalf of remote systems.
+Do not complete lookups on behalf of remote systems.
+.TP
+.B -s
+also cache DNS answers in memory,
+and answer domain requests sent to UDP port 53.
+.TP
+.B -x
+specifies the mount point of the
+network.
+.TP
+.B -z
+whenever we receive a UDP NOTIFY message, run
+.I program
+with the domain name of the area as its argument.
 .PD
 .PP
 When the
@@ -221,24 +283,23 @@ option is specified, the servers used come from the
 attribute in the database.  For example, to specify a set of dns servers that
 will resolve requests for systems on the network
 .IR mh-net :
+.IP
 .EX
-
 ipnet=mh-net ip=135.104.0.0 ipmask=255.255.0.0
 	dns=ns1.cs.bell-labs.com
 	dns=ns2.cs.bell-labs.com
 dom=ns1.cs.bell-labs.com ip=135.104.1.11
 dom=ns2.cs.bell-labs.com ip=135.104.1.12
 .EE
-.PP
+.LP
 The server for a domain is indicated by a database entry containing
 both a
 .I dom
 and a
 .I ns
 attribute.
-For example, the entry for the Internet root is:
+.IP
 .EX
-
 dom=
 	ns=A.ROOT-SERVERS.NET
 	ns=B.ROOT-SERVERS.NET
@@ -247,6 +308,7 @@ dom=A.ROOT-SERVERS.NET ip=198.41.0.4
 dom=B.ROOT-SERVERS.NET ip=128.9.0.107
 dom=C.ROOT-SERVERS.NET ip=192.33.4.12
 .EE
+.LP
 The last three lines provide a mapping for the
 server names to their ip addresses.  This is only
 a hint and will be superseded from whatever is learned
@@ -258,8 +320,8 @@ adding an
 .B soa=
 attribute to the root entry.
 For example, the Bell Labs CS research domain is:
+.IP
 .EX
-
 dom=cs.bell-labs.com soa=
 	refresh=3600 ttl=3600
 	ns=plan9.bell-labs.com
@@ -270,8 +332,8 @@ dom=cs.bell-labs.com soa=
 	mx=plan9.bell-labs.com pref=10
 	dnsslave=nslocum.cs.bell-labs.com
 	dnsslave=vex.cs.bell-labs.com
-
 .EE
+.LP
 Here, the
 .B mb
 entry is the mail address of the person responsible for the
@@ -299,14 +361,15 @@ goes with an IP address) by adding an
 attribute to the entry defining the root of the reverse space.
 For example, to provide reverse lookup for all addresses in
 starting with 135.104 you must have a record like:
+.IP
 .EX
-
 dom=104.135.in-addr.arpa soa=
 	refresh=3600 ttl=3600
 	ns=plan9.bell-labs.com
 	ns=ns1.cs.bell-labs.com
 	ns=ns2.cs.bell-labs.com
 .EE
+.LP
 Notice the form of the reverse address, i.e., it's the bytes of the
 address range you are serving reversed and with
 .B .in-addr.arpa
@@ -315,10 +378,11 @@ appended.  This is a standard form for a domain name in an IPv4 PTR record.
 If such an entry exists in the database, reverse addresses will
 automatically be generated from any IP addresses in the database
 that are under this root.  For example
+.IP
 .EX
-
 dom=ns1.cs.bell-labs.com ip=135.104.1.11
 .EE
+.LP
 will automatically create both forward and reverse entries for
 .B ns1.cs.bell-labs.com .
 Unlike other DNS servers, there's no way to generate
@@ -328,14 +392,14 @@ Delegation of a further subtree to another set of name servers
 is indicated by an
 .B soa=delegated
 attribute.
+.IP
 .EX
-
 dom=bignose.cs.research.bell-labs.com
 	soa=delegated
 	ns=anna.cs.research.bell-labs.com
 	ns=dj.cs.research.bell-labs.com
-
 .EE
+.LP
 Nameservers within the delegated domain (as in this example)
 must have their IP addresses listed elsewhere in
 .I ndb
@@ -343,12 +407,12 @@ files.
 .PP
 Wild-carded domain names can also be used.
 For example, to specify a mail forwarder for all Bell Labs research systems:
+.IP
 .EX
-
 dom=*.research.bell-labs.com
 	mx=research.bell-labs.com
-
 .EE
+.LP
 `Cname' aliases may be established by adding a
 .B cname
 attribute giving the real domain name;
@@ -359,11 +423,11 @@ attribute is the alias.
 the aliases may have no other attributes than
 .B dom
 and are daily further restricted in their use by new RFCs.
+.IP
 .EX
-
 cname=anna.cs.research.bell-labs.com dom=www.cs.research.bell-labs.com
-
 .EE
+.LP
 .I Ndb/dnsquery
 can be used to query
 .I ndb/dns
@@ -422,6 +486,13 @@ uses the
 interface and the database file
 .BR /lib/ndb/local.
 The
+.B -f
+option supplies the name of the data base file to use.
+The
+.B -r
+option is the same as for
+.IR ndb/dns .
+The
 .B -x
 option directs
 .I dnsdebug
@@ -429,46 +500,7 @@ to use the
 .B /net.alt
 interface and
 .B /lib/ndb/external
-file.
-The
-.B -r
-option is the same as for
-.IR ndb/dns .
-.PP
-.I Ndb/mkdb
-is used in concert with
-.IR awk (1)
-scripts to convert
-uucp systems files and IP host files
-into database files.
-It is very specific to the situation at Murray Hill.
-.PP
-When the database files change underfoot,
-.I ndb/cs
-and
-.I ndb/dns
-track them properly.  Nonetheless, to keep the database searches efficient
-it is necessary to run
-.I ndb/mkhash
-whenever the files are modified.
-It may be profitable to control this by a frequent
-.IR cron (8)
-job.
-.PP
-.I Ndb/mkhosts
-generates a BSD style 
-.BR hosts ,
-.BR hosts.txt ,
-and
-.B hosts.equiv
-files from an ndb data base file specified on the
-command line (default
-.BR /lib/ndb/local ).
-For local reasons the files are called
-.BR hosts.1127 ,
-.BR astro.txt ,
-and
-.BR hosts.equiv .
+database file.
 .SH EXAMPLES
 .EX
 % ndb/query sys helix
@@ -513,7 +545,7 @@ gets mounted
 .SH SOURCE
 .B /sys/src/cmd/ndb
 .SH SEE ALSO
-.IR ndb (2)
+.IR ndb (2),
 .IR ndb (6)
 .SH BUGS
 .I Ndb

+ 6 - 17
sys/src/ape/lib/ap/arm/vlrt.c

@@ -9,25 +9,15 @@ typedef	signed char	schar;
 typedef	struct	Vlong	Vlong;
 struct	Vlong
 {
-	union
-	{
-		struct
-		{
-			ulong	hi;
-			ulong	lo;
-		};
-		struct
-		{
-			ushort	hims;
-			ushort	hils;
-			ushort	loms;
-			ushort	lols;
-		};
-	};
+	ulong	lo;
+	ulong	hi;
 };
 
 void	abort(void);
 
+/* needed by profiler; can't be profiled */
+#pragma profile off
+
 void
 _addv(Vlong *r, Vlong a, Vlong b)
 {
@@ -54,6 +44,7 @@ _subv(Vlong *r, Vlong a, Vlong b)
 	r->hi = hi;
 }
 
+#pragma profile on
 
 void
 _d2v(Vlong *y, double d)
@@ -148,7 +139,6 @@ dodiv(Vlong num, Vlong den, Vlong *q, Vlong *r)
 	numlo = num.lo;
 	denhi = den.hi;
 	denlo = den.lo;
-
 	/*
 	 * get a divide by zero
 	 */
@@ -203,7 +193,6 @@ dodiv(Vlong num, Vlong den, Vlong *q, Vlong *r)
 void
 _divvu(Vlong *q, Vlong n, Vlong d)
 {
-
 	if(n.hi == 0 && d.hi == 0) {
 		q->hi = 0;
 		q->lo = n.lo / d.lo;

+ 6 - 3
sys/src/ape/lib/ap/plan9/kill.c

@@ -46,9 +46,12 @@ kill(pid_t pid, int sig)
 	if(pid < 0) {
 		sid = getpgrp();
 		mpid = getpid();
-		setpgid(mpid, -pid);
-		r = note(mpid, msg, "/proc/%d/notepg");
-		setpgid(mpid, sid);
+		if(setpgid(mpid, -pid) > 0) {
+			r = note(mpid, msg, "/proc/%d/notepg");
+			setpgid(mpid, sid);
+		} else {
+			r = -1;
+		}
 	} else if(pid == 0)
 		r = note(getpid(), msg, "/proc/%d/notepg");
 	else

+ 10 - 12
sys/src/cmd/ndb/convDNS2M.c

@@ -17,10 +17,10 @@ struct Dict
 		ushort	offset;		/* pointer to packed name in message */
 		char	*name;		/* pointer to unpacked name in buf */
 	} x[Ndict];
-	int n;			/* size of dictionary */
-	uchar *start;		/* start of packed message */
-	char buf[4*1024];	/* buffer for unpacked names */
-	char *ep;		/* first free char in buf */
+	int	n;		/* size of dictionary */
+	uchar	*start;		/* start of packed message */
+	char	buf[4*1024];	/* buffer for unpacked names */
+	char	*ep;		/* first free char in buf */
 };
 
 #define NAME(x)		p = pname(p, ep, x, dp)
@@ -129,17 +129,17 @@ pv6addr(uchar *p, uchar *ep, char *name)
 static uchar*
 pname(uchar *p, uchar *ep, char *np, Dict *dp)
 {
-	char *cp;
 	int i;
+	char *cp;
 	char *last;		/* last component packed */
 
-	if(strlen(np) >= Domlen)	/* make sure we don't exceed DNS limits */
+	if(strlen(np) >= Domlen) /* make sure we don't exceed DNS limits */
 		return ep+1;
 
 	last = 0;
 	while(*np){
 		/* look through every component in the dictionary for a match */
-		for(i = 0; i < dp->n; i++){
+		for(i = 0; i < dp->n; i++)
 			if(strcmp(np, dp->x[i].name) == 0){
 				if(ep - p < 2)
 					return ep+1;
@@ -147,10 +147,9 @@ pname(uchar *p, uchar *ep, char *np, Dict *dp)
 				*p++ = dp->x[i].offset;
 				return p;
 			}
-		}
 
 		/* if there's room, enter this name in dictionary */
-		if(dp->n < Ndict){
+		if(dp->n < Ndict)
 			if(last){
 				/* the whole name is already in dp->buf */
 				last = strchr(last, '.') + 1;
@@ -160,7 +159,7 @@ pname(uchar *p, uchar *ep, char *np, Dict *dp)
 			} else {
 				/* add to dp->buf */
 				i = strlen(np);
-				if(dp->ep + i + 1 < &dp->buf[sizeof(dp->buf)]){
+				if(dp->ep + i + 1 < &dp->buf[sizeof dp->buf]){
 					strcpy(dp->ep, np);
 					dp->x[dp->n].name = dp->ep;
 					last = dp->ep;
@@ -169,11 +168,10 @@ pname(uchar *p, uchar *ep, char *np, Dict *dp)
 					dp->n++;
 				}
 			}
-		}
 
 		/* put next component into message */
 		cp = strchr(np, '.');
-		if(cp == 0){
+		if(cp == nil){
 			i = strlen(np);
 			cp = np + i;	/* point to null terminator */
 		} else {

+ 176 - 100
sys/src/cmd/ndb/convM2DNS.c

@@ -9,66 +9,84 @@ struct Scan
 	uchar	*base;
 	uchar	*p;
 	uchar	*ep;
+
 	char	*err;
+	char	errbuf[256];	/* hold a formatted error sometimes */
+	int	errflags;	/* outgoing reply flags */
 };
 
-#define NAME(x)		gname(x, sp)
-#define SYMBOL(x)	(x = gsym(sp))
-#define STRING(x)	(x = gstr(sp))
-#define USHORT(x)	(x = gshort(sp))
-#define ULONG(x)	(x = glong(sp))
-#define UCHAR(x)	(x = gchar(sp))
-#define V4ADDR(x)	(x = gv4addr(sp))
-#define V6ADDR(x)	(x = gv6addr(sp))
-#define BYTES(x, y)	(y = gbytes(sp, &x, len - (sp->p - data)))
+#define NAME(x)		gname(x, rp, sp)
+#define SYMBOL(x)	(x = gsym(rp, sp))
+#define STRING(x)	(x = gstr(rp, sp))
+#define USHORT(x)	(x = gshort(rp, sp))
+#define ULONG(x)	(x = glong(rp, sp))
+#define UCHAR(x)	(x = gchar(rp, sp))
+#define V4ADDR(x)	(x = gv4addr(rp, sp))
+#define V6ADDR(x)	(x = gv6addr(rp, sp))
+#define BYTES(x, y)	(y = gbytes(rp, sp, &x, len - (sp->p - data)))
+
+static int
+errneg(RR *rp, Scan *sp, int actual)
+{
+	snprint(sp->errbuf, sizeof sp->errbuf, "negative len %d: %R",
+		actual, rp);
+	sp->err = sp->errbuf;
+	return 0;
+}
 
-static char *toolong = "too long";
+static int
+errtoolong(RR *rp, Scan *sp, int actual, int nominal, char *where)
+{
+	char ptype[64];
+
+	snprint(sp->errbuf, sizeof sp->errbuf,
+		"%s%s %s RR: wrong length (actual %d, nominal %d): %R",
+		where? where: "", where? ":": "",
+		rrname(rp? rp->type: -1, ptype, sizeof ptype),
+		actual, nominal, rp);
+	sp->err = sp->errbuf;
+	return 0;
+}
 
 /*
  *  get a ushort/ulong
  */
 static ushort
-gchar(Scan *sp)
+gchar(RR *rp, Scan *sp)
 {
 	ushort x;
 
 	if(sp->err)
 		return 0;
-	if(sp->ep - sp->p < 1){
-		sp->err = toolong;
-		return 0;
-	}
+	if(sp->ep - sp->p < 1)
+		return errtoolong(rp, sp, sp->ep - sp->p, 1, nil);
 	x = sp->p[0];
 	sp->p += 1;
 	return x;
 }
 static ushort
-gshort(Scan *sp)
+gshort(RR *rp, Scan *sp)
 {
 	ushort x;
 
 	if(sp->err)
 		return 0;
-	if(sp->ep - sp->p < 2){
-		sp->err = toolong;
-		return 0;
-	}
-	x = (sp->p[0]<<8) | sp->p[1];
+	if(sp->ep - sp->p < 2)
+		return errtoolong(rp, sp, sp->ep - sp->p, 2, nil);
+	x = sp->p[0]<<8 | sp->p[1];
 	sp->p += 2;
 	return x;
 }
 static ulong
-glong(Scan *sp)
+glong(RR *rp, Scan *sp)
 {
 	ulong x;
 
 	if(sp->err)
 		return 0;
-	if(sp->ep - sp->p < 4){
-		sp->err = toolong;
-		return 0;
-	}
-	x = (sp->p[0]<<24) | (sp->p[1]<<16) | (sp->p[2]<<8) | sp->p[3];
+	if(sp->ep - sp->p < 4)
+		return errtoolong(rp, sp, sp->ep - sp->p, 4, nil);
+	x = sp->p[0]<<24 | sp->p[1]<<16 | sp->p[2]<<8 | sp->p[3];
 	sp->p += 4;
 	return x;
 }
@@ -77,32 +95,28 @@ glong(Scan *sp)
  *  get an ip address
  */
 static DN*
-gv4addr(Scan *sp)
+gv4addr(RR *rp, Scan *sp)
 {
 	char addr[32];
 
 	if(sp->err)
 		return 0;
-	if(sp->ep - sp->p < 4){
-		sp->err = toolong;
-		return 0;
-	}
+	if(sp->ep - sp->p < 4)
+		return (DN*)errtoolong(rp, sp, sp->ep - sp->p, 4, nil);
 	snprint(addr, sizeof(addr), "%V", sp->p);
 	sp->p += 4;
 
 	return dnlookup(addr, Cin, 1);
 }
 static DN*
-gv6addr(Scan *sp)
+gv6addr(RR *rp, Scan *sp)
 {
 	char addr[64];
 
 	if(sp->err)
 		return 0;
-	if(sp->ep - sp->p < IPaddrlen){
-		sp->err = toolong;
-		return 0;
-	}
+	if(sp->ep - sp->p < IPaddrlen)
+		return (DN*)errtoolong(rp, sp, sp->ep - sp->p, IPaddrlen, nil);
 	snprint(addr, sizeof(addr), "%I", sp->p);
 	sp->p += IPaddrlen;
 
@@ -113,25 +127,27 @@ gv6addr(Scan *sp)
  *  get a string.  make it an internal symbol.
  */
 static DN*
-gsym(Scan *sp)
+gsym(RR *rp, Scan *sp)
 {
 	int n;
 	char sym[Strlen+1];
 
 	if(sp->err)
 		return 0;
-	n = *(sp->p++);
-	if(sp->p+n > sp->ep){
-		sp->err = toolong;
-		return 0;
-	}
+	n = 0;
+	if (sp->p < sp->ep)
+		n = *(sp->p++);
+	if(sp->ep - sp->p < n)
+		return (DN*)errtoolong(rp, sp, sp->ep - sp->p, n, "gsym");
 
 	if(n > Strlen){
-		sp->err = "illegal string";
+		sp->err = "illegal string (symbol)";
 		return 0;
 	}
 	strncpy(sym, (char*)sp->p, n);
 	sym[n] = 0;
+	if (strlen(sym) != n)
+		sp->err = "symbol shorter than declared length";
 	sp->p += n;
 
 	return dnlookup(sym, Csym, 1);
@@ -141,7 +157,7 @@ gsym(Scan *sp)
  *  get a string.  don't make it an internal symbol.
  */
 static Txt*
-gstr(Scan *sp)
+gstr(RR *rp, Scan *sp)
 {
 	int n;
 	char sym[Strlen+1];
@@ -149,11 +165,11 @@ gstr(Scan *sp)
 
 	if(sp->err)
 		return 0;
-	n = *(sp->p++);
-	if(sp->p+n > sp->ep){
-		sp->err = toolong;
-		return 0;
-	}
+	n = 0;
+	if (sp->p < sp->ep)
+		n = *(sp->p++);
+	if(sp->ep - sp->p < n)
+		return (Txt*)errtoolong(rp, sp, sp->ep - sp->p, n, "gstr");
 
 	if(n > Strlen){
 		sp->err = "illegal string";
@@ -161,6 +177,8 @@ gstr(Scan *sp)
 	}
 	strncpy(sym, (char*)sp->p, n);
 	sym[n] = 0;
+	if (strlen(sym) != n)
+		sp->err = "string shorter than declared length";
 	sp->p += n;
 
 	t = emalloc(sizeof(*t));
@@ -173,14 +191,15 @@ gstr(Scan *sp)
  *  get a sequence of bytes
  */
 static int
-gbytes(Scan *sp, uchar **p, int n)
+gbytes(RR *rp, Scan *sp, uchar **p, int n)
 {
+	*p = nil;			/* i think this is a good idea */
 	if(sp->err)
 		return 0;
-	if(sp->p+n > sp->ep || n < 0){
-		sp->err = toolong;
-		return 0;
-	}
+	if(n < 0)
+		return errneg(rp, sp, n);
+	if(sp->ep - sp->p < n)
+		return errtoolong(rp, sp, sp->ep - sp->p, n, "gbytes");
 	*p = emalloc(n);
 	memmove(*p, sp->p, n);
 	sp->p += n;
@@ -192,13 +211,10 @@ gbytes(Scan *sp, uchar **p, int n)
  *  get a domain name.  'to' must point to a buffer at least Domlen+1 long.
  */
 static char*
-gname(char *to, Scan *sp)
+gname(char *to, RR *rp, Scan *sp)
 {
-	int len, off;
-	int pointer;
-	int n;
-	char *tostart;
-	char *toend;
+	int len, off, pointer, n;
+	char *tostart, *toend;
 	uchar *p;
 
 	tostart = to;
@@ -207,14 +223,14 @@ gname(char *to, Scan *sp)
 	pointer = 0;
 	p = sp->p;
 	toend = to + Domlen;
-	for(len = 0; *p; len += pointer ? 0 : (n+1)){
+	for(len = 0; *p && p < sp->ep; len += pointer ? 0 : (n+1)){
 		if((*p & 0xc0) == 0xc0){
 			/* pointer to other spot in message */
 			if(pointer++ > 10){
 				sp->err = "pointer loop";
 				goto err;
 			}
-			off = ((p[0]<<8) + p[1]) & 0x3ff;
+			off = (p[0]<<8 | p[1]) & 0x3ff;
 			p = sp->base + off;
 			if(p >= sp->ep){
 				sp->err = "bad pointer";
@@ -223,10 +239,12 @@ gname(char *to, Scan *sp)
 			n = 0;
 			continue;
 		}
-		n = *p++;
+		n = 0;
+		if (p < sp->ep)
+			n = *p++;
 		if(len + n < Domlen - 1){
-			if(to + n > toend){
-				sp->err = toolong;
+			if(n > toend - to){
+				errtoolong(rp, sp, toend - to, n, "gname 1");
 				goto err;
 			}
 			memmove(to, p, n);
@@ -235,7 +253,8 @@ gname(char *to, Scan *sp)
 		p += n;
 		if(*p){
 			if(to >= toend){
-				sp->err = toolong;
+				errtoolong(rp, sp, to-tostart, toend-tostart,
+					"gname 2");
 				goto err;
 			}
 			*to++ = '.';
@@ -252,17 +271,31 @@ err:
 	return tostart;
 }
 
+/*
+ * ms windows 2000 seems to get the bytes backward in the type field
+ * of ptr records, so return a format error as feedback.
+ */
+static void
+mstypehack(Scan *sp, int type, char *where)
+{
+	if ((uchar)type == 0 && (uchar)(type>>8) != 0) {
+		syslog(0, "dns",
+			"%s: byte-swapped type field in ptr rr from win2k",
+			where);
+		if (sp->errflags == 0)
+			sp->errflags = Rformat;
+	}
+}
+
 /*
  *  convert the next RR from a message
  */
 static RR*
-convM2RR(Scan *sp)
+convM2RR(Scan *sp, char *what)
 {
-	RR *rp;
-	int type;
-	int class;
+	RR *rp = nil;
+	int type, class, len;
 	uchar *data;
-	int len;
 	char dname[Domlen+1];
 	Txt *t, **l;
 
@@ -271,6 +304,7 @@ retry:
 	USHORT(type);
 	USHORT(class);
 
+	mstypehack(sp, type, "convM2RR");
 	rp = rralloc(type);
 	rp->owner = dnlookup(dname, class, 1);
 	rp->type = type;
@@ -280,9 +314,20 @@ retry:
 	USHORT(len);
 	data = sp->p;
 
-	if(sp->p + len > sp->ep)
-		sp->err = toolong;
-	if(sp->err){
+	/*
+	 * ms windows generates a lot of badly-formatted hints.
+	 * hints are only advisory, so don't log complaints about them.
+	 * it also generates answers in which p overshoots ep by exactly
+	 * one byte; this seems to be harmless, so don't log them either.
+	 */
+	if (sp->ep - sp->p < len &&
+	   !(strcmp(what, "hints") == 0 ||
+	     sp->p == sp->ep + 1 && strcmp(what, "answers") == 0)) {
+		syslog(0, "dns", "%s sp: base %#p p %#p ep %#p len %d", what,
+			sp->base, sp->p, sp->ep, len);	/* DEBUG */
+		errtoolong(rp, sp, sp->ep - sp->p, len, "convM2RR");
+	}
+	if(sp->err || sp->errflags){
 		rrfree(rp);
 		return 0;
 	}
@@ -292,6 +337,7 @@ retry:
 		/* unknown type, just ignore it */
 		sp->p = data + len;
 		rrfree(rp);
+		rp = nil;
 		goto retry;
 	case Thinfo:
 		SYMBOL(rp->cpu);
@@ -306,11 +352,11 @@ retry:
 		break;
 	case Tmg:
 	case Tmr:
-		rp->mb = dnlookup(NAME(dname), Cin, 1);
+		rp->mb  = dnlookup(NAME(dname), Cin, 1);
 		break;
 	case Tminfo:
 		rp->rmb = dnlookup(NAME(dname), Cin, 1);
-		rp->mb = dnlookup(NAME(dname), Cin, 1);
+		rp->mb  = dnlookup(NAME(dname), Cin, 1);
 		break;
 	case Tmx:
 		USHORT(rp->pref);
@@ -327,7 +373,7 @@ retry:
 		break;
 	case Tsoa:
 		rp->host = dnlookup(NAME(dname), Cin, 1);
-		rp->rmb = dnlookup(NAME(dname), Cin, 1);
+		rp->rmb  = dnlookup(NAME(dname), Cin, 1);
 		ULONG(rp->soa->serial);
 		ULONG(rp->soa->refresh);
 		ULONG(rp->soa->retry);
@@ -337,7 +383,7 @@ retry:
 	case Ttxt:
 		l = &rp->txt;
 		*l = nil;
-		while(sp->p-data < len){
+		while(sp->p - data < len){
 			STRING(t);
 			*l = t;
 			l = &t->next;
@@ -348,7 +394,7 @@ retry:
 		break;
 	case Trp:
 		rp->rmb = dnlookup(NAME(dname), Cin, 1);
-		rp->rp = dnlookup(NAME(dname), Cin, 1);
+		rp->rp  = dnlookup(NAME(dname), Cin, 1);
 		break;
 	case Tkey:
 		USHORT(rp->key->flags);
@@ -374,8 +420,26 @@ retry:
 		BYTES(rp->cert->data, rp->cert->dlen);
 		break;
 	}
-	if(sp->p - data != len)
-		sp->err = "bad RR len";
+	if(sp->p - data != len) {
+		char ptype[64];
+
+		/*
+		 * ms windows 2000 generates cname queries for reverse lookups
+		 * with this particular error.  don't bother logging it.
+		 *
+		 * server: input error: bad cname RR len (actual 2 != len 0):
+		 * 235.9.104.135.in-addr.arpa cname
+		 *	235.9.104.135.in-addr.arpa from 135.104.9.235
+		 */
+		if (0 && type == Tcname && sp->p - data == 2 && len == 0) // WIN
+			return rp;
+
+		snprint(sp->errbuf, sizeof sp->errbuf,
+			"bad %s RR len (actual %lud != len %d): %R",
+			rrname(type, ptype, sizeof ptype),
+			sp->p - data, len, rp);
+		sp->err = sp->errbuf;
+	}
 	return rp;
 }
 
@@ -386,16 +450,16 @@ static RR*
 convM2Q(Scan *sp)
 {
 	char dname[Domlen+1];
-	int type;
-	int class;
-	RR *rp;
+	int type, class;
+	RR *rp = nil;
 
 	NAME(dname);
 	USHORT(type);
 	USHORT(class);
-	if(sp->err)
+	if(sp->err || sp->errflags)
 		return 0;
 
+	mstypehack(sp, type, "convM2Q");
 	rp = rralloc(type);
 	rp->owner = dnlookup(dname, class, 1);
 
@@ -403,21 +467,20 @@ convM2Q(Scan *sp)
 }
 
 static RR*
-rrloop(Scan *sp, int count, int quest)
+rrloop(Scan *sp, char *what, int count, int quest)
 {
 	int i;
-	static char errbuf[64];
 	RR *first, *rp, **l;
 
-	if(sp->err)
+	if(sp->err || sp->errflags)
 		return 0;
 	l = &first;
 	first = 0;
 	for(i = 0; i < count; i++){
-		rp = quest ? convM2Q(sp) : convM2RR(sp);
-		if(rp == 0)
+		rp = quest ? convM2Q(sp) : convM2RR(sp, what);
+		if(rp == nil)
 			break;
-		if(sp->err){
+		if(sp->err || sp->errflags){
 			rrfree(rp);
 			break;
 		}
@@ -428,31 +491,44 @@ rrloop(Scan *sp, int count, int quest)
 }
 
 /*
- *  convert the next DNS from a message stream
+ *  convert the next DNS from a message stream.
+ *  if there are formatting errors or the like during parsing
+ *  of the message, set *errp to the outgoing DNS flags (e.g., Rformat),
+ *  which will abort processing and reply immediately with the outgoing flags.
  */
 char*
-convM2DNS(uchar *buf, int len, DNSmsg *m)
+convM2DNS(uchar *buf, int len, DNSmsg *m, int *errp)
 {
 	Scan scan;
 	Scan *sp;
 	char *err;
+	RR *rp = nil;
 
+	if (errp)
+		*errp = 0;
+	assert(len >= 0);
 	scan.base = buf;
 	scan.p = buf;
 	scan.ep = buf + len;
-	scan.err = 0;
+	scan.err = nil;
+	scan.errbuf[0] = '\0';
+	scan.errflags = 0;
 	sp = &scan;
-	memset(m, 0, sizeof(DNSmsg));
+
+	memset(m, 0, sizeof *m);
 	USHORT(m->id);
 	USHORT(m->flags);
 	USHORT(m->qdcount);
 	USHORT(m->ancount);
 	USHORT(m->nscount);
 	USHORT(m->arcount);
-	m->qd = rrloop(sp, m->qdcount, 1);
-	m->an = rrloop(sp, m->ancount, 0);
-	m->ns = rrloop(sp, m->nscount, 0);
+
+	m->qd = rrloop(sp, "questions",	m->qdcount, 1);
+	m->an = rrloop(sp, "answers",	m->ancount, 0);
+	m->ns = rrloop(sp, "nameservers",m->nscount, 0);
 	err = scan.err;				/* live with bad ar's */
-	m->ar = rrloop(sp, m->arcount, 0);
+	m->ar = rrloop(sp, "hints",	m->arcount, 0);
+	if (errp)
+		*errp = scan.errflags;
 	return err;
 }

+ 0 - 59
sys/src/cmd/ndb/csgetval.c

@@ -1,59 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <ndb.h>
-#include <ndbhf.h>
-
-/*
- *  search for a tuple that has the given 'attr=val' and also 'rattr=x'.
- *  copy 'x' into 'buf' and return the whole tuple.
- *
- *  return 0 if not found.
- */
-Ndbtuple*
-csgetval(char *attr, char *val, char *rattr, char *buf)
-{
-	Ndbtuple *t, *first, *last;
-	int n, fd, linefound;
-	char line[1024];
-
-	buf[0] = 0;
-	fd = open("/net/cs", ORDWR);
-	if(fd < 0)
-		return 0;
-	fprint(fd, "!%s=%s", attr, val);
-	seek(fd, 0, 0);
-
-	first = last = 0;
-	linefound = 0;
-	for(;;){
-		n = read(fd, line, sizeof(line)-2);
-		if(n <= 0)
-			break;
-		line[n] = '\n';
-		line[n+1] = 0;
-
-		t = _ndbparseline(line);
-		if(t == 0)
-			continue;
-		if(first)
-			last->entry = t;
-		else
-			first = t;
-		last = t;
-
-		while(last->entry)
-			last = last->entry;
-
-		for(; t; t = t->entry){
-			if(buf[0] == 0 || linefound == 0)
-				if(strcmp(rattr, t->attr) == 0)
-					strcpy(buf, t->val);
-			if(linefound == 0)
-				if(strcmp(attr, t->attr) == 0)
-					linefound = 1;
-		}
-	}
-	close(fd);
-	return first;
-}

+ 41 - 44
sys/src/cmd/ndb/dblookup.c

@@ -137,10 +137,10 @@ dblookup(char *name, int class, int type, int auth, int ttl)
 	}
 out:
 	/* add owner to uncached records */
-	if(rp){
+	if(rp)
 		for(tp = rp; tp; tp = tp->next)
 			tp->owner = dp;
-	} else {
+	else {
 		/* don't call it non-existent if it's not ours */
 		if(err == Rname && !inmyarea(name))
 			err = Rserver;
@@ -462,13 +462,13 @@ soarr(Ndbtuple *entry, Ndbtuple *pair)
 		rp->rmb = dnlookup(mailbox, Cin, 1);
 	}
 
-	/*  hang dns slaves off of the soa.  this is 
+	/*  hang dns slaves off of the soa.  this is
 	 *  for managing the area.
 	 */
 	for(t = entry; t != nil; t = t->entry)
 		if(strcmp(t->attr, "dnsslave") == 0)
 			addserver(&rp->soa->slaves, t->val);
-			
+
 	return rp;
 }
 
@@ -527,9 +527,8 @@ dbfile2area(Ndb *db)
 	if(debug)
 		syslog(0, logfile, "rereading %s", db->file);
 	Bseek(&db->b, 0, 0);
-	while(t = ndbparse(db)){
+	while(t = ndbparse(db))
 		ndbfree(t);
-	}
 }
 
 /*
@@ -546,22 +545,20 @@ dbpair2cache(DN *dp, Ndbtuple *entry, Ndbtuple *pair)
 	if(cistrcmp(pair->attr, "ip") == 0){
 		dp->ordinal = ord++;
 		rp = addrrr(entry, pair);
-	} else 	if(cistrcmp(pair->attr, "ns") == 0){
+	} else 	if(cistrcmp(pair->attr, "ns") == 0)
 		rp = nsrr(entry, pair);
-	} else if(cistrcmp(pair->attr, "soa") == 0){
+	else if(cistrcmp(pair->attr, "soa") == 0) {
 		rp = soarr(entry, pair);
 		addarea(dp, rp, pair);
-	} else if(cistrcmp(pair->attr, "mx") == 0){
+	} else if(cistrcmp(pair->attr, "mx") == 0)
 		rp = mxrr(entry, pair);
-	} else if(cistrcmp(pair->attr, "cname") == 0){
+	else if(cistrcmp(pair->attr, "cname") == 0)
 		rp = cnamerr(entry, pair);
-	} else if(cistrcmp(pair->attr, "nullrr") == 0){
+	else if(cistrcmp(pair->attr, "nullrr") == 0)
 		rp = nullrr(entry, pair);
-	} else if(cistrcmp(pair->attr, "txtrr") == 0){
+	else if(cistrcmp(pair->attr, "txtrr") == 0)
 		rp = txtrr(entry, pair);
-	}
-
-	if(rp == 0)
+	if(rp == nil)
 		return;
 
 	rp->owner = dp;
@@ -612,11 +609,10 @@ dbfile2cache(Ndb *db)
 void
 db2cache(int doit)
 {
+	ulong youngest, temp;
 	Ndb *ndb;
 	Dir *d;
-	ulong youngest, temp;
-	static ulong lastcheck;
-	static ulong lastyoungest;
+	static ulong lastcheck, lastyoungest;
 
 	/* no faster than once every 2 minutes */
 	if(now < lastcheck + 2*Min && !doit)
@@ -641,23 +637,22 @@ db2cache(int doit)
 	for(;;){
 		lastcheck = now;
 		youngest = 0;
-		for(ndb = db; ndb; ndb = ndb->next){
-			/* the dirfstat avoids walking the mount table each time */
+		for(ndb = db; ndb; ndb = ndb->next)
+			/* dirfstat avoids walking the mount table each time */
 			if((d = dirfstat(Bfildes(&ndb->b))) != nil ||
 			   (d = dirstat(ndb->file)) != nil){
-				temp = d->mtime;		/* ulong vs int crap */
+				temp = d->mtime;	/* ulong vs int crap */
 				if(temp > youngest)
 					youngest = temp;
 				free(d);
 			}
-		}
 		if(!doit && youngest == lastyoungest)
 			break;
-	
+
 		/* forget our area definition */
 		freearea(&owned);
 		freearea(&delegated);
-	
+
 		/* reopen all the files (to get oldest for time stamp) */
 		for(ndb = db; ndb; ndb = ndb->next)
 			ndbreopen(ndb);
@@ -665,21 +660,20 @@ db2cache(int doit)
 		if(cachedb){
 			/* mark all db records as timed out */
 			dnagedb();
-	
+
 			/* read in new entries */
 			for(ndb = db; ndb; ndb = ndb->next)
 				dbfile2cache(ndb);
-	
+
 			/* mark as authentic anything in our domain */
 			dnauthdb();
-	
+
 			/* remove old entries */
 			dnageall(1);
-		} else {
+		} else
 			/* read all the soa's to get database defaults */
 			for(ndb = db; ndb; ndb = ndb->next)
 				dbfile2area(ndb);
-		}
 
 		doit = 0;
 		lastyoungest = youngest;
@@ -703,7 +697,7 @@ lookupinfo(char *attr)
 
 	snprint(buf, sizeof buf, "%I", ipaddr);
 	a[0] = attr;
-	
+
 	lock(&dblock);
 	if(opendatabase() < 0){
 		unlock(&dblock);
@@ -714,7 +708,7 @@ lookupinfo(char *attr)
 	return t;
 }
 
-char *localservers = "local#dns#servers";
+char *localservers =	  "local#dns#servers";
 char *localserverprefix = "local#dns#server";
 
 /*
@@ -740,7 +734,8 @@ baddelegation(RR *rp, RR *nsrp, uchar *addr)
 		if(rp->owner != nsrp->owner)
 		if(subsume(rp->owner->name, nsrp->owner->name) &&
 		   strcmp(nsrp->owner->name, localservers) != 0){
-			syslog(0, logfile, "delegation loop %R -> %R from %I", nsrp, rp, addr);
+			syslog(0, logfile, "delegation loop %R -> %R from %I",
+				nsrp, rp, addr);
 			return 1;
 		}
 
@@ -749,7 +744,8 @@ baddelegation(RR *rp, RR *nsrp, uchar *addr)
 			if(rp->host && cistrcmp(rp->host->name, nt->val) == 0)
 				break;
 		if(nt != nil && !inmyarea(rp->owner->name)){
-			syslog(0, logfile, "bad delegation %R from %I", rp, addr);
+			syslog(0, logfile, "bad delegation %R from %I",
+				rp, addr);
 			return 1;
 		}
 	}
@@ -792,12 +788,12 @@ addlocaldnsserver(DN *dp, int class, char *ipaddr, int i)
 RR*
 dnsservers(int class)
 {
+	int i, n;
+	char *p, *buf;
+	char *args[5];
 	Ndbtuple *t, *nt;
 	RR *nsrp;
 	DN *dp;
-	char *p;
-	int i, n;
-	char *buf, *args[5];
 
 	dp = dnlookup(localservers, class, 1);
 	nsrp = rrlookup(dp, Tns, NOneg);
@@ -880,12 +876,10 @@ static void
 createptrs(void)
 {
 	int len, dlen, n;
-	Area *s;
+	char buf[Domlen+1], ipa[48];
 	char *f[40];
-	char buf[Domlen+1];
-	uchar net[IPaddrlen];
-	uchar mask[IPaddrlen];
-	char ipa[48];
+	uchar net[IPaddrlen], mask[IPaddrlen];
+	Area *s;
 	Ndbtuple *t, *nt;
 
 	dlen = strlen(v4ptrdom);
@@ -928,10 +922,10 @@ createptrs(void)
 			net[IPv4off+3] = atoi(f[0]);
 			sprint(ipa, "%I", net);
 			t = ndbipinfo(db, "ip", ipa, attribs, 1);
-			if(t == nil) /* could be a reverse with no forward */
+			if(t == nil)	/* could be a reverse with no forward */
 				continue;
 			nt = look(t, t, "ipmask");
-			if(nt == nil){	/* we're confused */
+			if(nt == nil){		/* we're confused */
 				ndbfree(t);
 				continue;
 			}
@@ -942,7 +936,10 @@ createptrs(void)
 			continue;
 		}
 
-		/* go through all domain entries looking for RR's in this network and create ptrs */
+		/*
+		 * go through all domain entries looking for RR's
+		 * in this network and create ptrs
+		 */
 		dnptr(net, mask, s->soarr->owner->name, 6-n, 0);
 	}
 }

+ 239 - 141
sys/src/cmd/ndb/dn.c

@@ -9,17 +9,15 @@
  *  Hash table for domain names.  The hash is based only on the
  *  first element of the domain name.
  */
-DN	*ht[HTLEN];
+DN *ht[HTLEN];
 
-
-static struct
-{
+static struct {
 	Lock;
 	ulong	names;	/* names allocated */
 	ulong	oldest;	/* longest we'll leave a name around */
 	int	active;
 	int	mutex;
-	int	id;
+	ushort	id;	/* same size as in packet */
 } dnvars;
 
 /* names of RR types */
@@ -110,6 +108,7 @@ char *rname[Rmask+1] =
 [Rbadname]		"duplicate key name",
 [Rbadalg]		"bad algorithm",
 };
+unsigned nrname = nelem(rname);
 
 /* names of op codes */
 char *opname[] =
@@ -124,9 +123,6 @@ Lock	dnlock;
 
 static int sencodefmt(Fmt*);
 
-/*
- *  set up a pipe to use as a lock
- */
 void
 dninit(void)
 {
@@ -139,6 +135,7 @@ dninit(void)
 
 	dnvars.oldest = maxage;
 	dnvars.names = 0;
+	dnvars.id = truerand();	/* don't start with same id every time */
 }
 
 /*
@@ -151,7 +148,7 @@ dnhash(char *name)
 	uchar *val = (uchar*)name;
 
 	for(hash = 0; *val; val++)
-		hash = (hash*13) + tolower(*val)-'a';
+		hash = hash*13 + tolower(*val)-'a';
 	return hash % HTLEN;
 }
 
@@ -176,7 +173,8 @@ dnlookup(char *name, int class, int enter)
 		}
 		l = &dp->next;
 	}
-	if(enter == 0){
+
+	if(!enter){
 		unlock(&dnlock);
 		return 0;
 	}
@@ -184,7 +182,7 @@ dnlookup(char *name, int class, int enter)
 	dp = emalloc(sizeof(*dp));
 	dp->magic = DNmagic;
 	dp->name = estrdup(name);
-	assert(dp->name != 0);
+	assert(dp->name != nil);
 	dp->class = class;
 	dp->rr = 0;
 	dp->next = 0;
@@ -209,14 +207,14 @@ dndump(char *file)
 	if(fd < 0)
 		return;
 	lock(&dnlock);
-	for(i = 0; i < HTLEN; i++){
+	for(i = 0; i < HTLEN; i++)
 		for(dp = ht[i]; dp; dp = dp->next){
 			fprint(fd, "%s\n", dp->name);
 			for(rp = dp->rr; rp; rp = rp->next)
-				fprint(fd, "	%R %c%c %lud/%lud\n", rp, rp->auth?'A':'U',
-					rp->db?'D':'N', rp->expire, rp->ttl);
+				fprint(fd, "	%R %c%c %lud/%lud\n",
+					rp, rp->auth? 'A': 'U',
+					rp->db? 'D': 'N', rp->expire, rp->ttl);
 		}
-	}
 	unlock(&dnlock);
 	close(fd);
 }
@@ -274,12 +272,27 @@ dnage(DN *dp)
 	}
 }
 
-#define REF(x) if(x) x->refs++
+#define REF(x) upref(x)
+
+static void
+upref(DN *dp)
+{
+	if (dp == nil)
+		return;
+	dp->refs++;
+	assert(dp->refs < 120);		/* make sure it fits in a signed char */
+}
 
 /*
- *  our target is 4000 names cached, this should be larger on large servers
+ *  this comment used to say `our target is 4000 names cached, this should
+ *  be larger on large servers'.  /lib/ndb at Bell Labs starts off with
+ *  about 1780 names, so 4000 is not a lot.
  */
-#define TARGET 4000
+enum {
+	Deftarget = 8000,
+};
+
+ulong target = Deftarget;
 
 /*
  *  periodicly sweep for old records and remove unreferenced domain names
@@ -294,13 +307,16 @@ dnageall(int doit)
 	RR *rp;
 	static ulong nextage;
 
-	if(dnvars.names < TARGET && now < nextage && !doit){
+	if(dnvars.names < target || (now < nextage && !doit)){
 		dnvars.oldest = maxage;
 		return;
 	}
 
-	if(dnvars.names > TARGET)
+	if(dnvars.names >= target) {
+		syslog(0, "dns", "more names (%lud) than target (%lud)",
+			dnvars.names, target);
 		dnvars.oldest /= 2;
+	}
 	nextage = now + maxage;
 
 	lock(&dnlock);
@@ -375,6 +391,7 @@ dnageall(int doit)
 					free(dp->name);
 				dp->magic = ~dp->magic;
 				dnvars.names--;
+				memset(dp, 0, sizeof *dp); /* cause trouble */
 				free(dp);
 				continue;
 			}
@@ -409,14 +426,16 @@ dnagedb(void)
 }
 
 /*
- *  mark all local db records about my area as authoritative, time out any others
+ *  mark all local db records about my area as authoritative,
+ *  time out any others
  */
 void
 dnauthdb(void)
 {
-	DN *dp;
 	int i;
+	ulong minttl;
 	Area *area;
+	DN *dp;
 	RR *rp;
 	static ulong nextage;
 
@@ -429,13 +448,14 @@ dnauthdb(void)
 			for(rp = dp->rr; rp; rp = rp->next)
 				if(rp->db){
 					if(area){
-						if(rp->ttl < area->soarr->soa->minttl)
-							rp->ttl = area->soarr->soa->minttl;
+						minttl = area->soarr->soa->minttl;
+						if(rp->ttl < minttl)
+							rp->ttl = minttl;
 						rp->auth = 1;
 					}
 					if(rp->expire == 0){
 						rp->db = 0;
-						dp->referenced = now - Reserved - 1;
+						dp->referenced = now-Reserved-1;
 					}
 				}
 		}
@@ -452,7 +472,9 @@ getactivity(Request *req, int recursive)
 {
 	int rv;
 
-	if(traceactivity) syslog(0, "dns", "get %d by %d from %p", dnvars.active, getpid(), getcallerpc(&req));
+	if(traceactivity)
+		syslog(0, "dns", "get: %d active by pid %d from %p",
+			dnvars.active, getpid(), getcallerpc(&req));
 	lock(&dnvars);
 	/*
 	 * can't block here if we're already holding one
@@ -460,7 +482,9 @@ getactivity(Request *req, int recursive)
 	 */
 	while(!recursive && dnvars.mutex){
 		unlock(&dnvars);
-		sleep(200);
+		syslog(0, "dns", "get: waiting for dnvars.mutex, pid %d",
+			getpid());
+		sleep(100);			/* was 200 */
 		lock(&dnvars);
 	}
 	rv = ++dnvars.active;
@@ -475,17 +499,20 @@ putactivity(int recursive)
 {
 	static ulong lastclean;
 
-	if(traceactivity) syslog(0, "dns", "put %d by %d", dnvars.active, getpid());
+	if(traceactivity)
+		syslog(0, "dns", "put: %d active by pid %d",
+			dnvars.active, getpid());
 	lock(&dnvars);
 	dnvars.active--;
-	assert(dnvars.active >= 0); /* "dnvars.active %d", dnvars.active */;
+	assert(dnvars.active >= 0); /* "dnvars.active %d", dnvars.active */
 
 	/*
 	 *  clean out old entries and check for new db periodicly
 	 *  can't block here if being called to let go a "recursive" lock
 	 *  or we'll deadlock waiting for ourselves to give up the dnvars.active.
 	 */
-	if(recursive || dnvars.mutex || (needrefresh == 0 && dnvars.active > 0)){
+	if (recursive || dnvars.mutex ||
+	    (needrefresh == 0 && dnvars.active > 0)){
 		unlock(&dnvars);
 		return;
 	}
@@ -494,7 +521,9 @@ putactivity(int recursive)
 	dnvars.mutex = 1;
 	while(dnvars.active > 0){
 		unlock(&dnvars);
-		sleep(100);
+		syslog(0, "dns", "put: waiting for dnvars.active==0, pid %d",
+			getpid());
+		sleep(100);		/* was 100 */
 		lock(&dnvars);
 	}
 	unlock(&dnvars);
@@ -565,7 +594,8 @@ rrattach1(RR *new, int auth)
 			/* all things equal, pick the newer one */
 			if(rp->arg0 == new->arg0 && rp->arg1 == new->arg1){
 				/* new drives out old */
-				if(new->ttl > rp->ttl || new->expire > rp->expire){
+				if (new->ttl > rp->ttl ||
+				    new->expire > rp->expire){
 					*l = rp->next;
 					rp->cached = 0;
 					rrfree(rp);
@@ -580,11 +610,10 @@ rrattach1(RR *new, int auth)
 			 *  the ordering in the list reflects the ordering
 			 *  received or read from the database
 			 */
-			if(rp->type == Tptr){
+			if(rp->type == Tptr)
 				if(!rp->negative && !new->negative
 				&& rp->ptr->ordinal > new->ptr->ordinal)
 					break;
-			}
 		}
 		l = &rp->next;
 	}
@@ -612,7 +641,7 @@ rrattach(RR *rp, int auth)
 	lock(&dnlock);
 	for(; rp; rp = next){
 		next = rp->next;
-		rp->next = 0;
+		rp->next = nil;
 
 		/* avoid any outside spoofing */
 		if(cachedb && !rp->db && inmyarea(rp->owner->name))
@@ -676,41 +705,53 @@ rrfree(RR *rp)
 	if(dp){
 		assert(dp->magic == DNmagic);
 		for(nrp = dp->rr; nrp; nrp = nrp->next)
-			assert(nrp != rp); /* "rrfree of live rr" */;
+			assert(nrp != rp);	/* "rrfree of live rr" */
 	}
 
 	switch(rp->type){
 	case Tsoa:
 		freeserverlist(rp->soa->slaves);
+		memset(rp->soa, 0, sizeof *rp->soa);	/* cause trouble */
 		free(rp->soa);
 		break;
 	case Tkey:
+		memset(rp->key->data, 0, sizeof *rp->key->data); /* cause trouble */
 		free(rp->key->data);
+		memset(rp->key, 0, sizeof *rp->key);	/* cause trouble */
 		free(rp->key);
 		break;
 	case Tcert:
+		memset(rp->cert->data, 0, sizeof *rp->cert->data); /* cause trouble */
 		free(rp->cert->data);
+		memset(rp->cert, 0, sizeof *rp->cert);	/* cause trouble */
 		free(rp->cert);
 		break;
 	case Tsig:
+		memset(rp->sig->data, 0, sizeof *rp->sig->data); /* cause trouble */
 		free(rp->sig->data);
+		memset(rp->sig, 0, sizeof *rp->sig);	/* cause trouble */
 		free(rp->sig);
 		break;
 	case Tnull:
+		memset(rp->null->data, 0, sizeof *rp->null->data); /* cause trouble */
 		free(rp->null->data);
+		memset(rp->null, 0, sizeof *rp->null);	/* cause trouble */
 		free(rp->null);
 		break;
 	case Ttxt:
 		while(rp->txt != nil){
 			t = rp->txt;
 			rp->txt = t->next;
+			memset(t->p, 0, sizeof *t->p);	/* cause trouble */
 			free(t->p);
+			memset(t, 0, sizeof *t);	/* cause trouble */
 			free(t);
 		}
 		break;
 	}
 
 	rp->magic = ~rp->magic;
+	memset(rp, 0, sizeof *rp);		/* cause trouble */
 	free(rp);
 }
 
@@ -728,7 +769,7 @@ rrfreelist(RR *rp)
 	}
 }
 
-extern RR**
+RR**
 rrcopy(RR *rp, RR **last)
 {
 	RR *nrp;
@@ -874,13 +915,12 @@ rrlookup(DN *dp, int type, int flag)
 		goto out;
 
 	/* otherwise, settle for anything we got (except for negative caches)  */
-	for(rp = dp->rr; rp; rp = rp->next){
+	for(rp = dp->rr; rp; rp = rp->next)
 		if(tsame(type, rp->type)){
 			if(rp->negative)
 				goto out;
 			last = rrcopy(rp, last);
 		}
-	}
 
 out:
 	unlock(&dnlock);
@@ -900,7 +940,7 @@ rrtype(char *atype)
 		if(rrtname[i] && strcmp(rrtname[i], atype) == 0)
 			return i;
 
-	// make any a synonym for all
+	/* make any a synonym for all */
 	if(strcmp(atype, "any") == 0)
 		return Tall;
 	return atoi(atype);
@@ -914,10 +954,10 @@ rrname(int type, char *buf, int len)
 {
 	char *t;
 
-	t = 0;
-	if(type <= Tall)
+	t = nil;
+	if(type >= 0 && type <= Tall)
 		t = rrtname[type];
-	if(t==0){
+	if(t==nil){
 		snprint(buf, len, "%d", type);
 		t = buf;
 	}
@@ -932,7 +972,7 @@ rrsupported(int type)
 {
 	if(type < 0 || type >Tall)
 		return 0;
-	return rrtname[type] != 0;
+	return rrtname[type] != nil;
 }
 
 /*
@@ -954,7 +994,7 @@ rrcat(RR **start, RR *rp)
 	RR **last;
 
 	last = start;
-	while(*last != 0)
+	while(*last != nil)
 		last = &(*last)->next;
 
 	*last = rp;
@@ -992,8 +1032,8 @@ rrremneg(RR **l)
 RR*
 rrremtype(RR **l, int type)
 {
-	RR **nl, *rp;
-	RR *first;
+	RR *first, *rp;
+	RR **nl;
 
 	first = nil;
 	nl = &first;
@@ -1011,29 +1051,36 @@ rrremtype(RR **l, int type)
 	return first;
 }
 
+static char *
+dnname(DN *dn)
+{
+	return dn? dn->name: "<null>";
+}
+
 /*
  *  print conversion for rr records
  */
 int
 rrfmt(Fmt *f)
 {
-	RR *rp;
-	char *strp;
-	Fmt fstr;
 	int rv;
+	char *strp;
 	char buf[Domlen];
+	Fmt fstr;
+	RR *rp;
 	Server *s;
+	SOA *soa;
 	Txt *t;
 
 	fmtstrinit(&fstr);
 
 	rp = va_arg(f->args, RR*);
-	if(rp == 0){
+	if(rp == nil){
 		fmtprint(&fstr, "<null>");
 		goto out;
 	}
 
-	fmtprint(&fstr, "%s %s", rp->owner->name,
+	fmtprint(&fstr, "%s %s", dnname(rp->owner),
 		rrname(rp->type, buf, sizeof buf));
 
 	if(rp->negative){
@@ -1043,42 +1090,51 @@ rrfmt(Fmt *f)
 
 	switch(rp->type){
 	case Thinfo:
-		fmtprint(&fstr, "\t%s %s", rp->cpu->name, rp->os->name);
+		fmtprint(&fstr, "\t%s %s", dnname(rp->cpu), dnname(rp->os));
 		break;
 	case Tcname:
 	case Tmb:
 	case Tmd:
 	case Tmf:
 	case Tns:
-		fmtprint(&fstr, "\t%s", rp->host->name);
+		fmtprint(&fstr, "\t%s", dnname(rp->host));
 		break;
 	case Tmg:
 	case Tmr:
-		fmtprint(&fstr, "\t%s", rp->mb->name);
+		fmtprint(&fstr, "\t%s", dnname(rp->mb));
 		break;
 	case Tminfo:
-		fmtprint(&fstr, "\t%s %s", rp->mb->name, rp->rmb->name);
+		fmtprint(&fstr, "\t%s %s", dnname(rp->mb), dnname(rp->rmb));
 		break;
 	case Tmx:
-		fmtprint(&fstr, "\t%lud %s", rp->pref, rp->host->name);
+		fmtprint(&fstr, "\t%lud %s", rp->pref, dnname(rp->host));
 		break;
 	case Ta:
 	case Taaaa:
-		fmtprint(&fstr, "\t%s", rp->ip->name);
+		fmtprint(&fstr, "\t%s", dnname(rp->ip));
 		break;
 	case Tptr:
-//		fmtprint(&fstr, "\t%s(%lud)", rp->ptr->name, rp->ptr->ordinal);
-		fmtprint(&fstr, "\t%s", rp->ptr->name);
+//		fmtprint(&fstr, "\t%s(%lud)", dnname(rp->ptr),
+//			rp->ptr? rp->ptr->ordinal: "<null>");
+		fmtprint(&fstr, "\t%s", dnname(rp->ptr));
 		break;
 	case Tsoa:
-		fmtprint(&fstr, "\t%s %s %lud %lud %lud %lud %lud", rp->host->name,
-			rp->rmb->name, rp->soa->serial, rp->soa->refresh, rp->soa->retry,
-			rp->soa->expire, rp->soa->minttl);
-		for(s = rp->soa->slaves; s != nil; s = s->next)
-			fmtprint(&fstr, " %s", s->name);
+		soa = rp->soa;
+		fmtprint(&fstr, "\t%s %s %lud %lud %lud %lud %lud",
+			dnname(rp->host), dnname(rp->rmb),
+			(soa? soa->serial: 0),
+			(soa? soa->refresh: 0), (soa? soa->retry: 0),
+			(soa? soa->expire: 0), (soa? soa->minttl: 0));
+		if (soa)
+			for(s = soa->slaves; s != nil; s = s->next)
+				fmtprint(&fstr, " %s", s->name);
 		break;
 	case Tnull:
-		fmtprint(&fstr, "\t%.*H", rp->null->dlen, rp->null->data);
+		if (rp->null == nil)
+			fmtprint(&fstr, "\t<null>");
+		else
+			fmtprint(&fstr, "\t%.*H", rp->null->dlen,
+				rp->null->data);
 		break;
 	case Ttxt:
 		fmtprint(&fstr, "\t");
@@ -1086,22 +1142,31 @@ rrfmt(Fmt *f)
 			fmtprint(&fstr, "%s", t->p);
 		break;
 	case Trp:
-		fmtprint(&fstr, "\t%s %s", rp->rmb->name, rp->rp->name);
+		fmtprint(&fstr, "\t%s %s", dnname(rp->rmb), dnname(rp->rp));
 		break;
 	case Tkey:
-		fmtprint(&fstr, "\t%d %d %d", rp->key->flags, rp->key->proto,
-			rp->key->alg);
+		if (rp->key == nil)
+			fmtprint(&fstr, "\t<null> <null> <null>");
+		else
+			fmtprint(&fstr, "\t%d %d %d", rp->key->flags,
+				rp->key->proto, rp->key->alg);
 		break;
 	case Tsig:
-		fmtprint(&fstr, "\t%d %d %d %lud %lud %lud %d %s",
-			rp->sig->type, rp->sig->alg, rp->sig->labels, rp->sig->ttl,
-			rp->sig->exp, rp->sig->incep, rp->sig->tag, rp->sig->signer->name);
+		if (rp->sig == nil)
+			fmtprint(&fstr,
+		   "\t<null> <null> <null> <null> <null> <null> <null> <null>");
+		else
+			fmtprint(&fstr, "\t%d %d %d %lud %lud %lud %d %s",
+				rp->sig->type, rp->sig->alg, rp->sig->labels,
+				rp->sig->ttl, rp->sig->exp, rp->sig->incep,
+				rp->sig->tag, dnname(rp->sig->signer));
 		break;
 	case Tcert:
-		fmtprint(&fstr, "\t%d %d %d",
-			rp->sig->type, rp->sig->tag, rp->sig->alg);
-		break;
-	default:
+		if (rp->cert == nil)
+			fmtprint(&fstr, "\t<null> <null> <null>");
+		else
+			fmtprint(&fstr, "\t%d %d %d",
+				rp->cert->type, rp->cert->tag, rp->cert->alg);
 		break;
 	}
 out:
@@ -1117,69 +1182,78 @@ out:
 int
 rravfmt(Fmt *f)
 {
-	RR *rp;
+	int rv, quote;
 	char *strp;
 	Fmt fstr;
-	int rv;
+	RR *rp;
 	Server *s;
+	SOA *soa;
 	Txt *t;
-	int quote;
 
 	fmtstrinit(&fstr);
 
 	rp = va_arg(f->args, RR*);
-	if(rp == 0){
+	if(rp == nil){
 		fmtprint(&fstr, "<null>");
 		goto out;
 	}
 
 	if(rp->type == Tptr)
-		fmtprint(&fstr, "ptr=%s", rp->owner->name);
+		fmtprint(&fstr, "ptr=%s", dnname(rp->owner));
 	else
-		fmtprint(&fstr, "dom=%s", rp->owner->name);
+		fmtprint(&fstr, "dom=%s", dnname(rp->owner));
 
 	switch(rp->type){
 	case Thinfo:
-		fmtprint(&fstr, " cpu=%s os=%s", rp->cpu->name, rp->os->name);
+		fmtprint(&fstr, " cpu=%s os=%s",
+			dnname(rp->cpu), dnname(rp->os));
 		break;
 	case Tcname:
-		fmtprint(&fstr, " cname=%s", rp->host->name);
+		fmtprint(&fstr, " cname=%s", dnname(rp->host));
 		break;
 	case Tmb:
 	case Tmd:
 	case Tmf:
-		fmtprint(&fstr, " mbox=%s", rp->host->name);
+		fmtprint(&fstr, " mbox=%s", dnname(rp->host));
 		break;
 	case Tns:
-		fmtprint(&fstr,  " ns=%s", rp->host->name);
+		fmtprint(&fstr,  " ns=%s", dnname(rp->host));
 		break;
 	case Tmg:
 	case Tmr:
-		fmtprint(&fstr, " mbox=%s", rp->mb->name);
+		fmtprint(&fstr, " mbox=%s", dnname(rp->mb));
 		break;
 	case Tminfo:
-		fmtprint(&fstr, " mbox=%s mbox=%s", rp->mb->name, rp->rmb->name);
+		fmtprint(&fstr, " mbox=%s mbox=%s",
+			dnname(rp->mb), dnname(rp->rmb));
 		break;
 	case Tmx:
-		fmtprint(&fstr, " pref=%lud mx=%s", rp->pref, rp->host->name);
+		fmtprint(&fstr, " pref=%lud mx=%s", rp->pref, dnname(rp->host));
 		break;
 	case Ta:
 	case Taaaa:
-		fmtprint(&fstr, " ip=%s", rp->ip->name);
+		fmtprint(&fstr, " ip=%s", dnname(rp->ip));
 		break;
 	case Tptr:
-		fmtprint(&fstr, " dom=%s", rp->ptr->name);
+		fmtprint(&fstr, " dom=%s", dnname(rp->ptr));
 		break;
 	case Tsoa:
-		fmtprint(&fstr, " ns=%s mbox=%s serial=%lud refresh=%lud retry=%lud expire=%lud ttl=%lud",
-			rp->host->name, rp->rmb->name, rp->soa->serial,
-			rp->soa->refresh, rp->soa->retry,
-			rp->soa->expire, rp->soa->minttl);
-		for(s = rp->soa->slaves; s != nil; s = s->next)
+		soa = rp->soa;
+		fmtprint(&fstr,
+" ns=%s mbox=%s serial=%lud refresh=%lud retry=%lud expire=%lud ttl=%lud",
+			dnname(rp->host), dnname(rp->rmb),
+			(soa? soa->serial: 0),
+			(soa? soa->refresh: 0), (soa? soa->retry: 0),
+			(soa? soa->expire: 0), (soa? soa->minttl: 0));
+		for(s = soa->slaves; s != nil; s = s->next)
 			fmtprint(&fstr, " dnsslave=%s", s->name);
 		break;
 	case Tnull:
-		fmtprint(&fstr, " null=%.*H", rp->null->dlen, rp->null->data);
+		if (rp->null == nil)
+			fmtprint(&fstr, " null=<null>");
+		else
+			fmtprint(&fstr, " null=%.*H", rp->null->dlen,
+				rp->null->data);
 		break;
 	case Ttxt:
 		fmtprint(&fstr, " txt=");
@@ -1195,22 +1269,33 @@ rravfmt(Fmt *f)
 			fmtprint(&fstr, "\"");
 		break;
 	case Trp:
-		fmtprint(&fstr, " rp=%s txt=%s", rp->rmb->name, rp->rp->name);
+		fmtprint(&fstr, " rp=%s txt=%s",
+			dnname(rp->rmb), dnname(rp->rp));
 		break;
 	case Tkey:
-		fmtprint(&fstr, " flags=%d proto=%d alg=%d",
-			rp->key->flags, rp->key->proto, rp->key->alg);
+		if (rp->key == nil)
+			fmtprint(&fstr, " flags=<null> proto=<null> alg=<null>");
+		else
+			fmtprint(&fstr, " flags=%d proto=%d alg=%d",
+				rp->key->flags, rp->key->proto, rp->key->alg);
 		break;
 	case Tsig:
-		fmtprint(&fstr, " type=%d alg=%d labels=%d ttl=%lud exp=%lud incep=%lud tag=%d signer=%s",
-			rp->sig->type, rp->sig->alg, rp->sig->labels, rp->sig->ttl,
-			rp->sig->exp, rp->sig->incep, rp->sig->tag, rp->sig->signer->name);
+		if (rp->sig == nil)
+			fmtprint(&fstr,
+" type=<null> alg=<null> labels=<null> ttl=<null> exp=<null> incep=<null> tag=<null> signer=<null>");
+		else
+			fmtprint(&fstr,
+" type=%d alg=%d labels=%d ttl=%lud exp=%lud incep=%lud tag=%d signer=%s",
+				rp->sig->type, rp->sig->alg, rp->sig->labels,
+				rp->sig->ttl, rp->sig->exp, rp->sig->incep,
+				rp->sig->tag, dnname(rp->sig->signer));
 		break;
 	case Tcert:
-		fmtprint(&fstr, " type=%d tag=%d alg=%d",
-			rp->sig->type, rp->sig->tag, rp->sig->alg);
-		break;
-	default:
+		if (rp->cert == nil)
+			fmtprint(&fstr, " type=<null> tag=<null> alg=<null>");
+		else
+			fmtprint(&fstr, " type=%d tag=%d alg=%d",
+				rp->cert->type, rp->cert->tag, rp->cert->alg);
 		break;
 	}
 out:
@@ -1232,6 +1317,31 @@ warning(char *fmt, ...)
 	syslog(1, "dns", dnserr);
 }
 
+/*
+ * based on libthread's threadsetname, but drags in less library code.
+ * actually just sets the arguments displayed.
+ */
+void
+procsetname(char *fmt, ...)
+{
+	int fd;
+	char *cmdname;
+	char buf[128];
+	va_list arg;
+
+	va_start(arg, fmt);
+	cmdname = vsmprint(fmt, arg);
+	va_end(arg);
+	if (cmdname == nil)
+		return;
+	snprint(buf, sizeof buf, "#p/%d/args", getpid());
+	if((fd = open(buf, OWRITE)) >= 0){
+		write(fd, cmdname, strlen(cmdname)+1);
+		close(fd);
+	}
+	free(cmdname);
+}
+
 /*
  *  create a slave process to handle a request to avoid one request blocking
  *  another
@@ -1239,14 +1349,14 @@ warning(char *fmt, ...)
 void
 slave(Request *req)
 {
-	static int slaveid;
 	int ppid;
+	static int slaveid;
 
 	if(req->isslave)
 		return;		/* we're already a slave process */
 
 	/*
-	 * These calls to putactivity cannot block. 
+	 * These calls to putactivity cannot block.
 	 * After getactivity(), the current process is counted
 	 * twice in dnvars.active (one will pass to the child).
 	 * If putactivity tries to wait for dnvars.active == 0,
@@ -1255,7 +1365,8 @@ slave(Request *req)
 
 	/* limit parallelism */
 	if(getactivity(req, 1) > Maxactive){
-		if(traceactivity) syslog(0, "dns", "[%d] too much activity", getpid());
+		if(traceactivity)
+			syslog(0, "dns", "[%d] too much activity", getpid());
 		putactivity(1);
 		return;
 	}
@@ -1266,8 +1377,11 @@ slave(Request *req)
 		putactivity(1);
 		break;
 	case 0:
-		if(traceactivity) syslog(0, "dns", "[%d] take activity from %d", ppid, getpid());
-		req->isslave = 1;
+		procsetname("request slave of pid %d", ppid);
+ 		if(traceactivity)
+			syslog(0, "dns", "[%d] take activity from %d",
+				getpid(), ppid);
+		req->isslave = 1;	/* why not `= getpid()'? */
 		break;
 	default:
 		longjmp(req->mret, 1);
@@ -1283,7 +1397,6 @@ dncheck(void *p, int dolock)
 	int i;
 	DN *dp;
 	RR *rp;
-	extern Pool *mainmem;
 
 	if(p != nil){
 		dp = p;
@@ -1326,13 +1439,12 @@ unique(RR *rp)
 
 	for(; rp; rp = rp->next){
 		l = &rp->next;
-		for(nrp = *l; nrp; nrp = *l){
+		for(nrp = *l; nrp; nrp = *l)
 			if(rrequiv(rp, nrp)){
 				*l = nrp->next;
 				rrfree(nrp);
 			} else
 				l = &nrp->next;
-		}
 	}
 }
 
@@ -1346,15 +1458,9 @@ subsume(char *higher, char *lower)
 
 	ln = strlen(lower);
 	hn = strlen(higher);
-	if(ln < hn)
-		return 0;
-
-	if(cistrcmp(lower + ln - hn, higher) != 0)
+	if (ln < hn || cistrcmp(lower + ln - hn, higher) != 0 ||
+	    ln > hn && hn != 0 && lower[ln - hn - 1] != '.')
 		return 0;
-
-	if(ln > hn && hn != 0 && lower[ln - hn - 1] != '.')
-		return 0;
-
 	return 1;
 }
 
@@ -1378,7 +1484,7 @@ randomize(RR *rp)
 		if(x->type != Ta && x->type != Tmx && x->type != Tns)
 			return rp;
 
-	base = rp; 
+	base = rp;
 
 	n = rand();
 	last = first = nil;
@@ -1418,13 +1524,10 @@ randomize(RR *rp)
 static int
 sencodefmt(Fmt *f)
 {
-	char *out;
-	char *buf;
-	int i, len;
-	int ilen;
-	int rv;
+	int i, len, ilen, rv;
+	char *out, *buf;
 	uchar *b;
-	char obuf[64];	// rsc optimization
+	char obuf[64];		/* rsc optimization */
 
 	if(!(f->flags&FmtPrec) || f->prec < 1)
 		goto error;
@@ -1471,7 +1574,7 @@ sencodefmt(Fmt *f)
 	} else
 		buf = obuf;
 
-	// convert
+	/* convert */
 	out = buf;
 	switch(f->r){
 	case '<':
@@ -1497,7 +1600,6 @@ sencodefmt(Fmt *f)
 
 error:
 	return fmtstrcpy(f, "<encodefmt>");
-
 }
 
 void*
@@ -1555,17 +1657,16 @@ void
 dnptr(uchar *net, uchar *mask, char *dom, int bytes, int ttl)
 {
 	int i, j;
+	char *p, *e;
+	char ptr[Domlen];
+	uchar ip[IPaddrlen], nnet[IPaddrlen];
 	DN *dp;
 	RR *rp, *nrp, *first, **l;
-	uchar ip[IPaddrlen];
-	uchar nnet[IPaddrlen];
-	char ptr[Domlen];
-	char *p, *e;
 
 	l = &first;
 	first = nil;
-	for(i = 0; i < HTLEN; i++){
-		for(dp = ht[i]; dp; dp = dp->next){
+	for(i = 0; i < HTLEN; i++)
+		for(dp = ht[i]; dp; dp = dp->next)
 			for(rp = dp->rr; rp; rp = rp->next){
 				if(rp->type != Ta || rp->negative)
 					continue;
@@ -1582,8 +1683,6 @@ dnptr(uchar *net, uchar *mask, char *dom, int bytes, int ttl)
 				*l = nrp;
 				l = &nrp->next;
 			}
-		}
-	}
 
 	for(rp = first; rp != nil; rp = nrp){
 		nrp = rp->next;
@@ -1624,7 +1723,6 @@ copyserverlist(Server *s)
 {
 	Server *ns;
 
-	
 	for(ns = nil; s != nil; s = s->next)
 		addserver(&ns, s->name);
 	return ns;

+ 30 - 28
sys/src/cmd/ndb/dnarea.c

@@ -5,8 +5,7 @@
 #include <ip.h>
 #include "dns.h"
 
-Area *owned;
-Area *delegated;
+Area *owned, *delegated;
 
 /*
  *  true if a name is in our area
@@ -25,18 +24,19 @@ inmyarea(char *name)
 			if(len == s->len || name[len - s->len - 1] == '.')
 				break;
 	}
-	if(s == 0)
-		return 0;
+	if(s == nil)
+		return nil;
 
+	/* name is in area `s' */
 	for(d = delegated; d; d = d->next){
 		if(d->len > len)
 			continue;
 		if(cistrcmp(d->soarr->owner->name, name + len - d->len) == 0)
 			if(len == d->len || name[len - d->len - 1] == '.')
-				return 0;
+				return nil; /* name is in a delegated subarea */
 	}
 
-	return s;
+	return s;	/* name is in area `s' and not in a delegated subarea */
 }
 
 /*
@@ -46,13 +46,18 @@ inmyarea(char *name)
 void
 addarea(DN *dp, RR *rp, Ndbtuple *t)
 {
-	Area **l, *s;
+	Area *s;
+	Area **l;
 
 	if(t->val[0])
 		l = &delegated;
 	else
 		l = &owned;
 
+	for (s = *l; s != nil; s = s->next)
+		if (strcmp(dp->name, s->soarr->owner->name) == 0)
+			return;		/* we've already got one */
+
 	/*
 	 *  The area contains a copy of the soa rr that created it.
 	 *  The owner of the the soa rr should stick around as long
@@ -67,7 +72,8 @@ addarea(DN *dp, RR *rp, Ndbtuple *t)
 	s->neednotify = 1;
 	s->needrefresh = 0;
 
-syslog(0, logfile, "new area %s", dp->name);
+	syslog(0, logfile, "new area %s %s", dp->name,
+		l == &delegated? "delegated": "owned");
 
 	s->next = *l;
 	*l = s;
@@ -81,6 +87,7 @@ freearea(Area **l)
 	while(s = *l){
 		*l = s->next;
 		rrfree(s->soarr);
+		memset(s, 0, sizeof *s);	/* cause trouble */
 		free(s);
 	}
 }
@@ -105,26 +112,21 @@ refresh_areas(Area *s)
 			continue;
 		}
 
-		switch(pid = fork()){
-		case -1:
-			break;
-		case 0:
-			execl(zonerefreshprogram, "zonerefresh", s->soarr->owner->name, nil);
-			exits(0);
-			break;
-		default:
-			for(;;){
-				w = wait();
-				if(w == nil)
-					break;
-				if(w->pid == pid){
-					if(w->msg == nil || *w->msg == 0)
-						s->needrefresh = 0;
-					free(w);
-					break;
-				}
-				free(w);
-			}
+		pid = fork();
+		if (pid == -1) {
+			sleep(1000);	/* don't try it again immediately */
+			continue;
+		}
+		if (pid == 0){
+			execl(zonerefreshprogram, "zonerefresh",
+				s->soarr->owner->name, nil);
+			exits("exec zonerefresh failed");
 		}
+		while ((w = wait()) != nil && w->pid != pid)
+			free(w);
+		if (w && w->pid == pid)
+			if(w->msg == nil || *w->msg == '\0')
+				s->needrefresh = 0;
+		free(w);
 	}
 }

+ 12 - 13
sys/src/cmd/ndb/dnnotify.c

@@ -39,16 +39,14 @@ syslog(0, logfile, "notification for %s", repp->qd->owner->name);
 syslog(0, logfile, "serial old %lud new %lud", a->soarr->soa->serial, repp->qd->soa->serial);
 
 	/* do nothing if it didn't change */
-	if(a->soarr->soa->serial== repp->qd->soa->serial)
-		return;
-
-	a->needrefresh = 1;
+	if(a->soarr->soa->serial != repp->qd->soa->serial)
+		a->needrefresh = 1;
 }
 
 static void
 ding(void*, char *msg)
 {
-	if(strstr(msg, "alarm"))
+	if(strstr(msg, "alarm") != nil)
 		noted(NCONT);
 	else
 		noted(NDFLT);
@@ -59,11 +57,10 @@ static void
 send_notify(char *slave, RR *soa, Request *req)
 {
 	int i, len, n, reqno, status, fd;
-	uchar obuf[Maxudp+OUdphdrsize];
-	uchar ibuf[Maxudp+OUdphdrsize];
+	char *err;
+	uchar ibuf[Maxudp+OUdphdrsize], obuf[Maxudp+OUdphdrsize];
 	RR *rp;
 	OUdphdr *up = (OUdphdr*)obuf;
-	char *err;
 	DNSmsg repmsg;
 
 	/* create the request */
@@ -71,9 +68,9 @@ send_notify(char *slave, RR *soa, Request *req)
 	n = mkreq(soa->owner, Cin, obuf, Fauth | Onotify, reqno);
 
 	/* get an address */
-	if(strcmp(ipattr(slave), "ip") == 0) {
+	if(strcmp(ipattr(slave), "ip") == 0)
 		parseip(up->raddr, slave);
-	} else {
+	else {
 		rp = dnresolve(slave, Cin, Ta, req, nil, 0, 1, 1, &status);
 		if(rp == nil)
 			return;
@@ -98,13 +95,13 @@ syslog(0, logfile, "sending %d byte notify to %s/%I.%d about %s", n, slave, up->
 		alarm(0);
 		if(len <= OUdphdrsize)
 			continue;
-		err = convM2DNS(&ibuf[OUdphdrsize], len, &repmsg);
+		memset(&repmsg, 0, sizeof repmsg);
+		err = convM2DNS(&ibuf[OUdphdrsize], len, &repmsg, nil);
 		if(err != nil)
 			continue;
 		if(repmsg.id == reqno && (repmsg.flags & Omask) == Onotify)
 			break;
 	}
-
 	close(fd);
 }
 
@@ -147,7 +144,9 @@ notifyproc(void)
 		return;
 	}
 
-	req.isslave = 1;	/* son't fork off subprocesses */
+	procsetname("notify slaves");
+	memset(&req, 0, sizeof req);
+	req.isslave = 1;	/* don't fork off subprocesses */
 
 	for(;;){
 		getactivity(&req, 0);

+ 114 - 62
sys/src/cmd/ndb/dnresolve.c

@@ -14,21 +14,50 @@ static RR*	dnresolve1(char*, int, int, Request*, int, int);
 
 char *LOG = "dns";
 
+/*
+ * reading /proc/pid/args yields either "name" or "name [display args]",
+ * so return only display args, if any.
+ */
+static char *
+procgetname(void)
+{
+	int fd, n;
+	char *lp, *rp;
+	char buf[256];
+
+	snprint(buf, sizeof buf, "#p/%d/args", getpid());
+	if((fd = open(buf, OREAD)) < 0)
+		return strdup("");
+	*buf = '\0';
+	n = read(fd, buf, sizeof buf-1);
+	close(fd);
+	if (n >= 0)
+		buf[n] = '\0';
+	if ((lp = strchr(buf, '[')) == nil ||
+	    (rp = strrchr(buf, ']')) == nil)
+		return strdup("");
+	*rp = '\0';
+	return strdup(lp+1);
+}
+
 /*
  *  lookup 'type' info for domain name 'name'.  If it doesn't exist, try
  *  looking it up as a canonical name.
  */
 RR*
-dnresolve(char *name, int class, int type, Request *req, RR **cn, int depth, int recurse, int rooted, int *status)
+dnresolve(char *name, int class, int type, Request *req, RR **cn, int depth,
+	int recurse, int rooted, int *status)
 {
 	RR *rp, *nrp, *drp;
 	DN *dp;
 	int loops;
+	char *procname;
 	char nname[Domlen];
 
 	if(status)
 		*status = 0;
 
+	procname = procgetname();
 	/*
 	 *  hack for systems that don't have resolve search
 	 *  lists.  Just look up the simple name in the database.
@@ -37,14 +66,18 @@ dnresolve(char *name, int class, int type, Request *req, RR **cn, int depth, int
 		rp = nil;
 		drp = domainlist(class);
 		for(nrp = drp; nrp != nil; nrp = nrp->next){
-			snprint(nname, sizeof(nname), "%s.%s", name, nrp->ptr->name);
-			rp = dnresolve(nname, class, type, req,cn, depth, recurse, rooted, status);
+			snprint(nname, sizeof nname, "%s.%s", name,
+				nrp->ptr->name);
+			rp = dnresolve(nname, class, type, req, cn, depth,
+				recurse, rooted, status);
 			rrfreelist(rrremneg(&rp));
 			if(rp != nil)
 				break;
 		}
 		if(drp != nil)
 			rrfree(drp);
+		procsetname(procname);
+		free(procname);
 		return rp;
 	}
 
@@ -52,12 +85,15 @@ dnresolve(char *name, int class, int type, Request *req, RR **cn, int depth, int
 	 *  try the name directly
 	 */
 	rp = dnresolve1(name, class, type, req, depth, recurse);
-	if(rp)
+	if(rp) {
+		procsetname(procname);
+		free(procname);
 		return randomize(rp);
+	}
 
 	/* try it as a canonical name if we weren't told the name didn't exist */
 	dp = dnlookup(name, class, 0);
-	if(type != Tptr && dp->nonexistent != Rname){
+	if(type != Tptr && dp->nonexistent != Rname)
 		for(loops=0; rp == nil && loops < 32; loops++){
 			rp = dnresolve1(name, class, Tcname, req, depth, recurse);
 			if(rp == nil)
@@ -68,37 +104,40 @@ dnresolve(char *name, int class, int type, Request *req, RR **cn, int depth, int
 				rp = nil;
 				break;
 			}
-	
+
 			name = rp->host->name;
 			if(cn)
 				rrcat(cn, rp);
 			else
 				rrfreelist(rp);
-	
+
 			rp = dnresolve1(name, class, type, req, depth, recurse);
 		}
-	}
 
 	/* distinction between not found and not good */
-	if(rp == 0 && status != 0 && dp->nonexistent != 0)
+	if(rp == nil && status != nil && dp->nonexistent != 0)
 		*status = dp->nonexistent;
 
+	procsetname(procname);
+	free(procname);
 	return randomize(rp);
 }
 
 static RR*
-dnresolve1(char *name, int class, int type, Request *req, int depth, int recurse)
+dnresolve1(char *name, int class, int type, Request *req, int depth,
+	int recurse)
 {
 	DN *dp, *nsdp;
 	RR *rp, *nsrp, *dbnsrp;
 	char *cp;
 
 	if(debug)
-		syslog(0, LOG, "[%d] dnresolve1 %s %d %d", getpid(), name, type, class);
+		syslog(0, LOG, "[%d] dnresolve1 %s %d %d",
+			getpid(), name, type, class);
 
 	/* only class Cin implemented so far */
 	if(class != Cin)
-		return 0;
+		return nil;
 
 	dp = dnlookup(name, class, 1);
 
@@ -106,24 +145,22 @@ dnresolve1(char *name, int class, int type, Request *req, int depth, int recurse
 	 *  Try the cache first
 	 */
 	rp = rrlookup(dp, type, OKneg);
-	if(rp){
+	if(rp)
 		if(rp->db){
 			/* unauthenticated db entries are hints */
 			if(rp->auth)
 				return rp;
-		} else {
+		} else
 			/* cached entry must still be valid */
-			if(rp->ttl > now){
+			if(rp->ttl > now)
 				/* but Tall entries are special */
 				if(type != Tall || rp->query == Tall)
 					return rp;
-			}
-		}
-	}
+
 	rrfreelist(rp);
 
 	/*
-	 * try the cache for a canonical name. if found punt 
+	 * try the cache for a canonical name. if found punt
 	 * since we'll find it during the canonical name search
 	 * in dnresolve().
 	 */
@@ -131,7 +168,7 @@ dnresolve1(char *name, int class, int type, Request *req, int depth, int recurse
 		rp = rrlookup(dp, Tcname, NOneg);
 		rrfreelist(rp);
 		if(rp)
-			return 0;
+			return nil;
 	}
 
 	/*
@@ -221,7 +258,8 @@ dnresolve1(char *name, int class, int type, Request *req, int depth, int recurse
 }
 
 /*
- *  walk a domain name one element to the right.  return a pointer to that element.
+ *  walk a domain name one element to the right.
+ *  return a pointer to that element.
  *  in other words, return a pointer to the parent domain name.
  */
 char*
@@ -249,8 +287,7 @@ int
 udpport(void)
 {
 	int fd, ctl;
-	char ds[64];
-	char adir[64];
+	char ds[64], adir[64];
 
 	/* get a udp port */
 	snprint(ds, sizeof(ds), "%s/udp!*!0", mntpt);
@@ -272,11 +309,8 @@ udpport(void)
 	snprint(ds, sizeof(ds), "%s/data", adir);
 	fd = open(ds, ORDWR);
 	close(ctl);
-	if(fd < 0){
+	if(fd < 0)
 		warning("can't open udp port: %r");
-		return -1;
-	}
-
 	return fd;
 }
 
@@ -300,7 +334,7 @@ mkreq(DN *dp, int type, uchar *buf, int flags, ushort reqno)
 	m.qd->type = type;
 	len = convDNS2M(&m, &buf[OUdphdrsize], Maxudp);
 	if(len < 0)
-		abort(); /* "can't convert" */;
+		abort();	/* "can't convert" */
 	rrfree(m.qd);
 	return len;
 }
@@ -323,10 +357,12 @@ freeanswers(DNSmsg *mp)
 	rrfreelist(mp->an);
 	rrfreelist(mp->ns);
 	rrfreelist(mp->ar);
+	mp->qd = mp->an = mp->ns = mp->ar = nil;
 }
 
 /*
- *  read replies to a request.  ignore any of the wrong type.  wait at most 5 seconds.
+ *  read replies to a request.  ignore any of the wrong type.
+ *  wait at most 5 seconds.
  */
 static int
 readreply(int fd, DN *dp, int type, ushort req,
@@ -351,12 +387,12 @@ readreply(int fd, DN *dp, int type, ushort req,
 		len -= OUdphdrsize;
 		if(len < 0)
 			return -1;	/* timed out */
-		
+
 		/* convert into internal format  */
 		memset(mp, 0, sizeof(*mp));
-		err = convM2DNS(&ibuf[OUdphdrsize], len, mp);
+		err = convM2DNS(&ibuf[OUdphdrsize], len, mp, nil);
 		if(err){
-			syslog(0, LOG, "input err %s: %I", err, ibuf);
+			syslog(0, LOG, "input err: %s: %I", err, ibuf);
 			continue;
 		}
 		if(debug)
@@ -373,13 +409,13 @@ readreply(int fd, DN *dp, int type, ushort req,
 			continue;
 		}
 		if(mp->qd->owner != dp){
-			syslog(0, LOG, "%d: owner %s instead of %s: %I", reqp->id,
-				mp->qd->owner->name, dp->name, ibuf);
+			syslog(0, LOG, "%d: owner %s instead of %s: %I",
+				reqp->id, mp->qd->owner->name, dp->name, ibuf);
 			continue;
 		}
 		if(mp->qd->type != type){
-			syslog(0, LOG, "%d: type %d instead of %d: %I", reqp->id,
-				mp->qd->type, type, ibuf);
+			syslog(0, LOG, "%d: type %d instead of %d: %I",
+				reqp->id, mp->qd->type, type, ibuf);
 			continue;
 		}
 
@@ -406,10 +442,9 @@ contains(RR *rp1, RR *rp2)
 			if(trp1->owner == trp2->owner)
 				break;
 		}
-		if(trp1 == 0)
+		if(trp1 == nil)
 			return 0;
 	}
-
 	return 1;
 }
 
@@ -431,14 +466,12 @@ int
 ipisbm(uchar *ip)
 {
 	if(isv4(ip)){
-		if(ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)
+		if (ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0 ||
+		    ipcmp(ip, IPv4bcast) == 0)
 			return 4;
-		if(ipcmp(ip, IPv4bcast) == 0)
-			return 4;
-	} else {
+	} else
 		if(ip[0] == 0xff)
 			return 6;
-	}
 	return 0;
 }
 
@@ -481,7 +514,7 @@ serveraddrs(RR *nsrp, Dest *dest, int nd, int depth, Request *reqp)
 	 *  server addresses, try resolving one via the network.
 	 *  Mark any we try to resolve so we don't try a second time.
 	 */
-	if(arp == 0){
+	if(arp == 0)
 		for(rp = nsrp; rp; rp = rp->next){
 			if(rp->marker)
 				continue;
@@ -493,12 +526,12 @@ serveraddrs(RR *nsrp, Dest *dest, int nd, int depth, Request *reqp)
 			if(subsume(rp->owner->name, rp->host->name))
 				continue;
 
-			arp = dnresolve(rp->host->name, Cin, Ta, reqp, 0, depth+1, Recurse, 1, 0);
+			arp = dnresolve(rp->host->name, Cin, Ta, reqp, 0,
+				depth+1, Recurse, 1, 0);
 			rrfreelist(rrremneg(&arp));
 			if(arp)
 				break;
 		}
-	}
 
 	/* use any addresses that we found */
 	for(trp = arp; trp; trp = trp->next){
@@ -527,14 +560,14 @@ cacheneg(DN *dp, int type, int rcode, RR *soarr)
 	DN *soaowner;
 	ulong ttl;
 
-	/* no cache time specified, don' make anything up */
+	/* no cache time specified, don't make anything up */
 	if(soarr != nil){
 		if(soarr->next != nil){
 			rrfreelist(soarr->next);
 			soarr->next = nil;
 		}
 		soaowner = soarr->owner;
-	} else 
+	} else
 		soaowner = nil;
 
 	/* the attach can cause soarr to be freed so mine it now */
@@ -560,16 +593,18 @@ cacheneg(DN *dp, int type, int rcode, RR *soarr)
  *  name server, recurse.
  */
 static int
-netquery1(int fd, DN *dp, int type, RR *nsrp, Request *reqp, int depth, uchar *ibuf, uchar *obuf)
+netquery1(int fd, DN *dp, int type, RR *nsrp, Request *reqp, int depth,
+	uchar *ibuf, uchar *obuf)
 {
 	int ndest, j, len, replywaits, rv;
+	ulong endtime;
 	ushort req;
-	RR *tp, *soarr;
-	Dest *p, *l, *np;
+	char buf[12];
 	DN *ndp;
-	Dest dest[Maxdest];
 	DNSmsg m;
-	ulong endtime;
+	Dest *p, *l, *np;
+	Dest dest[Maxdest];
+	RR *tp, *soarr;
 
 	/* pack request into a message */
 	req = rand();
@@ -613,7 +648,10 @@ netquery1(int fd, DN *dp, int type, RR *nsrp, Request *reqp, int depth, uchar *i
 			if((1<<p->nx) > ndest)
 				continue;
 
-			memmove(obuf, p->a, sizeof(p->a));
+			procsetname("req slave: query to %I/%s %s %s",
+				obuf, p->s->name, dp->name,
+				rrname(type, buf, sizeof buf));
+			memmove(obuf, p->a, sizeof p->a);
 			if(debug)
 				logsend(reqp->id, depth, obuf, p->s->name,
 					dp->name, type);
@@ -630,6 +668,9 @@ netquery1(int fd, DN *dp, int type, RR *nsrp, Request *reqp, int depth, uchar *i
 			endtime = reqp->aborttime;
 
 		for(replywaits = 0; replywaits < ndest; replywaits++){
+			procsetname("req slave: reading reply from %I for %s %s",
+				obuf, dp->name, rrname(type, buf, sizeof buf));
+			memset(&m, 0, sizeof m);
 			if(readreply(fd, dp, type, req, ibuf, &m, endtime, reqp) < 0)
 				break;		/* timed out */
 
@@ -673,7 +714,7 @@ netquery1(int fd, DN *dp, int type, RR *nsrp, Request *reqp, int depth, uchar *i
 
 			/* incorporate answers */
 			if(m.an)
-				rrattach(m.an, (m.flags & Fauth) ? 1 : 0);
+				rrattach(m.an, (m.flags & Fauth) != 0);
 			if(m.ar)
 				rrattach(m.ar, 0);
 			if(m.ns){
@@ -700,7 +741,8 @@ netquery1(int fd, DN *dp, int type, RR *nsrp, Request *reqp, int depth, uchar *i
 				 *  cache any negative responses, free soarr
 				 */
 				if((m.flags & Fauth) && m.an == nil)
-					cacheneg(dp, type, (m.flags & Rmask), soarr);
+					cacheneg(dp, type, (m.flags & Rmask),
+						soarr);
 				else
 					rrfreelist(soarr);
 				return 1;
@@ -714,7 +756,12 @@ netquery1(int fd, DN *dp, int type, RR *nsrp, Request *reqp, int depth, uchar *i
 			if(m.ns){
 				tp = rrlookup(ndp, Tns, NOneg);
 				if(!contains(nsrp, tp)){
-					rv = netquery(dp, type, tp, reqp, depth+1);
+					procsetname(
+					 "req slave: recursive query for %s %s",
+						dp->name,
+						rrname(type, buf, sizeof buf));
+					rv = netquery(dp, type, tp, reqp,
+						depth + 1);
 					rrfreelist(tp);
 					return rv;
 				} else
@@ -723,7 +770,7 @@ netquery1(int fd, DN *dp, int type, RR *nsrp, Request *reqp, int depth, uchar *i
 		}
 	}
 
-	/* if all servers returned failure, propogate it */
+	/* if all servers returned failure, propagate it */
 	dp->nonexistent = Rserver;
 	for(p = dest; p < l; p++)
 		if(p->code != Rserver)
@@ -735,24 +782,29 @@ netquery1(int fd, DN *dp, int type, RR *nsrp, Request *reqp, int depth, uchar *i
 static int
 netquery(DN *dp, int type, RR *nsrp, Request *reqp, int depth)
 {
-	uchar *obuf;
-	uchar *ibuf;
-	RR *rp;
 	int fd, rv;
+//	int pid;
+	uchar *obuf, *ibuf;
+	RR *rp;
 
-	if(depth > 12)
+	if(depth > 12)			/* in a recursive loop? */
 		return 0;
 
 	/* use alloced buffers rather than ones from the stack */
 	ibuf = emalloc(Maxudpin+OUdphdrsize);
 	obuf = emalloc(Maxudp+OUdphdrsize);
 
+//	pid = getpid();
 	slave(reqp);
+	/* parent process longjmped to req->mret; we're the child slave */
 
 	/* prepare server RR's for incremental lookup */
 	for(rp = nsrp; rp; rp = rp->next)
 		rp->marker = 0;
 
+//	if (pid != getpid())
+//		syslog(0, LOG, "[%d] netquery: forked child for %s",
+//			getpid(), dp->name);
 	fd = udpport();
 	if(fd < 0)
 		rv = 0;

+ 107 - 107
sys/src/cmd/ndb/dns.c

@@ -11,12 +11,13 @@
 enum
 {
 	Maxrequest=		1024,
-	Ncache=			8,
 	Maxpath=		128,
 	Maxreply=		512,
 	Maxrrr=			16,
 	Maxfdata=		8192,
 
+	Defmaxage=		60*60,		/* 1 hour */
+
 	Qdir=			0,
 	Qdns=			1,
 };
@@ -42,9 +43,9 @@ struct Mfile
 	ushort		nrr;		/* number of rr's */
 };
 
-//
-//  active local requests
-//
+/*
+ *  active local requests
+ */
 struct Job
 {
 	Job	*next;
@@ -60,50 +61,51 @@ struct {
 	Mfile	*inuse;		/* active mfile's */
 } mfalloc;
 
-int	mfd[2];
-int	debug;
-int traceactivity;
 int	cachedb;
+int	debug;
+uchar	ipaddr[IPaddrlen];	/* my ip address */
+int	maxage = Defmaxage;
+int	mfd[2];
+int	needrefresh;
 ulong	now;
+int	resolver;
+int	sendnotifies;
 int	testing;
 char	*trace;
-int	needrefresh;
-int	resolver;
-uchar	ipaddr[IPaddrlen];	/* my ip address */
-int	maxage;
+int	traceactivity;
 char	*zonerefreshprogram;
-int	sendnotifies;
 
-void	rversion(Job*);
+char	*LOG;
+char	*dbfile;
+char	*logfile = "dns";
+char	mntpt[Maxpath];
+
+int	fillreply(Mfile*, int);
+void	freejob(Job*);
+void	io(void);
+void	mountinit(char*, char*);
+Job*	newjob(void);
+void	rattach(Job*, Mfile*);
 void	rauth(Job*);
+void	rclunk(Job*, Mfile*);
+void	rcreate(Job*, Mfile*);
 void	rflush(Job*);
-void	rattach(Job*, Mfile*);
-char*	rwalk(Job*, Mfile*);
 void	ropen(Job*, Mfile*);
-void	rcreate(Job*, Mfile*);
 void	rread(Job*, Mfile*);
-void	rwrite(Job*, Mfile*, Request*);
-void	rclunk(Job*, Mfile*);
 void	rremove(Job*, Mfile*);
 void	rstat(Job*, Mfile*);
+void	rversion(Job*);
+char*	rwalk(Job*, Mfile*);
+void	rwrite(Job*, Mfile*, Request*);
 void	rwstat(Job*, Mfile*);
 void	sendmsg(Job*, char*);
-void	mountinit(char*, char*);
-void	io(void);
-int	fillreply(Mfile*, int);
-Job*	newjob(void);
-void	freejob(Job*);
 void	setext(char*, int, char*);
 
-char	*logfile = "dns";
-char	*dbfile;
-char	mntpt[Maxpath];
-char	*LOG;
-
 void
 usage(void)
 {
-	fprint(2, "usage: %s [-rRs] [-f ndb-file] [-x netmtpt]\n", argv0);
+	fprint(2, "usage: %s [-nrRst] [-a maxage] [-f ndb-file] [-N target] "
+		"[-x netmtpt] [-z refreshprog]\n", argv0);
 	exits("usage");
 }
 
@@ -111,30 +113,29 @@ void
 main(int argc, char *argv[])
 {
 	int	serve;
-	char	servefile[Maxpath];
-	char	ext[Maxpath];
-	char	*p;
+	char	servefile[Maxpath], ext[Maxpath];
 
 	serve = 0;
 	setnetmtpt(mntpt, sizeof(mntpt), nil);
 	ext[0] = 0;
 	ARGBEGIN{
+	case 'a':
+		maxage = atol(EARGF(usage()));
+		break;
 	case 'd':
 		debug = 1;
 		traceactivity = 1;
 		break;
 	case 'f':
-		p = ARGF();
-		if(p == nil)
-			usage();
-		dbfile = p;
+		dbfile = EARGF(usage());
 		break;
-	case 'x':
-		p = ARGF();
-		if(p == nil)
-			usage();
-		setnetmtpt(mntpt, sizeof(mntpt), p);
-		setext(ext, sizeof(ext), mntpt);
+	case 'n':
+		sendnotifies = 1;
+		break;
+	case 'N':
+		target = atol(EARGF(usage()));
+		if (target < 100)
+			target = 100;
 		break;
 	case 'r':
 		resolver = 1;
@@ -146,26 +147,23 @@ main(int argc, char *argv[])
 		serve = 1;	/* serve network */
 		cachedb = 1;
 		break;
-	case 'a':
-		p = ARGF();
-		if(p == nil)
-			usage();
-		maxage = atoi(p);
-		break;
 	case 't':
 		testing = 1;
 		break;
-	case 'z':
-		zonerefreshprogram = ARGF();
+	case 'x':
+		setnetmtpt(mntpt, sizeof mntpt, EARGF(usage()));
+		setext(ext, sizeof ext, mntpt);
 		break;
-	case 'n':
-		sendnotifies = 1;
+	case 'z':
+		zonerefreshprogram = EARGF(usage());
 		break;
 	}ARGEND
 	USED(argc);
 	USED(argv);
 
-if(testing) mainmem->flags |= POOL_NOREUSE;
+	if(testing)
+		mainmem->flags |= POOL_NOREUSE;
+//		mainmem->flags |= POOL_ANTAGONISM | POOL_PARANOIA;
 	rfork(RFREND|RFNOTEG);
 
 	/* start syslog before we fork */
@@ -174,11 +172,11 @@ if(testing) mainmem->flags |= POOL_NOREUSE;
 	if(myipaddr(ipaddr, mntpt) < 0)
 		sysfatal("can't read my ip address");
 
-	syslog(0, logfile, "starting dns on %I", ipaddr);
+	syslog(0, logfile, "starting dns on %I's %s", ipaddr, mntpt);
 
 	opendatabase();
 
-	snprint(servefile, sizeof(servefile), "#s/dns%s", ext);
+	snprint(servefile, sizeof servefile, "#s/dns%s", ext);
 	unmount(servefile, mntpt);
 	remove(servefile);
 	mountinit(servefile, mntpt);
@@ -198,7 +196,7 @@ if(testing) mainmem->flags |= POOL_NOREUSE;
 }
 
 /*
- *  if a mount point is specified, set the cs extention to be the mount point
+ *  if a mount point is specified, set the cs extension to be the mount point
  *  with '_'s replacing '/'s
  */
 void
@@ -230,6 +228,7 @@ mountinit(char *service, char *mntpt)
 	switch(rfork(RFFDG|RFPROC|RFNAMEG)){
 	case 0:
 		close(p[1]);
+		procsetname("main");
 		break;
 	case -1:
 		abort(); /* "fork failed\n" */;
@@ -263,14 +262,13 @@ newfid(int fid, int needunused)
 	Mfile *mf;
 
 	lock(&mfalloc);
-	for(mf = mfalloc.inuse; mf != nil; mf = mf->next){
+	for(mf = mfalloc.inuse; mf != nil; mf = mf->next)
 		if(mf->fid == fid){
 			unlock(&mfalloc);
 			if(needunused)
 				return nil;
 			return mf;
 		}
-	}
 	mf = emalloc(sizeof(*mf));
 	if(mf == nil)
 		sysfatal("out of memory");
@@ -287,16 +285,18 @@ freefid(Mfile *mf)
 	Mfile **l;
 
 	lock(&mfalloc);
-	for(l = &mfalloc.inuse; *l != nil; l = &(*l)->next){
+	for(l = &mfalloc.inuse; *l != nil; l = &(*l)->next)
 		if(*l == mf){
 			*l = mf->next;
-			if(mf->user)
+			if(mf->user) {
+				memset(mf->user, 0, sizeof *mf->user); /* cause trouble */
 				free(mf->user);
+			}
+			memset(mf, 0, sizeof *mf);	/* cause trouble */
 			free(mf);
 			unlock(&mfalloc);
 			return;
 		}
-	}
 	sysfatal("freeing unused fid");
 }
 
@@ -336,13 +336,13 @@ freejob(Job *job)
 	Job **l;
 
 	lock(&joblock);
-	for(l = &joblist; *l; l = &(*l)->next){
+	for(l = &joblist; *l; l = &(*l)->next)
 		if((*l) == job){
 			*l = job->next;
+			memset(job, 0, sizeof *job);	/* cause trouble */
 			free(job);
 			break;
 		}
-	}
 	unlock(&joblock);
 }
 
@@ -352,12 +352,11 @@ flushjob(int tag)
 	Job *job;
 
 	lock(&joblock);
-	for(job = joblist; job; job = job->next){
+	for(job = joblist; job; job = job->next)
 		if(job->request.tag == tag && job->request.type != Tflush){
 			job->flushed = 1;
 			break;
 		}
-	}
 	unlock(&joblock);
 }
 
@@ -370,6 +369,7 @@ io(void)
 	Request req;
 	Job *job;
 
+	memset(&req, 0, sizeof req);
 	/*
 	 *  a slave process is sometimes forked to wait for replies from other
 	 *  servers.  The master process returns immediately via a longjmp
@@ -377,6 +377,7 @@ io(void)
 	 */
 	if(setjmp(req.mret))
 		putactivity(0);
+	procsetname("main 9p reading loop");
 	req.isslave = 0;
 	for(;;){
 		n = read9pmsg(mfd[0], mdata, sizeof mdata);
@@ -384,6 +385,7 @@ io(void)
 			syslog(0, logfile, "error reading mntpt: %r");
 			exits(0);
 		}
+
 		job = newjob();
 		if(convM2S(mdata, n, &job->request) != n){
 			freejob(job);
@@ -394,11 +396,12 @@ io(void)
 			syslog(0, logfile, "%F", &job->request);
 
 		getactivity(&req, 0);
-		req.aborttime = now + 60;	/* don't spend more than 60 seconds */
+		req.aborttime = now + Maxreqtm;
 
 		switch(job->request.type){
 		default:
-			syslog(1, logfile, "unknown request type %d", job->request.type);
+			syslog(1, logfile, "unknown request type %d",
+				job->request.type);
 			break;
 		case Tversion:
 			rversion(job);
@@ -442,7 +445,7 @@ io(void)
 		}
 
 		freejob(job);
-	
+
 		/*
 		 *  slave processes die after replying
 		 */
@@ -450,7 +453,7 @@ io(void)
 			putactivity(0);
 			_exits(0);
 		}
-	
+
 		putactivity(0);
 	}
 }
@@ -502,16 +505,15 @@ rattach(Job *job, Mfile *mf)
 char*
 rwalk(Job *job, Mfile *mf)
 {
+	int i, nelems;
 	char *err;
 	char **elems;
-	int nelems;
-	int i;
 	Mfile *nmf;
 	Qid qid;
 
 	err = 0;
 	nmf = nil;
-	elems = job->request.wname;
+	elems  = job->request.wname;
 	nelems = job->request.nwname;
 	job->reply.nwqid = 0;
 
@@ -534,10 +536,11 @@ rwalk(Job *job, Mfile *mf)
 				err = "not a directory";
 				break;
 			}
-			if(strcmp(elems[i], "..") == 0 || strcmp(elems[i], ".") == 0){
+			if (strcmp(elems[i], "..") == 0 ||
+			    strcmp(elems[i], ".") == 0){
 				qid.type = QTDIR;
 				qid.path = Qdir;
-    Found:
+Found:
 				job->reply.wqid[i] = qid;
 				job->reply.nwqid++;
 				continue;
@@ -552,7 +555,7 @@ rwalk(Job *job, Mfile *mf)
 		}
 	}
 
-    send:
+send:
 	if(nmf != nil && (err!=nil || job->reply.nwqid<nelems))
 		freefid(nmf);
 	if(err == nil)
@@ -589,11 +592,11 @@ void
 rread(Job *job, Mfile *mf)
 {
 	int i, n, cnt;
-	long off;
-	Dir dir;
-	uchar buf[Maxfdata];
-	char *err;
 	long clock;
+	vlong off;
+	char *err;
+	uchar buf[Maxfdata];
+	Dir dir;
 
 	n = 0;
 	err = 0;
@@ -608,11 +611,8 @@ rread(Job *job, Mfile *mf)
 			dir.qid.path = Qdns;
 			dir.mode = 0666;
 			dir.length = 0;
-			dir.uid = mf->user;
-			dir.gid = mf->user;
-			dir.muid = mf->user;
-			dir.atime = clock;	/* wrong */
-			dir.mtime = clock;	/* wrong */
+			dir.uid = dir.gid = dir.muid = mf->user;
+			dir.atime = dir.mtime = clock;	/* wrong */
 			n = convD2M(&dir, buf, sizeof buf);
 		}
 		job->reply.data = (char*)buf;
@@ -620,15 +620,14 @@ rread(Job *job, Mfile *mf)
 		for(i = 1; i <= mf->nrr; i++)
 			if(mf->rr[i] > off)
 				break;
-		if(i > mf->nrr)
-			goto send;
-		if(off + cnt > mf->rr[i])
-			n = mf->rr[i] - off;
-		else
-			n = cnt;
-		job->reply.data = mf->reply + off;
+		if(i <= mf->nrr) {
+			if(off + cnt > mf->rr[i])
+				n = mf->rr[i] - off;
+			else
+				n = cnt;
+			job->reply.data = mf->reply + off;
+		}
 	}
-send:
 	job->reply.count = n;
 	sendmsg(job, err);
 }
@@ -636,11 +635,10 @@ send:
 void
 rwrite(Job *job, Mfile *mf, Request *req)
 {
-	int cnt, rooted, status;
+	int cnt, rooted, status, wantsav;
 	long n;
 	char *err, *p, *atype;
 	RR *rp, *tp, *neg;
-	int wantsav;
 
 	err = 0;
 	cnt = job->request.count;
@@ -659,16 +657,20 @@ rwrite(Job *job, Mfile *mf, Request *req)
 	/*
 	 *  special commands
 	 */
-	if(strncmp(job->request.data, "debug", 5)==0 && job->request.data[5] == 0){
+	if(strncmp(job->request.data, "debug", 5)==0 &&
+	    job->request.data[5] == 0){
 		debug ^= 1;
 		goto send;
-	} else if(strncmp(job->request.data, "dump", 4)==0 && job->request.data[4] == 0){
+	} else if(strncmp(job->request.data, "dump", 4)==0 &&
+	    job->request.data[4] == 0){
 		dndump("/lib/ndb/dnsdump");
 		goto send;
-	} else if(strncmp(job->request.data, "refresh", 7)==0 && job->request.data[7] == 0){
+	} else if(strncmp(job->request.data, "refresh", 7)==0 &&
+	    job->request.data[7] == 0){
 		needrefresh = 1;
 		goto send;
-	} else if(strncmp(job->request.data, "poolcheck", 9)==0 && job->request.data[9] == 0){
+	} else if(strncmp(job->request.data, "poolcheck", 9)==0 &&
+	    job->request.data[9] == 0){
 		poolcheck(mainmem);
 		goto send;
 	}
@@ -760,8 +762,7 @@ rwrite(Job *job, Mfile *mf, Request *req)
 		unlock(&joblock);
 		rrfreelist(rp);
 	}
-
-    send:
+send:
 	dncheck(0, 1);
 	job->reply.count = cnt;
 	sendmsg(job, err);
@@ -796,9 +797,7 @@ rstat(Job *job, Mfile *mf)
 	}
 	dir.qid = mf->qid;
 	dir.length = 0;
-	dir.uid = mf->user;
-	dir.gid = mf->user;
-	dir.muid = mf->user;
+	dir.uid = dir.gid = dir.muid = mf->user;
 	dir.atime = dir.mtime = time(0);
 	job->reply.nstat = convD2M(&dir, buf, sizeof buf);
 	job->reply.stat = buf;
@@ -823,13 +822,13 @@ sendmsg(Job *job, char *err)
 		job->reply.type = Rerror;
 		snprint(ename, sizeof(ename), "dns: %s", err);
 		job->reply.ename = ename;
-	}else{
+	}else
 		job->reply.type = job->request.type+1;
-	}
 	job->reply.tag = job->request.tag;
 	n = convS2M(&job->reply, mdata, sizeof mdata);
 	if(n == 0){
-		syslog(1, logfile, "sendmsg convS2M of %F returns 0", &job->reply);
+		syslog(1, logfile, "sendmsg convS2M of %F returns 0",
+			&job->reply);
 		abort();
 	}
 	lock(&joblock);
@@ -872,7 +871,8 @@ logsend(int id, int subid, uchar *addr, char *sname, char *rname, int type)
 	char buf[12];
 
 	syslog(0, LOG, "[%d] %d.%d: sending to %I/%s %s %s",
-		getpid(), id, subid, addr, sname, rname, rrname(type, buf, sizeof buf));
+		getpid(), id, subid, addr, sname, rname,
+		rrname(type, buf, sizeof buf));
 }
 
 RR*

+ 135 - 133
sys/src/cmd/ndb/dns.h

@@ -3,7 +3,7 @@ typedef struct Ndbtuple Ndbtuple;
 enum
 {
 	/* RR types; see: http://www.iana.org/assignments/dns-parameters */
-	Ta=			1,
+	Ta=		1,
 	Tns=		2,
 	Tmd=		3,
 	Tmf=		4,
@@ -63,7 +63,7 @@ enum
 	Ttsig=	250,	/* transaction signature */
 	Tixfr=	251,	/* incremental zone transfer */
 	Taxfr=	252,	/* zone transfer */
-	Tmailb=	253,	/* { Tmb, Tmg, Tmr } */	
+	Tmailb=	253,	/* { Tmb, Tmg, Tmr } */
 	Tmaila= 254,	/* obsolete */
 	Tall=	255,	/* all records */
 
@@ -142,19 +142,22 @@ enum
 
 	/* parallelism */
 	Maxactive=	32,
+
+	Maxreqtm=	60,	/* max. seconds to process a request */
 };
 
+typedef struct Area	Area;
+typedef struct Block	Block;
+typedef struct Cert	Cert;
 typedef struct DN	DN;
 typedef struct DNSmsg	DNSmsg;
-typedef struct RR	RR;
-typedef struct SOA	SOA;
-typedef struct Area	Area;
-typedef struct Request	Request;
 typedef struct Key	Key;
-typedef struct Cert	Cert;
-typedef struct Sig	Sig;
 typedef struct Null	Null;
+typedef struct RR	RR;
+typedef struct Request	Request;
+typedef struct SOA	SOA;
 typedef struct Server	Server;
+typedef struct Sig	Sig;
 typedef struct Txt	Txt;
 
 /*
@@ -188,39 +191,37 @@ struct DN
 /*
  *  security info
  */
+struct Block
+{
+	int	dlen;
+	uchar	*data;
+};
 struct Key
 {
 	int	flags;
 	int	proto;
 	int	alg;
-	int	dlen;
-	uchar	*data;
+	Block;
 };
 struct Cert
 {
 	int	type;
 	int	tag;
 	int	alg;
-	int	dlen;
-	uchar	*data;
+	Block;
 };
 struct Sig
 {
-	int	type;
-	int	alg;
+	Cert;
 	int	labels;
 	ulong	ttl;
 	ulong	exp;
 	ulong	incep;
-	int	tag;
 	DN	*signer;
-	int	dlen;
-	uchar	*data;
 };
 struct Null
 {
-	int	dlen;
-	uchar	*data;
+	Block;
 };
 
 /*
@@ -240,28 +241,28 @@ struct RR
 	RR	*next;
 	ulong	magic;
 	DN	*owner;		/* domain that owns this resource record */
-	uchar	negative;	/* this is a cached negative response */
 	uintptr	pc;
 	ulong	ttl;		/* time to live to be passed on */
 	ulong	expire;		/* time this entry expires locally */
-	ushort	type;		/* RR type */
-	ushort	query;		/* query tyis is in response to */
-	uchar	auth;		/* authoritative */
-	uchar	db;		/* from database */
-	uchar	cached;		/* rr in cache */
 	ulong	marker;		/* used locally when scanning rrlists */
-	union {
+	ushort	type;		/* RR type */
+	ushort	query;		/* query type is in response to */
+	uchar	auth;		/* flag: authoritative */
+	uchar	db;		/* flag: from database */
+	uchar	cached;		/* flag: rr in cache */
+	uchar	negative;	/* flag: this is a cached negative response */
+
+	union {			/* discriminated how? negative & type? */
 		DN	*negsoaowner;	/* soa for cached negative response */
 		DN	*host;	/* hostname - soa, cname, mb, md, mf, mx, ns */
 		DN	*cpu;	/* cpu type - hinfo */
 		DN	*mb;	/* mailbox - mg, minfo */
-		DN	*ip;	/* ip addrss - a */
+		DN	*ip;	/* ip address - a */
 		DN	*rp;	/* rp arg - rp */
-		int	cruftlen;
 		ulong	arg0;
 	};
-	union {
-		int	negrcode;	/* response code for cached negative response */
+	union {			/* discriminated how? negative & type? */
+		int	negrcode; /* response code for cached negative response */
 		DN	*rmb;	/* responsible maibox - minfo, soa, rp */
 		DN	*ptr;	/* pointer to domain name - ptr */
 		DN	*os;	/* operating system - hinfo */
@@ -269,7 +270,7 @@ struct RR
 		ulong	local;	/* ns served from local database - ns */
 		ulong	arg1;
 	};
-	union {
+	union {			/* discriminated by type */
 		SOA	*soa;	/* soa timers - soa */
 		Key	*key;
 		Cert	*cert;
@@ -289,15 +290,16 @@ struct Server
 };
 
 /*
- *  timers for a start of authenticated record
+ *  timers for a start of authenticated record.  all ulongs are in seconds.
  */
 struct SOA
 {
-	ulong	serial;		/* zone serial # (sec) - soa */
-	ulong	refresh;	/* zone refresh interval (sec) - soa */
-	ulong	retry;		/* zone retry interval (sec) - soa */
-	ulong	expire;		/* time to expiration (sec) - soa */
-	ulong	minttl;		/* minimum time to live for any entry (sec) - soa */
+	ulong	serial;		/* zone serial # */
+	ulong	refresh;	/* zone refresh interval */
+	ulong	retry;		/* zone retry interval */
+	ulong	expire;		/* time to expiration */
+	ulong	minttl;		/* min. time to live for any entry */
+
 	Server	*slaves;	/* slave servers */
 };
 
@@ -323,12 +325,12 @@ struct DNSmsg
  */
 struct Area
 {
-	Area		*next;
+	Area	*next;
 
-	int		len;		/* strlen(area->soarr->owner->name) */
-	RR		*soarr;		/* soa defining this area */
-	int		neednotify;
-	int		needrefresh;
+	int	len;		/* strlen(area->soarr->owner->name) */
+	RR	*soarr;		/* soa defining this area */
+	int	neednotify;
+	int	needrefresh;
 };
 
 enum
@@ -339,114 +341,114 @@ enum
 	OKneg,
 };
 
+extern int	cachedb;
+extern char	*dbfile;
+extern int	debug;
+extern Area	*delegated;
+extern char	*logfile;
+extern int	maxage;		/* age of oldest entry in cache (secs) */
+extern char	mntpt[];
+extern int	needrefresh;
+extern int	norecursion;
+extern ulong	now;		/* time base */
+extern Area	*owned;
+extern int	resolver;
+extern int	sendnotifies;
+extern ulong	target;
+extern int	testing;	/* test cache whenever removing a DN */
+extern char	*trace;
+extern int	traceactivity;
+extern char	*zonerefreshprogram;
+
+#pragma	varargck	type	"R"	RR*
+#pragma	varargck	type	"Q"	RR*
+
+
 /* dn.c */
 extern char	*rrtname[];
 extern char	*rname[];
+extern unsigned	nrname;
 extern char	*opname[];
-extern void	db2cache(int);
-extern void	dninit(void);
-extern DN*	dnlookup(char*, int, int);
-extern void	dnage(DN*);
-extern void	dnageall(int);
-extern void	dnagedb(void);
-extern void	dnauthdb(void);
-extern void	dnget(void);
-extern void	dnpurge(void);
-extern void	dnput(void);
-extern Area*	inmyarea(char*);
-extern void	rrattach(RR*, int);
-extern RR*	rralloc(int);
-extern void	rrfree(RR*);
-extern void	rrfreelist(RR*);
-extern RR*	rrlookup(DN*, int, int);
-extern RR*	rrcat(RR**, RR*);
-extern RR**	rrcopy(RR*, RR**);
-extern RR*	rrremneg(RR**);
-extern RR*	rrremtype(RR**, int);
-extern int	rrfmt(Fmt*);
-extern int	rravfmt(Fmt*);
-extern int	rrsupported(int);
-extern int	rrtype(char*);
-extern char*	rrname(int, char*, int);
-extern int	tsame(int, int);
-extern void	dndump(char*);
-extern int	getactivity(Request*, int);
-extern void	putactivity(int);
-extern void	abort(); /* char*, ... */;
-extern void	warning(char*, ...);
-extern void	slave(Request*);
-extern void	dncheck(void*, int);
-extern void	unique(RR*);
-extern int	subsume(char*, char*);
-extern RR*	randomize(RR*);
-extern void*	emalloc(int);
-extern char*	estrdup(char*);
-extern void	dnptr(uchar*, uchar*, char*, int, int);
-extern void	addserver(Server**, char*);
-extern Server*	copyserverlist(Server*);
-extern void	freeserverlist(Server*);
+
+void	db2cache(int);
+void	dninit(void);
+DN*	dnlookup(char*, int, int);
+void	dnage(DN*);
+void	dnageall(int);
+void	dnagedb(void);
+void	dnauthdb(void);
+void	dnget(void);
+void	dnpurge(void);
+void	dnput(void);
+Area*	inmyarea(char*);
+void	rrattach(RR*, int);
+RR*	rralloc(int);
+void	rrfree(RR*);
+void	rrfreelist(RR*);
+RR*	rrlookup(DN*, int, int);
+RR*	rrcat(RR**, RR*);
+RR**	rrcopy(RR*, RR**);
+RR*	rrremneg(RR**);
+RR*	rrremtype(RR**, int);
+int	rrfmt(Fmt*);
+int	rravfmt(Fmt*);
+int	rrsupported(int);
+int	rrtype(char*);
+char*	rrname(int, char*, int);
+int	tsame(int, int);
+void	dndump(char*);
+int	getactivity(Request*, int);
+void	putactivity(int);
+void	abort(); /* char*, ... */;
+void	warning(char*, ...);
+void	slave(Request*);
+void	dncheck(void*, int);
+void	unique(RR*);
+int	subsume(char*, char*);
+RR*	randomize(RR*);
+void*	emalloc(int);
+char*	estrdup(char*);
+void	dnptr(uchar*, uchar*, char*, int, int);
+void	addserver(Server**, char*);
+Server*	copyserverlist(Server*);
+void	freeserverlist(Server*);
 
 /* dnarea.c */
-extern void	refresh_areas(Area*);
-extern void	freearea(Area**);
-extern void	addarea(DN *dp, RR *rp, Ndbtuple *t);
+void	refresh_areas(Area*);
+void	freearea(Area**);
+void	addarea(DN *dp, RR *rp, Ndbtuple *t);
 
 /* dblookup.c */
-extern RR*	dblookup(char*, int, int, int, int);
-extern RR*	dbinaddr(DN*, int);
-extern int	baddelegation(RR*, RR*, uchar*);
-extern RR*	dnsservers(int);
-extern RR*	domainlist(int);
-extern int	opendatabase(void);
+RR*	dblookup(char*, int, int, int, int);
+RR*	dbinaddr(DN*, int);
+int	baddelegation(RR*, RR*, uchar*);
+RR*	dnsservers(int);
+RR*	domainlist(int);
+int	opendatabase(void);
 
 /* dns.c */
-extern char*	walkup(char*);
-extern RR*	getdnsservers(int);
-extern void	logreply(int, uchar*, DNSmsg*);
-extern void	logsend(int, int, uchar*, char*, char*, int);
+char*	walkup(char*);
+RR*	getdnsservers(int);
+void	logreply(int, uchar*, DNSmsg*);
+void	logsend(int, int, uchar*, char*, char*, int);
+void	procsetname(char *fmt, ...);
 
 /* dnresolve.c */
-extern RR*	dnresolve(char*, int, int, Request*, RR**, int, int, int, int*);
-extern int	udpport(void);
-extern int	mkreq(DN *dp, int type, uchar *buf, int flags, ushort reqno);
+RR*	dnresolve(char*, int, int, Request*, RR**, int, int, int, int*);
+int	udpport(void);
+int	mkreq(DN *dp, int type, uchar *buf, int flags, ushort reqno);
 
 /* dnserver.c */
-extern void	dnserver(DNSmsg*, DNSmsg*, Request*);
-extern void	dnudpserver(char*);
-extern void	dntcpserver(char*);
+void	dnserver(DNSmsg*, DNSmsg*, Request*, uchar *, int);
+void	dnudpserver(char*);
+void	dntcpserver(char*);
 
 /* dnnotify.c */
-extern void	dnnotify(DNSmsg*, DNSmsg*, Request*);
-extern void	notifyproc(void);
+void	dnnotify(DNSmsg*, DNSmsg*, Request*);
+void	notifyproc(void);
 
 /* convDNS2M.c */
-extern int	convDNS2M(DNSmsg*, uchar*, int);
+int	convDNS2M(DNSmsg*, uchar*, int);
 
 /* convM2DNS.c */
-extern char*	convM2DNS(uchar*, int, DNSmsg*);
-
-/* malloc.c */
-extern void	mallocsanity(void*);
-extern void	lasthist(void*, int, ulong);
-
-extern int debug;
-extern int traceactivity;
-extern char	*trace;
-extern int	testing;	/* test cache whenever removing a DN */
-extern int	cachedb;
-extern int	needrefresh;
-extern char	*dbfile;
-extern char	mntpt[];
-extern char	*logfile;
-extern int	resolver;
-extern int	norecursion;
-extern int	maxage;		/* age of oldest entry in cache (secs) */
-extern char	*zonerefreshprogram;
-extern int	sendnotifies;
-extern ulong	now;		/* time base */
-extern Area	*owned;
-extern Area	*delegated;
-
-#pragma	varargck	type	"R"	RR*
-#pragma	varargck	type	"Q"	RR*
-
+char*	convM2DNS(uchar*, int, DNSmsg*, int*);

+ 60 - 60
sys/src/cmd/ndb/dnsdebug.c

@@ -6,40 +6,43 @@
 #include <ndb.h>
 #include "dns.h"
 
-enum
-{
+enum {
 	Maxrequest=		128,
-	Ncache=			8,
 	Maxpath=		128,
-	Maxreply=		512,
-	Maxrrr=			16,
 };
 
 static char *servername;
 static RR *serverrr;
 static RR *serveraddrs;
 
-int	debug;
 int	cachedb;
-ulong	now;
-int	testing;
-int traceactivity;
-char	*trace;
-int	needrefresh;
-int	resolver;
+char	*dbfile;
+int	debug;
 uchar	ipaddr[IPaddrlen];	/* my ip address */
-int	maxage;
 char	*logfile = "dns";
-char	*dbfile;
+int	maxage  = 60;
 char	mntpt[Maxpath];
+int	needrefresh;
+ulong	now;
+int	resolver;
+int	testing;
+char	*trace;
+int	traceactivity;
 char	*zonerefreshprogram;
 
-int prettyrrfmt(Fmt*);
-void preloadserveraddrs(void);
-void squirrelserveraddrs(void);
-int setserver(char*);
-void doquery(char*, char*);
-void docmd(int, char**);
+void	docmd(int, char**);
+void	doquery(char*, char*);
+void	preloadserveraddrs(void);
+int	prettyrrfmt(Fmt*);
+int	setserver(char*);
+void	squirrelserveraddrs(void);
+
+void
+usage(void)
+{
+	fprint(2, "%s: [-rx] [-f db-file]\n", argv0);
+	exits("usage");
+}
 
 void
 main(int argc, char *argv[])
@@ -52,6 +55,9 @@ main(int argc, char *argv[])
 	strcpy(mntpt, "/net");
 
 	ARGBEGIN{
+	case 'f':
+		dbfile = EARGF(usage());
+		break;
 	case 'r':
 		resolver = 1;
 		break;
@@ -59,9 +65,8 @@ main(int argc, char *argv[])
 		dbfile = "/lib/ndb/external";
 		strcpy(mntpt, "/net.alt");
 		break;
-	case 'f':
-		dbfile = ARGF();
-		break;
+	default:
+		usage();
 	}ARGEND
 
 	now = time(0);
@@ -85,14 +90,10 @@ main(int argc, char *argv[])
 	for(print("> "); p = Brdline(&in, '\n'); print("> ")){
 		p[Blinelen(&in)-1] = 0;
 		n = tokenize(p, f, 3);
-		if(n<1)
-			continue;
-
-		/* flush the cache */
-		dnpurge();
-
-		docmd(n, f);
-
+		if(n>=1) {
+			dnpurge();		/* flush the cache */
+			docmd(n, f);
+		}
 	}
 	exits(0);
 }
@@ -138,7 +139,7 @@ prettyrrfmt(Fmt *f)
 	p = buf;
 	e = buf + sizeof(buf);
 	p = seprint(p, e, "%-32.32s %-15.15s %-5.5s", rp->owner->name,
-		longtime(rp->db ? rp->ttl : (rp->ttl-now)),
+		longtime(rp->db? rp->ttl: (rp->ttl - now)),
 		rrname(rp->type, buf, sizeof buf));
 
 	if(rp->negative){
@@ -155,28 +156,31 @@ prettyrrfmt(Fmt *f)
 	case Tmd:
 	case Tmf:
 	case Tns:
-		seprint(p, e, "\t%s", rp->host->name);
+		seprint(p, e, "\t%s", (rp->host? rp->host->name: ""));
 		break;
 	case Tmg:
 	case Tmr:
-		seprint(p, e, "\t%s", rp->mb->name);
+		seprint(p, e, "\t%s", (rp->mb? rp->mb->name: ""));
 		break;
 	case Tminfo:
-		seprint(p, e, "\t%s %s", rp->mb->name, rp->rmb->name);
+		seprint(p, e, "\t%s %s", (rp->mb? rp->mb->name: ""),
+			(rp->rmb? rp->rmb->name: ""));
 		break;
 	case Tmx:
-		seprint(p, e, "\t%lud %s", rp->pref, rp->host->name);
+		seprint(p, e, "\t%lud %s", rp->pref,
+			(rp->host? rp->host->name: ""));
 		break;
 	case Ta:
 	case Taaaa:
-		seprint(p, e, "\t%s", rp->ip->name);
+		seprint(p, e, "\t%s", (rp->ip? rp->ip->name: ""));
 		break;
 	case Tptr:
-		seprint(p, e, "\t%s", rp->ptr->name);
+		seprint(p, e, "\t%s", (rp->ptr? rp->ptr->name: ""));
 		break;
 	case Tsoa:
-		seprint(p, e, "\t%s %s %lud %lud %lud %lud %lud", rp->host->name,
-			rp->rmb->name, rp->soa->serial, rp->soa->refresh, rp->soa->retry,
+		seprint(p, e, "\t%s %s %lud %lud %lud %lud %lud",
+			rp->host->name, rp->rmb->name, rp->soa->serial,
+			rp->soa->refresh, rp->soa->retry,
 			rp->soa->expire, rp->soa->minttl);
 		break;
 	case Tnull:
@@ -196,15 +200,14 @@ prettyrrfmt(Fmt *f)
 		break;
 	case Tsig:
 		seprint(p, e, "\t%d %d %d %lud %lud %lud %d %s",
-			rp->sig->type, rp->sig->alg, rp->sig->labels, rp->sig->ttl,
-			rp->sig->exp, rp->sig->incep, rp->sig->tag, rp->sig->signer->name);
+			rp->sig->type, rp->sig->alg, rp->sig->labels,
+			rp->sig->ttl, rp->sig->exp, rp->sig->incep,
+			rp->sig->tag, rp->sig->signer->name);
 		break;
 	case Tcert:
 		seprint(p, e, "\t%d %d %d",
 			rp->sig->type, rp->sig->tag, rp->sig->alg);
 		break;
-	default:
-		break;
 	}
 out:
 	return fmtstrcpy(f, buf);
@@ -224,8 +227,7 @@ void
 logreply(int id, uchar *addr, DNSmsg *mp)
 {
 	RR *rp;
-	char buf[12];
-	char resp[32];
+	char buf[12], resp[32];
 
 	switch(mp->flags & Rmask){
 	case Rok:
@@ -259,7 +261,8 @@ logreply(int id, uchar *addr, DNSmsg *mp)
 		mp->flags & (Fauth|Rname) == (Fauth|Rname) ?
 		" nx" : "");
 	for(rp = mp->qd; rp != nil; rp = rp->next)
-		print("\tQ:    %s %s\n", rp->owner->name, rrname(rp->type, buf, sizeof buf));
+		print("\tQ:    %s %s\n", rp->owner->name,
+			rrname(rp->type, buf, sizeof buf));
 	logsection("Ans:  ", mp->an);
 	logsection("Auth: ", mp->ns);
 	logsection("Hint: ", mp->ar);
@@ -312,7 +315,7 @@ squirrelserveraddrs(void)
 			continue;
 		}
 		req.isslave = 1;
-		req.aborttime = now + 60;	/* don't spend more than 60 seconds */
+		req.aborttime = now + Maxreqtm*2;	/* be patient */
 		*l = dnresolve(rp->host->name, Cin, Ta, &req, 0, 0, Recurse, 0, 0);
 		while(*l != nil)
 			l = &(*l)->next;
@@ -325,7 +328,7 @@ void
 preloadserveraddrs(void)
 {
 	RR *rp, **l, *first;
-	
+
 	l = &first;
 	for(rp = serveraddrs; rp != nil; rp = rp->next){
 		rrcopy(rp, l);
@@ -348,32 +351,29 @@ setserver(char *server)
 	if(serveraddrs == nil){
 		print("can't resolve %s\n", servername);
 		resolver = 0;
-	} else {
+	} else
 		resolver = 1;
-	}
 	return resolver ? 0 : -1;
 }
 
 void
 doquery(char *name, char *tstr)
 {
-	Request req;
-	RR *rr, *rp;
-	int len, type;
+	int len, type, rooted;
 	char *p, *np;
-	int rooted;
 	char buf[1024];
+	RR *rr, *rp;
+	Request req;
 
 	if(resolver)
 		preloadserveraddrs();
 
 	/* default to an "ip" request if alpha, "ptr" if numeric */
-	if(tstr == nil || *tstr == 0) {
+	if(tstr == nil || *tstr == 0)
 		if(strcmp(ipattr(name), "ip") == 0)
 			tstr = "ptr";
 		else
 			tstr = "ip";
-	}
 
 	/* if name end in '.', remove it */
 	len = strlen(name);
@@ -414,9 +414,10 @@ doquery(char *name, char *tstr)
 		return;
 	}
 
+	memset(&req, 0, sizeof req);
 	getactivity(&req, 0);
 	req.isslave = 1;
-	req.aborttime = now + 60;	/* don't spend more than 60 seconds */
+	req.aborttime = now + Maxreqtm*2;	/* be patient */
 	rr = dnresolve(buf, Cin, type, &req, 0, 0, Recurse, rooted, 0);
 	if(rr){
 		print("----------------------------\n");
@@ -435,8 +436,7 @@ docmd(int n, char **f)
 	int tmpsrv;
 	char *name, *type;
 
-	name = nil;
-	type = nil;
+	name = type = nil;
 	tmpsrv = 0;
 
 	if(*f[0] == '@') {

+ 35 - 20
sys/src/cmd/ndb/dnserver.c

@@ -15,18 +15,18 @@ int	norecursion;		/* don't allow recursive requests */
  *  answer a dns request
  */
 void
-dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req)
+dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req, uchar *srcip, int errflags)
 {
-	RR *tp, *neg;
-	char *cp;
+	int recursionflag;
+	char *cp, *errmsg;
+	char tname[32];
 	DN *nsdp, *dp;
 	Area *myarea;
-	char tname[32];
-	int recursionflag;
+	RR *tp, *neg;
 
 	dncheck(nil, 1);
 
-	recursionflag = norecursion?0:Fcanrec;
+	recursionflag = norecursion? 0: Fcanrec;
 	memset(repp, 0, sizeof(*repp));
 	repp->id = reqp->id;
 	repp->flags = Fresp | recursionflag | Oquery;
@@ -37,14 +37,26 @@ dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req)
 	tp->next = 0;
 	repp->qd = tp;
 
+	if (errflags) {
+		errmsg = "";
+		if (errflags >= 0 && errflags < nrname)
+			errmsg = rname[errflags];
+		syslog(0, logfile, "server: error flags 0%o (%s), req from %I",
+			errflags, errmsg, srcip);
+		/* provide feedback to clients who send us trash */
+		repp->flags = (errflags&Rmask) | Fresp | Fcanrec | Oquery;
+		return;
+	}
 	if(!rrsupported(repp->qd->type)){
-		syslog(0, logfile, "server: request %s", rrname(repp->qd->type, tname, sizeof tname));
+		syslog(0, logfile, "server: unsupported request %s from %I",
+			rrname(repp->qd->type, tname, sizeof tname), srcip);
 		repp->flags = Runimplimented | Fresp | Fcanrec | Oquery;
 		return;
 	}
 
 	if(repp->qd->owner->class != Cin){
-		syslog(0, logfile, "server: class %d", repp->qd->owner->class);
+		syslog(0, logfile, "server: unsupported class %d from %I",
+			repp->qd->owner->class, srcip);
 		repp->flags = Runimplimented | Fresp | Fcanrec | Oquery;
 		return;
 	}
@@ -52,17 +64,20 @@ dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req)
 	myarea = inmyarea(repp->qd->owner->name);
 	if(myarea != nil) {
 		if(repp->qd->type == Tixfr || repp->qd->type == Taxfr){
-			syslog(0, logfile, "server: request %s", rrname(repp->qd->type, tname, sizeof tname));
-			repp->flags = Runimplimented | Fresp | recursionflag | Oquery;
+			syslog(0, logfile,
+				"server: unsupported xfr request %s from %I",
+				rrname(repp->qd->type, tname, sizeof tname),
+				srcip);
+			repp->flags = Runimplimented | Fresp | recursionflag |
+				Oquery;
 			return;
 		}
-	} else {
+	} else
 		if(norecursion) {
 			/* we don't recurse and we're not authoritative */
 			repp->flags = Rok | Fresp | Oquery;
 			return;
 		}
-	}
 
 	/*
 	 *  get the answer if we can
@@ -84,7 +99,7 @@ dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req)
 				repp->flags |= dp->nonexistent|Fauth;
 	}
 
-	if(myarea == nil){
+	if(myarea == nil)
 		/*
 		 *  add name server if we know
 		 */
@@ -92,7 +107,7 @@ dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req)
 			nsdp = dnlookup(cp, repp->qd->owner->class, 0);
 			if(nsdp == 0)
 				continue;
-	
+
 			repp->ns = rrlookup(nsdp, Tns, OKneg);
 			if(repp->ns){
 				/* don't pass on anything we know is wrong */
@@ -102,12 +117,11 @@ dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req)
 				}
 				break;
 			}
-	
+
 			repp->ns = dblookup(cp, repp->qd->owner->class, Tns, 0, 0);
 			if(repp->ns)
 				break;
 		}
-	}
 
 	/*
 	 *  add ip addresses as hints
@@ -120,18 +134,19 @@ dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req)
 	}
 
 	/*
-	 *  add an soa to the authority section to help client with negative caching
+	 *  add an soa to the authority section to help client
+	 *  with negative caching
 	 */
-	if(repp->an == nil){
+	if(repp->an == nil)
 		if(myarea != nil){
 			rrcopy(myarea->soarr, &tp);
 			rrcat(&repp->ns, tp);
 		} else if(neg != nil) {
 			if(neg->negsoaowner != nil)
-				rrcat(&repp->ns, rrlookup(neg->negsoaowner, Tsoa, NOneg));
+				rrcat(&repp->ns, rrlookup(neg->negsoaowner,
+					Tsoa, NOneg));
 			repp->flags |= neg->negrcode;
 		}
-	}
 
 	/*
 	 *  get rid of duplicates

+ 43 - 35
sys/src/cmd/ndb/dnstcp.c

@@ -19,7 +19,7 @@ int 	resolver;
 char	mntpt[Maxpath];
 char	*caller = "";
 ulong	now;
-int	maxage;
+int	maxage = 60;
 uchar	ipaddr[IPaddrlen];	/* my ip address */
 char	*LOG;
 char	*zonerefreshprogram;
@@ -40,18 +40,14 @@ usage(void)
 void
 main(int argc, char *argv[])
 {
-	int len;
+	int len, errflags;
 	Request req;
 	DNSmsg reqmsg, repmsg;
 	uchar buf[512];
 	char tname[32];
-	char *err;
-	char *ext = "";
+	char *err, *ext = "";
 
 	ARGBEGIN{
-	case 'R':
-		norecursion = 1;
-		break;
 	case 'd':
 		debug++;
 		break;
@@ -61,6 +57,9 @@ main(int argc, char *argv[])
 	case 'r':
 		resolver = 1;
 		break;
+	case 'R':
+		norecursion = 1;
+		break;
 	case 'x':
 		ext = EARGF(usage());
 		break;
@@ -84,52 +83,58 @@ main(int argc, char *argv[])
 
 	db2cache(1);
 
+	memset(&req, 0, sizeof req);
 	setjmp(req.mret);
 	req.isslave = 0;
+	procsetname("main loop");
 
 	/* loop on requests */
 	for(;; putactivity(0)){
 		now = time(0);
-		memset(&repmsg, 0, sizeof(repmsg));
+		memset(&repmsg, 0, sizeof repmsg);
 		alarm(10*60*1000);
-		len = readmsg(0, buf, sizeof(buf));
+		len = readmsg(0, buf, sizeof buf);
 		alarm(0);
 		if(len <= 0)
 			break;
 		getactivity(&req, 0);
 		req.aborttime = now + 15*Min;
-		err = convM2DNS(buf, len, &reqmsg);
+		errflags = 0;
+		memset(&reqmsg, 0, sizeof reqmsg);
+		err = convM2DNS(buf, len, &reqmsg, &errflags);
 		if(err){
-			syslog(0, logfile, "server: input error: %s from %I", err, buf);
-			break;
-		}
-		if(reqmsg.qdcount < 1){
-			syslog(0, logfile, "server: no questions from %I", buf);
+			/* first bytes in buf are source IP addr */
+			syslog(0, logfile, "server: input error: %s from %I",
+				err, buf);
 			break;
 		}
-		if(reqmsg.flags & Fresp){
-			syslog(0, logfile, "server: reply not request from %I", buf);
-			break;
-		}
-		if((reqmsg.flags & Omask) != Oquery){
-			syslog(0, logfile, "server: op %d from %I", reqmsg.flags & Omask, buf);
-			break;
-		}
-
+		if (errflags == 0)
+			if(reqmsg.qdcount < 1){
+				syslog(0, logfile,
+					"server: no questions from %I", buf);
+				break;
+			} else if(reqmsg.flags & Fresp){
+				syslog(0, logfile,
+				    "server: reply not request from %I", buf);
+				break;
+			} else if((reqmsg.flags & Omask) != Oquery){
+				syslog(0, logfile, "server: op %d from %I",
+					reqmsg.flags & Omask, buf);
+				break;
+			}
 		if(debug)
 			syslog(0, logfile, "[%d] %d: serve (%s) %d %s %s",
-				getpid(),
-				req.id, caller,
-				reqmsg.id,
-				reqmsg.qd->owner->name,
+				getpid(), req.id, caller,
+				reqmsg.id, reqmsg.qd->owner->name,
 				rrname(reqmsg.qd->type, tname, sizeof tname));
 
 		/* loop through each question */
-		while(reqmsg.qd){
-			if(reqmsg.qd->type == Taxfr){
+		while(reqmsg.qd) {
+			memset(&repmsg, 0, sizeof repmsg);
+			if(reqmsg.qd->type == Taxfr)
 				dnzone(&reqmsg, &repmsg, &req);
-			} else {
-				dnserver(&reqmsg, &repmsg, &req);
+			else {
+				dnserver(&reqmsg, &repmsg, &req, buf, errflags);
 				reply(1, &repmsg, &req);
 				rrfreelist(repmsg.qd);
 				rrfreelist(repmsg.an);
@@ -137,7 +142,6 @@ main(int argc, char *argv[])
 				rrfreelist(repmsg.ar);
 			}
 		}
-
 		rrfreelist(reqmsg.qd);
 		rrfreelist(reqmsg.an);
 		rrfreelist(reqmsg.ns);
@@ -192,12 +196,13 @@ reply(int fd, DNSmsg *rep, Request *req)
 
 	len = convDNS2M(rep, buf+2, sizeof(buf) - 2);
 	if(len <= 0)
-		abort(); /* "dnserver: converting reply" */;
+		abort();	/* "dnserver: converting reply" */
 	buf[0] = len>>8;
 	buf[1] = len;
 	rv = write(fd, buf, len+2);
 	if(rv != len+2){
-		syslog(0, logfile, "[%d] sending reply: %d instead of %d", getpid(), rv, len+2);
+		syslog(0, logfile, "[%d] sending reply: %d instead of %d",
+			getpid(), rv, len+2);
 		exits(0);
 	}
 }
@@ -262,6 +267,7 @@ dnzone(DNSmsg *reqp, DNSmsg *repp, Request *req)
 	if(repp->an == 0)
 		goto out;
 	rrfreelist(repp->an);
+	repp->an = nil;
 
 	nlen = strlen(dp->name);
 
@@ -295,8 +301,10 @@ dnzone(DNSmsg *reqp, DNSmsg *repp, Request *req)
 	repp->an = rrlookup(dp, Tsoa, NOneg);
 	reply(1, repp, req);
 	rrfreelist(repp->an);
+	repp->an = nil;
 out:
 	rrfree(repp->qd);
+	repp->qd = nil;
 }
 
 static void

+ 47 - 38
sys/src/cmd/ndb/dnudpserver.c

@@ -40,10 +40,10 @@ clientrxmit(DNSmsg *req, uchar *buf)
 	OUdphdr *uh;
 
 	uh = (OUdphdr *)buf;
-	empty = 0;
+	empty = nil;
 	for(p = inprog; p < &inprog[Maxactive]; p++){
 		if(p->inuse == 0){
-			if(empty == 0)
+			if(empty == nil)
 				empty = p;
 			continue;
 		}
@@ -51,10 +51,10 @@ clientrxmit(DNSmsg *req, uchar *buf)
 		if(req->qd->owner == p->owner)
 		if(req->qd->type == p->type)
 		if(memcmp(uh, &p->uh, OUdphdrsize) == 0)
-			return 0;
+			return nil;
 	}
-	if(empty == 0)
-		return 0;	/* shouldn't happen - see slave() and definition of Maxactive */
+	if(empty == nil)
+		return nil; /* shouldn't happen: see slave() & Maxactive def'n */
 
 	empty->id = req->id;
 	empty->owner = req->qd->owner;
@@ -70,13 +70,13 @@ clientrxmit(DNSmsg *req, uchar *buf)
 void
 dnudpserver(char *mntpt)
 {
-	int fd, len, op;
-	Request req;
-	DNSmsg reqmsg, repmsg;
+	int fd, len, op, errflags;
 	uchar buf[OUdphdrsize + Maxudp + 1024];
 	char *err;
-	Inprogress *p;
 	char tname[32];
+	Request req;
+	DNSmsg reqmsg, repmsg;
+	Inprogress *p;
 	OUdphdr *uh;
 
 	/* fork sharing text, data, and bss with parent */
@@ -92,56 +92,67 @@ dnudpserver(char *mntpt)
 	fd = -1;
 	notify(ding);
 restart:
+	procsetname("udp server announcing");
 	if(fd >= 0)
 		close(fd);
 	while((fd = udpannounce(mntpt)) < 0)
 		sleep(5000);
+	memset(&req, 0, sizeof req);
 	if(setjmp(req.mret))
 		putactivity(0);
 	req.isslave = 0;
+	procsetname("udp server loop");
 
 	/* loop on requests */
 	for(;; putactivity(0)){
-		memset(&repmsg, 0, sizeof(repmsg));
-		memset(&reqmsg, 0, sizeof(reqmsg));
+		memset(&repmsg, 0, sizeof repmsg);
+		memset(&reqmsg, 0, sizeof reqmsg);
 		alarm(60*1000);
-		len = read(fd, buf, sizeof(buf));
+		len = read(fd, buf, sizeof buf);
 		alarm(0);
 		if(len <= OUdphdrsize)
 			goto restart;
 		uh = (OUdphdr*)buf;
 		len -= OUdphdrsize;
+		// syslog(0, logfile, "read received UDP from %I to %I",
+		//	((OUdphdr*)buf)->raddr, ((OUdphdr*)buf)->laddr);
 		getactivity(&req, 0);
-		req.aborttime = now + 30;	/* don't spend more than 30 seconds */
-		err = convM2DNS(&buf[OUdphdrsize], len, &reqmsg);
+		req.aborttime = now + Maxreqtm;
+		errflags = 0;
+		err = convM2DNS(&buf[OUdphdrsize], len, &reqmsg, &errflags);
 		if(err){
-			syslog(0, logfile, "server: input error: %s from %I", err, buf);
+			/* first bytes in buf are source IP addr */
+			syslog(0, logfile, "server: input error: %s from %I",
+				err, buf);
 			continue;
 		}
-		if(reqmsg.qdcount < 1){
-			syslog(0, logfile, "server: no questions from %I", buf);
-			goto freereq;
-		}
-		if(reqmsg.flags & Fresp){
-			syslog(0, logfile, "server: reply not request from %I", buf);
-			goto freereq;
-		}
+		if (errflags == 0)
+			if(reqmsg.qdcount < 1){
+				syslog(0, logfile,
+					"server: no questions from %I", buf);
+				goto freereq;
+			} else if(reqmsg.flags & Fresp){
+				syslog(0, logfile,
+				    "server: reply not request from %I", buf);
+				goto freereq;
+			}
 		op = reqmsg.flags & Omask;
 		if(op != Oquery && op != Onotify){
-			syslog(0, logfile, "server: op %d from %I", reqmsg.flags & Omask, buf);
+			syslog(0, logfile, "server: op %d from %I",
+				reqmsg.flags & Omask, buf);
 			goto freereq;
 		}
 
 		if(debug || (trace && subsume(trace, reqmsg.qd->owner->name))){
 			syslog(0, logfile, "%d: serve (%I/%d) %d %s %s",
-				req.id, buf, ((uh->rport[0])<<8)+uh->rport[1],
+				req.id, buf, uh->rport[0]<<8 | uh->rport[1],
 				reqmsg.id,
 				reqmsg.qd->owner->name,
 				rrname(reqmsg.qd->type, tname, sizeof tname));
 		}
 
 		p = clientrxmit(&reqmsg, buf);
-		if(p == 0){
+		if(p == nil){
 			if(debug)
 				syslog(0, logfile, "%d: duplicate", req.id);
 			goto freereq;
@@ -149,10 +160,10 @@ restart:
 
 		/* loop through each question */
 		while(reqmsg.qd){
-			memset(&repmsg, 0, sizeof(repmsg));
+			memset(&repmsg, 0, sizeof repmsg);
 			switch(op){
 			case Oquery:
-				dnserver(&reqmsg, &repmsg, &req);
+				dnserver(&reqmsg, &repmsg, &req, buf, errflags);
 				break;
 			case Onotify:
 				dnnotify(&reqmsg, &repmsg, &req);
@@ -166,7 +177,6 @@ restart:
 		}
 
 		p->inuse = 0;
-
 freereq:
 		rrfreelist(reqmsg.qd);
 		rrfreelist(reqmsg.an);
@@ -177,7 +187,6 @@ freereq:
 			putactivity(0);
 			_exits(0);
 		}
-
 	}
 }
 
@@ -190,10 +199,9 @@ static char *ohmsg = "oldheaders";
 static int
 udpannounce(char *mntpt)
 {
-	static int whined;
 	int data, ctl;
-	char dir[64];
-	char datafile[64+6];
+	char dir[64], datafile[64+6];
+	static int whined;
 
 	/* get a udp port */
 	sprint(datafile, "%s/udp!*!dns", mntpt);
@@ -207,7 +215,7 @@ udpannounce(char *mntpt)
 
 	/* turn on header style interface */
 	if(write(ctl, hmsg, strlen(hmsg)) , 0)
-		abort(); /* hmsg */;
+		abort();			/* hmsg */
 	write(ctl, ohmsg, strlen(ohmsg));
 	data = open(datafile, ORDWR);
 	if(data < 0){
@@ -230,14 +238,15 @@ reply(int fd, uchar *buf, DNSmsg *rep, Request *reqp)
 
 	if(debug || (trace && subsume(trace, rep->qd->owner->name)))
 		syslog(0, logfile, "%d: reply (%I/%d) %d %s %s an %R ns %R ar %R",
-			reqp->id, buf, ((buf[4])<<8)+buf[5],
+			reqp->id, buf, buf[4]<<8 | buf[5],
 			rep->id, rep->qd->owner->name,
-			rrname(rep->qd->type, tname, sizeof tname), rep->an, rep->ns, rep->ar);
+			rrname(rep->qd->type, tname, sizeof tname),
+			rep->an, rep->ns, rep->ar);
 
 	len = convDNS2M(rep, &buf[OUdphdrsize], Maxudp);
 	if(len <= 0){
-		syslog(0, logfile, "error converting reply: %s %d", rep->qd->owner->name,
-			rep->qd->type);
+		syslog(0, logfile, "error converting reply: %s %d",
+			rep->qd->owner->name, rep->qd->type);
 		for(rp = rep->an; rp; rp = rp->next)
 			syslog(0, logfile, "an %R", rp);
 		for(rp = rep->ns; rp; rp = rp->next)

+ 4 - 0
sys/src/cmd/ndb/mkfile

@@ -57,6 +57,8 @@ push: $O.dns $O.dnsdebug $O.dnstcp
 	unmount /n/divisadero
 
 cs.safeinstall: $O.cs
+	if(test -e $BIN/ooocs)
+		mv $BIN/ooocs $BIN/oooocs
 	if(test -e $BIN/oocs)
 		mv $BIN/oocs $BIN/ooocs
 	if(test -e $BIN/ocs)
@@ -65,6 +67,8 @@ cs.safeinstall: $O.cs
 	cp $O.cs $BIN/cs
 
 dns.safeinstall: $O.dns
+	if(test -e $BIN/ooodns)
+		mv $BIN/ooodns $BIN/oooodns
 	if(test -e $BIN/oodns)
 		mv $BIN/oodns $BIN/ooodns
 	if(test -e $BIN/odns)

+ 0 - 26
sys/src/cmd/ndb/time.c

@@ -1,26 +0,0 @@
-#include <u.h>
-#include <libc.h>
-
-static Lock tlock;
-
-long
-time(long *tp)
-{
-	char b[20];
-	static int f = -1;
-	long t;
-
-	lock(&tlock);
-	memset(b, 0, sizeof(b));
-	f = open("/dev/time", OREAD|OCEXEC);
-	if(f >= 0) {
-		seek(f, 0, 0);
-		read(f, b, sizeof(b));
-	}
-	t = atol(b);
-	if(tp)
-		*tp = t;
-	unlock(&tlock);
-
-	return t;
-}