* [9fans] csipinfo
@ 2006-10-18 3:10 Joel “chesky” Salomon
2006-10-18 3:36 ` geoff
2006-10-18 20:38 ` andrey mirtchovski
0 siblings, 2 replies; 23+ messages in thread
From: Joel âcheskyâ Salomon @ 2006-10-18 3:10 UTC (permalink / raw)
To: 9fans
My homework assignment reads:
> Write a program to receive multiple UDP messages ... Print to
> standard output the remote host and port from which the message
> originated (print the dotted decimal IP address and also use
> gethostbyaddr to print a textual host name), followed by the message
> itself.
I’ve got everything but the gethostbyaddr equivalent code. From
cpu% sig csipinfo
Ndbtuple* csipinfo(char *netroot, char *attr, char *val, char **attrs, int nattr)
it looks as if I should do something like:
lfd = listen(adir, ldir);
if (lfd < 0) sysfatal("listen: %r");
dfd = accept(lfd, ldir);
if (dfd < 0) sysfatal("can't accept: %r");
NetConnInfo *i = getnetconninfo(nil, lfd);
Ndbtuple *t = csipinfo(nil, "????", "????", ["ip", "dns"], 2);
...
— but what’re the attr and val arguments to csipinfo? I’ve read
ndb(2) and been thoroughly confused, and
http://www.google.com/codesearch turns up no uses of csipinfo, only
its implementation on Plan 9 and plan9ports.
Specifically, what attribute=value pair do I know about for this
remotely-initiated connection?
Thanks,
--Joel
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 3:10 [9fans] csipinfo Joel “chesky” Salomon @ 2006-10-18 3:36 ` geoff 2006-10-18 5:20 ` Joel “chesky” Salomon 2006-10-18 20:38 ` andrey mirtchovski 1 sibling, 1 reply; 23+ messages in thread From: geoff @ 2006-10-18 3:36 UTC (permalink / raw) To: 9fans It's used here: /sys/src/cmd/ssh/util.c:241 /sys/src/cmd/ssh/ip/ppp/ppp.c:738 ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 3:36 ` geoff @ 2006-10-18 5:20 ` Joel “chesky” Salomon 2006-10-18 5:37 ` geoff 0 siblings, 1 reply; 23+ messages in thread From: Joel âcheskyâ Salomon @ 2006-10-18 5:20 UTC (permalink / raw) To: 9fans > It's used here: > > /sys/src/cmd/ssh/util.c:241 > /sys/src/cmd/ssh/ip/ppp/ppp.c:738 (Actually /sys/src/cmd/ip/ppp/ppp.c:738) In ppp the ip address is known so csipinfo is called with (..., "ip", ip, ...); in ssh the system name is known so the pair ipattr(name), name can be used. How can I get any of that information—but specifically the ip address and dns name—for the other end of an announce-listen-accept connection? --Joel ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 5:20 ` Joel “chesky” Salomon @ 2006-10-18 5:37 ` geoff 2006-10-18 5:53 ` Joel “chesky” Salomon 0 siblings, 1 reply; 23+ messages in thread From: geoff @ 2006-10-18 5:37 UTC (permalink / raw) To: 9fans See getnetconninfo in dial(2). ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 5:37 ` geoff @ 2006-10-18 5:53 ` Joel “chesky” Salomon 2006-10-18 12:38 ` Joel “chesky” Salomon 2006-10-18 15:32 ` Russ Cox 0 siblings, 2 replies; 23+ messages in thread From: Joel âcheskyâ Salomon @ 2006-10-18 5:53 UTC (permalink / raw) To: 9fans > See getnetconninfo in dial(2). Thanks! I was calling getnetconninfo already for the remote-end “port number” and I’d overlooked the fact that the address, in *some* form, was there too. So should this invocation: NetConnInfo *i = getnetconninfo(nil, lfd); Ndbtuple *t = csipinfo(nil, ipattr(i->raddr), i->raddr, ["ip", "dns"], 2); work, or am I working too hard? Getnetconninfo will return either the ip address or the dns name (less likely), not both, so I still need csipinfo, right? --Joel ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 5:53 ` Joel “chesky” Salomon @ 2006-10-18 12:38 ` Joel “chesky” Salomon 2006-10-18 15:32 ` Russ Cox 1 sibling, 0 replies; 23+ messages in thread From: Joel âcheskyâ Salomon @ 2006-10-18 12:38 UTC (permalink / raw) To: 9fans > Ndbtuple *t = csipinfo(nil, ipattr(i->raddr), i->raddr, ["ip", "dns"], 2); ... has two problems. One, it should be i->rsys rather than ->raddr (—I think; does it really matter?); and two, the inline creation of the array doesn’t complie; the line now reads: char *attr[2] = {"ip", "dns"}; t = csipinfo(nil, ipattr(i->rsys), i->rsys, attr, 2); which sort of works. In testing I’ve gotten two different ip addresses referring to my system in the list; I’m guessing I need to walk the Ndbtuple list until I find the element referring to "dns"? After the code above, is for(dt = t; dt != nil; dt = dt->entry) if(strstr(dt->attr, "dns")) break; guaranteed to find an Ndbtuple with attr == "dns" or can that fail? --Joel ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 5:53 ` Joel “chesky” Salomon 2006-10-18 12:38 ` Joel “chesky” Salomon @ 2006-10-18 15:32 ` Russ Cox 2006-10-18 16:43 ` Joel Salomon 1 sibling, 1 reply; 23+ messages in thread From: Russ Cox @ 2006-10-18 15:32 UTC (permalink / raw) To: Fans of the OS Plan 9 from Bell Labs Getnetconninfo will return an IP address. Russ ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 15:32 ` Russ Cox @ 2006-10-18 16:43 ` Joel Salomon 2006-10-18 16:59 ` rog 0 siblings, 1 reply; 23+ messages in thread From: Joel Salomon @ 2006-10-18 16:43 UTC (permalink / raw) To: Fans of the OS Plan 9 from Bell Labs > Getnetconninfo will return an IP address. Seems I need getnetconninfo, but maybe not csipinfo, just a reverse dns lookup; Ndbtuple* t = dnsquery("/net" (or nil, or ?), i->rsys, "ptr") ought to do the trick. I just need to check which of t->attr and t->line->attr is "ptr" and which is "dom" (Is it guaranteed which is first? I guess I could check and ndbreorder(t, t->line) if needed.) and then build the "machine.dom" form of the name with something like print("%s.%s", t->val, t->list->val); I'll try this when I get back to my laptop, but if I'm misunderstanding something could somebody please warn me? --Joel ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 16:43 ` Joel Salomon @ 2006-10-18 16:59 ` rog 0 siblings, 0 replies; 23+ messages in thread From: rog @ 2006-10-18 16:59 UTC (permalink / raw) To: 9fans i don't know if it's any help, but here's some code that i have used in the past to do a reverse dns lookup. it was under inferno and the code's in limbo, but i think that /net/dns probably works the same in both inferno and plan 9, so it should be cross-applicable. it expects a host address of the form "123.45.67.89!9999" (as found in the remote file) and returns the dns name. hostname(addr: string): string { (nil, toks) := sys->tokenize(addr, "!"); if(len toks != 2) return addr; addr = hd toks; if(NoDNS) return addr; a := addr2arpa(addr); if(a == nil) return addr; fd := sys->open("/net/dns", Sys->ORDWR); if(fd == nil) return addr; if(sys->fprint(fd, "%s ptr", a) < 0){ err := sys->sprint("%r"); log(sys->sprint("dnslookup failed %q %q", addr, err)); return addr; } buf := array[1024] of byte; sys->seek(fd, big 0, 0); n := sys->read(fd, buf, len buf); if(n <= 0) return addr; a = string buf[0:n]; for(i := 0; i < len a; i++) if(a[i] == '\t') break; if(i == len a) return addr; i++; # return address of the form: # 68.1.1.200.in-addr.arpa ptr presto.vitanuova.com(0) for(j := len a - 1; j > i; j--) if(a[j] == '(') return a[i:j]; return a[i:]; } addr2arpa(a: string): string { addr := "in-addr.arpa"; for(toks := sys->tokenize(a, ".").t1; toks != nil; toks = tl toks) addr = hd toks + "." + addr; return addr; } ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 3:10 [9fans] csipinfo Joel “chesky” Salomon 2006-10-18 3:36 ` geoff @ 2006-10-18 20:38 ` andrey mirtchovski 1 sibling, 0 replies; 23+ messages in thread From: andrey mirtchovski @ 2006-10-18 20:38 UTC (permalink / raw) To: Fans of the OS Plan 9 from Bell Labs On 10/17/06, Joel "chesky" Salomon <chesky@plan9.jp> wrote: > My homework assignment reads: > > Write a program to receive multiple UDP messages ... Print to > > standard output the remote host and port from which the message > > originated (print the dotted decimal IP address and also use > > gethostbyaddr to print a textual host name), followed by the message > > itself. "make sure you cite all your sources and collaborators in your submission" ;) ^ permalink raw reply [flat|nested] 23+ messages in thread
[parent not found: <61d9157e8f6994d999d7f257cd2b05b4@coraid.com>]
* Re: [9fans] csipinfo [not found] <61d9157e8f6994d999d7f257cd2b05b4@coraid.com> @ 2006-10-18 18:44 ` Joel “chesky” Salomon 2006-10-18 19:14 ` rog 2006-10-18 19:30 ` erik quanstrom 0 siblings, 2 replies; 23+ messages in thread From: Joel âcheskyâ Salomon @ 2006-10-18 18:44 UTC (permalink / raw) To: 9fans > had to go around the list ... can't post from here. > > i think you're making this too hard. what you want is more > of a dns query. this is very easy to do. something like > (this might not complie -- i just typed it out.) > > char* > gethostbyaddr(char *net, char *addr) > { > char buf[64]; > int fd, l; > > if(net == 0) > net="/net"; > snprint(buf, sizeof buf, "%s/dns", net); > fd = open(buf, ORDWR); > if(fd < 0) > return 0; > snprint(buf, sizeof buf, "%s ptr", addr); > if(write(fd, buf, strlen(buf)) < 0) > return 0; > l = read(fd, buf, sizeof buf); > if(l < 0 || l == sizeof buf) > return 0; > return strdup(buf); > } > > - erik Thanks, this finally looks like what I need. Two points though: 1. Is 64 bytes sufficient for the domain name? Searching the ’net I’ve found other numbers — according to <http://tinyurl.com/ykyths> it should be 1005; <http://tinyurl.com/xdp4> links to a name about 140 bytes long and firefox handles it just fine. 2. Why the second part of “if(l < 0 || l == sizeof buf)”? I’ll bang on this a bit and see if I can make it set errstr appropriately. --Joel ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 18:44 ` Joel “chesky” Salomon @ 2006-10-18 19:14 ` rog 2006-10-18 19:26 ` erik quanstrom ` (2 more replies) 2006-10-18 19:30 ` erik quanstrom 1 sibling, 3 replies; 23+ messages in thread From: rog @ 2006-10-18 19:14 UTC (permalink / raw) To: 9fans > Thanks, this finally looks like what I need. it won't work. something like the code i posted is needed. for ptr resolution, /net/dns requires the numeric ip address, reversed, with ".in-addr.arpa" appended. also, the address read back from /net/dns is not the straight domain name (but you'll find that out soon enough). documentation on /net/dns is not great. if one knew more about DNS, maybe the .in-addr.arpa thing would be obvious... ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 19:14 ` rog @ 2006-10-18 19:26 ` erik quanstrom 2006-10-18 19:38 ` Joel “chesky” Salomon 2006-10-18 19:56 ` Charles Forsyth 2 siblings, 0 replies; 23+ messages in thread From: erik quanstrom @ 2006-10-18 19:26 UTC (permalink / raw) To: 9fans ah, you're right. i didn't remember that dnsquery supplies that magic. i think it would be a good think if /net/dns did the translation itself. - erik ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 19:14 ` rog 2006-10-18 19:26 ` erik quanstrom @ 2006-10-18 19:38 ` Joel “chesky” Salomon 2006-10-18 19:57 ` C H Forsyth ` (2 more replies) 2006-10-18 19:56 ` Charles Forsyth 2 siblings, 3 replies; 23+ messages in thread From: Joel âcheskyâ Salomon @ 2006-10-18 19:38 UTC (permalink / raw) To: 9fans > > Thanks, this finally looks like what I need. > > it won't work. something like the code i posted is needed. I’m trying to read the limbo code and translate it to my needs; bear with me as I translate this to c-ish pseudocode: char* gethostbyaddr(char *net, char *addr) { char buf[1024], *dq[4], s; int fd, l; if(net == nil) net = "/net"; snprint(buf, sizeof buf, "%s/dns", net); if((fd = open(buf, ORDWR)) < 0) return nil; // set errstr "gethostbyaddr failed: can't open %s: %r", buf) dq[0] = strtok(addr, "."); // neglecting error checking dq[1] = strtok(0, "."); dq[2] = strtok(0, "."); dq[3] = strtok(0, "."); snprint(buf, sizeof buf, "%s.%s.%s.%s.in-addr.arpa ptr", dq[3], dq[2], dq[1], dq[0]); if(write(fd, buf, l) != l) return nil; // close fd & set errstr if(read(fd, buf, sizeof buf) < 0) return nil; s = strstr(buf, " ptr "); return(strdup(s+5)); } Well, it’s less pseudocode than a rough draft. If it passes rog’s sanity check I’ll add better error checking and submit it for inclusion somewhere—someone, somewhere, has got to want this. --Joel ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 19:38 ` Joel “chesky” Salomon @ 2006-10-18 19:57 ` C H Forsyth 2006-10-18 23:51 ` Charles Forsyth 2006-10-18 20:17 ` Joel “chesky” Salomon 2006-10-18 21:29 ` geoff 2 siblings, 1 reply; 23+ messages in thread From: C H Forsyth @ 2006-10-18 19:57 UTC (permalink / raw) To: 9fans > dq[0] = strtok(addr, "."); // neglecting error checking > dq[1] = strtok(0, "."); dq[2] = strtok(0, "."); dq[3] = strtok(0, "."); see getfields etc. instead of tokenize. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 19:57 ` C H Forsyth @ 2006-10-18 23:51 ` Charles Forsyth 2006-10-19 8:29 ` Charles Forsyth 0 siblings, 1 reply; 23+ messages in thread From: Charles Forsyth @ 2006-10-18 23:51 UTC (permalink / raw) To: 9fans >see getfields etc. instead of tokenize. sorry, i meant: see getfields, tokenize, etc. instead of strtok obviously i was following my own advice ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 23:51 ` Charles Forsyth @ 2006-10-19 8:29 ` Charles Forsyth 0 siblings, 0 replies; 23+ messages in thread From: Charles Forsyth @ 2006-10-19 8:29 UTC (permalink / raw) To: 9fans >sorry, i meant: see getfields, tokenize, etc. instead of strtok i ought to have included an explanation, but i was short of time. the biggest problem is that strtok keeps some hidden state between calls, so it's a nuisance in concurrent programming. i usually find having the result as an array of strings more helpful than having to make several calls, as well. probably POSIX has fixed the concurrency problem by implying thread-local storage for strtok's state (thus creating a different problem elsewhere) tokenize is often useful because it handles quoting, which is useful for space-separated fields that need to be able to contain white space. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 19:38 ` Joel “chesky” Salomon 2006-10-18 19:57 ` C H Forsyth @ 2006-10-18 20:17 ` Joel “chesky” Salomon 2006-10-18 21:29 ` geoff 2 siblings, 0 replies; 23+ messages in thread From: Joel âcheskyâ Salomon @ 2006-10-18 20:17 UTC (permalink / raw) To: 9fans I think I have a working gethostbyaddr: char* gethostbyaddr(char *net, char *addr) { // Thanks to erik and rog for their help with this code char buf[1024], errbuf[ERRMAX], *dq[4], *host; int fd, l; if(net == nil) net = "/net"; snprint(buf, sizeof buf, "%s/dns", net); if((fd = open(buf, ORDWR)) < 0){ l = snprint(errbuf, ERRMAX, "gethostbyaddr: can't open %s: %r", buf); errstr(errbuf, l); return nil; } if(getfields(addr, dq, 4, 1, ".") != 4){ close(fd); werrstr("gethostbyaddr: malformed address"); return nil; } l = snprint(buf, sizeof buf, "%s.%s.%s.%s.in-addr.arpa ptr", dq[3], dq[2], dq[1], dq[0]); if(write(fd, buf, l) != l){ l = snprint(errbuf, ERRMAX, "gethostbyaddr: write error resolving %s.%s.%s.%s: %s/dns: %r", dq[0], dq[1], dq[2], dq[3], net); close(fd); errstr(errbuf, l); return nil; } if(read(fd, buf, sizeof buf) <= 0){ l = snprint(errbuf, ERRMAX, "gethostbyaddr: read error resolving %s.%s.%s.%s: %s/dns: %r", dq[0], dq[1], dq[2], dq[3], net); close(fd); errstr(errbuf, l); return nil; } close(fd); host = strstr(buf, " ptr "); if(host == nil){ werrstr("gethostbyaddr: dns lookup failed"); return nil; } return strdup(host); } --Joel ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 19:38 ` Joel “chesky” Salomon 2006-10-18 19:57 ` C H Forsyth 2006-10-18 20:17 ` Joel “chesky” Salomon @ 2006-10-18 21:29 ` geoff 2 siblings, 0 replies; 23+ messages in thread From: geoff @ 2006-10-18 21:29 UTC (permalink / raw) To: 9fans smtpd does a lot of this sort of DNS lookup. If all you want is to map an IP address back to a domainname, this one line from /sys/src/cmd/upas/smtp/greylist.c:265 should suffice: fqdn = csgetvalue(nil, "ip", nci->rsys, "dom", nil); where nci->rsys is a string containing a dotted-quad address like "135.104.9.82" for IPv4. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 19:14 ` rog 2006-10-18 19:26 ` erik quanstrom 2006-10-18 19:38 ` Joel “chesky” Salomon @ 2006-10-18 19:56 ` Charles Forsyth 2006-10-18 19:59 ` erik quanstrom 2006-10-18 20:15 ` rog 2 siblings, 2 replies; 23+ messages in thread From: Charles Forsyth @ 2006-10-18 19:56 UTC (permalink / raw) To: 9fans >if one knew more about DNS, maybe the .in-addr.arpa thing >would be obvious... that's what's the subject of DNS lookups to do a `reverse lookup'. it's really an ordinary lookup of specially-constructed names in a domain reserved for them. that's the DNS itself, nothing to do with Plan 9. dnsquery is mainly used interactively. i'm not sure you really want to do it inside ndb/dns itself, because it catches cases where client programs are confused (or have been confused) between domain names and IP addresses. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 19:56 ` Charles Forsyth @ 2006-10-18 19:59 ` erik quanstrom 2006-10-18 20:15 ` rog 1 sibling, 0 replies; 23+ messages in thread From: erik quanstrom @ 2006-10-18 19:59 UTC (permalink / raw) To: 9fans why should a program in general care what the difference between a domain and an ip address is? it's pretty easy to tell if you really need to know, which isn't often. - erik On Wed Oct 18 15:57:11 EDT 2006, forsyth@terzarima.net wrote: > >if one knew more about DNS, maybe the .in-addr.arpa thing > >would be obvious... > > that's what's the subject of DNS lookups to do a `reverse lookup'. > it's really an ordinary lookup of specially-constructed names in > a domain reserved for them. that's the DNS itself, nothing to do with Plan 9. > dnsquery is mainly used interactively. i'm not sure you really want to do it > inside ndb/dns itself, because it catches cases where client programs > are confused (or have been confused) between domain names and IP addresses. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 19:56 ` Charles Forsyth 2006-10-18 19:59 ` erik quanstrom @ 2006-10-18 20:15 ` rog 1 sibling, 0 replies; 23+ messages in thread From: rog @ 2006-10-18 20:15 UTC (permalink / raw) To: 9fans > it catches cases where client programs > are confused (or have been confused) between domain names and IP addresses. isn't the "ptr" query type clue enough? is there ever a case where one would use that that type and not do the in-addr.arpa thing? ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [9fans] csipinfo 2006-10-18 18:44 ` Joel “chesky” Salomon 2006-10-18 19:14 ` rog @ 2006-10-18 19:30 ` erik quanstrom 1 sibling, 0 replies; 23+ messages in thread From: erik quanstrom @ 2006-10-18 19:30 UTC (permalink / raw) To: 9fans > Thanks, this finally looks like what I need. Two points though: > 1. Is 64 bytes sufficient for the domain name? Searching the ’net > I’ve found other numbers — according to <http://tinyurl.com/ykyths> it > should be 1005; <http://tinyurl.com/xdp4> links to a name about 140 > bytes long and firefox handles it just fine. this was throwaway code. i didn't think very hard about that number. ndb does have a maximum value length of 64 bytes. ; g -i max /sys/src/cmd/ndb/dns.h: dns.h:68: Domlen= 256, /* max domain name length (with NULL) */ > 2. Why the second part of “if(l < 0 || l == sizeof buf)”? room for the terminating null. as pointed out, this doesn't quite work. you have to reverse the dots yourself and add in-addr.arpa. the code is in /sys/src/cmd/ndb/dnsquery.c - erik ^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2006-10-19 8:29 UTC | newest] Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2006-10-18 3:10 [9fans] csipinfo Joel “chesky” Salomon 2006-10-18 3:36 ` geoff 2006-10-18 5:20 ` Joel “chesky” Salomon 2006-10-18 5:37 ` geoff 2006-10-18 5:53 ` Joel “chesky” Salomon 2006-10-18 12:38 ` Joel “chesky” Salomon 2006-10-18 15:32 ` Russ Cox 2006-10-18 16:43 ` Joel Salomon 2006-10-18 16:59 ` rog 2006-10-18 20:38 ` andrey mirtchovski [not found] <61d9157e8f6994d999d7f257cd2b05b4@coraid.com> 2006-10-18 18:44 ` Joel “chesky” Salomon 2006-10-18 19:14 ` rog 2006-10-18 19:26 ` erik quanstrom 2006-10-18 19:38 ` Joel “chesky” Salomon 2006-10-18 19:57 ` C H Forsyth 2006-10-18 23:51 ` Charles Forsyth 2006-10-19 8:29 ` Charles Forsyth 2006-10-18 20:17 ` Joel “chesky” Salomon 2006-10-18 21:29 ` geoff 2006-10-18 19:56 ` Charles Forsyth 2006-10-18 19:59 ` erik quanstrom 2006-10-18 20:15 ` rog 2006-10-18 19:30 ` erik quanstrom
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).