patch-2.4.0-prerelease linux/net/atm/common.c
Next file: linux/net/atm/lec.c
Previous file: linux/net/atm/addr.c
Back to the patch index
Back to the overall index
- Lines: 565
- Date:
Fri Dec 29 14:35:47 2000
- Orig file:
v2.4.0-test12/linux/net/atm/common.c
- Orig date:
Thu Jul 6 21:37:24 2000
diff -u --recursive --new-file v2.4.0-test12/linux/net/atm/common.c linux/net/atm/common.c
@@ -72,6 +72,7 @@
#define DPRINTK(format,args...)
#endif
+spinlock_t atm_dev_lock = SPIN_LOCK_UNLOCKED;
static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
{
@@ -139,13 +140,19 @@
vcc->dev->ops->free_rx_skb(vcc,skb);
else kfree_skb(skb);
}
+ spin_lock (&atm_dev_lock);
+ fops_put (vcc->dev->ops);
if (atomic_read(&vcc->rx_inuse))
printk(KERN_WARNING "atm_release_vcc: strange ... "
"rx_inuse == %d after closing\n",
atomic_read(&vcc->rx_inuse));
bind_vcc(vcc,NULL);
- }
+ } else
+ spin_lock (&atm_dev_lock);
+
if (free_sk) free_atm_vcc_sk(sk);
+
+ spin_unlock (&atm_dev_lock);
}
@@ -238,9 +245,11 @@
vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu);
DPRINTK(" RX: %d, PCR %d..%d, SDU %d\n",vcc->qos.rxtp.traffic_class,
vcc->qos.rxtp.min_pcr,vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu);
+ fops_get (dev->ops);
if (dev->ops->open) {
error = dev->ops->open(vcc,vpi,vci);
if (error) {
+ fops_put (dev->ops);
bind_vcc(vcc,NULL);
return error;
}
@@ -252,10 +261,18 @@
static int atm_do_connect(struct atm_vcc *vcc,int itf,int vpi,int vci)
{
struct atm_dev *dev;
+ int return_val;
+ spin_lock (&atm_dev_lock);
dev = atm_find_dev(itf);
- if (!dev) return -ENODEV;
- return atm_do_connect_dev(vcc,dev,vpi,vci);
+ if (!dev)
+ return_val = -ENODEV;
+ else
+ return_val = atm_do_connect_dev(vcc,dev,vpi,vci);
+
+ spin_unlock (&atm_dev_lock);
+
+ return return_val;
}
@@ -285,8 +302,10 @@
else {
struct atm_dev *dev;
+ spin_lock (&atm_dev_lock);
for (dev = atm_devs; dev; dev = dev->next)
if (!atm_do_connect_dev(vcc,dev,vpi,vci)) break;
+ spin_unlock (&atm_dev_lock);
if (!dev) return -ENODEV;
}
if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC)
@@ -523,57 +542,86 @@
struct atm_vcc *vcc;
int *tmp_buf;
void *buf;
- int error,len,size,number;
+ int error,len,size,number, ret_val;
+ ret_val = 0;
+ spin_lock (&atm_dev_lock);
vcc = ATM_SD(sock);
switch (cmd) {
case SIOCOUTQ:
if (sock->state != SS_CONNECTED ||
- !test_bit(ATM_VF_READY,&vcc->flags))
- return -EINVAL;
- return put_user(vcc->sk->sndbuf-
+ !test_bit(ATM_VF_READY,&vcc->flags)) {
+ ret_val = -EINVAL;
+ goto done;
+ }
+ ret_val = put_user(vcc->sk->sndbuf-
atomic_read(&vcc->tx_inuse)-ATM_PDU_OVHD,
(int *) arg) ? -EFAULT : 0;
+ goto done;
case SIOCINQ:
{
struct sk_buff *skb;
- if (sock->state != SS_CONNECTED)
- return -EINVAL;
+ if (sock->state != SS_CONNECTED) {
+ ret_val = -EINVAL;
+ goto done;
+ }
skb = skb_peek(&vcc->recvq);
- return put_user(skb ? skb->len : 0,(int *) arg)
+ ret_val = put_user(skb ? skb->len : 0,(int *) arg)
? -EFAULT : 0;
+ goto done;
}
case ATM_GETNAMES:
if (get_user(buf,
- &((struct atm_iobuf *) arg)->buffer))
- return -EFAULT;
+ &((struct atm_iobuf *) arg)->buffer)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
if (get_user(len,
- &((struct atm_iobuf *) arg)->length))
- return -EFAULT;
+ &((struct atm_iobuf *) arg)->length)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
size = 0;
for (dev = atm_devs; dev; dev = dev->next)
size += sizeof(int);
- if (size > len) return -E2BIG;
+ if (size > len) {
+ ret_val = -E2BIG;
+ goto done;
+ }
tmp_buf = kmalloc(size,GFP_KERNEL);
- if (!tmp_buf) return -ENOMEM;
+ if (!tmp_buf) {
+ ret_val = -ENOMEM;
+ goto done;
+ }
for (dev = atm_devs; dev; dev = dev->next)
*tmp_buf++ = dev->number;
- if (copy_to_user(buf,(char *) tmp_buf-size,size))
- return -EFAULT;
- return put_user(size,
+ if (copy_to_user(buf,(char *) tmp_buf-size,size)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
+ ret_val = put_user(size,
&((struct atm_iobuf *) arg)->length) ? -EFAULT : 0;
+ goto done;
case SIOCGSTAMP: /* borrowed from IP */
- if (!vcc->timestamp.tv_sec) return -ENOENT;
+ if (!vcc->timestamp.tv_sec) {
+ ret_val = -ENOENT;
+ goto done;
+ }
vcc->timestamp.tv_sec += vcc->timestamp.tv_usec/1000000;
vcc->timestamp.tv_usec %= 1000000;
- return copy_to_user((void *) arg,&vcc->timestamp,
+ ret_val = copy_to_user((void *) arg,&vcc->timestamp,
sizeof(struct timeval)) ? -EFAULT : 0;
+ goto done;
case ATM_SETSC:
printk(KERN_WARNING "ATM_SETSC is obsolete\n");
- return 0;
+ ret_val = 0;
+ goto done;
case ATMSIGD_CTRL:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
/*
* The user/kernel protocol for exchanging signalling
* info uses kernel pointers as opaque references,
@@ -581,175 +629,308 @@
* on the kernel... so we should make sure that we
* have the same privledges that /proc/kcore needs
*/
- if (!capable(CAP_SYS_RAWIO)) return -EPERM;
+ if (!capable(CAP_SYS_RAWIO)) {
+ ret_val = -EPERM;
+ goto done;
+ }
error = sigd_attach(vcc);
if (!error) sock->state = SS_CONNECTED;
- return error;
+ ret_val = error;
+ goto done;
#ifdef CONFIG_ATM_CLIP
case SIOCMKCLIP:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- return clip_create(arg);
+ if (!capable(CAP_NET_ADMIN))
+ ret_val = -EPERM;
+ else
+ ret_val = clip_create(arg);
+ goto done;
case ATMARPD_CTRL:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
error = atm_init_atmarp(vcc);
if (!error) sock->state = SS_CONNECTED;
- return error;
+ ret_val = error;
+ goto done;
case ATMARP_MKIP:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- return clip_mkip(vcc,arg);
+ if (!capable(CAP_NET_ADMIN))
+ ret_val = -EPERM;
+ else
+ ret_val = clip_mkip(vcc,arg);
+ goto done;
case ATMARP_SETENTRY:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- return clip_setentry(vcc,arg);
+ if (!capable(CAP_NET_ADMIN))
+ ret_val = -EPERM;
+ else
+ ret_val = clip_setentry(vcc,arg);
+ goto done;
case ATMARP_ENCAP:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- return clip_encap(vcc,arg);
+ if (!capable(CAP_NET_ADMIN))
+ ret_val = -EPERM;
+ else
+ ret_val = clip_encap(vcc,arg);
+ goto done;
#endif
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
case ATMLEC_CTRL:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
if (atm_lane_ops.lecd_attach == NULL)
atm_lane_init();
- if (atm_lane_ops.lecd_attach == NULL) /* try again */
- return -ENOSYS;
- error = atm_lane_ops.lecd_attach(vcc, (int)arg);
- if (error >= 0) sock->state = SS_CONNECTED;
- return error;
+ if (atm_lane_ops.lecd_attach == NULL) { /* try again */
+ ret_val = -ENOSYS;
+ goto done;
+ }
+ error = atm_lane_ops.lecd_attach(vcc, (int)arg);
+ if (error >= 0) sock->state = SS_CONNECTED;
+ ret_val = error;
+ goto done;
case ATMLEC_MCAST:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- return atm_lane_ops.mcast_attach(vcc, (int)arg);
+ if (!capable(CAP_NET_ADMIN))
+ ret_val = -EPERM;
+ else
+ ret_val = atm_lane_ops.mcast_attach(vcc, (int)arg);
+ goto done;
case ATMLEC_DATA:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- return atm_lane_ops.vcc_attach(vcc, (void*)arg);
+ if (!capable(CAP_NET_ADMIN))
+ ret_val = -EPERM;
+ else
+ ret_val = atm_lane_ops.vcc_attach(vcc, (void*)arg);
+ goto done;
#endif
#if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
case ATMMPC_CTRL:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- if (atm_mpoa_ops.mpoad_attach == NULL)
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
+ if (atm_mpoa_ops.mpoad_attach == NULL)
atm_mpoa_init();
- if (atm_mpoa_ops.mpoad_attach == NULL) /* try again */
- return -ENOSYS;
- error = atm_mpoa_ops.mpoad_attach(vcc, (int)arg);
- if (error >= 0) sock->state = SS_CONNECTED;
- return error;
+ if (atm_mpoa_ops.mpoad_attach == NULL) { /* try again */
+ ret_val = -ENOSYS;
+ goto done;
+ }
+ error = atm_mpoa_ops.mpoad_attach(vcc, (int)arg);
+ if (error >= 0) sock->state = SS_CONNECTED;
+ ret_val = error;
+ goto done;
case ATMMPC_DATA:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- return atm_mpoa_ops.vcc_attach(vcc, arg);
+ if (!capable(CAP_NET_ADMIN))
+ ret_val = -EPERM;
+ else
+ ret_val = atm_mpoa_ops.vcc_attach(vcc, arg);
+ goto done;
#endif
#if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
case SIOCSIFATMTCP:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- if (!atm_tcp_ops.attach) return -ENOPKG;
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
+ if (!atm_tcp_ops.attach) {
+ ret_val = -ENOPKG;
+ goto done;
+ }
+ fops_get (&atm_tcp_ops);
error = atm_tcp_ops.attach(vcc,(int) arg);
if (error >= 0) sock->state = SS_CONNECTED;
- return error;
+ else fops_put (&atm_tcp_ops);
+ ret_val = error;
+ goto done;
case ATMTCP_CREATE:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- if (!atm_tcp_ops.create_persistent) return -ENOPKG;
- return atm_tcp_ops.create_persistent((int) arg);
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
+ if (!atm_tcp_ops.create_persistent) {
+ ret_val = -ENOPKG;
+ goto done;
+ }
+ error = atm_tcp_ops.create_persistent((int) arg);
+ if (error < 0) fops_put (&atm_tcp_ops);
+ ret_val = error;
+ goto done;
case ATMTCP_REMOVE:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- if (!atm_tcp_ops.remove_persistent) return -ENOPKG;
- return atm_tcp_ops.remove_persistent((int) arg);
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
+ if (!atm_tcp_ops.remove_persistent) {
+ ret_val = -ENOPKG;
+ goto done;
+ }
+ error = atm_tcp_ops.remove_persistent((int) arg);
+ fops_put (&atm_tcp_ops);
+ ret_val = error;
+ goto done;
#endif
default:
break;
}
- if (get_user(buf,&((struct atmif_sioc *) arg)->arg)) return -EFAULT;
- if (get_user(len,&((struct atmif_sioc *) arg)->length)) return -EFAULT;
- if (get_user(number,&((struct atmif_sioc *) arg)->number))
- return -EFAULT;
- if (!(dev = atm_find_dev(number))) return -ENODEV;
+ if (get_user(buf,&((struct atmif_sioc *) arg)->arg)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
+ if (get_user(len,&((struct atmif_sioc *) arg)->length)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
+ if (get_user(number,&((struct atmif_sioc *) arg)->number)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
+ if (!(dev = atm_find_dev(number))) {
+ ret_val = -ENODEV;
+ goto done;
+ }
+
size = 0;
switch (cmd) {
case ATM_GETTYPE:
size = strlen(dev->type)+1;
- if (copy_to_user(buf,dev->type,size)) return -EFAULT;
+ if (copy_to_user(buf,dev->type,size)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
break;
case ATM_GETESI:
size = ESI_LEN;
- if (copy_to_user(buf,dev->esi,size)) return -EFAULT;
+ if (copy_to_user(buf,dev->esi,size)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
break;
case ATM_SETESI:
{
int i;
for (i = 0; i < ESI_LEN; i++)
- if (dev->esi[i]) return -EEXIST;
+ if (dev->esi[i]) {
+ ret_val = -EEXIST;
+ goto done;
+ }
}
/* fall through */
case ATM_SETESIF:
{
unsigned char esi[ESI_LEN];
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- if (copy_from_user(esi,buf,ESI_LEN))
- return -EFAULT;
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
+ if (copy_from_user(esi,buf,ESI_LEN)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
memcpy(dev->esi,esi,ESI_LEN);
- return ESI_LEN;
+ ret_val = ESI_LEN;
+ goto done;
}
case ATM_GETSTATZ:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
/* fall through */
case ATM_GETSTAT:
size = sizeof(struct atm_dev_stats);
error = fetch_stats(dev,buf,cmd == ATM_GETSTATZ);
- if (error) return error;
+ if (error) {
+ ret_val = error;
+ goto done;
+ }
break;
case ATM_GETCIRANGE:
size = sizeof(struct atm_cirange);
- if (copy_to_user(buf,&dev->ci_range,size))
- return -EFAULT;
+ if (copy_to_user(buf,&dev->ci_range,size)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
break;
case ATM_GETLINKRATE:
size = sizeof(int);
- if (copy_to_user(buf,&dev->link_rate,size))
- return -EFAULT;
+ if (copy_to_user(buf,&dev->link_rate,size)) {
+ ret_val = -EFAULT;
+ goto done;
+ }
break;
case ATM_RSTADDR:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
reset_addr(dev);
break;
case ATM_ADDADDR:
case ATM_DELADDR:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
{
struct sockaddr_atmsvc addr;
- if (copy_from_user(&addr,buf,sizeof(addr)))
- return -EFAULT;
+ if (copy_from_user(&addr,buf,sizeof(addr))) {
+ ret_val = -EFAULT;
+ goto done;
+ }
if (cmd == ATM_ADDADDR)
- return add_addr(dev,&addr);
- else return del_addr(dev,&addr);
+ ret_val = add_addr(dev,&addr);
+ else
+ ret_val = del_addr(dev,&addr);
+ goto done;
}
case ATM_GETADDR:
size = get_addr(dev,buf,len);
- if (size < 0) return size;
+ if (size < 0)
+ ret_val = size;
+ else
/* may return 0, but later on size == 0 means "don't
write the length" */
- return put_user(size,
- &((struct atmif_sioc *) arg)->length) ? -EFAULT : 0;
+ ret_val = put_user(size,
+ &((struct atmif_sioc *) arg)->length) ? -EFAULT : 0;
+ goto done;
case ATM_SETLOOP:
if (__ATM_LM_XTRMT((int) (long) buf) &&
__ATM_LM_XTLOC((int) (long) buf) >
- __ATM_LM_XTRMT((int) (long) buf))
- return -EINVAL;
+ __ATM_LM_XTRMT((int) (long) buf)) {
+ ret_val = -EINVAL;
+ goto done;
+ }
/* fall through */
case ATM_SETCIRANGE:
case SONET_GETSTATZ:
case SONET_SETDIAG:
case SONET_CLRDIAG:
case SONET_SETFRAMING:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ if (!capable(CAP_NET_ADMIN)) {
+ ret_val = -EPERM;
+ goto done;
+ }
/* fall through */
default:
- if (!dev->ops->ioctl) return -EINVAL;
+ if (!dev->ops->ioctl) {
+ ret_val = -EINVAL;
+ goto done;
+ }
size = dev->ops->ioctl(dev,cmd,buf);
- if (size < 0)
- return size == -ENOIOCTLCMD ? -EINVAL : size;
+ if (size < 0) {
+ ret_val = (size == -ENOIOCTLCMD ? -EINVAL : size);
+ goto done;
+ }
}
- if (!size) return 0;
- return put_user(size,&((struct atmif_sioc *) arg)->length) ?
- -EFAULT : 0;
+
+ if (size)
+ ret_val = put_user(size,&((struct atmif_sioc *) arg)->length) ?
+ -EFAULT : 0;
+
+ done:
+ spin_unlock (&atm_dev_lock);
+ return ret_val;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)