Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

+321 -63
+10
include/linux/atmdev.h
··· 76 /* set interface ESI */ 77 #define ATM_SETESIF _IOW('a',ATMIOC_ITF+13,struct atmif_sioc) 78 /* force interface ESI */ 79 #define ATM_GETSTAT _IOW('a',ATMIOC_SARCOM+0,struct atmif_sioc) 80 /* get AAL layer statistics */ 81 #define ATM_GETSTATZ _IOW('a',ATMIOC_SARCOM+1,struct atmif_sioc) ··· 335 struct list_head entry; /* next address */ 336 }; 337 338 struct atm_dev { 339 const struct atmdev_ops *ops; /* device operations; NULL if unused */ 340 const struct atmphy_ops *phy; /* PHY operations, may be undefined */ ··· 347 void *phy_data; /* private PHY date */ 348 unsigned long flags; /* device flags (ATM_DF_*) */ 349 struct list_head local; /* local ATM addresses */ 350 unsigned char esi[ESI_LEN]; /* ESI ("MAC" addr) */ 351 struct atm_cirange ci_range; /* VPI/VCI range */ 352 struct k_atm_dev_stats stats; /* statistics */
··· 76 /* set interface ESI */ 77 #define ATM_SETESIF _IOW('a',ATMIOC_ITF+13,struct atmif_sioc) 78 /* force interface ESI */ 79 + #define ATM_ADDLECSADDR _IOW('a', ATMIOC_ITF+14, struct atmif_sioc) 80 + /* register a LECS address */ 81 + #define ATM_DELLECSADDR _IOW('a', ATMIOC_ITF+15, struct atmif_sioc) 82 + /* unregister a LECS address */ 83 + #define ATM_GETLECSADDR _IOW('a', ATMIOC_ITF+16, struct atmif_sioc) 84 + /* retrieve LECS address(es) */ 85 + 86 #define ATM_GETSTAT _IOW('a',ATMIOC_SARCOM+0,struct atmif_sioc) 87 /* get AAL layer statistics */ 88 #define ATM_GETSTATZ _IOW('a',ATMIOC_SARCOM+1,struct atmif_sioc) ··· 328 struct list_head entry; /* next address */ 329 }; 330 331 + enum atm_addr_type_t { ATM_ADDR_LOCAL, ATM_ADDR_LECS }; 332 + 333 struct atm_dev { 334 const struct atmdev_ops *ops; /* device operations; NULL if unused */ 335 const struct atmphy_ops *phy; /* PHY operations, may be undefined */ ··· 338 void *phy_data; /* private PHY date */ 339 unsigned long flags; /* device flags (ATM_DF_*) */ 340 struct list_head local; /* local ATM addresses */ 341 + struct list_head lecs; /* LECS ATM addresses learned via ILMI */ 342 unsigned char esi[ESI_LEN]; /* ESI ("MAC" addr) */ 343 struct atm_cirange ci_range; /* VPI/VCI range */ 344 struct k_atm_dev_stats stats; /* statistics */
+23 -14
include/net/sctp/user.h
··· 103 #define SCTP_SOCKOPT_BINDX_REM SCTP_SOCKOPT_BINDX_REM 104 SCTP_SOCKOPT_PEELOFF, /* peel off association. */ 105 #define SCTP_SOCKOPT_PEELOFF SCTP_SOCKOPT_PEELOFF 106 - SCTP_GET_PEER_ADDRS_NUM, /* Get number of peer addresss. */ 107 - #define SCTP_GET_PEER_ADDRS_NUM SCTP_GET_PEER_ADDRS_NUM 108 - SCTP_GET_PEER_ADDRS, /* Get all peer addresss. */ 109 - #define SCTP_GET_PEER_ADDRS SCTP_GET_PEER_ADDRS 110 - SCTP_GET_LOCAL_ADDRS_NUM, /* Get number of local addresss. */ 111 - #define SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS_NUM 112 - SCTP_GET_LOCAL_ADDRS, /* Get all local addresss. */ 113 - #define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS 114 SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */ 115 #define SCTP_SOCKOPT_CONNECTX SCTP_SOCKOPT_CONNECTX 116 }; 117 118 /* ··· 243 int spc_state; 244 int spc_error; 245 sctp_assoc_t spc_assoc_id; 246 - }; 247 248 /* 249 * spc_state: 32 bits (signed integer) ··· 468 struct sctp_setpeerprim { 469 sctp_assoc_t sspp_assoc_id; 470 struct sockaddr_storage sspp_addr; 471 - }; 472 473 /* 474 * 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR) ··· 481 struct sctp_prim { 482 sctp_assoc_t ssp_assoc_id; 483 struct sockaddr_storage ssp_addr; 484 - }; 485 486 /* 487 * 7.1.11 Set Adaption Layer Indicator (SCTP_ADAPTION_LAYER) ··· 508 struct sockaddr_storage spp_address; 509 __u32 spp_hbinterval; 510 __u16 spp_pathmaxrxt; 511 - }; 512 513 /* 514 * 7.2.2 Peer Address Information ··· 527 __u32 spinfo_srtt; 528 __u32 spinfo_rto; 529 __u32 spinfo_mtu; 530 - }; 531 532 /* Peer addresses's state. */ 533 enum sctp_spinfo_state { ··· 563 * SCTP_GET_LOCAL_ADDRS socket options used internally to implement 564 * sctp_getpaddrs() and sctp_getladdrs() API. 565 */ 566 - struct sctp_getaddrs { 567 sctp_assoc_t assoc_id; 568 int addr_num; 569 struct sockaddr __user *addrs; 570 }; 571 572 /* These are bit fields for msghdr->msg_flags. See section 5.1. */
··· 103 #define SCTP_SOCKOPT_BINDX_REM SCTP_SOCKOPT_BINDX_REM 104 SCTP_SOCKOPT_PEELOFF, /* peel off association. */ 105 #define SCTP_SOCKOPT_PEELOFF SCTP_SOCKOPT_PEELOFF 106 + SCTP_GET_PEER_ADDRS_NUM_OLD, /* Get number of peer addresss. */ 107 + #define SCTP_GET_PEER_ADDRS_NUM_OLD SCTP_GET_PEER_ADDRS_NUM_OLD 108 + SCTP_GET_PEER_ADDRS_OLD, /* Get all peer addresss. */ 109 + #define SCTP_GET_PEER_ADDRS_OLD SCTP_GET_PEER_ADDRS_OLD 110 + SCTP_GET_LOCAL_ADDRS_NUM_OLD, /* Get number of local addresss. */ 111 + #define SCTP_GET_LOCAL_ADDRS_NUM_OLD SCTP_GET_LOCAL_ADDRS_NUM_OLD 112 + SCTP_GET_LOCAL_ADDRS_OLD, /* Get all local addresss. */ 113 + #define SCTP_GET_LOCAL_ADDRS_OLD SCTP_GET_LOCAL_ADDRS_OLD 114 SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */ 115 #define SCTP_SOCKOPT_CONNECTX SCTP_SOCKOPT_CONNECTX 116 + SCTP_GET_PEER_ADDRS, /* Get all peer addresss. */ 117 + #define SCTP_GET_PEER_ADDRS SCTP_GET_PEER_ADDRS 118 + SCTP_GET_LOCAL_ADDRS, /* Get all local addresss. */ 119 + #define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS 120 }; 121 122 /* ··· 239 int spc_state; 240 int spc_error; 241 sctp_assoc_t spc_assoc_id; 242 + } __attribute__((packed, aligned(4))); 243 244 /* 245 * spc_state: 32 bits (signed integer) ··· 464 struct sctp_setpeerprim { 465 sctp_assoc_t sspp_assoc_id; 466 struct sockaddr_storage sspp_addr; 467 + } __attribute__((packed, aligned(4))); 468 469 /* 470 * 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR) ··· 477 struct sctp_prim { 478 sctp_assoc_t ssp_assoc_id; 479 struct sockaddr_storage ssp_addr; 480 + } __attribute__((packed, aligned(4))); 481 482 /* 483 * 7.1.11 Set Adaption Layer Indicator (SCTP_ADAPTION_LAYER) ··· 504 struct sockaddr_storage spp_address; 505 __u32 spp_hbinterval; 506 __u16 spp_pathmaxrxt; 507 + } __attribute__((packed, aligned(4))); 508 509 /* 510 * 7.2.2 Peer Address Information ··· 523 __u32 spinfo_srtt; 524 __u32 spinfo_rto; 525 __u32 spinfo_mtu; 526 + } __attribute__((packed, aligned(4))); 527 528 /* Peer addresses's state. */ 529 enum sctp_spinfo_state { ··· 559 * SCTP_GET_LOCAL_ADDRS socket options used internally to implement 560 * sctp_getpaddrs() and sctp_getladdrs() API. 561 */ 562 + struct sctp_getaddrs_old { 563 sctp_assoc_t assoc_id; 564 int addr_num; 565 struct sockaddr __user *addrs; 566 + }; 567 + struct sctp_getaddrs { 568 + sctp_assoc_t assoc_id; /*input*/ 569 + __u32 addr_num; /*output*/ 570 + __u8 addrs[0]; /*output, variable size*/ 571 }; 572 573 /* These are bit fields for msghdr->msg_flags. See section 5.1. */
+38 -13
net/atm/addr.c
··· 44 sigd_enq(NULL, as_itf_notify, NULL, &pvc, NULL); 45 } 46 47 - void atm_reset_addr(struct atm_dev *dev) 48 { 49 unsigned long flags; 50 struct atm_dev_addr *this, *p; 51 52 spin_lock_irqsave(&dev->lock, flags); 53 - list_for_each_entry_safe(this, p, &dev->local, entry) { 54 list_del(&this->entry); 55 kfree(this); 56 } 57 spin_unlock_irqrestore(&dev->lock, flags); 58 - notify_sigd(dev); 59 } 60 61 - int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) 62 { 63 unsigned long flags; 64 struct atm_dev_addr *this; 65 int error; 66 67 error = check_addr(addr); 68 if (error) 69 return error; 70 spin_lock_irqsave(&dev->lock, flags); 71 - list_for_each_entry(this, &dev->local, entry) { 72 if (identical(&this->addr, addr)) { 73 spin_unlock_irqrestore(&dev->lock, flags); 74 return -EEXIST; ··· 92 return -ENOMEM; 93 } 94 this->addr = *addr; 95 - list_add(&this->entry, &dev->local); 96 spin_unlock_irqrestore(&dev->lock, flags); 97 - notify_sigd(dev); 98 return 0; 99 } 100 101 - int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr) 102 { 103 unsigned long flags; 104 struct atm_dev_addr *this; 105 int error; 106 107 error = check_addr(addr); 108 if (error) 109 return error; 110 spin_lock_irqsave(&dev->lock, flags); 111 - list_for_each_entry(this, &dev->local, entry) { 112 if (identical(&this->addr, addr)) { 113 list_del(&this->entry); 114 spin_unlock_irqrestore(&dev->lock, flags); 115 kfree(this); 116 - notify_sigd(dev); 117 return 0; 118 } 119 } ··· 130 } 131 132 int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user * buf, 133 - size_t size) 134 { 135 unsigned long flags; 136 struct atm_dev_addr *this; 137 int total = 0, error; 138 struct sockaddr_atmsvc *tmp_buf, *tmp_bufp; 139 140 spin_lock_irqsave(&dev->lock, flags); 141 - list_for_each_entry(this, &dev->local, entry) 142 total += sizeof(struct sockaddr_atmsvc); 143 tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC); 144 if (!tmp_buf) { 145 spin_unlock_irqrestore(&dev->lock, flags); 146 return -ENOMEM; 147 } 148 - list_for_each_entry(this, &dev->local, entry) 149 memcpy(tmp_bufp++, &this->addr, sizeof(struct sockaddr_atmsvc)); 150 spin_unlock_irqrestore(&dev->lock, flags); 151 error = total > size ? -E2BIG : total;
··· 44 sigd_enq(NULL, as_itf_notify, NULL, &pvc, NULL); 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); 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) { 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, 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); 79 + if (atype == ATM_ADDR_LECS) 80 + head = &dev->lecs; 81 + else 82 + head = &dev->local; 83 + list_for_each_entry(this, head, entry) { 84 if (identical(&this->addr, addr)) { 85 spin_unlock_irqrestore(&dev->lock, flags); 86 return -EEXIST; ··· 80 return -ENOMEM; 81 } 82 this->addr = *addr; 83 + list_add(&this->entry, head); 84 spin_unlock_irqrestore(&dev->lock, flags); 85 + if (head == &dev->local) 86 + notify_sigd(dev); 87 return 0; 88 } 89 90 + int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, 91 + enum atm_addr_type_t atype) 92 { 93 unsigned long flags; 94 struct atm_dev_addr *this; 95 + struct list_head *head; 96 int error; 97 98 error = check_addr(addr); 99 if (error) 100 return error; 101 spin_lock_irqsave(&dev->lock, flags); 102 + if (atype == ATM_ADDR_LECS) 103 + head = &dev->lecs; 104 + else 105 + head = &dev->local; 106 + list_for_each_entry(this, head, entry) { 107 if (identical(&this->addr, addr)) { 108 list_del(&this->entry); 109 spin_unlock_irqrestore(&dev->lock, flags); 110 kfree(this); 111 + if (head == &dev->local) 112 + notify_sigd(dev); 113 return 0; 114 } 115 } ··· 110 } 111 112 int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user * buf, 113 + size_t size, enum atm_addr_type_t atype) 114 { 115 unsigned long flags; 116 struct atm_dev_addr *this; 117 + struct list_head *head; 118 int total = 0, error; 119 struct sockaddr_atmsvc *tmp_buf, *tmp_bufp; 120 121 spin_lock_irqsave(&dev->lock, flags); 122 + if (atype == ATM_ADDR_LECS) 123 + head = &dev->lecs; 124 + else 125 + head = &dev->local; 126 + list_for_each_entry(this, head, entry) 127 total += sizeof(struct sockaddr_atmsvc); 128 tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC); 129 if (!tmp_buf) { 130 spin_unlock_irqrestore(&dev->lock, flags); 131 return -ENOMEM; 132 } 133 + list_for_each_entry(this, head, entry) 134 memcpy(tmp_bufp++, &this->addr, sizeof(struct sockaddr_atmsvc)); 135 spin_unlock_irqrestore(&dev->lock, flags); 136 error = total > size ? -E2BIG : total;
+7 -5
net/atm/addr.h
··· 9 #include <linux/atm.h> 10 #include <linux/atmdev.h> 11 12 - 13 - void atm_reset_addr(struct atm_dev *dev); 14 - int atm_add_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr); 15 - int atm_del_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr); 16 - int atm_get_addr(struct atm_dev *dev,struct sockaddr_atmsvc __user *buf,size_t size); 17 18 #endif
··· 9 #include <linux/atm.h> 10 #include <linux/atmdev.h> 11 12 + void atm_reset_addr(struct atm_dev *dev, enum atm_addr_type_t type); 13 + int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, 14 + enum atm_addr_type_t type); 15 + int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr, 16 + enum atm_addr_type_t type); 17 + int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user *buf, 18 + size_t size, enum atm_addr_type_t type); 19 20 #endif
+1 -1
net/atm/br2684.c
··· 220 /* netif_stop_queue(dev); */ 221 dev_kfree_skb(skb); 222 read_unlock(&devs_lock); 223 - return -EUNATCH; 224 } 225 if (!br2684_xmit_vcc(skb, brdev, brvcc)) { 226 /*
··· 220 /* netif_stop_queue(dev); */ 221 dev_kfree_skb(skb); 222 read_unlock(&devs_lock); 223 + return 0; 224 } 225 if (!br2684_xmit_vcc(skb, brdev, brvcc)) { 226 /*
+15 -5
net/atm/resources.c
··· 40 dev->link_rate = ATM_OC3_PCR; 41 spin_lock_init(&dev->lock); 42 INIT_LIST_HEAD(&dev->local); 43 44 return dev; 45 } ··· 321 error = -EPERM; 322 goto done; 323 } 324 - atm_reset_addr(dev); 325 break; 326 case ATM_ADDADDR: 327 case ATM_DELADDR: 328 if (!capable(CAP_NET_ADMIN)) { 329 error = -EPERM; 330 goto done; ··· 338 error = -EFAULT; 339 goto done; 340 } 341 - if (cmd == ATM_ADDADDR) 342 - error = atm_add_addr(dev, &addr); 343 else 344 - error = atm_del_addr(dev, &addr); 345 goto done; 346 } 347 case ATM_GETADDR: 348 - error = atm_get_addr(dev, buf, len); 349 if (error < 0) 350 goto done; 351 size = error;
··· 40 dev->link_rate = ATM_OC3_PCR; 41 spin_lock_init(&dev->lock); 42 INIT_LIST_HEAD(&dev->local); 43 + INIT_LIST_HEAD(&dev->lecs); 44 45 return dev; 46 } ··· 320 error = -EPERM; 321 goto done; 322 } 323 + atm_reset_addr(dev, ATM_ADDR_LOCAL); 324 break; 325 case ATM_ADDADDR: 326 case ATM_DELADDR: 327 + case ATM_ADDLECSADDR: 328 + case ATM_DELLECSADDR: 329 if (!capable(CAP_NET_ADMIN)) { 330 error = -EPERM; 331 goto done; ··· 335 error = -EFAULT; 336 goto done; 337 } 338 + if (cmd == ATM_ADDADDR || cmd == ATM_ADDLECSADDR) 339 + error = atm_add_addr(dev, &addr, 340 + (cmd == ATM_ADDADDR ? 341 + ATM_ADDR_LOCAL : ATM_ADDR_LECS)); 342 else 343 + error = atm_del_addr(dev, &addr, 344 + (cmd == ATM_DELADDR ? 345 + ATM_ADDR_LOCAL : ATM_ADDR_LECS)); 346 goto done; 347 } 348 case ATM_GETADDR: 349 + case ATM_GETLECSADDR: 350 + error = atm_get_addr(dev, buf, len, 351 + (cmd == ATM_GETADDR ? 352 + ATM_ADDR_LOCAL : ATM_ADDR_LECS)); 353 if (error < 0) 354 goto done; 355 size = error;
+227 -25
net/sctp/socket.c
··· 3159 return 0; 3160 } 3161 3162 - static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len, 3163 - char __user *optval, int __user *optlen) 3164 { 3165 sctp_assoc_t id; 3166 struct sctp_association *asoc; ··· 3186 return cnt; 3187 } 3188 3189 - static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, 3190 - char __user *optval, int __user *optlen) 3191 { 3192 struct sctp_association *asoc; 3193 struct list_head *pos; 3194 int cnt = 0; 3195 - struct sctp_getaddrs getaddrs; 3196 struct sctp_transport *from; 3197 void __user *to; 3198 union sctp_addr temp; 3199 struct sctp_sock *sp = sctp_sk(sk); 3200 int addrlen; 3201 3202 - if (len != sizeof(struct sctp_getaddrs)) 3203 return -EINVAL; 3204 3205 - if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs))) 3206 return -EFAULT; 3207 3208 if (getaddrs.addr_num <= 0) return -EINVAL; ··· 3231 if (cnt >= getaddrs.addr_num) break; 3232 } 3233 getaddrs.addr_num = cnt; 3234 - if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs))) 3235 return -EFAULT; 3236 3237 return 0; 3238 } 3239 3240 - static int sctp_getsockopt_local_addrs_num(struct sock *sk, int len, 3241 - char __user *optval, 3242 - int __user *optlen) 3243 { 3244 sctp_assoc_t id; 3245 struct sctp_bind_addr *bp; ··· 3366 /* Helper function that copies local addresses to user and returns the number 3367 * of addresses copied. 3368 */ 3369 - static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, int max_addrs, 3370 - void __user *to) 3371 { 3372 struct list_head *pos; 3373 struct sctp_sockaddr_entry *addr; ··· 3401 return cnt; 3402 } 3403 3404 - static int sctp_getsockopt_local_addrs(struct sock *sk, int len, 3405 - char __user *optval, int __user *optlen) 3406 { 3407 struct sctp_bind_addr *bp; 3408 struct sctp_association *asoc; 3409 struct list_head *pos; 3410 int cnt = 0; 3411 - struct sctp_getaddrs getaddrs; 3412 struct sctp_sockaddr_entry *addr; 3413 void __user *to; 3414 union sctp_addr temp; ··· 3457 rwlock_t *addr_lock; 3458 int err = 0; 3459 3460 - if (len != sizeof(struct sctp_getaddrs)) 3461 return -EINVAL; 3462 3463 - if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs))) 3464 return -EFAULT; 3465 3466 if (getaddrs.addr_num <= 0) return -EINVAL; ··· 3492 addr = list_entry(bp->address_list.next, 3493 struct sctp_sockaddr_entry, list); 3494 if (sctp_is_any(&addr->a)) { 3495 - cnt = sctp_copy_laddrs_to_user(sk, bp->port, 3496 - getaddrs.addr_num, to); 3497 if (cnt < 0) { 3498 err = cnt; 3499 goto unlock; ··· 3520 3521 copy_getaddrs: 3522 getaddrs.addr_num = cnt; 3523 - if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs))) 3524 err = -EFAULT; 3525 3526 unlock: 3527 sctp_read_unlock(addr_lock); ··· 4001 case SCTP_INITMSG: 4002 retval = sctp_getsockopt_initmsg(sk, len, optval, optlen); 4003 break; 4004 - case SCTP_GET_PEER_ADDRS_NUM: 4005 - retval = sctp_getsockopt_peer_addrs_num(sk, len, optval, 4006 optlen); 4007 break; 4008 - case SCTP_GET_LOCAL_ADDRS_NUM: 4009 - retval = sctp_getsockopt_local_addrs_num(sk, len, optval, 4010 optlen); 4011 break; 4012 case SCTP_GET_PEER_ADDRS:
··· 3159 return 0; 3160 } 3161 3162 + static int sctp_getsockopt_peer_addrs_num_old(struct sock *sk, int len, 3163 + char __user *optval, 3164 + int __user *optlen) 3165 { 3166 sctp_assoc_t id; 3167 struct sctp_association *asoc; ··· 3185 return cnt; 3186 } 3187 3188 + /* 3189 + * Old API for getting list of peer addresses. Does not work for 32-bit 3190 + * programs running on a 64-bit kernel 3191 + */ 3192 + static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len, 3193 + char __user *optval, 3194 + int __user *optlen) 3195 { 3196 struct sctp_association *asoc; 3197 struct list_head *pos; 3198 int cnt = 0; 3199 + struct sctp_getaddrs_old getaddrs; 3200 struct sctp_transport *from; 3201 void __user *to; 3202 union sctp_addr temp; 3203 struct sctp_sock *sp = sctp_sk(sk); 3204 int addrlen; 3205 3206 + if (len != sizeof(struct sctp_getaddrs_old)) 3207 return -EINVAL; 3208 3209 + if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs_old))) 3210 return -EFAULT; 3211 3212 if (getaddrs.addr_num <= 0) return -EINVAL; ··· 3225 if (cnt >= getaddrs.addr_num) break; 3226 } 3227 getaddrs.addr_num = cnt; 3228 + if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs_old))) 3229 return -EFAULT; 3230 3231 return 0; 3232 } 3233 3234 + static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, 3235 + char __user *optval, int __user *optlen) 3236 + { 3237 + struct sctp_association *asoc; 3238 + struct list_head *pos; 3239 + int cnt = 0; 3240 + struct sctp_getaddrs getaddrs; 3241 + struct sctp_transport *from; 3242 + void __user *to; 3243 + union sctp_addr temp; 3244 + struct sctp_sock *sp = sctp_sk(sk); 3245 + int addrlen; 3246 + size_t space_left; 3247 + int bytes_copied; 3248 + 3249 + if (len < sizeof(struct sctp_getaddrs)) 3250 + return -EINVAL; 3251 + 3252 + if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs))) 3253 + return -EFAULT; 3254 + 3255 + /* For UDP-style sockets, id specifies the association to query. */ 3256 + asoc = sctp_id2assoc(sk, getaddrs.assoc_id); 3257 + if (!asoc) 3258 + return -EINVAL; 3259 + 3260 + to = optval + offsetof(struct sctp_getaddrs,addrs); 3261 + space_left = len - sizeof(struct sctp_getaddrs) - 3262 + offsetof(struct sctp_getaddrs,addrs); 3263 + 3264 + list_for_each(pos, &asoc->peer.transport_addr_list) { 3265 + from = list_entry(pos, struct sctp_transport, transports); 3266 + memcpy(&temp, &from->ipaddr, sizeof(temp)); 3267 + sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); 3268 + addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len; 3269 + if(space_left < addrlen) 3270 + return -ENOMEM; 3271 + temp.v4.sin_port = htons(temp.v4.sin_port); 3272 + if (copy_to_user(to, &temp, addrlen)) 3273 + return -EFAULT; 3274 + to += addrlen; 3275 + cnt++; 3276 + space_left -= addrlen; 3277 + } 3278 + 3279 + if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num)) 3280 + return -EFAULT; 3281 + bytes_copied = ((char __user *)to) - optval; 3282 + if (put_user(bytes_copied, optlen)) 3283 + return -EFAULT; 3284 + 3285 + return 0; 3286 + } 3287 + 3288 + static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len, 3289 + char __user *optval, 3290 + int __user *optlen) 3291 { 3292 sctp_assoc_t id; 3293 struct sctp_bind_addr *bp; ··· 3306 /* Helper function that copies local addresses to user and returns the number 3307 * of addresses copied. 3308 */ 3309 + static int sctp_copy_laddrs_to_user_old(struct sock *sk, __u16 port, int max_addrs, 3310 + void __user *to) 3311 { 3312 struct list_head *pos; 3313 struct sctp_sockaddr_entry *addr; ··· 3341 return cnt; 3342 } 3343 3344 + static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, 3345 + void * __user *to, size_t space_left) 3346 + { 3347 + struct list_head *pos; 3348 + struct sctp_sockaddr_entry *addr; 3349 + unsigned long flags; 3350 + union sctp_addr temp; 3351 + int cnt = 0; 3352 + int addrlen; 3353 + 3354 + sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); 3355 + list_for_each(pos, &sctp_local_addr_list) { 3356 + addr = list_entry(pos, struct sctp_sockaddr_entry, list); 3357 + if ((PF_INET == sk->sk_family) && 3358 + (AF_INET6 == addr->a.sa.sa_family)) 3359 + continue; 3360 + memcpy(&temp, &addr->a, sizeof(temp)); 3361 + sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), 3362 + &temp); 3363 + addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; 3364 + if(space_left<addrlen) 3365 + return -ENOMEM; 3366 + temp.v4.sin_port = htons(port); 3367 + if (copy_to_user(*to, &temp, addrlen)) { 3368 + sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, 3369 + flags); 3370 + return -EFAULT; 3371 + } 3372 + *to += addrlen; 3373 + cnt ++; 3374 + space_left -= addrlen; 3375 + } 3376 + sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags); 3377 + 3378 + return cnt; 3379 + } 3380 + 3381 + /* Old API for getting list of local addresses. Does not work for 32-bit 3382 + * programs running on a 64-bit kernel 3383 + */ 3384 + static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len, 3385 + char __user *optval, int __user *optlen) 3386 { 3387 struct sctp_bind_addr *bp; 3388 struct sctp_association *asoc; 3389 struct list_head *pos; 3390 int cnt = 0; 3391 + struct sctp_getaddrs_old getaddrs; 3392 struct sctp_sockaddr_entry *addr; 3393 void __user *to; 3394 union sctp_addr temp; ··· 3357 rwlock_t *addr_lock; 3358 int err = 0; 3359 3360 + if (len != sizeof(struct sctp_getaddrs_old)) 3361 return -EINVAL; 3362 3363 + if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs_old))) 3364 return -EFAULT; 3365 3366 if (getaddrs.addr_num <= 0) return -EINVAL; ··· 3392 addr = list_entry(bp->address_list.next, 3393 struct sctp_sockaddr_entry, list); 3394 if (sctp_is_any(&addr->a)) { 3395 + cnt = sctp_copy_laddrs_to_user_old(sk, bp->port, 3396 + getaddrs.addr_num, 3397 + to); 3398 if (cnt < 0) { 3399 err = cnt; 3400 goto unlock; ··· 3419 3420 copy_getaddrs: 3421 getaddrs.addr_num = cnt; 3422 + if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs_old))) 3423 err = -EFAULT; 3424 + 3425 + unlock: 3426 + sctp_read_unlock(addr_lock); 3427 + return err; 3428 + } 3429 + 3430 + static int sctp_getsockopt_local_addrs(struct sock *sk, int len, 3431 + char __user *optval, int __user *optlen) 3432 + { 3433 + struct sctp_bind_addr *bp; 3434 + struct sctp_association *asoc; 3435 + struct list_head *pos; 3436 + int cnt = 0; 3437 + struct sctp_getaddrs getaddrs; 3438 + struct sctp_sockaddr_entry *addr; 3439 + void __user *to; 3440 + union sctp_addr temp; 3441 + struct sctp_sock *sp = sctp_sk(sk); 3442 + int addrlen; 3443 + rwlock_t *addr_lock; 3444 + int err = 0; 3445 + size_t space_left; 3446 + int bytes_copied; 3447 + 3448 + if (len <= sizeof(struct sctp_getaddrs)) 3449 + return -EINVAL; 3450 + 3451 + if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs))) 3452 + return -EFAULT; 3453 + 3454 + /* 3455 + * For UDP-style sockets, id specifies the association to query. 3456 + * If the id field is set to the value '0' then the locally bound 3457 + * addresses are returned without regard to any particular 3458 + * association. 3459 + */ 3460 + if (0 == getaddrs.assoc_id) { 3461 + bp = &sctp_sk(sk)->ep->base.bind_addr; 3462 + addr_lock = &sctp_sk(sk)->ep->base.addr_lock; 3463 + } else { 3464 + asoc = sctp_id2assoc(sk, getaddrs.assoc_id); 3465 + if (!asoc) 3466 + return -EINVAL; 3467 + bp = &asoc->base.bind_addr; 3468 + addr_lock = &asoc->base.addr_lock; 3469 + } 3470 + 3471 + to = optval + offsetof(struct sctp_getaddrs,addrs); 3472 + space_left = len - sizeof(struct sctp_getaddrs) - 3473 + offsetof(struct sctp_getaddrs,addrs); 3474 + 3475 + sctp_read_lock(addr_lock); 3476 + 3477 + /* If the endpoint is bound to 0.0.0.0 or ::0, get the valid 3478 + * addresses from the global local address list. 3479 + */ 3480 + if (sctp_list_single_entry(&bp->address_list)) { 3481 + addr = list_entry(bp->address_list.next, 3482 + struct sctp_sockaddr_entry, list); 3483 + if (sctp_is_any(&addr->a)) { 3484 + cnt = sctp_copy_laddrs_to_user(sk, bp->port, 3485 + &to, space_left); 3486 + if (cnt < 0) { 3487 + err = cnt; 3488 + goto unlock; 3489 + } 3490 + goto copy_getaddrs; 3491 + } 3492 + } 3493 + 3494 + list_for_each(pos, &bp->address_list) { 3495 + addr = list_entry(pos, struct sctp_sockaddr_entry, list); 3496 + memcpy(&temp, &addr->a, sizeof(temp)); 3497 + sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); 3498 + addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; 3499 + if(space_left < addrlen) 3500 + return -ENOMEM; /*fixme: right error?*/ 3501 + temp.v4.sin_port = htons(temp.v4.sin_port); 3502 + if (copy_to_user(to, &temp, addrlen)) { 3503 + err = -EFAULT; 3504 + goto unlock; 3505 + } 3506 + to += addrlen; 3507 + cnt ++; 3508 + space_left -= addrlen; 3509 + } 3510 + 3511 + copy_getaddrs: 3512 + if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num)) 3513 + return -EFAULT; 3514 + bytes_copied = ((char __user *)to) - optval; 3515 + if (put_user(bytes_copied, optlen)) 3516 + return -EFAULT; 3517 3518 unlock: 3519 sctp_read_unlock(addr_lock); ··· 3807 case SCTP_INITMSG: 3808 retval = sctp_getsockopt_initmsg(sk, len, optval, optlen); 3809 break; 3810 + case SCTP_GET_PEER_ADDRS_NUM_OLD: 3811 + retval = sctp_getsockopt_peer_addrs_num_old(sk, len, optval, 3812 + optlen); 3813 + break; 3814 + case SCTP_GET_LOCAL_ADDRS_NUM_OLD: 3815 + retval = sctp_getsockopt_local_addrs_num_old(sk, len, optval, 3816 + optlen); 3817 + break; 3818 + case SCTP_GET_PEER_ADDRS_OLD: 3819 + retval = sctp_getsockopt_peer_addrs_old(sk, len, optval, 3820 optlen); 3821 break; 3822 + case SCTP_GET_LOCAL_ADDRS_OLD: 3823 + retval = sctp_getsockopt_local_addrs_old(sk, len, optval, 3824 optlen); 3825 break; 3826 case SCTP_GET_PEER_ADDRS: