Thread: RE: [GD-General] NAT Negotiation
Brought to you by:
vexxed72
From: Magnus A. <mag...@st...> - 2004-01-12 11:49:57
|
If I've understand this correctly you have two clients (named C1 and C2) behind NAT connected to a server (named S) and you want to establish a connection between the two clients without reconfiguring the NAT server. I've thought about this problem and I've come up with a solution that may work. 1. C1 decides that it want to establish a connection between itself and C2 so it send that request to S. 2. S starts listening to two new ports and sends one of the numbers to C1 and the other C2. 3. C1 and C2 respond to this packet. 4. S now have the current port numbers of the two clients NAT. Assuming that the NAT will give the next "connection" a port one step higher then this it sends out C2 port number+1 to C1 and vice versa. 5. C1 and C2 starts sending each other packets (about 3-5 with 100ms delay should be enough) on the assigned ports from the server until they get a response. Now the C1 and C2 can communicate with each other. I don't know if this works because of the assumption at point 4. You could perhaps use some other algorithm to predict what port will be the next one (don't have PP installed so I can't look at the .ppt file). Another problem is if the NAT is under a lot of pressure a lot of new entries will be made in the dynamic routing table so the assumption fails, but the procedure can be repeated until success. Also, if the NAT is smart it can refuse to use a port that has data that has been transmitted to it recently. This means that at point 5 the client must send the packets at the same time within one half of a RTT. A lot of problems but this are the only way I found to solve the problem. Please try it if you want. I don't know if it works. Perhaps there are better ways to solve it. :) .magnus auvinen -----Original Message----- From: Brett Bibby [mailto:res...@ga...] Sent: den 12 januari 2004 09:18 To: Gam...@li... Subject: [GD-General] NAT Negotiation This thread is being transferred form the GD-Algorithms list as Brian pointed out it may be OT for the algorithms list. I apologize if this attempt to transfer doesn't go well :-) **Original Post** Yet another network post <sigh>... I searched the archives for NAT and came up with 14 posts. Some say NAT is a problem, others say it's no problem especially when using a third server connected directly to the internet. Google results in a number of old pages, many with outdated links. My problem is that I need to come up with some sort of internal NAT solution (if it's really needed?) because we need to support multiple platforms, and I cannot find any third party solution (including Gamespy or open source) that covers all the platforms or compilable for them. Let's say I have two machines, both behind NATs. They both think their address is 192.168.1.100, but to the outside world it's 123.123.123.123 and 124.124.124.124 (whatever). The only way for these two machines to ever find each other is through some third party, and they are at 125.125.125.125. They each get their address locally (192.168.1.100) and send that to the server in a packet it can understand. The server reads the packet and also notes the ip address of the received packet, so now the server has both the public and private address of a given client. It then sends each of the clients the other's address(es) and they try to contact each other. Is this correct so far? Does it work because the NAT assigned different internal port numbers to the outgoing requests so it uses that to route the incoming packets back to the requestor? If so, this seems deceptively simple. Why does Gamespy mention they have to do other things too? http://www.igda.org/oc/IGDAGamespyNAT.ppt In a slide near the end they say they do some port guessing based upon common patterns. Why would they need this if a third party server is used? Also, Brian Hook mentions in one of his posts in the archive about using the lower 16 bits of the ip address as a unique identifier. Why would I need to do this? http://sourceforge.net/mailarchive/message.php?msg_id=3667950 There is also a mention that you shouldn't hard code port numbers. Is there a recommended way to generate one? Finally, what if I am playing a game where two of us are behind a NAT on a LAN but connected to the same game on the internet. It's likely that I would recieve an address from the server of some other player's private address that would coincide with the address of my friend. When I contact them at that address they reply and I get the wrong connection. Is this what Brian was using the low 16 bits as an identifier for in order to distinguish between people using the same private address accidentally contacting another machine on their LAN? Thanks Brett ** End Original Post ** ** Reply by Brian Hook** This is precariously on the border of being OT and should probably be handled on gd-general, but I don't think it's flagrant (but it's Tom's list, so if he disagrees, we can take it to gd-general) > I searched the archives for NAT and came up with 14 posts. Some say > NAT is a problem, others say it's no problem especially when using NAT is not a problem if you know what you're doing. That's not meant to be flippant or derogatory, but only to point out that A.) it's a hairy problem to the uninitiated and B.) it's a solvable problem. > They each get their address locally (192.168.1.100) and send that > to the server in a packet it can understand. The server reads the > packet and also notes the ip address of the received packet, so now > the server has both the public and private address of a given > client. It then sends each of the clients the other's address(es) > and they try to contact each other. Sounds about right. > Is this correct so far? Does it work because the NAT assigned > different internal port numbers to the outgoing requests so it uses > that to route the incoming packets back to the requestor? Yes, but you can't rely on this. UDP is a connectionless protocol, so in _theory_ (but rarely in practice, at least in the past 5 years or so), the reverse port mapping can change on a per packet basis. This is described in a bit more detail in my article on multiplayer programming you can find at bookofhook.com > In a slide near the end they say they do some port guessing based > upon common patterns. Why would they need this if a third party > server is used? What they're trying to do is allow two players to connect to each other _without opening up any ports_. At least, that's my understanding. This avoids the entire "explaining to users how NAT works and why they can't host a server" problem. > Also, Brian Hook mentions in one of his posts in the archive about > using the lower 16 bits of the ip address as a unique identifier. > Why would I need to do this? To resolve clients behind a NAT. > There is also a mention that you shouldn't hard code port numbers. > Is there a recommended way to generate one? Which port numbers? For your server, you should hardcode them (so that you can tell users what ports to open/forward) but you should also allow them to be relocated in case there's a conflict. > Finally, what if I am playing a game where two of us are behind a > NAT on a LAN but connected to the same game on the internet. It's > likely that I would recieve an address from the server of some > other player's private address that would coincide with the address > of my friend. No, you'll receive the other person's _public_ address and port mapping (ideally) that allows you to communicate with them directly. At least, that's what I'm assuming they're trying to do. If you received 192.168.1.100, well, that's not too helpful since it'll just route to your own internal network (on a router that uses that mapping). Brian **End Brian Hook's Reply** **Begin Second Post** > This is precariously on the border of being OT and should probably be > handled on gd-general, but I don't think it's flagrant (but it's Tom's > list, so if he disagrees, we can take it to gd-general) I posted it here since there was discussion before on this list with no mention of OT at that time. Let me know if you want it moved to GD-General and I will do so immediately. > What they're trying to do is allow two players to connect to each > other _without opening up any ports_. At least, that's my > understanding. This avoids the entire "explaining to users how NAT > works and why they can't host a server" problem. Couldn't they host a server as long as the third party matchmaking server game out thier public ip? Or is the rarely changing port number the problem here too? There isn't much difference between a client and a server once the third party matchmaking knows the correct ip and port number is there? > > > Also, Brian Hook mentions in one of his posts in the archive about > > using the lower 16 bits of the ip address as a unique identifier. > > Why would I need to do this? > > To resolve clients behind a NAT. > So this number would be used to identify players internally rather than ip/port, and when I want to send the packet I lookup the ip/port based upon this? > > Finally, what if I am playing a game where two of us are behind a > > NAT on a LAN but connected to the same game on the internet. It's > > likely that I would recieve an address from the server of some > > other player's private address that would coincide with the address > > of my friend. > > No, you'll receive the other person's _public_ address and port > mapping (ideally) that allows you to communicate with them directly. > At least, that's what I'm assuming they're trying to do. If you > received 192.168.1.100, well, that's not too helpful since it'll just > route to your own internal network (on a router that uses that > mapping). > Is this correct? So if I'm behind the same NAT as my friend, will the router detect the outgoing public ip address and port and reroute it back inside directly to them? Brett ** End Second Post** ------------------------------------------------------- This SF.net email is sponsored by: Perforce Software. Perforce is the Fast Software Configuration Management System offering advanced branching capabilities and atomic changes on 50+ platforms. Free Eval! http://www.perforce.com/perforce/loadprog.html _______________________________________________ Gamedevlists-general mailing list Gam...@li... https://lists.sourceforge.net/lists/listinfo/gamedevlists-general Archives: http://sourceforge.net/mailarchive/forum.php?forum_idU7 |
From: Aaron D. <ri...@in...> - 2004-01-12 22:53:27
|
On Mon, 12 Jan 2004 10:49 pm, Magnus Auvinen wrote: > Now the C1 and C2 can communicate with each other. I don't know if this > works because of the assumption at point 4. You could perhaps use some > other algorithm to predict what port will be the next one (don't have PP > installed so I can't look at the .ppt file). This is a *BAD* idea. I know that Linux doesn't just use the local port number for NAT connections but also the external destination address and destination port number. This is the most correct way to operate (especially from a security point of view) and any NAT implementation that relies on anything less (such as _only_ the local port number as you suggest) is clearly broken and should NOT be relied upon. The ONLY reliable way to do this is to have some mutually accessible server in the middle and use it to explicitly relay traffic between NATed clients. For the more educated users, port forwarding on the NAT device can allow incoming connections in but there is currently no (universal) NAT technology that allows a client to open a listening socket on the NAT device. The closest technology I can think of is Windows connection sharing but you won't find that being used in 95% of all NAT devices on the Internet (most will be ADSL/Cable modems). |
From: Neil S. <ne...@r0...> - 2004-01-12 23:16:03
|
Isn't UPnP NAT Traversal supposed to be the solution to these issues? - Neil. > -----Original Message----- > From: gam...@li... > [mailto:gam...@li...] On > Behalf Of Aaron Drew > Sent: 12 January 2004 10:49 PM > To: gam...@li... > Subject: Re: [GD-General] NAT Negotiation > > On Mon, 12 Jan 2004 10:49 pm, Magnus Auvinen wrote: > > Now the C1 and C2 can communicate with each other. I don't know if > > this works because of the assumption at point 4. You could > perhaps use > > some other algorithm to predict what port will be the next > one (don't > > have PP installed so I can't look at the .ppt file). > > This is a *BAD* idea. I know that Linux doesn't just use the > local port number for NAT connections but also the external > destination address and destination port number. This is the > most correct way to operate (especially from a security point > of view) and any NAT implementation that relies on anything > less (such as _only_ the local port number as you suggest) is > clearly broken and should NOT be relied upon. > > The ONLY reliable way to do this is to have some mutually > accessible server in the middle and use it to explicitly > relay traffic between NATed clients. > > For the more educated users, port forwarding on the NAT > device can allow incoming connections in but there is > currently no (universal) NAT technology that allows a client > to open a listening socket on the NAT device. The closest > technology I can think of is Windows connection sharing but > you won't find that being used in 95% of all NAT devices on > the Internet (most will be ADSL/Cable modems). > > > > > ------------------------------------------------------- > This SF.net email is sponsored by: Perforce Software. > Perforce is the Fast Software Configuration Management System > offering advanced branching capabilities and atomic changes > on 50+ platforms. > Free Eval! http://www.perforce.com/perforce/loadprog.html > _______________________________________________ > Gamedevlists-general mailing list > Gam...@li... > https://lists.sourceforge.net/lists/listinfo/gamedevlists-general > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_id=557 > |
From: J C L. <cl...@ka...> - 2004-01-13 06:06:01
|
On Tue, 13 Jan 2004 09:48:36 +1100 Aaron Drew <ri...@in...> wrote: > On Mon, 12 Jan 2004 10:49 pm, Magnus Auvinen wrote: >> Now the C1 and C2 can communicate with each other. I don't know if >> this works because of the assumption at point 4. You could perhaps >> use some other algorithm to predict what port will be the next one >> (don't have PP installed so I can't look at the .ppt file). > This is a *BAD* idea. I know that Linux doesn't just use the local > port number for NAT connections but also the external destination > address and destination port number. This is the most correct way to > operate (especially from a security point of view) and any NAT > implementation that relies on anything less (such as _only_ the local > port number as you suggest) is clearly broken and should NOT be relied > upon. It is a bad but surprisingly reliable idea. It is also a hack. Loosely it comes down to: Client1 sends packet to server. Server notes port etc. Client2 sends packet to server. Server notes port etc. Server predicts the next port which will allocated by the NAT devices for Client1 and Client2 and instructs each client to start sending a packet stream to the other's NAT device at the predicted port. If the prediction was successful after a few packets each way (so that each end creates a port mapping) two way communication through the NAT boxes will be in place. If the prediction was unsuccessful they'll either have to try again or fail. This is exactly what GameSpy and similar products do. Frankly they usually do it by taking the new port number allocated by the test packet stream to the server and incrementing it by one to get the predicted port for the next port allocation. Simple, dumb, surprisingly effective. > The ONLY reliable way to do this is to have some mutually accessible > server in the middle and use it to explicitly relay traffic between > NATed clients. Right. However an 85% solution covers a heck of a lot of bases, especially when you can just throw in a few retries to whittle down that 15% failure mode to something consumer-grade acceptable. -- J C Lawrence ---------(*) Satan, oscillate my metallic sonatas. cl...@ka... He lived as a devil, eh? http://www.kanga.nu/~claw/ Evil is a name of a foeman, as I live. |
From: Aaron D. <ri...@in...> - 2004-01-13 08:36:21
|
> Right. However an 85% solution covers a heck of a lot of bases, > especially when you can just throw in a few retries to whittle down that > 15% failure mode to something consumer-grade acceptable. What can I say? I'm amazed... I would never have attemped anything like this and I suprised that software like gamespy has as well but heck... What a big hack! In this case, take back my last linux-related post stating it won't work because linux uses incremental port numbers (with reuse of disconnected ports) and its highly likely that such a hack might work... I still can't help but dislike it however.... :) |
From: Brett B. <res...@ga...> - 2004-01-12 23:29:43
|
This is what everybody does pretty much. The link I included in my = previous reply is a good rxplanation of the issues invoilved ( = http://www.mindcontrol.org/~hplus/nat-punch.html ) I believe some NATs will increment port numbers and that would be a good = guess to try, but I also read that they may assign random port numbers. = Seems pretty hard to establish a connection to a NAT device randomly = generating port numbers. Hmmm... ----- Original Message -----=20 From: "Magnus Auvinen" <mag...@st...> To: <gam...@li...> Sent: Monday, January 12, 2004 7:49 PM Subject: RE: [GD-General] NAT Negotiation > If I've understand this correctly you have two clients (named C1 and = C2) > behind NAT connected to a server (named S) and you want to establish a > connection between the two clients without reconfiguring the NAT = server. > I've thought about this problem and I've come up with a solution that = may > work. >=20 > 1. C1 decides that it want to establish a connection between itself = and C2 > so it send that request to S. 2. S starts listening to two new ports = and > sends one of the numbers to C1 and the other C2. 3. C1 and C2 respond = to > this packet. 4. S now have the current port numbers of the two clients = NAT. > Assuming that the NAT will give the next "connection" a port one step = higher > then this it sends out C2 port number+1 to C1 and vice versa. 5. C1 = and C2 > starts sending each other packets (about 3-5 with 100ms delay should = be > enough) on the assigned ports from the server until they get a = response. >=20 > Now the C1 and C2 can communicate with each other. I don't know if = this > works because of the assumption at point 4. You could perhaps use some = other > algorithm to predict what port will be the next one (don't have PP = installed > so I can't look at the .ppt file). Another problem is if the NAT is = under a > lot of pressure a lot of new entries will be made in the dynamic = routing > table so the assumption fails, but the procedure can be repeated until > success. Also, if the NAT is smart it can refuse to use a port that = has data > that has been transmitted to it recently. This means that at point 5 = the > client must send the packets at the same time within one half of a = RTT. A > lot of problems but this are the only way I found to solve the = problem. > =20 > Please try it if you want. I don't know if it works. Perhaps there are > better ways to solve it. >=20 > :) >=20 > .magnus auvinen >=20 > -----Original Message----- > From: Brett Bibby [mailto:res...@ga...]=20 > Sent: den 12 januari 2004 09:18 > To: Gam...@li... > Subject: [GD-General] NAT Negotiation >=20 >=20 > This thread is being transferred form the GD-Algorithms list as Brian > pointed out it may be OT for the algorithms list. I apologize if this > attempt to transfer doesn't go well :-) >=20 > **Original Post** >=20 > Yet another network post <sigh>... >=20 > I searched the archives for NAT and came up with 14 posts. Some say = NAT is a > problem, others say it's no problem especially when using a third = server > connected directly to the internet. Google results in a number of old = pages, > many with outdated links. My problem is that I need to come up with = some > sort of internal NAT solution (if it's really needed?) because we need = to > support multiple platforms, and I cannot find any third party solution > (including Gamespy or open source) that covers all the platforms or > compilable for them. >=20 > Let's say I have two machines, both behind NATs. They both think their > address is 192.168.1.100, but to the outside world it's = 123.123.123.123 and > 124.124.124.124 (whatever). The only way for these two machines to = ever find > each other is through some third party, and they are at = 125.125.125.125. >=20 > They each get their address locally (192.168.1.100) and send that to = the > server in a packet it can understand. The server reads the packet and = also > notes the ip address of the received packet, so now the server has = both the > public and private address of a given client. It then sends each of = the > clients the other's address(es) and they try to contact each other. >=20 > Is this correct so far? Does it work because the NAT assigned = different > internal port numbers to the outgoing requests so it uses that to = route the > incoming packets back to the requestor? If so, this seems deceptively > simple. Why does Gamespy mention they have to do other things too? >=20 > http://www.igda.org/oc/IGDAGamespyNAT.ppt >=20 > In a slide near the end they say they do some port guessing based upon > common patterns. Why would they need this if a third party server is = used? >=20 > Also, Brian Hook mentions in one of his posts in the archive about = using the > lower 16 bits of the ip address as a unique identifier. Why would I = need to > do this? >=20 > http://sourceforge.net/mailarchive/message.php?msg_id=3D3667950 >=20 > There is also a mention that you shouldn't hard code port numbers. Is = there > a recommended way to generate one? >=20 > Finally, what if I am playing a game where two of us are behind a NAT = on a > LAN but connected to the same game on the internet. It's likely that I = would > recieve an address from the server of some other player's private = address > that would coincide with the address of my friend. When I contact them = at > that address they reply and I get the wrong connection. Is this what = Brian > was using the low 16 bits as an identifier for in order to distinguish > between people using the same private address accidentally contacting > another machine on their LAN? >=20 > Thanks > Brett >=20 > ** End Original Post ** > ** Reply by Brian Hook** >=20 > This is precariously on the border of being OT and should probably be=20 > handled on gd-general, but I don't think it's flagrant (but it's Tom's = > list, so if he disagrees, we can take it to gd-general) >=20 > > I searched the archives for NAT and came up with 14 posts. Some say > > NAT is a problem, others say it's no problem especially when using >=20 > NAT is not a problem if you know what you're doing. That's not meant=20 > to be flippant or derogatory, but only to point out that A.) it's a=20 > hairy problem to the uninitiated and B.) it's a solvable problem. >=20 > > They each get their address locally (192.168.1.100) and send that > > to the server in a packet it can understand. The server reads the > > packet and also notes the ip address of the received packet, so now > > the server has both the public and private address of a given > > client. It then sends each of the clients the other's address(es) > > and they try to contact each other. >=20 > Sounds about right. >=20 > > Is this correct so far? Does it work because the NAT assigned > > different internal port numbers to the outgoing requests so it uses > > that to route the incoming packets back to the requestor? >=20 > Yes, but you can't rely on this. UDP is a connectionless protocol, so = > in _theory_ (but rarely in practice, at least in the past 5 years or=20 > so), the reverse port mapping can change on a per packet basis. This=20 > is described in a bit more detail in my article on multiplayer=20 > programming you can find at bookofhook.com >=20 > > In a slide near the end they say they do some port guessing based > > upon common patterns. Why would they need this if a third party > > server is used? >=20 > What they're trying to do is allow two players to connect to each=20 > other _without opening up any ports_. At least, that's my=20 > understanding. This avoids the entire "explaining to users how NAT=20 > works and why they can't host a server" problem. >=20 > > Also, Brian Hook mentions in one of his posts in the archive about > > using the lower 16 bits of the ip address as a unique identifier. > > Why would I need to do this? >=20 > To resolve clients behind a NAT. >=20 > > There is also a mention that you shouldn't hard code port numbers. > > Is there a recommended way to generate one? >=20 > Which port numbers? For your server, you should hardcode them (so=20 > that you can tell users what ports to open/forward) but you should=20 > also allow them to be relocated in case there's a conflict. >=20 > > Finally, what if I am playing a game where two of us are behind a > > NAT on a LAN but connected to the same game on the internet. It's > > likely that I would recieve an address from the server of some > > other player's private address that would coincide with the address > > of my friend.=20 >=20 > No, you'll receive the other person's _public_ address and port=20 > mapping (ideally) that allows you to communicate with them directly. =20 > At least, that's what I'm assuming they're trying to do. If you=20 > received 192.168.1.100, well, that's not too helpful since it'll just=20 > route to your own internal network (on a router that uses that=20 > mapping). >=20 > Brian >=20 > **End Brian Hook's Reply** > **Begin Second Post** >=20 > > This is precariously on the border of being OT and should probably = be=20 > > handled on gd-general, but I don't think it's flagrant (but it's = Tom's=20 > > list, so if he disagrees, we can take it to gd-general) >=20 > I posted it here since there was discussion before on this list with = no > mention of OT at that time. Let me know if you want it moved to = GD-General > and I will do so immediately. >=20 > > What they're trying to do is allow two players to connect to each=20 > > other _without opening up any ports_. At least, that's my=20 > > understanding. This avoids the entire "explaining to users how NAT=20 > > works and why they can't host a server" problem. >=20 > Couldn't they host a server as long as the third party matchmaking = server > game out thier public ip? Or is the rarely changing port number the = problem > here too? There isn't much difference between a client and a server = once the > third party matchmaking knows the correct ip and port number is there? >=20 > >=20 > > > Also, Brian Hook mentions in one of his posts in the archive about > > > using the lower 16 bits of the ip address as a unique identifier. > > > Why would I need to do this? > >=20 > > To resolve clients behind a NAT. > >=20 >=20 > So this number would be used to identify players internally rather = than > ip/port, and when I want to send the packet I lookup the ip/port based = upon > this? > =20 > > > Finally, what if I am playing a game where two of us are behind a > > > NAT on a LAN but connected to the same game on the internet. It's > > > likely that I would recieve an address from the server of some > > > other player's private address that would coincide with the = address > > > of my friend.=20 > >=20 > > No, you'll receive the other person's _public_ address and port=20 > > mapping (ideally) that allows you to communicate with them directly. = =20 > > At least, that's what I'm assuming they're trying to do. If you=20 > > received 192.168.1.100, well, that's not too helpful since it'll = just=20 > > route to your own internal network (on a router that uses that=20 > > mapping). > >=20 >=20 > Is this correct? So if I'm behind the same NAT as my friend, will the = router > detect the outgoing public ip address and port and reroute it back = inside > directly to them? >=20 > Brett >=20 > ** End Second Post** >=20 >=20 > ------------------------------------------------------- > This SF.net email is sponsored by: Perforce Software. > Perforce is the Fast Software Configuration Management System offering > advanced branching capabilities and atomic changes on 50+ platforms. > Free Eval! http://www.perforce.com/perforce/loadprog.html > _______________________________________________ > Gamedevlists-general mailing list > Gam...@li... > https://lists.sourceforge.net/lists/listinfo/gamedevlists-general > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_idU7 >=20 >=20 > ------------------------------------------------------- > This SF.net email is sponsored by: Perforce Software. > Perforce is the Fast Software Configuration Management System offering > advanced branching capabilities and atomic changes on 50+ platforms. > Free Eval! http://www.perforce.com/perforce/loadprog.html > _______________________________________________ > Gamedevlists-general mailing list > Gam...@li... > https://lists.sourceforge.net/lists/listinfo/gamedevlists-general > Archives: > http://sourceforge.net/mailarchive/forum.php?forum_id=3D557 |
From: J C L. <cl...@ka...> - 2004-01-13 05:46:34
|
On Tue, 13 Jan 2004 07:30:58 +0800 Brett Bibby <res...@ga...> wrote: > I believe some NATs will increment port numbers and that would be a > good guess to try, but I also read that they may assign random port > numbers. Seems pretty hard to establish a connection to a NAT device > randomly generating port numbers. Hmmm... Every cheap consumer grade low margin NAT box I've examined (roughly a dozen) has used a base algorithm of simply incrementing the last allocated port. Some of them tweak this by periodically/variously stuffing old reclaimed ports back in the available list or some other port recycling pattern, but that's the exception rather than the rule, and a simple retry reduces it to pretty near a 0% margin. Higher end NAT boxes however have all sorts of tricks and behaviours. They allocate seemingly randomly, or with ports as members of a hash function of the address, or some other curiosity, usually in the name of scalability or performance. Some low end boxes do this as well (and no, I can't quote as I'm a long way from home and my files right now), but it isn't common at the lower ends. -- J C Lawrence ---------(*) Satan, oscillate my metallic sonatas. cl...@ka... He lived as a devil, eh? http://www.kanga.nu/~claw/ Evil is a name of a foeman, as I live. |