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.