Classless-Routes not being added by dhcp-client

search tag # rextended starlink classless route

Summary of the progress made so far:

By this setup on MikroTik DHCP Server I can simulate exactly what DHCP Server on Starlink device option 121 Classless-Route send to MikroTik DHCP Client:

/ip dhcp-server option
add code=121 name=Classless-Route value=0x20C0A8640100000000202278FFF40000000000647FFF05
/ip dhcp-server network
add ... dhcp-option=Classless-Route ...

Equivalent to:
Classless-Route = 192.168.100.1/32->0.0.0.0,34.120.255.244/32->0.0.0.0,0.0.0.0/0->100.127.255.5


With another device I can read Classless-Route passed and store it with DHCP Client interface name on two global variables:

/ip dhcp-client
... script=":global dhcpClientIF \$interface ; :global dhcpClientCR (\$\"lease-options\"->\"121\")" ...

For better readability:
:global dhcpClientIF $interface
:global dhcpClientCR ($“lease-options”->“121”)

and on global variables I obtain:

[rextended@MATRIX] /system script environment> pri
 # NAME               VALUE
0 dhcpClientIF      ether1
1 dhcpClientCR        \C0\A8d\01\00\00\00\00 "x\FF\F4\00\00\00\00\00d\7F\FF\05
spaces!!!------------^----------------------^

Space, d (as d letter not as 0xD exadecimal value), " and x are presents because on print Mikrotik escape the characters than can not display.
For example Space is present because hex value 0x20 (subnet /32) on ASCII correspond to Space characters
While >d< are for \64, the 100 of first IP address, >"< are for \22, the “34” of second IP adress, and >x< are for \78, the 120 of second IP address.


Later I have create two function.

The first called “chr2int” read one char passed to the function and return the corresponding decimal value.
For example, passing one character, like “\C0” return 192
The char can be any single char and return integer value from 0 to 255

The second called “str2ip” convert one string of 4 chars or less, using previous function, to dotted IP.
passing one 4 charecters string, like “\C0\A8\64\01” return “192.168.100.1”
If the length of the imput string is more than 4, exceeding characters are ignored
If the length of the imput string is less than 4, add carryng .0
passing one 3 charecters string, like “\C0\A8\64” return “192.168.100.0”
passing one 2 charecters string, like “\C0\A8” return “192.168.0.0”
passing one 1 charecters string, like “\C0” return “192.0.0.0”
passing one empty string, like “” value return “0.0.0.0”
Passing one other type of variable is converted first (internally by RouterOS) to string and processed as before.

How classless route work.
All routes are subsequently one by one without any form of division
Now I have understand how to split classless route raw value on single routes
Rules:

  1. first Byte is always the subnet and is always between hex \00 and \20 (dec 0 to 32)
  2. only relevant IP part of the ip / ip-prefix are provided, 5 cases are possible:
    if subnetis are /0 no other char/hex value for IP are present and it mean “all IPv4 space” (\00 = 0.0.0.0/0)
    and next four char/hex value for IP are used (\20\0A\0A\0A\0A = 0.0.0.0/0 default gateway 10.10.10.10)
    is a full IPv4 CLASSLESS IP (is whiy are called classles route…)
    if subnet is from /1 to /8 only one char/hex value for IP are present (\08\0A = 10/8 = 10.0.0.0/8)
    if subnet is from /9 to /16 only two char/hex value for IP are present (\10\0A\0A = 10.10/16 = 10.10.0.0/16)
    if subnet is from /17 to /24 only three char/hex value for IP are present (\18\0A\0A\0A = 10.10.10/24 = 10.10.10.0/24)
    if subnet is from /25 to /32 all four char/hex value for IP are present (\20\0A\0A\0A\0A = 10.10.10.10/32)

0x20C0A8640100000000202278FFF40000000000647FFF05
assuming dhcp-client.interface.name = Starlink

start reading:
first char \20 = subnet mask /32 (hex 20 = 32 dec)
the following 4 chars, because the subnet mask are /32 “\C0\A8\64\01” = 192.168.100.1
the following 4 chars, because now are set the classless route “\00\00\00\00” = 0.0.0.0
Only on this case, as RFC specify, when the dst ip is 0.0.0.0, really this it means “this interface” intending on what interface the DHCP Client is set
MikroTik do not understand this (as RFC say, if you do not understand this, ignore only this)
All of this means that the routes is not really 192.168.100.1/32->0.0.0.0 but must be intended as 192.168.100.1/32->Starlink

following the read of data:
“\20” subnet /32
“\22\78\FF\F4” 34.120.255.244
“\00\00\00\00” 0.0.0.0
34.120.255.244/32->Starlink


reading follow value “\00” is intended /0 and is for default gateway for all IP /0 (0.0.0.0/0)
“\64\7F\FF\05” 100.127.255.5
0.0.0.0/0->100.127.255.5


At this point, after all considerations, what I need to do to finish:

x) Create the option for 3-only / 2-only / 1-only character and empty / nil / nothing / invalid values for str2dotIP Done on 2021/06/17

x) Create one procedure that follows the raw classless-route value than understand and splits the routes as wrote before. Done on 2021/08/03

Added 2021/06/17:
saving the result as couple of array of values like
“192.168.100.1/32;0.0.0.0 , 34.120.255.244/32;0.0.0.0 , 0.0.0.0/0;100.127.255.5”
for be processed from following script
Done on 2021/08/03

Added 2021/08/03:
Now finally I obtain after split:
192.168.100.1/32->0.0.0.0
34.120.255.244/32->0.0.0.0
0.0.0.0/0->100.127.255.5

2021/08/03 What is missing now is:

  1. Create the DHCP-Client script for add classless-route to routung table and remove them when DHCP-Client are disabled / not renowed / released