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

📄 af_ax25.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *	AX.25 release 038 * *	This code REQUIRES 2.1.15 or higher/ NET3.038 * *	This module: *		This module is free software; you can redistribute it and/or *		modify it under the terms of the GNU General Public License *		as published by the Free Software Foundation; either version *		2 of the License, or (at your option) any later version. * *	History *	AX.25 006	Alan(GW4PTS)		Nearly died of shock - it's working 8-) *	AX.25 007	Alan(GW4PTS)		Removed the silliest bugs *	AX.25 008	Alan(GW4PTS)		Cleaned up, fixed a few state machine problems, added callbacks *	AX.25 009	Alan(GW4PTS)		Emergency patch kit to fix memory corruption * 	AX.25 010	Alan(GW4PTS)		Added RAW sockets/Digipeat. *	AX.25 011	Alan(GW4PTS)		RAW socket and datagram fixes (thanks) - Raw sendto now gets PID right *						datagram sendto uses correct target address. *	AX.25 012	Alan(GW4PTS)		Correct incoming connection handling, send DM to failed connects. *						Use skb->data not skb+1. Support sk->priority correctly. *						Correct receive on SOCK_DGRAM. *	AX.25 013	Alan(GW4PTS)		Send DM to all unknown frames, missing initialiser fixed *						Leave spare SSID bits set (DAMA etc) - thanks for bug report, *						removed device registration (it's not used or needed). Clean up for *						gcc 2.5.8. PID to AX25_P_ *	AX.25 014	Alan(GW4PTS)		Cleanup and NET3 merge *	AX.25 015	Alan(GW4PTS)		Internal test version. *	AX.25 016	Alan(GW4PTS)		Semi Internal version for PI card *						work. *	AX.25 017	Alan(GW4PTS)		Fixed some small bugs reported by *						G4KLX *	AX.25 018	Alan(GW4PTS)		Fixed a small error in SOCK_DGRAM *	AX.25 019	Alan(GW4PTS)		Clean ups for the non INET kernel and device ioctls in AX.25 *	AX.25 020	Jonathan(G4KLX)		/proc support and other changes. *	AX.25 021	Alan(GW4PTS)		Added AX25_T1, AX25_N2, AX25_T3 as requested. *	AX.25 022	Jonathan(G4KLX)		More work on the ax25 auto router and /proc improved (again)! *			Alan(GW4PTS)		Added TIOCINQ/OUTQ *	AX.25 023	Alan(GW4PTS)		Fixed shutdown bug *	AX.25 023	Alan(GW4PTS)		Linus changed timers *	AX.25 024	Alan(GW4PTS)		Small bug fixes *	AX.25 025	Alan(GW4PTS)		More fixes, Linux 1.1.51 compatibility stuff, timers again! *	AX.25 026	Alan(GW4PTS)		Small state fix. *	AX.25 027	Alan(GW4PTS)		Socket close crash fixes. *	AX.25 028	Alan(GW4PTS)		Callsign control including settings per uid. *						Small bug fixes. *						Protocol set by sockets only. *						Small changes to allow for start of NET/ROM layer. *	AX.25 028a	Jonathan(G4KLX)		Changes to state machine. *	AX.25 028b	Jonathan(G4KLX)		Extracted ax25 control block *						from sock structure. *	AX.25 029	Alan(GW4PTS)		Combined 028b and some KA9Q code *			Jonathan(G4KLX)		and removed all the old Berkeley, added IP mode registration. *			Darryl(G7LED)		stuff. Cross-port digipeating. Minor fixes and enhancements. *			Alan(GW4PTS)		Missed suser() on axassociate checks *	AX.25 030	Alan(GW4PTS)		Added variable length headers. *			Jonathan(G4KLX)		Added BPQ Ethernet interface. *			Steven(GW7RRM)		Added digi-peating control ioctl. *						Added extended AX.25 support. *						Added AX.25 frame segmentation. *			Darryl(G7LED)		Changed connect(), recvfrom(), sendto() sockaddr/addrlen to *						fall inline with bind() and new policy. *						Moved digipeating ctl to new ax25_dev structs. *						Fixed ax25_release(), set TCP_CLOSE, wakeup app *						context, THEN make the sock dead. *			Alan(GW4PTS)		Cleaned up for single recvmsg methods. *			Alan(GW4PTS)		Fixed not clearing error on connect failure. *	AX.25 031	Jonathan(G4KLX)		Added binding to any device. *			Joerg(DL1BKE)		Added DAMA support, fixed (?) digipeating, fixed buffer locking *						for "virtual connect" mode... Result: Probably the *						"Most Buggiest Code You've Ever Seen" (TM) *			HaJo(DD8NE)		Implementation of a T5 (idle) timer *			Joerg(DL1BKE)		Renamed T5 to IDLE and changed behaviour: *						the timer gets reloaded on every received or transmitted *						I frame for IP or NETROM. The idle timer is not active *						on "vanilla AX.25" connections. Furthermore added PACLEN *						to provide AX.25-layer based fragmentation (like WAMPES) *      AX.25 032	Joerg(DL1BKE)		Fixed DAMA timeout error. *						ax25_send_frame() limits the number of enqueued *						datagrams per socket. *	AX.25 033	Jonathan(G4KLX)		Removed auto-router. *			Hans(PE1AYX)		Converted to Module. *			Joerg(DL1BKE)		Moved BPQ Ethernet to separate driver. *	AX.25 034	Jonathan(G4KLX)		2.1 changes *			Alan(GW4PTS)		Small POSIXisations *	AX.25 035	Alan(GW4PTS)		Started fixing to the new *						format. *			Hans(PE1AYX)		Fixed interface to IP layer. *			Alan(GW4PTS)		Added asynchronous support. *			Frederic(F1OAT)		Support for pseudo-digipeating. *			Jonathan(G4KLX)		Support for packet forwarding. *	AX.25 036	Jonathan(G4KLX)		Major restructuring. *			Joerg(DL1BKE)		Fixed DAMA Slave. *			Jonathan(G4KLX)		Fix wildcard listen parameter setting. *	AX.25 037	Jonathan(G4KLX)		New timer architecture. *      AX.25 038       Matthias(DG2FEF)        Small fixes to the syscall interface to make kernel *                                              independent of AX25_MAX_DIGIS used by applications. *                      Tomi(OH2BNS)            Fixed ax25_getname(). *			Joerg(DL1BKE)		Starting to phase out the support for full_sockaddr_ax25 *						with only 6 digipeaters and sockaddr_ax25 in ax25_bind(), *						ax25_connect() and ax25_sendmsg() *			Joerg(DL1BKE)		Added support for SO_BINDTODEVICE *			Arnaldo C. Melo		s/suser/capable(CAP_NET_ADMIN)/, some more cleanups *			Michal Ostrowski	Module initialization cleanup. *			Jeroen(PE1RXQ)		Use sock_orphan() on release. */#include <linux/config.h>#include <linux/module.h>#include <linux/errno.h>#include <linux/types.h>#include <linux/socket.h>#include <linux/in.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/timer.h>#include <linux/string.h>#include <linux/sockios.h>#include <linux/net.h>#include <net/ax25.h>#include <linux/inet.h>#include <linux/netdevice.h>#include <linux/if_arp.h>#include <linux/skbuff.h>#include <net/sock.h>#include <asm/uaccess.h>#include <asm/system.h>#include <linux/fcntl.h>#include <linux/termios.h>	/* For TIOCINQ/OUTQ */#include <linux/mm.h>#include <linux/interrupt.h>#include <linux/notifier.h>#include <linux/proc_fs.h>#include <linux/stat.h>#include <linux/netfilter.h>#include <linux/sysctl.h>#include <linux/init.h>#include <net/ip.h>#include <net/arp.h>ax25_cb *volatile ax25_list;static struct proto_ops ax25_proto_ops;/* *	Free an allocated ax25 control block. This is done to centralise *	the MOD count code. */void ax25_free_cb(ax25_cb *ax25){	if (ax25->digipeat != NULL) {		kfree(ax25->digipeat);		ax25->digipeat = NULL;	}	kfree(ax25);	MOD_DEC_USE_COUNT;}static void ax25_free_sock(struct sock *sk){	ax25_free_cb(sk->protinfo.ax25);}/* *	Socket removal during an interrupt is now safe. */static void ax25_remove_socket(ax25_cb *ax25){	ax25_cb *s;	unsigned long flags;	save_flags(flags); cli();	if ((s = ax25_list) == ax25) {		ax25_list = s->next;		restore_flags(flags);		return;	}	while (s != NULL && s->next != NULL) {		if (s->next == ax25) {			s->next = ax25->next;			restore_flags(flags);			return;		}		s = s->next;	}	restore_flags(flags);}/* *	Kill all bound sockets on a dropped device. */static void ax25_kill_by_device(struct net_device *dev){	ax25_dev *ax25_dev;	ax25_cb *s;	if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)		return;	for (s = ax25_list; s != NULL; s = s->next) {		if (s->ax25_dev == ax25_dev) {			s->ax25_dev = NULL;			ax25_disconnect(s, ENETUNREACH);		}	}}/* *	Handle device status changes. */static int ax25_device_event(struct notifier_block *this,unsigned long event, void *ptr){	struct net_device *dev = (struct net_device *)ptr;	/* Reject non AX.25 devices */	if (dev->type != ARPHRD_AX25)		return NOTIFY_DONE;	switch (event) {		case NETDEV_UP:			ax25_dev_device_up(dev);			break;		case NETDEV_DOWN:			ax25_kill_by_device(dev);			ax25_rt_device_down(dev);			ax25_dev_device_down(dev);			break;		default:			break;	}	return NOTIFY_DONE;}/* *	Add a socket to the bound sockets list. */void ax25_insert_socket(ax25_cb *ax25){	unsigned long flags;	save_flags(flags);	cli();	ax25->next = ax25_list;	ax25_list  = ax25;	restore_flags(flags);}/* *	Find a socket that wants to accept the SABM we have just *	received. */struct sock *ax25_find_listener(ax25_address *addr, int digi, struct net_device *dev, int type){	unsigned long flags;	ax25_cb *s;	save_flags(flags);	cli();	for (s = ax25_list; s != NULL; s = s->next) {		if ((s->iamdigi && !digi) || (!s->iamdigi && digi))			continue;		if (s->sk != NULL && ax25cmp(&s->source_addr, addr) == 0 && s->sk->type == type && s->sk->state == TCP_LISTEN) {			/* If device is null we match any device */			if (s->ax25_dev == NULL || s->ax25_dev->dev == dev) {				restore_flags(flags);				return s->sk;			}		}	}	restore_flags(flags);	return NULL;}/* *	Find an AX.25 socket given both ends. */struct sock *ax25_find_socket(ax25_address *my_addr, ax25_address *dest_addr, int type){	ax25_cb *s;	unsigned long flags;	save_flags(flags);	cli();	for (s = ax25_list; s != NULL; s = s->next) {		if (s->sk != NULL && ax25cmp(&s->source_addr, my_addr) == 0 && ax25cmp(&s->dest_addr, dest_addr) == 0 && s->sk->type == type) {			restore_flags(flags);			return s->sk;		}	}	restore_flags(flags);	return NULL;}/* *	Find an AX.25 control block given both ends. It will only pick up *	floating AX.25 control blocks or non Raw socket bound control blocks. */ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr, ax25_digi *digi, struct net_device *dev){	ax25_cb *s;	unsigned long flags;	save_flags(flags);	cli();	for (s = ax25_list; s != NULL; s = s->next) {		if (s->sk != NULL && s->sk->type != SOCK_SEQPACKET)			continue;		if (s->ax25_dev == NULL)			continue;		if (ax25cmp(&s->source_addr, src_addr) == 0 && ax25cmp(&s->dest_addr, dest_addr) == 0 && s->ax25_dev->dev == dev) {			if (digi != NULL && digi->ndigi != 0) {				if (s->digipeat == NULL)					continue;				if (ax25digicmp(s->digipeat, digi) != 0)					continue;			} else {				if (s->digipeat != NULL && s->digipeat->ndigi != 0)					continue;			}			restore_flags(flags);			return s;		}	}	restore_flags(flags);	return NULL;}/* *	Look for any matching address - RAW sockets can bind to arbitrary names */struct sock *ax25_addr_match(ax25_address *addr){	unsigned long flags;	ax25_cb *s;	save_flags(flags);	cli();	for (s = ax25_list; s != NULL; s = s->next) {		if (s->sk != NULL && ax25cmp(&s->source_addr, addr) == 0 && s->sk->type == SOCK_RAW) {			restore_flags(flags);			return s->sk;		}	}	restore_flags(flags);	return NULL;}void ax25_send_to_raw(struct sock *sk, struct sk_buff *skb, int proto){	struct sk_buff *copy;	while (sk != NULL) {		if (sk->type == SOCK_RAW &&		    sk->protocol == proto &&		    atomic_read(&sk->rmem_alloc) <= sk->rcvbuf) {			if ((copy = skb_clone(skb, GFP_ATOMIC)) == NULL)				return;			if (sock_queue_rcv_skb(sk, copy) != 0)				kfree_skb(copy);		}		sk = sk->next;	}}/* *	Deferred destroy. */void ax25_destroy_socket(ax25_cb *);/* *	Handler for deferred kills. */static void ax25_destroy_timer(unsigned long data){	ax25_destroy_socket((ax25_cb *)data);}/* *	This is called from user mode and the timers. Thus it protects itself against *	interrupt users but doesn't worry about being called during work. *	Once it is removed from the queue no interrupt or bottom half will *	touch it and we are (fairly 8-) ) safe. */void ax25_destroy_socket(ax25_cb *ax25)	/* Not static as it's used by the timer */{	struct sk_buff *skb;	unsigned long flags;	save_flags(flags); cli();	ax25_stop_heartbeat(ax25);	ax25_stop_t1timer(ax25);	ax25_stop_t2timer(ax25);	ax25_stop_t3timer(ax25);	ax25_stop_idletimer(ax25);	ax25_remove_socket(ax25);	ax25_clear_queues(ax25);	/* Flush the queues */	if (ax25->sk != NULL) {		while ((skb = skb_dequeue(&ax25->sk->receive_queue)) != NULL) {			if (skb->sk != ax25->sk) {			/* A pending connection */				skb->sk->dead = 1;	/* Queue the unaccepted socket for death */				ax25_start_heartbeat(skb->sk->protinfo.ax25);				skb->sk->protinfo.ax25->state = AX25_STATE_0;			}			kfree_skb(skb);		}	}	if (ax25->sk != NULL) {		if (atomic_read(&ax25->sk->wmem_alloc) != 0 ||		    atomic_read(&ax25->sk->rmem_alloc) != 0) {			/* Defer: outstanding buffers */			init_timer(&ax25->timer);			ax25->timer.expires  = jiffies + 10 * HZ;			ax25->timer.function = ax25_destroy_timer;			ax25->timer.data     = (unsigned long)ax25;			add_timer(&ax25->timer);		} else {			sk_free(ax25->sk);		}	} else {		ax25_free_cb(ax25);	}	restore_flags(flags);}/* * dl1bke 960311: set parameters for existing AX.25 connections, *		  includes a KILL command to abort any connection. *		  VERY useful for debugging ;-) */static int ax25_ctl_ioctl(const unsigned int cmd, void *arg){	struct ax25_ctl_struct ax25_ctl;	ax25_digi digi;	ax25_dev *ax25_dev;	ax25_cb *ax25;	unsigned int k;	if (copy_from_user(&ax25_ctl, arg, sizeof(ax25_ctl)))		return -EFAULT;	if ((ax25_dev = ax25_addr_ax25dev(&ax25_ctl.port_addr)) == NULL)

⌨️ 快捷键说明

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