addr.c 3.8 KB

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