How do I programmatically disconnect an OpenVPN connection? - winforms

I am creating a WinForms application to start and stop an OpenVPN connection on Windows. I am trying to achieve the same functionality as OpenVPN GUI for Windows (http://openvpn.se/) provides but using my own .NET based UI.
I am starting the connection using the following approach:
Process openVpnProcess = new Process();
openVpnProcess.StartInfo.CreateNoWindow = true;
openVpnProcess.EnableRaisingEvents = true;
openVpnProcess.StartInfo.Arguments = "--config client.ovpn";
openVpnProcess.StartInfo.FileName = "openvpn.exe";
openVpnProcess.StartInfo.WorkingDirectory = #"C:\Program Files\OpenVPN\config";
openVpnProcess.Start();
This invokes openvpn.exe and the connection is established successfully.
I am however unable to determine a way to terminate the connection once it is established. I have tried using Process.Kill()
foreach (var p in Process.GetProcessesByName("openvpn"))
{
p.Kill();
}
This kills the process, but does not restore the initial routing state. Effectively, I cannot access the network until I manually disable/enable my LAN card.
Output of 'openvpn --show-net' before the VPN connection is established:
SYSTEM ROUTING TABLE
0.0.0.0 0.0.0.0 10.31.0.254 p=0 i=1376258 t=4 pr=3 a=21 h=0 m=1/-1/-1/-1/-1
10.31.0.0 255.255.240.0 10.31.10.235 p=0 i=1376258 t=3 pr=2 a=26 h=0 m=20/-1/-1/-1/-1
10.31.10.235 255.255.255.255 127.0.0.1 p=0 i=1 t=3 pr=2 a=26 h=0 m=20/-1/-1/-1/-1
10.255.255.255 255.255.255.255 10.31.10.235 p=0 i=1376258 t=3 pr=2 a=26 h=0 m=20/-1/-1/-1/-1
127.0.0.0 255.0.0.0 127.0.0.1 p=0 i=1 t=3 pr=2 a=116753 h=0 m=1/-1/-1/-1/-1
224.0.0.0 240.0.0.0 10.31.10.235 p=0 i=1376258 t=3 pr=2 a=26 h=0 m=20/-1/-1/-1/-1
255.255.255.255 255.255.255.255 10.31.10.235 p=0 i=1376258 t=3 pr=2 a=26 h=0 m=1/-1/-1/-1/-1
255.255.255.255 255.255.255.255 10.31.10.235 p=0 i=1441796 t=3 pr=2 a=4 h=0 m=1/-1/-1/-1/-1
SYSTEM ADAPTER LIST
TAP-Win32 Adapter V8
Index = 1441796
GUID = {013AB57F-DFE6-4FD9-B25E-9589E77DA4EB}
IP = 0.0.0.0/0.0.0.0
MAC = 00:ff:01:3a:b5:7f
GATEWAY =
DHCP SERV = 172.16.0.0
DHCP LEASE OBTAINED = Tue Jul 07 16:35:20 2009
DHCP LEASE EXPIRES = Wed Jul 07 16:35:20 2010
D-Link DFE-538TX 10/100 Adapter
Index = 1376258
GUID = {FB6051A1-E970-4F46-BB85-F442A194BA3D}
IP = 10.31.10.235/255.255.240.0
MAC = 00:08:a1:65:70:93
GATEWAY = 10.31.0.254/0.0.0.0
'openvpn --show-net' after VPN connection is closed using Process.Kill():
SYSTEM ROUTING TABLE
10.31.0.0 255.255.240.0 10.31.10.235 p=0 i=1376258 t=3 pr=2 a=106 h=0 m=20/-1/-1/-1/-1
10.31.10.235 255.255.255.255 127.0.0.1 p=0 i=1 t=3 pr=2 a=106 h=0 m=20/-1/-1/-1/-1
10.255.255.255 255.255.255.255 10.31.10.235 p=0 i=1376258 t=3 pr=2 a=106 h=0 m=20/-1/-1/-1/-1
127.0.0.0 255.0.0.0 127.0.0.1 p=0 i=1 t=3 pr=2 a=116833 h=0 m=1/-1/-1/-1/-1
208.94.64.10 255.255.255.255 10.31.0.254 p=0 i=1376258 t=4 pr=3 a=21 h=0 m=1/-1/-1/-1/-1
224.0.0.0 240.0.0.0 10.31.10.235 p=0 i=1376258 t=3 pr=2 a=106 h=0 m=20/-1/-1/-1/-1
255.255.255.255 255.255.255.255 10.31.10.235 p=0 i=1376258 t=3 pr=2 a=106 h=0 m=1/-1/-1/-1/-1
255.255.255.255 255.255.255.255 10.31.10.235 p=0 i=1441796 t=3 pr=2 a=84 h=0 m=1/-1/-1/-1/-1
SYSTEM ADAPTER LIST
TAP-Win32 Adapter V8
Index = 1441796
GUID = {013AB57F-DFE6-4FD9-B25E-9589E77DA4EB}
IP = 0.0.0.0/0.0.0.0
MAC = 00:ff:01:3a:b5:7f
GATEWAY =
DHCP SERV = 172.16.0.0
DHCP LEASE OBTAINED = Tue Jul 07 17:02:30 2009
DHCP LEASE EXPIRES = Wed Jul 07 17:02:30 2010
D-Link DFE-538TX 10/100 Adapter
Index = 1376258
GUID = {FB6051A1-E970-4F46-BB85-F442A194BA3D}
IP = 10.31.10.235/255.255.240.0
MAC = 00:08:a1:65:70:93
GATEWAY =
I also tried sending the process WM_CLOSE / WM_QUIT / WM_ENDMESSAGE messages but these did not produce any result.
const int WM_CLOSE = 0x10;
const int WM_QUIT = 0x12;
const int WM_ENDSESSION = 0x0016;
[DllImport("user32.dll")]
public static extern int SendMessage(int hwnd, int msg, int wparam, int lparam);
foreach (var p in Process.GetProcessesByName("openvpn"))
{
SendMessage(p.Handle.ToInt32(), WM_CLOSE, 0, 0);
SendMessage(p.Handle.ToInt32(), WM_QUIT, 0, 0);
SendMessage(p.Handle.ToInt32(), WM_ENDSESSION, 0, 0);
}
Further info on the appropriate solution: See instructions in section titled Using the management interface in Controlling a running OpenVPN process.
More info on using Telnet from C#.

I haven't tried this on Windows but you can use the OpenVPN Management interface to send a SIGTERM signal with the signal command. You'll need to include the management interface configuration entries in your configuration file of course.
More information in the OpenVPN man page
You may want to look at the way OpenVPN-admin is doing things. It's working under Windows and Linux and developed with Mono.

You're sending messages to the process handle - these, however, are window messages, that's why they must be sent to a window handle.
EDIT
As you got the process already, you might try the following:
foreach (var p in Process.GetProcessesByName("openvpn"))
{
p.CloseMainWindow();
}
or
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hwnd, int msg, int wparam, int lparam);
foreach (var p in Process.GetProcessesByName("openvpn"))
{
IntPtr hWnd = p.MainWindowHandle;
// Send message to hWnd (mind SendMessage's changed signature)
}

