Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
— |
kismet_auf_dem_pi [2015/06/02 19:57] (aktuell) admin angelegt |
||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | ====== Kismet auf dem Pi ====== | ||
+ | Kismet soll auf dem Pi nicht zum "war-drive" zum Einsatz kommen, sondern ein wenig Überblick über die gewünschten und ggfls. auch unerwünschten Besucher im heimischen Umfeld geben. | ||
+ | ====== Voraussetzungen ====== | ||
+ | Ein paar Pakete und dev-Pakete sind für's kompilieren und für den "Betrieb" notwendig. Außerdem gibt es ein paar Tools, die einem den Umgang mit dem System erleichtern. | ||
+ | <code bash> | ||
+ | # Voraussetzungen | ||
+ | apt-get install build-essential wireshark libncurses5-dev libcap-dev \ | ||
+ | libpcre3-dev libnl-3-dev libnl-genl-3-dev | ||
+ | # Tools | ||
+ | apt-get install vim rcconf | ||
+ | </code> | ||
+ | ====== Kismet kompilieren ====== | ||
+ | <code bash> | ||
+ | wget http://www.kismetwireless.net/code/kismet-2013-03-R1b.tar.gz | ||
+ | tar xvf kismet-2013-03-R1b.tar.gz | ||
+ | cd kismet-2013-03-R1b/ | ||
+ | ./configure --with-suidgroup=pi --prefix=/usr/local/kismet --sysconfdir=/etc/kismet | ||
+ | ########################## OUTPUT | ||
+ | # ... | ||
+ | Configuration complete: | ||
+ | Compiling for: linux-gnueabihf (armv6l) | ||
+ | C++ Library: stdc++ | ||
+ | Installing as group: root | ||
+ | Man pages owned by: man | ||
+ | Installing into: /usr/local/kismet | ||
+ | Setuid group: pi | ||
+ | Terminal Control: ncurses | ||
+ | Linux WEXT capture : yes | ||
+ | OSX/Darwin capture : n/a (only OSX/Darwin) | ||
+ | PCRE Regex Filters : yes | ||
+ | pcap capture: yes | ||
+ | airpcap control: n/a (only Cygwin/Win32) | ||
+ | PPI log format: yes | ||
+ | LibCapability (enhanced | ||
+ | privilege dropping): no | ||
+ | Linux Netlink: yes (mac80211 VAP creation) - libnl-3.0 libnl-genl-3.0 | ||
+ | |||
+ | # ... | ||
+ | ########################################################### | ||
+ | |||
+ | make | ||
+ | make suidinstall | ||
+ | </code> | ||
+ | |||
+ | ====== Konfigurieren ====== | ||
+ | |||
+ | <code bash> | ||
+ | # vi /etc/kismet/kismet.conf | ||
+ | # ... | ||
+ | logprefix=/var/log/kismet | ||
+ | # ... | ||
+ | ncsource=wlan0:type=rt73,forcevap=false,validatefcs=true | ||
+ | # ... | ||
+ | #ouifile=/etc/manuf | ||
+ | ouifile=/etc/kismet/manuf | ||
+ | # ... | ||
+ | gps=false | ||
+ | # ... | ||
+ | </code> | ||
+ | |||
+ | Eine aktuelle Manufacture (manuf) Datei holen: | ||
+ | <code bash> | ||
+ | cd /etc/kismet/ | ||
+ | wget http://anonsvn.wireshark.org/wireshark/trunk/manuf | ||
+ | </code> | ||
+ | |||
+ | <code bash> | ||
+ | # vi /etc/default/ifplugd | ||
+ | # ... | ||
+ | #INTERFACES="auto" | ||
+ | INTERFACES="eth0" | ||
+ | #HOTPLUG_INTERFACES="all" | ||
+ | HOTPLUG_INTERFACES="" | ||
+ | # ... | ||
+ | </code> | ||
+ | |||
+ | ===== Startskript ===== | ||
+ | Aus dem Skeleton-Skript (/etc/init.d/skeleton) lässt sich "auf die Schnelle" ein Startskript bauen, damit der kismet_server automatisch startet. Mit Hilfe von "rcconf" lässt sich dies dann auch in die entsprechende Systemkonfiguration einfügen. | ||
+ | |||
+ | <code bash kismet_server> | ||
+ | #! /bin/sh | ||
+ | ### BEGIN INIT INFO | ||
+ | # Provides: skeleton | ||
+ | # Required-Start: $remote_fs $syslog | ||
+ | # Required-Stop: $remote_fs $syslog | ||
+ | # Default-Start: 2 3 4 5 | ||
+ | # Default-Stop: 0 1 6 | ||
+ | # Short-Description: Example initscript | ||
+ | # Description: This file should be used to construct scripts to be | ||
+ | # placed in /etc/init.d. | ||
+ | ### END INIT INFO | ||
+ | |||
+ | # Author: Foo Bar <foobar@baz.org> | ||
+ | # | ||
+ | # Please remove the "Author" lines above and replace them | ||
+ | # with your own name if you copy and modify this script. | ||
+ | |||
+ | # Do NOT "set -e" | ||
+ | |||
+ | # PATH should only include /usr/* if it runs after the mountnfs.sh script | ||
+ | PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/kismet/bin | ||
+ | DESC="Kismet Server" | ||
+ | NAME=kismet_server | ||
+ | DAEMON=/usr/local/kismet/bin/kismet_server | ||
+ | DAEMON_ARGS="--daemonize" | ||
+ | PIDFILE=/var/run/$NAME.pid | ||
+ | SCRIPTNAME=/etc/init.d/$NAME | ||
+ | |||
+ | # Exit if the package is not installed | ||
+ | [ -x "$DAEMON" ] || exit 0 | ||
+ | |||
+ | # Read configuration variable file if it is present | ||
+ | [ -r /etc/default/$NAME ] && . /etc/default/$NAME | ||
+ | |||
+ | # Load the VERBOSE setting and other rcS variables | ||
+ | . /lib/init/vars.sh | ||
+ | |||
+ | # Define LSB log_* functions. | ||
+ | # Depend on lsb-base (>= 3.2-14) to ensure that this file is present | ||
+ | # and status_of_proc is working. | ||
+ | . /lib/lsb/init-functions | ||
+ | |||
+ | # | ||
+ | # Function that starts the daemon/service | ||
+ | # | ||
+ | do_start() | ||
+ | { | ||
+ | # Return | ||
+ | # 0 if daemon has been started | ||
+ | # 1 if daemon was already running | ||
+ | # 2 if daemon could not be started | ||
+ | start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ | ||
+ | || return 1 | ||
+ | start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ | ||
+ | $DAEMON_ARGS \ | ||
+ | || return 2 | ||
+ | # Add code here, if necessary, that waits for the process to be ready | ||
+ | # to handle requests from services started subsequently which depend | ||
+ | # on this one. As a last resort, sleep for some time. | ||
+ | } | ||
+ | |||
+ | # | ||
+ | # Function that stops the daemon/service | ||
+ | # | ||
+ | do_stop() | ||
+ | { | ||
+ | # Return | ||
+ | # 0 if daemon has been stopped | ||
+ | # 1 if daemon was already stopped | ||
+ | # 2 if daemon could not be stopped | ||
+ | # other if a failure occurred | ||
+ | start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME | ||
+ | RETVAL="$?" | ||
+ | [ "$RETVAL" = 2 ] && return 2 | ||
+ | # Wait for children to finish too if this is a daemon that forks | ||
+ | # and if the daemon is only ever run from this initscript. | ||
+ | # If the above conditions are not satisfied then add some other code | ||
+ | # that waits for the process to drop all resources that could be | ||
+ | # needed by services started subsequently. A last resort is to | ||
+ | # sleep for some time. | ||
+ | start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON | ||
+ | [ "$?" = 2 ] && return 2 | ||
+ | # Many daemons don't delete their pidfiles when they exit. | ||
+ | rm -f $PIDFILE | ||
+ | return "$RETVAL" | ||
+ | } | ||
+ | |||
+ | # | ||
+ | # Function that sends a SIGHUP to the daemon/service | ||
+ | # | ||
+ | do_reload() { | ||
+ | # | ||
+ | # If the daemon can reload its configuration without | ||
+ | # restarting (for example, when it is sent a SIGHUP), | ||
+ | # then implement that here. | ||
+ | # | ||
+ | start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME | ||
+ | return 0 | ||
+ | } | ||
+ | |||
+ | case "$1" in | ||
+ | start) | ||
+ | [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" | ||
+ | do_start | ||
+ | case "$?" in | ||
+ | 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; | ||
+ | 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; | ||
+ | esac | ||
+ | ;; | ||
+ | stop) | ||
+ | [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" | ||
+ | do_stop | ||
+ | case "$?" in | ||
+ | 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; | ||
+ | 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; | ||
+ | esac | ||
+ | ;; | ||
+ | status) | ||
+ | status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? | ||
+ | ;; | ||
+ | #reload|force-reload) | ||
+ | # | ||
+ | # If do_reload() is not implemented then leave this commented out | ||
+ | # and leave 'force-reload' as an alias for 'restart'. | ||
+ | # | ||
+ | #log_daemon_msg "Reloading $DESC" "$NAME" | ||
+ | #do_reload | ||
+ | #log_end_msg $? | ||
+ | #;; | ||
+ | restart|force-reload) | ||
+ | # | ||
+ | # If the "reload" option is implemented then remove the | ||
+ | # 'force-reload' alias | ||
+ | # | ||
+ | log_daemon_msg "Restarting $DESC" "$NAME" | ||
+ | do_stop | ||
+ | case "$?" in | ||
+ | 0|1) | ||
+ | do_start | ||
+ | case "$?" in | ||
+ | 0) log_end_msg 0 ;; | ||
+ | 1) log_end_msg 1 ;; # Old process is still running | ||
+ | *) log_end_msg 1 ;; # Failed to start | ||
+ | esac | ||
+ | ;; | ||
+ | *) | ||
+ | # Failed to stop | ||
+ | log_end_msg 1 | ||
+ | ;; | ||
+ | esac | ||
+ | ;; | ||
+ | *) | ||
+ | #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 | ||
+ | echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 | ||
+ | exit 3 | ||
+ | ;; | ||
+ | esac | ||
+ | |||
+ | </code> | ||
+ | |||
+ | |||
+ | ====== plugins ====== | ||
+ | Die Plugins werden im Source-Code mitgeliefert, müssen aber noch kompiliert werden. | ||
+ | Man kann alle Plugins "auf ein Mal" kompilieren: | ||
+ | <code bash> | ||
+ | cd /install/kismet-2013-03-R1b | ||
+ | make plugins | ||
+ | make plugins-install | ||
+ | </code> | ||
+ | |||
+ | Benötigt werden für dieses "Projekt" aber nur das 'plugin-syslog' und das 'plugin-btscan'. | ||
+ | ===== plugin-syslog ===== | ||
+ | Explizites Kompilieren des plugin-syslog | ||
+ | <code bash> | ||
+ | cd /install/kismet-2013-03-R1b/plugin-syslog | ||
+ | export KIS_SRC_DIR=/install/kismet-2013-03-R1b # Pfad zu den Kismet-Sourcen mitgeben | ||
+ | export KIS_DEST_DIR=/usr/local/kismet/plugins # Installations-Ziel | ||
+ | # funktioniert so nicht. | ||
+ | # Plugins werden nach /usr/local/kismet/lib/kismet installiert | ||
+ | make | ||
+ | make install | ||
+ | </code> | ||
+ | |||
+ | ===== config ===== | ||
+ | In der kismet.conf | ||
+ | <code bash> | ||
+ | # vi /etc/kismet/kismet.conf | ||
+ | # ... | ||
+ | # servername=Kismet Server | ||
+ | servername=kismet | ||
+ | # => hiermit wird der Syslog-Tag gefüllt. Wenn nichts angegeben wird, | ||
+ | # wird der Hostname genommen, der eh schon im Syslog steht. | ||
+ | # ... | ||
+ | # JB NEW -> | ||
+ | # Syslog log types can be: | ||
+ | # all All messages from Kismet are logged | ||
+ | # none No messages from Kismet are logged | ||
+ | # info INFO-class messages | ||
+ | # error ERROR-class messages | ||
+ | # fatal FATAL-class messages | ||
+ | # alert ALERT-class messages | ||
+ | syslogtype=all | ||
+ | # <- JB NEW | ||
+ | # ... | ||
+ | #logtypes=pcapdump,gpsxml,netxml,nettxt,alert | ||
+ | logtypes=alerts | ||
+ | # wenn das plugin-syslog benutzt wird, kann auf die meissten logs verzichtet werden. | ||
+ | </code> | ||
+ | |||
+ | ===== plugin-btscan ===== | ||
+ | Bluetooth-Erkennung | ||
+ | <code bash> | ||
+ | apt-get install bluetooth libbluetooth-dev | ||
+ | cd /install/kismet-2013-03-R1b/plugin-btscan | ||
+ | export KIS_SRC_DIR=/install/kismet-2013-03-R1b # Pfad zu den Kismet-Sourcen mitgeben | ||
+ | make | ||
+ | make install | ||
+ | </code> | ||
+ | ====== Weiterverarbeitung / WhoIsWho ====== | ||
+ | Zur Weiterverarbeitung sollen die Syslog-Meldungen in eine MySQL-DB geschrieben werden. Wir nutzen dazu das rsyslog-MySQL Modul und lassen den rsyslog direkt passend filtern. | ||
+ | |||
+ | <code bash> | ||
+ | apt-get install rsyslog-mysql | ||
+ | # ... | ||
+ | # dbconfig-common | ||
+ | # Konfigurieren der Datenbank für rsyslog-mysql mit dbconfig-common? <Nein> | ||
+ | </code> | ||
+ | |||
+ | Die automatische Konfiguration wird abgelehnt, da eine DB auf einem anderen System genutzt werden soll und weil zusätzliche Tabellen benötigt werden. | ||
+ | |||
+ | ===== rsyslog ===== | ||
+ | Die vom MySQL-Modul mitgebrachte /etc/rsyslog.d/mysql.conf kann gelöscht werden. | ||
+ | <code bash kismet.conf> | ||
+ | # vi /etc/rsyslog.d/kismet.conf | ||
+ | # MySQL Modul | ||
+ | $ModLoad ommysql | ||
+ | # 1 Tabelle - alles vom Kismet | ||
+ | if $syslogtag startswith 'kismet:' then :ommysql:192.168.11.11,kismet,kismet,password | ||
+ | # zweite Tabelle - nur Netzwerke und clients | ||
+ | $template SystemEventsKismet,"insert into Incoming (FromHost, Facility, Priority, Message, DeviceReportedTime, ReceivedAt, InfoUnitID, SyslogTag ) values ('%HOSTNAME%', ' %syslogfacility%', '%syslogpriority%', '%msg%', '%timereported:::date-mysql%', '%timegenerated:::date-mysql%', %iut%, '%syslogtag%')",SQL | ||
+ | #if $syslogtag startswith 'kismet:' then :ommysql:192.168.11.11,kismet,kismet,password;SystemEventsKismet | ||
+ | :msg,contains,"new managed network" :ommysql:192.168.11.11,kismet,kismet,password;SystemEventsKismet | ||
+ | :msg,contains,"new probe network" :ommysql:192.168.11.11,kismet,kismet,password;SystemEventsKismet | ||
+ | :msg,contains,"new data network" :ommysql:192.168.11.11,kismet,kismet,password;SystemEventsKismet | ||
+ | :msg,contains,"new ad-hoc network" :ommysql:192.168.11.11,kismet,kismet,password;SystemEventsKismet | ||
+ | </code> | ||
+ | |||
+ | |||
+ | ===== Datenbank ===== | ||
+ | Für die Datenbank brauchen wir, falls noch nicht vorhanden, einen MySQL-Server und sinnvollerweise PHPMyAdmin für die Verwaltung. | ||
+ | <code bash> | ||
+ | apt-get install mysql-server | ||
+ | apt-get install phpmyadmin | ||
+ | </code> | ||
+ | |||
+ | Die entsprechende Datenbank kann dann über den Reiter "SQL" im PHPMyAdmin angelegt werden. Bitte vorher "mypassword" durch etwas sinnvolles ersetzen. | ||
+ | |||
+ | ==== whoiswho.sql ==== | ||
+ | |||
+ | <code sql whoiswho.sql> | ||
+ | -- | ||
+ | -- Anlegen der DB und eines entsprechenden Users | ||
+ | -- | ||
+ | CREATE USER 'kismet'@'%' IDENTIFIED BY 'mypassword'; | ||
+ | GRANT USAGE ON * . * TO 'kismet'@'%' IDENTIFIED BY 'mypassword' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ; | ||
+ | CREATE DATABASE IF NOT EXISTS `kismet` ; | ||
+ | GRANT ALL PRIVILEGES ON `kismet` . * TO 'kismet'@'%'; | ||
+ | |||
+ | -- -------------------------------------------------------- | ||
+ | |||
+ | -- | ||
+ | -- Tabellenstruktur für Tabelle `Incoming` | ||
+ | -- | ||
+ | |||
+ | CREATE TABLE IF NOT EXISTS `Incoming` ( | ||
+ | `ID` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||
+ | `CustomerID` bigint(20) DEFAULT NULL, | ||
+ | `ReceivedAt` datetime DEFAULT NULL, | ||
+ | `DeviceReportedTime` datetime DEFAULT NULL, | ||
+ | `Facility` smallint(6) DEFAULT NULL, | ||
+ | `Priority` smallint(6) DEFAULT NULL, | ||
+ | `FromHost` varchar(60) DEFAULT NULL, | ||
+ | `Message` text, | ||
+ | `NTSeverity` int(11) DEFAULT NULL, | ||
+ | `Importance` int(11) DEFAULT NULL, | ||
+ | `EventSource` varchar(60) DEFAULT NULL, | ||
+ | `EventUser` varchar(60) DEFAULT NULL, | ||
+ | `EventCategory` int(11) DEFAULT NULL, | ||
+ | `EventID` int(11) DEFAULT NULL, | ||
+ | `EventBinaryData` text, | ||
+ | `MaxAvailable` int(11) DEFAULT NULL, | ||
+ | `CurrUsage` int(11) DEFAULT NULL, | ||
+ | `MinUsage` int(11) DEFAULT NULL, | ||
+ | `MaxUsage` int(11) DEFAULT NULL, | ||
+ | `InfoUnitID` int(11) DEFAULT NULL, | ||
+ | `SysLogTag` varchar(60) DEFAULT NULL, | ||
+ | `EventLogType` varchar(60) DEFAULT NULL, | ||
+ | `GenericFileName` varchar(60) DEFAULT NULL, | ||
+ | `SystemID` int(11) DEFAULT NULL, | ||
+ | `processid` varchar(60) NOT NULL DEFAULT '', | ||
+ | `checksum` int(11) unsigned NOT NULL DEFAULT '0', | ||
+ | PRIMARY KEY (`ID`), | ||
+ | KEY `FromHost` (`FromHost`), | ||
+ | KEY `checksum` (`checksum`), | ||
+ | KEY `DeviceReportedTime` (`DeviceReportedTime`), | ||
+ | KEY `EventID` (`EventID`), | ||
+ | KEY `InfoUnitID` (`InfoUnitID`) | ||
+ | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=33 ; | ||
+ | |||
+ | -- -------------------------------------------------------- | ||
+ | |||
+ | -- | ||
+ | -- Tabellenstruktur für Tabelle `Manufacturer` | ||
+ | -- | ||
+ | |||
+ | CREATE TABLE IF NOT EXISTS `Manufacturer` ( | ||
+ | `MAC` varchar(20) NOT NULL, | ||
+ | `ShortDescription` varchar(20) NOT NULL, | ||
+ | `Description` text NOT NULL, | ||
+ | PRIMARY KEY (`MAC`) | ||
+ | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; | ||
+ | |||
+ | -- -------------------------------------------------------- | ||
+ | |||
+ | -- | ||
+ | -- Tabellenstruktur für Tabelle `Seen` | ||
+ | -- | ||
+ | |||
+ | CREATE TABLE IF NOT EXISTS `Seen` ( | ||
+ | `ID` int(11) NOT NULL AUTO_INCREMENT, | ||
+ | `SyslogID` int(11) NOT NULL, | ||
+ | `MAC` varchar(20) NOT NULL, | ||
+ | `Time` datetime NOT NULL, | ||
+ | `Name` varchar(50) NOT NULL, | ||
+ | `Type` varchar(20) NOT NULL, | ||
+ | `Encryption` varchar(10) NOT NULL, | ||
+ | `Channel` int(3) NOT NULL, | ||
+ | `BitRate` int(8) NOT NULL, | ||
+ | PRIMARY KEY (`ID`) | ||
+ | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ; | ||
+ | |||
+ | |||
+ | -- -------------------------------------------------------- | ||
+ | |||
+ | -- | ||
+ | -- Tabellenstruktur für Tabelle `SystemEvents` | ||
+ | -- | ||
+ | |||
+ | CREATE TABLE IF NOT EXISTS `SystemEvents` ( | ||
+ | `ID` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||
+ | `CustomerID` bigint(20) DEFAULT NULL, | ||
+ | `ReceivedAt` datetime DEFAULT NULL, | ||
+ | `DeviceReportedTime` datetime DEFAULT NULL, | ||
+ | `Facility` smallint(6) DEFAULT NULL, | ||
+ | `Priority` smallint(6) DEFAULT NULL, | ||
+ | `FromHost` varchar(60) DEFAULT NULL, | ||
+ | `Message` text, | ||
+ | `NTSeverity` int(11) DEFAULT NULL, | ||
+ | `Importance` int(11) DEFAULT NULL, | ||
+ | `EventSource` varchar(60) DEFAULT NULL, | ||
+ | `EventUser` varchar(60) DEFAULT NULL, | ||
+ | `EventCategory` int(11) DEFAULT NULL, | ||
+ | `EventID` int(11) DEFAULT NULL, | ||
+ | `EventBinaryData` text, | ||
+ | `MaxAvailable` int(11) DEFAULT NULL, | ||
+ | `CurrUsage` int(11) DEFAULT NULL, | ||
+ | `MinUsage` int(11) DEFAULT NULL, | ||
+ | `MaxUsage` int(11) DEFAULT NULL, | ||
+ | `InfoUnitID` int(11) DEFAULT NULL, | ||
+ | `SysLogTag` varchar(60) DEFAULT NULL, | ||
+ | `EventLogType` varchar(60) DEFAULT NULL, | ||
+ | `GenericFileName` varchar(60) DEFAULT NULL, | ||
+ | `SystemID` int(11) DEFAULT NULL, | ||
+ | `processid` varchar(60) NOT NULL DEFAULT '', | ||
+ | `checksum` int(11) unsigned NOT NULL DEFAULT '0', | ||
+ | PRIMARY KEY (`ID`), | ||
+ | KEY `FromHost` (`FromHost`), | ||
+ | KEY `checksum` (`checksum`), | ||
+ | KEY `DeviceReportedTime` (`DeviceReportedTime`), | ||
+ | KEY `EventID` (`EventID`), | ||
+ | KEY `InfoUnitID` (`InfoUnitID`) | ||
+ | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=288 ; | ||
+ | |||
+ | -- -------------------------------------------------------- | ||
+ | |||
+ | -- | ||
+ | -- Tabellenstruktur für Tabelle `WellKnown` | ||
+ | -- | ||
+ | |||
+ | CREATE TABLE IF NOT EXISTS `WellKnown` ( | ||
+ | `MAC` varchar(20) NOT NULL, | ||
+ | `Comment` text NOT NULL, | ||
+ | PRIMARY KEY (`MAC`) | ||
+ | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; | ||
+ | |||
+ | |||
+ | </code> | ||
+ | |||
+ | ===== Webfrontend ===== | ||
+ | <code bash> | ||
+ | apt-get install apache2 php5 php5-mysql | ||
+ | </code> | ||
+ | |||
+ | Ein einfaches Webfront-End lässt sich schnell mit PHP erstellen. Natürlich braucht der Apache dafür noch eine entsprechende Config. | ||
+ | |||
+ | <code apache> | ||
+ | # vi /etc/apache2/conf.d/whoiswho.conf | ||
+ | Alias /whoiswho "/usr/local/whoiswho" | ||
+ | |||
+ | <Directory "/usr/local/whoiswho"> | ||
+ | Options +FollowSymLinks | ||
+ | AllowOverride None | ||
+ | # AuthName "WhoIsWho Access" | ||
+ | # AuthType Basic | ||
+ | # AuthUserFile /usr/local/whoiswho/etc/htpasswd.users | ||
+ | # Require valid-user | ||
+ | </Directory> | ||
+ | </code> | ||
+ | |||
+ | Unter /usr/local/whoiswho wird die eigentliche Webseite angelegt. | ||
+ | <code bash> | ||
+ | mkdir /usr/local/whoiswho | ||
+ | mkdir /usr/local/whoiswho/cron | ||
+ | mkdir /usr/local/whoiswho/etc | ||
+ | mkdir /usr/local/whoiswho/include | ||
+ | #mkdir /usr/local/whoiswho/images # noch nicht benötigt | ||
+ | </code> | ||
+ | |||
+ | ==== index.php ==== | ||
+ | |||
+ | <code php index.php> | ||
+ | <!-- vi /usr/local/whoiswho/index.php --> | ||
+ | <?php | ||
+ | # SESSION_NAME("WHOISWHO"); | ||
+ | # SESSION_START(); | ||
+ | require_once("etc/whoiswho.conf.php"); | ||
+ | require_once("include/mysql.inc.php"); | ||
+ | require_once("include/tools.inc.php"); | ||
+ | if (isset($_GET['col']) && is_numeric($_GET['col']) ) { | ||
+ | //isset prüft, ob eine Variable gesetzt ist | ||
+ | if ($_GET['col'] >= 0 && $_GET['col'] < 5) { | ||
+ | //Validitätsprüfung, nur Spalten 0..4 erlaubt | ||
+ | $sort_column = $_GET['col']; | ||
+ | } else { | ||
+ | echo "<H1>HANDS OFF MY URL!!!</H1>"; | ||
+ | $sort_column = 0; | ||
+ | } | ||
+ | } else { | ||
+ | $sort_column = 0; | ||
+ | }; | ||
+ | if (isset($_GET['group'])) | ||
+ | { $group = $_GET['group']; } else { $group = "no"; }; | ||
+ | #error_log("INDEX.PHP GROUP: $group"); | ||
+ | $title = "Who are my 'wireless' visitors"; | ||
+ | $db = dbconnect(); | ||
+ | $table = SEENTABLE; | ||
+ | switch($sort_column) | ||
+ | { | ||
+ | case '0': | ||
+ | $sql = "SELECT * FROM $table ORDER BY ID DESC"; | ||
+ | $title = $title." (sort by ID)"; | ||
+ | break; | ||
+ | case '1': | ||
+ | $sql = "SELECT * FROM $table ORDER BY TIME DESC"; | ||
+ | $title = $title." (sort by Time)"; | ||
+ | break; | ||
+ | case '2': | ||
+ | if ($group == "yes") | ||
+ | { | ||
+ | $sql = "SELECT * FROM $table GROUP BY MAC ASC"; | ||
+ | $title = $title." (grouped by MAC)"; | ||
+ | } else { | ||
+ | $sql = "SELECT * FROM $table ORDER BY MAC ASC"; | ||
+ | $title = $title." (sort by MAC)"; | ||
+ | }; | ||
+ | break; | ||
+ | case '3': | ||
+ | if ($group == "yes") | ||
+ | { | ||
+ | $sql = "SELECT * FROM $table GROUP BY Name DESC"; | ||
+ | $title = $title." (grouped by Network name)"; | ||
+ | } else { | ||
+ | $sql = "SELECT * FROM $table ORDER BY Name DESC"; | ||
+ | $title = $title." (sort by Network name)"; | ||
+ | }; | ||
+ | break; | ||
+ | case '4': | ||
+ | $sql = "SELECT * FROM $table ORDER BY Type DESC"; | ||
+ | $title = $title." (sort by Network type)"; | ||
+ | break; | ||
+ | default: | ||
+ | $sql = "SELECT * FROM $table ORDER BY Time DESC;"; | ||
+ | $title = $title." (sort by Time)"; | ||
+ | } | ||
+ | ?> | ||
+ | |||
+ | <html> | ||
+ | <head> | ||
+ | <title>'WhoIsWho'</title> | ||
+ | <meta charset="utf-8"> | ||
+ | <link rel="stylesheet" type="text/css" href="whoiswho.css"> | ||
+ | <meta http-equiv="refresh" content="60"> | ||
+ | </head> | ||
+ | |||
+ | <body> | ||
+ | <table width=1000><caption><?=$title;?></caption> | ||
+ | <thead> | ||
+ | <th style='width:50px'><a href="index.php?col=0">ID</a></th> | ||
+ | <th style='width:150px'><a href="index.php?col=1">Time</a></th> | ||
+ | <th style='width:150px'><a href="index.php?col=2">MAC</a> <a href="index.php?col=2&group=yes">(group)</a></th> | ||
+ | <th style='width:200px'><a href="index.php?col=3">Network name</a> <a href="index.php?col=3&group=yes">(group)</a></th> | ||
+ | <th style='width:100px'><a href="index.php?col=4">Network type</a></th> | ||
+ | <th style='width:400px'>Comment</th> | ||
+ | </thead> | ||
+ | <tbody> | ||
+ | |||
+ | <?php | ||
+ | $sth = $db->query($sql); | ||
+ | while ($row = $sth->fetch()) | ||
+ | { | ||
+ | $comment = lookup_mac($row['MAC']); | ||
+ | ?> | ||
+ | <tr> | ||
+ | <td><?=$row['ID'];?></td> | ||
+ | <td><?=$row['Time'];?></td> | ||
+ | <td><a href="#" onclick='window.open("macinfo.php?mac=<?=$row['MAC'];?>&comment=<?=$comment;?>","WhoIsWho MAC-Info","directories=0,titlebar=0,toolbar=0,location=0,status=0,menubar=0,scrollbars=yes,resizable=no,width=650,height=350"); return false;'><?=$row['MAC'];?></a></td> | ||
+ | <td><a href="#" onclick='window.open("netinfo.php?net=<?=$row['Name'];?>","WhoIsWho Network-Info","directories=0,titlebar=0,toolbar=0,location=0,status=0,menubar=0,scrollbars=yes,resizable=no,width=950,height=350"); return false;'><?=$row['Name'];?></a></td> | ||
+ | <td><?=$row['Type'];?></td> | ||
+ | <td><?=$comment;?></td> | ||
+ | </tr> | ||
+ | <?php | ||
+ | } | ||
+ | ?> | ||
+ | </tbody> | ||
+ | </thead> | ||
+ | </body> | ||
+ | </html> | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ==== whoiswho.css ==== | ||
+ | <code css whoiswho.css> | ||
+ | <!-- vi /usr/local/whoiswho/whoiswho.css --> | ||
+ | table { | ||
+ | margin:0; | ||
+ | padding:0; | ||
+ | font-family: arial, verdana, serif; | ||
+ | color: black; | ||
+ | font-size: 11px; | ||
+ | } | ||
+ | |||
+ | table, tr, th, td { | ||
+ | border-collapse: collapse; | ||
+ | } | ||
+ | |||
+ | caption { | ||
+ | margin:0; | ||
+ | padding:0; | ||
+ | background: #f0f0f0; | ||
+ | height: 25px; | ||
+ | line-height: 25px; | ||
+ | text-indent: 5px; | ||
+ | font-family: arial, verdana, serif; | ||
+ | font-weight: bold; | ||
+ | color: black; | ||
+ | font-size: 13px; | ||
+ | text-align: left; | ||
+ | /*letter-spacing: 3px;*/ | ||
+ | border: solid 1px #c0c0c0; | ||
+ | } | ||
+ | |||
+ | thead th { | ||
+ | height: 22px; | ||
+ | line-height: 20px; | ||
+ | text-align: left; | ||
+ | color: black; | ||
+ | font-size: 13px; | ||
+ | background: #A2A2A2; | ||
+ | } | ||
+ | |||
+ | tbody tr { | ||
+ | background: white; | ||
+ | padding: 3px; | ||
+ | } | ||
+ | |||
+ | tbody tr:hover { | ||
+ | background: #d0d0d0; | ||
+ | /*text-decoration: underline;*/ | ||
+ | } | ||
+ | |||
+ | table a { | ||
+ | /*color: #2c3763;*/ | ||
+ | color: black; | ||
+ | text-decoration: none; | ||
+ | font-size: 11px; | ||
+ | font-weight: bold; | ||
+ | border-bottom: solid 1px black; | ||
+ | } | ||
+ | |||
+ | table a:hover { | ||
+ | /*color: #2c3763;*/ | ||
+ | color: black; | ||
+ | font-weight: bold; | ||
+ | text-decoration: underline; | ||
+ | border-bottom: none; | ||
+ | } | ||
+ | |||
+ | table a:visited { | ||
+ | /*color: #2c3763;*/ | ||
+ | color: black; | ||
+ | font-weight: bold; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ==== macinfo.php ==== | ||
+ | <code php macinfo.php> | ||
+ | <!-- vi /usr/local/whoiswho/macinfo.php --> | ||
+ | <?php | ||
+ | require_once("etc/whoiswho.conf.php"); | ||
+ | require_once("include/mysql.inc.php"); | ||
+ | require_once("include/tools.inc.php"); | ||
+ | if (isset($_GET['mac'])) | ||
+ | { | ||
+ | $mac = $_GET['mac']; | ||
+ | // Prüfen ob MAC-Aufbau | ||
+ | // preg_grep('/([a-fA-F0-9]{2}[:|\-]?){6}/', $msg) | ||
+ | } else { | ||
+ | $mac = "unkown"; | ||
+ | }; | ||
+ | |||
+ | if (isset($_GET['comment'])) | ||
+ | { | ||
+ | $comment = $_GET['comment']; | ||
+ | } else { | ||
+ | $comment = "unkown"; | ||
+ | }; | ||
+ | |||
+ | $db = dbconnect(); | ||
+ | $table = SEENTABLE; | ||
+ | $title = "MAC Info for $mac - $comment"; | ||
+ | ?> | ||
+ | |||
+ | <html> | ||
+ | <head> | ||
+ | <title>'WhoIsWho - MAC Info'</title> | ||
+ | <meta charset="utf-8"> | ||
+ | <link rel="stylesheet" type="text/css" href="whoiswho.css"> | ||
+ | <!-- <meta http-equiv="refresh" content="60"> --> | ||
+ | </head> | ||
+ | |||
+ | <body> | ||
+ | <table width=620><caption><?=$title;?></caption> | ||
+ | <thead> | ||
+ | <th style='width:120px'>Time</th> | ||
+ | <th style='width:100px'>Network name</th> | ||
+ | <th style='width:100px'>Network type</th> | ||
+ | <th style='width:100px'>Encryption</th> | ||
+ | <th style='width:100px'>Channel</th> | ||
+ | <th style='width:100px'>BitRate</th> | ||
+ | </thead> | ||
+ | <tbody> | ||
+ | |||
+ | <?php | ||
+ | $sql = "SELECT * FROM $table WHERE MAC='$mac' ORDER BY Time DESC;"; | ||
+ | $sth = $db->query($sql); | ||
+ | $sql_rc = $db->errorCode(); | ||
+ | error_log("$sql_rc\n"); | ||
+ | |||
+ | while ($row = $sth->fetch()) | ||
+ | { | ||
+ | ?> | ||
+ | <tr> | ||
+ | <td><?=$row['Time'];?></td> | ||
+ | <td><a href="#" onclick='window.open("netinfo.php?net=<?=$row['Name'];?>","WhoIsWho Network-Info","directories=0,titlebar=0,toolbar=0,location=0,status=0,menubar=0,scrollbars=yes,resizable=no,width=950,height=350"); return false;'><?=$row['Name'];?></a></td> | ||
+ | <td><?=$row['Type'];?></td> | ||
+ | <td><?=$row['Encryption'];?></td> | ||
+ | <td><?=$row['Channel'];?></td> | ||
+ | <td><?=$row['BitRate'];?></td> | ||
+ | <?php | ||
+ | } | ||
+ | ?> | ||
+ | </tbody> | ||
+ | </thead> | ||
+ | </body> | ||
+ | </html> | ||
+ | </code> | ||
+ | |||
+ | ==== netinfo.php ==== | ||
+ | <code php netinfo.php> | ||
+ | <!-- vi /usr/local/whoiswho/netinfo.php --> | ||
+ | <?php | ||
+ | require_once("etc/whoiswho.conf.php"); | ||
+ | require_once("include/mysql.inc.php"); | ||
+ | require_once("include/tools.inc.php"); | ||
+ | if (isset($_GET['net'])) | ||
+ | { | ||
+ | $net = $_GET['net']; | ||
+ | } else { | ||
+ | $net = "unkown"; | ||
+ | }; | ||
+ | |||
+ | $db = dbconnect(); | ||
+ | $table = SEENTABLE; | ||
+ | $title = "More Info for $net"; | ||
+ | ?> | ||
+ | |||
+ | <html> | ||
+ | <head> | ||
+ | <title>'WhoIsWho - Network Info'</title> | ||
+ | <meta charset="utf-8"> | ||
+ | <link rel="stylesheet" type="text/css" href="whoiswho.css"> | ||
+ | <!-- <meta http-equiv="refresh" content="60"> --> | ||
+ | </head> | ||
+ | |||
+ | <body> | ||
+ | <table width=920><caption><?=$title;?></caption> | ||
+ | <thead> | ||
+ | <th style='width:120px'>Time</th> | ||
+ | <th style='width:100px'>MAC</th> | ||
+ | <th style='width:100px'>Network type</th> | ||
+ | <th style='width:100px'>Encryption</th> | ||
+ | <th style='width:100px'>Channel</th> | ||
+ | <th style='width:100px'>BitRate</th> | ||
+ | <th style='width:300px'>Comment</th> | ||
+ | </thead> | ||
+ | <tbody> | ||
+ | |||
+ | <?php | ||
+ | $sql = "SELECT * FROM $table WHERE Name='$net' ORDER BY Time DESC;"; | ||
+ | $sth = $db->query($sql); | ||
+ | $sql_rc = $db->errorCode(); | ||
+ | error_log("$sql_rc\n"); | ||
+ | |||
+ | while ($row = $sth->fetch()) | ||
+ | { | ||
+ | $comment = lookup_mac($row['MAC']); | ||
+ | ?> | ||
+ | <tr> | ||
+ | <td><?=$row['Time'];?></td> | ||
+ | <td><a href="#" onclick='window.open("macinfo.php?mac=<?=$row['MAC'];?>&comment=<?=$comment;?>","WhoIsWho MAC-Info","directories=0,titlebar=0,toolbar=0,location=0,status=0,menubar=0,scrollbars=yes,resizable=no,width=650,height=350"); return false;'><?=$row['MAC'];?></a></td> | ||
+ | <td><?=$row['Type'];?></td> | ||
+ | <td><?=$row['Encryption'];?></td> | ||
+ | <td><?=$row['Channel'];?></td> | ||
+ | <td><?=$row['BitRate'];?></td> | ||
+ | <td><?=$comment;?></td> | ||
+ | <?php | ||
+ | } | ||
+ | ?> | ||
+ | </tbody> | ||
+ | </thead> | ||
+ | </body> | ||
+ | </html> | ||
+ | </code> | ||
+ | |||
+ | ==== import-manuf.php ==== | ||
+ | |||
+ | Auf dem Pi ist der I/O nicht wirklich schnell, weshalb es zu empfehlen ist, die "manuf"-Datei in eine entsprechende Tabelle der Datenbank zu importieren. | ||
+ | |||
+ | Eine aktuelle "manuf"-Datei gibts unter https://code.wireshark.org/review/gitweb?p=wireshark.git;a=blob_plain;f=manuf;hb=HEAD ... abgelegt wird diese unter /usr/local/whoiswho/etc/. | ||
+ | |||
+ | <code php import-manuf.php> | ||
+ | <!-- vi /usr/local/whoiswho/import-manuf.php> | ||
+ | <?php | ||
+ | require_once("etc/whoiswho.conf.php"); | ||
+ | require_once("include/mysql.inc.php"); | ||
+ | $manuf = file("/usr/local/whoiswho/etc/manuf"); | ||
+ | $i = 0; | ||
+ | $db = dbconnect(); | ||
+ | $table = MANUFTABLE; | ||
+ | # clear table before start | ||
+ | $truncsql = "truncate $table;"; | ||
+ | $truncsth = $db->query($truncsql); | ||
+ | $sql_rc = $db->errorCode(); | ||
+ | print "$truncsql ..."; | ||
+ | print "$sql_rc\n"; | ||
+ | print "starting import...\n"; | ||
+ | foreach ($manuf AS $manuf_row) | ||
+ | { | ||
+ | #if (preg_match("/([a-fA-F0-9]{2}[:|\-]?){3}/",$manuf_row)) | ||
+ | if (preg_match("/([a-fA-F0-9]{2}[:]?){3}/",$manuf_row)) | ||
+ | { | ||
+ | $i++; | ||
+ | $mac = substr($manuf_row,0,8); | ||
+ | # eliminate multiple blanks | ||
+ | #$text = preg_replace('/\s{2,}/',' ',$manuf_row); | ||
+ | $manuf_row = preg_replace('/\040{1,}/',' ',$manuf_row); | ||
+ | # eliminate tabs | ||
+ | $manuf_row = str_replace("\t", " ", $manuf_row); | ||
+ | # elimate Carriage Return and Line Feed | ||
+ | $manuf_row = rtrim($manuf_row); | ||
+ | $row_presplit = explode("#", $manuf_row); | ||
+ | $row_split = explode(" ", $row_presplit[0]); | ||
+ | $shortdescr = $row_split[1]; | ||
+ | if (isset($row_presplit[1])) | ||
+ | { | ||
+ | $descr = ltrim($row_presplit[1]); | ||
+ | } else | ||
+ | { | ||
+ | $descr = "none"; | ||
+ | }; | ||
+ | print "$mac;$shortdescr;$descr \n"; | ||
+ | $sql = "INSERT INTO $table (MAC,ShortDescription,Description) values ('$mac','$shortdescr','$descr');"; | ||
+ | print $sql; | ||
+ | $sth = $db->query($sql); | ||
+ | $sql_rc = $db->errorCode(); | ||
+ | print "$sql_rc\n"; | ||
+ | } | ||
+ | } | ||
+ | print "$i rows imported!!\n"; | ||
+ | ?> | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ==== process_incoming.php ==== | ||
+ | Die eingehenden Meldungen werden über PHP-Skript in die "SEEN"-Tabelle übernommen. Das PHP-Skript wird über CRON gesteuert. | ||
+ | |||
+ | <code php process_incoming.php> | ||
+ | <?php | ||
+ | require_once("../etc/whoiswho.conf.php"); | ||
+ | require_once("../include/mysql.inc.php"); | ||
+ | $i = 0; | ||
+ | $db = dbconnect(); | ||
+ | $table = INCOMINGTABLE; | ||
+ | $sql = "SELECT * FROM $table;"; | ||
+ | $sth = $db->query($sql); | ||
+ | while ($row = $sth->fetch()) | ||
+ | { | ||
+ | $i++; | ||
+ | print "Processing Message: Time: ".$row['DeviceReportedTime']." Message: ".$row['Message']."\n"; | ||
+ | # ID | ||
+ | $id = $row['ID']; | ||
+ | # Time | ||
+ | $time = $row['DeviceReportedTime']; | ||
+ | # WLAN name | ||
+ | $msg = explode(",", $row['Message']); | ||
+ | $msgpart = ltrim($msg[0]); | ||
+ | preg_match('/"[^"]*"/', $msgpart, $netnamemsg); | ||
+ | $netnamemsg = str_replace(['"','<','>'], '', $netnamemsg); | ||
+ | $netname = $netnamemsg[0]; | ||
+ | # getting MAC | ||
+ | $macmsg = explode(" ", ltrim($msg[1])); | ||
+ | $mac = implode(preg_grep('/([a-fA-F0-9]{2}[:|\-]?){6}/', $macmsg)); | ||
+ | $mac = str_replace(",", "", $mac); | ||
+ | $mac = str_replace("-", ":", $mac); | ||
+ | $mac = strtoupper($mac); | ||
+ | # network type | ||
+ | switch (true) | ||
+ | { | ||
+ | case (preg_grep('/new managed network/', $msg)): | ||
+ | $type="access point"; | ||
+ | break; | ||
+ | case (preg_grep('/new probe network/', $msg)): | ||
+ | $type="client"; | ||
+ | break; | ||
+ | case (preg_grep('/new ad-hoc network/', $msg)): | ||
+ | $type="ad-hoc"; | ||
+ | break; | ||
+ | case (preg_grep('/new data network/', $msg)): | ||
+ | $type="data"; | ||
+ | break; | ||
+ | default: | ||
+ | $type="unknown"; | ||
+ | } | ||
+ | # encryption | ||
+ | $encmsg = explode(" ", $msg[2]); | ||
+ | $enc = $encmsg[2]; | ||
+ | # channel | ||
+ | $channelmsg = explode(" ", $msg[3]); | ||
+ | $channel = $channelmsg[2]; | ||
+ | # bit rate | ||
+ | $bitratemsg = explode(" ", $msg[4]); | ||
+ | $bitrate = $bitratemsg[1]; | ||
+ | # insert into SEEN Table | ||
+ | $inserttable = SEENTABLE; | ||
+ | $insertsql = "INSERT INTO $inserttable (SyslogID,MAC,Time,Name,Type,Encryption,Channel,BitRate) values('$id','$mac','$time','$netname','$type','$enc','$channel','$bitrate');"; | ||
+ | $insertsth = $db->query($insertsql); | ||
+ | $sql_rc = $db->errorCode(); | ||
+ | #print "$insertsql ..."; | ||
+ | #print "$sql_rc\n"; | ||
+ | # delete from INCOMING | ||
+ | $delsql = "DELETE FROM $table WHERE ID ='$id';"; | ||
+ | $delsth = $db->query($delsql); | ||
+ | } | ||
+ | print "$i messages processed.\n"; | ||
+ | ?> | ||
+ | |||
+ | </code> | ||
+ | |||
+ | <code bash> | ||
+ | # vi /etc/cron.hourly/whoiswho | ||
+ | #!/bin/bash | ||
+ | # | ||
+ | cd /usr/local/whoiswho/cron/ | ||
+ | /usr/bin/php process_incoming.php | ||
+ | cd - | ||
+ | </code> | ||
+ | |||
+ | ==== whoiswho.conf.php ==== | ||
+ | <code php whoiswho.conf.php> | ||
+ | <!-- vi /usr/local/whoiswho/etc/whoiswho.conf.php --> | ||
+ | <?php | ||
+ | # database connection | ||
+ | define('DBDRIVER', 'mysql'); | ||
+ | define('DBHOST', '192.168.11.11'); | ||
+ | define('DBNAME', 'kismet'); | ||
+ | define('DBUSER', 'kismet'); | ||
+ | define('DBPASS', 'password'); | ||
+ | define('WELLKNOWNTABLE', 'WellKnown'); | ||
+ | define('INCOMINGTABLE', 'Incoming'); | ||
+ | define('SEENTABLE', 'Seen'); | ||
+ | define('MANUFTABLE', 'Manufacturer'); | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ==== mysql.inc.php ==== | ||
+ | <code php mysql.inc.php> | ||
+ | <!-- vi /usr/local/whoiswho/include/mysql.inc.php --> | ||
+ | <?php | ||
+ | |||
+ | function dbconnect() | ||
+ | { | ||
+ | /*$opt = array( | ||
+ | PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'", | ||
+ | PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION | ||
+ | );*/ | ||
+ | $opt = array( | ||
+ | PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'" | ||
+ | ); | ||
+ | $dsn = sprintf('%s:host=%s;dbname=%s', DBDRIVER, DBHOST, DBNAME); | ||
+ | #error_log("Connect with " . $dsn); | ||
+ | $db = new PDO($dsn, DBUSER, DBPASS, $opt); | ||
+ | return $db; | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | ==== tools.inc.php ==== | ||
+ | <code php tools.inc.php> | ||
+ | <!-- vi /usr/local/whoiswho/include/tools.inc.php --> | ||
+ | <?php | ||
+ | function lookup_manuf_file($mac) | ||
+ | { | ||
+ | $manuf = file("/usr/local/whoiswho/etc/manuf"); | ||
+ | foreach ($manuf AS $manuf_row) | ||
+ | { | ||
+ | if (substr($mac,0,8) == substr($manuf_row,0,8)) | ||
+ | { | ||
+ | # eliminate multiple blanks | ||
+ | #$text = preg_replace('/\s{2,}/',' ',$manuf_row); | ||
+ | $manuf_row = preg_replace('/\040{1,}/',' ',$manuf_row); | ||
+ | # eliminate tabs | ||
+ | $manuf_row = str_replace("\t", " ", $manuf_row); | ||
+ | $row_presplit = explode("#", $manuf_row); | ||
+ | $row_split = explode(" ", $row_presplit[0]); | ||
+ | $shortdescr = $row_split[1]; | ||
+ | if (isset($row_presplit[1])) | ||
+ | { | ||
+ | $descr = ltrim($row_presplit[1]); | ||
+ | } else | ||
+ | { | ||
+ | $descr = "none"; | ||
+ | }; | ||
+ | } | ||
+ | } | ||
+ | if (isset($shortdescr) && isset($descr)) return array($shortdescr,$descr); | ||
+ | } | ||
+ | |||
+ | function lookup_manuf_db($mac) | ||
+ | { | ||
+ | $db = dbconnect(); | ||
+ | $table = MANUFTABLE; | ||
+ | $searchmac = substr($mac,0,8); | ||
+ | $sql = "SELECT * FROM $table WHERE MAC='$searchmac' LIMIT 1;"; | ||
+ | #error_log("LOOKUP_MANUF_DB: ".$sql); | ||
+ | $sth = $db->query($sql); | ||
+ | while ($row = $sth->fetch(PDO::FETCH_ASSOC)){ | ||
+ | (isset($row['ShortDescription'])) ? $shortdescr = $row['ShortDescription'] : $shortdesc = "none"; | ||
+ | (isset($row['Description'])) ? $descr = $row['Description'] : $descr = "none"; | ||
+ | } | ||
+ | if (isset($shortdescr) && isset($descr)) return array($shortdescr,$descr); | ||
+ | } | ||
+ | |||
+ | function lookup_mac($mac) | ||
+ | { | ||
+ | $db = dbconnect(); | ||
+ | $table = WELLKNOWNTABLE; | ||
+ | $sql = "SELECT * from $table WHERE MAC='$mac';"; | ||
+ | $sth = $db->query($sql); | ||
+ | while ($row = $sth->fetch(PDO::FETCH_ASSOC)) | ||
+ | { | ||
+ | $comment = "<B>".$row['Comment']."</B>"; | ||
+ | } | ||
+ | if (!isset($comment)) | ||
+ | { | ||
+ | #list($shortdescr,$descr) = lookup_manuf_file($mac); | ||
+ | list($shortdescr,$descr) = lookup_manuf_db($mac); | ||
+ | if (isset($shortdescr)) | ||
+ | { | ||
+ | if ($descr == "none") | ||
+ | { | ||
+ | $comment = $shortdescr; | ||
+ | } else | ||
+ | { | ||
+ | $comment = $shortdescr." (".$descr.")"; | ||
+ | } | ||
+ | } else $comment = "<i>unknown</i>"; | ||
+ | } | ||
+ | return $comment; | ||
+ | } | ||
+ | |||
+ | ?> | ||
+ | |||
+ | </code> |