On Linux: How to Programmatically Determine If a Nic Interface Is Enabled and Plugged In

On Linux: how can I programmatically determine if a NIC interface is enabled and plugged in?

You can look at /sys/class/net/eth0/operstate where eth0 is your interface to see if it's up.

Look at /sys/class/net/eth0/carrier to see if there is a carrier.

Though I guess executing ifconfig and friends will give you more compatibility to *BSDs.

How to detect the physical connected state of a network cable/connector?

You want to look at the nodes in


/sys/class/net/

I experimented with mine:

Wire Plugged in:

eth0/carrier:1
eth0/operstate:unknown

Wire Removed:

eth0/carrier:0
eth0/operstate:down

Wire Plugged in Again:

eth0/carrier:1
eth0/operstate:up

Side Trick: harvesting all properties at once the easy way:

grep "" eth0/* 

This forms a nice list of key:value pairs.

How to check if interface is up

Answer was simple: I used the bitwise OR (|) operator instead of the AND (&) operator. Fixed code is:

bool is_interface_online(std::string interface) {
struct ifreq ifr;
int sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, interface.c_str());
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
perror("SIOCGIFFLAGS");
}
close(sock);
return !!(ifr.ifr_flags & IFF_UP);
}

Get notified about network interface change on Linux

I believe the netlink (man 7 netlink) facility provides information about network interfaces via the NETLINK_ROUTE family (man 7 rtnetlink). You may be able to select() or poll() on a netlink socket to get the information you want. I'm not certain of this, though; I haven't used it myself.

At a higher level, if the system is running NetworkManager, that'll broadcast events via D-Bus when the system's network status changes. The Epiphany browser uses these events, for example, to automatically activate "Work Offline" mode when the system loses its network connection, and switch back to online mode when network connectivity resumes. There are D-Bus client libraries for a variety of languages, and it's less platform-specific than netlink, so this is what I'd recommend using.

Programmatically check whether my machine has internet access or not

If you work on Windows, just try this

#include <iostream>
#include <windows.h>
#include <wininet.h>
using namespace std;

int main(){

if(InternetCheckConnection(L"http://www.google.com",FLAG_ICC_FORCE_CONNECTION,0))
{
cout << "connected to internet";
}

return 0;
}

How to get network manager device name in Qt programmatically?

is there any possibility to get the network adapter device name
(network adapter description) using Qt / C++ in windows

The answer is no. Qt does not have any functionality to get the device name (description). QNetworkInterface can only obtain the interface name and hardware address (IP).

On Windows you can use this small code example. pAdapter->Description should hold the value you are looking for.

#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <QCoreApplication>
#pragma comment(lib, "IPHLPAPI.lib")

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

PIP_ADAPTER_INFO pAdapterInfo;
pAdapterInfo = (IP_ADAPTER_INFO *) malloc(sizeof(IP_ADAPTER_INFO));
ULONG buflen = sizeof(IP_ADAPTER_INFO);

if(GetAdaptersInfo(pAdapterInfo, &buflen) == ERROR_BUFFER_OVERFLOW) {
free(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *) malloc(buflen);
}

if(GetAdaptersInfo(pAdapterInfo, &buflen) == NO_ERROR) {
PIP_ADAPTER_INFO pAdapter = pAdapterInfo;
while (pAdapter) {
printf("\tAdapter Name: \t%s\n", pAdapter->AdapterName);
printf("\tAdapter Desc: \t%s\n", pAdapter->Description);
printf("\n\n");
pAdapter = pAdapter->Next;
}
}
return a.exec();
}

Example output

    Adapter Name:   {DF6051AF-8F8F-4AA8-94A9-34656236F101}
Adapter Desc: VMware Virtual Ethernet Adapter for VMnet1

Adapter Name: {13C8DF49-6D60-4702-9B3A-688B2E372E42}
Adapter Desc: TAP-Windows Adapter V9

Adapter Name: {42635D10-33A3-4FE9-96BA-1071808B6E2B}
Adapter Desc: Realtek PCIe GBE Family Controller

Adapter Name: {AA62E2BA-D140-4C2C-A1B5-58082ED21E00}
Adapter Desc: 1 x 1 11b/g/n Wireless LAN PCI Express Half Mini Card-Ad apter

Adapter Name: {7AE540D3-69FE-4BEE-A5CA-482CAF06DAB8}
Adapter Desc: VMware Virtual Ethernet Adapter for VMnet8

How to detect IP address change on OSX programmatically in C or C++

There are multiple ways to do this, from IOKit notifications on up, but the simplest is probably the SystemConfiguration framework.

The first step is to fire up scutil and play with it to figure out which key(s) you want notification on:

$ scutil
> list
...
> n.add State:/Network/Global/IPv4
> n.watch
... unplug your network cable (or disconnect from WiFi)
notification callback (store address = 0x10e80e3c0).
changed key [0] = State:/Network/Global/IPv4

Look at that, got it on first try. :) But if you want to watch a particular NIC, or use IPv6 instead of v4, etc., obviously you'll want a different key from the list. Note that you can use regex patterns (POSIX style, as defined by man 3 regex), so if you want to watch, say, any NIC for IPv4, you can use State:/Network/Interface/.*/IPv4, or if you want to say global IPv4 or IPv6, State:/Network/Global/IPv., etc.

