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