|
|
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
//
// Copyright (c) 1998-2000 Microsoft Corporation
//
// This file is part of the Microsoft Research IPv6 Network Protocol Stack.
// You should have received a copy of the Microsoft End-User License Agreement
// for this software along with this release; see the file "license.txt".
// If not, please see http://www.research.microsoft.com/msripv6/license.htm,
// or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
//
// Abstract:
//
// Dump current IPv6 state information.
//
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <ws2ip6.h>
#include <wspiapi.h>
#include <ntddip6.h>
#include <ip6.h>
#include <stdio.h>
#include <stdlib.h>
//
// Localization library and MessageIds.
//
#include <nls.h>
#include <winnlsp.h>
#include "localmsg.h"
HANDLE Handle;
int Verbose = FALSE;
int AdminAccess = TRUE;
int Persistent = FALSE;
void QueryInterface(int argc, char *argv[]); void CreateInterface(int argc, char *argv[]); void UpdateInterface(int argc, char *argv[]); void DeleteInterface(int argc, char *argv[]); void UpdateRouterLinkAddress(int argc, char *argv[]); void QueryNeighborCache(int argc, char *argv[]); void QueryRouteCache(int argc, char *argv[]); void QueryRouteTable(int argc, char *argv[]); void UpdateRouteTable(int argc, char *argv[]); void UpdateAddress(int argc, char *argv[]); void QueryBindingCache(int argc, char *argv[]); void FlushNeighborCache(int argc, char *argv[]); void FlushRouteCache(int argc, char *argv[]); void QuerySitePrefixTable(int argc, char *argv[]); void UpdateSitePrefixTable(int argc, char *argv[]); void QueryGlobalParameters(int argc, char *argv[]); void UpdateGlobalParameters(int argc, char *argv[]); void QueryPrefixPolicy(int argc, char *argv[]); void UpdatePrefixPolicy(int argc, char *argv[]); void DeletePrefixPolicy(int argc, char *argv[]); void ResetManualConfig(int argc, char *argv[]); void RenewInterface(int argc, char *argv[]); void AddOrRemoveIpv6(BOOL fAddIpv6); BOOL IsIpv6Installed();
void usage(void) { NlsPutMsg(STDOUT, IPV6_MESSAGE_14); // printf("usage: ipv6 [-p] [-v] if [ifindex]\n");
// printf(" ipv6 [-p] ifcr v6v4 v4src v4dst [nd] [pmld]\n");
// printf(" ipv6 [-p] ifcr 6over4 v4src\n");
// printf(" ipv6 [-p] ifc ifindex [forwards] [-forwards] [advertises] [-advertises] [mtu #bytes] [site site-identifier] [preference P]\n");
// printf(" ipv6 rlu ifindex v4dst\n");
// printf(" ipv6 [-p] ifd ifindex\n");
// printf(" ipv6 [-p] adu ifindex/address [life validlifetime[/preflifetime]] [anycast] [unicast]\n");
// printf(" ipv6 nc [ifindex [address]]\n");
// printf(" ipv6 ncf [ifindex [address]]\n");
// printf(" ipv6 rc [ifindex address]\n");
// printf(" ipv6 rcf [ifindex [address]]\n");
// printf(" ipv6 bc\n");
// printf(" ipv6 [-p] [-v] rt\n");
// printf(" ipv6 [-p] rtu prefix ifindex[/address] [life valid[/pref]] [preference P] [publish] [age] [spl SitePrefixLength]\n");
// printf(" ipv6 spt\n");
// printf(" ipv6 spu prefix ifindex [life L]\n");
// printf(" ipv6 [-p] gp\n");
// printf(" ipv6 [-p] gpu [parameter value] ... (try -?)\n");
// printf(" ipv6 renew [ifindex]\n");
// printf(" ipv6 [-p] ppt\n");
// printf(" ipv6 [-p] ppu prefix precedence P srclabel SL [dstlabel DL]\n");
// printf(" ipv6 [-p] ppd prefix\n");
// printf(" ipv6 [-p] reset\n");
// printf(" ipv6 install\n");
// printf(" ipv6 uninstall\n");
// printf("Some subcommands require local Administrator privileges.\n");
exit(1); }
void ausage(void) { NlsPutMsg(STDOUT, IPV6_MESSAGE_15); // printf("You do not have local Administrator privileges.\n");
exit(1); }
int __cdecl main(int argc, char **argv) { WSADATA wsaData; int i;
//
// This will ensure the correct language message is displayed when
// NlsPutMsg is called.
//
SetThreadUILanguage(0);
//
// Parse any global options.
//
for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-v")) Verbose = TRUE; else if (!strcmp(argv[i], "-p")) Persistent = TRUE; else break; }
argc -= i; argv += i;
if (argc < 1) { usage(); }
if (!strcmp(argv[0], "install")) { if (argc != 1) usage(); AddOrRemoveIpv6(TRUE); } else if (!strcmp(argv[0], "uninstall")) { if (argc != 1) usage(); AddOrRemoveIpv6(FALSE); } else {
//
// We initialize Winsock only to have access
// to WSAStringToAddress and WSAAddressToString.
//
if (WSAStartup(MAKEWORD(2, 0), &wsaData)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_18); // printf("WSAStartup failed\n");
exit(1); }
//
// First request write access.
// This will fail if the process does not have appropriate privs.
//
Handle = CreateFileW(WIN_IPV6_DEVICE_NAME, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, // security attributes
OPEN_EXISTING, 0, // flags & attributes
NULL); // template file
if (Handle == INVALID_HANDLE_VALUE) { //
// We will not have Administrator access to the stack.
//
AdminAccess = FALSE;
Handle = CreateFileW(WIN_IPV6_DEVICE_NAME, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, // security attributes
OPEN_EXISTING, 0, // flags & attributes
NULL); // template file
if (Handle == INVALID_HANDLE_VALUE) { if (IsIpv6Installed()) { NlsPutMsg(STDOUT, IPV6_MESSAGE_IPV6_NOT_RUNNING); // printf("Could not access IPv6 protocol stack - the stack is not running.\n");
// printf("To start it, please use 'net start tcpip6'.\n");
} else { NlsPutMsg(STDOUT, IPV6_MESSAGE_IPV6_NOT_INSTALLED); // printf("Could not access IPv6 protocol stack - the stack is not installed.\n");
// printf("To install, please use 'ipv6 install'.\n");
}
exit(1); } }
if (!strcmp(argv[0], "if")) { QueryInterface(argc - 1, argv + 1); } else if (!strcmp(argv[0], "ifcr")) { if (! AdminAccess) ausage(); CreateInterface(argc - 1, argv + 1); } else if (!strcmp(argv[0], "ifc")) { if (! AdminAccess) ausage(); UpdateInterface(argc - 1, argv + 1); } else if (!strcmp(argv[0], "ifd")) { if (! AdminAccess) ausage(); DeleteInterface(argc - 1, argv + 1); } else if (!strcmp(argv[0], "renew")) { if (! AdminAccess) ausage(); RenewInterface(argc - 1, argv + 1); } else if (!strcmp(argv[0], "adu")) { if (! AdminAccess) ausage(); UpdateAddress(argc - 1, argv + 1); } else if (!strcmp(argv[0], "nc")) { QueryNeighborCache(argc - 1, argv + 1); } else if (!strcmp(argv[0], "ncf")) { if (! AdminAccess) ausage(); FlushNeighborCache(argc - 1, argv + 1); } else if (!strcmp(argv[0], "rc")) { QueryRouteCache(argc - 1, argv + 1); } else if (!strcmp(argv[0], "rcf")) { if (! AdminAccess) ausage(); FlushRouteCache(argc - 1, argv + 1); } else if (!strcmp(argv[0], "rlu")) { if (! AdminAccess) ausage(); UpdateRouterLinkAddress(argc - 1, argv + 1); } else if (!strcmp(argv[0], "rt")) { QueryRouteTable(argc - 1, argv + 1); } else if (!strcmp(argv[0], "rtu")) { if (! AdminAccess) ausage(); UpdateRouteTable(argc - 1, argv + 1); } else if (!strcmp(argv[0], "spt")) { QuerySitePrefixTable(argc - 1, argv + 1); } else if (!strcmp(argv[0], "spu")) { if (! AdminAccess) ausage(); UpdateSitePrefixTable(argc - 1, argv + 1); } else if (!strcmp(argv[0], "bc")) { QueryBindingCache(argc - 1, argv + 1); } else if (!strcmp(argv[0], "gp")) { QueryGlobalParameters(argc - 1, argv + 1); } else if (!strcmp(argv[0], "gpu")) { if (! AdminAccess) ausage(); UpdateGlobalParameters(argc - 1, argv + 1); } else if (!strcmp(argv[0], "ppt")) { QueryPrefixPolicy(argc - 1, argv + 1); } else if (!strcmp(argv[0], "ppu")) { if (! AdminAccess) ausage(); UpdatePrefixPolicy(argc - 1, argv + 1); } else if (!strcmp(argv[0], "ppd")) { if (! AdminAccess) ausage(); DeletePrefixPolicy(argc - 1, argv + 1); } else if (!strcmp(argv[0], "reset")) { if (! AdminAccess) ausage(); ResetManualConfig(argc - 1, argv + 1); } else { usage(); } }
return 0; }
int GetNumber(char *astr, u_int *number) { u_int num;
num = 0; while (*astr != '\0') { if (('0' <= *astr) && (*astr <= '9')) num = 10 * num + (*astr - '0'); else return FALSE; astr++; }
*number = num; return TRUE; }
int GetGuid(char *astr, GUID *Guid) { WCHAR GuidStr[40+1]; UNICODE_STRING UGuidStr;
MultiByteToWideChar(CP_ACP, 0, astr, -1, GuidStr, 40);
RtlInitUnicodeString(&UGuidStr, GuidStr); return RtlGUIDFromString(&UGuidStr, Guid) == STATUS_SUCCESS; }
char * FormatGuid(const GUID *pGuid) { static char buffer[40];
sprintf(buffer, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", pGuid->Data1, pGuid->Data2, pGuid->Data3, pGuid->Data4[0], pGuid->Data4[1], pGuid->Data4[2], pGuid->Data4[3], pGuid->Data4[4], pGuid->Data4[5], pGuid->Data4[6], pGuid->Data4[7]); return buffer; }
int GetInterface(char *astr, IPV6_QUERY_INTERFACE *Query) { if (*astr == '{') { //
// Read a guid.
//
Query->Index = 0; return GetGuid(astr, &Query->Guid);
} else { //
// Read a non-zero interface index.
//
return GetNumber(astr, &Query->Index) && (Query->Index != 0); } }
#define SECONDS 1
#define MINUTES (60 * SECONDS)
#define HOURS (60 * MINUTES)
#define DAYS (24 * HOURS)
int GetLifetime(char *astr, u_int *number) { char *pUnit; u_int units; u_int value;
*number = 0;
while ((pUnit = strpbrk(astr, "sSmMhHdD")) != NULL) {
switch (*pUnit) { case 's': case 'S': units = SECONDS; break; case 'm': case 'M': units = MINUTES; break; case 'h': case 'H': units = HOURS; break; case 'd': case 'D': units = DAYS; break; }
*pUnit = '\0'; if (! GetNumber(astr, &value)) return FALSE;
*number += units * value;
astr = pUnit + 1; if (*astr == '\0') return TRUE; }
if (! GetNumber(astr, &value)) return FALSE;
*number += value; return TRUE; }
int GetLifetimes(char *astr, u_int *valid, u_int *preferred) { char *slash; u_int length;
slash = strchr(astr, '/'); if (slash == NULL) { if (strcmp(astr, "infinite")) { if (! GetLifetime(astr, valid)) return FALSE;
if (preferred != NULL) *preferred = *valid; }
return TRUE; }
if (preferred == NULL) return FALSE;
*slash = '\0';
if (strcmp(astr, "infinite")) if (! GetLifetime(astr, valid)) return FALSE;
if (strcmp(slash+1, "infinite")) if (! GetLifetime(slash+1, preferred)) return FALSE;
return TRUE; }
char * FormatLifetime(u_int Life) { static char buffer[64]; char *s = buffer; u_int Days, Hours, Minutes;
if (Life == INFINITE_LIFETIME) return "infinite";
if (Verbose) goto FormatSeconds;
if (Life < 2 * MINUTES) goto FormatSeconds;
if (Life < 2 * HOURS) goto FormatMinutes;
if (Life < 2 * DAYS) goto FormatHours;
Days = Life / DAYS; if (Days != 0) s += sprintf(s, "%ud", Days); Life -= Days * DAYS;
FormatHours: Hours = Life / HOURS; if (Hours != 0) s += sprintf(s, "%uh", Hours); Life -= Hours * HOURS;
FormatMinutes: Minutes = Life / MINUTES; if (Minutes != 0) s += sprintf(s, "%um", Minutes); Life -= Minutes * MINUTES;
if (Life == 0) return buffer;
FormatSeconds: (void) sprintf(s, "%us", Life); return buffer; }
char * FormatLifetimes(u_int Valid, u_int Preferred) { static char buffer[128]; char *s = buffer;
s += sprintf(s, "%s", FormatLifetime(Valid)); if (Preferred != Valid) s += sprintf(s, "/%s", FormatLifetime(Preferred));
return buffer; }
int GetAddress(char *astr, IPv6Addr *address) { struct sockaddr_in6 sin6; int addrlen = sizeof sin6;
sin6.sin6_family = AF_INET6; // shouldn't be required but is
if ((WSAStringToAddress(astr, AF_INET6, NULL, (struct sockaddr *)&sin6, &addrlen) == SOCKET_ERROR) || (sin6.sin6_port != 0) || (sin6.sin6_scope_id != 0)) return FALSE;
// The user gave us a numeric IPv6 address.
memcpy(address, &sin6.sin6_addr, sizeof *address); return TRUE; }
int GetPrefix(char *astr, IPv6Addr *prefix, u_int *prefixlen) { struct sockaddr_in6 sin6; int addrlen = sizeof sin6; char *slash; u_int length;
slash = strchr(astr, '/'); if (slash == NULL) return FALSE; *slash = '\0';
if (! GetNumber(slash+1, &length)) return FALSE; if (length > 128) return FALSE;
sin6.sin6_family = AF_INET6; // shouldn't be required but is
if ((WSAStringToAddress(astr, AF_INET6, NULL, (struct sockaddr *)&sin6, &addrlen) == SOCKET_ERROR) || (sin6.sin6_port != 0) || (sin6.sin6_scope_id != 0)) return FALSE;
// The user gave us a numeric IPv6 address.
memcpy(prefix, &sin6.sin6_addr, sizeof *prefix); *prefixlen = length; return TRUE; }
const char *PrefixConfStr[] = { "other", "manual", "well-known", "dhcp", "ra", NULL }; #define MAX_PREFIX_CONF (sizeof(PrefixConfStr) / sizeof(char *))
const char *InterfaceIdConfStr[] = { "other", "manual", "well-known", "dhcp", "LL-address-derived", "random", NULL }; #define MAX_IID_CONF (sizeof(InterfaceIdConfStr) / sizeof(char *))
int GetPrefixOrigin(char *astr, u_int *origin) { int i; for (i=0; PrefixConfStr[i]; i++) { if (!strcmp(astr, PrefixConfStr[i])) { *origin = i; return TRUE; } } return FALSE; }
int GetInterfaceIdOrigin(char *astr, u_int *origin) { int i; for (i=0; InterfaceIdConfStr[i]; i++) { if (!strcmp(astr, InterfaceIdConfStr[i])) { *origin = i; return TRUE; } } return FALSE; }
int GetNeighbor(char *astr, IPV6_QUERY_INTERFACE *IF, IPv6Addr *addr) { struct sockaddr_in6 sin6; int addrlen = sizeof sin6; char *slash; u_int length;
slash = strchr(astr, '/'); if (slash != NULL) *slash = '\0';
if (! GetInterface(astr, IF)) return FALSE;
if (slash == NULL) { *addr = in6addr_any; return TRUE; }
sin6.sin6_family = AF_INET6; // shouldn't be required but is
if ((WSAStringToAddress(slash+1, AF_INET6, NULL, (struct sockaddr *)&sin6, &addrlen) == SOCKET_ERROR) || (sin6.sin6_port != 0) || (sin6.sin6_scope_id != 0)) return FALSE;
// The user gave us a numeric IPv6 address.
*addr = sin6.sin6_addr; return TRUE; }
char * FormatIPv6Address(IPv6Addr *Address) { static char buffer[128]; DWORD buflen = sizeof buffer; struct sockaddr_in6 sin6;
memset(&sin6, 0, sizeof sin6); sin6.sin6_family = AF_INET6; sin6.sin6_addr = *Address;
if (WSAAddressToString((struct sockaddr *) &sin6, sizeof sin6, NULL, // LPWSAPROTOCOL_INFO
buffer, &buflen) == SOCKET_ERROR) strcpy(buffer, "<invalid>");
return buffer; }
char * FormatIPv4Address(struct in_addr *Address) { static char buffer[128]; DWORD buflen = sizeof buffer; struct sockaddr_in sin;
memset(&sin, 0, sizeof sin); sin.sin_family = AF_INET; sin.sin_addr = *Address;
if (WSAAddressToString((struct sockaddr *) &sin, sizeof sin, NULL, // LPWSAPROTOCOL_INFO
buffer, &buflen) == SOCKET_ERROR) strcpy(buffer, "<invalid>");
return buffer; }
char * FormatLinkLayerAddress(u_int length, u_char *addr) { static char buffer[128];
switch (length) { case 6: { int i, digit; char *s = buffer;
for (i = 0; i < 6; i++) { if (i != 0) *s++ = '-';
digit = addr[i] >> 4; if (digit < 10) *s++ = digit + '0'; else *s++ = digit - 10 + 'a';
digit = addr[i] & 0xf; if (digit < 10) *s++ = digit + '0'; else *s++ = digit - 10 + 'a'; } *s = '\0'; break; }
case 4: //
// IPv4 address (6-over-4 link)
//
strcpy(buffer, FormatIPv4Address((struct in_addr *)addr)); break;
case 0: //
// Null or loop-back address
//
buffer[0] = '\0'; break;
default: NlsPutMsg(STDOUT, IPV6_MESSAGE_21); // printf("unrecognized link-layer address format\n");
exit(1); }
return buffer; }
void ForEachAddress(IPV6_INFO_INTERFACE *IF, void (*func)(IPV6_INFO_INTERFACE *IF, IPV6_INFO_ADDRESS *)) { IPV6_QUERY_ADDRESS Query; IPV6_INFO_ADDRESS ADE; u_int BytesReturned;
Query.IF = IF->This; Query.Address = in6addr_any;
for (;;) { if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_ADDRESS, &Query, sizeof Query, &ADE, sizeof ADE, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_22, FormatIPv6Address(&Query.Address)); // printf("bad address %s\n", FormatIPv6Address(&Query.Address));
exit(1); }
if (!IN6_ADDR_EQUAL(&Query.Address, &in6addr_any)) {
if (BytesReturned != sizeof ADE) { NlsPutMsg(STDOUT, IPV6_MESSAGE_INCONSISTENT_ADDRESS); // printf("inconsistent address info length\n");
exit(1); }
(*func)(IF, &ADE); } else { if (BytesReturned != sizeof ADE.Next) { NlsPutMsg(STDOUT, IPV6_MESSAGE_INCONSISTENT_ADDRESS); // printf("inconsistent address info length\n");
exit(1); } }
if (IN6_ADDR_EQUAL(&ADE.Next.Address, &in6addr_any)) break; Query = ADE.Next; } }
void ForEachPersistentAddress(IPV6_INFO_INTERFACE *IF, void (*func)(IPV6_INFO_INTERFACE *IF, IPV6_UPDATE_ADDRESS *)) { IPV6_PERSISTENT_QUERY_ADDRESS Query; IPV6_UPDATE_ADDRESS ADE; u_int BytesReturned;
Query.IF.RegistryIndex = (u_int) -1; Query.IF.Guid = IF->This.Guid;
for (Query.RegistryIndex = 0;; Query.RegistryIndex++) {
if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_QUERY_ADDRESS, &Query, sizeof Query, &ADE, sizeof ADE, &BytesReturned, NULL) || (BytesReturned != sizeof ADE)) {
if (GetLastError() == ERROR_NO_MORE_ITEMS) break;
NlsPutMsg(STDOUT, IPV6_MESSAGE_22, FormatIPv6Address(&Query.Address)); // printf("bad address %s\n", FormatIPv6Address(&Query.Address));
exit(1); }
(*func)(IF, &ADE); } }
const char * FormatDADState(u_int DADState) { static char buffer[128];
switch (DADState) { case DAD_STATE_INVALID: return "invalid"; case DAD_STATE_DUPLICATE: return "duplicate"; case DAD_STATE_TENTATIVE: return "tentative"; case DAD_STATE_DEPRECATED: return "deprecated"; case DAD_STATE_PREFERRED: return "preferred"; default: sprintf(buffer, "DAD state %u>", DADState); return buffer; } }
const char * FormatScopeAdj(u_int Scope) { static char buffer[128];
switch (Scope) { case ADE_INTERFACE_LOCAL: return "interface-local"; case ADE_LINK_LOCAL: return "link-local"; case ADE_SUBNET_LOCAL: return "subnet-local"; case ADE_ADMIN_LOCAL: return "admin-local"; case ADE_SITE_LOCAL: return "site-local"; case ADE_ORG_LOCAL: return "org-local"; case ADE_GLOBAL: return "global"; default: sprintf(buffer, "scope %u", Scope); return buffer; } }
const char * FormatScopeNoun(u_int Scope) { static char buffer[128];
switch (Scope) { case ADE_INTERFACE_LOCAL: return "if"; case ADE_LINK_LOCAL: return "link"; case ADE_SUBNET_LOCAL: return "subnet"; case ADE_ADMIN_LOCAL: return "admin"; case ADE_SITE_LOCAL: return "site"; case ADE_ORG_LOCAL: return "org"; case ADE_GLOBAL: return "global"; default: sprintf(buffer, "zone%u", Scope); return buffer; } }
void PrintAddrOrigin(u_int PrefixConf, u_int InterfaceIdConf) { if ((PrefixConf == PREFIX_CONF_MANUAL) && (InterfaceIdConf == IID_CONF_MANUAL)) {
NlsPutMsg(STDOUT, IPV6_MESSAGE_25); // printf(" (manual)");
} else if ((PrefixConf == PREFIX_CONF_RA) && (InterfaceIdConf == IID_CONF_LL_ADDRESS)) {
NlsPutMsg(STDOUT, IPV6_MESSAGE_26); // printf(" (public)");
} else if ((PrefixConf == PREFIX_CONF_RA) && (InterfaceIdConf == IID_CONF_RANDOM)) {
NlsPutMsg(STDOUT, IPV6_MESSAGE_27); // printf(" (temporary)");
} else if ((PrefixConf == PREFIX_CONF_DHCP) && (InterfaceIdConf == IID_CONF_DHCP)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_28); // printf(" (dhcp)");
}
if (Verbose) { //
// Show prefix origin / interface id origin
//
NlsPutMsg(STDOUT, IPV6_MESSAGE_29); // printf(" (");
if (PrefixConf >= MAX_PREFIX_CONF) NlsPutMsg(STDOUT, IPV6_MESSAGE_30, PrefixConf); // printf("unknown prefix origin %u", PrefixConf);
else printf(PrefixConfStr[PrefixConf]);
NlsPutMsg(STDOUT, IPV6_MESSAGE_32); // printf("/");
if (InterfaceIdConf >= MAX_IID_CONF) NlsPutMsg(STDOUT, IPV6_MESSAGE_33, InterfaceIdConf); // printf("unknown ifid origin %u", InterfaceIdConf);
else printf(InterfaceIdConfStr[InterfaceIdConf]);
NlsPutMsg(STDOUT, IPV6_MESSAGE_35); // printf(")");
} }
void PrintAddress(IPV6_INFO_INTERFACE *IF, IPV6_INFO_ADDRESS *ADE) { if (!Verbose) { //
// Suppress invalid addresses.
//
if ((ADE->Type == ADE_UNICAST) && (ADE->DADState == DAD_STATE_INVALID)) return; }
switch (ADE->Type) { case ADE_UNICAST: NlsPutMsg(STDOUT, IPV6_MESSAGE_23, FormatDADState(ADE->DADState), FormatScopeAdj(ADE->Scope), FormatIPv6Address(&ADE->This.Address)); // printf(" %s %s %s, ",
// FormatDADState(ADE->DADState),
// FormatScopeAdj(ADE->Scope),
// FormatIPv6Address(&ADE->This.Address));
NlsPutMsg(STDOUT, IPV6_MESSAGE_24, FormatLifetimes(ADE->ValidLifetime, ADE->PreferredLifetime)); // printf("life %s",
// FormatLifetimes(ADE->ValidLifetime, ADE->PreferredLifetime));
PrintAddrOrigin(ADE->PrefixConf, ADE->InterfaceIdConf);
NlsPutMsg(STDOUT, IPV6_MESSAGE_36); // printf("\n");
break;
case ADE_ANYCAST: NlsPutMsg(STDOUT, IPV6_MESSAGE_37, FormatScopeAdj(ADE->Scope), FormatIPv6Address(&ADE->This.Address)); // printf(" anycast %s %s\n",
// FormatScopeAdj(ADE->Scope),
// FormatIPv6Address(&ADE->This.Address));
break;
case ADE_MULTICAST: NlsPutMsg(STDOUT, IPV6_MESSAGE_38, FormatScopeAdj(ADE->Scope), FormatIPv6Address(&ADE->This.Address), ADE->MCastRefCount); // printf(" multicast %s %s, %u refs",
// FormatScopeAdj(ADE->Scope),
// FormatIPv6Address(&ADE->This.Address),
// ADE->MCastRefCount);
if (!(ADE->MCastFlags & 0x01)) NlsPutMsg(STDOUT, IPV6_MESSAGE_39); // printf(", not reportable");
if (ADE->MCastFlags & 0x02) NlsPutMsg(STDOUT, IPV6_MESSAGE_40); // printf(", last reporter");
if (ADE->MCastTimer != 0) NlsPutMsg(STDOUT, IPV6_MESSAGE_41, ADE->MCastTimer); // printf(", %u seconds until report", ADE->MCastTimer);
NlsPutMsg(STDOUT, IPV6_MESSAGE_36); // printf("\n");
break;
default: NlsPutMsg(STDOUT, IPV6_MESSAGE_42, FormatScopeAdj(ADE->Scope), ADE->Type); // printf(" unknown %s address type %u\n",
// FormatScopeAdj(ADE->Scope), ADE->Type);
break; } }
u_int AddressScope(IPv6Addr *Address) { if (IN6_IS_ADDR_LINKLOCAL(Address)) return ADE_LINK_LOCAL; else if (IN6_IS_ADDR_SITELOCAL(Address)) return ADE_SITE_LOCAL; else if (IN6_IS_ADDR_LOOPBACK(Address)) return ADE_LINK_LOCAL; else return ADE_GLOBAL; }
void PrintPersistentAddress(IPV6_INFO_INTERFACE *IF, IPV6_UPDATE_ADDRESS *ADE) { NlsPutMsg(STDOUT, IPV6_MESSAGE_23, ((ADE->Type == ADE_ANYCAST) ? "anycast" : FormatDADState((ADE->PreferredLifetime == 0) ? DAD_STATE_DEPRECATED : DAD_STATE_PREFERRED)), FormatScopeAdj(AddressScope(&ADE->This.Address)), FormatIPv6Address(&ADE->This.Address)); // printf(" %s %s %s, ",
NlsPutMsg(STDOUT, IPV6_MESSAGE_24, FormatLifetimes(ADE->ValidLifetime, ADE->PreferredLifetime)); // printf("life %s",
PrintAddrOrigin(ADE->PrefixConf, ADE->InterfaceIdConf);
NlsPutMsg(STDOUT, IPV6_MESSAGE_36); // printf("\n");
}
IPV6_INFO_INTERFACE * GetInterfaceInfo(IPV6_QUERY_INTERFACE *Query) { IPV6_INFO_INTERFACE *IF; u_int InfoSize, BytesReturned;
InfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH; IF = malloc(InfoSize); if (IF == NULL) { NlsPutMsg(STDOUT, IPV6_MESSAGE_43); // printf("malloc failed\n");
exit(1); }
if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_INTERFACE, Query, sizeof *Query, IF, InfoSize, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_44, Query->Index); // printf("bad index %u\n", Query->Index);
exit(1); }
if ((BytesReturned < sizeof *IF) || (IF->Length < sizeof *IF) || (BytesReturned != IF->Length + ((IF->LocalLinkLayerAddress != 0) ? IF->LinkLayerAddressLength : 0) + ((IF->RemoteLinkLayerAddress != 0) ? IF->LinkLayerAddressLength : 0))) {
NlsPutMsg(STDOUT, IPV6_MESSAGE_45); // printf("inconsistent interface info length\n");
exit(1); }
return IF; }
IPV6_INFO_INTERFACE * GetPersistentInterfaceInfo(IPV6_PERSISTENT_QUERY_INTERFACE *Query) { IPV6_INFO_INTERFACE *IF; u_int InfoSize, BytesReturned;
InfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH; IF = malloc(InfoSize); if (IF == NULL) { NlsPutMsg(STDOUT, IPV6_MESSAGE_43); // printf("malloc failed\n");
exit(1); }
if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_QUERY_INTERFACE, Query, sizeof *Query, IF, InfoSize, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_44, Query->RegistryIndex); // printf("bad index %u\n", Query->RegistryIndex);
exit(1); }
if ((BytesReturned < sizeof *IF) || (IF->Length < sizeof *IF) || (BytesReturned != IF->Length + ((IF->LocalLinkLayerAddress != 0) ? IF->LinkLayerAddressLength : 0) + ((IF->RemoteLinkLayerAddress != 0) ? IF->LinkLayerAddressLength : 0))) {
NlsPutMsg(STDOUT, IPV6_MESSAGE_45); // printf("inconsistent interface info length\n");
exit(1); }
return IF; }
void ForEachInterface(void (*func)(IPV6_INFO_INTERFACE *)) { IPV6_QUERY_INTERFACE Query; IPV6_INFO_INTERFACE *IF; u_int InfoSize, BytesReturned;
InfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH; IF = malloc(InfoSize); if (IF == NULL) { NlsPutMsg(STDOUT, IPV6_MESSAGE_43); // printf("malloc failed\n");
exit(1); }
Query.Index = (u_int) -1;
for (;;) { if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_INTERFACE, &Query, sizeof Query, IF, InfoSize, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_46, Query.Index); // printf("bad index %u\n", Query.Index);
exit(1); }
if (Query.Index != (u_int) -1) {
if ((BytesReturned < sizeof *IF) || (IF->Length < sizeof *IF) || (BytesReturned != IF->Length + ((IF->LocalLinkLayerAddress != 0) ? IF->LinkLayerAddressLength : 0) + ((IF->RemoteLinkLayerAddress != 0) ? IF->LinkLayerAddressLength : 0))) {
NlsPutMsg(STDOUT, IPV6_MESSAGE_45); // printf("inconsistent interface info length\n");
exit(1); }
(*func)(IF); } else { if (BytesReturned != sizeof IF->Next) { NlsPutMsg(STDOUT, IPV6_MESSAGE_45); // printf("inconsistent interface info length\n");
exit(1); } }
if (IF->Next.Index == (u_int) -1) break; Query = IF->Next; }
free(IF); }
void ForEachPersistentInterface(void (*func)(IPV6_INFO_INTERFACE *)) { IPV6_PERSISTENT_QUERY_INTERFACE Query; IPV6_INFO_INTERFACE *IF; u_int InfoSize, BytesReturned;
InfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH; IF = malloc(InfoSize); if (IF == NULL) { NlsPutMsg(STDOUT, IPV6_MESSAGE_43); // printf("malloc failed\n");
exit(1); }
for (Query.RegistryIndex = 0;; Query.RegistryIndex++) {
if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_QUERY_INTERFACE, &Query, sizeof Query, IF, InfoSize, &BytesReturned, NULL)) { if (GetLastError() == ERROR_NO_MORE_ITEMS) break;
NlsPutMsg(STDOUT, IPV6_MESSAGE_46, Query.RegistryIndex); // printf("bad index %u\n", Query.RegistryIndex);
exit(1); }
if ((BytesReturned < sizeof *IF) || (IF->Length < sizeof *IF) || (BytesReturned != IF->Length + ((IF->LocalLinkLayerAddress != 0) ? IF->LinkLayerAddressLength : 0) + ((IF->RemoteLinkLayerAddress != 0) ? IF->LinkLayerAddressLength : 0))) {
NlsPutMsg(STDOUT, IPV6_MESSAGE_45); // printf("inconsistent interface info length\n");
exit(1); }
(*func)(IF); }
free(IF); }
#ifndef IP_TYPES_INCLUDED
//
// The real version of this structure in iptypes.h
// has more fields, but these are all we need here.
//
#define MAX_ADAPTER_DESCRIPTION_LENGTH 128 // arb.
#define MAX_ADAPTER_NAME_LENGTH 256 // arb.
#define MAX_ADAPTER_ADDRESS_LENGTH 8 // arb.
typedef struct _IP_ADAPTER_INFO { struct _IP_ADAPTER_INFO* Next; DWORD ComboIndex; char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4]; char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4]; UINT AddressLength; BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH]; DWORD Index; } IP_ADAPTER_INFO; #endif // IP_TYPES_INCLUDED
DWORD (WINAPI *pGetAdaptersInfo)(IP_ADAPTER_INFO *pAdapterInfo, ULONG *pOutBufLen);
IP_ADAPTER_INFO *pAdapterInfo;
HRESULT (WINAPI *pHrLanConnectionNameFromGuidOrPath)( const GUID *pGuid, LPCWSTR pszwPath, LPWSTR pszwName, LPDWORD pcchMax);
#define IPHLPAPI_LIBRARY_NAME "iphlpapi.dll"
#define NETMAN_LIBRARY_NAME "netman.dll"
void InitializeAdaptersInfo(void) { HMODULE hModule; CHAR SystemDir[MAX_PATH + 1]; CHAR Path[MAX_PATH + sizeof(IPHLPAPI_LIBRARY_NAME) + 2];
pAdapterInfo = NULL; if (GetSystemDirectory(SystemDir, MAX_PATH) == 0) { return; }
//
// Check if the GetAdaptersInfo API is available on this system.
//
lstrcpy(Path, SystemDir); lstrcat(Path, "\\" IPHLPAPI_LIBRARY_NAME); hModule = LoadLibrary(Path); if (hModule != NULL) {
pGetAdaptersInfo = (DWORD (WINAPI *)(IP_ADAPTER_INFO *, ULONG *)) GetProcAddress(hModule, "GetAdaptersInfo"); //
// We don't release hModule, to keep the module loaded.
//
if (pGetAdaptersInfo != NULL) { ULONG BufLen = 0; DWORD error;
//
// If this returns something other than buffer-overflow,
// it probably means that GetAdaptersInfo is not supported.
//
error = (*pGetAdaptersInfo)(NULL, &BufLen); if (error == ERROR_BUFFER_OVERFLOW) { pAdapterInfo = (IP_ADAPTER_INFO *) malloc(BufLen); if (pAdapterInfo != NULL) { error = (*pGetAdaptersInfo)(pAdapterInfo, &BufLen); if (error != 0) { free(pAdapterInfo); pAdapterInfo = NULL; } } } } }
//
// Only bother with HrLanConnectionNameFromGuidOrPath
// if we could get pAdapterInfo.
//
if (pAdapterInfo != NULL) { lstrcpy(Path, SystemDir); lstrcat(Path, "\\" NETMAN_LIBRARY_NAME); hModule = LoadLibrary(Path); if (hModule != NULL) {
pHrLanConnectionNameFromGuidOrPath = (HRESULT (WINAPI *)(const GUID *, LPCWSTR, LPWSTR, LPDWORD)) GetProcAddress(hModule, "HrLanConnectionNameFromGuidOrPath"); //
// We don't release hModule, to keep the module loaded.
//
}
if (pHrLanConnectionNameFromGuidOrPath == NULL) { free(pAdapterInfo); pAdapterInfo = NULL; } } }
#define MAX_FRIENDLY_NAME_LENGTH 2000
LPSTR MapAdapterNameToFriendly(LPSTR AdapterName) { WCHAR wszAdapterName[MAX_ADAPTER_NAME_LENGTH]; WCHAR wszFriendlyName[MAX_FRIENDLY_NAME_LENGTH]; DWORD cchFriendlyName = MAX_FRIENDLY_NAME_LENGTH; static CHAR FriendlyName[MAX_FRIENDLY_NAME_LENGTH];
MultiByteToWideChar(CP_ACP, 0, AdapterName, -1, wszAdapterName, MAX_ADAPTER_NAME_LENGTH);
if((*pHrLanConnectionNameFromGuidOrPath)( NULL, wszAdapterName, wszFriendlyName, &cchFriendlyName)) return NULL;
WideCharToMultiByte(CP_ACP, 0, wszFriendlyName, -1, FriendlyName, MAX_FRIENDLY_NAME_LENGTH, NULL, NULL); return FriendlyName; }
LPSTR MapAdapterAddressToFriendly(u_char *Address, u_int AddressLength) { IP_ADAPTER_INFO *pAdapter;
for (pAdapter = pAdapterInfo; pAdapter != NULL; pAdapter = pAdapter->Next) {
if ((AddressLength == pAdapter->AddressLength) && ! memcmp(Address, pAdapter->Address, AddressLength)) return MapAdapterNameToFriendly(pAdapter->AdapterName); }
return NULL; }
int ShouldPrintZones(IPV6_INFO_INTERFACE *IF) { u_int Scope;
for (Scope = ADE_SMALLEST_SCOPE; Scope <= ADE_LINK_LOCAL; Scope++) if (IF->ZoneIndices[Scope] != IF->This.Index) return TRUE;
for (; Scope <= ADE_LARGEST_SCOPE; Scope++) if (IF->ZoneIndices[Scope] != 1) return TRUE;
return FALSE; }
void PrintInterface(IPV6_INFO_INTERFACE *IF) { LPSTR FriendlyName; u_int Scope;
if (IF->LocalLinkLayerAddress == 0) FriendlyName = NULL; else FriendlyName = MapAdapterAddressToFriendly( (u_char *)IF + IF->LocalLinkLayerAddress, IF->LinkLayerAddressLength);
NlsPutMsg(STDOUT, IPV6_MESSAGE_47, IF->This.Index); // printf("Interface %u:", IF->This.Index);
switch (IF->Type) { case IPV6_IF_TYPE_LOOPBACK: NlsPutMsg(STDOUT, IPV6_MESSAGE_48); // printf(" Loopback Pseudo-Interface");
break; case IPV6_IF_TYPE_ETHERNET: NlsPutMsg(STDOUT, IPV6_MESSAGE_49); // printf(" Ethernet");
break; case IPV6_IF_TYPE_FDDI: NlsPutMsg(STDOUT, IPV6_MESSAGE_50); // printf(" FDDI");
break; case IPV6_IF_TYPE_TUNNEL_AUTO: NlsPutMsg(STDOUT, IPV6_MESSAGE_51); // printf(" Automatic Tunneling Pseudo-Interface");
break; case IPV6_IF_TYPE_TUNNEL_6OVER4: NlsPutMsg(STDOUT, IPV6_MESSAGE_52); // printf(" 6-over-4 Virtual Interface");
break; case IPV6_IF_TYPE_TUNNEL_V6V4: NlsPutMsg(STDOUT, IPV6_MESSAGE_53); // printf(" Configured Tunnel Interface");
break; case IPV6_IF_TYPE_TUNNEL_6TO4: NlsPutMsg(STDOUT, IPV6_6TO4_INTERFACE); // printf(" 6to4 Tunneling Pseudo-Interface");
break; case IPV6_IF_TYPE_TUNNEL_TEREDO: NlsPutMsg(STDOUT, IPV6_TEREDO_INTERFACE); // printf(" Teredo Tunneling Pseudo-Interface");
break; }
if (FriendlyName != NULL) NlsPutMsg(STDOUT, IPV6_MESSAGE_54, FriendlyName); // printf(": %s", FriendlyName);
NlsPutMsg(STDOUT, IPV6_MESSAGE_36); // printf("\n");
NlsPutMsg(STDOUT, IPV6_MESSAGE_GUID, FormatGuid(&IF->This.Guid)); // printf(" Guid %s\n", FormatGuid(&IF->This.Guid));
if (Verbose || ShouldPrintZones(IF)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_55); // printf(" zones:");
for (Scope = ADE_LINK_LOCAL; Scope < ADE_GLOBAL; Scope++) { u_int Expected;
if ((Scope == ADE_LINK_LOCAL) || (Scope == ADE_SITE_LOCAL)) Expected = 0; // Always print link & site.
else Expected = IF->ZoneIndices[Scope + 1];
if (IF->ZoneIndices[Scope] != Expected) NlsPutMsg(STDOUT, IPV6_MESSAGE_56, FormatScopeNoun(Scope), IF->ZoneIndices[Scope]); // printf(" %s %u",
// FormatScopeNoun(Scope),
// IF->ZoneIndices[Scope]);
} NlsPutMsg(STDOUT, IPV6_MESSAGE_36); // printf("\n");
}
switch (IF->MediaStatus) { case IPV6_IF_MEDIA_STATUS_DISCONNECTED: NlsPutMsg(STDOUT, IPV6_MESSAGE_57); // printf(" cable unplugged\n");
break; case IPV6_IF_MEDIA_STATUS_RECONNECTED: NlsPutMsg(STDOUT, IPV6_MESSAGE_58); // printf(" cable reconnected\n");
break; case IPV6_IF_MEDIA_STATUS_CONNECTED: break; }
if (IF->NeighborDiscovers) NlsPutMsg(STDOUT, IPV6_MESSAGE_USES_ND); // printf(" uses Neighbor Discovery\n");
else NlsPutMsg(STDOUT, IPV6_MESSAGE_DOESNT_USE_ND); // printf(" does not use Neighbor Discovery\n");
if (IF->RouterDiscovers) NlsPutMsg(STDOUT, IPV6_MESSAGE_USES_RD); else NlsPutMsg(STDOUT, IPV6_MESSAGE_DOESNT_USE_RD);
if (IF->Advertises) NlsPutMsg(STDOUT, IPV6_MESSAGE_SENDS_RAs); // printf(" sends Router Advertisements\n");
if (IF->Forwards) NlsPutMsg(STDOUT, IPV6_MESSAGE_FORWARDS); // printf(" forwards packets\n");
if (IF->PeriodicMLD) NlsPutMsg(STDOUT, IPV6_MESSAGE_SENDS_PERIODIC_MLD); // printf(" periodically sends MLD Reports\n");
if (IF->Preference != 0) NlsPutMsg(STDOUT, IPV6_MESSAGE_64, IF->Preference); // printf(" routing preference %u\n", IF->Preference);
if (IF->Type == IPV6_IF_TYPE_TUNNEL_AUTO) { if (IF->LocalLinkLayerAddress != 0) { NlsPutMsg(STDOUT, IPV6_MESSAGE_TOKEN_ADDRESS, FormatLinkLayerAddress(IF->LinkLayerAddressLength, (u_char *)IF + IF->LocalLinkLayerAddress)); // printf(" EUI-64 embedded IPv4 address: %s\n",
}
if (IF->RemoteLinkLayerAddress != 0) { NlsPutMsg(STDOUT, IPV6_MESSAGE_ROUTER_LL_ADDRESS, FormatLinkLayerAddress(IF->LinkLayerAddressLength, (u_char *)IF + IF->RemoteLinkLayerAddress)); // printf(" router link-layer address: %s\n",
} } else { if (IF->LocalLinkLayerAddress != 0) { NlsPutMsg(STDOUT, IPV6_MESSAGE_65, FormatLinkLayerAddress(IF->LinkLayerAddressLength, (u_char *)IF + IF->LocalLinkLayerAddress)); // printf(" link-layer address: %s\n",
}
if (IF->RemoteLinkLayerAddress != 0) { NlsPutMsg(STDOUT, IPV6_MESSAGE_66, FormatLinkLayerAddress(IF->LinkLayerAddressLength, (u_char *)IF + IF->RemoteLinkLayerAddress)); // printf(" remote link-layer address: %s\n",
} }
ForEachAddress(IF, PrintAddress);
NlsPutMsg(STDOUT, IPV6_MESSAGE_67, IF->LinkMTU, IF->TrueLinkMTU); // printf(" link MTU %u (true link MTU %u)\n",
// IF->LinkMTU, IF->TrueLinkMTU);
NlsPutMsg(STDOUT, IPV6_MESSAGE_68, IF->CurHopLimit); // printf(" current hop limit %u\n", IF->CurHopLimit);
NlsPutMsg(STDOUT, IPV6_MESSAGE_69, IF->ReachableTime, IF->BaseReachableTime); // printf(" reachable time %ums (base %ums)\n",
// IF->ReachableTime, IF->BaseReachableTime);
NlsPutMsg(STDOUT, IPV6_MESSAGE_70, IF->RetransTimer); // printf(" retransmission interval %ums\n", IF->RetransTimer);
NlsPutMsg(STDOUT, IPV6_MESSAGE_71, IF->DupAddrDetectTransmits); // printf(" DAD transmits %u\n", IF->DupAddrDetectTransmits);
NlsPutMsg(STDOUT, IPV6_MESSAGE_DEFAULT_SITE_PREFIX_LENGTH, IF->DefSitePrefixLength); // printf(" default site prefix length %u\n",
}
void PrintPersistentInterface(IPV6_INFO_INTERFACE *IF) { u_int Scope;
NlsPutMsg(STDOUT, IPV6_MESSAGE_INTERFACE); // printf("Interface:"
switch (IF->Type) { case IPV6_IF_TYPE_LOOPBACK: NlsPutMsg(STDOUT, IPV6_MESSAGE_48); // printf(" Loopback Pseudo-Interface");
break; case IPV6_IF_TYPE_ETHERNET: NlsPutMsg(STDOUT, IPV6_MESSAGE_49); // printf(" Ethernet");
break; case IPV6_IF_TYPE_FDDI: NlsPutMsg(STDOUT, IPV6_MESSAGE_50); // printf(" FDDI");
break; case IPV6_IF_TYPE_TUNNEL_AUTO: NlsPutMsg(STDOUT, IPV6_MESSAGE_51); // printf(" Automatic Tunneling Pseudo-Interface");
break; case IPV6_IF_TYPE_TUNNEL_6OVER4: NlsPutMsg(STDOUT, IPV6_MESSAGE_52); // printf(" 6-over-4 Virtual Interface");
break; case IPV6_IF_TYPE_TUNNEL_V6V4: NlsPutMsg(STDOUT, IPV6_MESSAGE_53); // printf(" Configured Tunnel Interface");
break; case IPV6_IF_TYPE_TUNNEL_6TO4: NlsPutMsg(STDOUT, IPV6_6TO4_INTERFACE); // printf(" 6to4 Tunneling Pseudo-Interface");
break; }
NlsPutMsg(STDOUT, IPV6_MESSAGE_36); // printf("\n");
NlsPutMsg(STDOUT, IPV6_MESSAGE_GUID, FormatGuid(&IF->This.Guid)); // printf(" Guid %s\n", FormatGuid(&IF->This.Guid));
if (IF->NeighborDiscovers == TRUE) NlsPutMsg(STDOUT, IPV6_MESSAGE_USES_ND); // printf(" uses Neighbor Discovery\n");
else if (IF->NeighborDiscovers == FALSE) NlsPutMsg(STDOUT, IPV6_MESSAGE_DOESNT_USE_ND); // printf(" does not use Neighbor Discovery\n");
if (IF->RouterDiscovers == TRUE) NlsPutMsg(STDOUT, IPV6_MESSAGE_USES_RD); else if (IF->RouterDiscovers == FALSE) NlsPutMsg(STDOUT, IPV6_MESSAGE_DOESNT_USE_RD);
if (IF->Advertises == TRUE) NlsPutMsg(STDOUT, IPV6_MESSAGE_SENDS_RAs); // printf(" sends Router Advertisements\n");
else if (IF->Advertises == FALSE) NlsPutMsg(STDOUT, IPV6_MESSAGE_DOESNT_SEND_RAs); // printf(" does not send Router Advertisements\n");
if (IF->Forwards == TRUE) NlsPutMsg(STDOUT, IPV6_MESSAGE_FORWARDS); // printf(" forwards packets\n");
else if (IF->Forwards == FALSE) NlsPutMsg(STDOUT, IPV6_MESSAGE_DOESNT_FORWARD); // printf(" does not forward packets\n");
if (IF->PeriodicMLD == TRUE) NlsPutMsg(STDOUT, IPV6_MESSAGE_SENDS_PERIODIC_MLD); // printf(" periodically sends MLD Reports\n");
else if (IF->PeriodicMLD == FALSE) NlsPutMsg(STDOUT, IPV6_MESSAGE_DOESNT_SEND_PERIODIC_MLD); // printf(" does not periodically send MLD Reports\n");
if (IF->Preference != (u_int)-1) NlsPutMsg(STDOUT, IPV6_MESSAGE_64, IF->Preference); // printf(" routing preference %u\n", IF->Preference);
if (IF->Type == IPV6_IF_TYPE_TUNNEL_AUTO) { if (IF->LocalLinkLayerAddress != 0) { NlsPutMsg(STDOUT, IPV6_MESSAGE_TOKEN_ADDRESS, FormatLinkLayerAddress(IF->LinkLayerAddressLength, (u_char *)IF + IF->LocalLinkLayerAddress)); // printf(" EUI-64 embedded IPv4 address: %s\n",
}
if (IF->RemoteLinkLayerAddress != 0) { NlsPutMsg(STDOUT, IPV6_MESSAGE_ROUTER_LL_ADDRESS, FormatLinkLayerAddress(IF->LinkLayerAddressLength, (u_char *)IF + IF->RemoteLinkLayerAddress)); // printf(" router link-layer address: %s\n",
} } else { if (IF->LocalLinkLayerAddress != 0) { NlsPutMsg(STDOUT, IPV6_MESSAGE_65, FormatLinkLayerAddress(IF->LinkLayerAddressLength, (u_char *)IF + IF->LocalLinkLayerAddress)); // printf(" link-layer address: %s\n",
}
if (IF->RemoteLinkLayerAddress != 0) { NlsPutMsg(STDOUT, IPV6_MESSAGE_66, FormatLinkLayerAddress(IF->LinkLayerAddressLength, (u_char *)IF + IF->RemoteLinkLayerAddress)); // printf(" remote link-layer address: %s\n",
} }
ForEachPersistentAddress(IF, PrintPersistentAddress);
if (IF->LinkMTU != 0) { NlsPutMsg(STDOUT, IPV6_MESSAGE_LINK_MTU, IF->LinkMTU); // printf(" link MTU %u\n",
}
if (IF->CurHopLimit != (u_int)-1) { NlsPutMsg(STDOUT, IPV6_MESSAGE_68, IF->CurHopLimit); // printf(" current hop limit %u\n", IF->CurHopLimit);
}
if (IF->BaseReachableTime != 0) { NlsPutMsg(STDOUT, IPV6_MESSAGE_BASE_REACHABLE_TIME, IF->BaseReachableTime); // printf(" base reachable time %ums\n",
}
if (IF->RetransTimer != 0) { NlsPutMsg(STDOUT, IPV6_MESSAGE_70, IF->RetransTimer); // printf(" retransmission interval %ums\n", IF->RetransTimer);
}
if (IF->DupAddrDetectTransmits != (u_int)-1) { NlsPutMsg(STDOUT, IPV6_MESSAGE_71, IF->DupAddrDetectTransmits); // printf(" DAD transmits %u\n", IF->DupAddrDetectTransmits);
}
if (IF->DefSitePrefixLength != (u_int)-1) { NlsPutMsg(STDOUT, IPV6_MESSAGE_DEFAULT_SITE_PREFIX_LENGTH, IF->DefSitePrefixLength); // printf(" default site prefix length %u\n",
} }
IPV6_INFO_NEIGHBOR_CACHE * GetNeighborCacheEntry(IPV6_QUERY_NEIGHBOR_CACHE *Query) { IPV6_INFO_NEIGHBOR_CACHE *NCE; u_int InfoSize, BytesReturned;
InfoSize = sizeof *NCE + MAX_LINK_LAYER_ADDRESS_LENGTH; NCE = (IPV6_INFO_NEIGHBOR_CACHE *) malloc(InfoSize); if (NCE == NULL) { NlsPutMsg(STDOUT, IPV6_MESSAGE_36); // printf("malloc failed\n");
exit(1); }
if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_NEIGHBOR_CACHE, Query, sizeof *Query, NCE, InfoSize, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_72, FormatIPv6Address(&Query->Address)); // printf("bad address %s\n", FormatIPv6Address(&Query->Address));
exit(1); }
if ((BytesReturned < sizeof *NCE) || (BytesReturned != sizeof *NCE + NCE->LinkLayerAddressLength)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_73); // printf("inconsistent neighbor cache info length\n");
exit(1); }
NCE->Query = *Query; return NCE; }
void ForEachNeighborCacheEntry(IPV6_QUERY_INTERFACE *IF, void (*func)(IPV6_INFO_NEIGHBOR_CACHE *)) { IPV6_QUERY_NEIGHBOR_CACHE Query, NextQuery; IPV6_INFO_NEIGHBOR_CACHE *NCE; u_int InfoSize, BytesReturned;
InfoSize = sizeof *NCE + MAX_LINK_LAYER_ADDRESS_LENGTH; NCE = (IPV6_INFO_NEIGHBOR_CACHE *) malloc(InfoSize); if (NCE == NULL) { NlsPutMsg(STDOUT, IPV6_MESSAGE_36); // printf("malloc failed\n");
exit(1); }
NextQuery.IF = *IF; NextQuery.Address = in6addr_any;
for (;;) { Query = NextQuery;
if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_NEIGHBOR_CACHE, &Query, sizeof Query, NCE, InfoSize, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_72, FormatIPv6Address(&Query.Address)); // printf("bad address %s\n", FormatIPv6Address(&Query.Address));
exit(1); }
NextQuery = NCE->Query;
if (!IN6_ADDR_EQUAL(&Query.Address, &in6addr_any)) {
if ((BytesReturned < sizeof *NCE) || (BytesReturned != sizeof *NCE + NCE->LinkLayerAddressLength)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_73); // printf("inconsistent neighbor cache info length\n");
exit(1); }
NCE->Query = Query; (*func)(NCE); }
if (IN6_ADDR_EQUAL(&NextQuery.Address, &in6addr_any)) break; }
free(NCE); }
void PrintNeighborCacheEntry(IPV6_INFO_NEIGHBOR_CACHE *NCE) { NlsPutMsg(STDOUT, IPV6_MESSAGE_74, NCE->Query.IF.Index, FormatIPv6Address(&NCE->Query.Address)); // printf("%u: %18s", NCE->Query.IF.Index,
// FormatIPv6Address(&NCE->Query.Address));
if (NCE->NDState != 0) NlsPutMsg(STDOUT, IPV6_MESSAGE_75, FormatLinkLayerAddress( NCE->LinkLayerAddressLength, (u_char *)(NCE + 1))); // printf(" %-17s", FormatLinkLayerAddress(NCE->LinkLayerAddressLength,
// (u_char *)(NCE + 1)));
else NlsPutMsg(STDOUT, IPV6_MESSAGE_75, ""); // printf(" %-17s", "");
switch (NCE->NDState) { case ND_STATE_INCOMPLETE: NlsPutMsg(STDOUT, IPV6_MESSAGE_76); // printf(" incomplete");
break; case ND_STATE_PROBE: NlsPutMsg(STDOUT, IPV6_MESSAGE_77); // printf(" probe");
break; case ND_STATE_DELAY: NlsPutMsg(STDOUT, IPV6_MESSAGE_78); // printf(" delay");
break; case ND_STATE_STALE: NlsPutMsg(STDOUT, IPV6_MESSAGE_79); // printf(" stale");
break; case ND_STATE_REACHABLE: NlsPutMsg(STDOUT, IPV6_MESSAGE_80, NCE->ReachableTimer); // printf(" reachable (%ums)", NCE->ReachableTimer);
break; case ND_STATE_PERMANENT: NlsPutMsg(STDOUT, IPV6_MESSAGE_81); // printf(" permanent");
break; default: NlsPutMsg(STDOUT, IPV6_MESSAGE_82, NCE->NDState); // printf(" unknown ND state %u", NCE->NDState);
break; }
if (NCE->IsRouter) NlsPutMsg(STDOUT, IPV6_MESSAGE_83); // printf(" (router)");
if (NCE->IsUnreachable) NlsPutMsg(STDOUT, IPV6_MESSAGE_84); // printf(" (unreachable)");
NlsPutMsg(STDOUT, IPV6_MESSAGE_36); // printf("\n");
}
void QueryInterface(int argc, char *argv[]) { InitializeAdaptersInfo();
if (argc == 0) { if (Persistent) ForEachPersistentInterface(PrintPersistentInterface); else ForEachInterface(PrintInterface); } else if (argc == 1) { IPV6_INFO_INTERFACE *IF;
if (Persistent) { IPV6_PERSISTENT_QUERY_INTERFACE Query;
Query.RegistryIndex = (u_int)-1; if (! GetGuid(argv[0], &Query.Guid)) usage();
IF = GetPersistentInterfaceInfo(&Query); PrintPersistentInterface(IF); free(IF); } else { IPV6_QUERY_INTERFACE Query;
if (! GetInterface(argv[0], &Query)) usage();
IF = GetInterfaceInfo(&Query); PrintInterface(IF); free(IF); } } else { usage(); } }
void RenewViaReconnect(IPV6_INFO_INTERFACE *IF) { u_int BytesReturned;
if (!DeviceIoControl(Handle, IOCTL_IPV6_RENEW_INTERFACE, &IF->This, sizeof IF->This, NULL, 0, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_RENEW_INTERFACE, GetLastError()); // printf("renew interface error: %x\n", GetLastError());
exit(1); } }
VOID Poke6to4Service() { SC_HANDLE Service, SCManager; SERVICE_STATUS Status;
SCManager = OpenSCManager(NULL, NULL, GENERIC_READ); if (SCManager == NULL) { return; }
Service = OpenService(SCManager, "6to4", SERVICE_ALL_ACCESS); if (Service != NULL) { //
// Tell the 6to4 service to re-read its configuration information.
//
(VOID) ControlService(Service, SERVICE_CONTROL_PARAMCHANGE, &Status); CloseServiceHandle(Service); }
CloseServiceHandle(SCManager); }
void RenewInterface(int argc, char *argv[]) { BOOL PokeService = FALSE; if (argc == 0) { ForEachInterface(RenewViaReconnect); PokeService = TRUE; } else if (argc == 1) { IPV6_QUERY_INTERFACE Query; IPV6_INFO_INTERFACE *IF;
if (! GetInterface(argv[0], &Query)) usage();
IF = GetInterfaceInfo(&Query); RenewViaReconnect(IF);
//
// Poke the 6to4 service if it manages the interface being renewed.
//
PokeService = (IF->Type == IPV6_IF_TYPE_TUNNEL_6TO4) || (IF->Type == IPV6_IF_TYPE_TUNNEL_TEREDO) || (IF->Type == IPV6_IF_TYPE_TUNNEL_AUTO); free(IF); } else { usage(); }
if (PokeService) { Poke6to4Service(); } }
int GetV4Address(char *astr, struct in_addr *address) { struct addrinfo hints; struct addrinfo *result;
memset(&hints, 0, sizeof hints); hints.ai_family = PF_INET;
if (getaddrinfo(astr, NULL, &hints, &result)) return FALSE;
*address = ((struct sockaddr_in *)result->ai_addr)->sin_addr; freeaddrinfo(result); return TRUE; }
void CreateInterface(int argc, char *argv[]) { struct { IPV6_INFO_INTERFACE Info; struct in_addr SrcAddr; struct in_addr DstAddr; } Create; IPV6_QUERY_INTERFACE Result; u_int BytesReturned; u_int FlagsOn, FlagsOff; int i;
IPV6_INIT_INFO_INTERFACE(&Create.Info);
if (argc < 1) usage();
if (!strcmp(argv[0], "v6v4")) { i = 3; if (argc < i) usage();
if (! GetV4Address(argv[1], &Create.SrcAddr)) usage();
if (! GetV4Address(argv[2], &Create.DstAddr)) usage();
Create.Info.Type = IPV6_IF_TYPE_TUNNEL_V6V4; Create.Info.LinkLayerAddressLength = sizeof(struct in_addr); Create.Info.LocalLinkLayerAddress = (u_int) ((char *)&Create.SrcAddr - (char *)&Create.Info); Create.Info.RemoteLinkLayerAddress = (u_int) ((char *)&Create.DstAddr - (char *)&Create.Info); } else if (!strcmp(argv[0], "6over4")) { i = 2; if (argc < i) usage();
if (! GetV4Address(argv[1], &Create.SrcAddr)) usage();
Create.Info.Type = IPV6_IF_TYPE_TUNNEL_6OVER4; Create.Info.LinkLayerAddressLength = sizeof(struct in_addr); Create.Info.LocalLinkLayerAddress = (u_int) ((char *)&Create.SrcAddr - (char *)&Create.Info); } else usage();
for (; i < argc; i++) { if (!strcmp(argv[i], "nd")) { Create.Info.NeighborDiscovers = TRUE; Create.Info.RouterDiscovers = TRUE; } else if (!strcmp(argv[i], "pmld")) { Create.Info.PeriodicMLD = TRUE; } else if (!strcmp(argv[i], "nond")) { Create.Info.NeighborDiscovers = FALSE; Create.Info.RouterDiscovers = FALSE; } else usage(); }
if (!DeviceIoControl(Handle, (Persistent ? IOCTL_IPV6_PERSISTENT_CREATE_INTERFACE : IOCTL_IPV6_CREATE_INTERFACE), &Create, sizeof Create, &Result, sizeof Result, &BytesReturned, NULL) || (BytesReturned != sizeof Result)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_85, GetLastError()); // printf("control interface error: %x\n", GetLastError());
exit(1); }
NlsPutMsg(STDOUT, IPV6_MESSAGE_86, Result.Index); // printf("Created interface %u.\n", Result.Index);
}
void UpdateInterface(int argc, char *argv[]) { IPV6_INFO_INTERFACE Update; u_int BytesReturned; int i;
IPV6_INIT_INFO_INTERFACE(&Update);
if (argc < 1) usage();
if (! GetInterface(argv[0], &Update.This)) usage();
for (i = 1; i < argc; i++) { if (!strncmp(argv[i], "advertises", strlen(argv[i]))) Update.Advertises = TRUE; else if (!strncmp(argv[i], "-advertises", strlen(argv[i]))) Update.Advertises = FALSE; else if (!strncmp(argv[i], "forwards", strlen(argv[i]))) Update.Forwards = TRUE; else if (!strncmp(argv[i], "-forwards", strlen(argv[i]))) Update.Forwards = FALSE; else if (!strcmp(argv[i], "mtu") && (i+1 < argc)) { if (! GetNumber(argv[i+1], &Update.LinkMTU)) usage(); i++; } else if (!strncmp(argv[i], "preference", strlen(argv[i])) && (i+1 < argc)) { if (! GetNumber(argv[++i], &Update.Preference)) usage(); } else if (!strncmp(argv[i], "basereachabletime", strlen(argv[i])) && (i+1 < argc)) { if (! GetNumber(argv[++i], &Update.BaseReachableTime)) usage(); } else if (!strncmp(argv[i], "retranstimer", strlen(argv[i])) && (i+1 < argc)) { if (! GetNumber(argv[++i], &Update.RetransTimer)) usage(); } else if (!strncmp(argv[i], "dupaddrdetecttransmits", strlen(argv[i])) && (i+1 < argc)) { if (! GetNumber(argv[++i], &Update.DupAddrDetectTransmits)) usage(); } else if (!strncmp(argv[i], "curhoplimit", strlen(argv[i])) && (i+1 < argc)) { if (! GetNumber(argv[++i], &Update.CurHopLimit)) usage(); } else if ((!strncmp(argv[i], "defsiteprefixlength", strlen(argv[i])) || !strcmp(argv[i], "spl")) && (i+1 < argc)) { if (! GetNumber(argv[++i], &Update.DefSitePrefixLength)) usage(); } else if (!strcmp(argv[i], "link") && (i+1 < argc)) { if (! GetNumber(argv[i+1], &Update.ZoneIndices[ADE_LINK_LOCAL])) usage(); i++; } else if (!strcmp(argv[i], "subnet") && (i+1 < argc)) { if (! GetNumber(argv[i+1], &Update.ZoneIndices[ADE_SUBNET_LOCAL])) usage(); i++; } else if (!strcmp(argv[i], "admin") && (i+1 < argc)) { if (! GetNumber(argv[i+1], &Update.ZoneIndices[ADE_ADMIN_LOCAL])) usage(); i++; } else if (!strcmp(argv[i], "site") && (i+1 < argc)) { if (! GetNumber(argv[i+1], &Update.ZoneIndices[ADE_SITE_LOCAL])) usage(); i++; } else if (!strcmp(argv[i], "org") && (i+1 < argc)) { if (! GetNumber(argv[i+1], &Update.ZoneIndices[ADE_ORG_LOCAL])) usage(); i++; } else usage(); }
if (!DeviceIoControl(Handle, (Persistent ? IOCTL_IPV6_PERSISTENT_UPDATE_INTERFACE : IOCTL_IPV6_UPDATE_INTERFACE), &Update, sizeof Update, NULL, 0, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_85, GetLastError()); // printf("control interface error: %x\n", GetLastError());
exit(1); } }
void UpdateRouterLinkAddress(int argc, char *argv[]) { char Buffer[sizeof(IPV6_UPDATE_ROUTER_LL_ADDRESS) + 2 * sizeof(IN_ADDR)]; IPV6_UPDATE_ROUTER_LL_ADDRESS *Update = (IPV6_UPDATE_ROUTER_LL_ADDRESS *)Buffer; IN_ADDR *Addr = (IN_ADDR *)(Update + 1); u_int BytesReturned; SOCKET s; SOCKADDR_IN sinRemote, sinLocal;
if (argc != 2) usage();
if (! GetInterface(argv[0], &Update->IF)) usage();
if (! GetV4Address(argv[1], &Addr[1])) usage();
s = socket(AF_INET, SOCK_DGRAM, 0); if (s == INVALID_SOCKET) { NlsPutMsg(STDOUT, IPV6_MESSAGE_85, WSAGetLastError()); exit(1); }
sinRemote.sin_family = AF_INET; sinRemote.sin_addr = Addr[1];
if (WSAIoctl(s, SIO_ROUTING_INTERFACE_QUERY, &sinRemote, sizeof sinRemote, &sinLocal, sizeof sinLocal, &BytesReturned, NULL, NULL) == SOCKET_ERROR) { NlsPutMsg(STDOUT, IPV6_MESSAGE_85, WSAGetLastError()); exit(1); }
closesocket(s);
Addr[0] = sinLocal.sin_addr; if (Addr[0].s_addr == htonl(INADDR_LOOPBACK)) { //
// We're the router.
//
Addr[0] = Addr[1]; }
if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_ROUTER_LL_ADDRESS, Buffer, sizeof Buffer, NULL, 0, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_85, GetLastError()); // printf("control interface error: %x\n", GetLastError());
exit(1); } }
void DeleteInterface(int argc, char *argv[]) { IPV6_QUERY_INTERFACE Query; u_int BytesReturned;
if (argc != 1) usage();
if (! GetInterface(argv[0], &Query)) usage();
if (!DeviceIoControl(Handle, (Persistent ? IOCTL_IPV6_PERSISTENT_DELETE_INTERFACE : IOCTL_IPV6_DELETE_INTERFACE), &Query, sizeof Query, NULL, 0, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_87, GetLastError()); // printf("delete interface error: %x\n", GetLastError());
exit(1); } }
void PrintNeighborCache(IPV6_INFO_INTERFACE *IF) { ForEachNeighborCacheEntry(&IF->This, PrintNeighborCacheEntry); }
void QueryNeighborCache(int argc, char *argv[]) { if (argc == 0) { ForEachInterface(PrintNeighborCache); } else if (argc == 1) { IPV6_QUERY_INTERFACE Query;
if (! GetInterface(argv[0], &Query)) usage();
ForEachNeighborCacheEntry(&Query, PrintNeighborCacheEntry); } else if (argc == 2) { IPV6_QUERY_NEIGHBOR_CACHE Query; IPV6_INFO_NEIGHBOR_CACHE *NCE;
if (! GetInterface(argv[0], &Query.IF)) usage();
if (! GetAddress(argv[1], &Query.Address)) usage();
NCE = GetNeighborCacheEntry(&Query); PrintNeighborCacheEntry(NCE); free(NCE); } else { usage(); } }
IPV6_INFO_ROUTE_CACHE * GetRouteCacheEntry(IPV6_QUERY_ROUTE_CACHE *Query) { IPV6_INFO_ROUTE_CACHE *RCE; u_int BytesReturned;
RCE = (IPV6_INFO_ROUTE_CACHE *) malloc(sizeof *RCE); if (RCE == NULL) { NlsPutMsg(STDOUT, IPV6_MESSAGE_36); // printf("malloc failed\n");
exit(1); }
if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_ROUTE_CACHE, Query, sizeof *Query, RCE, sizeof *RCE, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_88); // printf("bad index or address\n");
exit(1); }
RCE->Query = *Query; return RCE; }
void ForEachDestination(void (*func)(IPV6_INFO_ROUTE_CACHE *)) { IPV6_QUERY_ROUTE_CACHE Query, NextQuery; IPV6_INFO_ROUTE_CACHE RCE; u_int BytesReturned;
NextQuery.IF.Index = 0;
for (;;) { Query = NextQuery;
if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_ROUTE_CACHE, &Query, sizeof Query, &RCE, sizeof RCE, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_89, Query.IF.Index); // printf("bad index %u\n", Query.IF.Index);
exit(1); }
NextQuery = RCE.Query;
if (Query.IF.Index != 0) {
RCE.Query = Query; (*func)(&RCE); }
if (NextQuery.IF.Index == 0) break; } }
void PrintRouteCacheEntry(IPV6_INFO_ROUTE_CACHE *RCE) { NlsPutMsg(STDOUT, IPV6_MESSAGE_90, FormatIPv6Address(&RCE->Query.Address)); // printf("%s via ", FormatIPv6Address(&RCE->Query.Address));
NlsPutMsg(STDOUT, IPV6_MESSAGE_91, RCE->NextHopInterface, FormatIPv6Address(&RCE->NextHopAddress)); // printf("%u/%s", RCE->NextHopInterface,
// FormatIPv6Address(&RCE->NextHopAddress));
if (! RCE->Valid) NlsPutMsg(STDOUT, IPV6_MESSAGE_92); // printf(" (stale)");
switch (RCE->Type) { case RCE_TYPE_COMPUTED: break; case RCE_TYPE_REDIRECT: NlsPutMsg(STDOUT, IPV6_MESSAGE_93); // printf(" (redirect)");
break; default: NlsPutMsg(STDOUT, IPV6_MESSAGE_94, RCE->Type); // printf(" (unknown type %u)", RCE->Type);
break; }
switch (RCE->Flags) { case RCE_FLAG_CONSTRAINED: NlsPutMsg(STDOUT, IPV6_MESSAGE_95); // printf(" (interface-specific)\n");
break; case RCE_FLAG_CONSTRAINED_SCOPEID: NlsPutMsg(STDOUT, IPV6_MESSAGE_96); // printf(" (zone-specific)\n");
break; case 0: NlsPutMsg(STDOUT, IPV6_MESSAGE_36); // printf("\n");
break; default: NlsPutMsg(STDOUT, IPV6_MESSAGE_97, RCE->Flags); // printf(" (flags 0x%x)\n", RCE->Flags);
}
NlsPutMsg(STDOUT, IPV6_MESSAGE_98, RCE->Query.IF.Index, FormatIPv6Address(&RCE->SourceAddress)); // printf(" src %u/%s\n",
// RCE->Query.IF.Index,
// FormatIPv6Address(&RCE->SourceAddress));
if (RCE->PathMTU == 0) NlsPutMsg(STDOUT, IPV6_MESSAGE_99, IPv6_MINIMUM_MTU); // printf(" PMTU %u-", IPv6_MINIMUM_MTU);
else NlsPutMsg(STDOUT, IPV6_MESSAGE_100, RCE->PathMTU); // printf(" PMTU %u", RCE->PathMTU);
if (RCE->PMTUProbeTimer != INFINITE_LIFETIME) NlsPutMsg(STDOUT, IPV6_MESSAGE_101, RCE->PMTUProbeTimer/1000); // printf(" (%u seconds until PMTU probe)\n", RCE->PMTUProbeTimer/1000);
else NlsPutMsg(STDOUT, IPV6_MESSAGE_36); // printf("\n");
if ((RCE->ICMPLastError != 0) && (RCE->ICMPLastError < 10*60*1000)) NlsPutMsg(STDOUT, IPV6_MESSAGE_102, RCE->ICMPLastError/1000); // printf(" %d seconds since ICMP error\n", RCE->ICMPLastError/1000);
if ((RCE->BindingSeqNumber != 0) || (RCE->BindingLifetime != 0) || ! IN6_ADDR_EQUAL(&RCE->CareOfAddress, &in6addr_any)) NlsPutMsg(STDOUT, IPV6_MESSAGE_103, FormatIPv6Address(&RCE->CareOfAddress), RCE->BindingSeqNumber, RCE->BindingLifetime); // printf(" careof %s seq %u life %us\n",
// FormatIPv6Address(&RCE->CareOfAddress),
// RCE->BindingSeqNumber,
// RCE->BindingLifetime);
}
void QueryRouteCache(int argc, char *argv[]) { if (argc == 0) { ForEachDestination(PrintRouteCacheEntry); } else if (argc == 2) { IPV6_QUERY_ROUTE_CACHE Query; IPV6_INFO_ROUTE_CACHE *RCE;
if (! GetInterface(argv[0], &Query.IF)) usage();
if (! GetAddress(argv[1], &Query.Address)) usage();
RCE = GetRouteCacheEntry(&Query); PrintRouteCacheEntry(RCE); free(RCE); } else { usage(); } }
void ForEachRoute(void (*func)(IPV6_INFO_ROUTE_TABLE *)) { IPV6_QUERY_ROUTE_TABLE Query, NextQuery; IPV6_INFO_ROUTE_TABLE RTE; u_int BytesReturned;
NextQuery.Neighbor.IF.Index = 0;
for (;;) { Query = NextQuery;
if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_ROUTE_TABLE, &Query, sizeof Query, &RTE, sizeof RTE, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_104, Query.Neighbor.IF.Index); // printf("bad index %u\n", Query.Neighbor.IF.Index);
exit(1); }
NextQuery = RTE.Next;
if (Query.Neighbor.IF.Index != 0) {
RTE.This = Query; (*func)(&RTE); }
if (NextQuery.Neighbor.IF.Index == 0) break; } }
void ForEachPersistentRoute(IPV6_INFO_INTERFACE *IF, void (*func)(IPV6_INFO_ROUTE_TABLE *)) { IPV6_PERSISTENT_QUERY_ROUTE_TABLE Query; IPV6_INFO_ROUTE_TABLE RTE; u_int BytesReturned;
Query.IF.RegistryIndex = (u_int) -1; Query.IF.Guid = IF->This.Guid;
for (Query.RegistryIndex = 0;; Query.RegistryIndex++) {
if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_QUERY_ROUTE_TABLE, &Query, sizeof Query, &RTE, sizeof RTE, &BytesReturned, NULL) || (BytesReturned != sizeof RTE)) {
if (GetLastError() == ERROR_NO_MORE_ITEMS) break;
NlsPutMsg(STDOUT, IPV6_MESSAGE_104, Query.RegistryIndex); // printf("bad index %u\n", Query.RegistryIndex);
exit(1); }
(*func)(&RTE); } }
void PrintRouteTableEntry(IPV6_INFO_ROUTE_TABLE *RTE) { IPV6_INFO_INTERFACE *IF;
if (!Verbose) { //
// Suppress system routes (used for loopback).
//
if (RTE->Type == RTE_TYPE_SYSTEM) return; }
NlsPutMsg(STDOUT, IPV6_MESSAGE_105, FormatIPv6Address(&RTE->This.Prefix), RTE->This.PrefixLength, RTE->This.Neighbor.IF.Index); // printf("%s/%u -> %u",
if (! IN6_ADDR_EQUAL(&RTE->This.Neighbor.Address, &in6addr_any)) NlsPutMsg(STDOUT, IPV6_MESSAGE_106, FormatIPv6Address(&RTE->This.Neighbor.Address)); // printf("/%s", FormatIPv6Address(&RTE->This.Neighbor.Address));
IF = GetInterfaceInfo(&RTE->This.Neighbor.IF); if (IF != NULL) { if (IF->Preference != 0) { NlsPutMsg(STDOUT, IPV6_MESSAGE_107, IF->Preference, RTE->Preference, IF->Preference + RTE->Preference); // printf(" pref %uif+%u=%u ",
// IF->Preference, RTE->Preference,
// IF->Preference + RTE->Preference);
} else { NlsPutMsg(STDOUT, IPV6_MESSAGE_108, RTE->Preference); // printf(" pref %u ", RTE->Preference);
} free(IF); } else { NlsPutMsg(STDOUT, IPV6_MESSAGE_108, RTE->Preference); // printf(" pref %u ", RTE->Preference);
}
NlsPutMsg(STDOUT, IPV6_MESSAGE_109, FormatLifetimes(RTE->ValidLifetime, RTE->PreferredLifetime)); // printf("life %s",
// FormatLifetimes(RTE->ValidLifetime, RTE->PreferredLifetime));
if (RTE->Publish) NlsPutMsg(STDOUT, IPV6_MESSAGE_110); // printf(", publish");
if (RTE->Immortal) NlsPutMsg(STDOUT, IPV6_MESSAGE_111); // printf(", no aging");
if (RTE->SitePrefixLength != 0) NlsPutMsg(STDOUT, IPV6_MESSAGE_112, RTE->SitePrefixLength); // printf(", spl %u", RTE->SitePrefixLength);
NlsPutMsg(STDOUT, IPV6_MESSAGE_113); // printf(" (");
switch (RTE->Type) { case RTE_TYPE_SYSTEM: NlsPutMsg(STDOUT, IPV6_MESSAGE_114); // printf("system");
break;
case RTE_TYPE_MANUAL: NlsPutMsg(STDOUT, IPV6_MESSAGE_115); // printf("manual");
break;
case RTE_TYPE_AUTOCONF: NlsPutMsg(STDOUT, IPV6_MESSAGE_116); // printf("autoconf");
break;
case RTE_TYPE_RIP: NlsPutMsg(STDOUT, IPV6_MESSAGE_117); // printf("RIP");
break;
case RTE_TYPE_OSPF: NlsPutMsg(STDOUT, IPV6_MESSAGE_118); // printf("OSPF");
break;
case RTE_TYPE_BGP: NlsPutMsg(STDOUT, IPV6_MESSAGE_119); // printf("BGP");
break;
case RTE_TYPE_IDRP: NlsPutMsg(STDOUT, IPV6_MESSAGE_120); // printf("IDRP");
break;
case RTE_TYPE_IGRP: NlsPutMsg(STDOUT, IPV6_MESSAGE_121); // printf("IGRP");
break;
default: NlsPutMsg(STDOUT, IPV6_MESSAGE_122, RTE->Type); // printf("type %u", RTE->Type);
break; }
NlsPutMsg(STDOUT, IPV6_MESSAGE_123); // printf(")\n");
}
void PrintPersistentRouteTableEntry(IPV6_INFO_ROUTE_TABLE *RTE) { IPV6_INFO_INTERFACE *IF;
NlsPutMsg(STDOUT, IPV6_MESSAGE_PRINT_PERSISTENT_ROUTE, FormatIPv6Address(&RTE->This.Prefix), RTE->This.PrefixLength, FormatGuid(&RTE->This.Neighbor.IF.Guid)); // printf("%s/%u -> %s",
if (! IN6_ADDR_EQUAL(&RTE->This.Neighbor.Address, &in6addr_any)) NlsPutMsg(STDOUT, IPV6_MESSAGE_106, FormatIPv6Address(&RTE->This.Neighbor.Address)); // printf("/%s", FormatIPv6Address(&RTE->This.Neighbor.Address));
NlsPutMsg(STDOUT, IPV6_MESSAGE_108, RTE->Preference); // printf(" pref %u ", RTE->Preference);
NlsPutMsg(STDOUT, IPV6_MESSAGE_109, FormatLifetimes(RTE->ValidLifetime, RTE->PreferredLifetime)); // printf("life %s",
// FormatLifetimes(RTE->ValidLifetime, RTE->PreferredLifetime));
if (RTE->Publish) NlsPutMsg(STDOUT, IPV6_MESSAGE_110); // printf(", publish");
if (RTE->Immortal) NlsPutMsg(STDOUT, IPV6_MESSAGE_111); // printf(", no aging");
if (RTE->SitePrefixLength != 0) NlsPutMsg(STDOUT, IPV6_MESSAGE_112, RTE->SitePrefixLength); // printf(", spl %u", RTE->SitePrefixLength);
NlsPutMsg(STDOUT, IPV6_MESSAGE_36); // printf("\n");
}
void PrintPersistentRoutesOnInterface(IPV6_INFO_INTERFACE *IF) { ForEachPersistentRoute(IF, PrintPersistentRouteTableEntry); }
void QueryRouteTable(int argc, char *argv[]) { if (argc == 0) { if (Persistent) ForEachPersistentInterface(PrintPersistentRoutesOnInterface); else ForEachRoute(PrintRouteTableEntry); } else { usage(); } }
void UpdateRouteTable(int argc, char *argv[]) { IPV6_INFO_ROUTE_TABLE Route; u_int BytesReturned; int i;
Route.SitePrefixLength = 0; Route.ValidLifetime = INFINITE_LIFETIME; Route.PreferredLifetime = INFINITE_LIFETIME; Route.Preference = ROUTE_PREF_HIGHEST; Route.Type = RTE_TYPE_MANUAL; Route.Publish = FALSE; Route.Immortal = -1;
if (argc < 2) usage();
if (! GetNeighbor(argv[1], &Route.This.Neighbor.IF, &Route.This.Neighbor.Address)) usage();
if (! GetPrefix(argv[0], &Route.This.Prefix, &Route.This.PrefixLength)) usage();
for (i = 2; i < argc; i++) { if (!strncmp(argv[i], "lifetime", strlen(argv[i])) && (i+1 < argc)) {
if (! GetLifetimes(argv[++i], &Route.ValidLifetime, &Route.PreferredLifetime)) usage(); } else if (!strncmp(argv[i], "preference", strlen(argv[i])) && (i+1 < argc)) {
i++; if (!strncmp(argv[i], "low", strlen(argv[i]))) Route.Preference = ROUTE_PREF_LOW; else if (!strncmp(argv[i], "medium", strlen(argv[i]))) Route.Preference = ROUTE_PREF_MEDIUM; else if (!strncmp(argv[i], "high", strlen(argv[i]))) Route.Preference = ROUTE_PREF_HIGH; else if (!strncmp(argv[i], "onlink", strlen(argv[i]))) Route.Preference = ROUTE_PREF_ON_LINK; else if (!strncmp(argv[i], "loopback", strlen(argv[i]))) Route.Preference = ROUTE_PREF_LOOPBACK; else if (! GetNumber(argv[i], &Route.Preference)) usage(); } else if (!strcmp(argv[i], "spl") && (i+1 < argc)) {
if (! GetNumber(argv[++i], &Route.SitePrefixLength)) usage(); } else if (!strncmp(argv[i], "advertise", strlen(argv[i])) || !strncmp(argv[i], "publish", strlen(argv[i]))) {
Route.Publish = TRUE; } else if (!strncmp(argv[i], "immortal", strlen(argv[i])) || !strncmp(argv[i], "noaging", strlen(argv[i])) || !strcmp(argv[i], "noage")) {
Route.Immortal = TRUE; } else if (!strncmp(argv[i], "aging", strlen(argv[i])) || !strcmp(argv[i], "age")) {
Route.Immortal = FALSE; } else if (!strcmp(argv[i], "system")) {
Route.Type = RTE_TYPE_SYSTEM; } else if (!strcmp(argv[i], "manual")) {
Route.Type = RTE_TYPE_MANUAL; } else if (!strcmp(argv[i], "autoconf")) {
Route.Type = RTE_TYPE_AUTOCONF; } else if (!strcmp(argv[i], "rip")) {
Route.Type = RTE_TYPE_RIP; } else if (!strcmp(argv[i], "ospf")) {
Route.Type = RTE_TYPE_OSPF; } else if (!strcmp(argv[i], "bgp")) {
Route.Type = RTE_TYPE_BGP; } else if (!strcmp(argv[i], "idrp")) {
Route.Type = RTE_TYPE_IDRP; } else if (!strcmp(argv[i], "igrp")) {
Route.Type = RTE_TYPE_IGRP; } else usage(); }
if (Route.Immortal == -1) Route.Immortal = Route.Publish;
if (!DeviceIoControl(Handle, (Persistent ? IOCTL_IPV6_PERSISTENT_UPDATE_ROUTE_TABLE : IOCTL_IPV6_UPDATE_ROUTE_TABLE), &Route, sizeof Route, NULL, 0, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_124, GetLastError()); // printf("route update error: %x\n", GetLastError());
exit(1); } }
void UpdateAddress(int argc, char *argv[]) { IPV6_UPDATE_ADDRESS Update; u_int BytesReturned; int i; int Origin;
Update.Type = ADE_UNICAST; Update.PrefixConf = PREFIX_CONF_MANUAL; Update.InterfaceIdConf = IID_CONF_MANUAL; Update.ValidLifetime = INFINITE_LIFETIME; Update.PreferredLifetime = INFINITE_LIFETIME;
if (argc < 1) usage();
if ((strchr(argv[0], '/') == NULL) || ! GetNeighbor(argv[0], &Update.This.IF, &Update.This.Address)) usage();
for (i = 1; i < argc; i++) { if (!strncmp(argv[i], "lifetime", strlen(argv[i])) && (i+1 < argc)) {
if (! GetLifetimes(argv[++i], &Update.ValidLifetime, &Update.PreferredLifetime)) usage(); } else if (!strcmp(argv[i], "unicast")) Update.Type = ADE_UNICAST; else if (!strcmp(argv[i], "anycast")) Update.Type = ADE_ANYCAST; else if (!strcmp(argv[i], "prefixorigin") && (i+1 < argc)) {
if (! GetPrefixOrigin(argv[++i], &Origin)) usage(); Update.PrefixConf = Origin; } else if (!strcmp(argv[i], "ifidorigin") && (i+1 < argc)) {
if (! GetInterfaceIdOrigin(argv[++i], &Origin)) usage(); Update.InterfaceIdConf = Origin; } else usage(); }
if (!DeviceIoControl(Handle, (Persistent ? IOCTL_IPV6_PERSISTENT_UPDATE_ADDRESS : IOCTL_IPV6_UPDATE_ADDRESS), &Update, sizeof Update, NULL, 0, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_125, GetLastError()); // printf("address update error: %x\n", GetLastError());
exit(1); } }
void ForEachBinding(void (*func)(IPV6_INFO_BINDING_CACHE *)) { IPV6_QUERY_BINDING_CACHE Query, NextQuery; IPV6_INFO_BINDING_CACHE BCE; u_int BytesReturned;
NextQuery.HomeAddress = in6addr_any;
for (;;) { Query = NextQuery;
if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_BINDING_CACHE, &Query, sizeof Query, &BCE, sizeof BCE, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_126, FormatIPv6Address(&Query.HomeAddress)); // printf("bad home address %s\n",
// FormatIPv6Address(&Query.HomeAddress));
exit(1); }
NextQuery = BCE.Query;
if (!IN6_ADDR_EQUAL(&Query.HomeAddress, &in6addr_any)) { BCE.Query = Query; (*func)(&BCE); }
if (IN6_ADDR_EQUAL(&NextQuery.HomeAddress, &in6addr_any)) break; } }
void PrintBindingCacheEntry(IPV6_INFO_BINDING_CACHE *BCE) { NlsPutMsg(STDOUT, IPV6_MESSAGE_127, FormatIPv6Address(&BCE->HomeAddress)); // printf("home: %s\n", FormatIPv6Address(&BCE->HomeAddress));
NlsPutMsg(STDOUT, IPV6_MESSAGE_128, FormatIPv6Address(&BCE->CareOfAddress)); // printf(" c/o: %s\n", FormatIPv6Address(&BCE->CareOfAddress));
NlsPutMsg(STDOUT, IPV6_MESSAGE_129, BCE->BindingSeqNumber, BCE->BindingLifetime); // printf(" seq: %u Lifetime: %us\n\n",
// BCE->BindingSeqNumber, BCE->BindingLifetime);
}
void QueryBindingCache(int argc, char *argv[]) { if (argc == 0) { ForEachBinding(PrintBindingCacheEntry); } else { usage(); } }
void FlushNeighborCacheForInterface(IPV6_INFO_INTERFACE *IF) { IPV6_QUERY_NEIGHBOR_CACHE Query; u_int BytesReturned;
Query.IF = IF->This; Query.Address = in6addr_any;
if (!DeviceIoControl(Handle, IOCTL_IPV6_FLUSH_NEIGHBOR_CACHE, &Query, sizeof Query, NULL, 0, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_130, GetLastError()); // printf("flush neighbor cache error: %x\n", GetLastError());
exit(1); } }
void FlushNeighborCache(int argc, char *argv[]) { //
// Rather than put code in the kernel ioctl to iterate
// over the interfaces, we do it here in user space.
//
if (argc == 0) { ForEachInterface(FlushNeighborCacheForInterface); } else { IPV6_QUERY_NEIGHBOR_CACHE Query; u_int BytesReturned;
Query.IF.Index = 0; Query.Address = in6addr_any;
switch (argc) { case 2: if (! GetAddress(argv[1], &Query.Address)) usage(); // fall-through
case 1: if (! GetInterface(argv[0], &Query.IF)) usage(); // fall-through
case 0: break;
default: usage(); }
if (!DeviceIoControl(Handle, IOCTL_IPV6_FLUSH_NEIGHBOR_CACHE, &Query, sizeof Query, NULL, 0, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_130, GetLastError()); // printf("flush neighbor cache error: %x\n", GetLastError());
exit(1); } } }
void FlushRouteCache(int argc, char *argv[]) { IPV6_QUERY_ROUTE_CACHE Query; u_int BytesReturned;
Query.IF.Index = (u_int)-1; Query.Address = in6addr_any;
switch (argc) { case 2: if (! GetAddress(argv[1], &Query.Address)) usage(); // fall-through
case 1: if (! GetInterface(argv[0], &Query.IF)) usage(); // fall-through
case 0: break;
default: usage(); }
if (!DeviceIoControl(Handle, IOCTL_IPV6_FLUSH_ROUTE_CACHE, &Query, sizeof Query, NULL, 0, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_131, GetLastError()); // printf("flush route cache error: %x\n", GetLastError());
exit(1); } }
void ForEachSitePrefix(void (*func)(IPV6_INFO_SITE_PREFIX *)) { IPV6_QUERY_SITE_PREFIX Query, NextQuery; IPV6_INFO_SITE_PREFIX SPE; u_int BytesReturned;
NextQuery.IF.Index = 0;
for (;;) { Query = NextQuery;
if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_SITE_PREFIX, &Query, sizeof Query, &SPE, sizeof SPE, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_132, Query.IF.Index); // printf("bad index %u\n", Query.IF.Index);
exit(1); }
NextQuery = SPE.Query;
if (Query.IF.Index != 0) {
SPE.Query = Query; (*func)(&SPE); }
if (NextQuery.IF.Index == 0) break; } }
void PrintSitePrefix(IPV6_INFO_SITE_PREFIX *SPE) { NlsPutMsg(STDOUT, IPV6_MESSAGE_133, FormatIPv6Address(&SPE->Query.Prefix), SPE->Query.PrefixLength, SPE->Query.IF.Index, FormatLifetimes(SPE->ValidLifetime, SPE->ValidLifetime)); // printf("%s/%u -> %u (life %s)\n",
// FormatIPv6Address(&SPE->Query.Prefix),
// SPE->Query.PrefixLength,
// SPE->Query.IF.Index,
// FormatLifetimes(SPE->ValidLifetime, SPE->ValidLifetime));
}
void QuerySitePrefixTable(int argc, char *argv[]) { if (argc == 0) { ForEachSitePrefix(PrintSitePrefix); } else { usage(); } }
void UpdateSitePrefixTable(int argc, char *argv[]) { IPV6_INFO_SITE_PREFIX SitePrefix; u_int BytesReturned; int i;
SitePrefix.ValidLifetime = INFINITE_LIFETIME;
if (argc < 2) usage();
if (! GetInterface(argv[1], &SitePrefix.Query.IF)) usage();
if (! GetPrefix(argv[0], &SitePrefix.Query.Prefix, &SitePrefix.Query.PrefixLength)) usage();
for (i = 2; i < argc; i++) { if (!strncmp(argv[i], "lifetime", strlen(argv[i])) && (i+1 < argc)) {
if (! GetLifetimes(argv[++i], &SitePrefix.ValidLifetime, NULL)) usage(); } else usage(); }
if (!DeviceIoControl(Handle, IOCTL_IPV6_UPDATE_SITE_PREFIX, &SitePrefix, sizeof SitePrefix, NULL, 0, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_134, GetLastError()); // printf("site prefix update error: %x\n", GetLastError());
exit(1); } }
void QueryGlobalParameters(int argc, char *argv[]) { IPV6_GLOBAL_PARAMETERS Params; u_int BytesReturned;
if (argc != 0) usage();
if (!DeviceIoControl(Handle, (Persistent ? IOCTL_IPV6_PERSISTENT_QUERY_GLOBAL_PARAMETERS : IOCTL_IPV6_QUERY_GLOBAL_PARAMETERS), NULL, 0, &Params, sizeof Params, &BytesReturned, NULL) || (BytesReturned != sizeof Params)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_135, GetLastError()); // printf("query global params error: %x\n", GetLastError());
exit(1); }
if (Params.DefaultCurHopLimit != (u_int) -1) { NlsPutMsg(STDOUT, IPV6_MESSAGE_136, Params.DefaultCurHopLimit); // printf("DefaultCurHopLimit = %u\n", Params.DefaultCurHopLimit);
}
if (Params.UseTemporaryAddresses != (u_int) -1) { switch (Params.UseTemporaryAddresses) { case USE_TEMP_NO: NlsPutMsg(STDOUT, IPV6_MESSAGE_137); // printf("UseTemporaryAddresses = no\n");
break; case USE_TEMP_YES: NlsPutMsg(STDOUT, IPV6_MESSAGE_138); // printf("UseTemporaryAddresses = yes\n");
break; case USE_TEMP_ALWAYS: NlsPutMsg(STDOUT, IPV6_MESSAGE_139); // printf("UseTemporaryAddresses = yes, new random interface id for every address\n");
break; case USE_TEMP_COUNTER: NlsPutMsg(STDOUT, IPV6_MESSAGE_140); // printf("UseTemporaryAddresses = yes, incrementing interface ids\n");
break; default: NlsPutMsg(STDOUT, IPV6_MESSAGE_141, Params.UseTemporaryAddresses); // printf("UseTemporaryAddresses = %u\n", Params.UseTemporaryAddresses);
break; } }
if (Params.MaxTempDADAttempts != (u_int) -1) { NlsPutMsg(STDOUT, IPV6_MESSAGE_142, Params.MaxTempDADAttempts); // printf("MaxTempDADAttempts = %u\n", Params.MaxTempDADAttempts);
}
if ((Params.MaxTempValidLifetime != (u_int) -1) || (Params.MaxTempPreferredLifetime != (u_int) -1)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_143, FormatLifetimes(Params.MaxTempValidLifetime, Params.MaxTempPreferredLifetime)); // printf("MaxTempLifetime = %s\n",
// FormatLifetimes(Params.MaxTempValidLifetime,
// Params.MaxTempPreferredLifetime));
}
if (Params.TempRegenerateTime != (u_int) -1) { NlsPutMsg(STDOUT, IPV6_MESSAGE_144, Params.TempRegenerateTime); // printf("TempRegenerateTime = %us\n", Params.TempRegenerateTime);
}
if (Params.MaxTempRandomTime != (u_int) -1) { NlsPutMsg(STDOUT, IPV6_MESSAGE_145, FormatLifetime(Params.MaxTempRandomTime)); // printf("MaxTempRandomTime = %s\n",
// FormatLifetime(Params.MaxTempRandomTime));
}
if (! Persistent) { NlsPutMsg(STDOUT, IPV6_MESSAGE_146, FormatLifetime(Params.TempRandomTime)); // printf("TempRandomTime = %s\n",
// FormatLifetime(Params.TempRandomTime));
}
if (Params.NeighborCacheLimit != (u_int) -1) { NlsPutMsg(STDOUT, IPV6_MESSAGE_147, Params.NeighborCacheLimit); // printf("NeighborCacheLimit = %u\n", Params.NeighborCacheLimit);
}
if (Params.RouteCacheLimit != (u_int) -1) { NlsPutMsg(STDOUT, IPV6_MESSAGE_148, Params.RouteCacheLimit); // printf("RouteCacheLimit = %u\n", Params.RouteCacheLimit);
}
if (Params.BindingCacheLimit != (u_int) -1) { NlsPutMsg(STDOUT, IPV6_MESSAGE_BCL_DISPLAY, Params.BindingCacheLimit); // printf("BindingCacheLimit = %u\n", Params.BindingCacheLimit);
}
if (Params.ReassemblyLimit != (u_int) -1) { NlsPutMsg(STDOUT, IPV6_MESSAGE_REASS_LIMIT_DISPLAY, Params.ReassemblyLimit); // printf("ReassemblyLimit = %u\n", Params.ReassemblyLimit);
}
if (Params.MobilitySecurity != -1) { if (Params.MobilitySecurity) { NlsPutMsg(STDOUT, IPV6_MESSAGE_MOBILITY_SECURITY_ON); // printf("MobilitySecurity = on\n");
} else { NlsPutMsg(STDOUT, IPV6_MESSAGE_MOBILITY_SECURITY_OFF); // printf("MobilitySecurity = off\n");
} }
if (Params.MobileIPv6Mode != (u_int) -1) { NlsPutMsg(STDOUT, MIPV6_MESSAGE_MODE); // printf("MobileIPv6Mode =");
if (Params.MobileIPv6Mode & MOBILE_MOBILE_NODE) { NlsPutMsg(STDOUT, MIPV6_MESSAGE_MODE_MN); // printf(" MN");
} if (Params.MobileIPv6Mode & MOBILE_HOME_AGENT) { NlsPutMsg(STDOUT, MIPV6_MESSAGE_MODE_HA); // printf(" HA");
} if (Params.MobileIPv6Mode & MOBILE_CORRESPONDENT) { NlsPutMsg(STDOUT, MIPV6_MESSAGE_MODE_CN); // printf(" CN");
} NlsPutMsg(STDOUT, IPV6_MESSAGE_36); // printf("\n");
} }
void UpdateGlobalParameters(int argc, char *argv[]) { IPV6_GLOBAL_PARAMETERS Params; u_int BytesReturned; int i;
IPV6_INIT_GLOBAL_PARAMETERS(&Params);
for (i = 0; i < argc; i++) { if (!strcmp(argv[i], "DefaultCurHopLimit") && (i+1 < argc)) { if (! GetNumber(argv[++i], &Params.DefaultCurHopLimit)) goto usage; } else if (!strcmp(argv[i], "UseTemporaryAddresses") && (i+1 < argc)) { if (!strncmp(argv[++i], "no", strlen(argv[i]))) Params.UseTemporaryAddresses = USE_TEMP_NO; else if (!strncmp(argv[i], "yes", strlen(argv[i]))) Params.UseTemporaryAddresses = USE_TEMP_YES; else if (!strncmp(argv[i], "always", strlen(argv[i]))) Params.UseTemporaryAddresses = USE_TEMP_ALWAYS; else if (!strncmp(argv[i], "counter", strlen(argv[i]))) Params.UseTemporaryAddresses = USE_TEMP_COUNTER; else goto usage; } else if (!strcmp(argv[i], "MaxTempDADAttempts") && (i+1 < argc)) { if (! GetNumber(argv[++i], &Params.MaxTempDADAttempts)) goto usage; } else if (!strcmp(argv[i], "MaxTempLifetime") && (i+1 < argc)) { if (! GetLifetimes(argv[++i], &Params.MaxTempValidLifetime, &Params.MaxTempPreferredLifetime)) goto usage; } else if (!strcmp(argv[i], "TempRegenerateTime") && (i+1 < argc)) { if (! GetLifetime(argv[++i], &Params.TempRegenerateTime)) goto usage; } else if (!strcmp(argv[i], "MaxTempRandomTime") && (i+1 < argc)) { if (! GetLifetime(argv[++i], &Params.MaxTempRandomTime)) goto usage; } else if (!strcmp(argv[i], "TempRandomTime") && (i+1 < argc)) { if (! GetLifetime(argv[++i], &Params.TempRandomTime)) goto usage; } else if (!strcmp(argv[i], "NeighborCacheLimit") && (i+1 < argc)) { if (! GetNumber(argv[++i], &Params.NeighborCacheLimit)) goto usage; } else if (!strcmp(argv[i], "RouteCacheLimit") && (i+1 < argc)) { if (! GetNumber(argv[++i], &Params.RouteCacheLimit)) goto usage; } else if (!strcmp(argv[i], "BindingCacheLimit") && (i+1 < argc)) { if (! GetNumber(argv[++i], &Params.BindingCacheLimit)) goto usage; } else if (!strcmp(argv[i], "ReassemblyLimit") && (i+1 < argc)) { if (! GetNumber(argv[++i], &Params.ReassemblyLimit)) goto usage; } else if (!strcmp(argv[i], "MobilitySecurity") && (i+1 < argc)) { if (!strncmp(argv[++i], "on", strlen(argv[i]))) Params.MobilitySecurity = TRUE; else if (!strncmp(argv[i], "off", strlen(argv[i]))) Params.MobilitySecurity = FALSE; else if (!strncmp(argv[i], "yes", strlen(argv[i]))) Params.MobilitySecurity = TRUE; else if (!strncmp(argv[i], "no", strlen(argv[i]))) Params.MobilitySecurity = FALSE; else goto usage; } else if (!strcmp(argv[i], "MobileIPv6Mode")) { Params.MobileIPv6Mode = 0; while (++i < argc) { if (!strncmp(argv[i], "CN", strlen(argv[i]))) Params.MobileIPv6Mode |= MOBILE_CORRESPONDENT; else if (!strncmp(argv[i], "MN", strlen(argv[i]))) Params.MobileIPv6Mode |= MOBILE_MOBILE_NODE; else if (!strncmp(argv[i], "HA", strlen(argv[i]))) Params.MobileIPv6Mode |= MOBILE_HOME_AGENT; else break; } i--; //
// Until we have full mobility support, only allow CN.
//
if (Params.MobileIPv6Mode &~ MOBILE_CORRESPONDENT) { // printf("MobileIPv6Modes MN and HA currently unsupported\n");
NlsPutMsg(STDOUT, MIPV6_MESSAGE_UNSUPPORTED_MODE); exit(1); } //
// Disallow nonsensical combinations.
//
if ((Params.MobileIPv6Mode & MOBILE_MOBILE_NODE) && (Params.MobileIPv6Mode & MOBILE_HOME_AGENT)) { // printf("invalid MobileIPv6Mode combination (HA and MN).\n");
NlsPutMsg(STDOUT, MIPV6_MESSAGE_INVALID_MODE_COMBINATION1); exit(1); } if ((Params.MobileIPv6Mode & MOBILE_HOME_AGENT) && !(Params.MobileIPv6Mode & MOBILE_CORRESPONDENT)) { // printf("invalid MobileIPv6Mode combination (HA and not CN).\n");
NlsPutMsg(STDOUT, MIPV6_MESSAGE_INVALID_MODE_COMBINATION2); exit(1); } } else { usage: NlsPutMsg(STDOUT, IPV6_MESSAGE_149); // printf("usage: ipv6 gpu [parameter value] ...\n");
// printf(" ipv6 gpu DefaultCurHopLimit hops\n");
// printf(" ipv6 gpu UseTemporaryAddresses [yes|no|always|counter]\n");
// printf(" ipv6 gpu MaxTempDADAttempts number\n");
// printf(" ipv6 gpu MaxTempLifetime valid[/preferred]\n");
// printf(" ipv6 gpu TempRegenerateTime time\n");
// printf(" ipv6 gpu MaxTempRandomTime time\n");
// printf(" ipv6 gpu TempRandomTime time\n");
// printf(" ipv6 gpu NeighborCacheLimit number\n");
// printf(" ipv6 gpu RouteCacheLimit number\n");
// printf(" ipv6 gpu BindingCacheLimit number\n");
// printf(" ipv6 gpu ReassemblyLimit number\n");
// printf(" ipv6 gpu MobilitySecurity [on|off]\n");
// printf(" ipv6 gpu MobileIPv6Mode [CN|MN|HA]*\n");
// printf("Use ipv6 -p gpu ... to make a persistent change\n");
// printf("in the registry. Many global parameter changes\n");
// printf("only take effect after restarting the stack.\n");
// printf("MobileIPv6Modes MN and HA are currently unsupported.\n");
exit(1); } }
if (!DeviceIoControl(Handle, (Persistent ? IOCTL_IPV6_PERSISTENT_UPDATE_GLOBAL_PARAMETERS : IOCTL_IPV6_UPDATE_GLOBAL_PARAMETERS), &Params, sizeof Params, NULL, 0, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_150, GetLastError()); // printf("update global params error: %x\n", GetLastError());
exit(1); } }
void ForEachPrefixPolicy(void (*func)(IPV6_INFO_PREFIX_POLICY *)) { IPV6_QUERY_PREFIX_POLICY Query; IPV6_INFO_PREFIX_POLICY PPE; u_int BytesReturned;
Query.PrefixLength = (u_int) -1;
for (;;) { if (!DeviceIoControl(Handle, IOCTL_IPV6_QUERY_PREFIX_POLICY, &Query, sizeof Query, &PPE, sizeof PPE, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_160); // printf("bad prefix\n");
exit(1); }
if (Query.PrefixLength != (u_int) -1) {
if (BytesReturned != sizeof PPE) { NlsPutMsg(STDOUT, IPV6_MESSAGE_160); // printf("bad prefix\n");
exit(1); }
(*func)(&PPE); } else { if (BytesReturned != sizeof PPE.Next) { NlsPutMsg(STDOUT, IPV6_MESSAGE_160); // printf("bad prefix\n");
exit(1); } }
if (PPE.Next.PrefixLength == (u_int) -1) break; Query = PPE.Next; } }
void ForEachPersistentPrefixPolicy(void (*func)(IPV6_INFO_PREFIX_POLICY *)) { IPV6_PERSISTENT_QUERY_PREFIX_POLICY Query; IPV6_INFO_PREFIX_POLICY PPE; u_int BytesReturned;
for (Query.RegistryIndex = 0;; Query.RegistryIndex++) {
if (!DeviceIoControl(Handle, IOCTL_IPV6_PERSISTENT_QUERY_PREFIX_POLICY, &Query, sizeof Query, &PPE, sizeof PPE, &BytesReturned, NULL)) { if (GetLastError() == ERROR_NO_MORE_ITEMS) break;
NlsPutMsg(STDOUT, IPV6_MESSAGE_160); // printf("bad prefix\n");
exit(1); }
if (BytesReturned != sizeof PPE) { NlsPutMsg(STDOUT, IPV6_MESSAGE_160); // printf("bad prefix\n");
exit(1); }
(*func)(&PPE); } }
void PrintPrefixPolicyEntry(IPV6_INFO_PREFIX_POLICY *PPE) { NlsPutMsg(STDOUT, IPV6_MESSAGE_161, FormatIPv6Address(&PPE->This.Prefix), PPE->This.PrefixLength, PPE->Precedence, PPE->SrcLabel, PPE->DstLabel); // printf("%s/%u -> precedence %u srclabel %u dstlabel %u\n",
// FormatIPv6Address(&PPE->This.Prefix),
// PPE->This.PrefixLength,
// PPE->Precedence,
// PPE->SrcLabel,
// PPE->DstLabel);
}
void QueryPrefixPolicy(int argc, char *argv[]) { if (argc == 0) { if (Persistent) ForEachPersistentPrefixPolicy(PrintPrefixPolicyEntry); else ForEachPrefixPolicy(PrintPrefixPolicyEntry); } else { usage(); } }
void UpdatePrefixPolicy(int argc, char *argv[]) { IPV6_INFO_PREFIX_POLICY Info; u_int BytesReturned; int i;
if (argc < 1) usage();
if (! GetPrefix(argv[0], &Info.This.Prefix, &Info.This.PrefixLength)) usage();
Info.Precedence = (u_int) -1; Info.SrcLabel = (u_int) -1; Info.DstLabel = (u_int) -1;
for (i = 1; i < argc; i++) { if (!strncmp(argv[i], "precedence", strlen(argv[i])) && ((i + 1) < argc)) { if (! GetNumber(argv[++i], &Info.Precedence)) usage(); } else if ((!strncmp(argv[i], "srclabel", strlen(argv[i])) || !strcmp(argv[i], "sl") || !strcmp(argv[i], "label")) && ((i + 1) < argc)) { if (! GetNumber(argv[++i], &Info.SrcLabel)) usage(); } else if ((!strncmp(argv[i], "dstlabel", strlen(argv[i])) || !strcmp(argv[i], "dl")) && ((i + 1) < argc)) { if (! GetNumber(argv[++i], &Info.DstLabel)) usage(); } else usage(); }
if ((Info.Precedence == (u_int) -1) || (Info.SrcLabel == (u_int) -1)) usage();
if (Info.DstLabel == (u_int) -1) Info.DstLabel = Info.SrcLabel;
if (!DeviceIoControl(Handle, (Persistent ? IOCTL_IPV6_PERSISTENT_UPDATE_PREFIX_POLICY : IOCTL_IPV6_UPDATE_PREFIX_POLICY), &Info, sizeof Info, NULL, 0, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_162, GetLastError()); // printf("prefix policy create error: %x\n", GetLastError());
exit(1); } }
void DeletePrefixPolicy(int argc, char *argv[]) { IPV6_QUERY_PREFIX_POLICY Query; u_int BytesReturned;
if (argc == 1) { if (! GetPrefix(argv[0], &Query.Prefix, &Query.PrefixLength)) usage(); } else { usage(); }
if (!DeviceIoControl(Handle, (Persistent ? IOCTL_IPV6_PERSISTENT_DELETE_PREFIX_POLICY : IOCTL_IPV6_DELETE_PREFIX_POLICY), &Query, sizeof Query, NULL, 0, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_163, GetLastError()); // printf("prefix policy delete error: %x\n", GetLastError());
exit(1); } }
void ResetManualConfig(int argc, char *argv[]) { u_int BytesReturned;
if (argc != 0) usage();
if (!DeviceIoControl(Handle, (Persistent ? IOCTL_IPV6_PERSISTENT_RESET : IOCTL_IPV6_RESET), NULL, 0, NULL, 0, &BytesReturned, NULL)) { NlsPutMsg(STDOUT, IPV6_MESSAGE_RESET, GetLastError()); // printf("reset error: %x\n", GetLastError());
exit(1); } }
|