Related

Carriage returns removed from array when adding to variable

I have the following code:
$PreReqFail1 = "- Your computer is not in the office"
$PreReqFail2 = "- Your computer does not have its power cable plugged in"
$PreReqFail3 = "- Your computer does not have a network cable plugged in"
If (-NOT([string]::IsNullOrEmpty($PreReqFail1))) {$PreReqFail = $True}
If (-NOT([string]::IsNullOrEmpty($PreReqFail2))) {$PreReqFail = $True}
If (-NOT([string]::IsNullOrEmpty($PreReqFail3))) {$PreReqFail = $True}
If ($PreReqFail)
{
$Issues = #($PreReqFail1,$PreReqFail2,$PreReqFail3)
$Issues
$PreReqFails = "The following conditions have not been met:`r`n`r`n" + $Issues
$PreReqFails
}
$Issues = $null
$PreReqFail = $null
$PreReqFail1 = $null
$PreReqFail2 = $null
$PreReqFail3 = $null
$PreReqFails = $null
The idea is that I can comment out any one or more of the $PreReqFailx variables and present a dynamic list of the issues, e.g. 1,2,3 or 1,2 or 1,3 or 2,3, etc.
The Output from $Issues (lines 11 & 12) is as follows:
- Your computer is not in the office
- Your computer does not have its power cable plugged in
- Your computer does not have a network cable plugged in
This is the format I want. However, when I add it to the $PreReqFails variable, as shown in lines 13 & 14, this is what I get:
The following conditions have not been met:
- Your computer is not in the office - Your computer does not have its power cable plugged in - Your computer does not have a network cable plugged in
How I do tweak things so the output shows carriage returns for each issue, for example:
The following conditions have not been met:
- Your computer is not in the office
- Your computer does not have its power cable plugged in
- Your computer does not have a network cable plugged in
Thanks in advance for your assistance.
Why not use a single array that contains all the values:
$PreReqFail = #(
# commenting here also works
"- Your computer is not in the office"
"- Your computer does not have its power cable plugged in"
"- Your computer does not have a network cable plugged in"
)
Then you can follow more or less the same logic you already have but without needing to check if each variable is empty and join then by `n (new-line escape character):
If ($PreReqFail) {
"The following conditions have not been met:`r`n`r`n$($PreReqFail -join "`n")"
}

Wireguard access devices on client side

I am having some issues with wireguard setup. The logic that I want to achieve is that I will be able to connect from Client 1 (laptop) to Client 2 (opensense) subnet 10.88.1.1/24.
For the moment all is OK from Client to Server but no ping or any other access between the Clients.
Current setup is
Main wireguard server (ubuntu server) IP eg. 5.123.456.678
[Interface]
Address = 203.0.113.5/24
SaveConfig = true
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
ListenPort = 51820
FwMark = 0xca6c
PrivateKey = XXXXXXXXXXXXXXXXXXXXXXX
[Peer]
PublicKey = XXXXXXXXXXXXXXXXXXXXXXX
AllowedIPs = 203.0.113.13/32
Endpoint = 89.xxx.xxx.xxx:33943
[Peer]
PublicKey = XXXXXXXXXXXXXXXXXXXXXXX
AllowedIPs = 203.0.113.15/32
Endpoint = 46.xxx.xxx.xxx:4109
Client 1 (laptop)
[Interface]
PrivateKey = XXXXXXXXXXXXXXXXXXXXXXX
Address = 203.0.113.15/24
ListenPort = 51820
[Peer]
PublicKey = XXXXXXXXXXXXXXXXXXXXXXX
AllowedIPs = 203.0.113.5/32
Endpoint = 5.123.456.678:51820
PersistentKeepalive = 5
Client 2 (opensense) with subnet 10.88.1.1.
interface: wg0
public key: XXXXXXXXXXXXXXXXXXXXXXX
private key: (hidden)
listening port: 51820
peer: XXXXXXXXXXXXXXXXXXXXXXX
endpoint: 5.123.456.678:51820
allowed ips: 203.0.113.0/24
I have done some more testing and the the logic is that you need to add
subnet or individual IP to the setting in my case setting now looks like this
Server
[Interface]
Address = 203.0.113.5/24
SaveConfig = true
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
ListenPort = 51820
FwMark = 0xca6c
PrivateKey = XXXXXXXXXXXXXXXXXXXXXXX
[Peer]
PublicKey = XXXXXXXXXXXXXXXXXXXXXXX
AllowedIPs = 203.0.113.13/32, 10.88.1.0/24
Endpoint = 89.xxx.xxx.xxx:33943
[Peer]
PublicKey = XXXXXXXXXXXXXXXXXXXXXXX
AllowedIPs = 203.0.113.15/32, 10.88.1.0/24
Endpoint = 46.xxx.xxx.xxx:4109
Client 1 (laptop)
[Interface]
PrivateKey = XXXXXXXXXXXXXXXXXXXXXXX
Address = 203.0.113.15/24
ListenPort = 51820
[Peer]
PublicKey = XXXXXXXXXXXXXXXXXXXXXXX
AllowedIPs = 203.0.113.0/24,10.88.1.0/24
Endpoint = 5.123.456.678:51820
PersistentKeepalive = 5
Client 2 (opensense) with subnet 10.88.1.1.
interface: wg0
public key: XXXXXXXXXXXXXXXXXXXXXXX
private key: (hidden)
listening port: 51820
peer: XXXXXXXXXXXXXXXXXXXXXXX
endpoint: 5.123.456.678:51820
allowed ips: 203.0.113.0/24,10.88.1.0/24

when use isql,i got this: [IM002][unixODBC][Driver Manager]Data source name not found, and no default driver specified

