summaryrefslogtreecommitdiffstats
path: root/apol/netcontexts_tab.tcl
diff options
context:
space:
mode:
Diffstat (limited to 'apol/netcontexts_tab.tcl')
-rw-r--r--apol/netcontexts_tab.tcl878
1 files changed, 878 insertions, 0 deletions
diff --git a/apol/netcontexts_tab.tcl b/apol/netcontexts_tab.tcl
new file mode 100644
index 0000000..d59d19c
--- /dev/null
+++ b/apol/netcontexts_tab.tcl
@@ -0,0 +1,878 @@
+# Copyright (C) 2001-2007 Tresys Technology, LLC
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+namespace eval Apol_NetContexts {
+ variable widgets
+ variable vals
+}
+
+proc Apol_NetContexts::create {tab_name nb} {
+ variable widgets
+ variable vals
+
+ _initializeVars
+
+ # Layout frames
+ set frame [$nb insert end $tab_name -text "Net Contexts"]
+ set pw [PanedWindow $frame.pw -side top -weights extra]
+ set leftf [$pw add -weight 0]
+ set rightf [$pw add -weight 1]
+ pack $pw -fill both -expand yes
+
+ # build the left column, where one selects a particular type of
+ # context; below it will be a scrolled listbox of keys for that
+ # context
+ set context_box [TitleFrame $leftf.context_f -text "Context Type"]
+ set context_f [$context_box getframe]
+ radiobutton $context_f.portcon -text "portcon" -value portcon \
+ -variable Apol_NetContexts::vals(context_type)
+ radiobutton $context_f.netifcon -text "netifcon" -value netifcon \
+ -variable Apol_NetContexts::vals(context_type)
+ radiobutton $context_f.nodecon -text "nodecon" -value nodecon \
+ -variable Apol_NetContexts::vals(context_type)
+ trace add variable Apol_NetContexts::vals(context_type) write \
+ {Apol_NetContexts::_contextTypeChanged}
+ pack $context_f.portcon $context_f.netifcon $context_f.nodecon \
+ -anchor w -expand 0 -padx 4 -pady 5
+ pack $context_box -anchor nw -expand 0 -fill x
+
+ set widgets(items_tf) [TitleFrame $leftf.items_f -text "Port Contexts"]
+ set widgets(items) [Apol_Widget::makeScrolledListbox [$widgets(items_tf) getframe].items \
+ -height 20 -width 20 -listvar Apol_NetContexts::vals(items)]
+ Apol_Widget::setListboxCallbacks $widgets(items) \
+ {{"Show Context Info" {Apol_NetContexts::_popupContextInfo}}}
+ pack $widgets(items) -expand 1 -fill both
+ pack $widgets(items_tf) -expand 1 -fill both
+
+ # build the search options
+ set optsbox [TitleFrame $rightf.optsbox -text "Search Options"]
+ pack $optsbox -side top -expand 0 -fill both -padx 2
+ set widgets(options_pm) [PagesManager [$optsbox getframe].pm]
+
+ _portcon_create [$widgets(options_pm) add portcon]
+ _netifcon_create [$widgets(options_pm) add netifcon]
+ _nodecon_create [$widgets(options_pm) add nodecon]
+
+ $widgets(options_pm) compute_size
+ pack $widgets(options_pm) -expand 1 -fill both -side left
+ $widgets(options_pm) raise portcon
+
+ set ok [button [$optsbox getframe].ok -text "OK" -width 6 \
+ -command Apol_NetContexts::_runSearch]
+ pack $ok -side right -pady 5 -padx 5 -anchor ne
+
+ set resultsbox [TitleFrame $rightf.resultsbox -text "Search Results"]
+ pack $resultsbox -expand yes -fill both -padx 2
+ set widgets(results) [Apol_Widget::makeSearchResults [$resultsbox getframe].results]
+ pack $widgets(results) -side top -expand yes -fill both
+
+ return $frame
+}
+
+proc Apol_NetContexts::open {ppath} {
+ variable vals
+
+ _portcon_open
+ _netifcon_open
+ _nodecon_open
+
+ # force a flip to the portcon page
+ set vals(context_type) portcon
+}
+
+proc Apol_NetContexts::close {} {
+ variable widgets
+
+ _initializeVars
+ Apol_Widget::clearSearchResults $widgets(results)
+ Apol_Widget::clearContextSelector $widgets(portcon:context)
+ Apol_Widget::clearContextSelector $widgets(netifcon:ifcon)
+ Apol_Widget::clearContextSelector $widgets(netifcon:msgcon)
+ Apol_Widget::clearContextSelector $widgets(nodecon:context)
+ $widgets(portcon:proto) configure -values {}
+ $widgets(netifcon:dev) configure -values {}
+}
+
+proc Apol_NetContexts::getTextWidget {} {
+ variable widgets
+ return $widgets(results).tb
+}
+
+#### private functions below ####
+
+proc Apol_NetContexts::_initializeVars {} {
+ variable vals
+ array set vals {
+ portcon:items {}
+ portcon:proto_enable 0 portcon:proto {}
+ portcon:port_enable 0 portcon:port 0
+ portcon:hiport_enable 0 portcon:hiport 0
+
+ netifcon:items {}
+ netifcon:dev_enable 0 netifcon:dev {}
+
+ nodecon:items {}
+ nodecon:ip_type ipv4
+ nodecon:ipv4_addr_enable 0
+ nodecon:ipv4_addr0 0 nodecon:ipv4_addr1 0
+ nodecon:ipv4_addr2 0 nodecon:ipv4_addr3 0
+ nodecon:ipv4_mask_enable 0
+ nodecon:ipv4_mask0 255 nodecon:ipv4_mask1 255
+ nodecon:ipv4_mask2 255 nodecon:ipv4_mask3 255
+ nodecon:ipv6_addr_enable 0 nodecon:ipv6_addr ::
+ nodecon:ipv6_mask_enable 0 nodecon:ipv6_mask ::
+
+ items {}
+ context_type portcon
+ }
+}
+
+proc Apol_NetContexts::_contextTypeChanged {name1 name2 op} {
+ variable vals
+ variable widgets
+ Apol_Widget::clearSearchResults $widgets(results)
+ if {$vals(context_type) == "portcon"} {
+ _portcon_show
+ } elseif {$vals(context_type) == "netifcon"} {
+ _netifcon_show
+ } else {
+ _nodecon_show
+ }
+}
+
+proc Apol_NetContexts::_popupContextInfo {value} {
+ variable vals
+ if {$vals(context_type) == "portcon"} {
+ _portcon_popup $value
+ } elseif {$vals(context_type) == "netifcon"} {
+ _netifcon_popup $value
+ } else {
+ _nodecon_popup $value
+ }
+}
+
+proc Apol_NetContexts::_toggleCheckbutton {path name1 name2 op} {
+ variable vals
+ variable widgets
+ if {$vals($name2)} {
+ $path configure -state normal
+ } else {
+ $path configure -state disabled
+ }
+}
+
+proc Apol_NetContexts::_runSearch {} {
+ variable vals
+ variable widgets
+
+ Apol_Widget::clearSearchResults $widgets(results)
+ if {![ApolTop::is_policy_open]} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No current policy file is opened."
+ return
+ }
+ if {$vals(context_type) == "portcon"} {
+ _portcon_runSearch
+ } elseif {$vals(context_type) == "netifcon"} {
+ _netifcon_runSearch
+ } else {
+ _nodecon_runSearch
+ }
+}
+
+#### portcon private functions below ####
+
+# create the portcon-specific options widgets
+proc Apol_NetContexts::_portcon_create {p_f} {
+ variable widgets
+ variable vals
+
+ frame $p_f.proto
+ set proto_cb [checkbutton $p_f.proto.proto_enable -text "Protocol" \
+ -variable Apol_NetContexts::vals(portcon:proto_enable)]
+ set widgets(portcon:proto) [ComboBox $p_f.proto.proto -entrybg white -width 8 -state disabled \
+ -textvariable Apol_NetContexts::vals(portcon:proto) -autopost 1]
+ trace add variable Apol_NetContexts::vals(portcon:proto_enable) write \
+ [list Apol_NetContexts::_toggleCheckbutton $widgets(portcon:proto)]
+ pack $proto_cb -side top -anchor w
+ pack $widgets(portcon:proto) -side top -expand 0 -fill x -padx 4
+
+ frame $p_f.port
+ set low [frame $p_f.port.l]
+ set port_cb [checkbutton $low.port_enable -text "Single Port" \
+ -variable Apol_NetContexts::vals(portcon:port_enable)]
+ set widgets(portcon:port) [spinbox $low.port -bg white -width 8 \
+ -justify right -state disabled \
+ -from 0 -to 65535 \
+ -validate all -vcmd [list Apol_NetContexts::_portcon_limitPort %W %V %P port] \
+ -textvariable Apol_NetContexts::vals(portcon:port)]
+ set high [frame $p_f.port.h]
+ set hiport_cb [checkbutton $high.hiport_enable -text "High Port" \
+ -state disabled \
+ -variable Apol_NetContexts::vals(portcon:hiport_enable)]
+ set widgets(portcon:hiport) [spinbox $high.hiport -bg white -width 8 \
+ -justify right -state disabled \
+ -from 0 -to 65535 \
+ -validate all -vcmd [list Apol_NetContexts::_portcon_limitPort %W %V %P hiport] \
+ -textvariable Apol_NetContexts::vals(portcon:hiport)]
+ trace add variable Apol_NetContexts::vals(portcon:port_enable) write \
+ [list Apol_NetContexts::_portcon_toggleCheckbutton_lowport \
+ $widgets(portcon:port) $hiport_cb $widgets(portcon:hiport)]
+ trace add variable Apol_NetContexts::vals(portcon:hiport_enable) write \
+ [list Apol_NetContexts::_portcon_toggleCheckbutton_hiport $port_cb $widgets(portcon:hiport)]
+ pack $port_cb -side top -anchor w -expand 0
+ pack $widgets(portcon:port) -side top -expand 0 -fill x -padx 4
+ pack $hiport_cb -side top -anchor w -expand 0
+ pack $widgets(portcon:hiport) -side top -expand 0 -fill x -padx 4
+ pack $low $high -side left -expand 0 -fill both
+
+ frame $p_f.c
+ set widgets(portcon:context) [Apol_Widget::makeContextSelector $p_f.c.context "Contexts"]
+ pack $widgets(portcon:context)
+ pack $p_f.proto $p_f.port $p_f.c -side left -padx 4 -pady 2 -anchor nw
+}
+
+proc Apol_NetContexts::_portcon_open {} {
+ variable vals
+
+ set q [new_apol_portcon_query_t]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set portcons [portcon_vector_to_list $v]
+ $v -acquire
+ $v -delete
+ set vals(portcon:items) {}
+ set protos {}
+ foreach p $portcons {
+ set low [$p get_low_port $::ApolTop::qpolicy]
+ set high [$p get_high_port $::ApolTop::qpolicy]
+ set proto [$p get_protocol $::ApolTop::qpolicy]
+ if {$low == $high} {
+ lappend vals(portcon:items) $low
+ } else {
+ lappend vals(portcon:items) "$low-$high"
+ }
+ lappend protos [apol_protocol_to_str $proto]
+ }
+
+ variable widgets
+ set vals(portcon:items) [lsort -unique -dictionary $vals(portcon:items)]
+ $widgets(portcon:proto) configure -values [lsort -unique -dictionary $protos]
+}
+
+proc Apol_NetContexts::_portcon_show {} {
+ variable vals
+ variable widgets
+ $widgets(items_tf) configure -text "Port Contexts"
+ $widgets(options_pm) raise portcon
+ set vals(items) $vals(portcon:items)
+}
+
+proc Apol_NetContexts::_portcon_popup {port} {
+ foreach {low high} [split $port "-"] {break}
+ if {$high == {}} {
+ set high $low
+ }
+
+ set q [new_apol_portcon_query_t]
+ $q set_low $::ApolTop::policy $low
+ $q set_high $::ApolTop::policy $high
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set portcons [portcon_vector_to_list $v]
+ $v -acquire
+ $v -delete
+
+ set text "port $port ([llength $portcons] context"
+ if {[llength $portcons] != 1} {
+ append text s
+ }
+ append text ")"
+ foreach p [lsort -command _portcon_sort $portcons] {
+ append text "\n [_portcon_render $p]"
+ }
+ Apol_Widget::showPopupText "port $port" $text
+}
+
+proc Apol_NetContexts::_portcon_limitPort {widget command new_port varname} {
+ variable vals
+ if {$command == "key"} {
+ if {$new_port != "" &&
+ (![string is integer $new_port] || $new_port < 0 || $new_port > 65535)} {
+ return 0
+ }
+ } elseif {$command == "focusout"} {
+ if {$new_port == ""} {
+ set vals(portcon:$varname) 0
+ } elseif {[string length $new_port] > 1} {
+ set vals(portcon:$varname) [string trimleft $new_port " 0"]
+ }
+
+ # re-enable the validation command (it could have been
+ # disabled because the variable changed)
+ $widget config -validate all
+ }
+ return 1
+}
+
+proc Apol_NetContexts::_portcon_toggleCheckbutton_lowport {low high_cb high name1 name2 op} {
+ variable vals
+ variable widgets
+ if {$vals($name2)} {
+ $low configure -state normal
+ $high_cb configure -state normal
+ if {$vals(portcon:hiport_enable)} {
+ $high configure -state normal
+ }
+ } else {
+ $low configure -state disabled
+ $high_cb configure -state disabled
+ $high configure -state disabled
+ }
+}
+
+proc Apol_NetContexts::_portcon_toggleCheckbutton_hiport {low high name1 name2 op} {
+ variable vals
+ variable widgets
+ if {$vals($name2)} {
+ $low configure -text "Low Port"
+ $high configure -state normal
+ } else {
+ $low configure -text "Single Port"
+ $high configure -state disabled
+ }
+}
+
+proc Apol_NetContexts::_portcon_runSearch {} {
+ variable vals
+ variable widgets
+
+ # explicitly validate the spinboxes (they could still have focus)
+ _portcon_limitPort $widgets(portcon:port) focusout $vals(portcon:port) port
+ _portcon_limitPort $widgets(portcon:hiport) focusout $vals(portcon:hiport) hiport
+
+ if {$vals(portcon:port_enable)} {
+ set low $vals(portcon:port)
+ set high $low
+ if {$vals(portcon:hiport_enable)} {
+ set high $vals(portcon:hiport)
+ if {$vals(portcon:port_enable) && $high < $low} {
+ tk_messageBox -icon error -type ok -title "Error" -message "The second port is not greater than the first."
+ return
+ }
+ }
+ } else {
+ set low -1
+ set high -1
+ }
+
+ set q [new_apol_portcon_query_t]
+ $q set_low $::ApolTop::policy $low
+ $q set_high $::ApolTop::policy $high
+ if {$vals(portcon:proto_enable)} {
+ if {[set proto $vals(portcon:proto)] == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No protocol selected."
+ return
+ }
+ $q set_protocol $::ApolTop::policy [apol_str_to_protocol $proto]
+ }
+ if {[Apol_Widget::getContextSelectorState $widgets(portcon:context)]} {
+ foreach {context range_match attribute} [Apol_Widget::getContextSelectorValue $widgets(portcon:context)] {break}
+ $q set_context $::ApolTop::policy $context $range_match
+ }
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set portcons [portcon_vector_to_list $v]
+ $v -acquire
+ $v -delete
+
+ set results "PORTCONS:"
+ if {[llength $portcons] == 0} {
+ append results "\nSearch returned no results."
+ } else {
+ foreach p [lsort -command _portcon_sort $portcons] {
+ append results "\n[_portcon_render $p]"
+ }
+ }
+ Apol_Widget::appendSearchResultText $widgets(results) $results
+}
+
+proc Apol_NetContexts::_portcon_render {qpol_portcon_datum} {
+ set loport [$qpol_portcon_datum get_low_port $::ApolTop::qpolicy]
+ set hiport [$qpol_portcon_datum get_high_port $::ApolTop::qpolicy]
+ set proto [apol_protocol_to_str [$qpol_portcon_datum get_protocol $::ApolTop::qpolicy]]
+ set qpol_context [$qpol_portcon_datum get_context $::ApolTop::qpolicy]
+ if {$loport == $hiport} {
+ set line "portcon $proto $loport "
+ } else {
+ set line "portcon $proto ${loport}-${hiport} "
+ }
+ concat $line [apol_qpol_context_render $::ApolTop::policy $qpol_context]
+}
+
+proc Apol_NetContexts::_portcon_sort {a b} {
+ set loport1 [$a get_low_port $::ApolTop::qpolicy]
+ set hiport1 [$a get_high_port $::ApolTop::qpolicy]
+ set loport2 [$b get_low_port $::ApolTop::qpolicy]
+ set hiport2 [$b get_high_port $::ApolTop::qpolicy]
+ if {$loport1 == $hiport1} {
+ set singleport1 1
+ } else {
+ set singleport1 0
+ }
+ if {$loport2 == $hiport2} {
+ set singleport2 1
+ } else {
+ set singleport2 0
+ }
+ if {$singleport1 && !$singleport2} {
+ return -1
+ } elseif {!$singleport1 && $singleport2} {
+ return 1
+ }
+ if {$loport1 < $loport2} {
+ return -1
+ } elseif {$loport1 > $loport2} {
+ return 1
+ }
+ if {$hiport1 < $hiport2} {
+ return -1
+ } elseif {$hiport1 > $hiport2} {
+ return 1
+ }
+ set proto1 [apol_protocol_to_str [$a get_protocol $::ApolTop::qpolicy]]
+ set proto2 [apol_protocol_to_str [$b get_protocol $::ApolTop::qpolicy]]
+ string compare $proto1 $proto2
+}
+
+#### netifcon private functions below ####
+
+proc Apol_NetContexts::_netifcon_create {p_f} {
+ variable vals
+ variable widgets
+
+ frame $p_f.dev
+ set dev_cb [checkbutton $p_f.dev.dev_enable -text "Device" \
+ -variable Apol_NetContexts::vals(netifcon:dev_enable)]
+ set widgets(netifcon:dev) [ComboBox $p_f.dev.dev -entrybg white -width 8 -state disabled \
+ -textvariable Apol_NetContexts::vals(netifcon:dev) -autopost 1]
+ trace add variable Apol_NetContexts::vals(netifcon:dev_enable) write \
+ [list Apol_NetContexts::_toggleCheckbutton $widgets(netifcon:dev)]
+ pack $dev_cb -side top -anchor w
+ pack $widgets(netifcon:dev) -side top -expand 0 -fill x -padx 4
+
+ frame $p_f.ifcon
+ set widgets(netifcon:ifcon) [Apol_Widget::makeContextSelector $p_f.ifcon.context "Contexts" "Interface context" -width 18]
+ pack $widgets(netifcon:ifcon)
+
+ frame $p_f.msgcon
+ set widgets(netifcon:msgcon) [Apol_Widget::makeContextSelector $p_f.msgcon.context "Contexts" "Message context" -width 18]
+ pack $widgets(netifcon:msgcon)
+
+ pack $p_f.dev $p_f.ifcon $p_f.msgcon -side left -padx 4 -pady 2 -anchor nw
+}
+
+proc Apol_NetContexts::_netifcon_open {} {
+ variable vals
+
+ set q [new_apol_netifcon_query_t]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set vals(netifcon:items) [lsort [netifcon_vector_to_list $v]]
+ $v -acquire
+ $v -delete
+
+ variable widgets
+ $widgets(netifcon:dev) configure -values $vals(netifcon:items)
+}
+
+proc Apol_NetContexts::_netifcon_show {} {
+ variable vals
+ variable widgets
+ $widgets(items_tf) configure -text "NetIF Contexts"
+ $widgets(options_pm) raise netifcon
+ set vals(items) $vals(netifcon:items)
+}
+
+proc Apol_NetContexts::_netifcon_popup {netif} {
+ set text "network interface $netif"
+ append text "\n [_netifcon_render $netif]"
+ Apol_Widget::showPopupText "interface $netif" $text
+}
+
+proc Apol_NetContexts::_netifcon_runSearch {} {
+ variable vals
+ variable widgets
+
+ if {$vals(netifcon:dev_enable)} {
+ if {$vals(netifcon:dev) == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No device selected."
+ return
+ }
+ set dev $vals(netifcon:dev)
+ } else {
+ set dev {}
+ }
+
+ set q [new_apol_netifcon_query_t]
+ $q set_device $::ApolTop::policy $dev
+ if {[Apol_Widget::getContextSelectorState $widgets(netifcon:ifcon)]} {
+ foreach {context range_match attribute} [Apol_Widget::getContextSelectorValue $widgets(netifcon:ifcon)] {break}
+ $q set_if_context $::ApolTop::policy $context $range_match
+ }
+ if {[Apol_Widget::getContextSelectorState $widgets(netifcon:msgcon)]} {
+ foreach {context range_match attribute} [Apol_Widget::getContextSelectorValue $widgets(netifcon:msgcon)] {break}
+ $q set_msg_context $::ApolTop::policy $context $range_match
+ }
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set netifcons [netifcon_vector_to_list $v]
+ $v -acquire
+ $v -delete
+
+ set results "NETIFCONS:"
+ if {[llength $netifcons] == 0} {
+ append results "\nSearch returned no results."
+ } else {
+ foreach n [lsort $netifcons] {
+ append results "\n[_netifcon_render $n]"
+ }
+ }
+ Apol_Widget::appendSearchResultText $widgets(results) $results
+}
+
+proc Apol_NetContexts::_netifcon_render {netifcon} {
+ set qpol_netifcon_datum [new_qpol_netifcon_t $::ApolTop::qpolicy $netifcon]
+ apol_netifcon_render $::ApolTop::policy $qpol_netifcon_datum
+}
+
+#### nodecon private functions below ####
+
+proc Apol_NetContexts::_nodecon_create {p_f} {
+ variable vals
+ variable widgets
+
+ frame $p_f.ip_type
+ set ipv4_rb [radiobutton $p_f.ip_type.v4 -text "IPv4" -value ipv4 \
+ -variable Apol_NetContexts::vals(nodecon:ip_type)]
+ set ipv6_rb [radiobutton $p_f.ip_type.v6 -text "IPv6" -value ipv6 \
+ -variable Apol_NetContexts::vals(nodecon:ip_type)]
+ trace add variable Apol_NetContexts::vals(nodecon:ip_type) write \
+ [list Apol_NetContexts::_nodecon_pageChanged]
+ pack $ipv4_rb $ipv6_rb -side top -anchor nw -pady 5
+
+ frame $p_f.opts
+ set widgets(nodecon:ip_pm) [PagesManager $p_f.opts.pm]
+ _nodecon_ipv4Create [$widgets(nodecon:ip_pm) add ipv4]
+ _nodecon_ipv6Create [$widgets(nodecon:ip_pm) add ipv6]
+ $widgets(nodecon:ip_pm) compute_size
+ pack $widgets(nodecon:ip_pm)
+ $widgets(nodecon:ip_pm) raise ipv4
+
+ frame $p_f.con
+ set widgets(nodecon:context) [Apol_Widget::makeContextSelector $p_f.con.context "Contexts"]
+ pack $widgets(nodecon:context)
+
+ pack $p_f.ip_type $p_f.opts $p_f.con -side left -padx 4 -pady 2 -anchor nw
+}
+
+proc Apol_NetContexts::_nodecon_open {} {
+ set q [new_apol_nodecon_query_t]
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set nodecons [nodecon_vector_to_list $v]
+
+ variable vals
+ variable widgets
+ set vals(nodecon:items) {}
+ foreach n [lsort -command _nodecon_sort $nodecons] {
+ set proto [$n get_protocol $::ApolTop::qpolicy]
+ set addr [$n get_addr $::ApolTop::qpolicy]
+ if {$proto == $::QPOL_IPV4} {
+ set addr [apol_ipv4_addr_render $::ApolTop::policy $addr]
+ } elseif {$proto == $::QPOL_IPV6} {
+ set addr [apol_ipv6_addr_render $::ApolTop::policy $addr]
+ } else {
+ puts stderr "Unknown protocol $proto"
+ exit -1
+ }
+ lappend vals(nodecon:items) $addr
+ }
+ set vals(nodecon:items) [lsort -unique -dictionary $vals(nodecon:items)]
+
+ # because qpol_policy_get_nodecon_iter() returns allocated items,
+ # destroying the vector before using its items will segfault
+ $v -acquire
+ $v -delete
+}
+
+proc Apol_NetContexts::_nodecon_show {} {
+ variable vals
+ variable widgets
+ $widgets(items_tf) configure -text "Node Contexts"
+ $widgets(options_pm) raise nodecon
+ set vals(items) $vals(nodecon:items)
+}
+
+proc Apol_NetContexts::_nodecon_ipv4Create {fv4} {
+ variable widgets
+ set v4addrf [frame $fv4.addr]
+ set ipv4_addr_cb [checkbutton $v4addrf.enable -text "IP address" \
+ -variable Apol_NetContexts::vals(nodecon:ipv4_addr_enable)]
+ set widgets(nodecon:v4addrf2) [frame $v4addrf.a]
+ for {set i 0} {$i < 4} {incr i} {
+ set e [entry $widgets(nodecon:v4addrf2).e$i -bg white -justify center -width 4 \
+ -state disabled \
+ -validate all -vcmd [list Apol_NetContexts::_nodecon_limitAddr %W %V %P ipv4_addr$i] \
+ -textvariable Apol_NetContexts::vals(nodecon:ipv4_addr$i)]
+ pack $e -side left -padx 1 -anchor center
+ if {$i < 3} {
+ pack [label $widgets(nodecon:v4addrf2).l$i -text "."] -side left -expand 0 -anchor s
+ }
+ }
+ trace add variable Apol_NetContexts::vals(nodecon:ipv4_addr_enable) write \
+ [list Apol_NetContexts::_nodecon_toggleV4button $widgets(nodecon:v4addrf2).e]
+ pack $ipv4_addr_cb -anchor w
+ pack $widgets(nodecon:v4addrf2) -padx 3 -expand 0 -fill x
+
+ set v4maskf [frame $fv4.mask]
+ set ipv4_mask_cb [checkbutton $v4maskf.enable -text "Mask" \
+ -variable Apol_NetContexts::vals(nodecon:ipv4_mask_enable)]
+ set widgets(nodecon:v4maskf2) [frame $v4maskf.m]
+ for {set i 0} {$i < 4} {incr i} {
+ set e [entry $widgets(nodecon:v4maskf2).e$i -bg white -justify center -width 4 \
+ -state disabled \
+ -validate all -vcmd [list Apol_NetContexts::_nodecon_limitAddr %W %V %P ipv4_mask$i] \
+ -textvariable Apol_NetContexts::vals(nodecon:ipv4_mask$i)]
+ pack $e -side left -padx 1 -anchor center
+ if {$i < 3} {
+ pack [label $widgets(nodecon:v4maskf2).l$i -text "."] -side left -expand 0 -anchor s
+ }
+ }
+ trace add variable Apol_NetContexts::vals(nodecon:ipv4_mask_enable) write \
+ [list Apol_NetContexts::_nodecon_toggleV4button $widgets(nodecon:v4maskf2).e]
+ pack $ipv4_mask_cb -anchor w
+ pack $widgets(nodecon:v4maskf2) -padx 3 -expand 0 -fill x
+
+ pack $v4addrf $v4maskf -padx 4 -pady 2 -anchor nw
+}
+
+proc Apol_NetContexts::_nodecon_ipv6Create {fv6} {
+ set v6addrf [frame $fv6.addr]
+ set ipv4_addr_cb [checkbutton $v6addrf.enable -text "IP address" \
+ -variable Apol_NetContexts::vals(nodecon:ipv6_addr_enable)]
+ set e [entry $v6addrf.addr -bg white -width 28 -state disabled \
+ -textvariable Apol_NetContexts::vals(nodecon:ipv6_addr)]
+ trace add variable Apol_NetContexts::vals(nodecon:ipv6_addr_enable) write \
+ [list Apol_NetContexts::_toggleCheckbutton $e]
+ pack $ipv4_addr_cb -anchor w
+ pack $e -padx 4 -expand 0 -fill x
+
+ set v6maskf [frame $fv6.mask]
+ set ipv6_mask_cb [checkbutton $v6maskf.enable -text "Mask" \
+ -variable Apol_NetContexts::vals(nodecon:ipv6_mask_enable)]
+ set e [entry $v6maskf.addr -bg white -width 28 -state disabled \
+ -textvariable Apol_NetContexts::vals(nodecon:ipv6_mask)]
+ trace add variable Apol_NetContexts::vals(nodecon:ipv6_mask_enable) write \
+ [list Apol_NetContexts::_toggleCheckbutton $e]
+ pack $ipv6_mask_cb -anchor w
+ pack $e -padx 4 -expand 0 -fill x
+
+ pack $v6addrf $v6maskf -padx 4 -pady 2 -anchor w
+}
+
+proc Apol_NetContexts::_nodecon_pageChanged {name1 name2 op} {
+ variable vals
+ variable widgets
+ $widgets(nodecon:ip_pm) raise $vals(nodecon:ip_type)
+}
+
+proc Apol_NetContexts::_nodecon_limitAddr {widget command new_addr varname} {
+ variable vals
+ if {$command == "key"} {
+ if {$new_addr != "" &&
+ (![string is integer $new_addr] || $new_addr < 0 || $new_addr > 255)} {
+ return 0
+ }
+ } elseif {$command == "focusout"} {
+ if {$new_addr == ""} {
+ set vals(nodecon:$varname) 0
+ } elseif {[string length $new_addr] > 1} {
+ set vals(nodecon:$varname) [string trimleft $new_addr " 0"]
+ }
+
+ # re-enable the validation command (it could have been
+ # disabled because the variable changed)
+ after idle [list $widget config -validate all]
+ }
+ return 1
+}
+
+proc Apol_NetContexts::_nodecon_toggleV4button {path name1 name2 op} {
+ variable vals
+ if {$vals($name2)} {
+ for {set i 0} {$i < 4} {incr i} {
+ ${path}${i} configure -state normal
+ }
+ } else {
+ for {set i 0} {$i < 4} {incr i} {
+ ${path}${i} configure -state disabled
+ }
+ }
+}
+
+proc Apol_NetContexts::_nodecon_popup {nodecon_addr} {
+ set q [new_apol_nodecon_query_t]
+ set ip [apol_str_to_internal_ip $nodecon_addr]
+ $q set_addr $::ApolTop::policy $ip
+ $ip -acquire
+ $ip -delete
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set nodecons [nodecon_vector_to_list $v]
+
+ set text "nodecon $nodecon_addr ([llength $nodecons] context"
+ if {[llength $nodecons] != 1} {
+ append text s
+ }
+ append text ")"
+ foreach n [lsort -command _nodecon_sort $nodecons] {
+ append text "\n [_nodecon_render $n]"
+ }
+ Apol_Widget::showPopupText "address $nodecon_addr" $text
+
+ # because qpol_policy_get_nodecon_iter() returns allocated items,
+ # destroying the vector before using its items will segfault
+ $v -acquire
+ $v -delete
+}
+
+proc Apol_NetContexts::_nodecon_runSearch {} {
+ variable vals
+ variable widgets
+
+ set addr {}
+ set mask {}
+ if {$vals(nodecon:ip_type) == "ipv4"} {
+ # explicitly validate the entries (they could still have focus)
+ foreach i {0 1 2 3} {
+ _nodecon_limitAddr $widgets(nodecon:v4addrf2).e$i focusout $vals(nodecon:ipv4_addr$i) ipv4_addr$i
+ _nodecon_limitAddr $widgets(nodecon:v4maskf2).e$i focusout $vals(nodecon:ipv4_mask$i) ipv4_mask$i
+ }
+ if {$vals(nodecon:ipv4_addr_enable)} {
+ set addr [format "%d.%d.%d.%d" \
+ $vals(nodecon:ipv4_addr0) $vals(nodecon:ipv4_addr1) \
+ $vals(nodecon:ipv4_addr2) $vals(nodecon:ipv4_addr3)]
+ }
+ if {$vals(nodecon:ipv4_mask_enable)} {
+ set mask [format "%d.%d.%d.%d" \
+ $vals(nodecon:ipv4_mask0) $vals(nodecon:ipv4_mask1) \
+ $vals(nodecon:ipv4_mask2) $vals(nodecon:ipv4_mask3)]
+ }
+ set proto $::QPOL_IPV4
+ } else {
+ if {$vals(nodecon:ipv6_addr_enable)} {
+ if {[set addr $vals(nodecon:ipv6_addr)] == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No IPV6 address provided."
+ return
+ }
+ }
+ if {$vals(nodecon:ipv6_mask_enable)} {
+ if {[set mask $vals(nodecon:ipv6_mask)] == {}} {
+ tk_messageBox -icon error -type ok -title "Error" -message "No IPV6 address provided."
+ return
+ }
+ }
+ set proto $::QPOL_IPV6
+ }
+
+ set q [new_apol_nodecon_query_t]
+ $q set_protocol $::ApolTop::policy $proto
+ if {$addr != {}} {
+ if {[catch {apol_str_to_internal_ip $addr} u]} {
+ tk_messageBox -icon error -type ok -title "Error" -message $u
+ return
+ }
+ $q set_addr $::ApolTop::policy $u
+ }
+ if {$mask != {}} {
+ if {[catch {apol_str_to_internal_ip $mask} u]} {
+ tk_messageBox -icon error -type ok -title "Error" -message $u
+ return
+ }
+ $q set_mask $::ApolTop::policy $u
+ }
+ if {[Apol_Widget::getContextSelectorState $widgets(nodecon:context)]} {
+ foreach {context range_match attribute} [Apol_Widget::getContextSelectorValue $widgets(nodecon:context)] {break}
+ $q set_context $::ApolTop::policy $context $range_match
+ }
+
+ set v [$q run $::ApolTop::policy]
+ $q -acquire
+ $q -delete
+ set nodecons [nodecon_vector_to_list $v]
+
+ set results "NODECONS:"
+ if {[llength $nodecons] == 0} {
+ append results "\nSearch returned no results."
+ } else {
+ foreach n [lsort -command _nodecon_sort $nodecons] {
+ append results "\n[_nodecon_render $n]"
+ }
+ }
+ Apol_Widget::appendSearchResultText $widgets(results) $results
+
+ # because qpol_policy_get_nodecon_iter() returns allocated items,
+ # destroying the vector before using its items will segfault
+ $v -acquire
+ $v -delete
+}
+
+proc Apol_NetContexts::_nodecon_render {qpol_nodecon_datum} {
+ apol_nodecon_render $::ApolTop::policy $qpol_nodecon_datum
+}
+
+# Sort nodecons, grouping ipv4 before ipv6. Then sort by address and
+# then mask.
+proc Apol_NetContexts::_nodecon_sort {a b} {
+ set proto1 [$a get_protocol $::ApolTop::qpolicy]
+ set proto2 [$b get_protocol $::ApolTop::qpolicy]
+ if {$proto1 == $::QPOL_IPV4 && $proto2 == $::QPOL_IPV6} {
+ return -1
+ } elseif {$proto1 == $::QPOL_IPV6 && $proto1 == $::QPOL_IPV4} {
+ return 0
+ }
+
+ if {$proto1 == $::QPOL_IPV4} {
+ set render apol_ipv4_addr_render
+ } else {
+ set render apol_ipv6_addr_render
+ }
+ set addr1 [$render $::ApolTop::policy [$a get_addr $::ApolTop::qpolicy]]
+ set addr2 [$render $::ApolTop::policy [$b get_addr $::ApolTop::qpolicy]]
+ if {[set x [string compare $addr1 $addr2]] != 0} {
+ return $x
+ }
+
+ set mask1 [$render $::ApolTop::policy [$a get_mask $::ApolTop::qpolicy]]
+ set mask2 [$render $::ApolTop::policy [$b get_mask $::ApolTop::qpolicy]]
+ string compare $mask1 $mask2
+}