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