when i type fllow command: isql dsnOracle -v
i got :
[IM002][unixODBC][Driver Manager]Data source name not found, and no default driver specified
[ISQL]ERROR: Could not SQLConnect
my config file:
[root#localhost lib]# cat /etc/odbc.ini
[dsnOracle]
Description = data source to oracle
Driver = Oracle
Servername = PARA_ORACLE
port = 1521
[root#localhost lib]# cat /etc/odbcinst.ini
[Oracle]
Description = ODBC for Oracle 
Driver  = /usr/lib/libsqora.so.11.1
[root#localhost lib]# cat $TNS_ADMIN/tnsnames.ora
PARA_ORACLE =
(DESCRIPTION =
(ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 172.100.2.13)(PORT = 1521)) )
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl)
)
)
[root#localhost lib]# rpm -qa |grep oracle
oracle-instantclient11.2-odbc-11.2.0.1.0-1.x86_64
oracle-instantclient11.2-basic-11.2.0.1.0-1.x86_64
[root#localhost lib]# rpm -qa |grep ODBC
unixODBC-2.2.14-12.el6_3.x86_64
i have try for a long time ,but i always get :data source name not found .
(it's there any relation with x86 or x64?).
any suggestion is fine for me.
finally i change my /etc/odbc.ini like this and it works.
[dsnOracle]
Application Attributes=T
Attributes=W
BatchAutocommitMode=IfAllSuccessful
BindAsFLOAT=F
CloseCursor=F
DisableDPM=F
DisableMTS=T
Driver=Oracle
DSN=OracleODBC-11g
EXECSchemaOpt=
EXECSyntax=T
Failover=T
FailoverDelay=10
FailoverRetryCount=10
FetchBufferSize=64000
ForceWCHAR=F
Lobs=T
Longs=T
MaxLargeData=0
MetadataIdDefault=F
QueryTimeout=T
ResultSets=T
SQLGetData extensions=F
Translation DLL=
Translation Option=0
DisableRULEHint=T
StatementCache=F
CacheBufferSize=20
UseOCIDescribeAny=F
UserID=userid
ServerName=PARA_ORACLE
Password=password

Retrying with different port number

I have a program that will ping an IP address, then log the IP to a file if it pings successfully:
Invalid IP: 128.201.166.30
Proxy created: 66.25.173.128:80
Invalid IP: 225.195.111.59
Invalid IP: 249.133.221.70
Invalid IP: 40.21.11.99
Invalid IP: 201.27.136.108
Invalid IP: 152.77.109.45
Invalid IP: 120.76.159.122
Invalid IP: 108.244.67.42
Invalid IP: 73.231.16.193
Proxy created: 146.134.102.95:3128
Invalid IP: 133.216.1.59
Proxy created: 118.75.196.75:3128
Now what I would like to do is have the "good" IP address use each port in the following array: port = %w(80 3128 8080 8090 8888 8898 9999), for example:
Proxy created: 66.25.173.128:80
Proxy created: 66.25.173.128:3128
Proxy created: 66.25.173.128:8080
Proxy created: 66.25.173.128:8090
Proxy created: 66.25.173.128:8888
Proxy created: 66.25.173.128:8898
Proxy created: 66.25.173.128:9999
#Creates an IP with a port extension with each port number
I think I have a general idea on how I could do this:
File.open("example.txt", "a+"){
|s| s.puts("#{ip}:#{port[0]}",
"#{ip}:#{port[1]}",
"#{ip}:#{port[2]}"
#etc...
)}
I'm not entirely sure if that would work the way I'm expecting it to though, and even if it does, I'm 100% sure there's a better way to do, any help with this would be greatly appreciated, thank you.
Source:
require 'colored'
require 'timeout'
def create_possibles
port = %w(80 3128 8080 8090 8888 8898 9999).each do |port|
10.times do
ip = Array.new(4){rand(256)}.join('.')
Timeout::timeout(5) do
ping = `ping -n 1 #{ip}`
if ping =~ /Received = 1/
proxy = "#{ip}:#{port}"
puts "Proxy created: #{proxy}".green.bold
File.open("proxies.txt", "a+") {|s| s.puts(proxy)}
else
puts "Invalid IP: #{ip}".red.bold
next
end
end
end
end
end
create_possibles
EDIT:
I attempted my general idea of how to do this:
require 'colored'
require 'timeout'
def create_possibles
w%(80 3128 8080 8090 8888 8898 9999).each do |port|
1.times do
ip = Array.new(4){rand(256)}.join('.')
Timeout::timeout(5) do
ping = `ping -n 1 #{ip}`
if ping =~ /Received = 1/
# proxy = "#{ip}:#{port}"
puts "[SUCCESS]Proxy created for IP: #{ip}".green.bold
File.open("proxies.txt", "a+") {|s| s.puts("#{ip}:#{port[0]}",
"#{ip}:#{port[1]}",
"#{ip}:#{port[2]}",
"#{ip}:#{port[3]}",
"#{ip}:#{port[4]}",
"#{ip}:#{port[5]}",
"#{ip}:#{port[6]}",
"#{ip}:#{port[7]}")}
else
puts "[ERROR]IP failed to ping: #{ip}".red.bold
next
end
end
end
end
end
create_possibles
When run:
[ERROR]IP failed to ping: 185.105.73.104
[ERROR]IP failed to ping: 93.182.117.11
[ERROR]IP failed to ping: 112.210.73.187
[ERROR]IP failed to ping: 111.109.127.178
[SUCCESS]Proxy created for IP: 201.153.205.131
[ERROR]IP failed to ping: 128.236.57.123
[ERROR]IP failed to ping: 248.84.17.31
It ends up outputting information that looks like this:
201.153.205.131:0
201.153.205.131:0
201.153.205.131:0
201.153.205.131:1
201.153.205.131:1
201.153.205.131:1
201.153.205.131:0
201.153.205.131:1
I figured it out! The problem had to do with the .each do |ports|;
If I take that out like this:
require 'colored'
require 'timeout'
def create_possibles
ports = %w(80 3128 8080 8090 8888 8898 9999)
5.times do
ip = Array.new(4){rand(256)}.join('.')
Timeout::timeout(5) do
ping = `ping -n 1 #{ip}`
if ping =~ /Received = 1/
# proxy = "#{ip}:#{port}"
puts "[SUCCESS]Proxy created for IP: #{ip}".green.bold
File.open("proxies.txt", "a+") {|s| s.puts("#{ip}:#{ports[0]}",
"#{ip}:#{ports[1]}",
"#{ip}:#{ports[2]}",
"#{ip}:#{ports[3]}",
"#{ip}:#{ports[4]}",
"#{ip}:#{ports[5]}",
"#{ip}:#{ports[6]}")}
else
puts "[ERROR]IP failed to ping: #{ip}".red.bold
next
end
end
end
end
create_possibles
Then run it as is, it will output:
[ERROR]IP failed to ping: 111.20.77.200
[SUCCESS]Proxy created for IP: 217.252.149.35
[ERROR]IP failed to ping: 49.214.128.47
[ERROR]IP failed to ping: 116.101.28.115
[ERROR]IP failed to ping: 75.49.120.242
And will log:
217.252.149.35:80
217.252.149.35:3128
217.252.149.35:8080
217.252.149.35:8090
217.252.149.35:8888
217.252.149.35:8898
217.252.149.35:9999

Sorting an array in lexicographical order. Pure bash

I have two arrays with IPs. I want to combine them into a third array and apply an ascending ordering.
#!/bin/bash
#
dbip[0]=1.1.1.1
dbip[1]=1.1.1.2
dbip[2]=1.1.1.3
dbip[3]=1.1.1.4
dbip[4]=1.1.1.5
dbip[5]=1.1.1.10
dbip[6]=1.1.1.9
ngip[0]=1.1.1.5
ngip[1]=1.1.1.6
ngip[2]=1.1.1.7
ngip[3]=1.1.1.1
ngip[4]=1.1.1.11
#I am adding the dbip array into the final one
for (( i=0; i<${#dbip[#]}; i++ ))
do
allip[$i]=${dbip[$i]}
done
#Remembering the no. of elements in the final array
var=${#allip[#]}
echo "$var"
#Adding the ngip array into the final one
for (( i=0; i<${#ngip[#]}; i++ ))
do
allip[$var+$i]=${ngip[$i]}
done
#Printing the initial order of the elements in the array
echo "size= ${#allip[#]}"
for (( i=0; i<${#allip[#]}; i++ ))
do
echo "${allip[$i]}"
done
#Sorting the array in ascending order
for (( i=0; i<${#allip[#]}; i++ ))
do
for (( j=$i; j<${#allip[#]}; j++ ))
do
if [ allip[$i] \> allip[$j] ];
then
aux=${allip[$i]}
allip[$i]=${allip[$j]}
allip[$j]=$aux;
fi
done
done
echo "###############################"
#Printing the final form of the array
for (( i=0; i<${#allip[#]}; i++ ))
do
echo "${allip[$i]}"
done
Problem is that the output is not ordered in numerical or lexicographical way.
Output:
1.1.1.1
1.1.1.11
1.1.1.1
1.1.1.2
1.1.1.3
1.1.1.4
1.1.1.5
1.1.1.10
1.1.1.9
1.1.1.5
1.1.1.7
1.1.1.6
The output should be like this:
1.1.1.1
1.1.1.1
1.1.1.2
1.1.1.3
.......
1.1.1.10
1.1.1.11
or like this
1.1.1.1
1.1.1.1
1.1.1.10
1.1.1.11
so i can remove the duplicates later.
How can i do this in a pure programming way in bash. No pipes.
Note that IPs can be from different classes: 10.55.72.190, 10.55.70.1, 10.51.72.44, etc.
Here is "pure" bash:
dbip=( [0]=1.1.1.1 [1]=1.1.1.2 [2]=1.1.1.3 [3]=1.1.1.4 [4]=1.1.1.5 [5]=1.1.1.10 [6]=1.1.1.9 )
ngip=( [0]=1.1.1.5 [1]=1.1.1.6 [2]=1.1.1.7 [3]=1.1.1.1 [4]=1.1.1.11 )
allip=( $(printf "%s\n" "${dbip[#]}" "${ngip[#]}" | sort -V) )
printf "%s\n" "${allip[#]}"
1.1.1.1
1.1.1.1
1.1.1.2
1.1.1.3
1.1.1.4
1.1.1.5
1.1.1.5
1.1.1.6
1.1.1.7
1.1.1.9
1.1.1.10
1.1.1.11
A pure bash implementation (no call to any tool like sort).
The idea: convert IPs to integers, perform a bubble sort on these, convert back to x.x.x.x format.
#! /bin/bash
ips=(192.0.2.235 1.1.1.1 1.1.1.11 1.1.1.1 1.1.1.2 1.1.1.3 1.1.1.4
1.1.1.5 1.1.1.10 1.1.1.9 1.1.1.5 1.1.1.7 1.1.1.6)
# integer IPs
intips=()
echo Initial addresses:
for ((i=0; i<${#ips[#]}; ++i)); do
echo ${ips[$i]}
done
echo
# convert ip to int
ip2int() {
local -i intip
local -a ip
local IFS="."
ip=($1)
intip=$(( ${ip[0]}*2**24 + ${ip[1]}*2**16 + ${ip[2]}*2**8 + ${ip[3]} ))
echo $intip
}
# convert int to ip
int2ip() {
local -i a1 a2 a3 a4 intip=$1
a1=$(( intip / (2**24) )); ((intip -= a1*2**24))
a2=$(( intip / (2**16) )); ((intip -= a2*2**16))
a3=$(( intip / (2**8) )); ((intip -= a3*2**8))
a4=$(($intip))
echo "$a1.$a2.$a3.$a4"
}
# simple bubble sort (ascending) of an integer array
sortn_asc() {
local -a array=( "$#" )
local -i max i val1 val2
for (( max=$(( ${#array[#]} - 1 )); max > 0; max-- )); do
for (( i=0; i<max; i++ )); do
val1=${array[$i]}
val2=${array[$((i + 1))]}
# switch if necessary
if (( $val1 > $val2 )); then
local tmp=$val1
array[$i]=$val2
array[$(($i + 1))]=$tmp
fi
done
done
echo "${array[#]}"
}
# convert ips to integers
for ((i=0; i<${#ips[#]}; ++i)); do
intips[$i]=$(ip2int ${ips[$i]})
done
# sort
intips=( $(sortn_asc ${intips[#]}) )
# convert and echo sorted integers table
echo Sorted addresses:
for ((i=0; i<${#intips[#]}; ++i)); do
echo $(int2ip ${intips[$i]})
done
exit 0
The output:
br#lorien:~/tmp$ ./19398658.sh
Initial addresses:
192.0.2.235
1.1.1.1
1.1.1.11
1.1.1.1
1.1.1.2
1.1.1.3
1.1.1.4
1.1.1.5
1.1.1.10
1.1.1.9
1.1.1.5
1.1.1.7
1.1.1.6
Sorted addresses:
1.1.1.1
1.1.1.1
1.1.1.2
1.1.1.3
1.1.1.4
1.1.1.5
1.1.1.5
1.1.1.6
1.1.1.7
1.1.1.9
1.1.1.10
1.1.1.11
192.0.2.235

Resources