#!/usr/local/bin/tclsh8.6

#
# List networks, or network details
#
# Called by: all topo scripts
#
# Parameters (form or url):
#	- addr : ip address
#	- format : nothing, or "pdf" or "png"
#
# History
#   2006/06/05 : pda      : design
#   2006/06/20 : pda      : prologue depends upon format
#   2006/06/22 : pda      : fix a bug on link numbers
#   2006/06/22 : pda      : output depends upon format
#   2006/08/09 : pda      : full path of ps2pdf
#   2006/08/14 : pda      : merge with listl2
#   2007/01/04 : pda      : add parameter uid
#   2007/01/11 : pda      : common initialization
#   2007/01/11 : pda      : uid substitution
#   2010/12/12 : pda      : i18n
#   2010/12/20 : pda      : reworked installation
#   2010/12/25 : pda      : use cgi-dispatch
#

#
# Template pages used by this script
#

set conf(page1)		l3.html
set conf(pagen)		topolist.html

#
# Next actions
# 

set conf(nexteq)	"eq"
set conf(nextl2)	"l2"
set conf(nextl3)	"l3"


#
# Script parameters
#

set conf(dumpgraph)	"dumpgraph -o rnet %s"
set conf(extractl3)	"extractl3 %s %s"

#
# Netmagis general library
#

source /usr/local/lib/netmagis/libnetmagis.tcl

# ::webapp::cgidebug ; exit

##############################################################################
# Utilities
##############################################################################

