"Fossies" - the Fresh Open Source Software Archive

Member "sysdig-0.26.1/userspace/libsinsp/ifinfo.cpp" (24 May 2019, 9730 Bytes) of package /linux/misc/sysdig-0.26.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ifinfo.cpp" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.25_vs_0.26.0.

    1 /*
    2 Copyright (C) 2013-2018 Draios Inc dba Sysdig.
    3 
    4 This file is part of sysdig.
    5 
    6 Licensed under the Apache License, Version 2.0 (the "License");
    7 you may not use this file except in compliance with the License.
    8 You may obtain a copy of the License at
    9 
   10     http://www.apache.org/licenses/LICENSE-2.0
   11 
   12 Unless required by applicable law or agreed to in writing, software
   13 distributed under the License is distributed on an "AS IS" BASIS,
   14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   15 See the License for the specific language governing permissions and
   16 limitations under the License.
   17 
   18 */
   19 
   20 #include "sinsp.h"
   21 #include "sinsp_int.h"
   22 
   23 sinsp_network_interfaces::sinsp_network_interfaces(sinsp* inspector)
   24     : m_inspector(inspector)
   25 {
   26     if(inet_pton(AF_INET6, "::1", m_ipv6_loopback_addr.m_b) != 1)
   27     {
   28         throw sinsp_exception("Could not convert ipv6 loopback address ::1 to ipv6addr struct");
   29     }
   30 }
   31 
   32 sinsp_ipv4_ifinfo::sinsp_ipv4_ifinfo(uint32_t addr, uint32_t netmask, uint32_t bcast, const char* name)
   33 {
   34     m_addr = addr;
   35     m_netmask = netmask;
   36     m_bcast = bcast;
   37     m_name = name;
   38 }
   39 
   40 void sinsp_ipv4_ifinfo::convert_to_string(char * dest, const uint32_t addr)
   41 {
   42     sprintf(
   43         dest, 
   44         "%d.%d.%d.%d", 
   45         (addr & 0xFF),
   46         ((addr & 0xFF00) >> 8),
   47         ((addr & 0xFF0000) >> 16),
   48         ((addr & 0xFF000000) >> 24));
   49 }
   50 
   51 string sinsp_ipv4_ifinfo::address() const
   52 {
   53     char str_addr[16];
   54     convert_to_string(str_addr, m_addr);
   55     return string(str_addr);
   56 }
   57 
   58 string sinsp_ipv4_ifinfo::to_string() const
   59 {
   60     char s[100];
   61     char str_addr[16];
   62     char s_netmask[16];
   63     char s_bcast[16];
   64 
   65     convert_to_string(str_addr, m_addr);
   66     convert_to_string(s_netmask, m_netmask);
   67     convert_to_string(s_bcast, m_bcast);
   68     sprintf(s, "%s inet %s netmask %s broadcast %s", m_name.c_str(), str_addr, s_netmask, s_bcast);
   69     return string(s);
   70 }
   71 
   72 uint32_t sinsp_network_interfaces::infer_ipv4_address(uint32_t destination_address)
   73 {
   74     vector<sinsp_ipv4_ifinfo>::iterator it;
   75 
   76     // first try to find exact match
   77     for(it = m_ipv4_interfaces.begin(); it != m_ipv4_interfaces.end(); it++)
   78     {
   79         if(it->m_addr == destination_address)
   80         {
   81             return it->m_addr;
   82         }
   83     }
   84 
   85     // try to find an interface for the same subnet
   86     for(it = m_ipv4_interfaces.begin(); it != m_ipv4_interfaces.end(); it++)
   87     {
   88         if((it->m_addr & it->m_netmask) == (destination_address & it->m_netmask))
   89         {
   90             return it->m_addr;
   91         }
   92     }
   93 
   94     // otherwise take the first non loopback interface
   95     for(it = m_ipv4_interfaces.begin(); it != m_ipv4_interfaces.end(); it++)
   96     {
   97         if(it->m_addr != LOOPBACK_ADDR)
   98         {
   99             return it->m_addr;
  100         }
  101     }
  102     return 0;
  103 }
  104 
  105 void sinsp_network_interfaces::update_fd(sinsp_fdinfo_t *fd)
  106 {
  107     ipv4tuple *pipv4info = &(fd->m_sockinfo.m_ipv4info);
  108     ipv6tuple *pipv6info = &(fd->m_sockinfo.m_ipv6info);
  109 
  110     //
  111     // only handle ipv4/ipv6 udp sockets
  112     //
  113     if(fd->m_type != SCAP_FD_IPV4_SOCK &&
  114        fd->m_type != SCAP_FD_IPV6_SOCK)
  115     {
  116         return;
  117     }
  118 
  119     if(fd->m_type == SCAP_FD_IPV4_SOCK)
  120     {
  121 
  122         if(0 != pipv4info->m_fields.m_sip && 0 != pipv4info->m_fields.m_dip)
  123         {
  124             return;
  125         }
  126         if(0 == pipv4info->m_fields.m_sip)
  127         {
  128             uint32_t newaddr;
  129             newaddr = infer_ipv4_address(pipv4info->m_fields.m_dip);
  130 
  131             if(newaddr == pipv4info->m_fields.m_dip)
  132             {
  133                 if(pipv4info->m_fields.m_sport == pipv4info->m_fields.m_dport)
  134                 {
  135                     return;
  136                 }
  137             }
  138 
  139             pipv4info->m_fields.m_sip = newaddr;
  140         }
  141         else
  142         {
  143             uint32_t newaddr;
  144             newaddr = infer_ipv4_address(pipv4info->m_fields.m_sip);
  145 
  146             if(newaddr == pipv4info->m_fields.m_sip)
  147             {
  148                 if(pipv4info->m_fields.m_sport == pipv4info->m_fields.m_dport)
  149                 {
  150                     return;
  151                 }
  152             }
  153 
  154             pipv4info->m_fields.m_dip = newaddr;
  155         }
  156     }
  157     else if(fd->m_type == SCAP_FD_IPV6_SOCK)
  158     {
  159 
  160         if(ipv6addr::empty_address != pipv6info->m_fields.m_sip &&
  161            ipv6addr::empty_address != pipv6info->m_fields.m_dip)
  162         {
  163             return;
  164         }
  165         if(ipv6addr::empty_address == pipv6info->m_fields.m_sip)
  166         {
  167             ipv6addr newaddr;
  168             newaddr = infer_ipv6_address(pipv6info->m_fields.m_dip);
  169 
  170             if(newaddr == pipv6info->m_fields.m_dip)
  171             {
  172                 if(pipv6info->m_fields.m_sport == pipv6info->m_fields.m_dport)
  173                 {
  174                     return;
  175                 }
  176             }
  177 
  178             pipv6info->m_fields.m_sip = newaddr;
  179         }
  180         else
  181         {
  182             ipv6addr newaddr;
  183             newaddr = infer_ipv6_address(pipv6info->m_fields.m_sip);
  184 
  185             if(newaddr == pipv6info->m_fields.m_sip)
  186             {
  187                 if(pipv6info->m_fields.m_sport == pipv6info->m_fields.m_dport)
  188                 {
  189                     return;
  190                 }
  191             }
  192 
  193             pipv6info->m_fields.m_dip = newaddr;
  194         }
  195     }
  196 }
  197 
  198 bool sinsp_network_interfaces::is_ipv4addr_in_subnet(uint32_t addr)
  199 {
  200     vector<sinsp_ipv4_ifinfo>::iterator it;
  201 
  202     //
  203     // Accept everything that comes from 192.168.0.0/16 or 10.0.0.0/8
  204     //
  205     if((addr & 0x000000ff) == 0x0000000a ||
  206         (addr & 0x0000ffff) == 0x0000a8c0 ||
  207         (addr & 0x00003fff) == 0x000010ac)
  208     {
  209         return true;
  210     }
  211 
  212     // try to find an interface for the same subnet
  213     for(it = m_ipv4_interfaces.begin(); it != m_ipv4_interfaces.end(); it++)
  214     {
  215         if((it->m_addr & it->m_netmask) == (addr & it->m_netmask))
  216         {
  217             return true;
  218         }
  219     }
  220 
  221     return false;
  222 }
  223 
  224 bool sinsp_network_interfaces::is_ipv4addr_in_local_machine(uint32_t addr, sinsp_threadinfo* tinfo)
  225 {
  226     if(!tinfo->m_container_id.empty())
  227     {
  228         const sinsp_container_info * container_info =
  229             m_inspector->m_container_manager.get_container(tinfo->m_container_id);
  230 
  231         //
  232         // Note: if we don't have container info, any pick we make is arbitrary.
  233         // To at least achieve consistency across client and server, we just match the host interface addresses. 
  234         //
  235         if(container_info)
  236         {
  237             if(container_info->m_container_ip != 0)
  238             {
  239                 //
  240                 // We have a container info with a valid container IP. Let's use it.
  241                 //
  242                 if(addr == htonl(container_info->m_container_ip))
  243                 {
  244                     return true;
  245                 }
  246             }
  247             else
  248             {
  249                 //
  250                 // Container info is valid, but the IP address is zero.
  251                 // Scan the list of the containers looking for matches.
  252                 // If no match is found, we just jump to checking the
  253                 // host interfaces.
  254                 //
  255 
  256                 if(!container_info->m_metadata_complete)
  257                 {
  258                     g_logger.format(sinsp_logger::SEV_DEBUG, "Checking IP address of container %s with incomplete metadata",
  259                         tinfo->m_container_id.c_str());
  260                 }
  261 
  262                 const unordered_map<string, sinsp_container_info>* clist = m_inspector->m_container_manager.get_containers();
  263 
  264                 for(auto it = clist->begin(); it != clist->end(); ++it)
  265                 {
  266                     if(!it->second.m_metadata_complete)
  267                     {
  268                         g_logger.format(sinsp_logger::SEV_DEBUG, "Checking IP address of container %s with incomplete metadata (in context of %s)",
  269                                 it->second.m_id.c_str(), tinfo->m_container_id.c_str());
  270                     }
  271 
  272                     if(htonl(it->second.m_container_ip) == addr)
  273                     {
  274                         return true;
  275                     }
  276                 }
  277             }
  278         }
  279     }
  280 
  281     vector<sinsp_ipv4_ifinfo>::iterator it;
  282 
  283     // try to find an interface that has the given IP as address
  284     for(it = m_ipv4_interfaces.begin(); it != m_ipv4_interfaces.end(); it++)
  285     {
  286         if(it->m_addr == addr)
  287         {
  288             return true;
  289         }
  290     }
  291 
  292     return false;
  293 }
  294 
  295 void sinsp_network_interfaces::import_ipv4_ifaddr_list(uint32_t count, scap_ifinfo_ipv4* plist)
  296 {
  297     if (count == 0)
  298     {
  299         return;
  300     }
  301     for(uint32_t j = 0; j < count; j++)
  302     {
  303         sinsp_ipv4_ifinfo info;
  304         info.m_addr = plist->addr;
  305         info.m_netmask = plist->netmask;
  306         info.m_bcast = plist->bcast;
  307         info.m_name = plist->ifname;
  308         m_ipv4_interfaces.push_back(info);
  309         plist++;
  310     }
  311 }
  312 
  313 ipv6addr sinsp_network_interfaces::infer_ipv6_address(ipv6addr &destination_address)
  314 {
  315     vector<sinsp_ipv6_ifinfo>::iterator it;
  316 
  317     // first try to find exact match
  318     for(it = m_ipv6_interfaces.begin(); it != m_ipv6_interfaces.end(); it++)
  319     {
  320         if(destination_address == it->m_net)
  321         {
  322             return it->m_net;
  323         }
  324     }
  325 
  326     // try to find an interface for the same subnet
  327     for(it = m_ipv6_interfaces.begin(); it != m_ipv6_interfaces.end(); it++)
  328     {
  329         if(it->m_net.in_subnet(destination_address))
  330         {
  331             return it->m_net;
  332         }
  333     }
  334 
  335     // otherwise take the first non loopback interface
  336     for(it = m_ipv6_interfaces.begin(); it != m_ipv6_interfaces.end(); it++)
  337     {
  338         if(it->m_net != m_ipv6_loopback_addr)
  339         {
  340             return it->m_net;
  341         }
  342     }
  343 
  344     return ipv6addr::empty_address;
  345 }
  346 
  347 bool sinsp_network_interfaces::is_ipv6addr_in_local_machine(ipv6addr &addr, sinsp_threadinfo* tinfo)
  348 {
  349     if(!tinfo->m_container_id.empty())
  350     {
  351         // For now, not supporting ipv6 networking for containers. So always return false;
  352         return false;
  353     }
  354 
  355     vector<sinsp_ipv6_ifinfo>::iterator it;
  356 
  357     // try to find an interface that has the given IP as address
  358     for(it = m_ipv6_interfaces.begin(); it != m_ipv6_interfaces.end(); it++)
  359     {
  360         if(addr.in_subnet(it->m_net))
  361         {
  362             return true;
  363         }
  364     }
  365 
  366     return false;
  367 }
  368 
  369 void sinsp_network_interfaces::import_ipv6_ifaddr_list(uint32_t count, scap_ifinfo_ipv6* plist)
  370 {
  371     if (count == 0)
  372     {
  373         return;
  374     }
  375     for(uint32_t j = 0; j < count; j++)
  376     {
  377         sinsp_ipv6_ifinfo info;
  378 
  379         // Only saving the address portion. (Assumes
  380         // convention of first 48 bits for network, next 16
  381         // bits for subnet).
  382         memcpy(info.m_net.m_b, plist->addr, SCAP_IPV6_ADDR_LEN);
  383 
  384         info.m_name = plist->ifname;
  385         m_ipv6_interfaces.push_back(info);
  386         plist++;
  387     }
  388 }
  389 
  390 void sinsp_network_interfaces::import_interfaces(scap_addrlist* paddrlist)
  391 {
  392     if(NULL != paddrlist)
  393     {
  394         clear();
  395         import_ipv4_ifaddr_list(paddrlist->n_v4_addrs, paddrlist->v4list);
  396         import_ipv6_ifaddr_list(paddrlist->n_v6_addrs, paddrlist->v6list);
  397     }
  398 }
  399 
  400 void sinsp_network_interfaces::import_ipv4_interface(const sinsp_ipv4_ifinfo& ifinfo)
  401 {
  402     m_ipv4_interfaces.push_back(ifinfo);
  403 }
  404 
  405 void sinsp_network_interfaces::import_ipv6_interface(const sinsp_ipv6_ifinfo& ifinfo)
  406 {
  407     m_ipv6_interfaces.push_back(ifinfo);
  408 }
  409 
  410 vector<sinsp_ipv4_ifinfo>* sinsp_network_interfaces::get_ipv4_list()
  411 {
  412     return &m_ipv4_interfaces;
  413 }
  414 
  415 vector<sinsp_ipv6_ifinfo>* sinsp_network_interfaces::get_ipv6_list()
  416 {
  417     return &m_ipv6_interfaces;
  418 }