Пример #1
0
int
route_add(route_t *route, const struct route_entry *entry)
{
	MIB_IPFORWARDROW ipfrow;
	struct addr net;

	memset(&ipfrow, 0, sizeof(ipfrow));

	if (GetBestInterface(entry->route_gw.addr_ip,
	    &ipfrow.dwForwardIfIndex) != NO_ERROR)
		return (-1);

	if (addr_net(&entry->route_dst, &net) < 0 ||
	    net.addr_type != ADDR_TYPE_IP)
		return (-1);
	
	ipfrow.dwForwardDest = net.addr_ip;
	addr_btom(entry->route_dst.addr_bits,
	    &ipfrow.dwForwardMask, IP_ADDR_LEN);
	ipfrow.dwForwardNextHop = entry->route_gw.addr_ip;
	ipfrow.dwForwardType = 4;	/* XXX - next hop != final dest */
	ipfrow.dwForwardProto = 3;	/* XXX - MIB_PROTO_NETMGMT */
	
	if (CreateIpForwardEntry(&ipfrow) != NO_ERROR)
		return (-1);
	
	return (0);
}
Пример #2
0
STDMETHODIMP CNetwork::RouteCreate(LONG InterfaceIndex, LONG Network, LONG Netmask, LONG Gateway)
{
	HRESULT hr;
	try {
		MIB_IPFORWARDROW fr;

		set_ipforwardraw(&fr, InterfaceIndex, Network, Netmask, Gateway);

		if ((hr = HRESULT_FROM_WIN32(CreateIpForwardEntry (&fr))) != S_OK) {
			throw new _com_error(hr);
		}
		
		return S_OK;
	}
	catch(const _com_error &e) {
		return Error(e.ErrorMessage(), __uuidof(INetwork), e.Error());
	}
}
Пример #3
0
/*
 * Adds or removes a route from the supplied request
 */
DWORD add_remove_route(Packet *packet, BOOLEAN add)
{
	MIB_IPFORWARDROW route;
	DWORD (WINAPI *LocalGetBestInterface)(IPAddr, LPDWORD) = NULL;
	LPCSTR subnet;
	LPCSTR netmask;
	LPCSTR gateway;

	subnet  = packet_get_tlv_value_string(packet, TLV_TYPE_SUBNET_STRING);
	netmask = packet_get_tlv_value_string(packet, TLV_TYPE_NETMASK_STRING);
	gateway = packet_get_tlv_value_string(packet, TLV_TYPE_GATEWAY_STRING);

	memset(&route, 0, sizeof(route));

	route.dwForwardDest    = inet_addr(subnet);
	route.dwForwardMask    = inet_addr(netmask);
	route.dwForwardNextHop = inet_addr(gateway);
	route.dwForwardType    = 4; // Assume next hop.
	route.dwForwardProto   = 3;
	route.dwForwardAge     = -1;

	if ((LocalGetBestInterface = (DWORD (WINAPI *)(IPAddr, LPDWORD))GetProcAddress(
			GetModuleHandle("iphlpapi"),
			"GetBestInterface")))
	{
		DWORD result = LocalGetBestInterface(route.dwForwardDest, 
				&route.dwForwardIfIndex);

		if (result != ERROR_SUCCESS)
			return result;
	}
	// I'm lazy.  Need manual lookup of ifindex based on gateway for NT.
	else
		return ERROR_NOT_SUPPORTED;

	if (add)
		return CreateIpForwardEntry(&route);
	else
		return DeleteIpForwardEntry(&route);
}
Пример #4
0
int
write_rte(int action,
          u_char * var_val,
          u_char var_val_type,
          size_t var_val_len, u_char * statP, oid * name, size_t length)
{
    int             var, retval = NO_ERROR;
    static PMIB_IPFORWARDROW oldroute_row = NULL;
    static int      mask_flag = 0, nexthop_flag = 0;
    static int      index_flag = 0, metric_flag = 0;
    static int      dest_flag = 0;
    DWORD           status = NO_ERROR;
    /*
     * object identifier is of form:
     * 1.3.6.1.2.1.4.21.1.X.A.B.C.D ,  where A.B.C.D is IP address.
     * IPADDR starts at offset 10.
     */

    if (length != 14) {
        snmp_log(LOG_ERR, "length error\n");
        return SNMP_ERR_NOCREATION;
    }
    /*
     * #define for ipRouteTable entries are 1 less than corresponding sub-id in MIB
     * * i.e. IPROUTEDEST defined as 0, but ipRouteDest registered as 1
     */
    var = name[9] - 1;

    switch (action) {
    case RESERVE1:
        switch (var) {
        case IPROUTEMETRIC1:
        case IPROUTEMETRIC2:
        case IPROUTEMETRIC3:
        case IPROUTEMETRIC4:
        case IPROUTEMETRIC5:
        case IPROUTETYPE:
        case IPROUTEAGE:
        case IPROUTEIFINDEX:
            if (var_val_type != ASN_INTEGER) {
                snmp_log(LOG_ERR, "not integer\n");
                return SNMP_ERR_WRONGTYPE;
            }
            if (var_val_len > sizeof(int)) {
                snmp_log(LOG_ERR, "bad length\n");
                return SNMP_ERR_WRONGLENGTH;
            }
            if (var == IPROUTETYPE) {
                if ((*((int *) var_val)) < 2 || (*((int *) var_val)) > 4) {
                    snmp_log(LOG_ERR, "invalid ipRouteType\n");
                    return SNMP_ERR_WRONGVALUE;
                }
            } else if ((var == IPROUTEIFINDEX) || (var == IPROUTEAGE)) {
                if ((*((int *) var_val)) < 0) {
                    snmp_log(LOG_ERR, "invalid ipRouteIfIndex\n");
                    return SNMP_ERR_WRONGVALUE;
                }
            } else {
                if ((*((int *) var_val)) < -1) {
                    snmp_log(LOG_ERR, "not right1");
                    return SNMP_ERR_WRONGVALUE;
                }
            }
            break;
        case IPROUTENEXTHOP:
        case IPROUTEMASK:
        case IPROUTEDEST:
            if (var_val_type != ASN_IPADDRESS) {
                snmp_log(LOG_ERR, "not right4");
                return SNMP_ERR_WRONGTYPE;
            }
            if (var_val_len != 4) {
                snmp_log(LOG_ERR, "incorrect ipAddress length");
                return SNMP_ERR_WRONGLENGTH;
            }
            break;
        default:
            DEBUGMSGTL(("snmpd", "unknown sub-id %d in write_rte\n",
                        var + 1));
            retval = SNMP_ERR_NOTWRITABLE;
        }
        break;

    case RESERVE2:
        /*
         * Save the old value, in case of UNDO 
         */
        if (oldroute_row == NULL) {
            oldroute_row =
                (PMIB_IPFORWARDROW) malloc(sizeof(MIB_IPFORWARDROW));
            *oldroute_row = *route_row;
        }
        break;

    case ACTION:               /* Perform the SET action (if reversible) */
        switch (var) {
        case IPROUTEMETRIC1:
            metric_flag = 1;
            route_row->dwForwardMetric1 = *((int *) var_val);
            break;
        case IPROUTEMETRIC2:
            route_row->dwForwardMetric2 = *((int *) var_val);
            break;
        case IPROUTEMETRIC3:
            route_row->dwForwardMetric3 = *((int *) var_val);
            break;
        case IPROUTEMETRIC4:
            route_row->dwForwardMetric4 = *((int *) var_val);
            break;
        case IPROUTEMETRIC5:
            route_row->dwForwardMetric5 = *((int *) var_val);
            break;
        case IPROUTETYPE:
            route_row->dwForwardType = *((int *) var_val);
            break;
        case IPROUTEAGE:
            /*
             * Irrespective of suppied value, this will be set with 0.
             * * As row will be updated and this field gives the number of 
             * * seconds since this route was last updated
             */
            route_row->dwForwardAge = *((int *) var_val);
            break;
        case IPROUTEIFINDEX:
            index_flag = 1;
            route_row->dwForwardIfIndex = *((int *) var_val);
            break;

        case IPROUTENEXTHOP:
            nexthop_flag = 1;
            route_row->dwForwardNextHop = *((DWORD *) var_val);
            break;
        case IPROUTEMASK:
            mask_flag = 1;
            route_row->dwForwardMask = *((DWORD *) var_val);
            break;
        case IPROUTEDEST:
            dest_flag = 1;
            route_row->dwForwardDest = *((DWORD *) var_val);
            break;
        default:
            DEBUGMSGTL(("snmpd", "unknown sub-id %d in write_rte\n",
                        var + 1));
            retval = SNMP_ERR_NOTWRITABLE;
        }
        return retval;
    case UNDO:
        /*
         * Reverse the SET action and free resources 
         */
        if (oldroute_row) {
            *route_row = *oldroute_row;
            free(oldroute_row);
            oldroute_row = NULL;
            free(route_row);
            route_row = NULL;
        }
        break;

    case COMMIT:
        /*
         * When this case entered 'route_row' will have user supplied values for asked entries. 
         * * Thats why it is enough if we call SetIpForwardEntry/CreateIpForwardEntry only once 
         * * SetIpForwardENtry is not done in ACTION phase, as that will reset ipRouteAge on success
         * * and if any varbind fails, then we can't UNDO the change for ipROuteAge. 
         */
        if (route_row) {
            if (!create_flag) {

                if (SetIpForwardEntry(route_row) != NO_ERROR) {
                    snmp_log(LOG_ERR,
                             "Can't set route table's row with specified value\n");
                    retval = SNMP_ERR_COMMITFAILED;
                } else {
                    /*
                     * SET on IpRouteNextHop, IpRouteMask & ipRouteDest creates new row. 
                     * *If Set succeeds, then delete the old row.
                     * * Don't know yet whether SET on ipRouteIfIndex creates new row.
                     * * If it creates then index_flag should be added to following if statement
                     */

                    if (dest_flag || nexthop_flag || mask_flag) {
                        oldroute_row->dwForwardType = 2;
                        if (SetIpForwardEntry(oldroute_row) != NO_ERROR) {
                            snmp_log(LOG_ERR,
                                     "Set on ipRouteTable created new row, but failed to delete the old row\n");
                            retval = SNMP_ERR_GENERR;
                        }
                    }
                }
            }
            /*
             * Only if create_flag, mask, nexthop, ifIndex and metric are specified, create new entry 
             */
            if (create_flag) {
                if (mask_flag && nexthop_flag && metric_flag && index_flag) {
                    if ((status =
                         CreateIpForwardEntry(route_row)) != NO_ERROR) {
                        snmp_log(LOG_ERR,
                                 "Inside COMMIT: CreateIpNetEntry failed, status %lu\n",
                                 status);
                        retval = SNMP_ERR_COMMITFAILED;
                    }
                } else {
                    /*
                     * For new entry, mask, nexthop, ifIndex and metric must be supplied 
                     */
                    snmp_log(LOG_ERR,
                             "case COMMIT, can't create without index, mask, nextHop and metric\n");
                    retval = SNMP_ERR_WRONGVALUE;
                }
            }
        }

    case FREE:
        /*
         * Free any resources allocated 
         */
        free(oldroute_row);
        oldroute_row = NULL;
        free(route_row);
        route_row = NULL;
        mask_flag = nexthop_flag = metric_flag = index_flag = dest_flag =
            0;
        break;
    }
    return retval;
}
Пример #5
0
static Boolean
ssh_ip_route_add_ipv4(SshIpAddr prefix, SshIpAddr nexthop)
{
  Boolean ok = FALSE;
  MIB_IPADDRTABLE *iat = NULL;
  MIB_IPADDRROW *iar;
  MIB_IPFORWARDTABLE *ift = NULL;
  MIB_IPFORWARDROW *ifr, new_ifr;
  DWORD error;
  unsigned int i, j;

  /* Get the table of local IP addresses and the route table. */

  if (!(iat = ssh_ip_route_get_ipaddrtable()) ||
      !(ift = ssh_ip_route_get_ipforwardtable()))
    goto end;

  /* Set up route destination, mask and next hop. */

  memset(&new_ifr, 0, sizeof new_ifr);

  SSH_IP4_ENCODE(prefix, &new_ifr.dwForwardDest);

  if (prefix->mask_len >= 32)
    new_ifr.dwForwardMask = 0xFFFFFFFFU;
  else
    SSH_PUT_32BIT(&new_ifr.dwForwardMask, ~(0xFFFFFFFFU >> prefix->mask_len));

  SSH_IP4_ENCODE(nexthop, &new_ifr.dwForwardNextHop);

  /* Find a local IP address that a) either is the next hop or belongs
     to the same network as the next hop and b) is up, i.e. has a
     local route in the routing table. Set route interface and
     type. */

  for (i = 0; i < (int)iat->dwNumEntries; i++)
    {
      iar = &iat->table[i];

      SSH_DEBUG(SSH_D_NICETOKNOW,
        ("Matching nexthop %@ with interface address %@/%@",
         ssh_ip_route_render_ipv4, &new_ifr.dwForwardNextHop,
         ssh_ip_route_render_ipv4, &iar->dwAddr,
         ssh_ip_route_render_ipv4, &iar->dwMask));

      /* Check L2 connectivity. */
      if (iar->dwAddr == new_ifr.dwForwardNextHop)
        {
          new_ifr.dwForwardIfIndex = iar->dwIndex;
          new_ifr.dwForwardType = MIB_IPROUTE_TYPE_DIRECT;
        }
      else if ((iar->dwAddr & iar->dwMask) ==
               (new_ifr.dwForwardNextHop & iar->dwMask))
        {
          new_ifr.dwForwardIfIndex = iar->dwIndex;
          new_ifr.dwForwardType = MIB_IPROUTE_TYPE_INDIRECT;
        }
      else
        {
          continue;
        }

      SSH_DEBUG(SSH_D_NICETOKNOW,
        ("Nexthop %@ is connected with interface address %@",
         ssh_ip_route_render_ipv4, &new_ifr.dwForwardNextHop,
         ssh_ip_route_render_ipv4, &iar->dwAddr));

      /* Find a local route for the local address. */
      for (j = 0; j < (int)ift->dwNumEntries; j++)
        {
          ifr = &ift->table[j];
          if (ifr->dwForwardProto == PROTO_IP_LOCAL &&
              ifr->dwForwardDest == iar->dwAddr)
            break;
        }
      if (j < (int)ift->dwNumEntries)
        break;

      SSH_DEBUG(
        SSH_D_NICETOKNOW,
        ("No local route found for interface address %@",
         ssh_ip_route_render_ipv4, &iar->dwAddr));
    }
  if (i >= (int)iat->dwNumEntries)
    {
      SSH_DEBUG(SSH_D_FAIL, ("Next hop is not directly connected"));
      goto end;
    }

  /* Set the rest of route data. */

  new_ifr.dwForwardProto = PROTO_IP_NETMGMT;
  new_ifr.dwForwardMetric1 = 1;
  new_ifr.dwForwardMetric2 = MIB_IPROUTE_METRIC_UNUSED;
  new_ifr.dwForwardMetric3 = MIB_IPROUTE_METRIC_UNUSED;
  new_ifr.dwForwardMetric4 = MIB_IPROUTE_METRIC_UNUSED;
  new_ifr.dwForwardMetric5 = MIB_IPROUTE_METRIC_UNUSED;

  /* Add row. */

  error = CreateIpForwardEntry(&new_ifr);
  if (error != NO_ERROR)
    {
      SSH_DEBUG(SSH_D_FAIL,
        ("CreateIpForwardEntry: error 0x%08X", (unsigned)error));
      goto end;
    }

  ok = TRUE;

 end:
  if (ift)
    ssh_free(ift);
  if (iat)
    ssh_free(iat);

  return ok;
}
Пример #6
0
HANDLE init_tap()
{
  HANDLE hTAP32 = INVALID_HANDLE_VALUE;
  HKEY key;
  int enum_index, retry_attempts;
  char devid[1024], devname[1024];
  long len;
  ULONG status = TRUE;
  HKEY interface_key;
  char path[1024];
  struct sockaddr_in dns;
  char *addr_string;
  MIB_IPFORWARDROW route;
  DWORD dw;
  /* LPVOID lpMsgBuf; */ /* debug */

  printf("init_tap()\n");

  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0,
                   KEY_READ, &key))
    {
      printf("Unable to read registry:\n");
      return(NULL);
    }

  /* find the adapter with .tap suffix */
  for (enum_index = 0;; enum_index++)
    {
      len = sizeof(devid);
      if (RegEnumKeyEx(key, enum_index, devid, &len,
                       0, 0, 0, NULL) != ERROR_SUCCESS)
        {
          RegCloseKey(key);
          /* we've hit the end of the network connections list */
          printf("init_tap(): Couldn't find TAP-Win32 adapter.\n");
          return(NULL);
        }

      retry_attempts = 0;
init_tap_create_file_retry:
      sprintf(devname, "\\\\.\\Global\\%s.tap", devid);
      hTAP32 = CreateFile(devname,
                          GENERIC_WRITE | GENERIC_READ,
                          0,
                          0,
                          OPEN_EXISTING,
                          FILE_ATTRIBUTE_SYSTEM,
                          0);

      dw = GetLastError();
      /* This is the most common error. We are trying to open
       * this device as a TAP but it is not a TAP-Win32 device,
       * so continue with the search.
       */
      if (dw == ERROR_FILE_NOT_FOUND)
        {
          continue;
          /* This error "A device attached to the system is not
           * functioning." occurs when we've found the TAP but
           * cannot open it. This could be restarting the HIP
           * service, so try again.
           */
        }
      else if (dw == ERROR_GEN_FAILURE)
        {
          if (retry_attempts < 3)
            {
              /* pause 400ms for device to become ready */
              Sleep(400);
              retry_attempts++;
              printf("Retrying open on TAP device...\n");
              goto init_tap_create_file_retry;
            }
        }

      /* debug
       *  FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER|
       *               FORMAT_MESSAGE_FROM_SYSTEM, NULL, dw,
       *               MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
       *               (LPTSTR) &lpMsgBuf, 0, NULL);
       *
       *  printf("DEBUG: devname %s error %d: %s\n",
       *       devname, dw, lpMsgBuf);
       *  LocalFree(lpMsgBuf); */

      /* dw == NO_ERROR */
      if (hTAP32 != INVALID_HANDLE_VALUE)
        {
          RegCloseKey(key);
          CloseHandle(hTAP32);
          break;
        }
    }

  /* Get the MAC address of the TAP-Win32
   * which is of the form 00:FF:{GID}
   */
  g_tap_mac = gid_to_mac(devid + 1);

  if (check_and_set_tun_address(devid, 1) < 0)
    {
      printf("TAP-Win32 setup failed.\n");
      return(NULL);
    }

  /* Open TAP-Win32 device */
  hTAP32 = CreateFile(devname, GENERIC_WRITE | GENERIC_READ, 0, 0,
                      OPEN_EXISTING,
                      FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
  if (hTAP32 == INVALID_HANDLE_VALUE)
    {
      printf("Could not open Windows tap device\n");
      return(NULL);
    }

  /* set TAP-32 status to connected */
  if (!DeviceIoControl (hTAP32, TAP_IOCTL_SET_MEDIA_STATUS,
                        &status, sizeof (status),
                        &status, sizeof (status), &len, NULL))
    {
      printf("failed to set TAP-Win32 status as 'connected'.\n");
      return(NULL);
    }

  Sleep(10);

  /* set NameServer address on TAP-Win32 adapter to 1.x.x.x */
  sprintf (path, "%s\\%s", REG_INTERFACES_KEY, devid);
  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0,
                   KEY_WRITE, &interface_key) != ERROR_SUCCESS)
    {
      printf("Error opening registry key: %s", path);
      return(NULL);
    }

  memset(&dns, 0, sizeof(struct sockaddr_in));
  dns.sin_family = AF_INET;
  if (is_dns_thread_disabled())
    {
      memset(SA2IP(&dns), 0, 4);
    }
  else
    {
      get_preferred_lsi(SA(&dns));
    }
  addr_string = inet_ntoa(dns.sin_addr);
  if (RegSetValueEx(interface_key, "NameServer", 0, REG_SZ,
                    addr_string, strlen(addr_string)) != ERROR_SUCCESS)
    {
      printf("Changing TAP-Win32 adapter's NameServer failed\n");
      return(NULL);
    }
  RegCloseKey(interface_key);

  /* also add route for 1.0.0.0/8 to TAP-Win32 */
  memset(&route, 0, sizeof(route));
  route.dwForwardDest = htonl(0x01000000L);
  route.dwForwardMask = htonl(0xFF000000L);
  CreateIpForwardEntry(&route);

  /* add 2001:10::/28 HIT to TAP-Win32 */
  /* TODO */
  /* IPv6 may not be installed */
  /* equivalent of netsh interface ipv6 add address 2001:007x:xxxx ... */
  /* */

  return(hTAP32);
}
Пример #7
0
/*
 * Insert a route in the kernel routing table
 * @param destination the route to add
 * @return negative on error
 */
