1#!%TCLSH% 2 3# 4# Search for a name or an IP/MAC address and display all sessions 5# 6# History 7# 2004/11/14 : jean : design 8# 2005/06/04 : jean : search optimization (gen-ipmac and gen-portmac) 9# remove SQL joints, 2 requests and tcl processing 10# 2010/11/30 : pda/jean : integration a Netmagis 11# 2010/12/12 : pda : i18n 12# 2010/12/26 : pda : use cgi-dispatch 13# 14 15# 16# Template pages used by this script 17# 18 19set conf(page) mac.html 20set conf(pagesearch) macsearch.html 21 22# 23# Next actions 24# 25 26set conf(next) "mac" 27 28# 29# Script parameters 30# 31 32set conf(tabsession) { 33 global { 34 chars {12 normal} 35 align {left} 36 botbar {yes} 37 columns {15 35 15 35} 38 } 39 pattern Title { 40 vbar {yes} 41 column { 42 multicolumn {4} 43 align {center} 44 chars {14 bold} 45 } 46 vbar {yes} 47 } 48 pattern Rem { 49 vbar {yes} 50 column { 51 multicolumn {4} 52 align {center} 53 chars {14} 54 } 55 vbar {yes} 56 } 57 pattern Close { 58 vbar {yes} 59 column { 60 multicolumn {2} 61 } 62 vbar {yes} 63 column { 64 multicolumn {2} 65 } 66 vbar {yes} 67 } 68 pattern Active { 69 vbar {yes} 70 column { 71 multicolumn {2} 72 chars {bold} 73 } 74 vbar {yes} 75 column { 76 multicolumn {2} 77 chars {bold} 78 } 79 vbar {yes} 80 } 81 pattern Info { 82 vbar {yes} 83 column { 84 } 85 vbar {yes} 86 column { 87 multicolumn {3} 88 chars {bold} 89 format {raw} 90 } 91 vbar {yes} 92 } 93} 94 95set conf(tabmenuipmac) { 96 global { 97 chars {12 normal} 98 align {left} 99 botbar {yes} 100 columns {12 48 15 25} 101 } 102 pattern Data { 103 vbar {yes} 104 column { 105 format {raw} 106 } 107 vbar {yes} 108 column { 109 format {raw} 110 } 111 vbar {yes} 112 column { 113 format {raw} 114 } 115 vbar {yes} 116 column { } 117 vbar {yes} 118 } 119 pattern Title { 120 vbar {yes} 121 column { 122 chars {bold} 123 } 124 vbar {yes} 125 column { 126 chars {bold} 127 } 128 vbar {yes} 129 column { 130 chars {bold} 131 } 132 vbar {yes} 133 column { 134 chars {bold} 135 } 136 vbar {yes} 137 } 138} 139 140set conf(tabmenuportmac) { 141 global { 142 chars {12 normal} 143 align {left} 144 botbar {yes} 145 columns {5 5 10 10 25 25} 146 } 147 pattern Data { 148 vbar {yes} 149 column { 150 format {raw} 151 } 152 vbar {yes} 153 column { 154 format {raw} 155 } 156 vbar {yes} 157 column { 158 format {raw} 159 } 160 vbar {yes} 161 column { 162 } 163 vbar {yes} 164 column { 165 format {raw} 166 } 167 vbar {yes} 168 column { 169 } 170 vbar {yes} 171 } 172 pattern Title { 173 vbar {yes} 174 column { 175 chars {bold} 176 } 177 vbar {yes} 178 column { 179 chars {bold} 180 } 181 vbar {yes} 182 column { 183 chars {bold} 184 } 185 vbar {yes} 186 column { 187 chars {bold} 188 } 189 vbar {yes} 190 column { 191 chars {bold} 192 } 193 vbar {yes} 194 column { 195 chars {bold} 196 } 197 vbar {yes} 198 } 199} 200 201# 202# Script parameters 203# 204 205set conf(sqldateformat) {'DD/MM/YYYY HH24:MI:SS'} 206set conf(clockformat) {%d/%m/%Y %H:%M:%S} 207 208# 209# Netmagis general library 210# 211 212source %LIBNETMAGIS% 213 214# ::webapp::cgidebug ; exit 215 216############################################################################## 217# Utility functions 218############################################################################## 219 220# 221# Guess parameter type 222# 223# Input: 224# - mdbfd : mac database handle 225# - ndbfd : netmagis database handle 226# - param : parameter given by the user 227# - _msg : in return, error message 228# Output: 229# - return value: empty list (error) or list {type param} where 230# - type = "ip", "name", "mac", "idipmac", ... 231# - param = canonical representation of parameter 232# - msg : empty string or error message 233# 234 235proc guess-type {mdbfd ndbfd param _msg} { 236 upvar $_msg msg 237 238 set type "" 239 set msg "" 240 241 set ipversion [::ip::version $param] 242 243 set mac_re {[0-9a-f]{1,2}(:[0-9a-f]{1,2}){5}} 244 set ip4_re {[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+} 245 set ip6_re {[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+} 246 set port_re {[0-9a-zA-Z/.\-]+} 247 set vlan_re {[0-9]+} 248 set ipmac_assoc_re "$mac_re,$ip4_re" 249 set portmac_assoc_re "$ip4_re,$mac_re,$port_re,$vlan_re" 250 set eq_re $ip4_re 251 252 253 if {[regexp "^$mac_re\$" $param]} then { 254 # MAC address 255 set type "mac" 256 } elseif {[regexp {^[0-9a-f]{4}(.[0-9a-f]{4}){2}$} $param]} then { 257 # MAC address with Cisco format (00AB.1234.5678) 258 set n {([0-9a-f]{2})} 259 regsub "^$n$n.$n$n.$n$n" $param {\1:\2:\3:\4:\5:\6} param 260 set type "mac" 261 } elseif {[regexp {^[0-9a-f]{6}-[0-9a-f]{6}$} $param]} then { 262 # MAC address with HP format (00206b-7a1477) 263 set n {([0-9a-f]{2})} 264 regsub "^$n$n$n-$n$n$n" $param {\1:\2:\3:\4:\5:\6} param 265 set type "mac" 266 } elseif {[regexp "^portmac_assoc:($portmac_assoc_re)\$" $param dummy \ 267 portmac_assoc]} then { 268 # portmac association 269 set type "portmac_assoc" 270 set param $portmac_assoc 271 } elseif {[regexp "^ipmac_assoc:($ipmac_assoc_re)\$" $param dummy \ 272 ipmac_assoc]} then { 273 # ipmac association 274 set type "ipmac_assoc" 275 set param $ipmac_assoc 276 } elseif {[regexp "^eq:($eq_re)\$" $param dummy eq]} then { 277 # By equipment 278 set type "equipement" 279 set param $eq 280 } elseif {[regexp "^vlan:($vlan_re)\$" $param dummy vlan]} then { 281 # By VLAN 282 set type "vlan" 283 set param $vlan 284 } elseif {$ipversion == 4 || $ipversion == 6} then { 285 # IP Address 286 set msg [check-ip-syntax $ndbfd $param "inet"] 287 if {$msg eq ""} then { 288 set type "ip" 289 } else { 290 return {} 291 } 292 } elseif {[regexp {^[a-z0-9\-.]+$} $param]} then { 293 # name 294 set type "name" 295 } else { 296 # Other 297 set msg [mc "Invalid search string '%s'" $param] 298 return {} 299 } 300 301 return [list $type $param] 302} 303 304# 305# Display an HTML result with search result 306# 307# Input: 308# - mdbfd : mac database handle 309# - ndbfd : netmagis database handle 310# - type : search type (ip, mac, etc.) 311# - param : search criterion 312# Output: 313# - return value : HTML code 314# 315 316proc html-result {mdbfd ndbfd type param} { 317 set tab "" 318 switch $type { 319 name { 320 set lip [resolve "name" $param resmsg] 321 if {$resmsg ne ""} { 322 d error "resolve: $resmsg" 323 } 324 foreach ip $lip { 325 append tab [gen-choice-ipmac $mdbfd $ndbfd $ip ""] 326 } 327 } 328 ip { 329 append tab [gen-choice-ipmac $mdbfd $ndbfd $param ""] 330 } 331 portmac_assoc { 332 append tab [gen-portmac-assoc $mdbfd $ndbfd $param] 333 } 334 ipmac_assoc { 335 append tab [gen-ipmac-assoc $mdbfd $ndbfd $param] 336 } 337 equipement { 338 append tab [gen-eq $mdbfd $ndbfd $param] 339 } 340 vlan { 341 append tab [gen-vlan $mdbfd $ndbfd $param] 342 } 343 mac { 344 append tab [gen-choice-ipmac $mdbfd $ndbfd "" $param] 345 append tab [gen-mac $mdbfd $ndbfd $param] 346 } 347 default { 348 d error [mc "Internal error: invalid parameter type '%s'" $type] 349 } 350 } 351 return $tab 352} 353 354# 355# Display ip-mac association 356# Input: 357# ipmac_assoc : string containing "ip,mac" 358# Return: 359# html string containing ip-mac association sessions 360# 361 362proc gen-ipmac-assoc {mdbfd ndbfd ipmac_assoc} { 363 global conf 364 365 # 366 # Check if IP and MAC addresses exist 367 # 368 369 lassign [split $ipmac_assoc ","] searchmac searchip 370 set ip "" 371 set mac "" 372 set sql "SELECT (data).ip, (data).mac FROM mac.ipmac 373 WHERE (data).ip = '$searchip' AND (data).mac = '$searchmac' 374 LIMIT 1" 375 pg_select $mdbfd $sql tab { 376 set ip $tab(ip) 377 set mac $tab(mac) 378 } 379 if {$ip eq ""} then { 380 return [mc "IP-MAC association (%1$s,%2$s) not found" $searchip $searchmac] 381 } 382 383 set lines {} 384 385 set dnsname [resolve "ip" $ip resmsg] 386 if {$resmsg ne ""} { 387 d error "resolve: $resmsg" 388 } 389 390 set iplink [gen-link [display-ip $ip $dnsname] $ip] 391 lappend lines [list Info [mc "IP address"] $iplink] 392 393 lappend lines [list Info [mc "MAC address"] \ 394 [gen-link [display-mac $mdbfd $mac] $mac] \ 395 ] 396 397 # 398 # Display sessions 399 # 400 401 set found 0 402 set sql "SELECT to_char(start,$conf(sqldateformat)) AS dstart, 403 to_char(stop,$conf(sqldateformat)) AS dstop, 404 closed AS closed 405 FROM mac.ipmac 406 WHERE (data).ip = '$ip' AND (data).mac = '$mac' 407 ORDER BY start DESC" 408 pg_select $mdbfd $sql tab2 { 409 if {$tab2(closed)} then { set pat "Close" } else { set pat "Active" } 410 if {$found == 0} then { 411 lappend lines [list Active [mc "Start"] [mc "End"]] 412 set found 1 413 } 414 lappend lines [list $pat $tab2(dstart) $tab2(dstop)] 415 } 416 417 if {$found == 0} then { 418 lappend lines [list Rem [mc "No IP-MAC association found"]] 419 } 420 421 # 422 # Format result 423 # 424 425 return [::arrgen::output "html" $conf(tabsession) $lines] 426} 427 428# 429# Display a portmac session list, for a given idportmac 430# 431 432proc gen-portmac-assoc {mdbfd ndbfd portmac_assoc} { 433 global conf 434 435 lassign [split $portmac_assoc ","] searchsrc searchmac searchport searchvlan 436 if {$searchvlan eq ""} then { 437 set searchvlan 0 438 } 439 set lines {} 440 set sql "SELECT (data).mac AS mac, 441 (data).port AS port, 442 src AS src, 443 (data).vlanid AS vlanid 444 FROM mac.portmac 445 WHERE (data).mac='$searchmac' 446 AND lower((data).port)='$searchport' 447 AND (data).vlanid=$searchvlan 448 AND src='$searchsrc'" 449 pg_select $mdbfd $sql tab { 450 lappend lines [list "Info" \ 451 [mc "MAC address"] \ 452 [gen-link [display-mac $mdbfd $tab(mac)] $tab(mac)] \ 453 ] 454 set eq [get-eq-name $ndbfd $tab(src)] 455 lappend lines [list "Info" \ 456 [mc "Equipment"] \ 457 [gen-link $eq "eq:$tab(src)"] \ 458 ] 459 lappend lines [list "Info" \ 460 [mc "Interface"] \ 461 $tab(port) \ 462 ] 463 set vlan [display-vlan $ndbfd $tab(vlanid)] 464 lappend lines [list "Info" \ 465 [mc "Vlan"] \ 466 [gen-link $vlan "vlan:$tab(vlanid)"] \ 467 ] 468 } 469 470 set found 0 471 set sql "SELECT to_char(portmac.start,$conf(sqldateformat)) AS dstart, 472 to_char(portmac.stop,$conf(sqldateformat)) AS dstop, 473 portmac.closed AS closed 474 FROM mac.portmac 475 WHERE (data).mac='$searchmac' 476 AND (data).port='$searchport' 477 AND (data).vlanid=$searchvlan 478 ORDER BY portmac.stop DESC" 479 pg_select $mdbfd $sql tab2 { 480 if {$found==0} then { 481 lappend lines [list Active [mc "Start"] [mc "End"]] 482 set found 1 483 } 484 485 if {$tab2(closed)} then { set pat "Close" } else { set pat "Active" } 486 lappend lines [list $pat $tab2(dstart) $tab2(dstop)] 487 } 488 489 return [::arrgen::output "html" $conf(tabsession) $lines] 490} 491 492# 493# Display a menu of the different IP-MAC associations given an IP or MAC address 494# 495# Input: 496# - ip : ip address (may be null) 497# - mac : mac address (may be null) 498# 499# Output: 500# - return value : HTML code 501# 502 503proc gen-choice-ipmac {mdbfd ndbfd ip mac} { 504 global conf 505 506 # This case should not happen 507 if {$mac eq "" && $ip eq ""} then { 508 return "" 509 } 510 511 set table "" 512 set lines {} 513 lappend lines [list Title \ 514 [mc "Sessions"] \ 515 [mc "IP address"] \ 516 [mc "MAC address"] \ 517 [mc "Last occurrence"] \ 518 ] 519 set crit {} 520 521 if {$ip ne ""} then { 522 lappend crit " (data).ip='$ip' " 523 } 524 525 if {$mac ne ""} then { 526 lappend crit " (data).mac='$mac' " 527 } 528 529 # 530 # Search all ip-mac associations and last occurrence date 531 # 532 533 set n 0 534 set sql "SELECT DISTINCT (data).ip AS ip, (data).mac AS mac 535 FROM mac.ipmac WHERE [join $crit AND]" 536 set d {} 537 pg_select $mdbfd $sql tab { 538 incr n 539 set ipmac_assoc_link [gen-link [mc "Details"] "ipmac_assoc:$tab(mac),$tab(ip)"] 540 set dnsname [resolve "ip" $tab(ip) resmsg] 541 if {$resmsg ne ""} { 542 d error "resolve: $resmsg" 543 } 544 set iplink [gen-link [display-ip $tab(ip) $dnsname] $tab(ip)] 545 546 pg_select $mdbfd "SELECT extract(epoch from max(stop)) AS laststop 547 FROM mac.ipmac 548 WHERE (data).ip='$tab(ip)' AND (data).mac='$tab(mac)'" tab2 { 549 set laststop $tab2(laststop) 550 } 551 552 if {$laststop ne ""} then { 553 set laststop [expr int($laststop)] 554 } else { 555 set laststop 0 556 } 557 set maclink [gen-link [display-mac $mdbfd $tab(mac)] $tab(mac)] 558 lappend d [list Data $ipmac_assoc_link $iplink $maclink $laststop] 559 } 560 561 # 562 # Sort list and convert date 563 # 564 565 foreach l [lsort -index end -integer $d] { 566 set t [lindex $l end] 567 set date [clock format $t -format "$conf(clockformat)"] 568 if {[regexp {^01/01/1970} $date]} then { 569 set date [mc "(no date)"] 570 } 571 lappend lines [lreplace $l end end $date] 572 } 573 574 if {$n > 0} then { 575 set table [mc {%1$s MAC-IP address associations found for %2$s:} $n "$mac$ip"] 576 append table "<br>" 577 append table [::arrgen::output "html" $conf(tabmenuipmac) $lines] 578 } else { 579 set table [mc "No MAC-IP address association found for %s" "$mac$ip"] 580 append table "<br>" 581 } 582 583 append table "<br>" 584 return $table 585} 586 587# 588# Display a menu of the different MAC-port-vlan associations given a 589# MAC address. This is a just a wrapper to gen-choice-portmac 590# 591# Input: 592# - mac : MAC address 593# 594# Output: 595# - return value : HTML code 596# 597 598proc gen-mac {mdbfd ndbfd mac} { 599 if {$mac eq ""} then { 600 return "" 601 } 602 return [gen-choice-portmac $mdbfd $ndbfd "(data).mac='$mac'"] 603} 604 605# 606# Display a menu of MAC-Port-Vlan for an equipment 607# 608# Input: 609# - mdbfd : mac database handle 610# - ndbfd : netmagis database handle 611# - eq : equipment ip address 612# 613# Output: 614# - return value : HTML code 615# 616 617proc gen-eq {mdbfd ndbfd eq} { 618 if {$eq eq ""} then { 619 return [mc "No equipment address"] 620 } 621 return [gen-choice-portmac $mdbfd $ndbfd "portmac.src='$eq'"] 622} 623 624# 625# Display a menu of MAC-Port-Vlan for a Vlan 626# 627# Input: 628# - vlanid : vlan-id 629# 630# Output: 631# - return value : HTML code 632# 633 634proc gen-vlan {mdbfd ndbfd vlanid} { 635 if {[display-vlan $ndbfd $vlanid] eq ""} then { 636 return [mc "Vlan '%s' not found" $vlanid] 637 } 638 return [gen-choice-portmac $mdbfd $ndbfd "(data).vlanid=$vlanid"] 639} 640 641# 642# Search all distinct Port-MAC-vlan associations and last occurrence date 643# according to a criterion (SQL expression). 644# 645 646proc gen-choice-portmac {mdbfd ndbfd crit} { 647 global conf 648 649 set n 0 650 set table "" 651 set lines {} 652 lappend lines [list Title \ 653 [mc "Sessions"] \ 654 [mc "MAC address"] \ 655 [mc "Equipment"] \ 656 [mc "Interface"] \ 657 [mc "Vlan"] \ 658 [mc "Last occurrence"] \ 659 ] 660 set sql "SELECT DISTINCT src AS src, 661 (data).mac AS mac, 662 (data).port AS port, 663 (data).vlanid AS vlanid 664 FROM mac.portmac 665 WHERE $crit 666 GROUP BY src, data" 667 set d {} 668 pg_select $mdbfd $sql tab { 669 incr n 670 set portmac_assoc_link [gen-link [mc "Details"] \ 671 "portmac_assoc:$tab(src),$tab(mac),$tab(port),$tab(vlanid)"] 672 set maclink [gen-link [display-mac $mdbfd $tab(mac)] $tab(mac)] 673 674 if {$tab(vlanid) eq ""} then { 675 set tab(vlanid) 0 676 } 677 set vlanid $tab(vlanid) 678 set vlanlink [gen-link [display-vlan $ndbfd $vlanid] "vlan:$vlanid"] 679 set eqname [get-eq-name $ndbfd $tab(src)] 680 set eqlink [gen-link [display-eq $eqname] "eq:$tab(src)"] 681 682 set sql "SELECT extract(epoch from max(stop)) AS stop 683 FROM mac.portmac 684 WHERE src='$tab(src)' 685 AND (data).mac='$tab(mac)' 686 AND (data).port='$tab(port)' 687 AND (data).vlanid=$tab(vlanid)" 688 set stop "" 689 pg_select $mdbfd $sql tab2 { 690 set stop $tab2(stop) 691 } 692 693 if {$stop ne ""} then { 694 set stop [expr int($stop)] 695 } else { 696 set stop 0 697 } 698 lappend d [list Data \ 699 $portmac_assoc_link $maclink $eqlink $tab(port) $vlanlink $stop ] 700 701 } 702 703 # 704 # Sort list and convert date 705 # 706 707 foreach l [lsort -index end -integer $d] { 708 set t [lindex $l end] 709 set ndate [clock format $t -format "$conf(clockformat)"] 710 if {[regexp {^01/01/1970} $ndate]} then { 711 set ndate [mc "(no date)"] 712 } 713 lappend lines [lreplace $l end end $ndate] 714 } 715 716 if {$n > 0} then { 717 set table [mc "%s MAC-Port-VLAN associations found" $n] 718 append table [::arrgen::output "html" $conf(tabmenuportmac) $lines] 719 } else { 720 set table [mc "No MAC-Port-VLAN association found"] 721 } 722 723 return $table 724} 725 726# 727# Display an HTML link 728# 729 730proc gen-link {text target} { 731 global conf 732 733 d urlset "" $conf(next) [list [list "recherche" $target]] 734 set url [d urlget ""] 735 return [::webapp::helem "a" $text "href" $url] 736} 737 738# 739# Display a Vlan name: "vlanid (description)" or "vlanid" 740# 741 742proc display-vlan {ndbfd vlanid} { 743 global cachevlan 744 745 if {[info exists cachevlan($vlanid)]} then { 746 set descr $cachevlan($vlanid) 747 } else { 748 set descr "" 749 if {[regexp {^[0-9]+$} $vlanid]} then { 750 set sql "SELECT descr AS descr FROM topo.vlan WHERE vlanid=$vlanid" 751 pg_select $ndbfd $sql tab { 752 set descr $tab(descr) 753 } 754 } else { 755 set descr "-" 756 } 757 set cachevlan($vlanid) $descr 758 } 759 760 if {$descr ne ""} then { 761 set dispvlan "$vlanid ($descr)" 762 } else { 763 set dispvlan $vlanid 764 } 765 766 return $dispvlan 767} 768 769proc display-eq {eq} { 770 global conf 771 772 regsub "\.$conf(defaultdomain)\$" $eq "" eq 773 774 return $eq 775} 776 777# 778# Search equipment name given its address 779# 780# Input: 781# - ndbfd : netmagis database handle 782# - addr : ip address of equipment 783# 784# Return: equipment name or empty string if not found 785# 786 787proc get-eq-name {ndbfd addr} { 788 global cacheeq 789 790 if {[info exists cacheeq(addr:$addr)]} then { 791 set eq $cacheeq(addr:$addr) 792 } else { 793 set eq [mc "Unknown equipment (address %s)" $addr] 794 set sql "SELECT rr.name || '.' || domain.name AS fqdn 795 FROM dns.rr_ip, dns.rr, dns.domain 796 WHERE rr_ip.addr = '$addr' 797 AND rr.idrr = rr_ip.idrr 798 AND rr.iddom = domain.iddom" 799 pg_select $ndbfd $sql tab { 800 set eq $tab(fqdn) 801 } 802 set cacheeq(name:$eq) $addr 803 set cacheeq(addr:$addr) $eq 804 } 805 806 return $eq 807} 808 809# 810# Search equipment addr given an equipment name 811# 812# Return: equipment IP address or empty string if not found 813# 814 815proc get-eq-addr {ndbfd eq} { 816 global cacheeq 817 818 if {[info exists cacheeq(name:$eq)]} then { 819 set addr $cacheeq(name:$eq) 820 } else { 821 set l [split $eq "."] 822 set shortname [lindex $l 0] 823 set domain [join [lrange $l 1 end] "."] 824 set sql "SELECT rr_ip.addr 825 FROM dns.rr_ip, dns.rr, dns.domain 826 WHERE rr.idrr = rr_ip.idrr 827 AND rr.iddom = domain.iddom 828 AND rr.name = '$shortname' 829 AND domain.name = '$domain'" 830 set addr "" 831 pg_select $ndbfd $sql tab { 832 set addr $tab(addr) 833 } 834 set cacheeq(addr:$addr) $eq 835 set cacheeq(name:$eq) $addr 836 } 837 return $addr 838} 839 840# 841# Display search criterion on result page as a (somewhat) readable text 842# 843 844proc display-crit {ndbfd type param} { 845 switch $type { 846 mac { set m "MAC address %s" } 847 ip { set m "IP address %s" } 848 ipmac_assoc { set m "IP-MAC" } 849 portmac_assoc { set m "MAC-Port-Vlan" } 850 vlan { set m "Vlan %s" ; set param [display-vlan $ndbfd $param] } 851 name { set m "host %s" } 852 default { set m "???" } 853 } 854 return [mc $m $param] 855} 856 857# 858# Format an IP address: either IP followed by DNS name if it exists, or IP 859# address only. 860# 861 862proc display-ip {ip dnsname} { 863 if {$dnsname ne ""} then { 864 set disp "$ip ($dnsname)" 865 } else { 866 set disp "$ip" 867 } 868 return $disp 869} 870 871# 872# Search OUI for a given MAC address and returns a string built from 873# MAC address and manufacturer name 874# 875# Example: 876# - MAC address "08:00:20:67:89:ab" becomes 877# "08:00:20:67:89:ab (SUN MICROSYSTEMS INC.)" 878# 879# - MAC address mac "01:23:45:67:89:ab" becomes 880# "01:23:45:67:89:ab" 881# (no change since OUI is not found) 882# 883 884proc display-mac {mdbfd mac} { 885 global ouicache 886 887 if {[info exists ouicache($mac)]} then { 888 return $ouicache($mac) 889 } 890 891 set manuf 0 892 pg_select $mdbfd "SELECT mac.manuf('$mac') AS m" tab { 893 set manuf $tab(m) 894 } 895 896 if {$manuf ne ""} then { 897 set dispmac "$mac ($manuf)" 898 } else { 899 set dispmac "$mac" 900 } 901 set ouicache($mac) $dispmac 902 return $dispmac 903} 904 905# 906# DNS resolver : calls "host" command and produces an IP address list or a FQDN 907# 908# Input: 909# - type : "name" for a standard resolution, "ip" for a reverse resolution 910# - arg : resolve parameter 911# Output: 912# - return value: addresse list or domain name 913# 914 915proc resolve {type arg _msg} { 916 global conf 917 global dnscache 918 upvar $_msg msg 919 920 set msg "" 921 922 if {! ([regexp {^[a-z0-9\-.]+$} $arg] || [regexp {^([0-9.]+|[0-9a-f:.]+)$} $arg])} then { 923 return {} 924 } 925 926 # 927 # Filter definition 928 # 929 930 if {[info exists dnscache($arg)]} then { 931 return $dnscache($arg) 932 } 933 934 switch $type { 935 "name" { set pat "address" } 936 "ip" { set pat "domain name pointer" } 937 } 938 939 # 940 # Extract "host" command result 941 # 942 943 set hostcmd [get-local-conf "hostcmd"] 944 if {[catch {exec $hostcmd $arg} buf]} then { 945 if {[regexp {Host .+ not found} $buf]} then { 946 # the host was not found, not an error 947 } else { 948 # real error 949 set msg $buf 950 } 951 set buf "" 952 } 953 954 # 955 # Keep only the last word of each line 956 # 957 958 set l {} 959 foreach line [split $buf "\n"] { 960 if {[regexp $pat $line]} then { 961 lappend l [lindex $line end] 962 } 963 } 964 set dnscache($arg) $l 965 return $l 966} 967 968############################################################################## 969# Display page 970############################################################################## 971 972d cgi-register {recherche {}} {} { 973 global conf 974 975 # 976 # End of script: output page and close database 977 # 978 979 d urlset "%URLFORM%" $conf(next) {} 980 d result $conf(pagesearch) {} 981} 982 983############################################################################## 984# Search 985############################################################################## 986 987d cgi-register {recherche .+} {} { 988 global conf 989 990 # 991 # Save netmagis database handler 992 # 993 994 set ndbfd $dbfd 995 996 997 # 998 # Get default domain 999 # 1000 1001 set conf(defaultdomain) [dnsconfig get "defdomain"] 1002 1003 # 1004 # Open MAC database 1005 # 1006 1007 set conninfo [get-conninfo "macdb"] 1008 if {[catch {set mdbfd [pg_connect -conninfo $conninfo]} msg]} then { 1009 d error $msg 1010 } 1011 1012 # 1013 # Guess search type 1014 # 1015 1016 set recherche [string tolower $recherche] 1017 set l [guess-type $mdbfd $ndbfd $recherche msg] 1018 if {[llength $l] == 0} then { 1019 d error $msg 1020 } 1021 lassign $l type param 1022 1023 # 1024 # Display output 1025 # 1026 1027 set table [html-result $mdbfd $ndbfd $type $param] 1028 if {$table eq ""} then { 1029 set table [mc "No information found"] 1030 } 1031 1032 # 1033 # End of script: output page and close database 1034 # 1035 1036 d result $conf(page) \ 1037 [list \ 1038 [list %RECHERCHE% [display-crit $mdbfd $type $param]] \ 1039 [list %TABLEAU% $table] \ 1040 ] 1041} 1042 1043############################################################################## 1044# Main procedure 1045############################################################################## 1046 1047d cgi-dispatch "mac" "mac" 1048