1#!%TCLSH% 2 3# 4# Display page to edit one or more equipment interfaces 5# 6# Called by: eq 7# 8# Parameters (form or url): 9# - display page 10# - mode : (empty) 11# - eq: equipment name 12# - iface : interface name, or empty for all interfaces of an equipement 13# - process modifications 14# - mode : "mono" or "multi" (single or multiple interfaces) 15# - eq: equipment name 16# - iface : interface name (may be given more than once) 17# - vlan : vlan-id or -1 to shutdown the interface 18# - voip : vlan-id or -1 to shutdown the interface 19# - desc : description (or empty, notably if multiple interfaces) 20# - stat : sensors (or empty) 21# 22# History 23# 2010/11/03 : pda : design 24# 2010/11/26 : pda/jean : add modification processing 25# 2010/11/30 : pda/jean : add sensor 26# 2010/12/11 : pda : i18n 27# 2010/12/25 : pda : use cgi-dispatch 28# 29 30# 31# Template pages used by this script 32# 33 34set conf(page-sel) ifchg-sel.html 35set conf(page-mod) ifchg-mod.html 36 37# 38# Next actions 39# 40 41set conf(next) "ifchg" 42 43# 44# Netmagis general library 45# 46 47source %LIBNETMAGIS% 48 49# ::webapp::cgidebug ; exit 50 51############################################################################## 52# Display page 53############################################################################## 54 55d cgi-register {mode {}} { 56 {eq 1 1} 57 {iface 0 1} 58} { 59 global conf 60 61 # 62 # Read equipment information from graph. 63 # 64 65 set l [eq-iflist $eq tabuid] 66 67 lassign $l eq type model location liferr iflist arrayif arrayvlan 68 array set tabiface $arrayif 69 array set tabvlan $arrayvlan 70 71 # 72 # If an error is found, exit immediately. This case means that 73 # one (or more) interface(s) which is writable, but not readable. 74 # 75 76 if {[llength $liferr] > 0} then { 77 set l [join $liferr " "] 78 d error [mc "Inconsistent permissions on interfaces: %s" $l] 79 } 80 81 # 82 # Prepare Vlan list for menus 83 # Note : a Vlan is either a standard Vlan or a VoIP vlan 84 # 85 86 set lvlan [list [list -1 [mc "Shutdown interface"]]] 87 set lvoip [list [list -1 [mc "Shutdown VoIP on this interface"]]] 88 foreach id [lsort -integer [array names tabvlan]] { 89 lassign $tabvlan($id) desc voip 90 if {$desc eq "-"} then { 91 set desc "" 92 } else { 93 set desc [binary format H* $desc] 94 } 95 if {$voip} then { 96 lappend lvoip [list $id "$id ($desc)"] 97 } else { 98 lappend lvlan [list $id "$id ($desc)"] 99 } 100 } 101 102 set nvoip [llength $lvoip] 103 104 # 105 # Do we have to display all interfaces, or just one? 106 # 107 108 if {$iface ne ""} then { 109 # 110 # There is a name. Just display this one. 111 # 112 113 if {! [info exists tabiface($iface)]} then { 114 d error [mc {Interface '%1$s' not found on %2$s} $iface $eq] 115 } 116 117 # 118 # Get status information relative to this equipment and this 119 # interface. 120 # 121 122 set eqsta [eq-graph-status $dbfd $eq $iface] 123 124 # 125 # Get interface characteristics 126 # 127 128 lassign $tabiface($iface) name edit radio ifstat ifmode desc lien natif 129 set trunk [lreplace $tabiface($iface) 0 7] 130 131 if {$edit ne "edit"} then { 132 d error [mc {You can't modify interface %1$s on %2$s} $iface $eq] 133 } 134 135 # 136 # Prepare informations 137 # 138 139 set mode "mono" 140 set title [mc {Edit interface %1$s on %2$s} $iface $eq] 141 set menuif [::webapp::form-hidden iface $iface] 142 143 # display option "multiple interfaces" if there is more than one 144 # writable interface 145 set nifmod 0 146 foreach i $iflist { 147 if {[lindex $tabiface($i) 1] eq "edit"} then { 148 incr nifmod 149 } 150 } 151 if {$nifmod > 1} then { 152 d urlset "" $conf(next) [list [list "eq" $eq]] 153 set url [d urlget ""] 154 set multi [::webapp::helem "p" \ 155 [mc {You can also <a href="%s">edit more than one interfaces</a> simultaneously} $url] \ 156 ] 157 } else { 158 set multi "" 159 } 160 161 # interface description menu 162 if {$desc eq "-"} then { 163 set desc "" 164 } else { 165 set desc [::webapp::html-string [binary format H* $desc]] 166 } 167 set libifordesc [mc "Description"] 168 set menuifordesc [::webapp::form-text desc 1 40 40 $desc] 169 append menuifordesc " (" 170 append menuifordesc [mc "authorized special characters: -+/()&.:#_"] 171 append menuifordesc ")" 172 173 append libifordesc [::webapp::form-hidden "iface" $iface] 174 175 # vlan menu 176 if {$ifmode eq "Disabled"} then { 177 set pos -1 178 } else { 179 set pos [lsearch -index 0 $lvlan $natif] 180 } 181 if {$pos == -1} then { 182 set lsel {} 183 } else { 184 set lsel [list $pos] 185 } 186 set menuvlan [::webapp::form-menu "vlan" 1 0 $lvlan $lsel] 187 188 # voip vlan menu if needed 189 if {$nvoip > 1} then { 190 set pos -1 191 if {$ifmode eq "Trunk"} then { 192 # search voip vlan amon tagged vlans 193 foreach v $trunk { 194 lassign $v id desc stat 195 # search for the vlan in the menu list 196 set pos [lsearch -index 0 $lvoip $id] 197 if {$pos != -1} then { 198 break 199 } 200 } 201 } 202 if {$pos == -1} then { 203 set lsel {} 204 } else { 205 set lsel [list $pos] 206 } 207 set libvoip [mc "VoIP"] 208 set menuvoip [::webapp::form-menu "voip" 1 0 $lvoip $lsel] 209 } else { 210 set libvoip "" 211 set menuvoip [::webapp::form-hidden "voip" -1] 212 } 213 214 # sensor menu 215 if {$tabuid(p_admin)} then { 216 if {$ifstat eq "-"} then { 217 set ifstat "" 218 } 219 set libstat [mc "Sensors"] 220 set menustat [::webapp::form-text "stat" 1 40 40 $ifstat] 221 } else { 222 set libstat "" 223 set menustat "" 224 } 225 } else { 226 # 227 # Display all interfaces 228 # 229 230 set title [mc "Edit interfaces on %s" $eq] 231 set mode "multi" 232 233 # 234 # Get status information relative to this equipment and all 235 # its interfaces. 236 # 237 set eqsta [eq-graph-status $dbfd $eq] 238 239 # interface list 240 set lif {} 241 foreach i $iflist { 242 set edit [lindex $tabiface($i) 1] 243 if {$edit eq "edit"} then { 244 lappend lif [list $i $i] 245 } 246 } 247 set nif [llength $lif] 248 set libifordesc [mc "Interfaces"] 249 set menuifordesc [::webapp::form-menu "iface" $nif 1 $lif {}] 250 set multi "" 251 252 # vlan menu 253 set menuvlan [::webapp::form-menu "vlan" 1 0 $lvlan {}] 254 255 # voip vlan menu if needed 256 if {$nvoip > 1} then { 257 set libvoip [mc "VoIP"] 258 set menuvoip [::webapp::form-menu "voip" 1 0 $lvoip {}] 259 } else { 260 set libvoip "" 261 set menuvoip [::webapp::form-hidden "voip" -1] 262 } 263 264 # sensor menu is empty 265 set libstat "" 266 set menustat "" 267 } 268 269 # 270 # Next script 271 # 272 273 d urlset "%URLFORM%" $conf(next) {} 274 275 # 276 # End of script: output page and close database 277 # 278 279 d result $conf(page-sel) [list \ 280 [list %EQSTA% $eqsta] \ 281 [list %EQ% $eq] \ 282 [list %TITLE% $title] \ 283 [list %MODE% $mode] \ 284 [list %MULTI% $multi] \ 285 [list %LIBIFORDESC% $libifordesc] \ 286 [list %MENUIFORDESC% $menuifordesc] \ 287 [list %MENUVLAN% $menuvlan] \ 288 [list %LIBVOIP% $libvoip] \ 289 [list %MENUVOIP% $menuvoip] \ 290 [list %LIBSTAT% $libstat] \ 291 [list %MENUSTAT% $menustat] \ 292 ] 293 294} 295 296############################################################################## 297# Commit modifications 298############################################################################## 299 300d cgi-register {mode .+} { 301 {eq 1 1} 302 {iface 0 999999} 303 {vlan 1 1} 304 {voip 1 1} 305 {desc 0 1} 306 {stat 0 1} 307} { 308 global conf 309 310 # 311 # Read equipment information from the graph 312 # 313 314 set l [eq-iflist $eq tabuid] 315 316 lassign $l eq type model location liferr iflist arrayif arrayvlan 317 array set tabiface $arrayif 318 array set tabvlan $arrayvlan 319 320 # 321 # If there is an error, exit immediately 322 # This case means than one (or more) interfaces are writable, but 323 # not readable: this does not make sense. 324 # 325 326 if {[llength $liferr] > 0} then { 327 d error [mc "Inconsistency in access rights for following interfaces: %s" [join $liferr ", "]] 328 } 329 330 # 331 # If no interface is given, there is nothing to do 332 # 333 334 if {[llength $iface] == 0} then { 335 d error [mc "You did not selected any interface"] 336 } 337 338 # 339 # Check write consistency for interfaces 340 # 341 342 foreach i $iface { 343 if {! ([info exists tabiface($i)] && 344 [lindex $tabiface($i) 1] eq "edit")} then { 345 d error [mc {You don't have write access to interface '%1$s' on '%2$s'} $i $eq] 346 } 347 } 348 349 # 350 # Check parameters 351 # 352 353 # vlan 354 if {$vlan eq "-1"} then { 355 # shutdown interface 356 } elseif {[regexp {^[0-9]+$} $vlan] && [info exists tabvlan($vlan)]} then { 357 lassign $tabvlan($vlan) vlandesc isvoip 358 if {$isvoip} then { 359 d error [mc "Vlan '%s' is a voice Vlan" $vlan] 360 } 361 } else { 362 d error [mc "Vlan '%s' not found" $vlan] 363 } 364 365 # voip 366 if {$voip eq "-1"} then { 367 # disable voip 368 } elseif {[regexp {^[0-9]+$} $voip] && [info exists tabvlan($voip)]} then { 369 lassign $tabvlan($voip) vlandesc isvoip 370 if {! $isvoip} then { 371 d error [mc "Vlan '%s' is not a voice Vlan" $voip] 372 } 373 } else { 374 d error [mc "Vlan '%s' not found" $voip] 375 } 376 377 # description 378 switch -- $mode { 379 multi { 380 # nothing: we'll do the test in the next loop 381 } 382 mono { 383 # check special characters and add "X" 384 if {[regexp {[^- a-zA-Z0-9+/()&.:#_]} $desc match]} then { 385 d error [mc "Special character '%s' is not allowed" $match] 386 } 387 # if user is admin, use the given sensor, else use the old sensor 388 if {! $tabuid(p_admin)} then { 389 set i [lindex $iface 0] 390 set stat [lindex $tabiface($i) 3] 391 } 392 set stat [string trim $stat] 393 if {$stat eq "" || $stat eq "-"} then { 394 set desc "X $desc" 395 } else { 396 if {! [regexp {^M\S+$} $stat]} then { 397 d error [mc "Invalid sensor name '%s' (should be M...)" $stat] 398 } 399 set desc "$desc <X $stat>" 400 } 401 set qifdesc [::pgsql::quote $desc] 402 } 403 } 404 405 # 406 # Insert changes in spool 407 # 408 409 # the real user (not the substituted one) 410 set qlogin [::pgsql::quote [lindex [d euid] 0]] 411 # equipment name 412 set fqdn [format "%s.%s" $eq [dnsconfig get "defdomain"]] 413 set qeq [::pgsql::quote $fqdn] 414 415 set sql {} 416 foreach i $iface { 417 set qiface [::pgsql::quote $i] 418 switch $mode { 419 multi { 420 if {[info exists tabiface($i)]} then { 421 # put back old values 422 lassign $tabiface($i) oname oedit oradio ostat omode odesc rem 423 set qifdesc "<X" 424 if {$ostat ne "-"} then { 425 append qifdesc " $ostat" 426 } 427 append qifdesc ">" 428 if {$odesc ne "-"} then { 429 append qifdesc " " 430 append qifdesc [binary format H* $odesc] 431 } 432 } else { 433 set qifdesc "X" 434 } 435 } 436 mono { 437 # nothing: qifdesc has been filled above 438 } 439 } 440 lappend sql "INSERT INTO topo.ifchanges 441 (login, eq, iface, ifdesc, ethervlan, voicevlan) 442 VALUES ('$qlogin', '$qeq', '$qiface', 443 '$qifdesc', $vlan, $voip)" 444 } 445 set sql [join $sql ";"] 446 if {! [::pgsql::execsql $dbfd $sql msg]} then { 447 d error [mc "Error during spool insertion: %s" $msg] 448 } 449 450 # 451 # Get status for graph building and spooled equipment modifications 452 # 453 454 if {[llength $iface] == 1} then { 455 set eqsta [eq-graph-status $dbfd $eq $iface] 456 } else { 457 set eqsta [eq-graph-status $dbfd $eq] 458 } 459 460 # 461 # End of script: output page and close database 462 # 463 464 d result $conf(page-mod) [list \ 465 [list %EQSTA% $eqsta] \ 466 ] 467} 468 469############################################################################## 470# Main procedure 471############################################################################## 472 473d cgi-dispatch "topo" "" 474