LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 07-17-2017, 03:33 AM   #1
pedropt
Member
 
Registered: Aug 2014
Distribution: Devuan
Posts: 345

Rep: Reputation: Disabled
[SOLVED] Detect if input is a valid ip & subnet


I am doing a script that requires the user to insert an ip , in case user writes text then it will abort the script .

I want 2 options to be available .

1st - user can enter a single ip (ex: 100.0.0.0)
2nd - user can enter a single ip & subnet (ex: 100.0.0.0/24)

the first part i was able to figure out with this code :

Quote:
echo "Enter Ip range to scan ex: 192.168.1.1/24"
echo "IP Range : ";tput sgr0
read ip
if [[ $ip =~ ^[0-255]+\.[0-255]+\.[0-255]+\.[0-254]+$ ]]
then
echo "$ip is valid"
else
echo "$ip is not valid"
exit 1
fi
Now , how to add to this if code :
[[ $ip =~ ^[0-255]+\.[0-255]+\.[0-255]+\.[0-254]+$ ]]

the possibility of a subnet input between 0 & 32 (ex: 100.0.0.0/24)?

I only need the if instruction so i can write an "elif" instruction if the first code .

Last edited by pedropt; 07-18-2017 at 08:46 AM.
 
Old 07-17-2017, 04:03 AM   #2
business_kid
LQ Guru
 
Registered: Jan 2006
Location: Ireland
Distribution: Slackware, Slarm64 & Android
Posts: 16,144

Rep: Reputation: 2308Reputation: 2308Reputation: 2308Reputation: 2308Reputation: 2308Reputation: 2308Reputation: 2308Reputation: 2308Reputation: 2308Reputation: 2308Reputation: 2308
What exactly are you trying to check on the subnet? That a subnet exists?

I'm thinking of my router. The internet sees a single address in the 84.xxx.xxx.xxx range; I see an address 192.168.178.1 for the router, and pretty random addresses in the 192.168.178.xxx range for the various attached devices (this pc, printer, poser phone, tablets, etc.). 84.xxx.xxx.xxx passes trasffic to and from 192.168.178.xxx but never the twain shall meet. It's a tall order to ferret out the 192.168.178.xxx at all, let alone with a few lines of bash scripting.

Have you played with nmap? Read the man page and have a go. It's probably a better way.
 
Old 07-17-2017, 05:17 AM   #3
pedropt
Member
 
Registered: Aug 2014
Distribution: Devuan
Posts: 345

Original Poster
Rep: Reputation: Disabled
Quote:
What exactly are you trying to check on the subnet? That a subnet exists?
No , i am trying to build an is statement to check if user input is between these values :
0.0.0.0/0 - 255.255.255.254/32

Quote:
Have you played with nmap? Read the man page and have a go. It's probably a better way.
No ...comments
 
Old 07-17-2017, 06:32 AM   #4
michaelk
Moderator
 
Registered: Aug 2002
Posts: 25,592

Rep: Reputation: 5880Reputation: 5880Reputation: 5880Reputation: 5880Reputation: 5880Reputation: 5880Reputation: 5880Reputation: 5880Reputation: 5880Reputation: 5880Reputation: 5880
Code:
if [[ $ip =~ ^[0-255]+\.[0-255]+\.[0-255]+\.[0-254]+$ ]]
A regex expression matches a string of characters and not a range of numbers. Your expression does not work for 192.168.0.1.


Code:
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} ]]
while this works for any digit you still need to verify that the range is 0-255 for each octet. You can add another regex to check for the netmask mask but again you need to verify the range is correct.

Code:
if [[ $ip =~ /[0-9]{1,2}$ ]]; then
  echo "netmask valid"
else
  echo "netmask not present or invalid"
fi
 
Old 07-17-2017, 06:42 AM   #5
pedropt
Member
 
Registered: Aug 2014
Distribution: Devuan
Posts: 345

Original Poster
Rep: Reputation: Disabled
Thanks Michaelk , it is working perfectly .

I will leave here the final code for others :

Quote:
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} ]]
then
if [[ $ip =~ /[0-9]{1,2}$ ]]; then
echo "netmask valid"
else
echo "netmask not present or invalid"
fi
else
echo "$ip is not valid"
exit 1
fi
However , how to determine when the netmask is invalid or not present in the code ?

One idea was to put the first check of netmask to see if leters was inputed by user in that field .