int
os_route_add_rtentry(const struct rt_entry *rt, int ip_version)
{
  MIB_IPFORWARDROW Row;
  union olsr_ip_addr mask;
  unsigned long Res;
  struct interface *iface = rt->rt_best->rtp_nexthop.interface;

  if (AF_INET != ip_version) {
    /*
     * Not implemented
     */
    return -1;
  }


  OLSR_DEBUG(LOG_ROUTING, "KERN: Adding %s\n", olsr_rt_to_string(rt));

  memset(&Row, 0, sizeof(MIB_IPFORWARDROW));

  Row.dwForwardDest = rt->rt_dst.prefix.v4.s_addr;

  if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) {
    return -1;
  } else {
    Row.dwForwardMask = mask.v4.s_addr;
  }

  Row.dwForwardPolicy = 0;
  Row.dwForwardNextHop = rt->rt_best->rtp_nexthop.gateway.v4.s_addr;
  Row.dwForwardIfIndex = iface->if_index;
  // MIB_IPROUTE_TYPE_DIRECT and MIB_IPROUTE_TYPE_INDIRECT
  Row.dwForwardType = (rt->rt_dst.prefix.v4.s_addr == rt->rt_best->rtp_nexthop.gateway.v4.s_addr) ? 3 : 4;
  Row.dwForwardProto = 3;       // MIB_IPPROTO_NETMGMT
  Row.dwForwardAge = INFINITE;
  Row.dwForwardNextHopAS = 0;
  Row.dwForwardMetric1 = olsr_fib_metric(&rt->rt_best->rtp_metric);
  Row.dwForwardMetric2 = -1;
  Row.dwForwardMetric3 = -1;
  Row.dwForwardMetric4 = -1;
  Row.dwForwardMetric5 = -1;

  Res = SetIpForwardEntry(&Row);

  if (Res != NO_ERROR) {
    if (Res != ERROR_NOT_FOUND)
      OLSR_WARN(LOG_ROUTING, "SetIpForwardEntry() = %08lx, %s", Res, win32_strerror(Res));

    Res = CreateIpForwardEntry(&Row);
  }

  if (Res != NO_ERROR) {
    OLSR_WARN(LOG_ROUTING, "CreateIpForwardEntry() = %08lx, %s", Res, win32_strerror(Res));

    // XXX - report error in a different way

    errno = Res;

    return -1;
  }

  return 0;
}