addr.c 3.9 KB

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