Now you just call SCDynamicStoreSetNotificationKeys with the keys you want.

Note that SCDynamicStoreSetNotificationKeys can take regex patterns (POSIX style, as defined by man 3 regex)

Since it's a bit painful in C, I'll write it in Python:

#!/usr/bin/python

from Foundation import *
from SystemConfiguration import *

def callback(store, keys, info):
for key in keys:
print key, SCDynamicStoreCopyValue(store, key)

store = SCDynamicStoreCreate(None,
"global-network-watcher",
callback,
None)
SCDynamicStoreSetNotificationKeys(store,
None,
['State:/Network/Global/IPv4'])
CFRunLoopAddSource(CFRunLoopGetCurrent(),
SCDynamicStoreCreateRunLoopSource(None, store, 0),
kCFRunLoopCommonModes)
CFRunLoopRun()

The main reason this is more painful in C is that you need dozens of lines of boilerplate for things like creating an CFArray with a CFString in it, printing CFString values, managing the lifetimes of the objects, etc. From Jeremy Friesner's comment, there's C++ sample code available if you'd rather read 113 lines of C++ than 17 lines of Python. But really, there's only one line here that should be unfamiliar to someone who's never used Python:

def callback(store, keys, info):
for key in keys:
print key, SCDynamicStoreCopyValue(store, key)

… is the equivalent of the C definition:

void callback(SCDynamicStoreRef store, CFArrayRef keys, void *info) {
/* iterate over keys, printing something for each one */
}

Oddly, I can't find the actual reference or guide documentation on SystemConfiguration anymore; the only thing that comes up for SCDynamicStoreSetNotificationKeys or related functions is in the Navigating Firewalls section of CFNetwork Programming Guide. But the original technote TN1145: Living in a Dynamic TCP/IP Environment still exists, and it's got enough background and sample code to figure out how write this yourself (and how to detect the new IP address(es) when you get notified).

Obviously this requires you to know what exactly you're trying to watch for. If you don't know that, nobody can tell you how to watch for it. Your original question was how to "detect an IP address change".

What the code above will do is detect when your default address changes. That's the address that gets used when you connect a socket to an internet address without binding it, or bind a socket to '0.0.0.0' to act as an internet server. If you haven't written the server code you care about, nearly all network clients do the former, and most servers do the latter unless you configure them otherwise, so that's probably all you care about.

Now let's go through the examples in your comments one by one:

if i am trying to determine a network change, wifi to LAN

There is no such thing as changing from WiFi to LAN. When you connect to a LAN, the WiFi is still working. Of course you can manually disable it before or after connecting to the LAN, but you don't have to, and it's a separate step, with a separate notification.

Normally, adding a LAN will change your default address to the LAN's address, so /Network/Global will notify you. If the OS can tell the LAN is not actually connected to the internet, or you've changed some hidden settings to make it prefer WiFi to LAN, etc., it won't change the default address, and /Network/Global will not notify you, but you probably don't care.

If you do care about whether a particular interface gets, loses, or changes an address, you can watch that interface. On most Macs, the built-in Ethernet is en0, and the built-in WiFi is en1, but of course you may have a third-party USB WiFi connector, or you may be using a tethered cell phone, or you may be interested not so much in the actual IP address of the LAN as in the VPN address of the VPN the LAN is connected to, etc. If you're writing something special purpose, you probably know which interface you care about, so you can watch, e.g., State:/Network/Interface/en0/IPv4. If you want to be notified on any interface changing no matter what, just watch State:/Network/Interface/.*/IPv4.

or to hotspot or another wifi

Changing from one WiFi network to another (hotspot or otherwise) will change en1—or, if you're using a third-party WiFi adapter, some other interface. If your default address at the time comes from WiFi, it will also change Global, which means the code above will work as-is. If your default address is still your LAN, Global won't change, but you probably don't care. If you do care, watch Interface/en1 or Interface/.*, etc., as above.

what all network settings should I be watching for IPV4 and 6

Just replace IPv4 with IPv6, or use IPv.. But do you really care about IPv6?

what else

What else do you care about? If there's something you actually want notification of, you presumably know what that something is.

Beyond that, if the system tells you that the foo address on the bar interface has changed to "ZZ9 Plural Z Alpha", and you've never heard of the foo protocol, what could you usefully do with that information? But if you really want it anyway, again, you can just use a regex pattern to watch for anything under each interface.



Related Topics



Leave a reply



Submit