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

📄 af_netrom.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
	nr_insert_socket(make);	skb_queue_head(&sk->sk_receive_queue, skb);	nr_start_heartbeat(make);	nr_start_idletimer(make);	if (!sock_flag(sk, SOCK_DEAD))		sk->sk_data_ready(sk, skb->len);	bh_unlock_sock(sk);	return 1;}static int nr_sendmsg(struct kiocb *iocb, struct socket *sock,		      struct msghdr *msg, size_t len){	struct sock *sk = sock->sk;	nr_cb *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 (sk->sk_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);	/*	 *	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->h.raw = skb_put(skb, len);	asmptr = skb->h.raw;	SOCK_DEBUG(sk, "NET/ROM: Appending user data\n");	/* User data follows immediately after the NET/ROM transport header */	if (memcpy_fromiovec(asmptr, 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->h.raw = skb->data;	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;		memcpy(sax->sax25_call.ax25_call, skb->data + 7, 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;	lock_sock(sk);	switch (cmd) {	case TIOCOUTQ: {		long amount;		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;		/* 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:		ret = -EINVAL;		if (sk != NULL)			ret = sock_get_timestamp(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:		release_sock(sk);		return -EINVAL;	case SIOCADDRT:	case SIOCDELRT:	case SIOCNRDECOBS:		release_sock(sk);		if (!capable(CAP_NET_ADMIN)) return -EPERM;		return nr_rt_ioctl(cmd, argp);	default:		release_sock(sk);		return dev_ioctl(cmd, argp);	}	release_sock(sk);	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;	nr_cb *nr;	const char *devname;	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(&nr->user_addr));		seq_printf(seq, "%-9s ", ax2asc(&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(&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 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 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 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 char banner[] __initdata = KERN_INFO "G4KLX NET/ROM for Linux. Version 0.7 for AX25.037 Linux 2.4\n";static int __init nr_proto_init(void){	int i;	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 = kmalloc(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;	}	memset(dev_nr, 0x00, nr_ndevs * sizeof(struct net_device *));	for (i = 0; i < nr_ndevs; i++) {		char name[IFNAMSIZ];		struct net_device *dev;		sprintf(name, "nr%d", i);		dev = alloc_netdev(sizeof(struct net_device_stats), 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;		}		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);	printk(banner);	ax25_protocol_register(AX25_P_NETROM, nr_route_frame);	ax25_linkfail_register(nr_link_failed);#ifdef CONFIG_SYSCTL	nr_register_sysctl();#endif	nr_loopback_init();	proc_net_fops_create("nr", S_IRUGO, &nr_info_fops);	proc_net_fops_create("nr_neigh", S_IRUGO, &nr_neigh_fops);	proc_net_fops_create("nr_nodes", S_IRUGO, &nr_nodes_fops);	return 0; fail:	while (--i >= 0) {		unregister_netdev(dev_nr[i]);		free_netdev(dev_nr[i]);	}	kfree(dev_nr);	return -1;}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("nr");	proc_net_remove("nr_neigh");	proc_net_remove("nr_nodes");	nr_loopback_clear();	nr_rt_free();#ifdef CONFIG_SYSCTL	nr_unregister_sysctl();#endif	ax25_linkfail_release(nr_link_failed);	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);}module_exit(nr_exit);

⌨️ 快捷键说明

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