Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| docs:guide-developer:network-scripting [2021/01/09 13:23] – Add error codes help lemoer | docs:guide-developer:network-scripting [2023/07/19 09:34] (current) – [Get WAN gateway for unmanaged default route] add vgaetera | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== Network scripts ====== | ====== Network scripts ====== | ||
| - | + | netifd can (probably) bring up a wired, static ip configuration without shell scripts. | |
| - | netifd can (probably) bring up a wired, static ip configuration without shell scripts. For everything else (PPPoE or 3G) it needs //protocol handlers// implemented as sets of shell functions. | + | For everything else (PPPoE or 3G) it needs //protocol handlers// implemented as sets of shell functions. |
| ===== Writing protocol handlers ===== | ===== Writing protocol handlers ===== | ||
| - | + | Each protocol handler is a shell script in ''/ | |
| - | Each protocol handler is a shell script in ''/ | + | It is run (or maybe sourced) when netifd daemon starts. |
| + | Changes made to the scripts do not take effect until netifd restarts. | ||
| + | The name of the file usually matches '' | ||
| To be able to access the network functions, the script needs to include the necessary shell scripts at the beginning: | To be able to access the network functions, the script needs to include the necessary shell scripts at the beginning: | ||
| Line 26: | Line 28: | ||
| ==== init_config ==== | ==== init_config ==== | ||
| - | + | The main purpose of this function is to let netifd know which parameters does this protocol have. | |
| - | The main purpose of this function is to let netifd know which parameters does this protocol have. These parameters then can be stored in ''/ | + | These parameters then can be stored in ''/ |
| <code bash> | <code bash> | ||
| proto_protocolname_init_config() { | proto_protocolname_init_config() { | ||
| - | | + | proto_config_add_string " |
| - | proto_config_add_int " | + | proto_config_add_int " |
| - | proto_config_add_boolean " | + | proto_config_add_boolean " |
| - | ... | + | ... |
| } | } | ||
| </ | </ | ||
| ==== Setup ==== | ==== Setup ==== | ||
| - | |||
| The setup procedure implements the actual protocol specifc configuration logic and interface bringup. | The setup procedure implements the actual protocol specifc configuration logic and interface bringup. | ||
| Line 49: | Line 50: | ||
| <code bash> | <code bash> | ||
| proto_protocolname_setup() { | proto_protocolname_setup() { | ||
| - | | + | local config=" |
| - | # set up the interface | + | # set up the interface |
| } | } | ||
| </ | </ | ||
| Line 56: | Line 57: | ||
| This function must be implemented by any protocol backend. | This function must be implemented by any protocol backend. | ||
| - | There' | + | There' |
| + | If '' | ||
| + | It waits for '' | ||
| If '' | If '' | ||
| Line 69: | Line 72: | ||
| </ | </ | ||
| - | However, this only works once. If someone called '' | + | However, this only works once. |
| + | If someone called '' | ||
| ==== Teardown ==== | ==== Teardown ==== | ||
| - | + | Protocols that need special shutdown handling, for example to kill associated daemons, may implement a stop procedure. | |
| - | Protocols that need special shutdown handling, for example to kill associated daemons, may implement | + | This procedure is called when an interface is brought down before the associated UCI state is cleared. |
| - | a stop procedure. This procedure is called when an interface is brought down before the associated UCI | + | |
| - | state is cleared. | + | |
| The function is called when we do '' | The function is called when we do '' | ||
| Line 85: | Line 87: | ||
| <code bash> | <code bash> | ||
| proto_protocolname_teardown() { | proto_protocolname_teardown() { | ||
| - | | + | local config=" |
| - | local iface=" | + | local iface=" |
| - | # tear down the interface | + | # tear down the interface |
| } | } | ||
| </ | </ | ||
| Line 94: | Line 96: | ||
| ==== Coldplug ==== | ==== Coldplug ==== | ||
| - | |||
| By default, only interfaces present in ''/ | By default, only interfaces present in ''/ | ||
| Protocols which use virtual interfaces must set two variables at the beginning of init_config. | Protocols which use virtual interfaces must set two variables at the beginning of init_config. | ||
| Line 100: | Line 101: | ||
| <code bash> | <code bash> | ||
| proto_protocolname_init_config() { | proto_protocolname_init_config() { | ||
| - | | + | no_device=1 |
| - | available=1 | + | available=1 |
| - | ... | + | ... |
| } | } | ||
| </ | </ | ||
| ==== Debugging ==== | ==== Debugging ==== | ||
| - | |||
| * STDERR in protos is redirected to the syslog. '' | * STDERR in protos is redirected to the syslog. '' | ||
| * As '' | * As '' | ||
| * There is a pending patch: https:// | * There is a pending patch: https:// | ||
| - | ==== Available | + | ==== Available |
| - | + | Flags can be added to a proto handler in '' | |
| - | Flags can be added to a proto handler in '' | + | The information about all loaded protocols can be obtained by calling //ubus call network get_proto_handlers// |
| ^ Name ^ Name in //ubus call network get_proto_handlers// | ^ Name ^ Name in //ubus call network get_proto_handlers// | ||
| | no_device | no_device | The interface does not have a lower device. <color # | | no_device | no_device | The interface does not have a lower device. <color # | ||
| - | | | immediate | <color # | + | | | immediate | <color # |
| | available | init_available | Initialize the device directly as available, without the device specified by ifname being present <color # | | available | init_available | Initialize the device directly as available, without the device specified by ifname being present <color # | ||
| | renew_handler | renew_available | Has a renew handler, which can be called. <color # | | renew_handler | renew_available | Has a renew handler, which can be called. <color # | ||
| Line 125: | Line 125: | ||
| | no_proto_task | no_task | <color # | | no_proto_task | no_task | <color # | ||
| - | + | ==== Error codes ==== | |
| - | ==== Error Codes ==== | + | If errors for interfaces occur, the json object in //ifstatus interfacename// |
| - | + | If there are no errors, this attribute is not existing. | |
| - | If errors for interfaces occur, the json object in //ifstatus interfacename// | + | |
| ^ CODE ^ Meaning ^ | ^ CODE ^ Meaning ^ | ||
| | NO_DEVICE | The configured device in ifname is not found. | | | NO_DEVICE | The configured device in ifname is not found. | | ||
| - | | DEVICE_CLAIM_FAILED | <color # | + | | DEVICE_CLAIM_FAILED | One of the reasons for this is, that the device configured by ifname does not exist. Usually this would result in NO_DEVICE as the device is only claimed when it is available. However when the proto flags // |
| | SETUP_FAILED | <color # | | SETUP_FAILED | <color # | ||
| + | Custom error codes can be thrown from the proto scripts aswell. | ||
| + | This is done via '' | ||
| ==== How does it work internally? ==== | ==== How does it work internally? ==== | ||
| - | |||
| <code bash> | <code bash> | ||
| init_proto $proto $cmd $interface $data $ifname | init_proto $proto $cmd $interface $data $ifname | ||
| Line 155: | Line 155: | ||
| Otherwise the script will fail with something like: | Otherwise the script will fail with something like: | ||
| * '' | * '' | ||
| - | |||
| ===== API ===== | ===== API ===== | ||
| - | |||
| The following functions are defined in ''/ | The following functions are defined in ''/ | ||
| ==== netifd functions ==== | ==== netifd functions ==== | ||
| - | |||
| === initialization functions === | === initialization functions === | ||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| - | ---- | + | === notification functions === |
| + | Note: some of these function exit immediately. | ||
| + | These functions are dispatched to ubus and arrive [[commit>? | ||
| - | ** '' | + | |
| - | ---- | + | |
| + | | ||
| + | | ||
| + | * '' | ||
| - | ** '' | + | We can start a daemon that maintains the connection asynchronously by calling |
| - | ---- | + | Netifd remembers its pid. |
| + | It can be killed manually by calling '' | ||
| + | Netifd can automatically kill it, when the profile stopped. | ||
| - | ** '' | + | * '' |
| - | ---- | + | |
| - | ** '' | + | It seems to avoid race conditions in protos. |
| - | ---- | + | We can register the following type of dependencies by calling: |
| + | | ||
| + | | ||
| + | * (maybe more?) | ||
| - | ** '' | + | Only if '' |
| - | ---- | + | So we need another proto to be completed, we can use this here. |
| - | === notification functions === | + | From some observations I think it looks like technically the '' |
| + | However, currently I do not know where to find the source code, so this is only a vague idea of what happens. | ||
| - | Note: some of these function exit immediately. | + | * '' |
| + | * '' | ||
| - | ---- | + | ==== common functions ==== |
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| - | ** '' | + | ===== Examples ===== |
| - | ---- | + | [[https:// |
| + | Replace automatic WAN detection with explicit interface definition if necessary. | ||
| - | ** '' | + | ==== Get LAN address ==== |
| - | ---- | + | <code bash> |
| + | # Runtime configuration | ||
| + | NET_IF=" | ||
| + | . / | ||
| + | network_flush_cache | ||
| + | network_get_ipaddr NET_ADDR "${NET_IF}" | ||
| + | network_get_ipaddr6 NET_ADDR6 "${NET_IF}" | ||
| + | echo " | ||
| + | echo "${NET_ADDR6}" | ||
| + | </ | ||
| - | ** '' | + | ==== Get WAN interface |
| - | ---- | + | <code bash> |
| + | # Runtime configuration | ||
| + | . / | ||
| + | network_flush_cache | ||
| + | network_find_wan NET_IF | ||
| + | network_find_wan6 NET_IF6 | ||
| + | echo " | ||
| + | echo "${NET_IF6}" | ||
| + | </ | ||
| - | ** '' | + | ==== Get WAN L2 device ==== |
| - | ---- | + | <code bash> |
| + | # Runtime configuration | ||
| + | . / | ||
| + | network_flush_cache | ||
| + | network_find_wan NET_IF | ||
| + | network_find_wan6 NET_IF6 | ||
| + | network_get_physdev NET_L2D "${NET_IF}" | ||
| + | network_get_physdev NET_L2D6 "${NET_IF6}" | ||
| + | echo "${NET_L2D}" | ||
| + | echo "${NET_L2D6}" | ||
| + | </ | ||
| - | ** '' | + | ==== Get WAN L3 device ==== |
| + | <code bash> | ||
| + | # Runtime configuration | ||
| + | . / | ||
| + | network_flush_cache | ||
| + | network_find_wan NET_IF | ||
| + | network_find_wan6 NET_IF6 | ||
| + | network_get_device NET_L3D " | ||
| + | network_get_device NET_L3D6 " | ||
| + | echo " | ||
| + | echo " | ||
| - | We can start a daemon that maintains the connection asynchronously by calling '' | + | # Persistent configuration |
| + | uci get network.wan.device | ||
| + | uci get network.wan6.device | ||
| + | </ | ||
| - | ---- | + | ==== Get WAN address ==== |
| + | <code bash> | ||
| + | # Runtime configuration | ||
| + | . / | ||
| + | network_flush_cache | ||
| + | network_find_wan NET_IF | ||
| + | network_find_wan6 NET_IF6 | ||
| + | network_get_ipaddr NET_ADDR " | ||
| + | network_get_ipaddr6 NET_ADDR6 " | ||
| + | echo " | ||
| + | echo " | ||
| - | ** '' | + | # Persistent static configuration |
| + | uci get network.wan.ipaddr | ||
| + | uci get network.wan6.ip6addr | ||
| + | </ | ||
| - | It seems to avoid race conditions in protos. We can register the following type of dependencies by calling: | + | ==== Get WAN gateway ==== |
| - | * '' | + | <code bash> |
| - | * '' | + | # Runtime configuration |
| - | * (maybe more?) | + | . / |
| + | network_flush_cache | ||
| + | network_find_wan NET_IF | ||
| + | network_find_wan6 NET_IF6 | ||
| + | network_get_gateway NET_GW | ||
| + | network_get_gateway6 NET_GW6 | ||
| + | echo "${NET_GW}" | ||
| + | echo "${NET_GW6}" | ||
| - | Only if '' | + | # Persistent static configuration |
| + | uci get network.wan.gateway | ||
| + | uci get network.wan6.ip6gw | ||
| + | </ | ||
| - | From some observations I think it looks like technically the '' | + | ==== Get WAN prefix ==== |
| + | <code bash> | ||
| + | # Runtime configuration | ||
| + | . / | ||
| + | network_flush_cache | ||
| + | network_find_wan6 NET_IF6 | ||
| + | network_get_prefix6 NET_PFX6 "${NET_IF6}" | ||
| + | echo "${NET_PFX6}" | ||
| + | # Persistent static configuration | ||
| + | uci get network.wan6.ip6prefix | ||
| + | </ | ||
| - | ---- | + | ==== Get WAN gateway for unmanaged default route ==== |
| - | + | <code bash> | |
| - | ** '' | + | # Runtime configuration |
| - | + | ubus call network.interface dump \ | |
| - | ---- | + | | jsonfilter |
| - | ** '' | + | ['route'][*]['target'='0.0.0.0','mask'='0','nexthop']" |
| - | ---- | + | </ |
| - | + | ||
| - | ==== common functions | + | |
| - | + | ||
| - | ---- | + | |
| - | ** '' | + | |
| - | ---- | + | |
| - | ** '' | + | |
| - | ---- | + | |
| - | ** '' | + | |
| - | ---- | + | |
| - | ** '' | + | |
| - | ---- | + | |
| - | ** '' | + | |