bash script tells me when new computer joins LAN via smbclient

I'm thinking of creating a script that loops until it finds a new IP on the Network created by the router DHCP Server. I am thinking of using NMAP.

nmap 192.168.0.1-254

However I am wondering how I could write the script to identify the newly created IP, then send your self a message (smbclient?) on the local computer, that IP### was created. THe meesage would say " IP/HOST ###, has joined your network"

Any idea's? Examples?


I can help you, partly, with the following script.

I added lots of comments (to clarify the script) but you can edit them out.

BTW. I would use the -sP parameter with nmap. Default nmap will scan lots of ports (slow) and usually it's enough to just use the ping-method (in a local network). If it's not, you can always adjust it.

#!/bin/sh

# the file in which the last know ips are stored
LOG_FILE="last_online.txt"

# use this if you want to "hard" set the ip range
# IP_RANGE="192.168.0.1-100"
#

# however, we use this
# this is more flexible and gets the ip range from the ip-command
# if this doesn't work use the "hard"-setting above
# result is i.e. 192.168.0.1/24
IP_RANGE=`ip -o addr show | grep inet\  | grep eth | cut -d\  -f 7 | head -n1`

# this would give you IP numbers ONLY (no text "appears to be up")
# i didn't use it here because the message "Host xx (ip) appears to be up"
# is (almost) exactly what we want
# ONLINE=`nmap -oG - -sP $IP_RANGE | grep ": Up" | awk '/Host/{print $2}'`

# and this line gives us a complete message-line
# like "Host router (192.168.1.254) appears to be up."
ONLINE=`nmap -sP $IP_RANGE | grep "up\."`

# loop through all the "up" ip addresses
while read -r IP
do

  # check if IP-line (with complete appears-text) exists in last know ip-file
  if ! grep -Fxq "$IP" $LOG_FILE
  then

     # if not, do this (note the ! in the if-line)

     # my own script for sending udp signal to my windows-app
     # /home/util/udp.pl 1200 "$IP"

     # smclient winpopup message
     # couldn't get this to work in win7 anymore
     # echo "$IP" | smbclient -M YOUR_PC

     # ok, lets send an e-mail
     echo "$IP" | mail -s "$IP" [email protected]

  fi

done <<< "$ONLINE"

# write the new online ip addresses to the log_file
echo "$ONLINE" > $LOG_FILE

The only problem i encountered was sending a message to my Windows 7 PC.

I have my own Windows-app (always present in task-tray) which monitors incoming phone-calls and which communicates with my Linux server through UDP-packets. In my script that's the line with /home/util/udp.pl (to send a UDP-broadcast packet on port 1200).

I tried smbclient to send a message but couldn't get that to work. Maybe you have more luck on your Ubuntu-box.

So i added a line to send a message via e-mail instead.


You should first try if you can send messages with Ununtu to your other workstations (or local desktop):

echo "hello world" | smbclient -M YOUR_PC

or

echo "hello world" | smbclient -M YOUR_PC -U YOUR_USERNAME

If you can't send anything to you desktop you'll have to settle for the e-mail method.


If you are not using a simple router, but a more capable dns/dhcp service like dnsmasq you can let the DHCPd handle this. I have my dnsmasq configured to run a script every time a DHCP lease is given. You can do this with a single line in the dnsmasq.conf:

dhcp-script=/path/to/new_lease.php

In the script I write the mac address, ip, name and datetime to a database. If the mac address is unknown, it sends an email to me notifying me of the new device in my network.

My PHP script with a SQLite database looks like this:

#!/usr/bin/php
<?php
# The arguments sent to the script are "add" or "del",
# then the MAC address, the IP address and finally the hostname
# if there is one.
$params = extract_array($argv, array(null, 'command', 'mac', 'ip', 'name'));
extract($params);

switch ($command) {
    case 'old':
    case 'add':
        $stmt = $db->prepare("UPDATE leases SET ip='' WHERE ip=:ip");
        $stmt->bindParam(":ip", $ip);
        $stmt->execute();
        if ($stmt->rowCount() == 0) {
                // new device
                $stmt = $db->prepare("SELECT vendor_name FROM vendors WHERE mac_prefix=:mac COLLATE NOCASE");
                $stmt->bindParam(":mac", $mac_prefix);

                $mac_prefix = substr($mac,0,8);
                if ($stmt->execute()) {
                  $result = $stmt->fetch();
                  $vendor = $result['vendor_name'];
                }

                // send email
        }
        $stmt = $db->prepare("INSERT OR IGNORE INTO leases (mac) VALUES (:mac)");
        $stmt->bindParam(":mac", $mac);
        $stmt->execute();
        $stmt = $db->prepare("UPDATE leases SET ip=:ip,name=:name,`date`=DATETIME('now') WHERE mac=:mac");
        $stmt->bindParam(":mac", $mac);
        $stmt->bindParam(":ip", $ip);
        $stmt->bindParam(":name", $name);
        $stmt->execute();
        break;
    case 'delete':
        $stmt = $db->prepare("UPDATE leases SET ip='' WHERE ip=:ip");
        $stmt->bindParam(":ip", $ip);
        $stmt->execute();
        break;
}
?>