https://stackoverflow.com/questions/4951257/using-c-code-to-get-same-info-as-ifconfig
#include <stdio.h>
#include <unistd.h>
#include <string.h> /* for strncpy */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
void parse_ioctl(const char *ifname)
{
printf("%s\n", "scarf rosari...");
int sock;
struct ifreq ifr;
struct sockaddr_in *ipaddr;
char address[INET_ADDRSTRLEN];
size_t ifnamelen;
/* copy ifname to ifr object */
ifnamelen = strlen(ifname);
if (ifnamelen >= sizeof(ifr.ifr_name)) {
printf("error :%s\n", ifr.ifr_name);
return ;
}
memcpy(ifr.ifr_name, ifname, ifnamelen);
ifr.ifr_name[ifnamelen] = '\0';
/* open socket */
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sock < 0) {
printf("error :%s\n", "unable to open socket..");
return;
}
/* process mac */
if (ioctl(sock, SIOCGIFHWADDR, &ifr) != -1) {
printf("Mac address: %02x:%02x:%02x:%02x:%02x:%02x\n",
(unsigned char)ifr.ifr_hwaddr.sa_data[0],
(unsigned char)ifr.ifr_hwaddr.sa_data[1],
(unsigned char)ifr.ifr_hwaddr.sa_data[2],
(unsigned char)ifr.ifr_hwaddr.sa_data[3],
(unsigned char)ifr.ifr_hwaddr.sa_data[4],
(unsigned char)ifr.ifr_hwaddr.sa_data[5]);
}
/* process mtu */
if (ioctl(sock, SIOCGIFMTU, &ifr) != -1) {
printf("MTU: %d\n", ifr.ifr_mtu);
}
/* die if cannot get address */
if (ioctl(sock, SIOCGIFADDR, &ifr) == -1) {
close(sock);
return;
}
/* process ip */
ipaddr = (struct sockaddr_in *)&ifr.ifr_addr;
if (inet_ntop(AF_INET, &ipaddr->sin_addr, address, sizeof(address)) != NULL) {
printf("Ip address: %s\n", address);
}
/* try to get broadcast */
if (ioctl(sock, SIOCGIFBRDADDR, &ifr) != -1) {
ipaddr = (struct sockaddr_in *)&ifr.ifr_broadaddr;
if (inet_ntop(AF_INET, &ipaddr->sin_addr, address, sizeof(address)) != NULL) {
printf("Broadcast: %s\n", address);
}
}
/* try to get mask */
if (ioctl(sock, SIOCGIFNETMASK, &ifr) != -1) {
ipaddr = (struct sockaddr_in *)&ifr.ifr_netmask;
if (inet_ntop(AF_INET, &ipaddr->sin_addr, address, sizeof(address)) != NULL) {
printf("Netmask: %s\n", address);
}
}
close(sock);
}
int main()
{
parse_ioctl("eth0");
}
$ ./getip2
scarf rosari...
Mac address: 00:0c:29:0e:eb:92
MTU: 1500
Ip address: 192.168.80.178
Broadcast: 192.168.80.255
Netmask: 255.255.255.0
离线
获取网关地址:
$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.80.2 0.0.0.0 UG 100 0 0 ens33
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.80.0 0.0.0.0 255.255.255.0 U 100 0 0 ens33
$ route -n |grep ens33 | grep 'UG[ \t]' | awk '{print $2}'
192.168.80.2
https://stackoverflow.com/questions/3288065/getting-gateway-to-use-for-a-given-ip-in-ansi-c
char* GetGatewayForInterface(const char* interface)
{
char* gateway = NULL;
char cmd [1000] = {0x0};
sprintf(cmd,"route -n | grep %s | grep 'UG[ \t]' | awk '{print $2}'", interface);
FILE* fp = popen(cmd, "r");
char line[256]={0x0};
if(fgets(line, sizeof(line), fp) != NULL)
gateway = string(line);
pclose(fp);
}
离线
或者用另外一个方法:
This is OS specific, there's no unified(or ANSI C) API for this.
Assuming Linux, the best way is to just parse /proc/net/route , look for the entry where Destination is 00000000 , the default gateway is in the Gateway column , where you can read the hex representation of the gateway IP address (in big endian , I believe)
If you want to do this via more specific API calls, you'll have to go through quite some hoops, here's an example program:
https://stackoverflow.com/questions/3288065/getting-gateway-to-use-for-a-given-ip-in-ansi-c
#include <netinet/in.h>
#include <net/if.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define BUFSIZE 8192
char gateway[255];
struct route_info {
struct in_addr dstAddr;
struct in_addr srcAddr;
struct in_addr gateWay;
char ifName[IF_NAMESIZE];
};
int readNlSock(int sockFd, char *bufPtr, int seqNum, int pId)
{
struct nlmsghdr *nlHdr;
int readLen = 0, msgLen = 0;
do {
/* Recieve response from the kernel */
if ((readLen = recv(sockFd, bufPtr, BUFSIZE - msgLen, 0)) < 0) {
perror("SOCK READ: ");
return -1;
}
nlHdr = (struct nlmsghdr *) bufPtr;
/* Check if the header is valid */
if ((NLMSG_OK(nlHdr, readLen) == 0)
|| (nlHdr->nlmsg_type == NLMSG_ERROR)) {
perror("Error in recieved packet");
return -1;
}
/* Check if the its the last message */
if (nlHdr->nlmsg_type == NLMSG_DONE) {
break;
} else {
/* Else move the pointer to buffer appropriately */
bufPtr += readLen;
msgLen += readLen;
}
/* Check if its a multi part message */
if ((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0) {
/* return if its not */
break;
}
} while ((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != pId));
return msgLen;
}
/* For printing the routes. */
void printRoute(struct route_info *rtInfo)
{
char tempBuf[512];
/* Print Destination address */
if (rtInfo->dstAddr.s_addr != 0)
strcpy(tempBuf, inet_ntoa(rtInfo->dstAddr));
else
sprintf(tempBuf, "*.*.*.*\t");
fprintf(stdout, "%s\t", tempBuf);
/* Print Gateway address */
if (rtInfo->gateWay.s_addr != 0)
strcpy(tempBuf, (char *) inet_ntoa(rtInfo->gateWay));
else
sprintf(tempBuf, "*.*.*.*\t");
fprintf(stdout, "%s\t", tempBuf);
/* Print Interface Name*/
fprintf(stdout, "%s\t", rtInfo->ifName);
/* Print Source address */
if (rtInfo->srcAddr.s_addr != 0)
strcpy(tempBuf, inet_ntoa(rtInfo->srcAddr));
else
sprintf(tempBuf, "*.*.*.*\t");
fprintf(stdout, "%s\n", tempBuf);
}
void printGateway()
{
printf("%s\n", gateway);
}
/* For parsing the route info returned */
void parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo)
{
struct rtmsg *rtMsg;
struct rtattr *rtAttr;
int rtLen;
rtMsg = (struct rtmsg *) NLMSG_DATA(nlHdr);
/* If the route is not for AF_INET or does not belong to main routing table
then return. */
if ((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN))
return;
/* get the rtattr field */
rtAttr = (struct rtattr *) RTM_RTA(rtMsg);
rtLen = RTM_PAYLOAD(nlHdr);
for (; RTA_OK(rtAttr, rtLen); rtAttr = RTA_NEXT(rtAttr, rtLen)) {
switch (rtAttr->rta_type) {
case RTA_OIF:
if_indextoname(*(int *) RTA_DATA(rtAttr), rtInfo->ifName);
break;
case RTA_GATEWAY:
rtInfo->gateWay.s_addr= *(u_int *) RTA_DATA(rtAttr);
break;
case RTA_PREFSRC:
rtInfo->srcAddr.s_addr= *(u_int *) RTA_DATA(rtAttr);
break;
case RTA_DST:
rtInfo->dstAddr .s_addr= *(u_int *) RTA_DATA(rtAttr);
break;
}
}
//printf("%s\n", inet_ntoa(rtInfo->dstAddr));
if (rtInfo->dstAddr.s_addr == 0)
sprintf(gateway, (char *) inet_ntoa(rtInfo->gateWay));
//printRoute(rtInfo);
return;
}
int main()
{
struct nlmsghdr *nlMsg;
struct rtmsg *rtMsg;
struct route_info *rtInfo;
char msgBuf[BUFSIZE];
int sock, len, msgSeq = 0;
/* Create Socket */
if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0)
perror("Socket Creation: ");
memset(msgBuf, 0, BUFSIZE);
/* point the header and the msg structure pointers into the buffer */
nlMsg = (struct nlmsghdr *) msgBuf;
rtMsg = (struct rtmsg *) NLMSG_DATA(nlMsg);
/* Fill in the nlmsg header*/
nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message.
nlMsg->nlmsg_type = RTM_GETROUTE; // Get the routes from kernel routing table .
nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // The message is a request for dump.
nlMsg->nlmsg_seq = msgSeq++; // Sequence of the message packet.
nlMsg->nlmsg_pid = getpid(); // PID of process sending the request.
/* Send the request */
if (send(sock, nlMsg, nlMsg->nlmsg_len, 0) < 0) {
printf("Write To Socket Failed...\n");
return -1;
}
/* Read the response */
if ((len = readNlSock(sock, msgBuf, msgSeq, getpid())) < 0) {
printf("Read From Socket Failed...\n");
return -1;
}
/* Parse and print the response */
rtInfo = (struct route_info *) malloc(sizeof(struct route_info));
//fprintf(stdout, "Destination\tGateway\tInterface\tSource\n");
for (; NLMSG_OK(nlMsg, len); nlMsg = NLMSG_NEXT(nlMsg, len)) {
memset(rtInfo, 0, sizeof(struct route_info));
parseRoutes(nlMsg, rtInfo);
}
free(rtInfo);
close(sock);
printGateway();
return 0;
}
离线
How can I enumerate the list of network devices or interfaces in C or C++ in FreeBSD ?
I want a list like "ue0", "ath0", "wlan0".
I've been looking though the ifconfig(1) code but its not clear at all where the task is being performed.
I'll happily take an answer, a pointer to a man page, or a link to the appropriate line in ifconfig. I may have just missed it.
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#include <arpa/inet.h>
int main(void)
{
char buf[1024];
struct ifconf ifc;
struct ifreq *ifr;
int sck;
int nInterfaces;
int i;
/* Get a socket handle. */
sck = socket(AF_INET, SOCK_DGRAM, 0);
if(sck < 0)
{
perror("socket");
return 1;
}
/* Query available interfaces. */
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
if(ioctl(sck, SIOCGIFCONF, &ifc) < 0)
{
perror("ioctl(SIOCGIFCONF)");
return 1;
}
/* Iterate through the list of interfaces. */
ifr = ifc.ifc_req;
nInterfaces = ifc.ifc_len / sizeof(struct ifreq);
for(i = 0; i < nInterfaces; i++)
{
struct ifreq *item = &ifr[i];
/* Show the device name and IP address */
printf("%s: IP %s",
item->ifr_name,
inet_ntoa(((struct sockaddr_in *)&item->ifr_addr)->sin_addr));
/* Get the broadcast address (added by Eric) */
if(ioctl(sck, SIOCGIFBRDADDR, item) >= 0)
printf(", BROADCAST %s", inet_ntoa(((struct sockaddr_in *)&item->ifr_broadaddr)->sin_addr));
printf("\n");
}
return 0;
}
$ ./i
lo: IP 127.0.0.1, BROADCAST 0.0.0.0
ens33: IP 192.168.80.178, BROADCAST 192.168.80.255
docker0: IP 172.17.0.1, BROADCAST 172.17.255.255
离线
https://stackoverflow.com/questions/13140753/binding-with-wifi-interface-in-linux
binding with wifi interface in linux
if (getifaddrs(&ifaddrs) < 0) {
my_loge(CRIT, "address detection failed");
return(0);
}
// zero
count = 0;
// unset all but CAP_HOST and CAP_ROUTER
sysinfo->cap &= (CAP_HOST|CAP_ROUTER);
sysinfo->cap_active &= (CAP_HOST|CAP_ROUTER);
// reset counter
sysinfo->physif_count = 0;
// mark all interfaces
TAILQ_FOREACH(netif, netifs, entries) {
netif->type = NETIF_OLD;
}
for (ifaddr = ifaddrs; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {
// skip interfaces without addresses
if (ifaddr->ifa_addr == NULL) {
my_log(INFO, "skipping interface %s", ifaddr->ifa_name);
continue;
}
// only handle datalink addresses
if (ifaddr->ifa_addr->sa_family != NETIF_AF)
continue;
// prepare ifr struct
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifaddr->ifa_name, sizeof(ifr.ifr_name));
// skip non-ethernet interfaces
memcpy(&saddrll, ifaddr->ifa_addr, sizeof(saddrll));
if (saddrll.sll_hatype != ARPHRD_ETHER) {
my_log(INFO, "skipping interface %s", ifaddr->ifa_name);
continue;
}
index = saddrll.sll_ifindex;
memcpy(&saddrdl, ifaddr->ifa_addr, sizeof(saddrdl));
if ((saddrdl.sdl_type != IFT_BRIDGE) &&
(saddrdl.sdl_type != IFT_ETHER)) {
if (saddrdl.sdl_type != IFT_ETHER) {
my_log(INFO, "skipping interface %s", ifaddr->ifa_name);
continue;
}
index = saddrdl.sdl_index;
// check for interfaces that are down
enabled = 0;
if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t)&ifr) >= 0)
enabled = (ifr.ifr_flags & IFF_UP);
// detect interface type
type = netif_type(sockfd, index, ifaddr, &ifr);
if (type == NETIF_REGULAR) {
my_log(INFO, "found ethernet interface %s", ifaddr->ifa_name);
sysinfo->physif_count++;
} else if (type == NETIF_WIRELESS) {
my_log(INFO, "found wireless interface %s", ifaddr->ifa_name);
sysinfo->cap |= CAP_WLAN;
sysinfo->cap_active |= (enabled == 1) ? CAP_WLAN : 0;
} else if (type == NETIF_TAP) {
my_log(INFO, "found tun/tap interface %s", ifaddr->ifa_name);
} else if (type == NETIF_BONDING) {
my_log(INFO, "found bond interface %s", ifaddr->ifa_name);
} else if (type == NETIF_BRIDGE) {
my_log(INFO, "found bridge interface %s", ifaddr->ifa_name);
sysinfo->cap |= CAP_BRIDGE;
sysinfo->cap_active |= (enabled == 1) ? CAP_BRIDGE : 0;
} else if (type == NETIF_VLAN) {
my_log(INFO, "found vlan interface %s", ifaddr->ifa_name);
} else if (type == NETIF_INVALID) {
my_log(INFO, "skipping interface %s", ifaddr->ifa_name);
continue;
}
https://raw.githubusercontent.com/sspans/ladvd/master/src/netif.c
/*
* $Id$
*
* Copyright (c) 2008, 2009, 2010
* Sten Spans <sten@blinkenlights.nl>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "common.h"
#include "util.h"
#include "proto/lldp.h"
#include <ifaddrs.h>
#include <dirent.h>
#include <ctype.h>
#if HAVE_ASM_TYPES_H
#include <asm/types.h>
#endif /* HAVE_ASM_TYPES_H */
#if HAVE_LINUX_SOCKIOS_H
#include <linux/sockios.h>
#endif /* HAVE_LINUX_SOCKIOS_H */
#if HAVE_SYS_SOCKIO_H
#include <sys/sockio.h>
#endif /* HAVE_SYS_SOCKIO_H */
#ifdef HAVE_NETPACKET_PACKET_H
#include <netpacket/packet.h>
#endif /* HAVE_NETPACKET_PACKET_H */
#ifdef HAVE_NET_IF_DL_H
#include <net/if_dl.h>
#endif /* HAVE_NET_IF_DL_H */
#ifdef HAVE_NET_IF_TYPES_H
#include <net/if_types.h>
#endif /* HAVE_NET_IF_TYPES_H */
#ifdef AF_PACKET
#define NETIF_AF AF_PACKET
#elif defined(AF_LINK)
#define NETIF_AF AF_LINK
#endif
static int sockfd = -1;
static void netif_addrs(struct ifaddrs *, struct nhead *, struct my_sysinfo *);
#if defined(NETIF_LINUX)
#include "netif_linux.c"
#elif defined(NETIF_BSD)
#include "netif_bsd.c"
#endif
void netif_init() {
if (sockfd == -1)
sockfd = my_socket(AF_INET, SOCK_DGRAM, 0);
}
// create netifs for a list of interfaces
uint16_t netif_fetch(int ifc, char *ifl[], struct my_sysinfo *sysinfo,
struct nhead *netifs) {
struct ifaddrs *ifaddrs, *ifaddr = NULL;
struct ifreq ifr;
int count = 0;
int type, enabled;
uint32_t index;
struct parent_req mreq = {};
#ifdef AF_PACKET
struct sockaddr_ll saddrll;
#elif defined(AF_LINK)
struct sockaddr_dl saddrdl;
#endif
// netifs
struct netif *n_netif, *netif = NULL;
if (sockfd == -1)
my_fatal("please call netif_init first");
if (getifaddrs(&ifaddrs) < 0) {
my_loge(CRIT, "address detection failed");
return(0);
}
// zero
count = 0;
// unset all but CAP_HOST and CAP_ROUTER
sysinfo->cap &= (CAP_HOST|CAP_ROUTER);
sysinfo->cap_active &= (CAP_HOST|CAP_ROUTER);
// reset counter
sysinfo->physif_count = 0;
// mark all interfaces
TAILQ_FOREACH(netif, netifs, entries) {
netif->type = NETIF_OLD;
}
for (ifaddr = ifaddrs; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {
// skip interfaces without addresses
if (ifaddr->ifa_addr == NULL) {
my_log(INFO, "skipping interface %s", ifaddr->ifa_name);
continue;
}
// only handle datalink addresses
if (ifaddr->ifa_addr->sa_family != NETIF_AF)
continue;
// prepare ifr struct
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifaddr->ifa_name, sizeof(ifr.ifr_name));
// skip non-ethernet interfaces
#ifdef AF_PACKET
memcpy(&saddrll, ifaddr->ifa_addr, sizeof(saddrll));
if (saddrll.sll_hatype != ARPHRD_ETHER) {
my_log(INFO, "skipping interface %s", ifaddr->ifa_name);
continue;
}
index = saddrll.sll_ifindex;
#elif defined(AF_LINK)
memcpy(&saddrdl, ifaddr->ifa_addr, sizeof(saddrdl));
#ifdef IFT_BRIDGE
if ((saddrdl.sdl_type != IFT_BRIDGE) &&
(saddrdl.sdl_type != IFT_ETHER)) {
#else
if (saddrdl.sdl_type != IFT_ETHER) {
#endif
my_log(INFO, "skipping interface %s", ifaddr->ifa_name);
continue;
}
index = saddrdl.sdl_index;
#endif
// check for interfaces that are down
enabled = 0;
if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t)&ifr) >= 0)
enabled = (ifr.ifr_flags & IFF_UP);
// detect interface type
type = netif_type(sockfd, index, ifaddr, &ifr);
if (type == NETIF_REGULAR) {
my_log(INFO, "found ethernet interface %s", ifaddr->ifa_name);
sysinfo->physif_count++;
} else if (type == NETIF_WIRELESS) {
my_log(INFO, "found wireless interface %s", ifaddr->ifa_name);
sysinfo->cap |= CAP_WLAN;
sysinfo->cap_active |= (enabled == 1) ? CAP_WLAN : 0;
} else if (type == NETIF_TAP) {
my_log(INFO, "found tun/tap interface %s", ifaddr->ifa_name);
} else if (type == NETIF_TEAMING) {
my_log(INFO, "found teaming interface %s", ifaddr->ifa_name);
} else if (type == NETIF_BONDING) {
my_log(INFO, "found bond interface %s", ifaddr->ifa_name);
} else if (type == NETIF_BRIDGE) {
my_log(INFO, "found bridge interface %s", ifaddr->ifa_name);
sysinfo->cap |= CAP_BRIDGE;
sysinfo->cap_active |= (enabled == 1) ? CAP_BRIDGE : 0;
} else if (type == NETIF_VLAN) {
my_log(INFO, "found vlan interface %s", ifaddr->ifa_name);
} else if (type == NETIF_INVALID) {
my_log(INFO, "skipping interface %s", ifaddr->ifa_name);
continue;
}
// skip interfaces that are down
if (enabled == 0) {
my_log(INFO, "skipping interface %s (down)", ifaddr->ifa_name);
continue;
}
my_log(INFO, "adding interface %s", ifaddr->ifa_name);
// fetch / create netif
if ((netif = netif_byindex(netifs, index)) == NULL) {
netif = my_malloc(sizeof(struct netif));
TAILQ_INSERT_TAIL(netifs, netif, entries);
} else {
// reset everything up to the tailq_entry but keep protos
uint16_t protos = netif->protos;
memset(netif, 0, offsetof(struct netif, entries));
netif->protos = protos;
}
// copy name, index and type
netif->index = index;
strlcpy(netif->name, ifaddr->ifa_name, sizeof(netif->name));
netif->type = type;
#ifdef HAVE_SYSFS
mreq.op = PARENT_ALIAS;
mreq.index = netif->index;
if (my_mreq(&mreq))
strlcpy(netif->description, mreq.buf, IFDESCRSIZE);
#elif defined(SIOCGIFDESCR)
#ifndef __FreeBSD__
ifr.ifr_data = (caddr_t)&netif->description;
#else
ifr.ifr_buffer.buffer = &netif->description;
ifr.ifr_buffer.length = IFDESCRSIZE;
#endif
ioctl(sockfd, SIOCGIFDESCR, &ifr);
#endif
if (sysinfo->mifname && (strcmp(netif->name, sysinfo->mifname) == 0))
sysinfo->mnetif = netif;
// update counters
count++;
}
// remove old interfaces
TAILQ_FOREACH_SAFE(netif, netifs, entries, n_netif) {
if (netif->type != NETIF_OLD)
continue;
my_log(INFO, "removing old interface %s", netif->name);
mreq.op = PARENT_CLOSE;
mreq.index = netif->index;
my_mreq(&mreq);
TAILQ_REMOVE(netifs, netif, entries);
if (sysinfo->mnetif == netif)
sysinfo->mnetif = NULL;
free(netif);
}
// add child subif lists to each bond/bridge
// detect vlan interface settings
TAILQ_FOREACH(netif, netifs, entries) {
my_log(INFO, "detecting %s settings", netif->name);
switch(netif->type) {
#ifdef HAVE_LIBTEAM
case NETIF_TEAMING:
netif_team(sockfd, netifs, netif, &ifr);
break;
#endif /* HAVE_LIBTEAM */
case NETIF_BONDING:
netif_bond(sockfd, netifs, netif, &ifr);
break;
case NETIF_BRIDGE:
netif_bridge(sockfd, netifs, netif, &ifr);
break;
case NETIF_VLAN:
netif_vlan(sockfd, netifs, netif, &ifr);
break;
case NETIF_REGULAR:
netif_device_id(sockfd, netif, &ifr);
break;
default:
break;
}
}
// add addresses to netifs
my_log(INFO, "fetching addresses for all interfaces");
netif_addrs(ifaddrs, netifs, sysinfo);
// use the first mac as chassis id
if ((netif = TAILQ_FIRST(netifs)) != NULL)
memcpy(&sysinfo->hwaddr, &netif->hwaddr, ETHER_ADDR_LEN);
// validate detected interfaces
if (ifc > 0) {
count = 0;
for (int j = 0; j < ifc; j++) {
netif = netif_byname(netifs, ifl[j]);
if (netif == NULL) {
my_log(CRIT, "interface %s is invalid", ifl[j]);
} else if (netif->type == NETIF_VLAN) {
my_log(CRIT, "vlan interface %s is not supported", ifl[j]);
} else {
netif->argv = 1;
count++;
}
}
if (count != ifc)
count = 0;
} else if (count == 0) {
my_log(CRIT, "no valid interface found");
}
if ((options & OPT_MNETIF) && !sysinfo->mnetif)
my_log(CRIT, "could not detect the specified management interface");
// cleanup
freeifaddrs(ifaddrs);
return(count);
};
// perform address detection for all netifs
static void netif_addrs(struct ifaddrs *ifaddrs, struct nhead *netifs,
struct my_sysinfo *sysinfo) {
struct ifaddrs *ifaddr;
struct netif *netif, *mnetif;
struct sockaddr_in saddr4;
struct sockaddr_in6 saddr6;
#ifdef AF_PACKET
struct sockaddr_ll saddrll;
#endif
#ifdef AF_LINK
struct sockaddr_dl saddrdl;
#endif
for (ifaddr = ifaddrs; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {
// skip interfaces without addresses
if (ifaddr->ifa_addr == NULL)
continue;
// fetch the netif for this ifaddr
netif = netif_byname(netifs, ifaddr->ifa_name);
if (netif == NULL)
continue;
if (ifaddr->ifa_addr->sa_family == AF_INET) {
if (netif->ipaddr4 != 0)
continue;
// alignment
memcpy(&saddr4, ifaddr->ifa_addr, sizeof(saddr4));
memcpy(&netif->ipaddr4, &saddr4.sin_addr,
sizeof(saddr4.sin_addr));
// detect mnetif
if (sysinfo->mnetif || (sysinfo->maddr4 == 0))
continue;
if (sysinfo->maddr4 == netif->ipaddr4)
sysinfo->mnetif = netif;
} else if (ifaddr->ifa_addr->sa_family == AF_INET6) {
if (!IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)netif->ipaddr6))
continue;
// alignment
memcpy(&saddr6, ifaddr->ifa_addr, sizeof(saddr6));
// skip link-local
if (IN6_IS_ADDR_LINKLOCAL(&saddr6.sin6_addr))
continue;
memcpy(&netif->ipaddr6, &saddr6.sin6_addr,
sizeof(saddr6.sin6_addr));
// detect mnetif
if (sysinfo->mnetif ||
(IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)sysinfo->maddr6)))
continue;
if (memcmp(&sysinfo->maddr6, &netif->ipaddr6,
sizeof(sysinfo->maddr6)) == 0)
sysinfo->mnetif = netif;
#ifdef AF_PACKET
} else if (ifaddr->ifa_addr->sa_family == AF_PACKET) {
// alignment
memcpy(&saddrll, ifaddr->ifa_addr, sizeof(saddrll));
memcpy(&netif->hwaddr, &saddrll.sll_addr, ETHER_ADDR_LEN);
#endif
#ifdef AF_LINK
} else if (ifaddr->ifa_addr->sa_family == AF_LINK) {
// alignment
memcpy(&saddrdl, ifaddr->ifa_addr, sizeof(saddrdl));
memcpy(&netif->hwaddr, LLADDR(&saddrdl), ETHER_ADDR_LEN);
#endif
}
}
// return when no management netif is available
if (!(options & OPT_MADDR) || !sysinfo->mnetif)
return;
mnetif = sysinfo->mnetif;
// use management address when requested
TAILQ_FOREACH(netif, netifs, entries) {
netif->ipaddr4 = mnetif->ipaddr4;
memcpy(&netif->ipaddr6, &mnetif->ipaddr6, sizeof(mnetif->ipaddr6));
}
}
// perform media detection on physical interfaces
int netif_media(struct netif *netif) {
struct ifreq ifr = {};
if (sockfd == -1)
my_fatal("please call netif_init first");
netif->duplex = -1;
netif->autoneg_supported = -1;
netif->autoneg_enabled = -1;
netif->autoneg_pmd = 0;
netif->mau = 0;
strlcpy(ifr.ifr_name, netif->name, sizeof(ifr.ifr_name));
// interface mtu
if (ioctl(sockfd, SIOCGIFMTU, (caddr_t)&ifr) >= 0)
netif->mtu = ifr.ifr_mtu;
else
my_log(INFO, "mtu detection failed on interface %s", netif->name);
// the rest only makes sense for real interfaces
if (netif->type != NETIF_REGULAR)
return(EXIT_SUCCESS);
netif_physical(sockfd, netif);
return(EXIT_SUCCESS);
}
离线