1 /*
   2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
   3  * Use is subject to license terms.
   4  */
   5 
   6 /*
   7  * drm_auth.h -- IOCTLs for authentication -*- linux-c -*-
   8  * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
   9  */
  10 /*
  11  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  12  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  13  * All Rights Reserved.
  14  *
  15  * Permission is hereby granted, free of charge, to any person obtaining a
  16  * copy of this software and associated documentation files (the "Software"),
  17  * to deal in the Software without restriction, including without limitation
  18  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  19  * and/or sell copies of the Software, and to permit persons to whom the
  20  * Software is furnished to do so, subject to the following conditions:
  21  *
  22  * The above copyright notice and this permission notice (including the next
  23  * paragraph) shall be included in all copies or substantial portions of the
  24  * Software.
  25  *
  26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  27  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  28  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  29  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  30  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  31  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  32  * OTHER DEALINGS IN THE SOFTWARE.
  33  *
  34  * Authors:
  35  *    Rickard E. (Rik) Faith <faith@valinux.com>
  36  *    Gareth Hughes <gareth@valinux.com>
  37  *
  38  */
  39 
  40 #pragma ident   "%Z%%M% %I%     %E% SMI"
  41 
  42 #include "drmP.h"
  43 
  44 static int
  45 drm_hash_magic(drm_magic_t magic)
  46 {
  47         return (magic & (DRM_HASH_SIZE-1));
  48 }
  49 
  50 drm_file_t *
  51 drm_find_file(drm_device_t *dev, drm_magic_t magic)
  52 {
  53         drm_file_t        *retval = NULL;
  54         drm_magic_entry_t *pt;
  55         int               hash;
  56 
  57         hash = drm_hash_magic(magic);
  58         for (pt = dev->magiclist[hash].head; pt; pt = pt->next) {
  59                 if (pt->magic == magic) {
  60                         retval = pt->priv;
  61                         break;
  62                 }
  63         }
  64 
  65         return (retval);
  66 }
  67 
  68 static int
  69 drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
  70 {
  71         int               hash;
  72         drm_magic_entry_t *entry;
  73 
  74         hash = drm_hash_magic(magic);
  75         entry = drm_alloc(sizeof (*entry), DRM_MEM_MAGIC);
  76         if (!entry)
  77                 return (ENOMEM);
  78         entry->magic = magic;
  79         entry->priv  = priv;
  80         entry->next  = NULL;
  81 
  82         DRM_LOCK();
  83         if (dev->magiclist[hash].tail) {
  84                 dev->magiclist[hash].tail->next = entry;
  85                 dev->magiclist[hash].tail    = entry;
  86         } else {
  87                 dev->magiclist[hash].head    = entry;
  88                 dev->magiclist[hash].tail    = entry;
  89         }
  90         DRM_UNLOCK();
  91 
  92         return (0);
  93 }
  94 
  95 int
  96 drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
  97 {
  98         drm_magic_entry_t *prev = NULL;
  99         drm_magic_entry_t *pt;
 100         int               hash;
 101 
 102         DRM_DEBUG("drm_remove_magic : %d", magic);
 103         hash = drm_hash_magic(magic);
 104 
 105         DRM_LOCK();
 106         for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) {
 107                 if (pt->magic == magic) {
 108                         if (dev->magiclist[hash].head == pt) {
 109                                 dev->magiclist[hash].head = pt->next;
 110                         }
 111                         if (dev->magiclist[hash].tail == pt) {
 112                                 dev->magiclist[hash].tail = prev;
 113                         }
 114                         if (prev) {
 115                                 prev->next = pt->next;
 116                         }
 117                         DRM_UNLOCK();
 118                         drm_free(pt, sizeof (*pt), DRM_MEM_MAGIC);
 119                         return (0);
 120                 }
 121         }
 122         DRM_UNLOCK();
 123 
 124         return (EINVAL);
 125 }
 126 
 127 /*ARGSUSED*/
 128 int
 129 drm_getmagic(DRM_IOCTL_ARGS)
 130 {
 131         DRM_DEVICE;
 132         static drm_magic_t sequence = 0;
 133         drm_auth_t auth;
 134 
 135         /* Find unique magic */
 136         if (fpriv->magic) {
 137                 auth.magic = fpriv->magic;
 138         } else {
 139                 do {
 140                         int old = sequence;
 141                         auth.magic = old+1;
 142                         if (!atomic_cmpset_int(&sequence, old, auth.magic))
 143                                 continue;
 144                 } while (drm_find_file(dev, auth.magic));
 145                 fpriv->magic = auth.magic;
 146                 (void) drm_add_magic(dev, fpriv, auth.magic);
 147         }
 148 
 149 
 150         DRM_DEBUG("drm_getmagic: %u", auth.magic);
 151 
 152         DRM_COPYTO_WITH_RETURN((void *)data, &auth, sizeof (auth));
 153 
 154         return (0);
 155 }
 156 
 157 /*ARGSUSED*/
 158 int
 159 drm_authmagic(DRM_IOCTL_ARGS)
 160 {
 161         drm_auth_t         auth;
 162         drm_file_t         *file;
 163         DRM_DEVICE;
 164 
 165         DRM_COPYFROM_WITH_RETURN(&auth, (void *)data, sizeof (auth));
 166 
 167         if ((file = drm_find_file(dev, auth.magic))) {
 168                 file->authenticated = 1;
 169                 (void) drm_remove_magic(dev, auth.magic);
 170                 return (0);
 171         }
 172         return (EINVAL);
 173 }