I am using Linux and I need some indication that an IP address has been acquired by the n/w interface over DHCP. Is there any event that I can wait for... Ideally I would like to have something like this: An event or a call back so that whenever the interface acquires an IP address I can get to know immediately. Is there any such event or call back or any provision?
Thanks!
If you're on a desktop distro running NetworkManager, it will run scripts in /etc/NetworkManager/dispatcher.d when the network interface changes state, passing information via the command line and environment variables. I forget the details, but you can check the documentation and existing examples.
NetworkManager also has a dbus interface, which you can listen to for the same information. Running (as root) dbus-monitor --system while you bounce your interface will show you the relevant signal.
Related
How can I wait in my user space program until connman has finished the network configuration on Linux booting? (Unfortunately, this is not Wants=connman.service.)
After systemd service connman is up, my user space program starts via systemd service (Wants=network.target connman.service), and it wants to read the network configuration via C function getifaddrs() (e.g. ifa->ifa_addr and ifa->ifa_addr->sa_family). Now two things can happen, either connman reads an explicitely unconfigured network (IPv4=0.0.0.0/0.0.0.0/0.0.0.0) or a certain network configuration (e.g. IPv4=192.168.0.50/255.255.255.0/0.0.0.0) from its config file. For some reasons my program has to wait on a certain code line until connman has finished its setup with one of both cases. How do I do that?
All I found in the systemd synchronisation possibilities were points of times when the connman service is up (Wants=connman.service) which does not mean it has processed its config file, it's before that!!!), and secondly, network-online.target for when an IP address is configured (which does not include the case of 0.0.0.0/0.0.0.0/0.0.0.0 in the connman config file).
addon: I noticed an IP address is set during Linux booting as soon as "Link is up - 100Mbps/Full - flow control off" is printed on console. How do I detect that in my user program?
Uhm, all I found is this workaround. The start script of my service looks into connman's .config file and searches for the line with "IPv4=", and in case it's all 0.0.0.0 there I can immediately start my application or otherwise I have to loop in that script until ifconfig reports it has set an IP address for that certain network adapter interface.
I'm looking for a specific place to add some kind of hook to the linux kernel that will allow me to do the following:
Detect just the case of a TCP connection going to loopback (127.0.0.1)
Detect if the source process of the packet is the same as the destination process
If this is the case, allow the connection, deny any other loopback connection (one process to another process)
I've been looking at netfilter hooks but they don't seem to fit the need. bpf filters only look at the packet itself.
I was also looking at the LSM hook of socket-connect. I can try to achieve this from the socket-connect hook by looking at what process has the requested port current bound to predict where the connection is going to connect that this sounds quite hackish.
A simple approach could be the use of Linux network namespaces.
Linux Network Namespaces
As the name would imply, network namespaces partition the use of the network—devices, addresses, ports, routes, firewall rules, etc.—into separate boxes, essentially virtualizing the network within a single running kernel instance. Network namespaces entered the kernel in 2.6.24,...
see https://lwn.net/Articles/580893/
Unshare
unshare() allows a process (or thread) to disassociate parts of its execution context that are currently being shared with other processes (or threads).
see http://man7.org/linux/man-pages/man2/unshare.2.html
Testcase
Since a program should be able to comunicate with itself we need a program that communicates with itself via sockes. There is a cool SO answer that shows a simple Java program that transfers the text 'Hello World!' via socket to itself, see here https://stackoverflow.com/a/8119708.
/usr/bin/java SendReceive
works as expected and gives the output 'Hello World!'
With the -n option one can unshare network namespace.
unshare -n -- sh -c '/usr/bin/java SendReceive'
gives a SocketException: Network is unreachable because there is no access to the loopback device.
unshare -n -- sh -c 'ip link set dev lo up; /usr/bin/java SendReceive'
finally transfers 'Hello World!' again via a loopback interface. BTW: this is a private loopback device. You cannot access open ports on the standard loopback device.
See also this cool Unix Stackexchange answer: https://unix.stackexchange.com/a/83348: Block network access of a process?
Screenshot
Here a screenshot of the test case mentioned above executed on Ubuntu 18.10:
I am trying to add a hook.
The functionality of the hook is to get the notification when a network interface card is on or off. On and off means having an active ip address or not. I don't want to check all the available ip addresses periodically. Instead, can I get notified when this happen?
I have setup a CentOS 6.4 server (minimal install) which is connected to network through an ethernet cable. The problem is that when the network link goes down, the status changes are not automatically detected but if i type "ifconfig" the interface still keeps its IP address (which is assigned by a DHCP server). After some time that the link is down the interface loses the address but when the link comes up again the network connection is not automatically restored like it would happen in a desktop computer. Even the command "dhclient eth0" does not always work to restore things, and I have to restart the whole network service with "/ect/init.d/network restart".
Is there any way to automatically detect network status changes like it happens in desktop installations? I'm thinking about a cron script that every 5 minutes pings a server outside my network and if it doesn't get any response it restarts network service, but this does not sound very efficient... is there another way?
EDIT: I realized I have not explained the situation correctly. My network topology is: server --> switch --> router --> external network (the router is another centos server with DHCPD).
For some reasons (that i'm not getting), when it happens that the router goes down and reboots, the other server becomes unreachable, and I have to manually restart network service on it. So the link does not effectively go down (the switch keeps it up), but the status change is at IP level.
You can check if you have NetworkManager enabled, I usually don't use it in the servers but it can help you in this case because it will monitor automatically the connections (it is quite common in desktop installations).
https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Deployment_Guide/ch-NetworkManager.html
To look for messages indicating an issue with the NIC just check the kernel ring buffer using the dmesg command.
For example when the cable is disconnected from a given interface this is what I get:
igb: eth1 NIC Link is Down
The first word will depend on the name of your network driver.
You could also configure the system to log these messages also to /var/log/messages (by default I am not sure if they appear there). Then it would be just a matter of monitoring the log, look for similar messages and restart the network service.
In any case the NetworkManager, if it is not already enabled, it should be an easier solution.
There is a module called miimon for monitoring the network interface's status. ethtool will give you the link status.
$ethtool eth0
...
Link detected: yes
I have a Linux server with multiple ips (so, multiple eth0, eth0:0, eth0:1 etc).
The script I'm trying to start is a php CLI script which is downloading stuff from an another server API, and I would like to change the IP based on different parameters. Once the script is started, I don't need anymore to change the ip OF THAT SPECIFIC script until his end.
Do you have any clue if it is possible to achieve it?
My other solution was to install Xen or OpenVZ and create N different VPS per each IP, but as you can see is definitely a PITA :-)
You don't specify how you connect to the other server, but with sockets you can try socket_bind.
EDIT:
With curl you can try curl_setopt.
CURLOPT_INTERFACE The name of the outgoing network interface to use. This can be an interface name, an IP address or a host name.
I know how to do it in C - you use bind() on your socket before you call connect(), and you bind to the IP address assigned to the desired interface, passing 0 for port. I don't know how to do it in PHP.