/* showif.c : PUBLIC DOMAIN - Jon Mayo - August 22, 2006 * - You may remove any comments you wish, modify this code any way you wish, * and distribute any way you wish. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * * Updated: June 1, 2011 */ /* finds all network interfaces and shows a little information about them. * some operating systems list interfaces multiple times because of different * flags, modes, etc. if you want to use this code you should be aware that * duplicate interfaces is a possibility */ #include #include /* Old way */ #include #include #include #include #include #include #include static void show_interface(int fd, const char *name) { int family; struct ifreq ifreq; char host[128]; memset(&ifreq, 0, sizeof ifreq); strncpy(ifreq.ifr_name, name, IFNAMSIZ); if (ioctl(fd, SIOCGIFADDR, &ifreq) != 0) { perror(name); return; /* ignore */ } switch (family = ifreq.ifr_addr.sa_family) { case AF_UNSPEC: return; /* ignore */ case AF_INET: case AF_INET6: getnameinfo(&ifreq.ifr_addr, sizeof(ifreq.ifr_addr), host, sizeof(host), 0, 0, NI_NUMERICHOST); break; default: sprintf(host, "unknown (family: %d)", family); } printf("%-24s%s\n", name, host); } static void list_interfaces(int fd, void (*show)(int fd, const char *name)) { struct ifreq *ifreq; struct ifconf ifconf; char buf[16384]; int i; size_t len; ifconf.ifc_len = sizeof buf; ifconf.ifc_buf = buf; if (ioctl(fd, SIOCGIFCONF, &ifconf) != 0) { perror("ioctl(SIOCGIFCONF)"); exit(EXIT_FAILURE); } ifreq = ifconf.ifc_req; for (i = 0; i < ifconf.ifc_len;) { /* some systems have ifr_addr.sa_len and adjust the length that * way, but not mine. weird */ #ifndef linux len = IFNAMSIZ + ifreq->ifr_addr.sa_len; #else len = sizeof * ifreq; #endif if (show) { show(fd, ifreq->ifr_name); } else { printf("%s\n", ifreq->ifr_name); } ifreq = (struct ifreq*)((char*)ifreq + len); i += len; } } /* IPv4 only, but works with old systems */ void show_all_interfaces_old(void) { int fd; const int family = AF_INET; fd = socket(family, SOCK_DGRAM, 0); if (fd < 0) { perror("socket()"); exit(EXIT_FAILURE); } list_interfaces(fd, show_interface); close(fd); } /** New way **/ #include #include void show_all_interfaces_new(void) { struct ifaddrs *a, *curr; char host[128]; if (getifaddrs(&a)) { perror("getifaddrs()"); return; } for (curr = a; curr; curr = curr->ifa_next) { size_t addr_len; switch (curr->ifa_addr->sa_family) { default: continue; case AF_INET: addr_len = sizeof(struct sockaddr_in); break; case AF_INET6: addr_len = sizeof(struct sockaddr_in6); break; } getnameinfo(curr->ifa_addr, addr_len, host, sizeof(host), 0, 0, NI_NUMERICHOST); printf("%-24s%s\n", curr->ifa_name, host); } freeifaddrs(a); } int main() { fprintf(stderr, "OLD:\n"); show_all_interfaces_old(); fprintf(stderr, "NEW:\n"); show_all_interfaces_new(); return EXIT_SUCCESS; }