From: VMware, Inc <> Date: Fri, 12 Apr 2013 19:40:27 +0000 (-0700) Subject: Internal branch sync. Included in this change: X-Git-Tag: 2013.04.16-1098359~82 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e49e2059c803553373467b07dd4ddb5e2682550d;p=thirdparty%2Fopen-vm-tools.git Internal branch sync. Included in this change: . changes in shared code that don't affect open-vm-tools functionality Signed-off-by: Dmitry Torokhov --- diff --git a/open-vm-tools/lib/file/filePosix.c b/open-vm-tools/lib/file/filePosix.c index 2bd9e9f76..7cf5173d4 100644 --- a/open-vm-tools/lib/file/filePosix.c +++ b/open-vm-tools/lib/file/filePosix.c @@ -483,7 +483,7 @@ File_Cwd(ConstUnicode drive) // IN: free(buffer); buffer = NULL; - if (errno != ENAMETOOLONG) { + if (errno != ERANGE) { break; } @@ -572,6 +572,207 @@ FileStripFwdSlashes(ConstUnicode pathName) // IN: } +#if defined(VMX86_SERVER) +/* + *---------------------------------------------------------------------------- + * + * FileVMFSGetCanonicalPath -- + * + * Given an absolute pathname of a VM directory, return its canonical + * pathname. + * + * Canonical name for a VM directory has a special significance only for + * the case of NFS config VVols where the absolute pathname of VM directory + * could be an NFS PE based path. + * f.e. the VM directory on an NFS config VVol could have the absolute + * pathname /vmfs/volumes/nfs_pe_2/vvol36/meta_vvol36/, whereas the + * canonical name would be the one containing the VVol container name, + * f.e. /vmfs/volumes/vvol:26acd2ae55ea49c3-87dd47a44e4f327/rfc4122.d140c97a-7208-474e-95c7-a4ee6cac7f15/ + * Both pathnames refer to the same directory (using bind mount), but + * canonical pathname is important as it is used in many places to identify + * object-backed storage from regular filesystem-backed storage. + * + * It can also correctly handle cases where 'absVMDirName' is not the + * config-vvol directory but is a sub-directory inside the config-vvol + * directory. It will climb up one directory at a time looking for an + * NFS config VVol. The max number of directory components it'll check + * is MAX_SUBDIR_LEVEL. + * + * Note: + * 'absVMDirName' should not have extra slashes in the name. This will + * be true if we have gotten it from Posix_RealPath or friends. + * + * Results: + * Returns a unicode string containing the canonical pathname to use. + * For VM directories not on NFS config VVol, this will be the same as + * absVMDirName. + * Caller has to free the returned unicode string using Unicode_Free. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------------- + */ + +static Unicode +FileVMFSGetCanonicalPath(ConstUnicode absVMDirName) // IN +{ + /* + * Max directory level that we will climb looking for an NFS config VVol. + * Don't set it very high or else we will hurt the common case. + */ +#define MAX_SUBDIR_LEVEL 1 + + struct statfs statfs_buf; + VVol_IoctlArgs args; + VVolGetNFSCanonicalPathArgs *getCanonArgs = NULL; + int ctrlfd = -1; + int searchDepth = MAX_SUBDIR_LEVEL; + /* + * Directory that we are currently verifying. This starts as + * absVMDirName and then keeps climbing to the parent one level + * at a time, till we exhaust searchDepth or we get a successful + * translation, indicating that we have hit an NFS config vvol + * directory, or we run outside the NFS filesystem. + */ + Unicode currDir = NULL; + /* + * This holds the path fragment after the NFS config VVol. This will be + * non-empty only in the case when absVMDirName refers to some subdir + * inside the NFS config VVol directory. We keep collecting the path + * components as we change currDir one level at a time. + */ + Unicode dirPath = NULL; + Unicode canonPath = NULL; /* result */ + + /* + * absVMDirName should start with /vmfs/volumes/. + */ + if (!Unicode_StartsWith(absVMDirName, VCFS_MOUNT_PATH)) { + goto use_same_path; + } + + /* + * Only NFS config vvols can have a canonical name different from the + * absolute pathname provided. This will do the validity check also. + */ + if (Posix_Statfs(absVMDirName, &statfs_buf) != 0 || + (statfs_buf.f_type != NFSCLIENT_FSTYPENUM && + statfs_buf.f_type != NFS41CLIENT_FSTYPENUM)) { + goto use_same_path; + } + + /* + * The most likely reason this will fail is if the VVol control node is + * not present which means VVol module is not loaded. We can not translate + * the pathname in that case. + */ + ctrlfd = Posix_Open(VVOL_NAMESPACE_CONTROL_NODE, O_RDONLY); + if (ctrlfd < 0) { + goto use_same_path; + } + + /* + * If the user has passed a filename (instead of a dirname) we + * cannot pass it as-is to the ioctl as it works on a directory + * name. + */ + if (!File_IsDirectory(absVMDirName)) { + File_GetPathName(absVMDirName, &currDir, &dirPath); + ASSERT(currDir); + ASSERT(dirPath); + } + + /* + * VM directory is on an NFS fileystem. It could be a regular NFS filesystem + * backed storage or an NFS config VVol. We need to check. + */ + getCanonArgs = Util_SafeCalloc(1, sizeof(*getCanonArgs)); + + args.type = VVOL_GET_NFS_CANONICAL_PATH; + args.data = (uint64)(VA) getCanonArgs; + args.length = sizeof(*getCanonArgs); + + /* + * Start searching for the NFS config VVol starting from absVMDirName + * (or currDir, if absVMDirName is not a directory). + * In most case this will be the NFS config VVol directory, but we also + * support cases where absVMDirName refers to a subdir inside the NFS + * config VVol directory. + */ + do { + Unicode pathname, basename; + + Unicode_CopyBytes(getCanonArgs->absNFSPath, + currDir ? : absVMDirName, + sizeof(getCanonArgs->absNFSPath), + NULL, STRING_ENCODING_UTF8); + + if (ioctl(ctrlfd, IOCTLCMD_VMFS_VVOL, &args) == 0) { + /* + * ioctl successful. currDir refers to an NFS config VVol directory. + * getCanonArgs->canonPath contains the canonical path to use. + * This is the fastpath. + */ + break; + } else if (errno != ENOENT) { + /* + * ENOENT indicates that the kernel did not find a matching bind + * mount. In that case we try climbing up one level and test that + * for an NFS config VVol. + */ + goto use_same_path; + } + + if (searchDepth == 0) { + goto use_same_path; + } + /* + * Try the next level dir. + */ + File_GetPathName(currDir ? : absVMDirName, &pathname, &basename); + Unicode_Free(currDir); + currDir = pathname; + /* + * Update dirPath that we eventually need to append to get the full path. + */ + if (dirPath == NULL) { + dirPath = basename; + } else { + Unicode tmpDirPath = Unicode_Join(basename, DIRSEPS, dirPath, NULL); + Unicode_Free(basename); + Unicode_Free(dirPath); + dirPath = tmpDirPath; + } + /* + * If we have fallen off the NFS filesystem no need to search further, + * we can never find the config VVol. + */ + if (Posix_Statfs(currDir, &statfs_buf) != 0 || + (statfs_buf.f_type != NFSCLIENT_FSTYPENUM && + statfs_buf.f_type != NFS41CLIENT_FSTYPENUM)) { + goto use_same_path; + } + } while (searchDepth-- > 0); + + canonPath = Unicode_Format("%s%s", getCanonArgs->canonPath, dirPath ? : ""); + +done: + close(ctrlfd); + free(getCanonArgs); + Unicode_Free(currDir); + Unicode_Free(dirPath); + ASSERT(canonPath != NULL); + return canonPath; + +use_same_path: + ASSERT(canonPath == NULL); + canonPath = Unicode_Alloc(absVMDirName, STRING_ENCODING_DEFAULT); + goto done; +} +#endif + + /* *---------------------------------------------------------------------- * @@ -594,6 +795,9 @@ File_FullPath(ConstUnicode pathName) // IN: { Unicode cwd; Unicode ret; +#if defined(VMX86_SERVER) + Unicode canonPath; +#endif if ((pathName != NULL) && File_IsFullPath(pathName)) { cwd = NULL; @@ -624,7 +828,21 @@ File_FullPath(ConstUnicode pathName) // IN: Unicode_Free(cwd); +#if defined(VMX86_SERVER) + /* + * NFS config-VVols introduce a special type of in-kernel link called the + * bind mount. Posix_RealPath() doesn't resolve that. We need to resolve + * it explicitly. + * We don't want to store PE based path in any file. All configuration + * files should contain canonical path only. + */ + canonPath = FileVMFSGetCanonicalPath(ret); + Unicode_Free(ret); + + return canonPath; +#else return ret; +#endif } diff --git a/open-vm-tools/lib/file/fileTempPosix.c b/open-vm-tools/lib/file/fileTempPosix.c index 13a8caf91..e5e892191 100644 --- a/open-vm-tools/lib/file/fileTempPosix.c +++ b/open-vm-tools/lib/file/fileTempPosix.c @@ -335,13 +335,13 @@ FileFindExistingSafeTmpDir(uid_t userId, // IN: Unicode pattern; Unicode tmpDir = NULL; Unicode *fileList = NULL; - + /* * We always use the pattern PRODUCT-USER-xxxx when creating * alternative safe temp directories, so check for ones with * those names and the appropriate permissions. */ - + pattern = Unicode_Format("%s-%s-", PRODUCT_GENERIC_NAME_LOWER, userName); if (pattern == NULL) { return NULL; @@ -405,32 +405,24 @@ FileCreateSafeTmpDir(uid_t userId, // IN: char *tmpDir = NULL; while (TRUE) { - unsigned int suffix; - - /* - * We use a crypographically strong random number which is overkill - * for this purpose but makes it slightly more likely that we will - * create an unused name than if we had simply tried suffixes in - * numeric order. + /* + * We use a random number that makes it more likely that we will create + * an unused name than if we had simply tried suffixes in numeric order. */ - if (!Random_Crypto(sizeof(suffix), &suffix)) { - Warning("%s: Call to Random_Crypto failed.\n", __FUNCTION__); - break; - } - tmpDir = Str_Asprintf(NULL, "%s%s%s-%s-%u", baseTmpDir, DIRSEPS, - PRODUCT_GENERIC_NAME_LOWER, userName, suffix); - + PRODUCT_GENERIC_NAME_LOWER, userName, + FileSimpleRandom()); + if (!tmpDir) { Warning("%s: Out of memory error.\n", __FUNCTION__); break; } - + if (FileAcceptableSafeTmpDir(tmpDir, userId)) { break; } - + if (++curDirIter > MAX_DIR_ITERS) { Warning("%s: Failed to create a safe temporary directory, path " "\"%s\". The maximum number of attempts was exceeded.\n", @@ -439,7 +431,7 @@ FileCreateSafeTmpDir(uid_t userId, // IN: tmpDir = NULL; break; } - + free(tmpDir); tmpDir = NULL; } @@ -456,9 +448,12 @@ FileCreateSafeTmpDir(uid_t userId, // IN: * * Return a safe temporary directory (i.e. a temporary directory which * is not prone to symlink attacks, because it is only writable by the - * current effective user). Guaranteed to return the same directory - * every time it is called during the lifetime of the current process - * (unless that directory is deleted while the process is running). + * current effective user). + * + * Guaranteed to return the same directory every time it is + * called during the lifetime of the current process, for the + * current effective user ID. (Barring the user manually deleting + * or renaming the directory.) * * Results: * The allocated directory path on success. @@ -507,30 +502,30 @@ File_GetSafeTmpDir(Bool useConf) // IN: /* We don't have a useable temporary dir, create one. */ baseTmpDir = FileGetTmpDir(useConf); - + if (!baseTmpDir) { Warning("%s: FileGetTmpDir failed.\n", __FUNCTION__); goto exit; } - + userName = FileGetUserName(userId); - + if (!userName) { Warning("%s: FileGetUserName failed, using numeric ID " "as username instead.\n", __FUNCTION__); - + /* Fallback on just using the userId as the username. */ userName = Str_Asprintf(NULL, "uid-%d", userId); - + if (!userName) { Warning("%s: Str_Asprintf error.\n", __FUNCTION__); goto exit; } } - + tmpDir = Str_Asprintf(NULL, "%s%s%s-%s", baseTmpDir, DIRSEPS, PRODUCT_GENERIC_NAME_LOWER, userName); - + if (!tmpDir) { Warning("%s: Out of memory error.\n", __FUNCTION__); goto exit; diff --git a/open-vm-tools/lib/hgfsServer/hgfsServer.c b/open-vm-tools/lib/hgfsServer/hgfsServer.c index d43aad89e..a07383ca8 100644 --- a/open-vm-tools/lib/hgfsServer/hgfsServer.c +++ b/open-vm-tools/lib/hgfsServer/hgfsServer.c @@ -2989,7 +2989,7 @@ static void HgfsServerSessionReceive(HgfsPacket *packet, // IN: Hgfs Packet void *clientData) // IN: session info { - HgfsTransportSessionInfo *transportSession = (HgfsTransportSessionInfo *)clientData; + HgfsTransportSessionInfo *transportSession = clientData; HgfsInternalStatus status; HgfsInputParam *input = NULL; @@ -3946,7 +3946,7 @@ HgfsDisconnectSessionInt(HgfsSessionInfo *session) // IN: session context static void HgfsServerSessionDisconnect(void *clientData) // IN: session context { - HgfsTransportSessionInfo *transportSession = (HgfsTransportSessionInfo *)clientData; + HgfsTransportSessionInfo *transportSession = clientData; DblLnkLst_Links *curr, *next; LOG(8, ("%s: entered\n", __FUNCTION__)); @@ -3990,7 +3990,7 @@ HgfsServerSessionDisconnect(void *clientData) // IN: session context static void HgfsServerSessionClose(void *clientData) // IN: session context { - HgfsTransportSessionInfo *transportSession = (HgfsTransportSessionInfo *)clientData; + HgfsTransportSessionInfo *transportSession = clientData; ASSERT(transportSession); ASSERT(transportSession->state == HGFS_SESSION_STATE_CLOSED); @@ -4147,8 +4147,7 @@ void HgfsServerSessionSendComplete(HgfsPacket *packet, // IN/OUT: Hgfs packet void *clientData) // IN: session info { - HgfsTransportSessionInfo *transportSession = - (HgfsTransportSessionInfo *)clientData; + HgfsTransportSessionInfo *transportSession = clientData; if (packet->guestInitiated) { HSPU_PutMetaPacket(packet, transportSession); @@ -4425,8 +4424,7 @@ void HgfsServerSessionInvalidateObjects(void *clientData, // IN: DblLnkLst_Links *shares) // IN: List of new shares { - HgfsTransportSessionInfo *transportSession = - (HgfsTransportSessionInfo *)clientData; + HgfsTransportSessionInfo *transportSession = clientData; DblLnkLst_Links *curr; ASSERT(transportSession); @@ -4474,8 +4472,7 @@ HgfsServerSessionInvalidateObjects(void *clientData, // IN: uint32 HgfsServerSessionInvalidateInactiveSessions(void *clientData) // IN: { - HgfsTransportSessionInfo *transportSession = - (HgfsTransportSessionInfo *)clientData; + HgfsTransportSessionInfo *transportSession = clientData; uint32 numActiveSessionsLeft = 0; DblLnkLst_Links shares, *curr, *next; diff --git a/open-vm-tools/lib/hgfsServer/hgfsServerOplock.c b/open-vm-tools/lib/hgfsServer/hgfsServerOplock.c index 708b99fe9..340f138a0 100644 --- a/open-vm-tools/lib/hgfsServer/hgfsServerOplock.c +++ b/open-vm-tools/lib/hgfsServer/hgfsServerOplock.c @@ -246,7 +246,8 @@ HgfsServerOplockBreakReply(const unsigned char *packetIn, // IN: Reply packet void *clientData) // IN: From request { HgfsReplyServerLockChange *reply; - ServerLockData *lockData; + ServerLockData *lockData = clientData; + ASSERT(packetIn); ASSERT(clientData); @@ -254,7 +255,6 @@ HgfsServerOplockBreakReply(const unsigned char *packetIn, // IN: Reply packet return; } reply = (HgfsReplyServerLockChange *)packetIn; - lockData = (ServerLockData *)clientData; /* * XXX: It should be safe to ignore the status and id from the actual diff --git a/open-vm-tools/lib/include/loglevel_user.h b/open-vm-tools/lib/include/loglevel_user.h index 9fcb47f4e..340058ff6 100644 --- a/open-vm-tools/lib/include/loglevel_user.h +++ b/open-vm-tools/lib/include/loglevel_user.h @@ -250,6 +250,7 @@ LOGLEVEL_VAR(inputdevtap), \ LOGLEVEL_VAR(objlib), \ LOGLEVEL_VAR(vsanobj), \ + LOGLEVEL_VAR(vvolbe), \ LOGLEVEL_VAR(svgadevtap), \ LOGLEVEL_VAR(masReceipt), /* lib/masReceipt */ \ LOGLEVEL_VAR(serviceImpl), /* lib/serviceImpl */ \ diff --git a/open-vm-tools/lib/include/random.h b/open-vm-tools/lib/include/random.h index fe12f0638..b666819fe 100644 --- a/open-vm-tools/lib/include/random.h +++ b/open-vm-tools/lib/include/random.h @@ -29,9 +29,8 @@ #include "vm_basic_types.h" -Bool -Random_Crypto(unsigned int size, // IN - void *buffer); // OUT +Bool Random_Crypto(size_t size, + void *buffer); /* * High quality - research grade - random number generator. @@ -41,17 +40,14 @@ Random_Crypto(unsigned int size, // IN typedef struct rqContext rqContext; -rqContext * -Random_QuickSeed(uint32 seed); +rqContext *Random_QuickSeed(uint32 seed); -uint32 -Random_Quick(rqContext *context); +uint32 Random_Quick(rqContext *context); /* - * Simple multiplicative conguential RNG. + * Simple multiplicative congruential RNG. */ -int -Random_Simple(int seed); +int Random_Simple(int seed); #endif /* __RANDOM_H__ */ diff --git a/open-vm-tools/lib/include/vm_basic_defs.h b/open-vm-tools/lib/include/vm_basic_defs.h index 3c23d9f44..4713a16b1 100644 --- a/open-vm-tools/lib/include/vm_basic_defs.h +++ b/open-vm-tools/lib/include/vm_basic_defs.h @@ -368,39 +368,13 @@ void *_ReturnAddress(void); #ifdef __GNUC__ #ifndef sun -static INLINE_SINGLE_CALLER uintptr_t -GetFrameAddr(void) -{ - uintptr_t bp; -#if !(__GNUC__ == 4 && (__GNUC_MINOR__ == 0 || __GNUC_MINOR__ == 1)) - bp = (uintptr_t)__builtin_frame_address(0); -#else - /* - * We use this assembly hack due to a bug discovered in gcc 4.1.1. - * The bug was fixed in 4.2.0; assume it originated with 4.0. - * PR147638, PR554369. - */ - __asm__ __volatile__( -# if defined(VM_X86_64) - "movq %%rbp, %0\n" -# else - "movl %%ebp, %0\n" -# endif - : "=g" (bp)); -#endif - return bp; -} - - /* - * Returns the frame pointer of the calling function. - * Equivalent to __builtin_frame_address(1). + * A bug in __builtin_frame_address was discovered in gcc 4.1.1, and + * fixed in 4.2.0; assume it originated in 4.0. PR 147638 and 554369. */ -static INLINE_SINGLE_CALLER uintptr_t -GetCallerFrameAddr(void) -{ - return *(uintptr_t*)GetFrameAddr(); -} +#if !(__GNUC__ == 4 && (__GNUC_MINOR__ == 0 || __GNUC_MINOR__ == 1)) +#define GetFrameAddr() __builtin_frame_address(0) +#endif #endif // sun #endif // __GNUC__ diff --git a/open-vm-tools/lib/lock/ul.c b/open-vm-tools/lib/lock/ul.c index f4fc0c8b0..5187f8ed7 100644 --- a/open-vm-tools/lib/lock/ul.c +++ b/open-vm-tools/lib/lock/ul.c @@ -124,36 +124,11 @@ MXUserSyndrome(void) syndrome = Atomic_Read(&syndromeMem); if (syndrome == 0) { - uint32 retries = 25; - - /* - * Do not assume that the source of bits from the host OS are sane. - * Perhaps its random bits service is not working or always returns - * zero or something is misconfigured. Only perform a small number - * of retries attempting to appropriate the required bits. - */ - - do { - /* Only changes syndrome on success. No need to check for errors */ - Random_Crypto(sizeof syndrome, &syndrome); - - if (syndrome != 0) { - break; - } - } while (retries--); - - /* - * If the source was unable to provide the appropriate bits, switch - * to plan B. - */ - - if (syndrome == 0) { #if defined(_WIN32) - syndrome = GetTickCount(); + syndrome = GetTickCount(); #else - syndrome = time(NULL) & 0xFFFFFFFF; + syndrome = time(NULL) & 0xFFFFFFFF; #endif - } /* * Protect against a total failure. diff --git a/open-vm-tools/lib/misc/random.c b/open-vm-tools/lib/misc/random.c index a82fd0beb..23054c3e9 100644 --- a/open-vm-tools/lib/misc/random.c +++ b/open-vm-tools/lib/misc/random.c @@ -24,6 +24,7 @@ #include #include +#include #if defined(_WIN32) # include @@ -38,6 +39,7 @@ #include "vmware.h" #include "random.h" +#include "util.h" #if defined(_WIN32) @@ -57,17 +59,21 @@ */ static Bool -RandomBytesWin32(unsigned int size, // IN: - void *buffer) // OUT: +RandomBytesWin32(size_t size, // IN: + void *buffer) // OUT: { HCRYPTPROV csp; + if (size != (DWORD) size) { + return FALSE; + } + if (CryptAcquireContext(&csp, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) == FALSE) { return FALSE; } - if (CryptGenRandom(csp, size, buffer) == FALSE) { + if (CryptGenRandom(csp, (DWORD) size, buffer) == FALSE) { CryptReleaseContext(csp, 0); return FALSE; } @@ -95,17 +101,22 @@ RandomBytesWin32(unsigned int size, // IN: */ static Bool -RandomBytesPosix(const char *name, // IN: - unsigned int size, // IN: - void *buffer) // OUT: +RandomBytesPosix(const char *name, // IN: + size_t size, // IN: + void *buffer) // OUT: { int fd = open(name, O_RDONLY); if (fd == -1) { + Log("%s: failed to open %s: %s\n", __FUNCTION__, name, strerror(errno)); return FALSE; } - /* Although /dev/urandom does not block, it can return short reads. */ + /* + * Although /dev/urandom does not block, it can return short reads. That + * said, reads returning nothing should not happen. Just in case, track + * those any that do appear. + */ while (size > 0) { ssize_t bytesRead = read(fd, buffer, size); @@ -113,6 +124,14 @@ RandomBytesPosix(const char *name, // IN: if ((bytesRead == 0) || ((bytesRead == -1) && (errno != EINTR))) { close(fd); + if (bytesRead == 0) { + Log("%s: zero length read while reading from %s\n", + __FUNCTION__, name); + } else { + Log("%s: %"FMTSZ"u byte read failed while reading from %s: %s\n", + __FUNCTION__, size, name, strerror(errno)); + } + return FALSE; } @@ -123,7 +142,7 @@ RandomBytesPosix(const char *name, // IN: } if (close(fd) == -1) { - return FALSE; + Log("%s: failed to close %s: %s\n", __FUNCTION__, name, strerror(errno)); } return TRUE; @@ -155,8 +174,8 @@ RandomBytesPosix(const char *name, // IN: */ Bool -Random_Crypto(unsigned int size, // IN: - void *buffer) // OUT: +Random_Crypto(size_t size, // IN: + void *buffer) // OUT: { #if defined(_WIN32) return RandomBytesWin32(size, buffer); @@ -220,7 +239,7 @@ Random_QuickSeed(uint32 seed) // IN: 0x512C0C03, 0xEA857CCD, 0x4CC1D30F, 0x8891A8A1, 0xA6B7AADB }; - rs = (struct rqContext *) malloc(sizeof *rs); + rs = (struct rqContext *) Util_SafeMalloc(sizeof *rs); if (rs != NULL) { uint32 i; diff --git a/open-vm-tools/modules/shared/vmxnet/eth_public.h b/open-vm-tools/modules/shared/vmxnet/eth_public.h index db57294c4..b04b20359 100644 --- a/open-vm-tools/modules/shared/vmxnet/eth_public.h +++ b/open-vm-tools/modules/shared/vmxnet/eth_public.h @@ -235,6 +235,7 @@ enum { ETH_VMWARE_FRAME_TYPE_BEACON = 1, ETH_VMWARE_FRAME_TYPE_COLOR = 2, ETH_VMWARE_FRAME_TYPE_ECHO = 3, + ETH_VMWARE_FRAME_TYPE_LLC = 4, // XXX: Just re-use COLOR? }; typedef diff --git a/open-vm-tools/modules/shared/vmxnet/vmnet_def.h b/open-vm-tools/modules/shared/vmxnet/vmnet_def.h index dfce5b899..f06114b0d 100644 --- a/open-vm-tools/modules/shared/vmxnet/vmnet_def.h +++ b/open-vm-tools/modules/shared/vmxnet/vmnet_def.h @@ -105,6 +105,7 @@ #define VMNET_CAP_SELF_TEST 0x100000000000UL /* Self-test capability */ #define VMNET_CAP_PAUSE_PARAMS 0x200000000000UL /* Pause frame parameter adjusting */ #define VMNET_CAP_RESTART_NEG 0x400000000000UL /* Ability to restart negotiation of link speed/duplexity */ +#define VMNET_CAP_LRO 0x800000000000UL /* Hardware supported LRO */ #define VMNET_CAP_LEGACY 0x8000000000000000UL /* Uplink is compatible with vmklinux drivers */ #endif // _VMNET_DEF_H_