1 /* net/atm/resources.c - Statically allocated resources */ 2 3 /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ 4 5 /* Fixes 6 * Arnaldo Carvalho de Melo <acme@conectiva.com.br> 7 * 2002/01 - don't free the whole struct sock on sk->destruct time, 8 * use the default destruct function initialized by sock_init_data */ 9 10 11 #include <linux/config.h> 12 #include <linux/ctype.h> 13 #include <linux/string.h> 14 #include <linux/atmdev.h> 15 #include <linux/sonet.h> 16 #include <linux/kernel.h> /* for barrier */ 17 #include <linux/module.h> 18 #include <linux/bitops.h> 19 #include <linux/delay.h> 20 #include <net/sock.h> /* for struct sock */ 21 22 #include "common.h" 23 #include "resources.h" 24 #include "addr.h" 25 26 27 LIST_HEAD(atm_devs); 28 DEFINE_SPINLOCK(atm_dev_lock); 29 30 static struct atm_dev *__alloc_atm_dev(const char *type) 31 { 32 struct atm_dev *dev; 33 34 dev = kmalloc(sizeof(*dev), GFP_KERNEL); 35 if (!dev) 36 return NULL; 37 memset(dev, 0, sizeof(*dev)); 38 dev->type = type; 39 dev->signal = ATM_PHY_SIG_UNKNOWN; 40 dev->link_rate = ATM_OC3_PCR; 41 spin_lock_init(&dev->lock); 42 INIT_LIST_HEAD(&dev->local); 43 44 return dev; 45 } 46 47 static void __free_atm_dev(struct atm_dev *dev) 48 { 49 kfree(dev); 50 } 51 52 static struct atm_dev *__atm_dev_lookup(int number) 53 { 54 struct atm_dev *dev; 55 struct list_head *p; 56 57 list_for_each(p, &atm_devs) { 58 dev = list_entry(p, struct atm_dev, dev_list); 59 if ((dev->ops) && (dev->number == number)) { 60 atm_dev_hold(dev); 61 return dev; 62 } 63 } 64 return NULL; 65 } 66 67 struct atm_dev *atm_dev_lookup(int number) 68 { 69 struct atm_dev *dev; 70 71 spin_lock(&atm_dev_lock); 72 dev = __atm_dev_lookup(number); 73 spin_unlock(&atm_dev_lock); 74 return dev; 75 } 76 77 struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, 78 int number, unsigned long *flags) 79 { 80 struct atm_dev *dev, *inuse; 81 82 dev = __alloc_atm_dev(type); 83 if (!dev) { 84 printk(KERN_ERR "atm_dev_register: no space for dev %s\n", 85 type); 86 return NULL; 87 } 88 spin_lock(&atm_dev_lock); 89 if (number != -1) { 90 if ((inuse = __atm_dev_lookup(number))) { 91 atm_dev_put(inuse); 92 spin_unlock(&atm_dev_lock); 93 __free_atm_dev(dev); 94 return NULL; 95 } 96 dev->number = number; 97 } else { 98 dev->number = 0; 99 while ((inuse = __atm_dev_lookup(dev->number))) { 100 atm_dev_put(inuse); 101 dev->number++; 102 } 103 } 104 105 dev->ops = ops; 106 if (flags) 107 dev->flags = *flags; 108 else 109 memset(&dev->flags, 0, sizeof(dev->flags)); 110 memset(&dev->stats, 0, sizeof(dev->stats)); 111 atomic_set(&dev->refcnt, 1); 112 list_add_tail(&dev->dev_list, &atm_devs); 113 spin_unlock(&atm_dev_lock); 114 115 if (atm_proc_dev_register(dev) < 0) { 116 printk(KERN_ERR "atm_dev_register: " 117 "atm_proc_dev_register failed for dev %s\n", 118 type); 119 spin_lock(&atm_dev_lock); 120 list_del(&dev->dev_list); 121 spin_unlock(&atm_dev_lock); 122 __free_atm_dev(dev); 123 return NULL; 124 } 125 126 return dev; 127 } 128 129 130 void atm_dev_deregister(struct atm_dev *dev) 131 { 132 unsigned long warning_time; 133 134 atm_proc_dev_deregister(dev); 135 136 spin_lock(&atm_dev_lock); 137 list_del(&dev->dev_list); 138 spin_unlock(&atm_dev_lock); 139 140 warning_time = jiffies; 141 while (atomic_read(&dev->refcnt) != 1) { 142 msleep(250); 143 if ((jiffies - warning_time) > 10 * HZ) { 144 printk(KERN_EMERG "atm_dev_deregister: waiting for " 145 "dev %d to become free. Usage count = %d\n", 146 dev->number, atomic_read(&dev->refcnt)); 147 warning_time = jiffies; 148 } 149 } 150 151 __free_atm_dev(dev); 152 } 153 154 void shutdown_atm_dev(struct atm_dev *dev) 155 { 156 if (atomic_read(&dev->refcnt) > 1) { 157 set_bit(ATM_DF_CLOSE, &dev->flags); 158 return; 159 } 160 if (dev->ops->dev_close) 161 dev->ops->dev_close(dev); 162 atm_dev_deregister(dev); 163 } 164 165 166 static void copy_aal_stats(struct k_atm_aal_stats *from, 167 struct atm_aal_stats *to) 168 { 169 #define __HANDLE_ITEM(i) to->i = atomic_read(&from->i) 170 __AAL_STAT_ITEMS 171 #undef __HANDLE_ITEM 172 } 173 174 175 static void subtract_aal_stats(struct k_atm_aal_stats *from, 176 struct atm_aal_stats *to) 177 { 178 #define __HANDLE_ITEM(i) atomic_sub(to->i, &from->i) 179 __AAL_STAT_ITEMS 180 #undef __HANDLE_ITEM 181 } 182 183 184 static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg, int zero) 185 { 186 struct atm_dev_stats tmp; 187 int error = 0; 188 189 copy_aal_stats(&dev->stats.aal0, &tmp.aal0); 190 copy_aal_stats(&dev->stats.aal34, &tmp.aal34); 191 copy_aal_stats(&dev->stats.aal5, &tmp.aal5); 192 if (arg) 193 error = copy_to_user(arg, &tmp, sizeof(tmp)); 194 if (zero && !error) { 195 subtract_aal_stats(&dev->stats.aal0, &tmp.aal0); 196 subtract_aal_stats(&dev->stats.aal34, &tmp.aal34); 197 subtract_aal_stats(&dev->stats.aal5, &tmp.aal5); 198 } 199 return error ? -EFAULT : 0; 200 } 201 202 203 int atm_dev_ioctl(unsigned int cmd, void __user *arg) 204 { 205 void __user *buf; 206 int error, len, number, size = 0; 207 struct atm_dev *dev; 208 struct list_head *p; 209 int *tmp_buf, *tmp_p; 210 struct atm_iobuf __user *iobuf = arg; 211 struct atmif_sioc __user *sioc = arg; 212 switch (cmd) { 213 case ATM_GETNAMES: 214 if (get_user(buf, &iobuf->buffer)) 215 return -EFAULT; 216 if (get_user(len, &iobuf->length)) 217 return -EFAULT; 218 spin_lock(&atm_dev_lock); 219 list_for_each(p, &atm_devs) 220 size += sizeof(int); 221 if (size > len) { 222 spin_unlock(&atm_dev_lock); 223 return -E2BIG; 224 } 225 tmp_buf = kmalloc(size, GFP_ATOMIC); 226 if (!tmp_buf) { 227 spin_unlock(&atm_dev_lock); 228 return -ENOMEM; 229 } 230 tmp_p = tmp_buf; 231 list_for_each(p, &atm_devs) { 232 dev = list_entry(p, struct atm_dev, dev_list); 233 *tmp_p++ = dev->number; 234 } 235 spin_unlock(&atm_dev_lock); 236 error = ((copy_to_user(buf, tmp_buf, size)) || 237 put_user(size, &iobuf->length)) 238 ? -EFAULT : 0; 239 kfree(tmp_buf); 240 return error; 241 default: 242 break; 243 } 244 245 if (get_user(buf, &sioc->arg)) 246 return -EFAULT; 247 if (get_user(len, &sioc->length)) 248 return -EFAULT; 249 if (get_user(number, &sioc->number)) 250 return -EFAULT; 251 252 if (!(dev = atm_dev_lookup(number))) 253 return -ENODEV; 254 255 switch (cmd) { 256 case ATM_GETTYPE: 257 size = strlen(dev->type) + 1; 258 if (copy_to_user(buf, dev->type, size)) { 259 error = -EFAULT; 260 goto done; 261 } 262 break; 263 case ATM_GETESI: 264 size = ESI_LEN; 265 if (copy_to_user(buf, dev->esi, size)) { 266 error = -EFAULT; 267 goto done; 268 } 269 break; 270 case ATM_SETESI: 271 { 272 int i; 273 274 for (i = 0; i < ESI_LEN; i++) 275 if (dev->esi[i]) { 276 error = -EEXIST; 277 goto done; 278 } 279 } 280 /* fall through */ 281 case ATM_SETESIF: 282 { 283 unsigned char esi[ESI_LEN]; 284 285 if (!capable(CAP_NET_ADMIN)) { 286 error = -EPERM; 287 goto done; 288 } 289 if (copy_from_user(esi, buf, ESI_LEN)) { 290 error = -EFAULT; 291 goto done; 292 } 293 memcpy(dev->esi, esi, ESI_LEN); 294 error = ESI_LEN; 295 goto done; 296 } 297 case ATM_GETSTATZ: 298 if (!capable(CAP_NET_ADMIN)) { 299 error = -EPERM; 300 goto done; 301 } 302 /* fall through */ 303 case ATM_GETSTAT: 304 size = sizeof(struct atm_dev_stats); 305 error = fetch_stats(dev, buf, cmd == ATM_GETSTATZ); 306 if (error) 307 goto done; 308 break; 309 case ATM_GETCIRANGE: 310 size = sizeof(struct atm_cirange); 311 if (copy_to_user(buf, &dev->ci_range, size)) { 312 error = -EFAULT; 313 goto done; 314 } 315 break; 316 case ATM_GETLINKRATE: 317 size = sizeof(int); 318 if (copy_to_user(buf, &dev->link_rate, size)) { 319 error = -EFAULT; 320 goto done; 321 } 322 break; 323 case ATM_RSTADDR: 324 if (!capable(CAP_NET_ADMIN)) { 325 error = -EPERM; 326 goto done; 327 } 328 atm_reset_addr(dev); 329 break; 330 case ATM_ADDADDR: 331 case ATM_DELADDR: 332 if (!capable(CAP_NET_ADMIN)) { 333 error = -EPERM; 334 goto done; 335 } 336 { 337 struct sockaddr_atmsvc addr; 338 339 if (copy_from_user(&addr, buf, sizeof(addr))) { 340 error = -EFAULT; 341 goto done; 342 } 343 if (cmd == ATM_ADDADDR) 344 error = atm_add_addr(dev, &addr); 345 else 346 error = atm_del_addr(dev, &addr); 347 goto done; 348 } 349 case ATM_GETADDR: 350 error = atm_get_addr(dev, buf, len); 351 if (error < 0) 352 goto done; 353 size = error; 354 /* may return 0, but later on size == 0 means "don't 355 write the length" */ 356 error = put_user(size, &sioc->length) 357 ? -EFAULT : 0; 358 goto done; 359 case ATM_SETLOOP: 360 if (__ATM_LM_XTRMT((int) (unsigned long) buf) && 361 __ATM_LM_XTLOC((int) (unsigned long) buf) > 362 __ATM_LM_XTRMT((int) (unsigned long) buf)) { 363 error = -EINVAL; 364 goto done; 365 } 366 /* fall through */ 367 case ATM_SETCIRANGE: 368 case SONET_GETSTATZ: 369 case SONET_SETDIAG: 370 case SONET_CLRDIAG: 371 case SONET_SETFRAMING: 372 if (!capable(CAP_NET_ADMIN)) { 373 error = -EPERM; 374 goto done; 375 } 376 /* fall through */ 377 default: 378 if (!dev->ops->ioctl) { 379 error = -EINVAL; 380 goto done; 381 } 382 size = dev->ops->ioctl(dev, cmd, buf); 383 if (size < 0) { 384 error = (size == -ENOIOCTLCMD ? -EINVAL : size); 385 goto done; 386 } 387 } 388 389 if (size) 390 error = put_user(size, &sioc->length) 391 ? -EFAULT : 0; 392 else 393 error = 0; 394 done: 395 atm_dev_put(dev); 396 return error; 397 } 398 399 static __inline__ void *dev_get_idx(loff_t left) 400 { 401 struct list_head *p; 402 403 list_for_each(p, &atm_devs) { 404 if (!--left) 405 break; 406 } 407 return (p != &atm_devs) ? p : NULL; 408 } 409 410 void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos) 411 { 412 spin_lock(&atm_dev_lock); 413 return *pos ? dev_get_idx(*pos) : (void *) 1; 414 } 415 416 void atm_dev_seq_stop(struct seq_file *seq, void *v) 417 { 418 spin_unlock(&atm_dev_lock); 419 } 420 421 void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) 422 { 423 ++*pos; 424 v = (v == (void *)1) ? atm_devs.next : ((struct list_head *)v)->next; 425 return (v == &atm_devs) ? NULL : v; 426 } 427 428 429 EXPORT_SYMBOL(atm_dev_register); 430 EXPORT_SYMBOL(atm_dev_deregister); 431 EXPORT_SYMBOL(atm_dev_lookup); 432 EXPORT_SYMBOL(shutdown_atm_dev); 433