Quote:
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} ]]
then
if [[ $ip =~ /[a-z]{1,2}$ ]]; then
echo "netmask ok without letters"
else
echo "netmask not ok with letters"
exit 1
fi
if [[ $ip =~ /[0-9]{1,2}$ ]]; then
echo "netmask ok with numbers"
else
echo "netmask not present"
fi
else
echo "$ip is not valid !"
exit 1
fi
Other idea would be defining the ip variable correctly after if statement check it .

In case if detects :
$ip = 192.168.1.1/ewwer

then
$ip = 192.168.1.1

but if :
$ip = 192.168.1.1/24
then it is ok and do not change it .

Last edited by pedropt; 07-17-2017 at 07:00 AM.
 
Old 07-17-2017, 06:57 AM   #6
michaelk
Moderator
 
Registered: Aug 2002
Posts: 25,592

Rep: Reputation: 5880Reputation: 5880Reputation: 5880Reputation: 5880Reputation: 5880Reputation: 5880Reputation: 5880Reputation: 5880Reputation: 5880Reputation: 5880Reputation: 5880
Code:
if [[ "$ip" =~ (([01]{,1}[0-9]{1,2}|2[0-4][0-9]|25[0-5])\.([01]{,1}[0-9]{1,2}|2[0-4][0-9]|25[0-5])\.([01]{,1}[0-9]{1,2}|2[0-4][0-9]|25[0-5])\.([01]{,1}[0-9]{1,2}|2[0-4][0-9]|25[0-5])) ]]; then
I have not verified but this regex expression should verify all combinations of octets without additional code. You can use a subtring functions to extract anything from a / to the end of string and go from there.
 
Old 07-17-2017, 07:25 AM   #7
pedropt
Member
 
Registered: Aug 2014
Distribution: Devuan
Posts: 345

Original Poster
Rep: Reputation: Disabled
Quote:
if [[ "$ip" =~ (([01]{,1}[0-9]{1,2}|2[0-4][0-9]|25[0-5])\.([01]{,1}[0-9]{1,2}|2[0-4][0-9]|25[0-5])\.([01]{,1}[0-9]{1,2}|2[0-4][0-9]|25[0-5])\.([01]{,1}[0-9]{1,2}|2[0-4][0-9]|25[0-5])) ]]
then
echo "ip ok"
else
echo "ip not ok"
is not working correctly

192.168.0.1/345 = ok
192.168.0.1/tuy = ok

I believe that expression is only to check the ip address .
 
Old 07-17-2017, 07:29 AM   #8
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 21,103

Rep: Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117
I would be monumentally disappointed - to the point of disbelief - if CPAN didn't have something to handle this trivially. Including the subnet check.
Why (re-)invent a square wheel ?.
 
Old 07-17-2017, 07:44 AM   #9
Turbocapitalist
LQ Guru
 
Registered: Apr 2005
Distribution: Linux Mint, Devuan, OpenBSD
Posts: 7,258
Blog Entries: 3

Rep: Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713
Yes, there are several modules available in CPAN. It's trivial to pound out a script to check addresses or networks. I'd hate to re-implement the whole module in the shell:

Code:
#!/usr/bin/perl -T

use Net::IP;
use strict;
use warnings;

my $ip = shift 
    or die ("Missing address or network.\n");

$ip =~ m/^([\/\:\.0-9a-fA-F]+)$/
    or die("Bad address or network format.\n");

my $addr = new Net::IP($ip) 
    or die (Net::IP::Error());

exit ( 0 );
That returns non-zero if the network is invalid and returns zero if it is valid.

Additionally, if there is something wrong with the address or network then an error describing the problem goes to stderr.
 
1 members found this post helpful.
Old 07-17-2017, 08:55 AM   #10
pedropt
Member
 
Registered: Aug 2014
Distribution: Devuan
Posts: 345

Original Poster
Rep: Reputation: Disabled
My whole script is written in bash , to adapt it to perl would take me a course of perl , which i don't want to get in now .

This issue is "easy" if we understand the logic that must take .
Many of the impossible bash code that we think that is not possible , is because we are unable to figure out a logic way to do it .

the target is an ip and subnet (192.168.1.1/24)

logic to be acquired in code :

0 - check if there is a slash in the var (/) , case "/" does not exist then go to step 5
1 - split the var in / and check if it is a number or letters in the subnet .
2 - case it is letters then it is invalid
2a- set the current var with user input until the "/"
ex user input : 100.0.0.0/sfg

