tun6bed4-devel Mailing List for 6bed4 (Page 3)
zeroconfig IPv6 tunnel
Status: Beta
Brought to you by:
vanrein
You can subscribe to this list here.
2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(19) |
Dec
(5) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2012 |
Jan
|
Feb
|
Mar
(3) |
Apr
|
May
(3) |
Jun
(12) |
Jul
(12) |
Aug
|
Sep
(3) |
Oct
|
Nov
|
Dec
|
2013 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(9) |
2014 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
|
From: Rick v. R. <ri...@op...> - 2011-11-30 10:18:20
|
Hello Joost, I do not agree that any host in the routing layer should keep state. This would seriously degrade their performance, and also the performance of the layers built on top of it, due to the lookups that have to be made in tables that grow with the complexity of the network. Moreover, I am not sure what you are trying to accomplish with this proposal. The mechanism of Neighbor Discovery is extremely lightweight and already does all it should do -- AFAIK. We already have an over-engineered tunnel protocol named Teredo; I think 6bed4 should avoid taking that path, but with the complexity that you are introducing we would probably have to add lots more. The power of 6bed4 is, IMHO, its simplicity. The addition of ND is a necessity, but it actually is to my disliking because it disrupts the elegant simplicity of the v00 version. I hope to be clear with this response; not putting you off. I do value your input. I hope to find the time to construct a new version of the draft in the coming few days. Cheers, -Rick |
From: Rick v. R. <ri...@op...> - 2011-11-30 10:04:00
|
Hello Timothy, Welcome :) > > I don't see a benefit in deviating from the IPv6 protocol here and would say a minimum MTU of 1280 is required. If the MTU is too large, let the v6 layer handle the problem. > > That could lead to a relay reassembling IPv4 packets before forwarding > them, the IPv6 MTU should be limited to IPv4 MTU-overhead. Packet fragmentation at the IPv4 layer is always possible. IPv4 was dimensioned for packets up to 576 bytes (after reassembly) as per RFC 791 and may quietly drop larger ones. This deviates from current practice, so it is a bit of a theoretical problem. What this means however, is that an MTU in excess of 576 is never safe to assume; IPv6 on the other hand, requires a minimum MTU of 1280. Combining these spells disaster for tunnels -- in theory. In practice, this should not be much of a problem. Virtuall all current Internet is run over MTU 1500 networks, so fragmentation at the IPv4 level would be highly exceptional. Fragmantation can occur within IPv6, even after path discovery. This is the result of routing dynamicity. It is a risk that every IPv6 layer should take into account. But it is also true that 6bed4 increases that dynamicity. > The client > MUST perform IPv4 MTU discovery reliably, this is difficult given some > NAT routers don't issue ICMP Fragmentation Needed errors, but instead > adjust the TCP MSS. You are saying that the 6bed4 tunnel would have to perform IPv4 MTU discovery if it were to support higher MTU's for IPv6, right? Are you suggesting that 6bed4 needs to do more than merely pass the MTU discovery attempts from a using IPv6 layer? > The route from the relay to client is more difficult, IPv4 MTU discovery > by the relay is impossible, and there is a risk that packets from > different relays will have different identification fields and mixed up > on reassembly. Perhaps the client could respond to IPv4 fragments with > IPv6 Too Big. I'm afraid that IPv4-level fragmentation, which can arise as soon as a path element has an MTU below 1500, is a fact of life that cannot be avoided. I don't think this problem can be solved in the tunnel. It is one of the ways of saying "native IPv6 is better". Cheers, -Rick |
From: Joost L. <vla...@gm...> - 2011-11-30 09:22:55
|
On Nov 30, 2011, at 12:13 AM, Timothy Baldwin wrote: > That could lead to a relay reassembling IPv4 packets before forwarding > them, the IPv6 MTU should be limited to IPv4 MTU-overhead. The client > MUST perform IPv4 MTU discovery reliably, this is difficult given some > NAT routers don't issue ICMP Fragmentation Needed errors, but instead > adjust the TCP MSS. > > The route from the relay to client is more difficult, IPv4 MTU discovery > by the relay is impossible, and there is a risk that packets from > different relays will have different identification fields and mixed up > on reassembly. Perhaps the client could respond to IPv4 fragments with > IPv6 Too Big. I agree that the ideal situation would be to determine the IPv4 MTU and then set the IPv6 MTU to that, substracted by IPv4+UDP overhead. But as you already stated, determining IPv4 MTU is difficult at best, and will regularly prove to be impossible. With that option unavailable I agree with Rick in his view that 1280 should be a very reasonable default. On the subject of fragmented v4 packets: won't that be transparent for the tunnel client unless the DF bit is set? I can see that there will be a performance penalty to pay, but I think (reliable) connectivity should be the first priority. Joost |
From: Timothy B. <tim...@fa...> - 2011-11-29 23:12:42
|
On 26/11/11 13:02, Joost Lek wrote: > On Nov 26, 2011, at 1:49 PM, Rick van Rein wrote: > > I don't see a benefit in deviating from the IPv6 protocol here and would say a minimum MTU of 1280 is required. If the MTU is too large, let the v6 layer handle the problem. That could lead to a relay reassembling IPv4 packets before forwarding them, the IPv6 MTU should be limited to IPv4 MTU-overhead. The client MUST perform IPv4 MTU discovery reliably, this is difficult given some NAT routers don't issue ICMP Fragmentation Needed errors, but instead adjust the TCP MSS. The route from the relay to client is more difficult, IPv4 MTU discovery by the relay is impossible, and there is a risk that packets from different relays will have different identification fields and mixed up on reassembly. Perhaps the client could respond to IPv4 fragments with IPv6 Too Big. |
From: Joost L. <vla...@gm...> - 2011-11-28 16:37:45
|
I think there are three categories of peers with every 6bed4 client falling into one of these categories: 1. An application aware (embedded) peer actively initiating p2p connections to obtain specific paths 2. An infrastructure peer, unaware of the meaning of the packets it is forwarding, accepting p2p connections and having a possibility of forming them when desired (implementation specific) 3. A peer only connecting to the relay server, not accepting p2p connections either intentionally or not (because of firewall restrictions) To enable a smooth operation for all these three peer types I propose to create state in the paths formed between peers. These paths should be similar to TCP connections in handshake and control, but not implement any windowing or checksumming. That way state information can be kept up-to-date between peers in a way that has proven itself in the real world and all possible peer scenarios can be implemented efficiently. The technical details of the proposal can be found below: Neighbor solicitations are augmented with 5 bits (using the reserved section of the ICMPv6 NS and NA headers): SYN: synchronise bit ACK: acknowledgement FIN: finalize RST: reset connection KPA: keep-alive packet A lot of the flag names are copied from TCP, their intent is exactly the same or very similar. When a peer A desires direct connection to peer B an NS packet is sent with SYN set to 1. A -> NS SYN -> B B indicates it has recevied the peering attempt and answers positively: B -> NA SYN,ACK, -> A A indicates the path is now in a state of established and sends a message to indicate this: A -> NS ACK -> B B now also considers the path established and normal packets can flow through the path. For PEERTIMEOUT/2 seconds no packets have been received across the path by B, B sends a keepalive packet: B -> NS KPA -> A A replies positively to indicate the connection should still be open: A -> NA KPA,ACK -> B When either one of the peers decides the connection should be closed it sends a an NS with FIN set: A -> NS FIN -> B The other peer agrees and sends an acknowledgement across the path, after which the path is discarded B -> NA FIN -> A When a peer receives a packet other than an NS down a path that is not established the peer sends back a reset: A -> ICMPv6 PING -> B B -> NS, RST -> A After sending the RST packet down the path the peer may ignore any traffic down that path for TIMEOUT seconds, except for NS messages. This way neighbor paths are established in a three-way handshake manner like TCP, this guarantees a proper connection. Revisiting the client scenarios we can see all possible clients needs are met: 1. The client is able to form peer paths when required and buffer packets until it is certain they can be delivered down the path. 2. When requested the client is able to form paths, it can choose to initiate paths at it's own discretion and it can refuse paths if so desired. 3. When the peer receives NS SYN packets it SHOULD reply with an NA RST packet to indicate it refuses peering, the initiating peer can then send the packet down to the client via the relay. The 5 bits can easily be accommodated in the reserved bits for NS (32 available) and NA (29 available) as they will be processed by 6bed4 clients only and not be sent to the greater internet. If this option is in any way undesirable the other possibility is creating a new ICMPv6 extension header, which seams a bit wasteful for only 5 bits as they add a minimum of 4 bytes to the NS and NA ICMPv6 messages. Thoughts? Joost |
From: Joost L. <vla...@gm...> - 2011-11-26 13:02:35
|
On Nov 26, 2011, at 1:49 PM, Rick van Rein wrote: > Hi Joost, > >> In section 3.5 it is stated tunnel MTU is set to 1280 as a MUST. What's the reasoning behind this requirement? > > This is the minimum MTU that's guaranteed for IPv6 traffic. > In an anycast system, there's no way of knowing what server > will handle the traffic, which could lead to trouble. So > instead of risking that, I've specified the minimum MTU as > the reliable value. > > You're asking about the MUST -- are you thinking it should > be a SHOULD? IPv6 gets pretty mad when breaking up occurs, > AFAIK. It basically flags down the communication channel > over ICMPv6. I don't see a benefit in deviating from the IPv6 protocol here and would say a minimum MTU of 1280 is required. If the MTU is too large, let the v6 layer handle the problem. Joost |
From: Rick v. R. <ri...@op...> - 2011-11-26 12:50:03
|
Hi Joost, > In section 3.5 it is stated tunnel MTU is set to 1280 as a MUST. What's the reasoning behind this requirement? This is the minimum MTU that's guaranteed for IPv6 traffic. In an anycast system, there's no way of knowing what server will handle the traffic, which could lead to trouble. So instead of risking that, I've specified the minimum MTU as the reliable value. You're asking about the MUST -- are you thinking it should be a SHOULD? IPv6 gets pretty mad when breaking up occurs, AFAIK. It basically flags down the communication channel over ICMPv6. -Rick |
From: Joost L. <vla...@gm...> - 2011-11-26 11:19:59
|
Hey, In section 3.5 it is stated tunnel MTU is set to 1280 as a MUST. What's the reasoning behind this requirement? Joost |
From: Joost L. <vla...@gm...> - 2011-11-26 11:08:10
|
On Nov 25, 2011, at 9:07 PM, Rick van Rein wrote: > In short, after a successful Neighbor Discovery exchange, there is a > timer that expires between 15 and 45 seconds, causing another round of > Neighbor Discovery for the path. This suffices to keep NAT or firewalls > open. Note however, that this is only done as long as the path is in > use; if the IPv6 application drops silent for too long, and if both sides > participate in that, the connection can still disappear; so what I wrote > before about needing to keep a firewall hole open by actively communicating > every now and then still applies. Right now that's implemented for the relay connection in the py-code branch like this: if peer does not receive a packet from the relay server for a set period of time (10s right now) a new RS is sent out to the relay server. This has two advantages: a NAT entry in an intermediary router is kept open and if the v4 address is somehow changed the v6 address gets updated within 10 seconds of this change, regardless of the host system being aware of any v4 address changes. > Do note that an expired entry simply leads to trying again. The only > problem might be that 6bed4 has changed its address by then... I believe the peer should drop all it's learned neighbor associations upon assigning a different v6 address (I can't find this in the spec right now, is it in there?). What if the spec would state these rules: 1. Upon receiving a neighbor solicitation a peer should reply via neighbor advertisement, from that moment the new path is learned. 2. If a non-NS valid packet is received over a new path the packet must be discarded. 3. Packets must be forwarded over a learned path. 4. After not receiving packets through a learned path for TIMEOUT a neighbor solicitation may be sent if a peer requires the path to be kept open. 5. The decision for sending a neighbor solicitation is left up to the peer implementation. 6. Upon assigning a different v6 address all known paths are discarded. That way different peer implementations can treat NS in their preferred way (1), for instance starting the NS and caching the packet until the path becomes available or sending the packet to the relay in the meantime. I'm uncertain on (2), discarding packets isn't very nice, maybe send an ICMP reply indicating an invalid path? By giving the peer the option for a keep-alive mechanism (4) a path that is only used for one-way traffic can be kept open by the sending peer 'requesting' a reply via NS. (5) allows for implementations deciding not to use lower-metric paths for some reason while still adhering to the spec. I feel these rules could be sufficient for allowing all peer-to-peer scenarios to be executed properly while still giving implementers a large amount of freedom in how to handle them. I don't think having peer-to-peer communication being a MUST is going to work since the availability of paths is going to be uncertain. Further I feel there should be a safeguard for keeping unused paths open for too long but I haven't wrapped my head around that completely yet. Also I feel we need a provision like (2) to allow for a resource constrained peer to drop a path in a graceful way. Joost |
From: Rick v. R. <ri...@op...> - 2011-11-25 20:42:15
|
Hello Joost, Thanks for all your work, and thanks for sharing it now in this repository. There are a few people interested, so sharing the ideas is ideal. > Reading the draft I was wondering why "Energy Level" has been chosen as a label for the "weight" of a route. It feels a bit confusing to me and I would like to suggest using "metric". This term will be more familiar for implementers as it is widely used throughout the networking word for a very similar meaning. I agree. The concept materialised from a fluid and dynamic form, and happened to settle on something common. Best to use the corresponding name then :) Also at your request, I've uploaded the working version of the spec to its own repository. We now have one for C, Python and InetDraft, all to be found from http://sf.net/projects/tun6bed4 -Rick |
From: Rick v. R. <ri...@op...> - 2011-11-25 20:42:15
|
Hello Joost, > The spec is very clear on when to forward a packet along which route, after the routes and energy levels have been learned. I'm not quite getting my head around when the peer should be trying to learn a new route and when it shouldn't. For instance on p10 the spec states: > > * Neighbor Solicitation messages are duplicated over all 6bed4 > paths that could work; > > However the path to the 6bed4 relay service is always available, so one wouldn't expect neighbor solicitations along this path. Agreed, this should only be done for metric 0x2000 and 0x4000. The current spec states that multicast subscription MUST always be done, but that does not seem to make any sense if there are no addresses with metric 0x2000. This is something I realised after having discussed the 0x2000-for-public-IP-on-LAN topic yesterday. > Also: > * The energy level of incoming traffic is determined, and if it has > a lower energy level than the current outgoing route, the latter > will be updated. > Does this mean the record with the lower energy level should always be discarded? The route with the higher metric should be discarded. > In practice: two routes are known for host A, a route via the public v4 address (0x4000) and the relay server (0x8000). A new route is learned via the local LAN (0x2000), should the public route be discarded altogether? The only route that should prevail is the one with the lowest metric. The aim is to follow paths with the same metric in both directions, so routes are symmetric as far as NAT and firewalls are concerned; this is helpful in keeping them open. Firewalls could otherwise drop active asymmetric connections if the only traffic getting through a hole is incoming. > Also: when is neighbor solicitation initiated? The idea of assigning a /64 to the 6bed4 interface is that this is what usual IPv6 practices dictate. > When a packet mean for IPv6 host A enters the peer program (the host is within the TBD2::/64 range) and no paths other than the relay server are known, how do we treat the packet? Sending out the packet to the relay server and attempting a neighbor solicitation would be the logical step in my opinion, but ofcourse the path should not be learned from that exact moment. Ah yes, that is something I didn't want to specify too tightly. If your program is in a hurry (realtime streaming, say) then you would send to the Public 6bed4 Relay while at the same time finding a more optimal route. However, if you can lay back and relax (downloading a page from an IIS server, for instance) you could also choose to first do the neighbor discovery. As for the 6bed4 tunnel layer, that means that a route to the Public 6bed4 Relay could be inserted as soon as a Neighbor Discover request arrives from the user program, or not until a certain delay has passed. This is dependent on the application. I know that is not very helpful for programming a generic tunnel client, but I suppose the spec should not make a choice here, and the tunnel client would be more concrete by either making a safe choice or making it configurable. > On p12 the spec states: > Before being able to address an IPv6 target starting with the 6bed4 > prefix TBD1::/64, the IPv6 layer would send a Neigbor Solicitation > message. The 6bed4 layer would forward that message to the following > targets: > What should be done with the packet while we wait for a reply from the NS? The IPv6 layer has nowhere to send it, so unless I'm mistaken, it would not offer the packet but keep it in its queues. In RFC 4861, this is described as follows: Once the IP address of the next-hop node is known, the sender examines the Neighbor Cache for link-layer information about that neighbor. If no entry exists, the sender creates one, sets its state to INCOMPLETE, initiates Address Resolution, and then queues the data packet pending completion of address resolution. > Dropping it doesn't sound very appealing to me, I'd suggest forwarding it to the relay server while the path is being learned. I agree that _if_ such a packet comes through, then passing it on to the Public 6bed4 Relay server is the best option. Dropping packets would put a bit too must faith in resending mechanisms and their expediency :-) > Also, since there is no three-way handshake for the neighbor paths, when do we consider a path working and when do we consider it dysfunctional? The path is considered to work from the moment that the Neighbor Solicitation returns an answer. When this happens, a message has been sent to the path and arrived back over it, and so it's party time. Dysfunctional paths are more difficult, as we cannot know for certain what timeouts act up in intermediate NAT and firewalls. However, the assumption made in the spec (and perhaps that needs a few words to make it explicit) is that the neighbor cache entry would expire before the path became dysfunt. I've been looking for confirmation that this is like with ARP, in half a minute, but haven't found it yet. This does touch upon an important issue: who is responsible for keeping a connection alive in the face of NAT and firewalls? If it were only a NAT issue, then the 6bed4 layer who addresses all NAT issues should take care of that. But in the IPv6 application, the situation of expiring firewall holes is also commonly understood, and handling it properly is therefore fair to assume from the application, IMHO. Any closed-down path as a result of NAT holes being closed are fairly and squarely interpreted as firewall hole closings at the IPv6 layer. I agree that this should be made explicit in the spec. An application that uses 6bed4 as part of its IPv6-only strategy, like the 0cpm Firmerware, should of course take care of firewall/NAT holes. You are a careful reader, Joost. I like that :) -Rick |
From: Rick v. R. <ri...@op...> - 2011-11-25 20:25:36
|
Hi, > Dysfunctional paths are more difficult, as we cannot know for certain > what timeouts act up in intermediate NAT and firewalls. However, the > assumption made in the spec (and perhaps that needs a few words to > make it explicit) is that the neighbor cache entry would expire before > the path became dysfunt. I've been looking for confirmation that this > is like with ARP, in half a minute, but haven't found it yet. Found it, in RFC 4861. The protocol constants in section 10 sets REACHABLE_TIME 30,000 milliseconds MIN_RANDOM_FACTOR .5 MAX_RANDOM_FACTOR 1.5 Then 6.3.2 defines BaseReachableTime A base value used for computing the random ReachableTime value. Default: REACHABLE_TIME milliseconds. ReachableTime The time a neighbor is considered reachable after receiving a reachability confirmation. This value should be a uniformly distributed random value between MIN_RANDOM_FACTOR and MAX_RANDOM_FACTOR times BaseReachableTime milliseconds. A new random value should be calculated when BaseReachableTime changes (due to Router Advertisements) or at least every few hours even if no Router Advertisements are received. Finally, a "reachbility configuration" in the last definition starts the timer, and 7.3.1 defines that as A neighbor is considered reachable if the node has recently received a confirmation that packets sent recently to the neighbor were received by its IP layer. Positive confirmation can be gathered in two ways: hints from upper-layer protocols that indicate a connection is making "forward progress", or receipt of a Neighbor Advertisement message that is a response to a Neighbor Solicitation message. In short, after a successful Neighbor Discovery exchange, there is a timer that expires between 15 and 45 seconds, causing another round of Neighbor Discovery for the path. This suffices to keep NAT or firewalls open. Note however, that this is only done as long as the path is in use; if the IPv6 application drops silent for too long, and if both sides participate in that, the connection can still disappear; so what I wrote before about needing to keep a firewall hole open by actively communicating every now and then still applies. Do note that an expired entry simply leads to trying again. The only problem might be that 6bed4 has changed its address by then... Cheers, -Rick |
From: Joost L. <vla...@gm...> - 2011-11-25 16:44:26
|
Hi, The spec is very clear on when to forward a packet along which route, after the routes and energy levels have been learned. I'm not quite getting my head around when the peer should be trying to learn a new route and when it shouldn't. For instance on p10 the spec states: * Neighbor Solicitation messages are duplicated over all 6bed4 paths that could work; However the path to the 6bed4 relay service is always available, so one wouldn't expect neighbor solicitations along this path. Also: * The energy level of incoming traffic is determined, and if it has a lower energy level than the current outgoing route, the latter will be updated. Does this mean the record with the lower energy level should always be discarded? In practice: two routes are known for host A, a route via the public v4 address (0x4000) and the relay server (0x8000). A new route is learned via the local LAN (0x2000), should the public route be discarded altogether? Also: when is neighbor solicitation initiated? When a packet mean for IPv6 host A enters the peer program (the host is within the TBD2::/64 range) and no paths other than the relay server are known, how do we treat the packet? Sending out the packet to the relay server and attempting a neighbor solicitation would be the logical step in my opinion, but ofcourse the path should not be learned from that exact moment. On p12 the spec states: Before being able to address an IPv6 target starting with the 6bed4 prefix TBD1::/64, the IPv6 layer would send a Neigbor Solicitation message. The 6bed4 layer would forward that message to the following targets: What should be done with the packet while we wait for a reply from the NS? Dropping it doesn't sound very appealing to me, I'd suggest forwarding it to the relay server while the path is being learned. Also, since there is no three-way handshake for the neighbor paths, when do we consider a path working and when do we consider it dysfunctional? Joost |
From: Joost L. <vla...@gm...> - 2011-11-25 16:14:39
|
Hi, Reading the draft I was wondering why "Energy Level" has been chosen as a label for the "weight" of a route. It feels a bit confusing to me and I would like to suggest using "metric". This term will be more familiar for implementers as it is widely used throughout the networking word for a very similar meaning. Joost |
From: Rick v. R. <ri...@op...> - 2011-11-24 15:32:21
|
Hello, It's good to be discussing the design reasons outside of the spec for 6bed4. (I've learnt from submitting v00 that it is better to leave motivations out of a spec, and stick to the definitions and specifications.) Joost Lek wrote a Dutch version of the following in a private mail to me; it is a useful point in understanding the current work towards draft v01: > I have quickle browsed through draft v1. [...] I do wonder > why you specify that only private addresses may send neighbor > solicition to the local LAN? In practice I often come accross > networks that use public addresses for protected office networks, > this would be ignorant of such networks. Initially I had listed "learned local addresses" in the list for energy level 0x2000, Private LAN and subnet paths, but I removed them to leave only static addresses. I had to think why I did this, but this is the reason: One advantage to that is simplicity. Another is a higher degree of consistency in the energy level found in two communicating peers (which is required to keep any firewall-passthrough open as a result of symmetric use). The thing is... that these networks that you mention are *not* left out; they merely end up at the higher energy level 0x4000, where the IPs are directly connected. In the networks that you have in mind the routing is probably as efficient and NAT-free as energy level 0x2000 in the average RFC 1918 network, but there is no reason to look at that distinction. The distinction between 0x2000 and 0x4000 matter only to RFC 1918 networks. In short, it is simpler and not harmful to classify networks with public IP space at energy level 0x4000. Agreed? -- Do let me know if I've overlooked something! Cheers, -Rick |
From: Rick v. R. <ri...@op...> - 2011-11-24 15:31:34
|
Hi, > The distinction > between 0x2000 and 0x4000 matter only to RFC 1918 networks. Another reason to actually not _want_ to assign energy level 0x2000 to public-IP-spaced LANs: | Note that IPv4 addresses that are publicly routeable never result in | energy level 0x2000, even if they are LAN-routeable. TODO:Could be a | problem when performing NgbDisc over multicast? This TODO is actually the opposite of what we'd want. You do not want to multicast on the LAN with Neighbor Discovery to look for the peer locally; this is only a trick to find an RFC 1918 address that cannot be determined from the IPv6-contained IPv4 address. When publicly routed IPv4 addresses are used on the LAN, then it is possible to address those hosts directly. That is much more efficient than asking every host on the LAN through Multicast. Ciao, -Rick |
From: Rick v. R. <ri...@op...> - 2011-11-24 13:52:23
|
Hello, Attached is the current version (between v00 and v01) of the 6bed4 spec that I've written. It breaks off halfway, in need of further edits, but it has been updated to support coding. Your feedback is warmly welcomed :) Best, -Rick |