addr.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /* net/atm/addr.c - Local ATM address registry */
  2. /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
  3. #include <linux/atm.h>
  4. #include <linux/atmdev.h>
  5. #include <linux/sched.h>
  6. #include <asm/uaccess.h>
  7. #include "signaling.h"
  8. #include "addr.h"
  9. static int check_addr(struct sockaddr_atmsvc *addr)
  10. {
  11. int i;
  12. if (addr->sas_family != AF_ATMSVC)
  13. return -EAFNOSUPPORT;
  14. if (!*addr->sas_addr.pub)
  15. return *addr->sas_addr.prv ? 0 : -EINVAL;
  16. for (i = 1; i < ATM_E164_LEN + 1; i++) /* make sure it's \0-terminated */
  17. if (!addr->sas_addr.pub[i])
  18. return 0;
  19. return -EINVAL;
  20. }
  21. static int identical(struct sockaddr_atmsvc *a, struct sockaddr_atmsvc *b)
  22. {
  23. if (*a->sas_addr.prv)
  24. if (memcmp(a->sas_addr.prv, b->sas_addr.prv, ATM_ESA_LEN))
  25. return 0;
  26. if (!*a->sas_addr.pub)
  27. return !*b->sas_addr.pub;
  28. if (!*b->sas_addr.pub)
  29. return 0;
  30. return !strcmp(a->sas_addr.pub, b->sas_addr.pub);
  31. }
  32. static void notify_sigd(struct atm_dev *dev)
  33. {
  34. struct sockaddr_atmpvc pvc;
  35. pvc.sap_addr.itf = dev->number;
  36. sigd_enq(NULL, as_itf_notify, NULL, &pvc, NULL);
  37. }
  38. void atm_reset_addr(struct atm_dev *dev)
  39. {
  40. unsigned long flags;
  41. struct atm_dev_addr *this, *p;
  42. spin_lock_irqsave(&dev->lock, flags);
  43. list_for_each_entry_safe(this, p, &dev->local, entry)
  44. kfree(this);
  45. spin_unlock_irqrestore(&dev->lock, flags);
  46. notify_sigd(dev);
  47. }
  48. int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr)
  49. {
  50. unsigned long flags;
  51. struct atm_dev_addr *this;
  52. int error;
  53. error = check_addr(addr);
  54. if (error)
  55. return error;
  56. spin_lock_irqsave(&dev->lock, flags);
  57. list_for_each_entry(this, &dev->local, entry) {
  58. if (identical(&this->addr, addr)) {
  59. spin_unlock_irqrestore(&dev->lock, flags);
  60. return -EEXIST;
  61. }
  62. }
  63. this = kmalloc(sizeof(struct atm_dev_addr), GFP_ATOMIC);
  64. if (!this) {
  65. spin_unlock_irqrestore(&dev->lock, flags);
  66. return -ENOMEM;
  67. }
  68. this->addr = *addr;
  69. list_add(&this->entry, &dev->local);
  70. spin_unlock_irqrestore(&dev->lock, flags);
  71. notify_sigd(dev);
  72. return 0;
  73. }
  74. int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr)
  75. {
  76. unsigned long flags;
  77. struct atm_dev_addr *this;
  78. int error;
  79. error = check_addr(addr);
  80. if (error)
  81. return error;
  82. spin_lock_irqsave(&dev->lock, flags);
  83. list_for_each_entry(this, &dev->local, entry) {
  84. if (identical(&this->addr, addr)) {
  85. list_del(&this->entry);
  86. spin_unlock_irqrestore(&dev->lock, flags);
  87. kfree(this);
  88. notify_sigd(dev);
  89. return 0;
  90. }
  91. }
  92. spin_unlock_irqrestore(&dev->lock, flags);
  93. return -ENOENT;
  94. }
  95. int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user * buf,
  96. size_t size)
  97. {
  98. unsigned long flags;
  99. struct atm_dev_addr *this;
  100. int total = 0, error;
  101. struct sockaddr_atmsvc *tmp_buf, *tmp_bufp;
  102. spin_lock_irqsave(&dev->lock, flags);
  103. list_for_each_entry(this, &dev->local, entry)
  104. total += sizeof(struct sockaddr_atmsvc);
  105. tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC);
  106. if (!tmp_buf) {
  107. spin_unlock_irqrestore(&dev->lock, flags);
  108. return -ENOMEM;
  109. }
  110. list_for_each_entry(this, &dev->local, entry)
  111. memcpy(tmp_bufp++, &this->addr, sizeof(struct sockaddr_atmsvc));
  112. spin_unlock_irqrestore(&dev->lock, flags);
  113. error = total > size ? -E2BIG : total;
  114. if (copy_to_user(buf, tmp_buf, total < size ? total : size))
  115. error = -EFAULT;
  116. kfree(tmp_buf);
  117. return error;
  118. }