Ejemplo n.º 1
0
DWORD getRouteTable(PMIB_IPFORWARDTABLE *ppIpForwardTable, HANDLE heap,
 DWORD flags)
{
  DWORD ret;

  if (!ppIpForwardTable)
    ret = ERROR_INVALID_PARAMETER;
  else {
    DWORD numRoutes = getNumRoutes();
    DWORD size = sizeof(MIB_IPFORWARDTABLE);
    PMIB_IPFORWARDTABLE table;

    if (numRoutes > 1)
      size += (numRoutes - 1) * sizeof(MIB_IPFORWARDROW);
    table = HeapAlloc(heap, flags, size);
    if (table) {
#if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP)
       int mib[6] = {CTL_NET, PF_ROUTE, 0, PF_INET, NET_RT_DUMP, 0};
       size_t needed;
       char *buf, *lim, *next, *addrPtr;
       struct rt_msghdr *rtm;

       if (sysctl (mib, 6, NULL, &needed, NULL, 0) < 0)
       {
          ERR ("sysctl 1 failed!\n");
          HeapFree (GetProcessHeap (), 0, table);
          return NO_ERROR;
       }

       buf = HeapAlloc (GetProcessHeap (), 0, needed);
       if (!buf)
       {
          HeapFree (GetProcessHeap (), 0, table);
          return ERROR_OUTOFMEMORY;
       }

       if (sysctl (mib, 6, buf, &needed, NULL, 0) < 0)
       {
          ERR ("sysctl 2 failed!\n");
          HeapFree (GetProcessHeap (), 0, table);
          HeapFree (GetProcessHeap (), 0, buf);
          return NO_ERROR;
       }

       *ppIpForwardTable = table;
       table->dwNumEntries = 0;

       lim = buf + needed;
       for (next = buf; next < lim; next += rtm->rtm_msglen)
       {
          int i;

          rtm = (struct rt_msghdr *)next;

          if (rtm->rtm_type != RTM_GET)
          {
             WARN ("Got unexpected message type 0x%x!\n",
                   rtm->rtm_type);
             continue;
          }

          /* Ignore all entries except for gateway routes which aren't
             multicast */
          if (!(rtm->rtm_flags & RTF_GATEWAY) ||
              (rtm->rtm_flags & RTF_MULTICAST))
             continue;

          memset (&table->table[table->dwNumEntries], 0,
                  sizeof (MIB_IPFORWARDROW));
          table->table[table->dwNumEntries].dwForwardIfIndex = rtm->rtm_index;
          table->table[table->dwNumEntries].dwForwardType =
             MIB_IPROUTE_TYPE_INDIRECT;
          table->table[table->dwNumEntries].dwForwardMetric1 =
             rtm->rtm_rmx.rmx_hopcount;
          table->table[table->dwNumEntries].dwForwardProto =
             MIB_IPPROTO_LOCAL;

          addrPtr = (char *)(rtm + 1);

          for (i = 1; i; i <<= 1)
          {
             struct sockaddr *sa;
             DWORD addr;

             if (!(i & rtm->rtm_addrs))
                continue;

             sa = (struct sockaddr *)addrPtr;
             ADVANCE (addrPtr, sa);

             /* default routes are encoded by length-zero sockaddr */
             if (sa->sa_len == 0)
                addr = 0;
             else if (sa->sa_family != AF_INET)
             {
                WARN ("Received unsupported sockaddr family 0x%x\n",
                     sa->sa_family);
                addr = 0;
             }
             else
             {
                struct sockaddr_in *sin = (struct sockaddr_in *)sa;

                addr = sin->sin_addr.s_addr;
             }

             switch (i)
             {
                case RTA_DST:
                   table->table[table->dwNumEntries].dwForwardDest = addr;
                   break;

                case RTA_GATEWAY:
                   table->table[table->dwNumEntries].dwForwardNextHop = addr;
                   break;

                case RTA_NETMASK:
                   table->table[table->dwNumEntries].dwForwardMask = addr;
                   break;

                default:
                   WARN ("Unexpected address type 0x%x\n", i);
             }
          }

          table->dwNumEntries++;
       }

       HeapFree (GetProcessHeap (), 0, buf);
       ret = NO_ERROR;
#else
      FILE *fp;

      ret = NO_ERROR;
      *ppIpForwardTable = table;
      table->dwNumEntries = 0;
      /* get from /proc/net/route, no error if can't */
      fp = fopen("/proc/net/route", "r");
      if (fp) {
        char buf[512] = { 0 }, *ptr;

        /* skip header line */
        ptr = fgets(buf, sizeof(buf), fp);
        while (ptr && table->dwNumEntries < numRoutes) {
          memset(&table->table[table->dwNumEntries], 0,
           sizeof(MIB_IPFORWARDROW));
          ptr = fgets(buf, sizeof(buf), fp);
          if (ptr) {
            DWORD index;

            while (!isspace(*ptr))
              ptr++;
            *ptr = '\0';
            ptr++;
            if (getInterfaceIndexByName(buf, &index) == NO_ERROR) {
              char *endPtr;

              table->table[table->dwNumEntries].dwForwardIfIndex = index;
              if (*ptr) {
                table->table[table->dwNumEntries].dwForwardDest =
                 strtoul(ptr, &endPtr, 16);
                ptr = endPtr;
              }
              if (ptr && *ptr) {
                table->table[table->dwNumEntries].dwForwardNextHop =
                 strtoul(ptr, &endPtr, 16);
                ptr = endPtr;
              }
              if (ptr && *ptr) {
                DWORD flags = strtoul(ptr, &endPtr, 16);

                if (!(flags & RTF_UP))
                  table->table[table->dwNumEntries].dwForwardType =
                   MIB_IPROUTE_TYPE_INVALID;
                else if (flags & RTF_GATEWAY)
                  table->table[table->dwNumEntries].dwForwardType =
                   MIB_IPROUTE_TYPE_INDIRECT;
                else
                  table->table[table->dwNumEntries].dwForwardType =
                   MIB_IPROUTE_TYPE_DIRECT;
                ptr = endPtr;
              }
              if (ptr && *ptr) {
                strtoul(ptr, &endPtr, 16); /* refcount, skip */
                ptr = endPtr;
              }
              if (ptr && *ptr) {
                strtoul(ptr, &endPtr, 16); /* use, skip */
                ptr = endPtr;
              }
              if (ptr && *ptr) {
                table->table[table->dwNumEntries].dwForwardMetric1 =
                 strtoul(ptr, &endPtr, 16);
                ptr = endPtr;
              }
              if (ptr && *ptr) {
                table->table[table->dwNumEntries].dwForwardMask =
                 strtoul(ptr, &endPtr, 16);
                ptr = endPtr;
              }
              /* FIXME: other protos might be appropriate, e.g. the default
               * route is typically set with MIB_IPPROTO_NETMGMT instead */
              table->table[table->dwNumEntries].dwForwardProto =
               MIB_IPPROTO_LOCAL;
              table->dwNumEntries++;
            }
          }
        }
        fclose(fp);
      }
      else
      {
        ERR ("unimplemented!\n");
        return ERROR_NOT_SUPPORTED;
      }
#endif
    }
    else
      ret = ERROR_OUTOFMEMORY;
  }
  return ret;
}
Ejemplo n.º 2
0
DWORD getIPStats(PMIB_IPSTATS stats)
{
#if defined(HAVE_SYS_SYSCTL_H) && defined(IPCTL_STATS)
  int mib[] = {CTL_NET, PF_INET, IPPROTO_IP, IPCTL_STATS};
#define MIB_LEN (sizeof(mib) / sizeof(mib[0]))
  int ip_ttl, ip_forwarding;
  struct ipstat ip_stat;
  size_t needed;

  if (!stats)
      return ERROR_INVALID_PARAMETER;

  needed = sizeof(ip_stat);
  if(sysctl(mib, MIB_LEN, &ip_stat, &needed, NULL, 0) == -1)
  {
      ERR ("failed to get ipstat\n");
      return ERROR_NOT_SUPPORTED;
  }

  needed = sizeof(ip_ttl);
  if (sysctlbyname ("net.inet.ip.ttl", &ip_ttl, &needed, NULL, 0) == -1)
  {
      ERR ("failed to get ip Default TTL\n");
      return ERROR_NOT_SUPPORTED;
  }

  needed = sizeof(ip_forwarding);
  if (sysctlbyname ("net.inet.ip.forwarding", &ip_forwarding, &needed, NULL, 0) == -1)
  {
      ERR ("failed to get ip forwarding\n");
      return ERROR_NOT_SUPPORTED;
  }

  stats->dwForwarding = ip_forwarding;
  stats->dwDefaultTTL = ip_ttl;
  stats->dwInDelivers = ip_stat.ips_delivered;
  stats->dwInHdrErrors = ip_stat.ips_badhlen + ip_stat.ips_badsum + ip_stat.ips_tooshort + ip_stat.ips_badlen;
  stats->dwInAddrErrors = ip_stat.ips_cantforward;
  stats->dwInReceives = ip_stat.ips_total;
  stats->dwForwDatagrams = ip_stat.ips_forward;
  stats->dwInUnknownProtos = ip_stat.ips_noproto;
  stats->dwInDiscards = ip_stat.ips_fragdropped;
  stats->dwOutDiscards = ip_stat.ips_odropped;
  stats->dwReasmOks = ip_stat.ips_reassembled;
  stats->dwFragOks = ip_stat.ips_fragmented;
  stats->dwFragFails = ip_stat.ips_cantfrag;
  stats->dwReasmTimeout = ip_stat.ips_fragtimeout;
  stats->dwOutNoRoutes = ip_stat.ips_noroute;
  stats->dwOutRequests = ip_stat.ips_localout;
  stats->dwReasmReqds = ip_stat.ips_fragments;

  return NO_ERROR;
#else
  FILE *fp;

  if (!stats)
    return ERROR_INVALID_PARAMETER;

  memset(stats, 0, sizeof(MIB_IPSTATS));
  stats->dwNumIf = stats->dwNumAddr = getNumInterfaces();
  stats->dwNumRoutes = getNumRoutes();

  /* get most of these stats from /proc/net/snmp, no error if can't */
  fp = fopen("/proc/net/snmp", "r");
  if (fp) {
    static const char hdr[] = "Ip:";
    char buf[512] = { 0 }, *ptr;

    do {
      ptr = fgets(buf, sizeof(buf), fp);
    } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
    if (ptr) {
      /* last line was a header, get another */
      ptr = fgets(buf, sizeof(buf), fp);
      if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) {
        char *endPtr;

        ptr += sizeof(hdr);
        if (ptr && *ptr) {
          stats->dwForwarding = strtoul(ptr, &endPtr, 10);
          ptr = endPtr;
        }
        if (ptr && *ptr) {
          stats->dwDefaultTTL = strtoul(ptr, &endPtr, 10);
          ptr = endPtr;
        }
        if (ptr && *ptr) {
          stats->dwInReceives = strtoul(ptr, &endPtr, 10);
          ptr = endPtr;
        }
        if (ptr && *ptr) {
          stats->dwInHdrErrors = strtoul(ptr, &endPtr, 10);
          ptr = endPtr;
        }
        if (ptr && *ptr) {
          stats->dwInAddrErrors = strtoul(ptr, &endPtr, 10);
          ptr = endPtr;
        }
        if (ptr && *ptr) {
          stats->dwForwDatagrams = strtoul(ptr, &endPtr, 10);
          ptr = endPtr;
        }
        if (ptr && *ptr) {
          stats->dwInUnknownProtos = strtoul(ptr, &endPtr, 10);
          ptr = endPtr;
        }
        if (ptr && *ptr) {
          stats->dwInDiscards = strtoul(ptr, &endPtr, 10);
          ptr = endPtr;
        }
        if (ptr && *ptr) {
          stats->dwInDelivers = strtoul(ptr, &endPtr, 10);
          ptr = endPtr;
        }
        if (ptr && *ptr) {
          stats->dwOutRequests = strtoul(ptr, &endPtr, 10);
          ptr = endPtr;
        }
        if (ptr && *ptr) {
          stats->dwOutDiscards = strtoul(ptr, &endPtr, 10);
          ptr = endPtr;
        }
        if (ptr && *ptr) {
          stats->dwOutNoRoutes = strtoul(ptr, &endPtr, 10);
          ptr = endPtr;
        }
        if (ptr && *ptr) {
          stats->dwReasmTimeout = strtoul(ptr, &endPtr, 10);
          ptr = endPtr;
        }
        if (ptr && *ptr) {
          stats->dwReasmReqds = strtoul(ptr, &endPtr, 10);
          ptr = endPtr;
        }
        if (ptr && *ptr) {
          stats->dwReasmOks = strtoul(ptr, &endPtr, 10);
          ptr = endPtr;
        }
        if (ptr && *ptr) {
          stats->dwReasmFails = strtoul(ptr, &endPtr, 10);
          ptr = endPtr;
        }
        if (ptr && *ptr) {
          stats->dwFragOks = strtoul(ptr, &endPtr, 10);
          ptr = endPtr;
        }
        if (ptr && *ptr) {
          stats->dwFragFails = strtoul(ptr, &endPtr, 10);
          ptr = endPtr;
        }
        if (ptr && *ptr) {
          stats->dwFragCreates = strtoul(ptr, &endPtr, 10);
          ptr = endPtr;
        }
        /* hmm, no routingDiscards */
      }
    }
    fclose(fp);
  }
  else
  {
     ERR ("unimplemented!\n");
     return ERROR_NOT_SUPPORTED;
  }

  return NO_ERROR;
#endif
}
Ejemplo n.º 3
0
RouteTable *getRouteTable(void)
{
    RouteTable *out_route_table;
    DWORD numRoutes = getNumRoutes(), routesAdded = 0;
    TDIEntityID ent;
    HANDLE tcpFile;
    NTSTATUS status = openTcpFile( &tcpFile );
    int i;

    if( !NT_SUCCESS(status) )
        return 0;

    TRACE("GETTING ROUTE TABLE\n");

    out_route_table = HeapAlloc( GetProcessHeap(), 0,
                                 sizeof(RouteTable) +
                                 (sizeof(RouteEntry) * (numRoutes - 1)) );
    if (!out_route_table) {
        closeTcpFile(tcpFile);
        return NULL;
    }

    out_route_table->numRoutes = numRoutes;

    for( i = 0; routesAdded < out_route_table->numRoutes; i++ ) {
        int j;
        IPRouteEntry *route_set;

        getNthIpEntity( tcpFile, i, &ent );

        tdiGetRoutesForIpEntity( tcpFile, &ent, &route_set, &numRoutes );
        
        if( !route_set ) {
            closeTcpFile( tcpFile );
            HeapFree( GetProcessHeap(), 0, out_route_table );
            return 0;
        }

        TRACE( "%d routes in instance %d\n", numRoutes, i );
#if 0
        HexDump( route_set,
                 sizeof( IPRouteEntry ) *
                 snmpInfo.ipsi_numroutes );
#endif

        for( j = 0; j < numRoutes; j++ ) {
            int routeNum = j + routesAdded;
            out_route_table->routes[routeNum].dest =
                route_set[j].ire_dest;
            out_route_table->routes[routeNum].mask =
                route_set[j].ire_mask;
            out_route_table->routes[routeNum].gateway =
                route_set[j].ire_gw;
            out_route_table->routes[routeNum].ifIndex =
                route_set[j].ire_index;
            out_route_table->routes[routeNum].metric =
                route_set[j].ire_metric1;
        }

        if( route_set ) tdiFreeThingSet( route_set );

        routesAdded += numRoutes;
    }

    closeTcpFile( tcpFile );

    TRACE("Return: %08x, %08x\n", status, out_route_table);

    return out_route_table;
}