87 #if defined( MBG_TGT_POSIX ) 89 #if defined( MBG_TGT_LINUX ) 91 #include <linux/types.h> 97 #if !defined( BITS_PER_LONG ) 104 #include <linux/sockios.h> 105 #include <linux/ethtool.h> 106 #include <linux/rtnetlink.h> 111 #include <sys/ioctl.h> 112 #include <arpa/inet.h> 113 #include <netinet/in.h> 118 #define SIOCGIFADDR 0 119 #define SIOCGIFNETMASK 0 120 #define SIOCGIFBRDADDR 0 122 #if defined( MBG_TGT_WIN32 ) 123 #define snprintf _snprintf 129 #if !defined( DEBUG_NETLINK ) 130 #if ( 0 && defined( DEBUG ) && defined( MBG_TGT_LINUX ) ) 131 #define DEBUG_NETLINK 1 133 #define DEBUG_NETLINK 0 140 #if !defined STANDALONE 141 #include <ptp2_cnf.h> 144 extern __attribute__( ( format( printf, 2, 3 ) ) ) void mbglog(
int priority, const
char *fmt, ... );
146 #endif // DEBUG_NETLINK 153 #define MAX_IP4_ADDR_STR_SIZE 16 156 #if defined( MBG_TGT_LINUX ) 190 if ( ( *p_mask & msb_mask ) == 0 )
256 const IP4_ADDR *p_mask,
const char *info )
265 n +=
snprintf_safe( &s[n], max_len - n,
"/%i", cidr_mask_bits );
301 unsigned long ul = strtoul( (
char *) cp, (
char **) &cp, 10 );
306 tmp_ip4_addr |= ul << ( 8 * (3 - i) );
319 *p_addr = tmp_ip4_addr;
322 return (
int) ( cp - s );
350 const char *cidr_str )
362 l = (int) strlen( cidr_str );
384 cidr_mask_bits = strtol( (
char *) cp, (
char **) &cp, 10 );
398 return (
int) ( cp - cidr_str );
425 if ( p_mask->
b[i] == 0xff )
431 if ( ( p_mask->
b[i] & msb_mask ) == 0 )
469 #define NUM_WORDS ( (int) ( sizeof( IP6_ADDR_STR ) / sizeof( uint16_t ) ) ) 477 } best = { 0 }, cur = { 0 };
494 if ( cur.base == -1 )
495 cur.base = i, cur.len = 1;
501 if ( cur.base != -1 )
503 if ( best.base == -1 || cur.len > best.len )
511 if ( cur.base != -1 )
513 if ( best.base == -1 || cur.len > best.len )
517 if ( best.base != -1 && best.len < 2 )
527 if ( best.base != -1 && i >= best.base && i < ( best.base + best.len ) )
540 if ( i == 6 && best.base == 0 && ( best.len == 6 || ( best.len == 5 && words[5] == 0xffff ) ) )
543 sprintf( tp,
"%x", words[i] );
548 if ( best.base != -1 && ( best.base + best.len ) == NUM_WORDS )
556 if ( ( tp - tmp ) > (
int) max_len )
593 const IP6_ADDR *p_mask,
const char *info )
601 n +=
snprintf_safe( &s[n], max_len - n,
"/%i", cidr_mask_bits );
630 const int cidr_mask_bits,
const char* info )
641 n +=
snprintf_safe( &s[n], max_len - n,
"/%i", cidr_mask_bits );
677 static const char xdigits[] =
"0123456789abcdef";
687 memset( p_addr, 0,
sizeof( *p_addr ) );
690 tp = startp +
sizeof( tmp );
706 while ( ( ch = tolower( (
int) *s++ ) ) !=
'\0' )
712 pch = strchr( xdigits, ch );
717 val |= ( pch - xdigits );
741 if ( tp -
sizeof(
uint16_t ) < startp )
744 *tp-- = (
uint8_t) ( val >> 8 ) & 0xff;
762 if ( tp -
sizeof(
uint16_t ) < startp )
765 *tp-- = (
uint8_t) (val >> 8) & 0xff;
769 if ( colonp != NULL )
775 const size_t n = colonp - tp;
781 for ( i = 0; i <= n; i++ )
783 startp[i] = colonp[i - n];
860 const char *cidr_str )
870 l = strlen( cidr_str );
889 cidr_mask_bits = strtol( (
char *) cp, (
char **) &cp, 10 );
897 *p_cidr = (int) cidr_mask_bits;
900 return (
int) ( cp - cidr_str );
924 memset( p_mask, 0,
sizeof( *p_mask ) );
926 if ( netmask_bits < 0 )
934 if ( netmask_bits > 8 )
941 p_mask->
b[i] = (0xff << ( 8 - netmask_bits ) ) & 0xff;
967 p_net_part->
b[i] = p_addr->
b[i] & p_mask->
b[i];
991 int num_octets,
char sep,
const char *info )
999 for ( i = 0; i < num_octets; i++ )
1004 n +=
snprintf_safe( &s[n], max_len - n,
"%02X", octets[i] );
1073 char *cp = (
char *) s;
1077 for ( i = 0; i < num_octets; )
1079 octets[i] = (
uint8_t) strtoul( cp, &cp, 16 );
1115 for ( i = 0; i < num_octets; i++ )
1116 if ( octets[i] != 0 )
1119 return i == num_octets;
1143 #if defined( MBG_TGT_POSIX ) 1160 if ( strlen( if_name ) > ( IFNAMSIZ - 1 ) )
1163 sock_fd = socket( AF_INET, SOCK_DGRAM, 0 );
1165 if ( sock_fd == -1 )
1168 strncpy_safe( p_ifreq->ifr_name, if_name,
sizeof( p_ifreq->ifr_name ) );
1170 rc = ioctl( sock_fd, ioctl_code, p_ifreq );
1183 #endif // defined( MBG_TGT_POSIX ) 1201 #if defined( MBG_TGT_LINUX ) 1202 struct ifreq ifr = { { { 0 } } };
1208 *p_intf_idx = ifr.ifr_ifindex;
1236 #if defined( MBG_TGT_LINUX ) 1237 struct ifreq ifr = { { { 0 } } };
1243 memcpy( p_mac_addr, ifr.ifr_hwaddr.sa_data,
sizeof( *p_mac_addr ) );
1249 memset( p_mac_addr, 0,
sizeof( *p_mac_addr ) );
1271 #if defined( MBG_TGT_LINUX ) 1272 struct ifreq ifr = { { { 0 } } };
1273 struct ethtool_value edata = { 0 };
1275 edata.cmd = ETHTOOL_GLINK;
1276 ifr.ifr_data = (caddr_t) &edata;
1281 rc = ( edata.data == 0 ) ? 0 : 1;
1306 #if defined( MBG_TGT_LINUX ) 1307 struct ifreq ifr = { { { 0 } } };
1308 struct ethtool_cmd cmd = { 0 };
1311 ifr.ifr_data = (
void *) &cmd;
1312 cmd.cmd = ETHTOOL_GSET;
1320 #if defined( ETH_TEST_FL_EXTERNAL_LB_DONE ) 1324 *p_speed = ok ? ethtool_cmd_speed( &cmd ) : 0;
1327 *p_speed = ok ? cmd.speed : 0;
1332 *p_duplex = ok ? cmd.duplex : -1;
1365 #if defined( MBG_TGT_LINUX ) 1366 struct ifreq ifr = { { { 0 } } };
1372 *p_addr = ntohl( ( (
struct sockaddr_in *) &ifr.ifr_addr )->sin_addr.s_addr );
1464 #if defined( MBG_TGT_LINUX ) 1472 int nl_read(
int sock_fd,
char *buf_ptr,
size_t buf_size,
int seq_num,
int pid )
1474 struct nlmsghdr *nl_hdr;
1481 if ( ( read_len = recv( sock_fd, buf_ptr, buf_size - msg_len, 0 ) ) == -1 )
1485 mbglog( LOG_ERR,
"%s: Failed to receive netlink packet: %s",
1491 nl_hdr = (
struct nlmsghdr *) buf_ptr;
1494 if ( ( NLMSG_OK( nl_hdr, read_len ) == 0 ) || ( nl_hdr->nlmsg_type == NLMSG_ERROR ) )
1497 mbglog( LOG_ERR,
"%s: Invalid header in received netlink packet",
1504 if ( nl_hdr->nlmsg_type == NLMSG_DONE )
1507 mbglog( LOG_ERR,
"%s: Reached last message in received packet",
1514 buf_ptr += read_len;
1515 msg_len += read_len;
1518 if ( ( nl_hdr->nlmsg_flags & NLM_F_MULTI ) == 0 )
1522 mbglog( LOG_ERR,
"%s: Received packet is not a multi part message",
1528 }
while ( ( nl_hdr->nlmsg_seq != seq_num ) || ( nl_hdr->nlmsg_pid != pid ) );
1531 mbglog( LOG_ERR,
"%s: Received packet has len %i",
1532 __func__, msg_len );
1544 void nl_log_bytes(
const char *fnc,
const char *info,
const void *p,
int n_bytes )
1550 for ( i = 0; i < n_bytes; i++ )
1553 mbglog( LOG_INFO,
"%s: attibute %s, copying %i bytes:%s",
1554 fnc, info, n_bytes, ws );
1566 struct rtmsg *rt_msg;
1567 struct rtattr *rt_attr;
1570 rt_msg = (
struct rtmsg *) NLMSG_DATA( nl_hdr );
1574 if ( rt_msg->rtm_family != AF_INET )
1577 mbglog( LOG_ERR,
"%s: Route is not AF_INET (%li), but %li",
1578 __func__, (
long) AF_INET, (
long) rt_msg->rtm_family );
1584 if ( rt_msg->rtm_table != RT_TABLE_MAIN )
1587 mbglog( LOG_ERR,
"%s: Route does not belong to main table (%li), but %li",
1588 __func__, (
long) RT_TABLE_MAIN, (
long) rt_msg->rtm_table );
1595 rt_attr = (
struct rtattr *) RTM_RTA( rt_msg );
1596 rt_len = RTM_PAYLOAD( nl_hdr );
1598 for ( ; RTA_OK( rt_attr, rt_len ); rt_attr = RTA_NEXT( rt_attr, rt_len ) )
1601 mbglog( LOG_ERR,
"rt_attr at %p, %i bytes left", rt_attr, rt_len );
1604 switch ( rt_attr->rta_type )
1607 if_indextoname( *(
int *)RTA_DATA( rt_attr ), rt_info->
ifName );
1609 mbglog( LOG_ERR,
"%s: attibute RTA_OIF, IF name: %s",
1610 __func__, rt_info->
ifName );
1615 memcpy( &rt_info->
gateWay, RTA_DATA( rt_attr ),
sizeof( rt_info->
gateWay ) );
1617 nl_log_bytes( __func__,
"RTA_GATEWAY", &rt_info->
gateWay,
sizeof( rt_info->
gateWay ) );
1622 memcpy( &rt_info->
srcAddr , RTA_DATA( rt_attr ),
sizeof( rt_info->
srcAddr ) );
1624 nl_log_bytes( __func__,
"RTA_PREFSRC", &rt_info->
srcAddr,
sizeof( rt_info->
srcAddr ) );
1629 memcpy( &rt_info->
dstAddr, RTA_DATA( rt_attr ),
sizeof( rt_info->
dstAddr ) );
1631 nl_log_bytes( __func__,
"RTA_DST", &rt_info->
dstAddr,
sizeof( rt_info->
dstAddr ) );
1649 memcpy( &rta_table, RTA_DATA( rt_attr ),
sizeof( rta_table ) );
1650 mbglog( LOG_ERR,
"%s: attibute RTA_TABLE %i (%i)",
1651 __func__, rta_table, rt_msg->rtm_table );
1656 mbglog( LOG_ERR,
"%s: Found unknown route type %li",
1657 __func__, (
long) rt_attr->rta_type );
1666 #endif // defined( MBG_TGT_LINUX ) 1683 #if defined( MBG_TGT_LINUX ) 1684 struct nlmsghdr *nlmsg;
1693 if ( ( sock_fd = socket( PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE ) ) == -1 )
1697 mbglog( LOG_ERR,
"%s: Failed to create netlink socket: %s",
1705 memset( msg_buf, 0,
sizeof( msg_buf ) );
1708 nlmsg = (
struct nlmsghdr *) msg_buf;
1711 nlmsg->nlmsg_len = NLMSG_LENGTH(
sizeof(
struct rtmsg ) );
1712 nlmsg->nlmsg_type = RTM_GETROUTE;
1714 nlmsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
1715 nlmsg->nlmsg_seq = msg_seq++;
1716 nlmsg->nlmsg_pid = getpid();
1719 if ( send( sock_fd, nlmsg, nlmsg->nlmsg_len, 0 ) == -1 )
1723 mbglog( LOG_ERR,
"%s: Failed to write to netlink socket: %s",
1730 if ( ( len =
nl_read( sock_fd, msg_buf,
sizeof( msg_buf ), msg_seq, getpid() ) ) < 0 )
1733 mbglog( LOG_ERR,
"%s: Failed to read from netlink socket",
1741 mbglog( LOG_ERR,
"%s: Read %i bytes from netlink socket", __func__, len );
1745 for ( idx = 0; NLMSG_OK( nlmsg, len ); nlmsg = NLMSG_NEXT( nlmsg, len ), idx++ )
1747 memset( &route_info, 0,
sizeof( route_info ) );
1750 mbglog( LOG_ERR,
"\nnl_msg at %p, %i bytes left", nlmsg, len );
1760 int l =
sizeof( ws );
1769 mbglog( LOG_ERR,
"%s: route %i: %s, if \"%s\"",
1770 __func__, idx, ws, route_info.
ifName );
1776 if ( strstr( (
char *) inet_ntoa( route_info.
dstAddr ),
"0.0.0.0" ) )
1778 *p_addr = ntohl( route_info.
gateWay.s_addr );
1784 mbglog( LOG_ERR,
"%s: Default gateway found: %s",
1785 __func__, (
char *) inet_ntoa( route_info.
gateWay ) );
1796 #endif // defined( MBG_TGT_LINUX ) 1928 memset( p, 0,
sizeof( *p ) );
size_t snprint_mac_addr(char *s, size_t max_len, const MBG_MAC_ADDR *p_mac_addr)
Print a MAC address to a string.
int cidr_str_to_ip6_addr_and_cidr_bits(IP6_ADDR *p_addr, int *p_cidr, const char *cidr_str)
Convert a string in CIDR notation to an IP6_ADDR and net mask bits.
The MAC address of a network interface.
Settings of an IPv4-only network interface.
char * strncpy_safe(char *dst, const char *src, size_t max_len)
A portable, safe implementation of strncpy()
uint32_t IP4_ADDR
An IPv4 address.
#define MAX_IP6_CIDR_NETMASK_BITS
static int get_specific_port_ip4_addr(const char *if_name, IP4_ADDR *p_addr, int sigioc_code)
Retrieve some IPv4 address-like info from a network interface.
void ip6_net_part_from_addr(IP6_ADDR *p_net_part, const IP6_ADDR *p_addr, const IP6_ADDR *p_mask)
Determine the network part of an IPv6 address based on the net mask.
static int nl_parse_routes(struct nlmsghdr *nl_hdr, struct route_info *rt_info)
#define MBG_ERR_PARM_FMT
parameter string format error
#define MBG_ERR_INV_PARM
Invalid parameter.
int get_port_ip4_addr(const char *if_name, IP4_ADDR *p_addr)
Retrieve the IPv4 address of a network interface.
#define IP6_ADDR_BITS
The number of bits used for an IPv6 address.
char IP6_ADDR_STR[(43+1)]
A buffer for an IPv6 address string.
#define mbg_rc_is_success(_rc)
void ip6_net_mask_from_cidr(IP6_ADDR *p_mask, int netmask_bits)
Compute an IPv6 net mask according to the number of CIDR netmask bits.
#define MBG_ERR_RANGE
input parameter was out of range
bool octets_are_all_zero(const uint8_t *octets, int num_octets)
Check if an array of octets is all zero.
IP4_ADDR ip_addr
the IP address
static __mbg_inline IP4_ADDR ip4_net_mask_from_cidr(int netmask_bits)
Compute an IP4 net mask according to the number of CIDR netmask bits.
size_t snprint_ip6_cidr_mask_addr(char *s, size_t max_len, const IP6_ADDR *p_addr, const int cidr_mask_bits, const char *info)
Print an IPv6 address plus number of net mask bits to string in CIDR notation.
#define MAX_IP4_CIDR_NETMASK_BITS
int cidr_str_to_ip6_addr_and_net_mask(IP6_ADDR *p_addr, IP6_ADDR *p_mask, const char *cidr_str)
Convert a string in CIDR notation to an IP6_ADDR and net mask.
int do_siocg_ioctl(const char *if_name, int ioctl_code, struct ifreq *p_ifreq)
Do a SIOCGxxx IOCTL call to read specific information from a LAN interface.
MBG_VLAN_CFG vlan_cfg
VLAN configuration.
#define MIN_IP4_CIDR_NETMASK_BITS
int str_to_octets(uint8_t *octets, int num_octets, const char *s)
Set a MAC ID or a similar array of octets from a string.
uint16_t flags
see MBG_IP4_FLAG_MASKS
size_t snprint_ip4_cidr_addr(char *s, size_t max_len, const IP4_ADDR *p_addr, const IP4_ADDR *p_mask, const char *info)
Print an IPv4 address plus net mask in CIDR notation to a string.
int get_port_intf_idx(const char *if_name, int *p_intf_idx)
Retrieve the index of a specific network interface.
bool mac_addr_is_all_zero(const MBG_MAC_ADDR *p_addr)
Check if a MAC address is all zero.
int get_ip4_net_mask_bits(const IP4_ADDR *p_mask)
Count the number of sequential bits in an IPv4 net mask.
int get_ip4_gateway(IP4_ADDR *p_addr)
Retrieve the IPv4 gateway (default route)
int get_port_ip4_netmask_str(const char *if_name, char *p_addr_buf, int buf_size)
Retrieve the IPv4 net mask of a network interface as string.
int get_port_ip4_broad_addr_str(const char *if_name, char *p_addr_buf, int buf_size)
Retrieve the IPv4 broadcast address of a network interface as string.
#define MBG_SUCCESS
Error codes used with Meinberg devices and drivers.
uint8_t b[(128/8)]
bytes holding the address bits (not the string notation), b[0] == LSBs
int get_port_ip4_broad_addr(const char *if_name, IP4_ADDR *p_addr)
Retrieve the IPv4 broadcast address of a network interface.
size_t snprint_ip6_cidr_addr(char *s, size_t max_len, const IP6_ADDR *p_addr, const IP6_ADDR *p_mask, const char *info)
Print an IPv6 address plus net mask to string in CIDR notation.
int str_to_ip6_addr(IP6_ADDR *p_addr, const char *s)
Convert a string to an IP6_ADDR.
IP4_ADDR netmask
the network mask
int check_port_link(const char *if_name)
Check the link state of a network interface.
int get_port_ip4_addr_str(const char *if_name, char *p_addr_buf, int buf_size)
Retrieve the IPv4 address of a network interface as string.
#define IP6_ADDR_BYTES
The number of bytes used for an IPv6 address.
int get_port_ip4_settings(const char *if_name, IP4_SETTINGS *p)
Retrieve the current IPv4 settings of a network interface.
static int nl_read(int sock_fd, char *buf_ptr, size_t buf_size, int seq_num, int pid)
Read a requested message from the netlink socket.
int snprintf_safe(char *s, size_t max_len, const char *fmt,...)
A portable, safe implementation of snprintf()
#define MBG_ERR_DATA_FMT
invalid data format
int check_port_status(const char *if_name, int *p_speed, int *p_duplex)
Check the state of a network interface.
IP4_ADDR gateway
the default gateway
#define MBG_ERR_OVERFLOW
range or buffer overflow
int get_port_ip4_netmask(const char *if_name, IP4_ADDR *p_addr)
Retrieve the IPv4 net mask of a network interface.
size_t snprint_ip4_addr(char *s, size_t max_len, const IP4_ADDR *p_addr, const char *info)
Print an IPv4 address to a dotted quad formatted string.
int mbg_get_last_socket_error(const char *info)
Get and translate last error after socket function call.
#define mbg_rc_is_error(_rc)
int get_ip6_net_mask_bits(const IP6_ADDR *p_mask)
Count the number of sequential bits in an IPv6 net mask.
const char * mbg_strerror(int mbg_errno)
Return an error string associated with the MBG_ERROR_CODES.
int cidr_str_to_ip4_addr_and_net_mask(IP4_ADDR *p_addr, IP4_ADDR *p_mask, const char *cidr_str)
Convert a string in CIDR notation to an IP4_ADDR and net mask.
unsigned __int64 uint64_t
#define MIN_IP6_CIDR_NETMASK_BITS
size_t snprint_ip6_addr(char *s, size_t max_len, const IP6_ADDR *p_addr, const char *info)
Print an IPv6 address in optimized format to a string.
size_t snprint_octets(char *s, size_t max_len, const uint8_t *octets, int num_octets, char sep, const char *info)
Print a MAC ID or similar array of octets to a string.
int str_to_ip4_addr(IP4_ADDR *p_addr, const char *s)
Convert a string to an IP4_ADDR.
#define MBG_ERR_NOT_SUPP_ON_OS
Function is not supported on this operating system.
IP4_ADDR broad_addr
the broadcast address
size_t snprint_ptp_clock_id(char *s, size_t max_len, const PTP_CLOCK_ID *p)
Print a PTP_CLOCK_ID to a string.
int get_port_mac_addr(const char *if_name, MBG_MAC_ADDR *p_mac_addr)
Retrieve the MAC address of a network interface.