Uci: how to check whether a firewall include exists?

Hi folks,

So basically I want to create an init script which will check whether a fw3/fw4 include exists and if it doesn't then create it.

Now I could parse the /etc/config/firewall file with grep etc but I'd like to see if there is a way to do this with the uci tool.

So far I have this code for adding the include:

# add firewall include
mk_owrt_fw_include() {
	uci add firewall include
	uci set firewall.@include[-1].enabled=1
	uci set firewall.@include[-1].type='script'
	uci set firewall.@include[-1].path="$somepath"

	# fw3
	[ "$_OWRTFW" = 3 ] && uci set firewall.@include[-1].reload=1

	uci commit firewall
	service firewall restart
}

However I just need to run it if the include doesn't exist yet. So how can I check for it using uci? I saw in the docs for uci that it is possible to create named sections. If this was possible with includes then I imagine that I could check for it like so:

uci get firewall.myapp.name or similar.

However the docs are unclear about how to add named sections programmatically, and whether this is possible for includes.

For reference:

https://openwrt.org/docs/guide-user/base-system/uci

https://openwrt.org/docs/guide-user/firewall/firewall_configuration#includes_2203_and_later_with_fw4

Use this:

uci set firewall.my_include_name=include
uci set firewall.my_include_name.enabled=1
uci set firewall.my_include_name.type='script'
uci set firewall.my_include_name.path="$somepath"
1 Like

Thanks. This way of creating named sections is currently undocumented in the uci wiki page. And the firewall_configuration page doesn't mention that includes can be named. Don't know if you are the correct person to say this to but someone with wiki modification rights should document this. I would volunteer if I had wiki mod rights.

Which page do you refer to? It is at least documented here: https://openwrt.org/docs/guide-user/base-system/uci#usage

That same page. I'm not seeing

You can create a named section this way:

uci set <config>.<section_name>=<section_type>

(edited to reflect the seemingly correct syntax)

The existing instructions are these:

Create a new named section of a given type

Create a new anonymous section of type blah:
uci add blah

Then just some examples which don't make sense to me in this context.

Once in the usage section:

set <config>.<section>[.<option>]=<value> Set the value of the given option, or add a new section with the type set to the given value.

And then once in the examples, although in a quite confusing manner.

I simplified the examples now.

1 Like

Thanks. Now the wiki page is clear about this.

I did miss the "or" clause in the usage section. Also since it refers to named sections, I think mentioning that would be helpful:

Set the value of the given option, or add a new named section with the type set to the given value.

@jow
Off topic but while we're at it, is there a way to feed a variable to uci batch? Heredocs make the code look kinda ugly, and if I try uci batch "$commands", it just gets stuck.

What's wrong with using heredocs? You can indent them as well if you like. (The answer is "no", uci batch has no interpolation capabilities, it simply parses an input stream as-is.)

Mainly the fact that the closing heredoc word must be without indentation.

root@OpenWrt:~# cat /tmp/test.sh 
#!/bin/sh

print_heredoc() {
	cat <<-EOT
		See, $1 in an indented heredoc!
		Yay.
	EOT
}

print_heredoc "some text"
root@OpenWrt:~# sh /tmp/test.sh
See, some text in an indented heredoc!
Yay.
root@fb7530:~# 

Then there's also this possibility if you do not want to left-strip the text contents:

(
	cat <<'	EOT'	# this is <tab>, followed by EOT
		Blah
		Blah
	EOT
)
1 Like

Ah, now I recall that I saw this <<-token syntax once but forgot about it. Thanks.

I just realized that "input stream" also means that uci batch can read STDIN, and indeed, tested that and it can. So I'll just pipe the commands into it then. Makes for a much cleaner (and a bit more compact) code. Also probably worth to mention in the wiki.

So this is the code that I've come up with eventually:

# add firewall include
mk_owrt_fw_include() {
	uci -q get firewall."$p_name_c" 1>/dev/null && return 0
	rel=
	[ "$_OWRTFW" = 3 ] && rel=".reload=1" # fw3
	for o in "=include" ".enabled=1" ".type=script" ".path=$path" "$rel"; do
		[ "$o" ] && printf '%s\n' "set firewall.$p_name_c$o"
	done |
	uci batch && uci commit firewall || errorout
	service firewall restart || errorout2
}

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.