Loading include/linux/atmdev.h +10 −0 Original line number Diff line number Diff line Loading @@ -76,6 +76,13 @@ struct atm_dev_stats { /* set interface ESI */ #define ATM_SETESIF _IOW('a',ATMIOC_ITF+13,struct atmif_sioc) /* force interface ESI */ #define ATM_ADDLECSADDR _IOW('a', ATMIOC_ITF+14, struct atmif_sioc) /* register a LECS address */ #define ATM_DELLECSADDR _IOW('a', ATMIOC_ITF+15, struct atmif_sioc) /* unregister a LECS address */ #define ATM_GETLECSADDR _IOW('a', ATMIOC_ITF+16, struct atmif_sioc) /* retrieve LECS address(es) */ #define ATM_GETSTAT _IOW('a',ATMIOC_SARCOM+0,struct atmif_sioc) /* get AAL layer statistics */ #define ATM_GETSTATZ _IOW('a',ATMIOC_SARCOM+1,struct atmif_sioc) Loading Loading @@ -328,6 +335,8 @@ struct atm_dev_addr { struct list_head entry; /* next address */ }; enum atm_addr_type_t { ATM_ADDR_LOCAL, ATM_ADDR_LECS }; struct atm_dev { const struct atmdev_ops *ops; /* device operations; NULL if unused */ const struct atmphy_ops *phy; /* PHY operations, may be undefined */ Loading @@ -338,6 +347,7 @@ struct atm_dev { void *phy_data; /* private PHY date */ unsigned long flags; /* device flags (ATM_DF_*) */ struct list_head local; /* local ATM addresses */ struct list_head lecs; /* LECS ATM addresses learned via ILMI */ unsigned char esi[ESI_LEN]; /* ESI ("MAC" addr) */ struct atm_cirange ci_range; /* VPI/VCI range */ struct k_atm_dev_stats stats; /* statistics */ Loading net/atm/addr.c +38 −13 Original line number Diff line number Diff line Loading @@ -44,31 +44,43 @@ static void notify_sigd(struct atm_dev *dev) sigd_enq(NULL, as_itf_notify, NULL, &pvc, NULL); } void atm_reset_addr(struct atm_dev *dev) void atm_reset_addr(struct atm_dev *dev, enum atm_addr_type_t atype) { unsigned long flags; struct atm_dev_addr *this, *p; struct list_head *head; spin_lock_irqsave(&dev->lock, flags); list_for_each_entry_safe(this, p, &dev->local, entry) { if (atype == ATM_ADDR_LECS) head = &dev->lecs; else head = &dev->local; list_for_each_entry_safe(this, p, head, entry) { list_del(&this->entry); kfree(this); } spin_unlock_irqrestore(&dev->lock, flags); if (head == &dev->local) notify_sigd(dev); } int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, enum atm_addr_type_t atype) { unsigned long flags; struct atm_dev_addr *this; struct list_head *head; int error; error = check_addr(addr); if (error) return error; spin_lock_irqsave(&dev->lock, flags); list_for_each_entry(this, &dev->local, entry) { if (atype == ATM_ADDR_LECS) head = &dev->lecs; else head = &dev->local; list_for_each_entry(this, head, entry) { if (identical(&this->addr, addr)) { spin_unlock_irqrestore(&dev->lock, flags); return -EEXIST; Loading @@ -80,27 +92,35 @@ int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) return -ENOMEM; } this->addr = *addr; list_add(&this->entry, &dev->local); list_add(&this->entry, head); spin_unlock_irqrestore(&dev->lock, flags); if (head == &dev->local) notify_sigd(dev); return 0; } int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, enum atm_addr_type_t atype) { unsigned long flags; struct atm_dev_addr *this; struct list_head *head; int error; error = check_addr(addr); if (error) return error; spin_lock_irqsave(&dev->lock, flags); list_for_each_entry(this, &dev->local, entry) { if (atype == ATM_ADDR_LECS) head = &dev->lecs; else head = &dev->local; list_for_each_entry(this, head, entry) { if (identical(&this->addr, addr)) { list_del(&this->entry); spin_unlock_irqrestore(&dev->lock, flags); kfree(this); if (head == &dev->local) notify_sigd(dev); return 0; } Loading @@ -110,22 +130,27 @@ int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) } int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user * buf, size_t size) size_t size, enum atm_addr_type_t atype) { unsigned long flags; struct atm_dev_addr *this; struct list_head *head; int total = 0, error; struct sockaddr_atmsvc *tmp_buf, *tmp_bufp; spin_lock_irqsave(&dev->lock, flags); list_for_each_entry(this, &dev->local, entry) if (atype == ATM_ADDR_LECS) head = &dev->lecs; else head = &dev->local; list_for_each_entry(this, head, entry) total += sizeof(struct sockaddr_atmsvc); tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC); if (!tmp_buf) { spin_unlock_irqrestore(&dev->lock, flags); return -ENOMEM; } list_for_each_entry(this, &dev->local, entry) list_for_each_entry(this, head, entry) memcpy(tmp_bufp++, &this->addr, sizeof(struct sockaddr_atmsvc)); spin_unlock_irqrestore(&dev->lock, flags); error = total > size ? -E2BIG : total; Loading net/atm/addr.h +7 −5 Original line number Diff line number Diff line Loading @@ -9,10 +9,12 @@ #include <linux/atm.h> #include <linux/atmdev.h> void atm_reset_addr(struct atm_dev *dev); int atm_add_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr); int atm_del_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr); int atm_get_addr(struct atm_dev *dev,struct sockaddr_atmsvc __user *buf,size_t size); void atm_reset_addr(struct atm_dev *dev, enum atm_addr_type_t type); int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, enum atm_addr_type_t type); int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, enum atm_addr_type_t type); int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user *buf, size_t size, enum atm_addr_type_t type); #endif net/atm/resources.c +15 −5 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ static struct atm_dev *__alloc_atm_dev(const char *type) dev->link_rate = ATM_OC3_PCR; spin_lock_init(&dev->lock); INIT_LIST_HEAD(&dev->local); INIT_LIST_HEAD(&dev->lecs); return dev; } Loading Loading @@ -320,10 +321,12 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg) error = -EPERM; goto done; } atm_reset_addr(dev); atm_reset_addr(dev, ATM_ADDR_LOCAL); break; case ATM_ADDADDR: case ATM_DELADDR: case ATM_ADDLECSADDR: case ATM_DELLECSADDR: if (!capable(CAP_NET_ADMIN)) { error = -EPERM; goto done; Loading @@ -335,14 +338,21 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg) error = -EFAULT; goto done; } if (cmd == ATM_ADDADDR) error = atm_add_addr(dev, &addr); if (cmd == ATM_ADDADDR || cmd == ATM_ADDLECSADDR) error = atm_add_addr(dev, &addr, (cmd == ATM_ADDADDR ? ATM_ADDR_LOCAL : ATM_ADDR_LECS)); else error = atm_del_addr(dev, &addr); error = atm_del_addr(dev, &addr, (cmd == ATM_DELADDR ? ATM_ADDR_LOCAL : ATM_ADDR_LECS)); goto done; } case ATM_GETADDR: error = atm_get_addr(dev, buf, len); case ATM_GETLECSADDR: error = atm_get_addr(dev, buf, len, (cmd == ATM_GETADDR ? ATM_ADDR_LOCAL : ATM_ADDR_LECS)); if (error < 0) goto done; size = error; Loading Loading
include/linux/atmdev.h +10 −0 Original line number Diff line number Diff line Loading @@ -76,6 +76,13 @@ struct atm_dev_stats { /* set interface ESI */ #define ATM_SETESIF _IOW('a',ATMIOC_ITF+13,struct atmif_sioc) /* force interface ESI */ #define ATM_ADDLECSADDR _IOW('a', ATMIOC_ITF+14, struct atmif_sioc) /* register a LECS address */ #define ATM_DELLECSADDR _IOW('a', ATMIOC_ITF+15, struct atmif_sioc) /* unregister a LECS address */ #define ATM_GETLECSADDR _IOW('a', ATMIOC_ITF+16, struct atmif_sioc) /* retrieve LECS address(es) */ #define ATM_GETSTAT _IOW('a',ATMIOC_SARCOM+0,struct atmif_sioc) /* get AAL layer statistics */ #define ATM_GETSTATZ _IOW('a',ATMIOC_SARCOM+1,struct atmif_sioc) Loading Loading @@ -328,6 +335,8 @@ struct atm_dev_addr { struct list_head entry; /* next address */ }; enum atm_addr_type_t { ATM_ADDR_LOCAL, ATM_ADDR_LECS }; struct atm_dev { const struct atmdev_ops *ops; /* device operations; NULL if unused */ const struct atmphy_ops *phy; /* PHY operations, may be undefined */ Loading @@ -338,6 +347,7 @@ struct atm_dev { void *phy_data; /* private PHY date */ unsigned long flags; /* device flags (ATM_DF_*) */ struct list_head local; /* local ATM addresses */ struct list_head lecs; /* LECS ATM addresses learned via ILMI */ unsigned char esi[ESI_LEN]; /* ESI ("MAC" addr) */ struct atm_cirange ci_range; /* VPI/VCI range */ struct k_atm_dev_stats stats; /* statistics */ Loading
net/atm/addr.c +38 −13 Original line number Diff line number Diff line Loading @@ -44,31 +44,43 @@ static void notify_sigd(struct atm_dev *dev) sigd_enq(NULL, as_itf_notify, NULL, &pvc, NULL); } void atm_reset_addr(struct atm_dev *dev) void atm_reset_addr(struct atm_dev *dev, enum atm_addr_type_t atype) { unsigned long flags; struct atm_dev_addr *this, *p; struct list_head *head; spin_lock_irqsave(&dev->lock, flags); list_for_each_entry_safe(this, p, &dev->local, entry) { if (atype == ATM_ADDR_LECS) head = &dev->lecs; else head = &dev->local; list_for_each_entry_safe(this, p, head, entry) { list_del(&this->entry); kfree(this); } spin_unlock_irqrestore(&dev->lock, flags); if (head == &dev->local) notify_sigd(dev); } int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, enum atm_addr_type_t atype) { unsigned long flags; struct atm_dev_addr *this; struct list_head *head; int error; error = check_addr(addr); if (error) return error; spin_lock_irqsave(&dev->lock, flags); list_for_each_entry(this, &dev->local, entry) { if (atype == ATM_ADDR_LECS) head = &dev->lecs; else head = &dev->local; list_for_each_entry(this, head, entry) { if (identical(&this->addr, addr)) { spin_unlock_irqrestore(&dev->lock, flags); return -EEXIST; Loading @@ -80,27 +92,35 @@ int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) return -ENOMEM; } this->addr = *addr; list_add(&this->entry, &dev->local); list_add(&this->entry, head); spin_unlock_irqrestore(&dev->lock, flags); if (head == &dev->local) notify_sigd(dev); return 0; } int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, enum atm_addr_type_t atype) { unsigned long flags; struct atm_dev_addr *this; struct list_head *head; int error; error = check_addr(addr); if (error) return error; spin_lock_irqsave(&dev->lock, flags); list_for_each_entry(this, &dev->local, entry) { if (atype == ATM_ADDR_LECS) head = &dev->lecs; else head = &dev->local; list_for_each_entry(this, head, entry) { if (identical(&this->addr, addr)) { list_del(&this->entry); spin_unlock_irqrestore(&dev->lock, flags); kfree(this); if (head == &dev->local) notify_sigd(dev); return 0; } Loading @@ -110,22 +130,27 @@ int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) } int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user * buf, size_t size) size_t size, enum atm_addr_type_t atype) { unsigned long flags; struct atm_dev_addr *this; struct list_head *head; int total = 0, error; struct sockaddr_atmsvc *tmp_buf, *tmp_bufp; spin_lock_irqsave(&dev->lock, flags); list_for_each_entry(this, &dev->local, entry) if (atype == ATM_ADDR_LECS) head = &dev->lecs; else head = &dev->local; list_for_each_entry(this, head, entry) total += sizeof(struct sockaddr_atmsvc); tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC); if (!tmp_buf) { spin_unlock_irqrestore(&dev->lock, flags); return -ENOMEM; } list_for_each_entry(this, &dev->local, entry) list_for_each_entry(this, head, entry) memcpy(tmp_bufp++, &this->addr, sizeof(struct sockaddr_atmsvc)); spin_unlock_irqrestore(&dev->lock, flags); error = total > size ? -E2BIG : total; Loading
net/atm/addr.h +7 −5 Original line number Diff line number Diff line Loading @@ -9,10 +9,12 @@ #include <linux/atm.h> #include <linux/atmdev.h> void atm_reset_addr(struct atm_dev *dev); int atm_add_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr); int atm_del_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr); int atm_get_addr(struct atm_dev *dev,struct sockaddr_atmsvc __user *buf,size_t size); void atm_reset_addr(struct atm_dev *dev, enum atm_addr_type_t type); int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, enum atm_addr_type_t type); int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, enum atm_addr_type_t type); int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user *buf, size_t size, enum atm_addr_type_t type); #endif
net/atm/resources.c +15 −5 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ static struct atm_dev *__alloc_atm_dev(const char *type) dev->link_rate = ATM_OC3_PCR; spin_lock_init(&dev->lock); INIT_LIST_HEAD(&dev->local); INIT_LIST_HEAD(&dev->lecs); return dev; } Loading Loading @@ -320,10 +321,12 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg) error = -EPERM; goto done; } atm_reset_addr(dev); atm_reset_addr(dev, ATM_ADDR_LOCAL); break; case ATM_ADDADDR: case ATM_DELADDR: case ATM_ADDLECSADDR: case ATM_DELLECSADDR: if (!capable(CAP_NET_ADMIN)) { error = -EPERM; goto done; Loading @@ -335,14 +338,21 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg) error = -EFAULT; goto done; } if (cmd == ATM_ADDADDR) error = atm_add_addr(dev, &addr); if (cmd == ATM_ADDADDR || cmd == ATM_ADDLECSADDR) error = atm_add_addr(dev, &addr, (cmd == ATM_ADDADDR ? ATM_ADDR_LOCAL : ATM_ADDR_LECS)); else error = atm_del_addr(dev, &addr); error = atm_del_addr(dev, &addr, (cmd == ATM_DELADDR ? ATM_ADDR_LOCAL : ATM_ADDR_LECS)); goto done; } case ATM_GETADDR: error = atm_get_addr(dev, buf, len); case ATM_GETLECSADDR: error = atm_get_addr(dev, buf, len, (cmd == ATM_GETADDR ? ATM_ADDR_LOCAL : ATM_ADDR_LECS)); if (error < 0) goto done; size = error; Loading