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); }
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()); } }
/* * 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); }
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; }
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; }
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); }
/* * 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; }