proc gen-graph {dbfd gv format xl3} {
    global conf

    dotattr-match-init $dbfd 3 td

    foreach line [split $xl3 "\n"] {
	switch -- [lindex $line 0] {
	    selection {
		$gv title [lreplace $line 0 0]
	    }
	    eq {
		lassign $line kw nodename nodetype
		set attrlist [dotattr-match-get $nodetype td]
		switch $nodetype {
		    router {
			if {! [regexp -- {([^:]+):(.*)} $nodename bidon eqname rinst]} then {
			    d error [mc "Invalid router instance '%s'" $nodename]
			}
			switch -- $rinst {
			    _v4 { set label "$eqname\\ndefault" }
			    _v6 { set label "$eqname\\ndefault (IPv6)" }
			    default { set label "$eqname\\r$rinst" }
			}
			lappend attrlist label=\"$label\"
		    }
		    host {
			set eqname $nodename
		    }
		    default {
			d error [mc {Invalid node type '%1$s' for %2$s} $nodetype $nodename]
		    }
		}

		d urlset "" $conf(nexteq) [list [list "eq" $eqname]]
		set url [d urlget ""]
		lappend attrlist "href=\"$url\""

		$gv node $nodename $attrlist
	    }
	    direct {
		lassign $line kw eq1 if1 ip1 linkname eq2 if2 ip2
		set attrlist [list label=\"$linkname\" \
					headlabel=\"$if2\\n$ip2\" \
					taillabel=\"$if1\\n$ip1\" \
				    ]
		$gv link $eq1 $eq2 $attrlist
	    }
	    cloud {
		lassign $line kw nodename bcastref vlans networks
		set attrlist [dotattr-match-get "cloud" td]
		set l {}
		set vlanid -1
		foreach vl $vlans {
		    set v [lindex $vl 0]
		    lappend l $v
		    if {$v != 0 && $vlanid == -1} then {
			set vlanid $v
		    }
		}
		set l [join $l ", "]
		set label [mc "Vlan"]
		append label " $l\\n"
		append label [join $networks "\\n"]
		lappend attrlist "label=\"$label\""

		if {$vlanid != -1} then {
		    d urlset "" $conf(nextl2) [list [list "vlan" $vlanid]]
		    set url [d urlget ""]
		    lappend attrlist "href=\"$url\""
		}

		$gv node $nodename $attrlist
	    }
	    link {
		lassign $line kw eqname ifname ipaddr linkname cloud
		set attrlist [list headlabel=\"$linkname\" \
					taillabel=\"$ifname\\n$ipaddr\" \
				    ]
		$gv link $eqname $cloud $attrlist
	    }
	}
    }

    #
    # Graph processors
    #

    set dotcmd [get-local-conf "dot"]
    set ps2pdf [get-local-conf "ps2pdf"]

    return [$gv graphviz $format "neato" $dotcmd $ps2pdf]
}

##############################################################################
# Display L3 parameters
##############################################################################

d cgi-register {} {
    {addr	0 1}
    {format	0 1}
} {
    global conf

    #
    # Initialization
    #

    set msgsta [topo-status $dbfd $tabuid(p_admin)]

    set tmp /tmp/l3-[pid]

    d urlset "%URLFORMEQ%" $conf(nexteq) {}
    d urlset "%URLFORML2%" $conf(nextl2) {}
    d urlset "%URLFORML3%" $conf(nextl3) {}

    #
    # Get IP networks from the graph
    #

    set cmd [format $conf(dumpgraph) $tabuid(flagsr)]
    if {! [call-topo $cmd msg]} then {
	d error [mc "Error while reading networks: %s" $msg]
    }
    foreach line [split $msg "\n"] {
	if {[regexp {^rnet ([^ ]+)} $line bidon a]} then {
	    set tabip($a) ""
	}
    }

    if {$addr eq ""} then {
	#
	# Sort IP addresses
	#

	set list {}
	foreach addr [lsort -command compare-ip [array names tabip]] {
	    d urlset "" $conf(nextl3) [list [list "addr" $addr]]
	    set url [d urlget ""]
	    lappend list [::webapp::helem "li" \
				[::webapp::helem "a" $addr "href" $url]]
	}
	set list [::webapp::helem "ul" [join $list "\n"]]

	#
	# End of script: output page and close database
	#

	d result $conf(pagen) [list \
				    [list %MSGSTA% $msgsta] \
				    [list %OBJETS% [mc "IP networks"]] \
				    [list %LIST% $list] \
				    [list %EQ%     ""] \
				    [list %VLAN%   ""] \
				    [list %ADDR%   ""] \
				    [list %HEADER% ""] \
				    [list %ONLOAD% ""] \
				]
    } else {
	set gv [::gvgraph %AUTO%]

	#
	# Checks the output format
	#

	if {$format eq ""} then {
	    set format "map"
	}
	set msg [$gv check-format $format]
	if {$msg ne ""} then {
	    d error $msg
	}

	#
	# Validate IP address
	#

	set msg [check-ip-syntax $dbfd $addr "loosecidr"]
	if {$msg ne ""} then {
	    d error $msg
	}

	#
	# Search given IP and get associated network
	#

	set lnet {}
	foreach net [array names tabip] {
	    if {[ip-in $addr $net]} then {
		lappend lnet $net
	    }
	}
	if {[llength $lnet] == 0} then {
	    set lnet $addr
	}

	#
	# Get data from graph
	#

	set cmd [format $conf(extractl3) $tabuid(flagsr) [join $lnet " "]]
	if {! [call-topo $cmd xl3]} then {
	    d error [mc "Error while reading networks: %s" $xl3]
	}

	#
	# Sketch the resulting data
	#

	if {[gen-graph $dbfd $gv $format $xl3]} then {
	    switch -- $format {
		pdf {
		    ::webapp::send rawpdf [$gv output]
		    d end
		}
		png {
		    ::webapp::send png [$gv output]
		    d end
		}
		map {
		    d urlset "" $conf(nextl3) [list {format png} [list "addr" $addr]]
		    set urlimg [d urlget ""]

		    d urlset "" $conf(nextl3) [list {format pdf} [list "addr" $addr]]
		    set urlpdf [d urlget ""]

		    set map [$gv output]
		    d result $conf(page1) [list \
						[list %MSGSTA% $msgsta] \
						[list %EQ%     ""] \
						[list %VLAN%   ""] \
						[list %RESEAU% $lnet] \
						[list %ADDR%   $addr] \
						[list %URLIMG% $urlimg] \
						[list %URLPDF% $urlpdf] \
						[list %MAP%    $map] \
					    ]
		}
		default {
		    d error "Internal error"
		}
	    }
	} else {
	    d error [$gv error]
	}
    }
}

##############################################################################
# Main procedure
##############################################################################

d cgi-dispatch "topo" ""
