⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 common.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		case ATM_GETNAMES:			if (get_user(buf,				     &((struct atm_iobuf *) arg)->buffer)) {				ret_val = -EFAULT;				goto done;			}			if (get_user(len,				     &((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) {				ret_val = -E2BIG;				goto done;			}			tmp_buf = kmalloc(size,GFP_KERNEL);			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)) {				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) {				ret_val = -ENOENT;				goto done;			}			vcc->timestamp.tv_sec += vcc->timestamp.tv_usec/1000000;			vcc->timestamp.tv_usec %= 1000000;			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");			ret_val = 0;			goto done;		case ATMSIGD_CTRL:			if (!capable(CAP_NET_ADMIN)) {				ret_val = -EPERM;				goto done;			}			/*			 * The user/kernel protocol for exchanging signalling			 * info uses kernel pointers as opaque references,			 * so the holder of the file descriptor can scribble			 * on the kernel... so we should make sure that we			 * have the same privledges that /proc/kcore needs			 */			if (!capable(CAP_SYS_RAWIO)) {				ret_val = -EPERM;				goto done;			}			error = sigd_attach(vcc);			if (!error) sock->state = SS_CONNECTED;			ret_val = error;			goto done;#ifdef CONFIG_ATM_CLIP		case SIOCMKCLIP:			if (!capable(CAP_NET_ADMIN))				ret_val = -EPERM;			else 				ret_val = clip_create(arg);			goto done;		case ATMARPD_CTRL:			if (!capable(CAP_NET_ADMIN)) {				ret_val = -EPERM;				goto done;			}			error = atm_init_atmarp(vcc);			if (!error) sock->state = SS_CONNECTED;			ret_val = error;			goto done;		case ATMARP_MKIP:			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)) 				ret_val = -EPERM;			else				ret_val = clip_setentry(vcc,arg);			goto done;		case ATMARP_ENCAP:			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)) {				ret_val = -EPERM;				goto done;			}                        if (atm_lane_ops.lecd_attach == NULL)				atm_lane_init();                        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))				ret_val = -EPERM;			else				ret_val = atm_lane_ops.mcast_attach(vcc, (int)arg);			goto done;                case ATMLEC_DATA:			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)) {				ret_val = -EPERM;				goto done;			}			if (atm_mpoa_ops.mpoad_attach == NULL)                                atm_mpoa_init();			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)) 				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)) {				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;			else            fops_put (&atm_tcp_ops);			ret_val = error;			goto done;		case ATMTCP_CREATE:			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)) {				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)) {		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)) {				ret_val = -EFAULT;				goto done;			}			break;		case ATM_GETESI:			size = ESI_LEN;			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]) {						ret_val = -EEXIST;						goto done;					}			}			/* fall through */		case ATM_SETESIF:			{				unsigned char esi[ESI_LEN];				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);				ret_val =  ESI_LEN;				goto done;			}		case ATM_GETSTATZ:			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) {				ret_val = error;				goto done;			}			break;		case ATM_GETCIRANGE:			size = sizeof(struct atm_cirange);			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)) {				ret_val = -EFAULT;				goto done;			}			break;		case ATM_RSTADDR:			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)) {				ret_val = -EPERM;				goto done;			}			{				struct sockaddr_atmsvc addr;				if (copy_from_user(&addr,buf,sizeof(addr))) {					ret_val = -EFAULT;					goto done;				}				if (cmd == ATM_ADDADDR)					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)				ret_val = size;			else			/* may return 0, but later on size == 0 means "don't			   write the length" */				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)) {				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)) {				ret_val = -EPERM;				goto done;			}			/* fall through */		default:			if (!dev->ops->ioctl) {				ret_val = -EINVAL;				goto done;			}			size = dev->ops->ioctl(dev,cmd,buf);			if (size < 0) {				ret_val = (size == -ENOIOCTLCMD ? -EINVAL : size);				goto done;			}	}		if (size)		ret_val =  put_user(size,&((struct atmif_sioc *) arg)->length) ?			-EFAULT : 0; done:	spin_unlock (&atm_dev_lock); 	return ret_val;}static int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos){	int error;	/*	 * Don't let the QoS change the already connected AAL type nor the	 * traffic class.	 */	if (qos->aal != vcc->qos.aal ||	    qos->rxtp.traffic_class != vcc->qos.rxtp.traffic_class ||	    qos->txtp.traffic_class != vcc->qos.txtp.traffic_class)		return -EINVAL;	error = adjust_tp(&qos->txtp,qos->aal);	if (!error) error = adjust_tp(&qos->rxtp,qos->aal);	if (error) return error;	if (!vcc->dev->ops->change_qos) return -EOPNOTSUPP;	if (vcc->family == AF_ATMPVC)		return vcc->dev->ops->change_qos(vcc,qos,ATM_MF_SET);	return svc_change_qos(vcc,qos);}static int check_tp(struct atm_trafprm *tp){	/* @@@ Should be merged with adjust_tp */	if (!tp->traffic_class || tp->traffic_class == ATM_ANYCLASS) return 0;	if (tp->traffic_class != ATM_UBR && !tp->min_pcr && !tp->pcr &&	    !tp->max_pcr) return -EINVAL;	if (tp->min_pcr == ATM_MAX_PCR) return -EINVAL;	if (tp->min_pcr && tp->max_pcr && tp->max_pcr != ATM_MAX_PCR &&	    tp->min_pcr > tp->max_pcr) return -EINVAL;	/*	 * We allow pcr to be outside [min_pcr,max_pcr], because later	 * adjustment may still push it in the valid range.	 */	return 0;}static int check_qos(struct atm_qos *qos){	int error;	if (!qos->txtp.traffic_class && !qos->rxtp.traffic_class)                return -EINVAL;	if (qos->txtp.traffic_class != qos->rxtp.traffic_class &&	    qos->txtp.traffic_class && qos->rxtp.traffic_class &&	    qos->txtp.traffic_class != ATM_ANYCLASS &&	    qos->rxtp.traffic_class != ATM_ANYCLASS) return -EINVAL;	error = check_tp(&qos->txtp);	if (error) return error;	return check_tp(&qos->rxtp);}static int atm_do_setsockopt(struct socket *sock,int level,int optname,    void *optval,int optlen){	struct atm_vcc *vcc;	unsigned long value;	int error;	vcc = ATM_SD(sock);	switch (optname) {		case SO_ATMQOS:			{				struct atm_qos qos;				if (copy_from_user(&qos,optval,sizeof(qos)))					return -EFAULT;				error = check_qos(&qos);				if (error) return error;				if (sock->state == SS_CONNECTED)					return atm_change_qos(vcc,&qos);				if (sock->state != SS_UNCONNECTED)					return -EBADFD;				vcc->qos = qos;				set_bit(ATM_VF_HASQOS,&vcc->flags);				return 0;			}		case SO_SETCLP:			if (get_user(value,(unsigned long *) optval))				return -EFAULT;			if (value) vcc->atm_options |= ATM_ATMOPT_CLP;			else vcc->atm_options &= ~ATM_ATMOPT_CLP;			return 0;		default:			if (level == SOL_SOCKET) return -EINVAL;			break;	}	if (!vcc->dev || !vcc->dev->ops->setsockopt) return -EINVAL;	return vcc->dev->ops->setsockopt(vcc,level,optname,optval,optlen);}static int atm_do_getsockopt(struct socket *sock,int level,int optname,    void *optval,int optlen){	struct atm_vcc *vcc;	vcc = ATM_SD(sock);	switch (optname) {		case SO_ATMQOS:			if (!test_bit(ATM_VF_HASQOS,&vcc->flags))				return -EINVAL;			return copy_to_user(optval,&vcc->qos,sizeof(vcc->qos)) ?			    -EFAULT : 0;		case SO_SETCLP:			return put_user(vcc->atm_options & ATM_ATMOPT_CLP ? 1 :			  0,(unsigned long *) optval) ? -EFAULT : 0;		case SO_ATMPVC:			{				struct sockaddr_atmpvc pvc;				if (!vcc->dev ||				    !test_bit(ATM_VF_ADDR,&vcc->flags))					return -ENOTCONN;				pvc.sap_family = AF_ATMPVC;				pvc.sap_addr.itf = vcc->dev->number;				pvc.sap_addr.vpi = vcc->vpi;				pvc.sap_addr.vci = vcc->vci;				return copy_to_user(optval,&pvc,sizeof(pvc)) ?				    -EFAULT : 0;			}		default:			if (level == SOL_SOCKET) return -EINVAL;			break;	}	if (!vcc->dev || !vcc->dev->ops->getsockopt) return -EINVAL;	return vcc->dev->ops->getsockopt(vcc,level,optname,optval,optlen);}int atm_setsockopt(struct socket *sock,int level,int optname,char *optval,    int optlen){	if (__SO_LEVEL_MATCH(optname, level) && optlen != __SO_SIZE(optname))		return -EINVAL;	return atm_do_setsockopt(sock,level,optname,optval,optlen);}int atm_getsockopt(struct socket *sock,int level,int optname,    char *optval,int *optlen){	int len;	if (get_user(len,optlen)) return -EFAULT;	if (__SO_LEVEL_MATCH(optname, level) && len != __SO_SIZE(optname))		return -EINVAL;	return atm_do_getsockopt(sock,level,optname,optval,len);}/* * lane_mpoa_init.c: A couple of helper functions * to make modular LANE and MPOA client easier to implement *//* * This is how it goes: * * if xxxx is not compiled as module, call atm_xxxx_init_ops() *    from here * else call atm_mpoa_init_ops() from init_module() within *    the kernel when xxxx module is loaded * * In either case function pointers in struct atm_xxxx_ops * are initialized to their correct values. Either they * point to functions in the module or in the kernel */ extern struct atm_mpoa_ops atm_mpoa_ops; /* in common.c */extern struct atm_lane_ops atm_lane_ops; /* in common.c */#if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)void atm_mpoa_init(void){#ifndef CONFIG_ATM_MPOA_MODULE /* not module */        atm_mpoa_init_ops(&atm_mpoa_ops);#else	request_module("mpoa");#endif        return;}#endif#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,						unsigned char *addr) = NULL;void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent) = NULL;#if defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE)EXPORT_SYMBOL(br_fdb_get_hook);EXPORT_SYMBOL(br_fdb_put_hook);#endif /* defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE) */#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */void atm_lane_init(void){#ifndef CONFIG_ATM_LANE_MODULE /* not module */        atm_lane_init_ops(&atm_lane_ops);#else	request_module("lec");#endif        return;}        #endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -