resources.c 9.8 KB

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