~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/atm/addr.c

Version: ~ [ linux-5.13-rc7 ] ~ [ linux-5.12.12 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.45 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.127 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.195 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.237 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.273 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.273 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp