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

📄 sdla_chdlc.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			printk(KERN_WARNING "  format A.B.C.1 or A.B.C.2.\n");		}		*/			}		return chdlc_configure(card, &cfg);}/*============================================================================ * Process global exception condition */static int process_global_exception(sdla_t *card){	CHDLC_MAILBOX_STRUCT* mbox = card->mbox;	int err;	mbox->buffer_length = 0;	mbox->command = READ_GLOBAL_EXCEPTION_CONDITION;	err = sdla_exec(mbox) ? mbox->return_code : CMD_TIMEOUT;	if(err != CMD_TIMEOUT ){			switch(mbox->return_code) {         	      	case EXCEP_MODEM_STATUS_CHANGE:			printk(KERN_INFO "%s: Modem status change\n",				card->devname);			switch(mbox->data[0] & (DCD_HIGH | CTS_HIGH)) {				case (DCD_HIGH):					printk(KERN_INFO "%s: DCD high, CTS low\n",card->devname);					break;				case (CTS_HIGH):                                        printk(KERN_INFO "%s: DCD low, CTS high\n",card->devname);                                        break;                                case ((DCD_HIGH | CTS_HIGH)):                                        printk(KERN_INFO "%s: DCD high, CTS high\n",card->devname);                                        break;				default:                                        printk(KERN_INFO "%s: DCD low, CTS low\n",card->devname);                                        break;			}			break;                case EXCEP_TRC_DISABLED:                        printk(KERN_INFO "%s: Line trace disabled\n",				card->devname);                        break;		case EXCEP_IRQ_TIMEOUT:			printk(KERN_INFO "%s: IRQ timeout occurred\n",				card->devname); 			break;                default:                        printk(KERN_INFO "%s: Global exception %x\n",				card->devname, mbox->return_code);                        break;                }	}	return 0;}/*============================================================================ * Process chdlc exception condition */static int process_chdlc_exception(sdla_t *card){	CHDLC_MAILBOX_STRUCT* mb = card->mbox;	int err;	mb->buffer_length = 0;	mb->command = READ_CHDLC_EXCEPTION_CONDITION;	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;	if(err != CMD_TIMEOUT) {			switch (err) {		case EXCEP_LINK_ACTIVE:			port_set_state(card, WAN_CONNECTED);			break;		case EXCEP_LINK_INACTIVE_MODEM:			port_set_state(card, WAN_DISCONNECTED);			unconfigure_ip(card);			break;		case EXCEP_LINK_INACTIVE_KPALV:			port_set_state(card, WAN_DISCONNECTED);			printk(KERN_INFO "%s: Keepalive timer expired.\n",				 		card->devname);			unconfigure_ip(card);			break;		case EXCEP_IP_ADDRESS_DISCOVERED:			if (configure_ip(card)) 				return -1;			break;		case EXCEP_LOOPBACK_CONDITION:			printk(KERN_INFO "%s: Loopback Condition Detected.\n",						card->devname);			break;		case NO_CHDLC_EXCEP_COND_TO_REPORT:			printk(KERN_INFO "%s: No exceptions reported.\n",						card->devname);			break;		}	}	return 0;}/*============================================================================ * Configure IP from SLARP negotiation * This adds dynamic routes when SLARP has provided valid addresses */static int configure_ip (sdla_t* card){	struct net_device *dev = card->wandev.dev;        chdlc_private_area_t *chdlc_priv_area = dev->priv;        char err;        /* set to discover */        if(card->u.c.slarp_timer != 0x00) {		CHDLC_MAILBOX_STRUCT* mb = card->mbox;		CHDLC_CONFIGURATION_STRUCT *cfg;     		mb->buffer_length = 0;		mb->command = READ_CHDLC_CONFIGURATION;		err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;			if(err != COMMAND_OK) {			chdlc_error(card,err,mb);			return -1;		}		cfg = (CHDLC_CONFIGURATION_STRUCT *)mb->data;                chdlc_priv_area->IP_address = cfg->IP_address;                chdlc_priv_area->IP_netmask = cfg->IP_netmask;        }	/* Set flag to add route */	chdlc_priv_area->route_status = ADD_ROUTE;	/* The idea here is to add the route in the poll routine.	   This way, we aren't in interrupt context when adding routes */	card->poll = process_route;	return 0;}/*============================================================================ * Un-Configure IP negotiated by SLARP * This removes dynamic routes when the link becomes inactive. */static int unconfigure_ip (sdla_t* card){	struct net_device *dev = card->wandev.dev;	chdlc_private_area_t *chdlc_priv_area= dev->priv;	if (chdlc_priv_area->route_status == ROUTE_ADDED) {	      	chdlc_priv_area->route_status = REMOVE_ROUTE;		/* The idea here is to delete the route in 		 * the poll routine.	   	 * This way, we aren't in interrupt context 		 * when adding routes 		 */                card->poll = process_route;	}	return 0;}/*============================================================================ * Routine to add/remove routes  * Called like a polling routine when Routes are flagged to be added/removed. */static void process_route (sdla_t *card){        struct net_device *dev = card->wandev.dev;        unsigned char port_num;        chdlc_private_area_t *chdlc_priv_area = NULL;	u32 local_IP_addr = 0;	u32 remote_IP_addr = 0;	u32 IP_netmask, IP_addr;        int err = 0;#ifdef LINUX_2_1	struct in_device *in_dev;	mm_segment_t fs;	struct ifreq if_info;        struct sockaddr_in *if_data1, *if_data2;#else	unsigned long fs = 0;        struct rtentry route;#endif	        chdlc_priv_area = dev->priv;        port_num = card->u.c.comm_port;	if((chdlc_priv_area->route_status == ADD_ROUTE) &&		((chdlc_priv_area->IP_address & 0x000000FF) > 2)) {		printk(KERN_INFO "%s: Dynamic route failure.\n",card->devname);                if(card->u.c.slarp_timer) {			printk(KERN_INFO "%s: Bad IP address %s received\n",				card->devname,				in_ntoa(ntohl(chdlc_priv_area->IP_address)));                        printk(KERN_INFO "%s: from remote station.\n",				card->devname);                }else{                         printk(KERN_INFO "%s: Bad IP address %s issued\n",				card->devname,				in_ntoa(ntohl(chdlc_priv_area->IP_address)));                        printk(KERN_INFO "%s: to remote station. Local\n",				card->devname);			printk(KERN_INFO "%s: IP address must be A.B.C.1\n",				card->devname);			printk(KERN_INFO "%s: or A.B.C.2.\n",card->devname);		}		/* remove the route due to the IP address error condition */		chdlc_priv_area->route_status = REMOVE_ROUTE;		err = 1;   	}	/* If we are removing a route with bad IP addressing, then use the */	/* locally configured IP addresses */        if((chdlc_priv_area->route_status == REMOVE_ROUTE) && err) { 	        /* do not remove a bad route that has already been removed */        	if(chdlc_priv_area->route_removed) {                	card->poll = NULL;	                return;        	}#ifdef LINUX_2_1                in_dev = dev->ip_ptr;                if(in_dev != NULL) {                        struct in_ifaddr *ifa = in_dev->ifa_list;                        if (ifa != NULL ) {                                local_IP_addr = ifa->ifa_local;                                IP_netmask  = ifa->ifa_mask;                        }                }#else                local_IP_addr = dev->pa_addr;                remote_IP_addr = dev->pa_dstaddr;                IP_netmask = dev->pa_mask;#endif	}else{        		/* According to Cisco HDLC, if the point-to-point address is		   A.B.C.1, then we are the opposite (A.B.C.2), and vice-versa.		*/		IP_netmask = ntohl(chdlc_priv_area->IP_netmask);	        remote_IP_addr = ntohl(chdlc_priv_area->IP_address);        	local_IP_addr = (remote_IP_addr & ntohl(0xFFFFFF00)) +                	(~remote_IP_addr & ntohl(0x0003));	        if(!card->u.c.slarp_timer) {			IP_addr = local_IP_addr;			local_IP_addr = remote_IP_addr;			remote_IP_addr = IP_addr;       		}	}        fs = get_fs();                  /* Save file system  */        set_fs(get_ds());               /* Get user space block */#ifdef LINUX_2_1        /* Setup a structure for adding/removing routes */        memset(&if_info, 0, sizeof(if_info));        strcpy(if_info.ifr_name, dev->name);#else	/* Setup a structure for adding/removing routes */	dev->pa_mask = IP_netmask;	dev->pa_dstaddr = remote_IP_addr;	dev->pa_addr = local_IP_addr;	memset(&route, 0, sizeof(route));	route.rt_dev = dev->name;	route.rt_flags = 0;	((struct sockaddr_in *)&(route.rt_dst))->sin_addr.s_addr =			dev->pa_dstaddr;	((struct sockaddr_in *)&(route.rt_dst))->sin_family = AF_INET;	((struct sockaddr_in *)&(route.rt_genmask))->sin_addr.s_addr =			0xFFFFFFFF;        ((struct sockaddr_in *)&(route.rt_genmask))->sin_family =			AF_INET;#endif	switch (chdlc_priv_area->route_status) {	case ADD_ROUTE:		if(!card->u.c.slarp_timer) {#ifdef LINUX_2_1			if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;			if_data2->sin_addr.s_addr = remote_IP_addr;			if_data2->sin_family = AF_INET;			err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);#else                        err = ip_rt_new(&route);#endif		} else { #ifdef LINUX_2_1			if_data1 = (struct sockaddr_in *)&if_info.ifr_addr;			if_data1->sin_addr.s_addr = local_IP_addr;			if_data1->sin_family = AF_INET;			if(!(err = devinet_ioctl(SIOCSIFADDR, &if_info))){				if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;				if_data2->sin_addr.s_addr = remote_IP_addr;				if_data2->sin_family = AF_INET;				err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);			}#else               		err = ip_rt_new(&route);#endif		}               if(err) {			printk(KERN_INFO "%s: Add route %s failed (%d)\n", 				card->devname, in_ntoa(remote_IP_addr), err);		} else {			((chdlc_private_area_t *)dev->priv)->route_status = ROUTE_ADDED;			printk(KERN_INFO "%s: Dynamic route added.\n",				card->devname);			printk(KERN_INFO "%s:    Local IP addr : %s\n",				card->devname, in_ntoa(local_IP_addr));			printk(KERN_INFO "%s:    Remote IP addr: %s\n",				card->devname, in_ntoa(remote_IP_addr));			chdlc_priv_area->route_removed = 0;		}		break;	case REMOVE_ROUTE:	#ifdef LINUX_2_1		/* Change the local ip address of the interface to 0.		 * This will also delete the destination route.		 */		if(!card->u.c.slarp_timer) {			if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;			if_data2->sin_addr.s_addr = 0;			if_data2->sin_family = AF_INET;			err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);		} else {			if_data1 = (struct sockaddr_in *)&if_info.ifr_addr;			if_data1->sin_addr.s_addr = 0;			if_data1->sin_family = AF_INET;			err = devinet_ioctl(SIOCSIFADDR,&if_info);				}#else		/* set the point-to-point IP address to 0.0.0.0 */		dev->pa_dstaddr = 0; 		err = ip_rt_kill(&route);#endif		if(err) {			printk(KERN_INFO				"%s: Remove route %s failed, (err %d)\n",					card->devname, in_ntoa(remote_IP_addr),					err);		} else {			((chdlc_private_area_t *)dev->priv)->route_status =				NO_ROUTE;                        printk(KERN_INFO "%s: Dynamic route removed: %s\n",                                        card->devname, in_ntoa(local_IP_addr)); 			chdlc_priv_area->route_removed = 1;		}		break;	}        set_fs(fs);                     /* Restore file system */        /* Once we've processed the route, stop polling */        card->poll = NULL;}/*============================================================================= * Store a UDP management packet for later processing. */static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,                                struct sk_buff *skb, struct net_device* dev,                                chdlc_private_area_t* chdlc_priv_area ){	int udp_pkt_stored = 0;	if(!chdlc_priv_area->udp_pkt_lgth &&	  (skb->len <= MAX_LGTH_UDP_MGNT_PKT)) {        	chdlc_priv_area->udp_pkt_lgth = skb->len;		chdlc_priv_area->udp_pkt_src = udp_pkt_src;       		memcpy(chdlc_priv_area->udp_pkt_data, skb->data, skb->len);		chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UDP;		udp_pkt_stored = 1;	}#ifdef LINUX_2_1	dev_kfree_skb(skb);#else	if(udp_pkt_src == UDP_PKT_FRM_STACK)		dev_kfree_skb(skb, FREE_WRITE);	else                dev_kfree_skb(skb, FREE_READ);#endif		return(udp_pkt_stored);}/*============================================================================= * Process UDP management packet. */static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev,				chdlc_private_area_t* chdlc_priv_area ) {	unsigned char *buf;	unsigned int frames, len;	struct sk_buff *new_skb;	unsigned short buffer_length, real_len;	unsigned long data_ptr;	unsigned data_length;	int udp_mgmt_req_valid = 1;	CHDLC_MAILBOX_STRUCT *mb = card->mbox;	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;	chdlc_udp_pkt_t *chdlc_udp_pkt;	struct timeval tv;	int err;	char ut_char;	chdlc_udp_pkt = (chdlc_udp_pkt_t *) chdlc_priv_area->udp_pkt_data;	switch(chdlc_udp_pkt->cblock.command

⌨️ 快捷键说明

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