2a if statement = change original var from 100.0.0.0/sfg to 100.0.0.0
3 - case it is numbers then it must between 0 and 32
4 - check the var until the "/"
5 - it is an ip ? then it must be between 0.0.0.0 and 255.255.255.255
6 - if it not an ip then the value is not accepted .

The big problem is to make all these steps with if statements and regex .

My experience with "if statements" is very limited , this is why i post it here , because many people here programming is their everyday job .

Last edited by pedropt; 07-17-2017 at 09:09 AM.
 
Old 07-17-2017, 10:22 PM   #11
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 21,103

Rep: Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117
I'd be pretty comfortable stating all the current respondents would be more than adept at bash. And can recognise it limitations.
There is no need to re-write all your script, just the IP testing bit. Turbocapitalist has given you a more than adequate solution that can be simply called and the return code tested, just like any other command you would use. You would likely have to install Net::IP from CPAN - search the web for instructions. Might even be in your repos, it is for Fedora.
 
Old 07-18-2017, 01:56 AM   #12
pedropt
Member
 
Registered: Aug 2014
Distribution: Devuan
Posts: 345

Original Poster
Rep: Reputation: Disabled
eventually i will figure out a way to do it , it would take 50 lines or more of code , but i will make it .

Thanks all for your help .
 
Old 07-18-2017, 06:03 AM   #13
pedropt
Member
 
Registered: Aug 2014
Distribution: Devuan
Posts: 345

Original Poster
Rep: Reputation: Disabled
Like i told in the previous post , i would figure out a way to do it in bash , and i did it .
However the regex michael give allows to input an ip like 999.999.999.999 , and that cannot happen .
But the rest of the code is working as it should be .

Quote:
#!/bin/bash
echo -ne "Enter IP or IP range : ";tput sgr0
read ips
echo $ips > tmp
ip="$ips"
if [[ $ip =~ "/" ]]
then
chk="/"
chk1=`grep -o $chk <<< "$ip" | wc -l`
if [ $chk1 != 1 ]
then
echo "Invalid IP"
exit 1
else
sub=`cat tmp | cut -d "/" -f 2`
if [[ ! $sub =~ ^[^A-Za-z]+$ ]]; then
echo "Invalid IP"
exit 1
else
if [ $sub -lt "0" ]
then
echo "Invalid IP"
elif [ $sub -gt "32" ]
then
echo "Invalid IP"
exit 1
else
ipo=`cat tmp | cut -f1 -d "/"`
if [[ $ipo =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} ]]
then
ip=`cat tmp`
echo "Valid $ip"
rm -f tmp
else
echo "Invalid IP"
fi
fi
fi
fi
else
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} ]]
then
echo "Valid IP"
else
echo "Invalid IP"
fi
fi
code still needs some refining that i did not had time yet to do it .
 
Old 07-18-2017, 06:19 AM   #14
Turbocapitalist
LQ Guru
 
Registered: Apr 2005
Distribution: Linux Mint, Devuan, OpenBSD
Posts: 7,258
Blog Entries: 3

Rep: Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713
For IPv4 addresses, you'd just have to look at each number and then see if it is in the range 0-254. It might be a good idea use a function for the actual comparison to avoid coding the same sequence four times.

For temp files, consider using mktemp

Code:
tmp=$(mktemp pedropt.ip.XXXXXXX);
...
test -f $tmp && rm -f $tmp;
And instead of backticks ` ` you might consider using $( ) as it is a bit more modern and readable.
 
Old 07-18-2017, 06:41 AM   #15
pedropt
Member
 
Registered: Aug 2014
Distribution: Devuan
Posts: 345

Original Poster
Rep: Reputation: Disabled
yup . i know , i have to split the ip in 4 parts on the dots and check in their values are between 0 and 255 .
But that i will do it other time .
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
valid packet returning to INPUT after going through INVALID chain vincix Linux - Networking 1 06-09-2017 12:01 AM
[SOLVED] Bash user input valid then continue powerplyer Linux - Newbie 9 02-10-2015 04:56 AM
[SOLVED] Firewall up & working; need input & advice on configuration. lupusarcanus Linux - Newbie 1 12-22-2009 05:45 AM
syslog-ng & subnet filters koncept Linux - Software 5 05-23-2007 03:38 PM
how to detect which networkaddress, gateway, subnet on network without dhcp deadeyes Linux - Wireless Networking 2 03-02-2007 01:53 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:46 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration