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

📄 af_netrom.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	nr_start_idletimer(make);	return 1;}static int nr_sendmsg(struct kiocb *iocb, struct socket *sock,		      struct msghdr *msg, size_t len){	struct sock *sk = sock->sk;	struct nr_sock *nr = nr_sk(sk);	struct sockaddr_ax25 *usax = (struct sockaddr_ax25 *)msg->msg_name;	int err;	struct sockaddr_ax25 sax;	struct sk_buff *skb;	unsigned char *asmptr;	int size;	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_CMSG_COMPAT))		return -EINVAL;	lock_sock(sk);	if (sock_flag(sk, SOCK_ZAPPED)) {		err = -EADDRNOTAVAIL;		goto out;	}	if (sk->sk_shutdown & SEND_SHUTDOWN) {		send_sig(SIGPIPE, current, 0);		err = -EPIPE;		goto out;	}	if (nr->device == NULL) {		err = -ENETUNREACH;		goto out;	}	if (usax) {		if (msg->msg_namelen < sizeof(sax)) {			err = -EINVAL;			goto out;		}		sax = *usax;		if (ax25cmp(&nr->dest_addr, &sax.sax25_call) != 0) {			err = -EISCONN;			goto out;		}		if (sax.sax25_family != AF_NETROM) {			err = -EINVAL;			goto out;		}	} else {		if (sk->sk_state != TCP_ESTABLISHED) {			err = -ENOTCONN;			goto out;		}		sax.sax25_family = AF_NETROM;		sax.sax25_call   = nr->dest_addr;	}	SOCK_DEBUG(sk, "NET/ROM: sendto: Addresses built.\n");	/* Build a packet */	SOCK_DEBUG(sk, "NET/ROM: sendto: building packet.\n");	size = len + NR_NETWORK_LEN + NR_TRANSPORT_LEN;	if ((skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL)		goto out;	skb_reserve(skb, size - len);	skb_reset_transport_header(skb);	/*	 *	Push down the NET/ROM header	 */	asmptr = skb_push(skb, NR_TRANSPORT_LEN);	SOCK_DEBUG(sk, "Building NET/ROM Header.\n");	/* Build a NET/ROM Transport header */	*asmptr++ = nr->your_index;	*asmptr++ = nr->your_id;	*asmptr++ = 0;		/* To be filled in later */	*asmptr++ = 0;		/*      Ditto            */	*asmptr++ = NR_INFO;	SOCK_DEBUG(sk, "Built header.\n");	/*	 *	Put the data on the end	 */	skb_put(skb, len);	SOCK_DEBUG(sk, "NET/ROM: Appending user data\n");	/* User data follows immediately after the NET/ROM transport header */	if (memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len)) {		kfree_skb(skb);		err = -EFAULT;		goto out;	}	SOCK_DEBUG(sk, "NET/ROM: Transmitting buffer\n");	if (sk->sk_state != TCP_ESTABLISHED) {		kfree_skb(skb);		err = -ENOTCONN;		goto out;	}	nr_output(sk, skb);	/* Shove it onto the queue */	err = len;out:	release_sock(sk);	return err;}static int nr_recvmsg(struct kiocb *iocb, struct socket *sock,		      struct msghdr *msg, size_t size, int flags){	struct sock *sk = sock->sk;	struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name;	size_t copied;	struct sk_buff *skb;	int er;	/*	 * This works for seqpacket too. The receiver has ordered the queue for	 * us! We do one quick check first though	 */	lock_sock(sk);	if (sk->sk_state != TCP_ESTABLISHED) {		release_sock(sk);		return -ENOTCONN;	}	/* Now we can treat all alike */	if ((skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &er)) == NULL) {		release_sock(sk);		return er;	}	skb_reset_transport_header(skb);	copied     = skb->len;	if (copied > size) {		copied = size;		msg->msg_flags |= MSG_TRUNC;	}	skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);	if (sax != NULL) {		sax->sax25_family = AF_NETROM;		skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call,			      AX25_ADDR_LEN);	}	msg->msg_namelen = sizeof(*sax);	skb_free_datagram(sk, skb);	release_sock(sk);	return copied;}static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg){	struct sock *sk = sock->sk;	void __user *argp = (void __user *)arg;	int ret;	switch (cmd) {	case TIOCOUTQ: {		long amount;		lock_sock(sk);		amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);		if (amount < 0)			amount = 0;		release_sock(sk);		return put_user(amount, (int __user *)argp);	}	case TIOCINQ: {		struct sk_buff *skb;		long amount = 0L;		lock_sock(sk);		/* These two are safe on a single CPU system as only user tasks fiddle here */		if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)			amount = skb->len;		release_sock(sk);		return put_user(amount, (int __user *)argp);	}	case SIOCGSTAMP:		lock_sock(sk);		ret = sock_get_timestamp(sk, argp);		release_sock(sk);		return ret;	case SIOCGSTAMPNS:		lock_sock(sk);		ret = sock_get_timestampns(sk, argp);		release_sock(sk);		return ret;	case SIOCGIFADDR:	case SIOCSIFADDR:	case SIOCGIFDSTADDR:	case SIOCSIFDSTADDR:	case SIOCGIFBRDADDR:	case SIOCSIFBRDADDR:	case SIOCGIFNETMASK:	case SIOCSIFNETMASK:	case SIOCGIFMETRIC:	case SIOCSIFMETRIC:		return -EINVAL;	case SIOCADDRT:	case SIOCDELRT:	case SIOCNRDECOBS:		if (!capable(CAP_NET_ADMIN)) return -EPERM;		return nr_rt_ioctl(cmd, argp);	default:		return -ENOIOCTLCMD;	}	return 0;}#ifdef CONFIG_PROC_FSstatic void *nr_info_start(struct seq_file *seq, loff_t *pos){	struct sock *s;	struct hlist_node *node;	int i = 1;	spin_lock_bh(&nr_list_lock);	if (*pos == 0)		return SEQ_START_TOKEN;	sk_for_each(s, node, &nr_list) {		if (i == *pos)			return s;		++i;	}	return NULL;}static void *nr_info_next(struct seq_file *seq, void *v, loff_t *pos){	++*pos;	return (v == SEQ_START_TOKEN) ? sk_head(&nr_list)		: sk_next((struct sock *)v);}static void nr_info_stop(struct seq_file *seq, void *v){	spin_unlock_bh(&nr_list_lock);}static int nr_info_show(struct seq_file *seq, void *v){	struct sock *s = v;	struct net_device *dev;	struct nr_sock *nr;	const char *devname;	char buf[11];	if (v == SEQ_START_TOKEN)		seq_puts(seq,"user_addr dest_node src_node  dev    my  your  st  vs  vr  va    t1     t2     t4      idle   n2  wnd Snd-Q Rcv-Q inode\n");	else {		bh_lock_sock(s);		nr = nr_sk(s);		if ((dev = nr->device) == NULL)			devname = "???";		else			devname = dev->name;		seq_printf(seq, "%-9s ", ax2asc(buf, &nr->user_addr));		seq_printf(seq, "%-9s ", ax2asc(buf, &nr->dest_addr));		seq_printf(seq,"%-9s %-3s  %02X/%02X %02X/%02X %2d %3d %3d %3d %3lu/%03lu %2lu/%02lu %3lu/%03lu %3lu/%03lu %2d/%02d %3d %5d %5d %ld\n",			ax2asc(buf, &nr->source_addr),			devname,			nr->my_index,			nr->my_id,			nr->your_index,			nr->your_id,			nr->state,			nr->vs,			nr->vr,			nr->va,			ax25_display_timer(&nr->t1timer) / HZ,			nr->t1 / HZ,			ax25_display_timer(&nr->t2timer) / HZ,			nr->t2 / HZ,			ax25_display_timer(&nr->t4timer) / HZ,			nr->t4 / HZ,			ax25_display_timer(&nr->idletimer) / (60 * HZ),			nr->idle / (60 * HZ),			nr->n2count,			nr->n2,			nr->window,			atomic_read(&s->sk_wmem_alloc),			atomic_read(&s->sk_rmem_alloc),			s->sk_socket ? SOCK_INODE(s->sk_socket)->i_ino : 0L);		bh_unlock_sock(s);	}	return 0;}static const struct seq_operations nr_info_seqops = {	.start = nr_info_start,	.next = nr_info_next,	.stop = nr_info_stop,	.show = nr_info_show,};static int nr_info_open(struct inode *inode, struct file *file){	return seq_open(file, &nr_info_seqops);}static const struct file_operations nr_info_fops = {	.owner = THIS_MODULE,	.open = nr_info_open,	.read = seq_read,	.llseek = seq_lseek,	.release = seq_release,};#endif	/* CONFIG_PROC_FS */static struct net_proto_family nr_family_ops = {	.family		=	PF_NETROM,	.create		=	nr_create,	.owner		=	THIS_MODULE,};static const struct proto_ops nr_proto_ops = {	.family		=	PF_NETROM,	.owner		=	THIS_MODULE,	.release	=	nr_release,	.bind		=	nr_bind,	.connect	=	nr_connect,	.socketpair	=	sock_no_socketpair,	.accept		=	nr_accept,	.getname	=	nr_getname,	.poll		=	datagram_poll,	.ioctl		=	nr_ioctl,	.listen		=	nr_listen,	.shutdown	=	sock_no_shutdown,	.setsockopt	=	nr_setsockopt,	.getsockopt	=	nr_getsockopt,	.sendmsg	=	nr_sendmsg,	.recvmsg	=	nr_recvmsg,	.mmap		=	sock_no_mmap,	.sendpage	=	sock_no_sendpage,};static struct notifier_block nr_dev_notifier = {	.notifier_call	=	nr_device_event,};static struct net_device **dev_nr;static struct ax25_protocol nr_pid = {	.pid	= AX25_P_NETROM,	.func	= nr_route_frame};static struct ax25_linkfail nr_linkfail_notifier = {	.func	= nr_link_failed,};static int __init nr_proto_init(void){	int i;	int rc = proto_register(&nr_proto, 0);	if (rc != 0)		goto out;	if (nr_ndevs > 0x7fffffff/sizeof(struct net_device *)) {		printk(KERN_ERR "NET/ROM: nr_proto_init - nr_ndevs parameter to large\n");		return -1;	}	dev_nr = kzalloc(nr_ndevs * sizeof(struct net_device *), GFP_KERNEL);	if (dev_nr == NULL) {		printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device array\n");		return -1;	}	for (i = 0; i < nr_ndevs; i++) {		char name[IFNAMSIZ];		struct net_device *dev;		sprintf(name, "nr%d", i);		dev = alloc_netdev(sizeof(struct nr_private), name, nr_setup);		if (!dev) {			printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device structure\n");			goto fail;		}		dev->base_addr = i;		if (register_netdev(dev)) {			printk(KERN_ERR "NET/ROM: nr_proto_init - unable to register network device\n");			free_netdev(dev);			goto fail;		}		lockdep_set_class(&dev->_xmit_lock, &nr_netdev_xmit_lock_key);		dev_nr[i] = dev;	}	if (sock_register(&nr_family_ops)) {		printk(KERN_ERR "NET/ROM: nr_proto_init - unable to register socket family\n");		goto fail;	}	register_netdevice_notifier(&nr_dev_notifier);	ax25_register_pid(&nr_pid);	ax25_linkfail_register(&nr_linkfail_notifier);#ifdef CONFIG_SYSCTL	nr_register_sysctl();#endif	nr_loopback_init();	proc_net_fops_create(&init_net, "nr", S_IRUGO, &nr_info_fops);	proc_net_fops_create(&init_net, "nr_neigh", S_IRUGO, &nr_neigh_fops);	proc_net_fops_create(&init_net, "nr_nodes", S_IRUGO, &nr_nodes_fops);out:	return rc;fail:	while (--i >= 0) {		unregister_netdev(dev_nr[i]);		free_netdev(dev_nr[i]);	}	kfree(dev_nr);	proto_unregister(&nr_proto);	rc = -1;	goto out;}module_init(nr_proto_init);module_param(nr_ndevs, int, 0);MODULE_PARM_DESC(nr_ndevs, "number of NET/ROM devices");MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>");MODULE_DESCRIPTION("The amateur radio NET/ROM network and transport layer protocol");MODULE_LICENSE("GPL");MODULE_ALIAS_NETPROTO(PF_NETROM);static void __exit nr_exit(void){	int i;	proc_net_remove(&init_net, "nr");	proc_net_remove(&init_net, "nr_neigh");	proc_net_remove(&init_net, "nr_nodes");	nr_loopback_clear();	nr_rt_free();#ifdef CONFIG_SYSCTL	nr_unregister_sysctl();#endif	ax25_linkfail_release(&nr_linkfail_notifier);	ax25_protocol_release(AX25_P_NETROM);	unregister_netdevice_notifier(&nr_dev_notifier);	sock_unregister(PF_NETROM);	for (i = 0; i < nr_ndevs; i++) {		struct net_device *dev = dev_nr[i];		if (dev) {			unregister_netdev(dev);			free_netdev(dev);		}	}	kfree(dev_nr);	proto_unregister(&nr_proto);}module_exit(nr_exit);

⌨️ 快捷键说明

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