~n-muench/ubuntu/precise/open-vm-tools/open-vm-tools.raring-precise.backport

« back to all changes in this revision

Viewing changes to lib/hgfsServer/hgfsServer.c

  • Committer: Package Import Robot
  • Author(s): Nate Muench
  • Date: 2012-01-23 16:09:45 UTC
  • mfrom: (1.4.6) (2.4.26 sid)
  • Revision ID: package-import@ubuntu.com-20120123160945-b6s0r1vkcovucpf3
Tags: 2011.12.20-562307-0ubuntu1
* Merge latest upstream git tag. Fixes building on Precise
  (LP: #898289, LP: #905612)

* Items merged from Debian unstable:
  - debian/control:
    + open-vm-tools recommends open-vm-dkms. (LP: #598933)
    + open-vm-tools now suggests open-vm-toolbox. (LP: #604998)
  (From 2011.08.21-471295-1 release)
  - Updating maintainer and uploaders fields.
  - Removing vcs fields.
  - Removing references to Daniel's old email address.
  - Updating years in copyright file.
  - Updating to standards version 3.9.2.
  - Updating to debhelper version 8.
  - Switching to source format 3.0 (quilt).
  - Removing manual chrpath setting.
  - Removing exclusion from plugins from debhelper shlibs.
  - Rediffing kvers.patch.
  (From 2011.09.23-491607-1 release)
  - Marking binary architecture-dependend packages as linux and kfreebsd
  only.
  - Removing liburiparser-dev from build-depends as upstream dropped
  unity support.
  - Building with libproc-dev on amd64 again.
  - Dropping disabling of dnet support.
  (From 2011.09.23-491607-2 release)
  - Adding doxygen to build-depends for api documentation.
  - Adding libcunit1-dev to build-depends for test suites.
  - Minimizing rules file.
  - Adding open-vm-tools-dev package, containing only the api
    documentation for now.
  (From 2011.09.23-491607-3 release)
  - Sorting overrides in rules alphabetically.
  - Compacting copyright file.
  - Adding udev rule to set timeout for vmware scsi devices
  (From 2011.12.20-562307-1 release)
  - Adding patch to correct typo in upstreams dkms configuration

* Remaining Changes:
  - Remove Stable part of version numbering.
  - debian folder:
    + Re-added open-vm-dkms.postinst & open-vm-dkms.prerm.
      * Allows dkms modules to compile upon installation.
  - debian/control:
    + Re-add open-vm-source and make into a transitional package
      for open-vm-toolbox.
    + Return dependancies that were moved to open-vm-tools back to
      open-vm-toolbox.
  - debian/rules and debian/open-vm-toolbox.lintian-overrides:
    + Make vmware-user-suid-wrapper suid-root
  - debian/rules:
    + Added CFLAGS field with -Wno-deprecated-declarations
      * Will suppress issues with glib 2.31 or later.
    + Add line to copy vmware-xdg-detect-de into place.
    + Install vmware-user.desktop through toolbox package.
  - debian/open-vm-tools.init:
    + Re-add 'modprobe [-r] vmblock'.
    + Add 'modprobe [-r] vmxnet'.
      * Incase it's not loaded during boot.
    + Remove and re-add pcnet32 module
      * Will be done before (remove) and after (readd) vmxnet module
        is added.
      * If vmxnet doesn't exist (aka modules fail to build), pcnet32 can be
        still used for network connectivity.
      * Workaround until a better fix can be done.
  - Re-add gnome-session to debian/local/xautostart.conf
  - Manpages removed (from debian/manpages):
    + vmmemctl.9
    + vmxnet3.9
    + Remove references to manpages that have been removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
41
41
#include "hgfsEscape.h"
42
42
#include "codeset.h"
43
43
#include "config.h"
 
44
#include "dbllnklst.h"
44
45
#include "file.h"
45
46
#include "util.h"
46
47
#include "wiper.h"
87
88
#endif
88
89
 
89
90
#define HGFS_ASSERT_INPUT(input) ASSERT(input && input->packet && input->metaPacket && \
90
 
                                        input->session && \
 
91
                                        ((!input->v4header && input->session) || \
 
92
                                         (input->v4header && \
 
93
                                          (input->op == HGFS_OP_CREATE_SESSION_V4 || input->session))) && \
91
94
                                        (!input->payloadSize || input->payload))
92
95
 
93
96
/*
186
189
static void HgfsServerSessionClose(void *clientData);
187
190
static void HgfsServerSessionInvalidateObjects(void *clientData,
188
191
                                               DblLnkLst_Links *shares);
 
192
static uint32 HgfsServerSessionInvalidateInactiveSessions(void *clientData);
189
193
static void HgfsServerSessionSendComplete(HgfsPacket *packet, void *clientData);
190
194
 
191
195
/*
197
201
   HgfsServerSessionClose,
198
202
   HgfsServerSessionReceive,
199
203
   HgfsServerSessionInvalidateObjects,
 
204
   HgfsServerSessionInvalidateInactiveSessions,
200
205
   HgfsServerSessionSendComplete,
201
206
};
202
207
 
222
227
   Bool markedForDeletion;
223
228
} HgfsSharedFolderProperties;
224
229
 
 
230
static void HgfsServerTransportRemoveSessionFromList(HgfsTransportSessionInfo *transportSession,
 
231
                                                     HgfsSessionInfo *sessionInfo);
 
232
 
225
233
/*
226
234
 *    Limit payload to 16M + header.
227
235
 *    This limit ensures that list of shared pages fits into VMCI datagram.
230
238
#define MAX_SERVER_PACKET_SIZE_V4         (0x1000000 + sizeof(HgfsHeader))
231
239
 
232
240
/* Local functions. */
233
 
 
234
241
static void HgfsInvalidateSessionObjects(DblLnkLst_Links *shares,
235
242
                                         HgfsSessionInfo *session);
236
243
static Bool HgfsAddToCacheInternal(HgfsHandle handle,
361
368
HgfsServerSessionPut(HgfsSessionInfo *session)   // IN: session context
362
369
{
363
370
   ASSERT(session);
 
371
 
364
372
   if (Atomic_FetchAndDec(&session->refCount) == 1) {
365
373
      HgfsServerExitSessionInternal(session);
366
374
   }
368
376
 
369
377
 
370
378
/*
 
379
 *----------------------------------------------------------------------------
 
380
 *
 
381
 * HgfsServerTransportSessionGet --
 
382
 *
 
383
 *      Increment transport session reference count.
 
384
 *
 
385
 * Results:
 
386
 *      None.
 
387
 *
 
388
 * Side effects:
 
389
 *      None.
 
390
 *
 
391
 *----------------------------------------------------------------------------
 
392
 */
 
393
 
 
394
void
 
395
HgfsServerTransportSessionGet(HgfsTransportSessionInfo *transportSession)   // IN: session context
 
396
{
 
397
   ASSERT(transportSession);
 
398
   Atomic_Inc(&transportSession->refCount);
 
399
}
 
400
 
 
401
 
 
402
/*
 
403
 *----------------------------------------------------------------------------
 
404
 *
 
405
 * HgfsServerTransportSessionPut --
 
406
 *
 
407
 *      Decrement transport session reference count.
 
408
 *
 
409
 *      Free session info data if no reference.
 
410
 *
 
411
 * Results:
 
412
 *      None.
 
413
 *
 
414
 * Side effects:
 
415
 *      None.
 
416
 *
 
417
 *----------------------------------------------------------------------------
 
418
 */
 
419
 
 
420
static void
 
421
HgfsServerTransportSessionPut(HgfsTransportSessionInfo *transportSession)   // IN: transport session context
 
422
{
 
423
   ASSERT(transportSession);
 
424
   if (Atomic_FetchAndDec(&transportSession->refCount) == 1) {
 
425
      DblLnkLst_Links *curr, *next;
 
426
 
 
427
      MXUser_AcquireExclLock(transportSession->sessionArrayLock);
 
428
 
 
429
      DblLnkLst_ForEachSafe(curr, next,  &transportSession->sessionArray) {
 
430
         HgfsSessionInfo *session = DblLnkLst_Container(curr, HgfsSessionInfo, links);
 
431
         HgfsServerTransportRemoveSessionFromList(transportSession, session);
 
432
         HgfsServerSessionPut(session);
 
433
      }
 
434
 
 
435
      MXUser_ReleaseExclLock(transportSession->sessionArrayLock);
 
436
   }
 
437
}
 
438
 
 
439
 
 
440
/*
371
441
 *-----------------------------------------------------------------------------
372
442
 *
373
443
 * HgfsServerInitHandleCounter --
2854
2924
   size_t replyPacketSize;
2855
2925
   size_t replySize;
2856
2926
 
2857
 
   HGFS_ASSERT_INPUT(input);
 
2927
   if (HGFS_ERROR_SUCCESS == status) {
 
2928
      HGFS_ASSERT_INPUT(input);
 
2929
   } else {
 
2930
      ASSERT(input);
 
2931
   }
2858
2932
 
2859
2933
   if (input->v4header) {
2860
2934
      HgfsHeader *header;
2861
2935
      replySize = sizeof *header + replyPayloadSize;
2862
2936
      replyPacketSize = replySize;
2863
2937
      header = HSPU_GetReplyPacket(input->packet, &replyPacketSize,
2864
 
                                   input->session);
 
2938
                                   input->transportSession);
2865
2939
      packetOut = (char *)header;
2866
2940
 
2867
2941
      ASSERT_DEVEL(header && (replySize <= replyPacketSize));
2868
2942
      if (header && (sizeof *header <= replyPacketSize)) {
 
2943
         uint64 replySessionId = HGFS_INVALID_SESSION_ID;
 
2944
 
 
2945
         if (NULL != input->session) {
 
2946
            replySessionId = input->session->sessionId;
 
2947
         }
2869
2948
         HgfsPackReplyHeaderV4(status, replyPayloadSize, input->op,
2870
 
                               input->session->sessionId, input->id, header);
 
2949
                               replySessionId, input->id, header);
2871
2950
      }
2872
2951
   } else {
2873
2952
      HgfsReply *reply;
2882
2961
      }
2883
2962
      replyPacketSize = replySize;
2884
2963
      reply = HSPU_GetReplyPacket(input->packet, &replyPacketSize,
2885
 
                                  input->session);
 
2964
                                  input->transportSession);
2886
2965
      packetOut = (char *)reply;
2887
2966
 
2888
2967
      ASSERT_DEVEL(reply && (replySize <= replyPacketSize));
2892
2971
      }
2893
2972
   }
2894
2973
   if (!HgfsPacketSend(input->packet, packetOut, replySize,
2895
 
                       input->session, 0)) {
 
2974
                       input->transportSession, 0)) {
2896
2975
      /* Send failed. Drop the reply. */
2897
2976
      LOG(4, ("Error sending reply\n"));
2898
2977
   }
2899
2978
 
2900
 
   HgfsServerSessionPut(input->session);
 
2979
   if (NULL != input->session) {
 
2980
      HgfsServerSessionPut(input->session);
 
2981
   }
 
2982
   HgfsServerTransportSessionPut(input->transportSession);
2901
2983
   free(input);
2902
2984
}
2903
2985
 
2925
3007
   if (!input->metaPacket) {
2926
3008
      input->metaPacket = HSPU_GetMetaPacket(input->packet,
2927
3009
                                             &input->metaPacketSize,
2928
 
                                             input->session);
 
3010
                                             input->transportSession);
2929
3011
   }
2930
3012
 
2931
3013
   input->payload = (char *)input->metaPacket + input->payloadOffset;
2968
3050
HgfsServerSessionReceive(HgfsPacket *packet,      // IN: Hgfs Packet
2969
3051
                         void *clientData)        // IN: session info
2970
3052
{
2971
 
   HgfsSessionInfo *session = (HgfsSessionInfo *)clientData;
 
3053
   HgfsTransportSessionInfo *transportSession = (HgfsTransportSessionInfo *)clientData;
2972
3054
   HgfsInternalStatus status;
2973
3055
   HgfsInputParam *input = NULL;
2974
3056
 
2975
 
   ASSERT(session);
 
3057
   ASSERT(transportSession);
2976
3058
 
2977
 
   if (session->state == HGFS_SESSION_STATE_CLOSED) {
 
3059
   if (transportSession->state == HGFS_SESSION_STATE_CLOSED) {
2978
3060
      LOG(4, ("%s: %d: Received packet after disconnected.\n", __FUNCTION__,
2979
3061
              __LINE__));
2980
3062
      return;
2981
3063
   }
2982
3064
 
2983
 
   HgfsServerSessionGet(session);
 
3065
   HgfsServerTransportSessionGet(transportSession);
2984
3066
 
2985
 
   if (!HgfsParseRequest(packet, session, &input, &status)) {
 
3067
   if (!HgfsParseRequest(packet, transportSession, &input, &status)) {
2986
3068
      LOG(4, ("%s: %d: Can't generate any response for the guest, just exit.\n ",
2987
3069
              __FUNCTION__, __LINE__));
2988
 
      HgfsServerSessionPut(session);
 
3070
      HgfsServerTransportSessionPut(transportSession);
2989
3071
      return;
2990
3072
   }
2991
3073
 
3008
3090
             * Asynchronous processing is supported by the transport.
3009
3091
             * We can release mappings here and reacquire when needed.
3010
3092
             */
3011
 
            HSPU_PutMetaPacket(packet, session);
 
3093
            HSPU_PutMetaPacket(packet, transportSession);
3012
3094
            input->metaPacket = NULL;
3013
3095
            Atomic_Inc(&gHgfsAsyncCounter);
3014
3096
 
3051
3133
/*
3052
3134
 *-----------------------------------------------------------------------------
3053
3135
 *
 
3136
 * HgfsServerTransportGetSessionInfo --
 
3137
 *
 
3138
 *   Scans the list of sessions and return the session with the specified
 
3139
 *   session id.
 
3140
 *
 
3141
 * Results:
 
3142
 *    A valid pointer to HgfsSessionInfo if there is a session with the
 
3143
 *    specified session id. NULL, otherwise.
 
3144
 *
 
3145
 * Side effects:
 
3146
 *    None
 
3147
 *
 
3148
 *-----------------------------------------------------------------------------
 
3149
 */
 
3150
 
 
3151
HgfsSessionInfo *
 
3152
HgfsServerTransportGetSessionInfo(HgfsTransportSessionInfo *transportSession,       // IN: transport session info
 
3153
                                  uint64 sessionId)                                 // IN: session id
 
3154
{
 
3155
   DblLnkLst_Links *curr;
 
3156
   HgfsSessionInfo *session = NULL;
 
3157
 
 
3158
   ASSERT(transportSession);
 
3159
 
 
3160
   if (HGFS_INVALID_SESSION_ID == sessionId) {
 
3161
      return NULL;
 
3162
   }
 
3163
 
 
3164
   MXUser_AcquireExclLock(transportSession->sessionArrayLock);
 
3165
 
 
3166
   DblLnkLst_ForEach(curr, &transportSession->sessionArray) {
 
3167
      session = DblLnkLst_Container(curr, HgfsSessionInfo, links);
 
3168
      if (session->sessionId == sessionId) {
 
3169
         HgfsServerSessionGet(session);
 
3170
         break;
 
3171
      }
 
3172
      session = NULL;
 
3173
   }
 
3174
 
 
3175
   MXUser_ReleaseExclLock(transportSession->sessionArrayLock);
 
3176
 
 
3177
   return session;
 
3178
}
 
3179
 
 
3180
 
 
3181
/*
 
3182
 *-----------------------------------------------------------------------------
 
3183
 *
 
3184
 * HgfsServerTransportRemoveSessionFromList --
 
3185
 *
 
3186
 *   Unlinks the specified session info from the list.
 
3187
 *
 
3188
 *   Note: The caller must acquire the sessionArrayLock in transportSession
 
3189
 *   before calling this function.
 
3190
 *
 
3191
 * Results:
 
3192
 *    None
 
3193
 *
 
3194
 * Side effects:
 
3195
 *    None
 
3196
 *
 
3197
 *-----------------------------------------------------------------------------
 
3198
 */
 
3199
 
 
3200
void
 
3201
HgfsServerTransportRemoveSessionFromList(HgfsTransportSessionInfo *transportSession,   // IN: transport session info
 
3202
                                         HgfsSessionInfo *session)                     // IN: session info
 
3203
{
 
3204
   ASSERT(transportSession);
 
3205
   ASSERT(session);
 
3206
 
 
3207
   DblLnkLst_Unlink1(&session->links);
 
3208
   transportSession->numSessions--;
 
3209
   HgfsServerSessionPut(session);
 
3210
}
 
3211
 
 
3212
 
 
3213
/*
 
3214
 *-----------------------------------------------------------------------------
 
3215
 *
 
3216
 * HgfsServerTransportAddSessionToList --
 
3217
 *
 
3218
 *    Links the specified session info to the list.
 
3219
 *
 
3220
 * Results:
 
3221
 *    HGFS_ERROR_SUCCESS if the session is successfully added to the list,
 
3222
 *    HGFS_ERROR_TOO_MANY_SESSIONS if maximum number of sessions were already
 
3223
 *                                 added to the list.
 
3224
 *
 
3225
 * Side effects:
 
3226
 *    None
 
3227
 *
 
3228
 *-----------------------------------------------------------------------------
 
3229
 */
 
3230
 
 
3231
HgfsInternalStatus
 
3232
HgfsServerTransportAddSessionToList(HgfsTransportSessionInfo *transportSession,       // IN: transport session info
 
3233
                                    HgfsSessionInfo *session)                         // IN: session info
 
3234
{
 
3235
   HgfsInternalStatus status = HGFS_ERROR_TOO_MANY_SESSIONS;
 
3236
 
 
3237
   ASSERT(transportSession);
 
3238
   ASSERT(session);
 
3239
 
 
3240
   MXUser_AcquireExclLock(transportSession->sessionArrayLock);
 
3241
 
 
3242
   if (transportSession->numSessions == MAX_SESSION_COUNT) {
 
3243
      goto abort;
 
3244
   }
 
3245
 
 
3246
   DblLnkLst_LinkLast(&transportSession->sessionArray, &session->links);
 
3247
   transportSession->numSessions++;
 
3248
   HgfsServerSessionGet(session);
 
3249
   status = HGFS_ERROR_SUCCESS;
 
3250
 
 
3251
abort:
 
3252
   MXUser_ReleaseExclLock(transportSession->sessionArrayLock);
 
3253
   return status;
 
3254
}
 
3255
 
 
3256
 
 
3257
/*
 
3258
 *-----------------------------------------------------------------------------
 
3259
 *
3054
3260
 * HgfsServerCleanupDeletedFolders --
3055
3261
 *
3056
3262
 *    This function iterates through all shared folders and removes all
3508
3714
 *
3509
3715
 *    Initialize a new client session.
3510
3716
 *
 
3717
 *    Allocate HgfsTransportSessionInfo and initialize it.
 
3718
 *
 
3719
 * Results:
 
3720
 *    TRUE on success, FALSE otherwise.
 
3721
 *
 
3722
 * Side effects:
 
3723
 *    None.
 
3724
 *
 
3725
 *-----------------------------------------------------------------------------
 
3726
 */
 
3727
 
 
3728
static Bool
 
3729
HgfsServerSessionConnect(void *transportData,                         // IN: transport session context
 
3730
                         HgfsServerChannelCallbacks *channelCbTable,  // IN: Channel callbacks
 
3731
                         uint32 channelCapabilities,                  // IN: channel capabilities
 
3732
                         void **transportSessionData)                 // OUT: server session context
 
3733
{
 
3734
   HgfsTransportSessionInfo *transportSession;
 
3735
 
 
3736
   ASSERT(transportSessionData);
 
3737
 
 
3738
   LOG(4, ("%s: initting.\n", __FUNCTION__));
 
3739
 
 
3740
   transportSession = Util_SafeCalloc(1, sizeof *transportSession);
 
3741
   transportSession->transportData = transportData;
 
3742
   transportSession->channelCbTable = channelCbTable;
 
3743
   transportSession->maxPacketSize = MAX_SERVER_PACKET_SIZE_V4;
 
3744
   transportSession->type = HGFS_SESSION_TYPE_REGULAR;
 
3745
   transportSession->state = HGFS_SESSION_STATE_OPEN;
 
3746
   transportSession->channelCapabilities = channelCapabilities;
 
3747
   transportSession->numSessions = 0;
 
3748
 
 
3749
   transportSession->sessionArrayLock =
 
3750
         MXUser_CreateExclLock("HgfsSessionArrayLock",
 
3751
                               RANK_hgfsSessionArrayLock);
 
3752
   if (transportSession->sessionArrayLock == NULL) {
 
3753
      LOG(4, ("%s: Could not create session sync mutex.\n", __FUNCTION__));
 
3754
      free(transportSession);
 
3755
      return FALSE;
 
3756
   }
 
3757
 
 
3758
   DblLnkLst_Init(&transportSession->sessionArray);
 
3759
 
 
3760
   transportSession->defaultSessionId = HGFS_INVALID_SESSION_ID;
 
3761
 
 
3762
   Atomic_Write(&transportSession->refCount, 0);
 
3763
 
 
3764
   /* Give our session a reference to hold while we are open. */
 
3765
   HgfsServerTransportSessionGet(transportSession);
 
3766
 
 
3767
   *transportSessionData = transportSession;
 
3768
   return TRUE;
 
3769
}
 
3770
 
 
3771
 
 
3772
/*
 
3773
 *-----------------------------------------------------------------------------
 
3774
 *
 
3775
 * HgfsServerAllocateSession --
 
3776
 *
 
3777
 *    Initialize a new Hgfs session.
 
3778
 *
3511
3779
 *    Allocate HgfsSessionInfo and initialize it. Create the nodeArray and
3512
3780
 *    searchArray for the session.
3513
3781
 *
3520
3788
 *-----------------------------------------------------------------------------
3521
3789
 */
3522
3790
 
3523
 
static Bool
3524
 
HgfsServerSessionConnect(void *transportData,                         // IN: transport session context
3525
 
                         HgfsServerChannelCallbacks *channelCbTable,  // IN: Channel callbacks
3526
 
                         uint32 channelCapabililies,                  // IN: channel capabilities
3527
 
                         void **sessionData)                          // OUT: server session context
 
3791
Bool
 
3792
HgfsServerAllocateSession(HgfsTransportSessionInfo *transportSession, // IN:
 
3793
                          uint32 channelCapabilities,                 // IN:
 
3794
                          HgfsSessionInfo **sessionData)              // OUT:
3528
3795
{
3529
3796
   int i;
3530
 
   HgfsSessionInfo *session = Util_SafeMalloc(sizeof *session);
3531
 
 
3532
 
   ASSERT(sessionData);
3533
 
 
3534
 
   LOG(4, ("%s: initting.\n", __FUNCTION__));
 
3797
   HgfsSessionInfo *session;
 
3798
 
 
3799
   ASSERT(transportSession);
 
3800
 
 
3801
   session = Util_SafeCalloc(1, sizeof *session);
3535
3802
 
3536
3803
   /*
3537
3804
    * Initialize all our locks first as these can fail.
3540
3807
   session->fileIOLock = MXUser_CreateExclLock("HgfsFileIOLock",
3541
3808
                                               RANK_hgfsFileIOLock);
3542
3809
   if (session->fileIOLock == NULL) {
 
3810
      LOG(4, ("%s: Could not create node array sync mutex.\n", __FUNCTION__));
3543
3811
      free(session);
3544
 
      LOG(4, ("%s: Could not create node array sync mutex.\n", __FUNCTION__));
3545
 
 
3546
3812
      return FALSE;
3547
3813
   }
3548
3814
 
3550
3816
                                                  RANK_hgfsNodeArrayLock);
3551
3817
   if (session->nodeArrayLock == NULL) {
3552
3818
      MXUser_DestroyExclLock(session->fileIOLock);
 
3819
      LOG(4, ("%s: Could not create node array sync mutex.\n", __FUNCTION__));
3553
3820
      free(session);
3554
 
      LOG(4, ("%s: Could not create node array sync mutex.\n", __FUNCTION__));
3555
 
 
3556
3821
      return FALSE;
3557
3822
   }
3558
3823
 
3561
3826
   if (session->searchArrayLock == NULL) {
3562
3827
      MXUser_DestroyExclLock(session->fileIOLock);
3563
3828
      MXUser_DestroyExclLock(session->nodeArrayLock);
3564
 
      free(session);
3565
3829
      LOG(4, ("%s: Could not create search array sync mutex.\n",
3566
3830
              __FUNCTION__));
3567
 
 
 
3831
      free(session);
3568
3832
      return FALSE;
3569
3833
   }
3570
3834
 
3571
3835
   session->sessionId = HgfsGenerateSessionId();
 
3836
   session->state = HGFS_SESSION_STATE_OPEN;
 
3837
   DblLnkLst_Init(&session->links);
3572
3838
   session->maxPacketSize = MAX_SERVER_PACKET_SIZE_V4;
3573
3839
   session->activeNotification = FALSE;
 
3840
   session->isInactive = TRUE;
 
3841
   session->transportSession = transportSession;
 
3842
   session->numInvalidationAttempts = 0;
 
3843
 
3574
3844
   /*
3575
3845
    * Initialize the node handling components.
3576
3846
    */
3598
3868
   /* Initialize search freelist. */
3599
3869
   DblLnkLst_Init(&session->searchFreeList);
3600
3870
 
 
3871
   Atomic_Write(&session->refCount, 0);
 
3872
 
 
3873
   /* Give our session a reference to hold while we are open. */
 
3874
   HgfsServerSessionGet(session);
 
3875
 
3601
3876
   /* Allocate array of searches and add them to free list. */
3602
3877
   session->numSearches = NUM_SEARCHES;
3603
3878
   session->searchArray = Util_SafeCalloc(session->numSearches,
3610
3885
                         &session->searchArray[i].links);
3611
3886
   }
3612
3887
 
3613
 
   /*
3614
 
    * Initialize the general session stuff.
3615
 
    */
3616
 
 
3617
 
   session->type = HGFS_SESSION_TYPE_REGULAR;
3618
 
   session->state = HGFS_SESSION_STATE_OPEN;
3619
 
   session->transportData = transportData;
3620
 
   session->channelCbTable = channelCbTable;
3621
 
   Atomic_Write(&session->refCount, 0);
3622
 
 
3623
3888
   /* Get common to all sessions capabiities. */
3624
3889
   HgfsServerGetDefaultCapabilities(session->hgfsSessionCapabilities,
3625
3890
                                    &session->numberOfCapabilities);
3626
3891
 
3627
 
   /* Give our session a reference to hold while we are open. */
3628
 
   HgfsServerSessionGet(session);
3629
 
   *sessionData = session;
3630
 
 
3631
 
   if (channelCapabililies & HGFS_CHANNEL_SHARED_MEM) {
 
3892
   if (channelCapabilities & HGFS_CHANNEL_SHARED_MEM) {
3632
3893
      HgfsServerSetSessionCapability(HGFS_OP_READ_FAST_V4,
3633
3894
                                     HGFS_REQUEST_SUPPORTED, session);
3634
3895
      HgfsServerSetSessionCapability(HGFS_OP_WRITE_FAST_V4,
3651
3912
                                     HGFS_REQUEST_SUPPORTED, session);
3652
3913
   }
3653
3914
 
 
3915
   *sessionData = session;
 
3916
 
3654
3917
   return TRUE;
3655
3918
}
3656
3919
 
3658
3921
/*
3659
3922
 *-----------------------------------------------------------------------------
3660
3923
 *
 
3924
 * HgfsDisconnectSessionInt --
 
3925
 *
 
3926
 *    Disconnect a client session.
 
3927
 *
 
3928
 *    Mark the session as closed as we are in the process of teardown
 
3929
 *    of the session. No more new requests should be processed. We would
 
3930
 *    start draining any outstanding pending operations at this point.
 
3931
 *
 
3932
 * Results:
 
3933
 *    None.
 
3934
 *
 
3935
 * Side effects:
 
3936
 *    None.
 
3937
 *
 
3938
 *-----------------------------------------------------------------------------
 
3939
 */
 
3940
 
 
3941
static void
 
3942
HgfsDisconnectSessionInt(HgfsSessionInfo *session)    // IN: session context
 
3943
{
 
3944
 
 
3945
   ASSERT(session);
 
3946
   ASSERT(session->nodeArray);
 
3947
   ASSERT(session->searchArray);
 
3948
   if (session->activeNotification) {
 
3949
      HgfsNotify_CleanupSession(session);
 
3950
   }
 
3951
}
 
3952
 
 
3953
 
 
3954
/*
 
3955
 *-----------------------------------------------------------------------------
 
3956
 *
3661
3957
 * HgfsServerSessionDisconnect --
3662
3958
 *
3663
3959
 *    Disconnect a client session.
3678
3974
static void
3679
3975
HgfsServerSessionDisconnect(void *clientData)    // IN: session context
3680
3976
{
3681
 
   HgfsSessionInfo *session = (HgfsSessionInfo *)clientData;
3682
 
 
3683
 
   ASSERT(session);
3684
 
   ASSERT(session->nodeArray);
3685
 
   ASSERT(session->searchArray);
3686
 
   if (session->activeNotification) {
3687
 
      HgfsNotify_CleanupSession(session);
 
3977
   HgfsTransportSessionInfo *transportSession = (HgfsTransportSessionInfo *)clientData;
 
3978
   DblLnkLst_Links *curr, *next;
 
3979
 
 
3980
   ASSERT(transportSession);
 
3981
 
 
3982
   MXUser_AcquireExclLock(transportSession->sessionArrayLock);
 
3983
 
 
3984
   DblLnkLst_ForEachSafe(curr, next, &transportSession->sessionArray) {
 
3985
      HgfsSessionInfo *session = DblLnkLst_Container(curr, HgfsSessionInfo, links);
 
3986
 
 
3987
      HgfsDisconnectSessionInt(session);
3688
3988
   }
3689
3989
 
3690
 
   session->state = HGFS_SESSION_STATE_CLOSED;
 
3990
   MXUser_ReleaseExclLock(transportSession->sessionArrayLock);
 
3991
 
 
3992
   transportSession->state = HGFS_SESSION_STATE_CLOSED;
3691
3993
}
3692
3994
 
3693
3995
 
3713
4015
static void
3714
4016
HgfsServerSessionClose(void *clientData)    // IN: session context
3715
4017
{
3716
 
   HgfsSessionInfo *session = (HgfsSessionInfo *)clientData;
3717
 
 
3718
 
   ASSERT(session);
3719
 
   ASSERT(session->nodeArray);
3720
 
   ASSERT(session->searchArray);
3721
 
 
3722
 
   ASSERT(session->state == HGFS_SESSION_STATE_CLOSED);
 
4018
   HgfsTransportSessionInfo *transportSession = (HgfsTransportSessionInfo *)clientData;
 
4019
 
 
4020
   ASSERT(transportSession);
 
4021
   ASSERT(transportSession->state == HGFS_SESSION_STATE_CLOSED);
3723
4022
 
3724
4023
   /* Remove, typically, the last reference, will teardown everything. */
3725
 
   HgfsServerSessionPut(session);
 
4024
   HgfsServerTransportSessionPut(transportSession);
3726
4025
}
3727
4026
 
3728
4027
 
3797
4096
   MXUser_DestroyExclLock(session->nodeArrayLock);
3798
4097
   MXUser_DestroyExclLock(session->searchArrayLock);
3799
4098
   MXUser_DestroyExclLock(session->fileIOLock);
 
4099
 
3800
4100
   free(session);
3801
4101
}
3802
4102
 
3864
4164
 * Side effects:
3865
4165
 *    Frees the packet buffer.
3866
4166
 *
3867
 
 *----------------------------------------------------------------------------
 
4167
 *---------------------------------------------------------------------------
3868
4168
 */
3869
4169
 
3870
4170
void
3871
4171
HgfsServerSessionSendComplete(HgfsPacket *packet,   // IN/OUT: Hgfs packet
3872
4172
                              void *clientData)     // IN: session info
3873
4173
{
3874
 
   HgfsSessionInfo *session = (HgfsSessionInfo *)clientData;
 
4174
   HgfsTransportSessionInfo *transportSession =
 
4175
         (HgfsTransportSessionInfo *)clientData;
3875
4176
 
3876
4177
   if (packet->guestInitiated) {
3877
 
      HSPU_PutMetaPacket(packet, session);
3878
 
      HSPU_PutReplyPacket(packet, session);
3879
 
      HSPU_PutDataPacketBuf(packet, session);
 
4178
      HSPU_PutMetaPacket(packet, transportSession);
 
4179
      HSPU_PutReplyPacket(packet, transportSession);
 
4180
      HSPU_PutDataPacketBuf(packet, transportSession);
3880
4181
   } else {
3881
4182
      free(packet->metaPacket);
3882
4183
      free(packet);
3981
4282
HgfsPacketSend(HgfsPacket *packet,            // IN/OUT: Hgfs Packet
3982
4283
               char *packetOut,               // IN: output buffer
3983
4284
               size_t packetOutLen,           // IN: packet size
3984
 
               HgfsSessionInfo *session,      // IN: session info
 
4285
               HgfsTransportSessionInfo *transportSession,      // IN: session info
3985
4286
               HgfsSendFlags flags)           // IN: flags for how to process
3986
4287
{
3987
4288
   Bool result = FALSE;
3988
4289
   Bool notificationNeeded = packet->guestInitiated && packet->processedAsync;
3989
4290
 
3990
4291
   ASSERT(packet);
3991
 
   ASSERT(session);
 
4292
   ASSERT(transportSession);
3992
4293
 
3993
 
   if (session->state == HGFS_SESSION_STATE_OPEN) {
 
4294
   if (transportSession->state == HGFS_SESSION_STATE_OPEN) {
3994
4295
      packet->replyPacketSize = packetOutLen;
3995
 
      ASSERT(session->type == HGFS_SESSION_TYPE_REGULAR);
3996
 
      result = session->channelCbTable->send(session->transportData,
 
4296
      ASSERT(transportSession->type == HGFS_SESSION_TYPE_REGULAR);
 
4297
      result = transportSession->channelCbTable->send(transportSession->transportData,
3997
4298
                                             packet, packetOut,
3998
4299
                                             packetOutLen, flags);
3999
4300
   }
4146
4447
 
4147
4448
void
4148
4449
HgfsServerSessionInvalidateObjects(void *clientData,         // IN:
4149
 
                                    DblLnkLst_Links *shares)  // IN: List of new shares
4150
 
{
4151
 
   HgfsSessionInfo *session = (HgfsSessionInfo *)clientData;
4152
 
 
4153
 
   HgfsInvalidateSessionObjects(shares, session);
 
4450
                                   DblLnkLst_Links *shares)  // IN: List of new shares
 
4451
{
 
4452
   HgfsTransportSessionInfo *transportSession =
 
4453
         (HgfsTransportSessionInfo *)clientData;
 
4454
   DblLnkLst_Links *curr;
 
4455
 
 
4456
   ASSERT(transportSession);
 
4457
   MXUser_AcquireExclLock(transportSession->sessionArrayLock);
 
4458
 
 
4459
   DblLnkLst_ForEach(curr, &transportSession->sessionArray) {
 
4460
      HgfsSessionInfo *session = DblLnkLst_Container(curr, HgfsSessionInfo, links);
 
4461
      HgfsServerSessionGet(session);
 
4462
      HgfsInvalidateSessionObjects(shares, session);
 
4463
      HgfsServerSessionPut(session);
 
4464
   }
 
4465
 
 
4466
   MXUser_ReleaseExclLock(transportSession->sessionArrayLock);
 
4467
}
 
4468
 
 
4469
 
 
4470
/*
 
4471
 *-----------------------------------------------------------------------------
 
4472
 *
 
4473
 * HgfsServerSessionInvalidateInactiveSessions --
 
4474
 *
 
4475
 *      Iterates over all sessions and invalidate all inactive session objects.
 
4476
 *
 
4477
 *      Following clock algorithm is used to determine whether the session object
 
4478
 *      is inactive or not.
 
4479
 *
 
4480
 *      When this function is called, the HGFS server manager will iterate
 
4481
 *      over all the sessions belonging to this manager. Each session is marked
 
4482
 *      as inactive. Whenever a message is processed for a session, that
 
4483
 *      session is marked as active. When this function is called the next time,
 
4484
 *      any sessions that are still inactive will be invalidated.
 
4485
 *
 
4486
 *      Caller guarantees that the sessions won't go away under us, so no locks
 
4487
 *      needed.
 
4488
 *
 
4489
 * Results:
 
4490
 *      Number of active sessions remaining inside the HGFS server.
 
4491
 *
 
4492
 * Side effects:
 
4493
 *      None
 
4494
 *
 
4495
 *-----------------------------------------------------------------------------
 
4496
 */
 
4497
 
 
4498
uint32
 
4499
HgfsServerSessionInvalidateInactiveSessions(void *clientData)         // IN:
 
4500
{
 
4501
   HgfsTransportSessionInfo *transportSession =
 
4502
         (HgfsTransportSessionInfo *)clientData;
 
4503
   uint32 numActiveSessionsLeft = 0;
 
4504
   DblLnkLst_Links shares, *curr, *next;
 
4505
 
 
4506
   ASSERT(transportSession);
 
4507
   MXUser_AcquireExclLock(transportSession->sessionArrayLock);
 
4508
 
 
4509
   DblLnkLst_Init(&shares);
 
4510
 
 
4511
   DblLnkLst_ForEachSafe(curr, next,  &transportSession->sessionArray) {
 
4512
      HgfsSessionInfo *session = DblLnkLst_Container(curr, HgfsSessionInfo, links);
 
4513
      HgfsServerSessionGet(session);
 
4514
 
 
4515
      session->numInvalidationAttempts++;
 
4516
      numActiveSessionsLeft++;
 
4517
 
 
4518
      /*
 
4519
       * Check if the session is inactive. If the session is inactive, then
 
4520
       * invalidate the session objects.
 
4521
       */
 
4522
      if (session->isInactive) {
 
4523
 
 
4524
         if (session->numInvalidationAttempts == MAX_SESSION_INVALIDATION_ATTEMPTS) {
 
4525
            HgfsServerTransportRemoveSessionFromList(transportSession,
 
4526
                                                     session);
 
4527
            /*
 
4528
             * We need to reduce the refcount by 1 since we want to
 
4529
             * destroy the session.
 
4530
             */
 
4531
            numActiveSessionsLeft--;
 
4532
            HgfsServerSessionPut(session);
 
4533
         } else {
 
4534
            HgfsInvalidateSessionObjects(&shares, session);
 
4535
         }
 
4536
      } else {
 
4537
         session->isInactive = TRUE;
 
4538
         session->numInvalidationAttempts = 0;
 
4539
      }
 
4540
 
 
4541
      HgfsServerSessionPut(session);
 
4542
   }
 
4543
 
 
4544
   MXUser_ReleaseExclLock(transportSession->sessionArrayLock);
 
4545
 
 
4546
   return numActiveSessionsLeft;
4154
4547
}
4155
4548
 
4156
4549
 
5206
5599
      headerSize = sizeof(HgfsReply);
5207
5600
   }
5208
5601
   replyPacketSize = headerSize + payloadSize;
5209
 
   reply = HSPU_GetReplyPacket(packet, &replyPacketSize, session);
 
5602
   reply = HSPU_GetReplyPacket(packet, &replyPacketSize, session->transportSession);
5210
5603
 
5211
5604
   if (reply && (replyPacketSize >= headerSize + payloadSize)) {
5212
5605
      memset(reply, 0, headerSize + payloadSize);
5252
5645
 
5253
5646
   if (!HgfsUnpackReadRequest(input->payload, input->payloadSize, input->op, &file,
5254
5647
                              &offset, &requiredSize)) {
 
5648
      LOG(4, ("%s: Failed to unpack a valid packet -> PROTOCOL_ERROR.\n", __FUNCTION__));
5255
5649
      status = HGFS_ERROR_PROTOCOL;
5256
5650
   } else {
5257
5651
      switch(input->op) {
5266
5660
                                    sizeof *reply + inlineDataSize, (void **)&reply,
5267
5661
                                    input->session)) {
5268
5662
               status = HGFS_ERROR_PROTOCOL;
 
5663
               LOG(4, ("%s: V3/V4 Failed to alloc reply -> PROTOCOL_ERROR.\n", __FUNCTION__));
5269
5664
            } else {
5270
 
               if (inlineDataSize > 0) {
5271
 
                  payload = reply->payload;
 
5665
               if (HGFS_OP_READ_V3 == input->op) {
 
5666
                  payload = &reply->payload[0];
5272
5667
               } else {
5273
5668
                  payload = HSPU_GetDataPacketBuf(input->packet, BUF_WRITEABLE,
5274
 
                                                  input->session);
 
5669
                                                  input->transportSession);
5275
5670
               }
5276
5671
               if (payload) {
5277
5672
                  status = HgfsPlatformReadFile(file, input->session, offset,
5284
5679
                  }
5285
5680
               } else {
5286
5681
                  status = HGFS_ERROR_PROTOCOL;
 
5682
                  LOG(4, ("%s: V3/V4 Failed to get payload -> PROTOCOL_ERROR.\n", __FUNCTION__));
5287
5683
               }
5288
5684
            }
5289
5685
            break;
5298
5694
                                             reply->payload, &reply->actualSize);
5299
5695
               if (HGFS_ERROR_SUCCESS == status) {
5300
5696
                  replyPayloadSize = sizeof *reply + reply->actualSize;
 
5697
               } else {
 
5698
                  LOG(4, ("%s: V1 Failed to read-> %d.\n", __FUNCTION__, status));
5301
5699
               }
5302
5700
            } else {
5303
5701
               status = HGFS_ERROR_PROTOCOL;
 
5702
               LOG(4, ("%s: V1 Failed to alloc reply -> PROTOCOL_ERROR.\n", __FUNCTION__));
5304
5703
            }
5305
5704
            break;
5306
5705
         }
5307
5706
      default:
5308
5707
         NOT_IMPLEMENTED();
5309
5708
         status = HGFS_ERROR_PROTOCOL;
 
5709
         LOG(4, ("%s: Unsupported protocol version passed %d -> PROTOCOL_ERROR.\n",
 
5710
                 __FUNCTION__, input->op));
5310
5711
      }
5311
5712
   }
5312
5713
 
5575
5976
 
5576
5977
   *freeBytes  = outFreeBytes;
5577
5978
   *totalBytes = outTotalBytes;
 
5979
   LOG(4, ("%s: return %"FMT64"u bytes Free %"FMT64"u bytes\n", __FUNCTION__,
 
5980
          outTotalBytes, outFreeBytes));
5578
5981
 
5579
5982
   return status;
5580
5983
}
7679
8082
 
7680
8083
         if (inlineDataSize == 0) {
7681
8084
            info.replyPayload = HSPU_GetDataPacketBuf(input->packet, BUF_WRITEABLE,
7682
 
                                                      input->session);
 
8085
                                                      input->transportSession);
7683
8086
         } else {
7684
8087
            info.replyPayload = (char *)info.reply + baseReplySize;
7685
8088
         }
7783
8186
 
7784
8187
   if (HgfsUnpackCreateSessionRequest(input->payload, input->payloadSize,
7785
8188
                                      input->op, &info)) {
 
8189
      HgfsSessionInfo *session;
7786
8190
      LOG(4, ("%s: create session\n", __FUNCTION__));
7787
 
      if (info.maxPacketSize < input->session->maxPacketSize) {
7788
 
         input->session->maxPacketSize = info.maxPacketSize;
 
8191
 
 
8192
      if (!HgfsServerAllocateSession(input->transportSession,
 
8193
                                     input->transportSession->channelCapabilities,
 
8194
                                     &session)) {
 
8195
         status = HGFS_ERROR_NOT_ENOUGH_MEMORY;
 
8196
         goto abort;
 
8197
      } else {
 
8198
         status = HgfsServerTransportAddSessionToList(input->transportSession,
 
8199
                                                      session);
 
8200
         if (HGFS_ERROR_SUCCESS != status) {
 
8201
            LOG(4, ("%s: Could not add session to the list.\n", __FUNCTION__));
 
8202
            HgfsServerSessionPut(session);
 
8203
            goto abort;
 
8204
         }
 
8205
      }
 
8206
 
 
8207
      if (info.maxPacketSize < session->maxPacketSize) {
 
8208
         session->maxPacketSize = info.maxPacketSize;
7789
8209
      }
7790
8210
      if (HgfsPackCreateSessionReply(input->packet, input->metaPacket,
7791
 
                                     &replyPayloadSize, input->session)) {
7792
 
 
7793
 
         /*
7794
 
          * XXX - TO BE RESTORED on session support implementation
7795
 
          * completion.
7796
 
          */
7797
 
#if defined HGFS_SESSION_SUPPORT
7798
 
         HgfsServerSessionGet(input->session);
7799
 
#endif
 
8211
                                     &replyPayloadSize, session)) {
7800
8212
         status = HGFS_ERROR_SUCCESS;
7801
8213
      } else {
7802
8214
         status = HGFS_ERROR_INTERNAL;
7805
8217
      status = HGFS_ERROR_PROTOCOL;
7806
8218
   }
7807
8219
 
 
8220
abort:
7808
8221
   HgfsServerCompleteRequest(status, replyPayloadSize, input);
7809
8222
}
7810
8223
 
7828
8241
static void
7829
8242
HgfsServerDestroySession(HgfsInputParam *input)  // IN: Input params
7830
8243
{
 
8244
   HgfsTransportSessionInfo *transportSession;
 
8245
   HgfsSessionInfo *session;
 
8246
 
7831
8247
   HGFS_ASSERT_INPUT(input);
7832
8248
 
 
8249
   transportSession = input->transportSession;
 
8250
   session = input->session;
 
8251
 
 
8252
   session->state = HGFS_SESSION_STATE_CLOSED;
 
8253
 
 
8254
   if (session->sessionId == transportSession->defaultSessionId) {
 
8255
      transportSession->defaultSessionId = HGFS_INVALID_SESSION_ID;
 
8256
   }
 
8257
 
 
8258
   /*
 
8259
    * Remove the session from the list. By doing that, the refcount of
 
8260
    * the session will be decremented. Later, we will be invoking
 
8261
    * HgfsServerCompleteRequest which will decrement the session's
 
8262
    * refcount and cleanup the session
 
8263
    */
 
8264
   MXUser_AcquireExclLock(transportSession->sessionArrayLock);
 
8265
   HgfsServerTransportRemoveSessionFromList(transportSession, session);
 
8266
   MXUser_ReleaseExclLock(transportSession->sessionArrayLock);
7833
8267
   HgfsServerCompleteRequest(HGFS_ERROR_SUCCESS, 0, input);
7834
 
   /*
7835
 
    * XXX - TO BE RESTORED on session support implementation
7836
 
    * completion.
7837
 
      */
7838
 
#if defined HGFS_SESSION_SUPPORT
7839
 
   HgfsServerSessionPut(input->session);
7840
 
#endif
 
8268
   HgfsServerSessionPut(session);
7841
8269
}
7842
8270
 
7843
8271
 
7990
8418
 
7991
8419
      HgfsPackChangeNotificationRequest(packetHeader, subscriber, shareName, fileName, mask,
7992
8420
                                        flags, session, &sizeNeeded);
7993
 
      if (!HgfsPacketSend(packet, (char *)packetHeader,  sizeNeeded, session, 0)) {
 
8421
      if (!HgfsPacketSend(packet, (char *)packetHeader,  sizeNeeded, session->transportSession, 0)) {
7994
8422
         LOG(4, ("%s: failed to send notification to the host\n", __FUNCTION__));
7995
8423
      }
7996
8424