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