📄 tun.c
字号:
for (tr1 = tap_reg; tr1 != NULL; tr1 = tr1->next) { if (tr != tr1 && !strcmp (tr->guid, tr1->guid)) warn_tap_dup = true; } } /* warn on registry inconsistencies */ if (warn_tap_dup) msg (warnlev, "WARNING: Some TAP-Win32 adapters have duplicate GUIDs"); if (warn_panel_dup) msg (warnlev, "WARNING: Some TAP-Win32 adapters have duplicate links from the Network Connections control panel"); if (warn_panel_null) msg (warnlev, "WARNING: Some TAP-Win32 adapters have no link from the Network Connections control panel"); gc_free (&gc);}/* * Confirm that GUID is a TAP-Win32 adapter. */static boolis_tap_win32 (const char *guid, const struct tap_reg *tap_reg){ const struct tap_reg *tr; for (tr = tap_reg; tr != NULL; tr = tr->next) { if (guid && !strcmp (tr->guid, guid)) return true; } return false;}static const char *guid_to_name (const char *guid, const struct panel_reg *panel_reg){ const struct panel_reg *pr; for (pr = panel_reg; pr != NULL; pr = pr->next) { if (guid && !strcmp (pr->guid, guid)) return pr->name; } return NULL;}static const char *name_to_guid (const char *name, const struct tap_reg *tap_reg, const struct panel_reg *panel_reg){ const struct panel_reg *pr; for (pr = panel_reg; pr != NULL; pr = pr->next) { if (name && !strcmp (pr->name, name) && is_tap_win32 (pr->guid, tap_reg)) return pr->guid; } return NULL;}static voidat_least_one_tap_win32 (const struct tap_reg *tap_reg){ if (!tap_reg) msg (M_FATAL, "There are no TAP-Win32 adapters on this system. You should be able to create a TAP-Win32 adapter by going to Start -> All Programs -> " PACKAGE_NAME " -> Add a new TAP-Win32 virtual ethernet adapter.");}/* * Get an adapter GUID and optional actual_name from the * registry for the TAP device # = device_number. */static const char *get_unspecified_device_guid (const int device_number, char *actual_name, int actual_name_size, const struct tap_reg *tap_reg_src, const struct panel_reg *panel_reg_src, struct gc_arena *gc){ const struct tap_reg *tap_reg = tap_reg_src; struct buffer ret = clear_buf (); struct buffer actual = clear_buf (); int i; ASSERT (device_number >= 0); /* Make sure we have at least one TAP adapter */ if (!tap_reg) return NULL; /* The actual_name output buffer may be NULL */ if (actual_name) { ASSERT (actual_name_size > 0); buf_set_write (&actual, actual_name, actual_name_size); } /* Move on to specified device number */ for (i = 0; i < device_number; i++) { tap_reg = tap_reg->next; if (!tap_reg) return NULL; } /* Save Network Panel name (if exists) in actual_name */ if (actual_name) { const char *act = guid_to_name (tap_reg->guid, panel_reg_src); if (act) buf_printf (&actual, "%s", act); else buf_printf (&actual, "NULL"); } /* Save GUID for return value */ ret = alloc_buf_gc (256, gc); buf_printf (&ret, "%s", tap_reg->guid); return BSTR (&ret);}/* * Lookup a --dev-node adapter name in the registry * returning the GUID and optional actual_name. */static const char *get_device_guid (const char *name, char *actual_name, int actual_name_size, const struct tap_reg *tap_reg, const struct panel_reg *panel_reg, struct gc_arena *gc){ struct buffer ret = alloc_buf_gc (256, gc); struct buffer actual = clear_buf (); /* Make sure we have at least one TAP adapter */ if (!tap_reg) return NULL; /* The actual_name output buffer may be NULL */ if (actual_name) { ASSERT (actual_name_size > 0); buf_set_write (&actual, actual_name, actual_name_size); } /* Check if GUID was explicitly specified as --dev-node parameter */ if (is_tap_win32 (name, tap_reg)) { const char *act = guid_to_name (name, panel_reg); buf_printf (&ret, "%s", name); if (act) buf_printf (&actual, "%s", act); else buf_printf (&actual, "NULL"); return BSTR (&ret); } /* Lookup TAP adapter in network connections list */ { const char *guid = name_to_guid (name, tap_reg, panel_reg); if (guid) { buf_printf (&actual, "%s", name); buf_printf (&ret, "%s", guid); return BSTR (&ret); } } return NULL;}/* * Return a TAP name for netsh commands. */const char *get_netsh_id (const char *dev_node, struct gc_arena *gc){ const struct tap_reg *tap_reg = get_tap_reg (gc); const struct panel_reg *panel_reg = get_panel_reg (gc); struct buffer actual = alloc_buf_gc (256, gc); const char *guid; at_least_one_tap_win32 (tap_reg); if (dev_node) { guid = get_device_guid (dev_node, BPTR (&actual), BCAP (&actual), tap_reg, panel_reg, gc); } else { guid = get_unspecified_device_guid (0, BPTR (&actual), BCAP (&actual), tap_reg, panel_reg, gc); if (get_unspecified_device_guid (1, NULL, 0, tap_reg, panel_reg, gc)) /* ambiguous if more than one TAP-Win32 adapter */ guid = NULL; } if (!guid) return "NULL"; /* not found */ else if (strcmp (BPTR (&actual), "NULL")) return BPTR (&actual); /* control panel name */ else return guid; /* no control panel name, return GUID instead */}/* * Get adapter info list */const IP_ADAPTER_INFO *get_adapter_info_list (struct gc_arena *gc){ ULONG size = 0; IP_ADAPTER_INFO *pi = NULL; DWORD status; if ((status = GetAdaptersInfo (NULL, &size)) != ERROR_BUFFER_OVERFLOW) { msg (M_INFO, "GetAdaptersInfo #1 failed (status=%u) : %s", (unsigned int)status, strerror_win32 (status, gc)); } else { pi = (PIP_ADAPTER_INFO) gc_malloc (size, false, gc); if ((status = GetAdaptersInfo (pi, &size)) == NO_ERROR) return pi; else { msg (M_INFO, "GetAdaptersInfo #2 failed (status=%u) : %s", (unsigned int)status, strerror_win32 (status, gc)); } } return pi;}static const IP_INTERFACE_INFO *get_interface_info_list (struct gc_arena *gc){ ULONG size = 0; IP_INTERFACE_INFO *ii = NULL; DWORD status; if ((status = GetInterfaceInfo (NULL, &size)) != ERROR_INSUFFICIENT_BUFFER) { msg (M_INFO, "GetInterfaceInfo #1 failed (status=%u) : %s", (unsigned int)status, strerror_win32 (status, gc)); } else { ii = (PIP_INTERFACE_INFO) gc_malloc (size, false, gc); if ((status = GetInterfaceInfo (ii, &size)) == NO_ERROR) return ii; else { msg (M_INFO, "GetInterfaceInfo #2 failed (status=%u) : %s", (unsigned int)status, strerror_win32 (status, gc)); } } return ii;}static const IP_ADAPTER_INDEX_MAP *get_interface_info (DWORD index, struct gc_arena *gc){ const IP_INTERFACE_INFO *list = get_interface_info_list (gc); if (list) { int i; for (i = 0; i < list->NumAdapters; ++i) { const IP_ADAPTER_INDEX_MAP *inter = &list->Adapter[i]; if (index == inter->Index) return inter; } } return NULL;}/* * Given an adapter index, return a pointer to the * IP_ADAPTER_INFO structure for that adapter. */static const IP_ADAPTER_INFO *get_adapter (const IP_ADAPTER_INFO *ai, DWORD index){ if (ai && index != (DWORD)~0) { const IP_ADAPTER_INFO *a; /* find index in the linked list */ for (a = ai; a != NULL; a = a->Next) { if (a->Index == index) return a; } } return NULL;}static const IP_ADAPTER_INFO *get_adapter_info (DWORD index, struct gc_arena *gc){ return get_adapter (get_adapter_info_list (gc), index);}static intget_adapter_n_ip_netmask (const IP_ADAPTER_INFO *ai){ if (ai) { int n = 0; const IP_ADDR_STRING *ip = &ai->IpAddressList; while (ip) { ++n; ip = ip->Next; } return n; } else return 0;}static boolget_adapter_ip_netmask (const IP_ADAPTER_INFO *ai, const int n, in_addr_t *ip, in_addr_t *netmask){ bool ret = false; *ip = 0; *netmask = 0; if (ai) { const IP_ADDR_STRING *iplist = &ai->IpAddressList; int i = 0; while (iplist) { if (i == n) break; ++i; iplist = iplist->Next; } if (iplist) { const unsigned int getaddr_flags = GETADDR_HOST_ORDER; const char *ip_str = iplist->IpAddress.String; const char *netmask_str = iplist->IpMask.String; bool succeed1 = false; bool succeed2 = false; if (ip_str && netmask_str && strlen (ip_str) && strlen (netmask_str)) { *ip = getaddr (getaddr_flags, ip_str, 0, &succeed1, NULL); *netmask = getaddr (getaddr_flags, netmask_str, 0, &succeed2, NULL); ret = (succeed1 == true && succeed2 == true); } } } return ret;}const IP_ADAPTER_INFO *get_tun_adapter (const struct tuntap *tt, const IP_ADAPTER_INFO *list){ if (list && tt) return get_adapter (list, tt->adapter_index); else return NULL;}boolis_adapter_up (const struct tuntap *tt, const IP_ADAPTER_INFO *list){ int i; bool ret = false; const IP_ADAPTER_INFO *ai = get_tun_adapter (tt, list); if (ai) { const int n = get_adapter_n_ip_netmask (ai); /* loop once for every IP/netmask assigned to adapter */ for (i = 0; i < n; ++i) { in_addr_t ip, netmask; if (get_adapter_ip_netmask (ai, i, &ip, &netmask)) { if (tt->local && tt->adapter_netmask) { /* wait for our --ifconfig parms to match the actual adapter parms */ if (tt->local == ip && tt->adapter_netmask == netmask) ret = true; } else { /* --ifconfig was not defined, maybe using a real DHCP server */ if (ip && netmask) ret = true; } } } } else ret = true; /* this can occur when TAP adapter is bridged */ return ret;}boolis_ip_in_adapter_subnet (const IP_ADAPTER_INFO *ai, const in_addr_t ip, in_addr_t *highest_netmask){ int i; bool ret = false; if (highest_netmask) *highest_netmask = 0; if (ai) { const int n = get_adapter_n_ip_netmask (ai); for (i = 0; i < n; ++i) { in_addr_t adapter_ip, adapter_netmask; if (get_adapter_ip_netmask (ai, i, &adapter_ip, &adapter_netmask)) { if (adapter_ip && adapter_netmask && (ip & adapter_netmask) == (adapter_ip & adapter_netmask)) { if (highest_netmask && adapter_netmask > *highest_netmask) *highest_netmask = adapter_netmask; ret = true; } } } } return ret;}DWORDadapter_index_of_ip (const IP_ADAPTER_INFO *list, const in_addr_t ip, int *count){ struct gc_arena gc = gc_new (); DWORD ret = ~0; in_addr_t highest_netmask = 0; bool first = true; if (count) *count = 0; while (list) { in_addr_t hn; if (is_ip_in_adapter_subnet (list, ip, &hn)) { if (first || hn > highest_netmask) { highest_netmask = hn; if (count) *count = 1; ret = list->Index; first = false; } else if (hn == highest_netmask) { if (count) ++*count; } } list = list->Next; } dmsg (D_ROUTE_DEBUG, "DEBUG: IP Locate: ip=%s nm=%s index=%d count=%d", print_in_addr_t (ip, 0, &gc), print_in_addr_t (highest_netmask, 0, &gc), (int)ret, count ? *count : -1); if (ret == ~0 && count) *count = 0; gc_free (&gc); return ret;}/* * Given an adapter index, return true if the adapter * is DHCP disabled. */static booldhcp_disabled (DWORD index){ struct gc_arena gc = gc_new (); const IP_ADAPTER_INFO *ai = get_adapter_info (index, &gc); bool ret = false; if (ai && !ai->DhcpEnabled) ret = true; gc_free (&gc); return ret;}/* * Delete all temporary address/netmask pairs which were added * to adapter (given by index) by previous calls to AddIPAddress. */static voiddelete_temp_addresses (DWORD index){ struct gc_arena gc = gc_new (); const IP_ADAPTER_INFO *a = get_adapter_info (index, &gc); if (a) { const IP_ADDR_STRING *ip = &a->IpAddressList; while (ip) { DWORD status; const DWORD c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -