Author: lwalter Date: 2007-08-31 23:11:38 +0200 (Fri, 31 Aug 2007) New Revision: 598
Modified: ofw/inetv6/ethernet.fth ofw/inetv6/icmpecho.fth ofw/inetv6/ipfrv6.fth ofw/inetv6/ipv6.fth ofw/inetv6/neighdis.fth Log: Add IPv6 fragmentation/reassembly
Modified: ofw/inetv6/ethernet.fth =================================================================== --- ofw/inetv6/ethernet.fth 2007-08-31 08:05:44 UTC (rev 597) +++ ofw/inetv6/ethernet.fth 2007-08-31 21:11:38 UTC (rev 598) @@ -9,6 +9,7 @@
0 instance value (link-mtu) \ max packet size 0 instance value packet-buffer +0 instance value /packet-buffer
\ Determine the Ethernet address for his-ip-addr instance defer resolve-en-addr ( 'dest-adr type -- 'en-adr type ) @@ -29,8 +30,8 @@ then ;
-: open-link ( -- ) link-mtu alloc-mem to packet-buffer ; -: close-link ( -- ) packet-buffer link-mtu free-mem ; +: open-link ( -- ) link-mtu dup to /packet-buffer alloc-mem to packet-buffer ; +: close-link ( -- ) packet-buffer /packet-buffer free-mem ;
6 constant /e
Modified: ofw/inetv6/icmpecho.fth =================================================================== --- ofw/inetv6/icmpecho.fth 2007-08-31 08:05:44 UTC (rev 597) +++ ofw/inetv6/icmpecho.fth 2007-08-31 21:11:38 UTC (rev 598) @@ -35,8 +35,7 @@ 2dup exchange-ipsv6 ( en-adr,len icmp-adr,len ip-adr,len ) 2over change-typev6 ( en-adr,len icmp-adr,len ip-adr,len ) recompute-icmpv6-checksum ( en-adr,len ) - tuck " write" $call-parent ( len actual ) - <> if ." Network transmit error" cr then + send-raw-packet ( ) ;
: handle-echo-reply ( adr len -- ) 2drop ;
Modified: ofw/inetv6/ipfrv6.fth =================================================================== --- ofw/inetv6/ipfrv6.fth 2007-08-31 08:05:44 UTC (rev 597) +++ ofw/inetv6/ipfrv6.fth 2007-08-31 21:11:38 UTC (rev 598) @@ -7,18 +7,10 @@ 1 sfield ipv6-fh-next-hdr 1 sfield ipv6-fh-len 2 sfield ipv6-fh-frag-offset \ OOOO.OOOO.OOOO.OxxM - \ Os contain the fragment offset; M=1=more fragments + \ Os contain the fragment offset in 8-byte unit + \ M=1=more fragments 4 sfield ipv6-fh-frag-id - \ Maybe followed by zero or more of headers in following order: - \ - Hop-by-Hop Options header - \ - Destination Options header (for first destination, plus destinations in the - \ Routing header) - \ - Routing header - \ - Fragment header - \ - Authentication header - \ - Encapsulating Security Payload header - \ - Destionation Options header (for final destination) - \ - Upper-Layer header + 0 sfield ipv6-fh-data constant /ipv6-frag-hdr
instance variable frag-id @@ -34,14 +26,11 @@ : send-ip-packet ( adr len protocol -- ) 3drop ; [then]
-: max-ipv6-payload ( -- n ) - max-link-payload /ipv6-header - - h# ffff.fff8 and -; : max-ipv6-fragment ( -- n ) max-link-payload /ipv6-header - /ipv6-frag-hdr - h# ffff.fff8 and ; +: max-ipv6-payload ( -- n ) max-ipv6-fragment /ipv6-frag-hdr + ;
headerless : (send-ipv6-packet) ( adr len protocol -- ) @@ -64,15 +53,15 @@ 0 value fadr \ fragment address
: send-ipv6-fragment ( offset -- ) - >r fadr ( fadr ) ( R: offset ) - olen r@ - max-ipv6-fragment min ( fadr flen ) ( R: offset ) - 2dup oaddr r@ + -rot move ( fadr flen ) ( R: offset ) - fadr set-struct ( fadr flen ) ( R: offset ) + >r fadr dup set-struct ( fadr ) ( R: offset ) + olen max-ipv6-fragment min ( fadr flen ) ( R: offset ) + oaddr r@ + ipv6-fh-data 2 pick move ( fadr flen ) ( R: offset ) oprotocol ipv6-fh-next-hdr xc! \ Next header in fragment header 0 ipv6-fh-len xc! \ Length of header in units of 8 bytes - 1 - frag-id ipv6-fh-frag-id xl! \ Fragment id - dup r@ + olen < 1 and ( fadr flen more? ) ( R: offset ) - r> 3 << or ipv6-fh-frag-offset xw! ( fadr flen ) + frag-id @ ipv6-fh-frag-id xl! \ Fragment id + dup olen u< 1 and ( fadr flen more? ) ( R: offset ) + r> or ipv6-fh-frag-offset xw! ( fadr flen ) + olen over - to olen ( fadr flen ) /ipv6-frag-hdr + ( fadr flen' ) IP_HDR_FRAGMENT (send-ipv6-packet) ( ) ; @@ -83,9 +72,9 @@ else 1 frag-id +! over max-ipv6-fragment /mod swap 0> if 1+ then ( adr len protocol #frags ) - >r to oprotocol to olen to oaddr r> ( #frags ) + >r to oprotocol to olen to oaddr r> ( #frags ) max-ipv6-payload allocate-ipv6 to fadr ( #frags ) - ( #frags ) 0 do ( ) + ( #frags ) 0 ?do ( ) i max-ipv6-fragment * send-ipv6-fragment loop fadr max-ipv6-payload free-ipv6 @@ -97,12 +86,328 @@ ;
\ ********************************************************************************* +\ Send fully prepared ethernet packet +\ ( For ECHO reply use where ethernet and IP headers are complete. ) +\ ********************************************************************************* + +\ For going between the two headers; used as a pair +: ipv6-struct ( -- ) /ipv6-header negate +struct ; +: frag-struct ( -- ) /ipv6-header +struct ; + +: alloc-fadr ( adr -- ) + dup link-mtu alloc-mem dup to fadr ( adr adr fadr ) + /ether-header /ipv6-header + move ( adr ) + /ether-header + set-struct ( ) + ipv6-length xw@ to olen + ipv6-next-hdr c@ to oprotocol + + \ Initialize static part of IPv6 header + fadr /ether-header + set-struct + IP_HDR_FRAGMENT ipv6-next-hdr xc! + + \ Initialize static part of fragment header + frag-struct + oprotocol ipv6-fh-next-hdr xc! + 0 ipv6-fh-len xc! + frag-id @ ipv6-fh-frag-id xl! + ipv6-struct +; + +: (send-raw-packet) ( adr len -- ) + tuck " write" $call-parent + <> if ." Network transmit error" cr then +; +: send-raw-fragment ( offset -- ) + >r ( ) ( R: offset ) + olen max-ipv6-fragment min ( flen ) ( R: offset ) + dup /ipv6-frag-hdr + ipv6-length xw! ( flen ) ( R: offset ) + frag-struct ( flen ) ( R: offset ) + dup olen u< 1 and ( flen more? ) ( R: offset ) + r@ or ipv6-fh-frag-offset xw! ( flen ) ( R: offset ) + oaddr r> + ipv6-fh-data 2 pick move ( flen ) + ipv6-struct ( flen ) + olen over - to olen ( flen ) + /ipv6-frag-hdr + /ipv6-header + /ether-header + ( len ) + fadr swap (send-raw-packet) ( ) +; +: send-raw-packet ( adr len -- ) + dup link-mtu <= if + (send-raw-packet) + else + 1 frag-id +! ( adr len ) + over alloc-fadr ( adr len ) + /ether-header /ipv6-header + /string ( content-adr,len ) + swap to oaddr ( content-len ) + max-ipv6-fragment /mod swap 0> if 1+ then ( #frags ) + ( #frags ) 0 ?do + i max-ipv6-fragment * send-raw-fragment + loop + fadr link-mtu free-mem + then +; + +\ ********************************************************************************* \ Receive IP packet \ *********************************************************************************
+list: ipv6list +listnode + /ether-header field >ipv6-ether \ Beginning of ethernet header + 0 field >ipv6-header \ Beginning of IPv6 header + 4 field >ipv6-version + 2 field >ipv6-len \ Total length of reassembled data + 1 field >ipv6-protocol + 1 field >ipv6-hop-limit + /ipv6 field >ipv6-source-addr + /ipv6 field >ipv6-dest-addr \ End of IPv6 header + /n field >ipv6-dghead \ Head of list of IPv6 datagrams + /n field >ipv6-dgtail \ Tail of list of IPv6 datagrams + /n field >ipv6-timer \ Timeout value in ms + /n field >ipv6-rangelist \ Pointer to range info + /n field >ipv6-id \ Fragment id +nodetype: ipv6node \ List of IPv6 reassembly in process + +0 ipv6list ! +0 ipv6node ! + +struct + /n field >dgv6-adr \ Pointer to content of fragmented data + /n field >dgv6-len \ Length of fragmented data + /n field >dgv6-offset \ Offset of fragmented data + /n field >dgv6-next +constant /dgv6list + +[ifndef] include-ipv4 +struct + /n field >rl-begin + /n field >rl-end + /n field >rl-next + /n field >rl-prev +constant /rangelist +[then] + +0 instance value reassembledv6-adr +0 instance value reassembledv6-len \ ihl + data len +d# 60 d# 1000 * constant tlbv6 \ 60 seconds for initial timer setting + +: ipv6-id=? ( node -- id=? ) + >r ( ) ( R: node ) + frag-struct ( ) ( R: node ) + ipv6-fh-next-hdr c@ ipv6-fh-frag-id xl@ ( next-hdr frag-id ) ( R: node ) + ipv6-struct ( next-hdr frag-id ) ( R: node ) + r@ >ipv6-id @ <> if r> 2drop false exit then ( next-hdr ) ( R: node ) + r@ >ipv6-protocol c@ <> if r> drop false exit then ( ) ( R: node ) + r@ >ipv6-source-addr ipv6-source-addr ipv6= not if r> drop false exit then + r> >ipv6-dest-addr ipv6-dest-addr ipv6= +; + +: find-ipv6? ( -- prev-node this-node | 0 ) + ipv6list ['] ipv6-id=? find-node +; + +: alloc-ipv6 ( last-node -- node ) + ipv6node allocate-node tuck swap insert-after + >r + the-struct /ether-header - r@ >ipv6-ether /ipv6-header /ether-header + move + 0 r@ >ipv6-dghead ! + 0 r@ >ipv6-dgtail ! + get-msecs tlbv6 + r@ >ipv6-timer ! + 0 r@ >ipv6-len xw! + 0 r@ >ipv6-rangelist ! + frag-struct + ipv6-fh-frag-id xl@ r@ >ipv6-id ! + ipv6-fh-next-hdr c@ r@ >ipv6-protocol xc! + ipv6-struct + r> +; + +: save-ipv6 ( node -- ) + >r + ipv6-length xw@ /ipv6-frag-hdr - dup alloc-mem ( len this-dg ) ( R: node ) + + frag-struct + 2dup swap the-struct /ipv6-frag-hdr + -rot move ( len this-dg ) ( R: node ) + ipv6-fh-frag-offset xw@ ( len this-dg offset ) ( R: node ) + ipv6-struct ( len this-dg offset ) ( R: node ) + dup h# fff8 and swap 1 and 0= if \ Last fragment + ipv6-length xw@ /ipv6-frag-hdr - over + ( len this-dg offset ) ( R: node ) + r@ >ipv6-len xw! + then + + /dgv6list alloc-mem ( len this-dg offset this-dglist ) ( R: node ) + tuck >dgv6-offset ! ( len this-dg this-dglist ) ( R: node ) + tuck >dgv6-adr ! ( len this-dglist ) ( R: node ) + tuck >dgv6-len ! ( this-dglist ) ( R: node ) + 0 over >dgv6-next ! ( this-dglist ) ( R: node ) + + r@ >ipv6-dghead @ 0= if dup r@ >ipv6-dghead ! then ( this-dglist ) ( R: node ) + r@ >ipv6-dgtail @ ?dup 0<> if >dgv6-next over swap ! then ( this-dglist ) ( R: node ) + r> >ipv6-dgtail ! ( ) +; + +: free-dgv6 ( dg -- ) + begin ?dup while ( 'dg ) + dup >dgv6-adr @ over >dgv6-len @ free-mem ( 'dg ) + dup >dgv6-next @ ( 'dg 'dg-next ) + swap /dgv6list free-mem ( 'dg-nest ) + repeat ( ) +; + +[ifndef] include-ipv4 +: free-rangelist ( rl -- ) + begin ?dup while ( rl ) + dup >rl-next @ swap /rangelist free-mem ( rl-next ) + repeat ( ) +; +[then] + +: free-ipv6node ( prev -- ) + delete-after + dup ipv6node free-node + dup >ipv6-dghead @ free-dgv6 + >ipv6-rangelist @ free-rangelist +; + +: free-ipv6list ( -- ) + find-ipv6? if free-ipv6node else drop then +; + +: ipv6-timeout? ( node -- flag ) >ipv6-timer @ get-msecs <= ; + +: process-timeoutv6? ( -- flag ) + ipv6list ['] ipv6-timeout? find-node if free-ipv6node true else drop false then +; + +[ifndef] include-ipv4 +0 value rlb +0 value rle +0 value last-rl + +: create-rangelist ( -- rl ) + /rangelist alloc-mem ( rl ) + rle over >rl-end ! ( rl ) + rlb over >rl-begin ! ( rl ) +; +[then] + +: insert-before-rangelistv6 ( node rl -- ) + create-rangelist >r ( node rl ) + dup r@ >rl-next ! ( node rl ) + dup >rl-prev @ dup r@ >rl-prev ! ( node rl rl-prev ) + ?dup 0<> if >rl-next r@ swap ! then ( node rl ) + r@ over >rl-prev ! ( node rl ) + r> -rot ( new node rl ) + over >ipv6-rangelist @ = if >ipv6-rangelist ! else 2drop then +; + +: insert-endof-rangelistv6 ( node rl -- ) + create-rangelist ( node rl new ) + 0 over >rl-next ! ( node rl new ) + 2dup >rl-prev ! ( node rl new ) + -rot tuck ( new rl node rl ) + 0= if nip >ipv6-rangelist ! else drop >rl-next ! then +; + +\ New range = b:e +\ Current node = x:y +\ if e<x-1, add node to front and exit +\ if b>y+1, goto examine next node +\ if b<x, x=b +\ if e>y, y=e and exit +\ if all the nodes have been examined, add node to end and exit +\ +: (update-rangelistv6) ( ofs len node -- ) + -rot over + 1- to rle to rlb ( node ) + 0 to last-rl ( node ) + dup >ipv6-rangelist @ ( node rl ) + begin ?dup while + >r ( node ) + rle r@ >rl-begin @ 1- < if r> insert-before-rangelistv6 exit then + rlb r@ >rl-end @ 1+ <= if ( node ) + rlb r@ >rl-begin @ < if rlb r@ >rl-begin ! then + rle r@ >rl-end @ > if rle r@ >rl-end ! then + r> 2drop + exit + then + r@ to last-rl ( node ) + r> >rl-next @ ( node rl ) + repeat ( node ) + last-rl insert-endof-rangelistv6 +; + +: update-rangelistv6 ( node -- ) + frag-struct + ipv6-fh-frag-offset xw@ h# fff8 and ( node ofs ) + ipv6-struct + ipv6-length xw@ /ipv6-frag-hdr - ( node ofs len ) + rot (update-rangelistv6) +; + +: rl-complete? ( rl -- complete? ) + 0 swap ( 0 rl ) + begin ( e rl ) + 2dup >rl-begin @ 1- < ( e rl gap? ) + if 2drop false exit then ( e rl ) + dup >rl-end @ rot max swap ( e' rl ) + >rl-next @ ?dup 0= ( e' rl-next ) + until ( e' ) + drop true +; + +: ipv6-done? ( node -- done? ) + dup >ipv6-len xw@ 0= if drop false exit then + >ipv6-rangelist @ rl-complete? +; + +: (reassemble-ipv6) ( adr dg -- ) + begin ?dup while ( adr dg ) + 2dup >dgv6-offset @ + ( adr dg dst ) + over >dgv6-adr @ swap ( adr dg src dst ) + 2 pick >dgv6-len @ move ( adr dg ) + >dgv6-next @ ( adr dg-next ) + repeat drop ( ) +; + +: reassemble-ipv6 ( node -- ip-adr,len ) + >r + r@ >ipv6-len xw@ ( dlen ) ( R: node ) + /ipv6-header + /ether-header + ( rlen ) ( R: node ) + dup to reassembledv6-len ( rlen ) ( R: node ) + alloc-mem dup to reassembledv6-adr ( radr ) ( R: node ) + r@ >ipv6-ether swap /ipv6-header /ether-header + move \ Copy IPv6 header content + reassembledv6-adr /ipv6-header + /ether-header + ( content-adr ) ( R: node ) + r> >ipv6-dghead @ (reassemble-ipv6) ( ) + reassembledv6-adr reassembledv6-len /ether-header /string ( ip-adr,len ) + free-ipv6list ( ip-adr,len ) +; + +: process-datagramv6 ( node -- false | ip-adr,len true) + dup save-ipv6 ( node ) + dup update-rangelistv6 ( node ) + dup ipv6-done? if ( node ) + reassemble-ipv6 ( ip-adr,len ) + true ( ip-adr,len true ) + else ( node ) + drop false ( false ) + then +; + +: process-done-ipv6 ( -- ) + reassembledv6-len 0> if + reassembledv6-adr reassembledv6-len free-mem + 0 to reassembledv6-adr 0 to reassembledv6-len + then +; + +: get-done-ipv6? ( -- false | ip-adr,len true ) + find-ipv6? ?dup if nip else alloc-ipv6 then + process-datagramv6 +; + defer handle-icmpv6 ( contents-adr,len protocol -- ) ' 3drop to handle-icmpv6
[ifndef] include-ipv4 +: process-done-ip ( -- ) ; : process-timeout? ( -- flag ) false ; : process-ipv4-packet ( adr len type -- flag ) 3drop ." Discarding IPv4 packet" cr false @@ -110,29 +415,48 @@ : ip-payload ( len -- adr len' ) .ipv4-not-supported ; [then]
+: process-timeout? ( -- flag ) + use-ipv6? if process-timeoutv6? else process-timeout? then +; + : process-ipv6-packet ( adr len type -- false | contents-adr,len true ) - \ XXX Not complete. Need to process additional headers and fragmentation. - \ XXX Assume no additional headers for now. + \ XXX Assume no additional headers other than fragmentation header for now. + nip swap ( type adr ) + dup set-struct to last-ipv6-packet ( type )
- nip swap ( type adr ) - dup set-struct to last-ip-packet ( type ) - ipv6-addr-match? if ( type ) - ipv6-next-hdr c@ dup >r = dup if ( type=? ) ( R: next-hdr ) - ipv6-payload rot ( contents-adr,len true ) ( R: next-hdr ) - then ( false | contents-adr,len true ) ( R: next-hdr ) - r> IP_HDR_ICMPV6 = if ( false | contents-adr,len true ) - ipv6-payload IP_HDR_ICMPV6 handle-icmpv6 \ Handle ICMPv6 packets + \ If IPv6 packet is not for me, exit + ipv6-addr-match? not if ( type ) + drop ipv6-payload handle-other-ipv6 ( ) + false exit \ Got an packet not for me + then ( type ) + + \ If IPv6 packet is a fragment, reassemble packet if possible + ipv6-next-hdr c@ IP_HDR_FRAGMENT = if ( type ) + get-done-ipv6? if ( type false | ip-adr,len true ) + drop dup set-struct to last-ipv6-packet \ Fragment reassembly complete else - dup not if ipv6-payload ipv6-next-hdr c@ handle-ipv6 then + drop false exit \ Fragment reassembly incomplete + then + then + + \ By now, we have a complete IPv6 packet. Is it what we're waiting for? + ipv6-next-hdr c@ >r ( type ) ( R: next-hdr ) + r@ = dup if ( type=next-hdr? ) ( R: next-hdr ) + ipv6-payload rot ( contents-adr,len true ) ( R: next-hdr ) + then ( false | contents-adr,len true ) ( R: next-hdr ) + \ Is it an ICMPv6 packet? + r> IP_HDR_ICMPV6 = if ( false | contents-adr,len true ) + ipv6-payload IP_HDR_ICMPV6 handle-icmpv6 \ Handle ICMPv6 packets + else + dup not if ipv6-payload ipv6-next-hdr c@ handle-ipv6 then \ Handle other unexpected packets - then ( false | contents-adr,len true ) - else - drop ipv6-payload handle-other-ipv6 \ Handle packets for other address - false ( false ) then ( false | contents-adr,len true ) ;
: receive-ip-packet ( type -- true | contents-adr,len false ) + process-done-ip + process-done-ipv6 + begin use-ipv6? if IPV6_TYPE else IP_TYPE then receive-ethernet-packet ( type [ip-adr,len] flag )
Modified: ofw/inetv6/ipv6.fth =================================================================== --- ofw/inetv6/ipv6.fth 2007-08-31 08:05:44 UTC (rev 597) +++ ofw/inetv6/ipv6.fth 2007-08-31 21:11:38 UTC (rev 598) @@ -31,7 +31,16 @@ 1 sfield ipv6-hop-limit /ipv6 sfield ipv6-source-addr /ipv6 sfield ipv6-dest-addr - \ There maybe extension headers here. + \ Maybe followed by zero or more of headers in following order: + \ - Hop-by-Hop Options header + \ - Destination Options header (for first destination, plus destinations in the + \ Routing header) + \ - Routing header + \ - Fragment header + \ - Authentication header + \ - Encapsulating Security Payload header + \ - Destionation Options header (for final destination) + \ - Upper-Layer header constant /ipv6-header
\ Values of ipv6-next-hdr @@ -186,9 +195,7 @@ ; : .name-server-ipv6 ( -- ) ." DNS IPv6: " name-server-ipv6 .ipv6 ;
-[ifndef] include-ipv4 -0 instance value last-ip-packet -[then] +0 instance value last-ipv6-packet
headers : (set-dest-ipv6) ( buf -- ) @@ -208,7 +215,7 @@ ;
: lock-ipv6-address ( -- ) - the-struct >r last-ip-packet set-struct + the-struct >r last-ipv6-packet set-struct \ Don't change his-ipv6-addr for booting over gateway use-routerv6? if \ booting over a gateway. bootnet-debug if indent ." Using router" cr then @@ -253,7 +260,12 @@ : ipv6-payload ( -- adr len ) the-struct /ipv6-header + ipv6-length xw@ ;
\ Skip checking his-ipv6-addr if it is an ICMPv6 packet which may come from anywhere. -: check-his-ipv6-addr? ( -- flag ) ipv6-next-hdr c@ IP_HDR_ICMPV6 <> ; +\ XXX Assume <IPv6 header> [ <fragment header> ] <data> +: check-his-ipv6-addr? ( -- flag ) + ipv6-next-hdr c@ IP_HDR_ICMPV6 = if false exit then + ipv6-next-hdr c@ IP_HDR_FRAGMENT <> if true exit then + the-struct /ipv6-header + c@ IP_HDR_ICMPV6 <> +; : ipv6-addr-match? ( -- flag ) check-his-ipv6-addr? if his-ipv6-addr his-ipv6-addr-mc? 0= if
Modified: ofw/inetv6/neighdis.fth =================================================================== --- ofw/inetv6/neighdis.fth 2007-08-31 08:05:44 UTC (rev 597) +++ ofw/inetv6/neighdis.fth 2007-08-31 21:11:38 UTC (rev 598) @@ -3,9 +3,9 @@
headerless
-d# 200 constant ND_TIMEOUT \ Neighbor discovery timeout (ms) -d# 200 constant DAD_TIMEOUT \ Duplicate Address Detection timeout (ms) -d# 500 constant RD_TIMEOUT \ Router Discovery timeout (ms) +d# 200 constant ND_TIMEOUT \ Neighbor discovery timeout (ms) +d# 200 constant DAD_TIMEOUT \ Duplicate Address Detection timeout (ms) +d# 2000 constant RD_TIMEOUT \ Router Discovery timeout (ms)
" stateless" d# 40 config-string ipv6-address \ leave room \ " dhcp" ' ipv6-address set-config-string-default @@ -141,7 +141,7 @@ over 8 + be-l@ to prefix-lifetime \ XXX lifetime over d# 16 + my-prefix copy-ipv6-addr \ Prefix endof - 5 of over 4 + be-l@ to (link-mtu) endof \ MTU option + 5 of over 4 + be-l@ link-mtu min to (link-mtu) endof \ MTU option d# 25 of over 8 + name-server-ipv6 copy-ipv6-addr endof \ RDNSS option endcase over 1+ c@ 8 * /string @@ -190,7 +190,6 @@
['] 4drop to icmpv6-err-callback-xt ['] 2drop to icmpv6-info-callback-xt - unknown-ipv6-addr name-server-ipv6 copy-ipv6-addr
discover-me discover-router @@ -212,6 +211,7 @@ ;
: close ( -- ) + process-done-ipv6 [ifdef] include-ipv4 close [else] @@ -241,6 +241,7 @@ true to use-ipv6? set-mc-hash if close false exit then ['] (resolve-en-addrv6) to resolve-en-addr + unknown-ipv6-addr name-server-ipv6 copy-ipv6-addr configure-ipv6 s-all-ipv6 setup-ip-attr