3737#include < sys/resource.h>
3838#include < string.h>
3939#include < iostream>
40+ #include < list>
4041#include " vma/util/if.h"
4142#include < sys/stat.h>
4243#include < linux/if_ether.h>
4344#include < linux/if_vlan.h>
4445#include < linux/sockios.h>
46+ #include < linux/netlink.h>
47+ #include < linux/rtnetlink.h>
4548#include < math.h>
4649#include < linux/ip.h> // IP header (struct iphdr) definition
4750#include < netinet/udp.h>
@@ -84,6 +87,7 @@ int get_sys_max_fd_num(int def_max_fd /*=1024*/)
8487 return def_max_fd;
8588}
8689
90+ // keep order of checks
8791int get_base_interface_name (const char *if_name, char *base_ifname, size_t sz_base_ifname)
8892{
8993 BULLSEYE_EXCLUDE_BLOCK_START
@@ -93,70 +97,25 @@ int get_base_interface_name(const char *if_name, char *base_ifname, size_t sz_ba
9397 BULLSEYE_EXCLUDE_BLOCK_END
9498 memset (base_ifname, 0 , sz_base_ifname);
9599
96- if (get_vlan_base_name_from_ifname (if_name, base_ifname, sz_base_ifname)) {
100+ // bond
101+ if (check_device_exist (if_name, BOND_DEVICE_FILE)) {
102+ snprintf (base_ifname, sz_base_ifname, " %s" ,if_name);
97103 return 0 ;
98104 }
99-
100- // Am I already the base (not virtual, not alias, can be bond)
101- if ((!check_device_exist (if_name, VIRTUAL_DEVICE_FOLDER) ||
102- check_device_exist (if_name, BOND_DEVICE_FILE)) && !strstr (if_name, " :" )) {
105+ // vlan
106+ if (check_device_exist (if_name, VIRTUAL_DEVICE_FOLDER) && get_vlan_base_name_from_ifname (if_name, base_ifname, sz_base_ifname)) {
107+ return 0 ;
108+ }
109+ // pysical interface or bond
110+ if (check_device_exist (if_name, FLAGS_PARAM_FILE)) {
103111 snprintf (base_ifname, sz_base_ifname, " %s" ,if_name);
104112 return 0 ;
105113 }
106-
107- unsigned char vlan_if_address[MAX_L2_ADDR_LEN];
108- const size_t ADDR_LEN = get_local_ll_addr (if_name, vlan_if_address, MAX_L2_ADDR_LEN, false );
109- if (ADDR_LEN > 0 ) {
110- struct ifaddrs *ifaddr, *ifa;
111- int rc = getifaddrs (&ifaddr);
112- BULLSEYE_EXCLUDE_BLOCK_START
113- if (rc == -1 ) {
114- __log_err (" getifaddrs failed" );
115- return -1 ;
116- }
117- BULLSEYE_EXCLUDE_BLOCK_END
118-
119- for (ifa = ifaddr; ifa != NULL ; ifa = ifa->ifa_next ) {
120- if (!strcmp (ifa->ifa_name , if_name)) {
121- continue ;
122- }
123- if (ifa->ifa_flags & IFF_SLAVE) {
124- // bond slave
125- continue ;
126- }
127-
128- if (strstr (ifa->ifa_name , " :" )) {
129- // alias
130- continue ;
131- }
132-
133- if (check_device_exist (ifa->ifa_name , VIRTUAL_DEVICE_FOLDER)) {
134- // virtual
135- if (!check_device_exist (ifa->ifa_name , BOND_DEVICE_FILE)) {
136- continue ;
137- }
138- }
139-
140- unsigned char tmp_mac[ADDR_LEN];
141- if (ADDR_LEN == get_local_ll_addr (ifa->ifa_name , tmp_mac, ADDR_LEN, false )) {
142- int size_to_compare;
143- if (ADDR_LEN == ETH_ALEN) size_to_compare = ETH_ALEN;
144- else size_to_compare = IPOIB_HW_ADDR_GID_LEN;
145- int offset = ADDR_LEN - size_to_compare;
146- if (0 == memcmp (vlan_if_address + offset, tmp_mac + offset, size_to_compare)) {
147- snprintf (base_ifname, sz_base_ifname, " %s" ,ifa->ifa_name );
148- freeifaddrs (ifaddr);
149- __log_dbg (" Found base_ifname %s for interface %s" , base_ifname, if_name);
150- return 0 ;
151- }
152- }
153- }
154-
155- freeifaddrs (ifaddr);
114+ // alias
115+ if (get_alias_base_name_from_ifname (if_name, base_ifname, sz_base_ifname)) {
116+ return 0 ;
156117 }
157- snprintf (base_ifname, sz_base_ifname, " %s" ,if_name);
158- __log_dbg (" no base for %s" , base_ifname, if_name);
159- return 0 ;
118+ return -1 ;
160119}
161120
162121unsigned short compute_ip_checksum (const unsigned short *buf, unsigned int nshort_words)
@@ -749,6 +708,126 @@ size_t get_vlan_base_name_from_ifname(const char* ifname, char* base_ifname, siz
749708 return 0 ;
750709}
751710
711+ size_t get_alias_base_name_from_ifname (const char * ifname, char * base_ifname, size_t sz_base_ifname)
712+ {
713+ int ret;
714+ // create netlink socket
715+ int sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
716+ if (sock < 0 ) {
717+ __log_dbg (" could not open netlink socket (%d %m)" , errno);
718+ return 0 ;
719+ }
720+ struct sockaddr_nl snl;
721+ memset (&snl, 0 , sizeof (snl));
722+ snl.nl_family = AF_NETLINK;
723+ snl.nl_pid = getpid ();
724+ if (bind (sock, (struct sockaddr *)&snl, sizeof (snl)) < 0 ) {
725+ __log_dbg (" could not bind netlink socket (%d %m)" , errno);
726+ close (sock);
727+ return 0 ;
728+ }
729+
730+ struct
731+ {
732+ struct nlmsghdr nlh;
733+ struct rtgenmsg g;
734+ } req;
735+
736+ // prepare request header
737+ memset (&req, 0 , sizeof (req));
738+ req.nlh .nlmsg_len = NLMSG_LENGTH (sizeof (struct rtgenmsg ));
739+ req.nlh .nlmsg_type = RTM_GETADDR;// RTM_GETLINK;
740+ req.nlh .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
741+ req.nlh .nlmsg_seq = 1 ;
742+ req.nlh .nlmsg_pid = getpid ();
743+ req.g .rtgen_family = AF_PACKET;
744+
745+ struct sockaddr_nl kernel;
746+ struct msghdr rtnl_msg;
747+ struct iovec io;
748+ memset (&rtnl_msg, 0 , sizeof (rtnl_msg));
749+ memset (&kernel, 0 , sizeof (kernel));
750+
751+ kernel.nl_family = AF_NETLINK;
752+ io.iov_base = &req;
753+ io.iov_len = req.nlh .nlmsg_len ;
754+ rtnl_msg.msg_iov = &io;
755+ rtnl_msg.msg_iovlen = 1 ;
756+ rtnl_msg.msg_name = &kernel;
757+ rtnl_msg.msg_namelen = sizeof (kernel);
758+
759+ ret = sendmsg (sock, (struct msghdr *) &rtnl_msg, 0 );
760+ if (ret < 0 ) {
761+ __log_dbg (" error sending netlink request (%d %m)" , errno);
762+ close (sock);
763+ return 0 ;
764+ }
765+
766+ unsigned char buffer[4096 ];
767+ struct nlmsghdr *msg_ptr;
768+ struct msghdr rtnl_reply;
769+ struct iovec io_reply;
770+
771+ memset (&io_reply, 0 , sizeof (io_reply));
772+ memset (&rtnl_reply, 0 , sizeof (rtnl_reply));
773+
774+ io.iov_base = buffer;
775+ io.iov_len = 10 *1024 ;
776+ rtnl_reply.msg_iov = &io;
777+ rtnl_reply.msg_iovlen = 1 ;
778+ rtnl_reply.msg_name = &kernel;
779+ rtnl_reply.msg_namelen = sizeof (kernel);
780+ ret = recvmsg (sock, &rtnl_reply, 0 ); /* read lots of data */
781+ if (ret < 0 ) {
782+ __log_dbg (" error receiving netlink data (%d %m)" , errno);
783+ close (sock);
784+ return 0 ;
785+ }
786+
787+ typedef std::pair<char *, int > int_index;
788+ list<int_index> interface_index_list;
789+ int my_index = -1 ;
790+ for (msg_ptr = (struct nlmsghdr *) buffer; NLMSG_OK (msg_ptr, (unsigned short )ret) && msg_ptr->nlmsg_type != NLMSG_DONE; msg_ptr = NLMSG_NEXT (msg_ptr, ret)) {
791+ if (msg_ptr->nlmsg_type == RTM_NEWADDR) {
792+ struct ifaddrmsg *iface;
793+ struct rtattr *attribute;
794+ int len;
795+
796+ iface = (struct ifaddrmsg *)NLMSG_DATA (msg_ptr);
797+ len = msg_ptr->nlmsg_len - NLMSG_LENGTH (sizeof (*iface));
798+ // save interface and it's index in map
799+ for (attribute = IFLA_RTA (iface); RTA_OK (attribute, len); attribute = RTA_NEXT (attribute, len)) {
800+ if (attribute->rta_type == IFA_LABEL) {
801+ char * attr_name = (char *)RTA_DATA (attribute);
802+ int_index elem;
803+ elem.first = attr_name;
804+ elem.second = iface->ifa_index ;
805+ interface_index_list.push_back (elem);
806+ // interface_index_list.add()[if_name] = iface->ifa_index;
807+ if (strcmp (attr_name, ifname) == 0 ) {
808+ my_index = iface->ifa_index ;
809+ }
810+ }
811+ }
812+ }
813+ }
814+
815+ // find a physical or bond interface that has the same index as me
816+ size_t name_size = 0 ;
817+ list<int_index>::iterator interface_index_iter;
818+ for (interface_index_iter=interface_index_list.begin (); interface_index_iter!=interface_index_list.end (); interface_index_iter++) {
819+ if ((interface_index_iter->second == my_index) && strcmp (interface_index_iter->first , ifname) != 0 ) {
820+ // check that this isn't another alias
821+ if (check_device_exist (interface_index_iter->first , FLAGS_PARAM_FILE)) {
822+ snprintf (base_ifname, sz_base_ifname, " %s" ,interface_index_iter->first );
823+ name_size = strlen (interface_index_iter->first );
824+ }
825+ }
826+ }
827+ close (sock);
828+ return name_size;
829+ }
830+
752831#if _BullseyeCoverage
753832 #pragma BullseyeCoverage off
754833#endif
@@ -946,12 +1025,14 @@ size_t get_local_ll_addr(IN const char * ifname, OUT unsigned char* addr, IN int
9461025{
9471026 char l2_addr_path[256 ] = {0 };
9481027 char buf[256 ] = {0 };
949-
950- // In case of alias (ib0/eth0:xx) take only the device name for that interface (ib0/eth0)
951- size_t ifname_len = strcspn (ifname, " :" ); // TODO: this is temp code till we get base interface for any alias format of an interface
9521028 const char * l2_addr_path_fmt = is_broadcast ? L2_BR_ADDR_FILE_FMT : L2_ADDR_FILE_FMT;
953- snprintf (l2_addr_path, sizeof (l2_addr_path)-1 , l2_addr_path_fmt, ifname_len, ifname);
954-
1029+ char base_ifname[32 ];
1030+ size_t ifname_len = get_alias_base_name_from_ifname (ifname, base_ifname, sizeof base_ifname);
1031+ if (ifname_len > 0 ) {
1032+ snprintf (l2_addr_path, sizeof (l2_addr_path)-1 , l2_addr_path_fmt, ifname_len, base_ifname);
1033+ } else {
1034+ snprintf (l2_addr_path, sizeof (l2_addr_path)-1 , l2_addr_path_fmt, strlen (ifname), ifname);
1035+ }
9551036 int len = priv_read_file (l2_addr_path, buf, sizeof (buf));
9561037 int bytes_len = (len + 1 ) / 3 ; // convert len from semantic of hex format L2 address with ':' delimiter (and optional newline character) into semantic of byte array
9571038 __log_dbg (" ifname=%s un-aliased-ifname=%.*s l2_addr_path=%s l2-addr=%s (addr-bytes_len=%d)" , ifname, ifname_len, ifname, l2_addr_path, buf, bytes_len);
0 commit comments