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

📄 hdlc.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	else if (mode_is(hdlc, MODE_X25)) {		struct lapb_register_struct cb;		cb.connect_confirmation = x25_connected;		cb.connect_indication = x25_connected;		cb.disconnect_confirmation = x25_disconnected;		cb.disconnect_indication = x25_disconnected;		cb.data_indication = x25_data_indication;		cb.data_transmit = x25_data_transmit;		result = lapb_register(hdlc, &cb);		if (result != LAPB_OK)			return result;	}#endif	result = hdlc->open(hdlc);	if (result) {		if (mode_is(hdlc, MODE_FR | MODE_SOFT) ||		    mode_is(hdlc, MODE_CISCO | MODE_SOFT))			fr_cisco_close(hdlc);#ifdef CONFIG_HDLC_PPP		else if (mode_is(hdlc, MODE_PPP | MODE_SOFT)) {			sppp_close(dev);			sppp_detach(dev);			dev->rebuild_header = NULL;			dev->change_mtu = hdlc_change_mtu;			dev->mtu = HDLC_MAX_MTU;			dev->hard_header_len = 16;		}#endif#ifdef CONFIG_HDLC_X25		else if (mode_is(hdlc, MODE_X25))			lapb_unregister(hdlc);#endif	}	return result;}static int hdlc_close(struct net_device *dev){	hdlc_device *hdlc = dev_to_hdlc(dev);	hdlc->close(hdlc);	if (mode_is(hdlc, MODE_FR | MODE_SOFT) ||	    mode_is(hdlc, MODE_CISCO | MODE_SOFT))		fr_cisco_close(hdlc);#ifdef CONFIG_HDLC_PPP	else if (mode_is(hdlc, MODE_PPP | MODE_SOFT)) {		sppp_close(dev);		sppp_detach(dev);		dev->rebuild_header = NULL;		dev->change_mtu = hdlc_change_mtu;		dev->mtu = HDLC_MAX_MTU;		dev->hard_header_len = 16;	}#endif#ifdef CONFIG_HDLC_X25	else if (mode_is(hdlc, MODE_X25))		lapb_unregister(hdlc);#endif	return 0;}static int hdlc_xmit(struct sk_buff *skb, struct net_device *dev){	hdlc_device *hdlc = dev_to_hdlc(dev);#ifdef CONFIG_HDLC_X25	if (mode_is(hdlc, MODE_X25 | MODE_SOFT)) {		int result;		/* X.25 to LAPB */		switch (skb->data[0]) {		case 0:		/* Data to be transmitted */			skb_pull(skb, 1);			if ((result = lapb_data_request(hdlc, skb)) != LAPB_OK)				dev_kfree_skb(skb);			return 0;		case 1:			if ((result = lapb_connect_request(hdlc))!= LAPB_OK) {				if (result == LAPB_CONNECTED) {				/* Send connect confirm. msg to level 3 */					x25_connected(hdlc, 0);				} else {					printk(KERN_ERR "%s: LAPB connect "					       "request failed, error code = "					       "%i\n", hdlc_to_name(hdlc),					       result);				}			}			break;		case 2:			if ((result=lapb_disconnect_request(hdlc))!=LAPB_OK) {				if (result == LAPB_NOTCONNECTED) {				/* Send disconnect confirm. msg to level 3 */					x25_disconnected(hdlc, 0);				} else {					printk(KERN_ERR "%s: LAPB disconnect "					       "request failed, error code = "					       "%i\n", hdlc_to_name(hdlc),					       result);				}			}			break;		default:			/* to be defined */			break;		}		dev_kfree_skb(skb);		return 0;	} /* MODE_X25 */#endif /* CONFIG_HDLC_X25 */	return hdlc->xmit(hdlc, skb);}void hdlc_netif_rx(hdlc_device *hdlc, struct sk_buff *skb){/* skb contains raw HDLC frame, in both hard- and software modes */	skb->mac.raw = skb->data;	switch(hdlc->mode & MODE_MASK) {	case MODE_HDLC:		skb->protocol = htons(ETH_P_IP);		skb->dev = hdlc_to_dev(hdlc);		netif_rx(skb);		return;	case MODE_FR:		fr_netif(hdlc, skb);		return;	case MODE_CISCO:		cisco_netif(hdlc, skb);		return;#ifdef CONFIG_HDLC_PPP	case MODE_PPP:#if 0		sppp_input(hdlc_to_dev(hdlc), skb);#else		skb->protocol = htons(ETH_P_WAN_PPP);		skb->dev = hdlc_to_dev(hdlc);		netif_rx(skb);#endif		return;#endif#ifdef CONFIG_HDLC_X25	case MODE_X25:		skb->dev = hdlc_to_dev(hdlc);		if (lapb_data_received(hdlc, skb) == LAPB_OK)			return;		break;#endif	}	hdlc->stats.rx_errors++;	dev_kfree_skb_any(skb);}static struct net_device_stats *hdlc_get_stats(struct net_device *dev){	return &dev_to_hdlc(dev)->stats;}static int hdlc_set_mode(hdlc_device *hdlc, int mode){	int result = -1;	/* Default to soft modes */	struct net_device *dev = hdlc_to_dev(hdlc);	if(!capable(CAP_NET_ADMIN))		return -EPERM;	if(dev->flags & IFF_UP)		return -EBUSY;	dev->addr_len = 0;	dev->hard_header = NULL;	hdlc->mode = MODE_NONE;	if (!(mode & MODE_SOFT))		switch(mode & MODE_MASK) {		case MODE_HDLC:			result = hdlc->set_mode ?				hdlc->set_mode(hdlc, MODE_HDLC) : 0;			break;		case MODE_CISCO: /* By card */#ifdef CONFIG_HDLC_PPP		case MODE_PPP:#endif#ifdef CONFIG_HDLC_X25		case MODE_X25:#endif		case MODE_FR:			result = hdlc->set_mode ?				hdlc->set_mode(hdlc, mode) : -ENOSYS;			break;		default:			return -EINVAL;		}	if (result) {		mode |= MODE_SOFT; /* Try "host software" protocol */		switch(mode & MODE_MASK) {		case MODE_CISCO:			dev->hard_header = cisco_hard_header;			break;#ifdef CONFIG_HDLC_PPP		case MODE_PPP:			break;#endif#ifdef CONFIG_HDLC_X25		case MODE_X25:			break;#endif		case MODE_FR:			dev->hard_header = fr_hard_header;			dev->addr_len = 2;			*(u16*)dev->dev_addr = htons(LMI_DLCI);			dlci_to_q922(dev->broadcast, LMI_DLCI);			break;		default:			return -EINVAL;		}		result = hdlc->set_mode ?			hdlc->set_mode(hdlc, MODE_HDLC) : 0;	}	if (result)		return result;	hdlc->mode = mode;	switch(mode & MODE_MASK) {#ifdef CONFIG_HDLC_PPP	case MODE_PPP:   dev->type = ARPHRD_PPP;   break;#endif#ifdef CONFIG_HDLC_X25	case MODE_X25:   dev->type = ARPHRD_X25;   break;#endif	case MODE_FR:    dev->type = ARPHRD_FRAD;  break;	case MODE_CISCO: dev->type = ARPHRD_CISCO; break;	default:         dev->type = ARPHRD_RAWHDLC;	}	memset(&(hdlc->stats), 0, sizeof(struct net_device_stats));	destroy_pvc_list(hdlc);	return 0;}static int hdlc_fr_pvc(hdlc_device *hdlc, int dlci){	pvc_device **pvc_p = &hdlc->first_pvc;	pvc_device *pvc;	int result, create = 1;	/* Create or delete PVC */	if(!capable(CAP_NET_ADMIN))		return -EPERM;	if(dlci<0) {		dlci = -dlci;		create = 0;	}	if(dlci <= 0 || dlci >= 1024)		return -EINVAL;	/* Only 10 bits for DLCI, DLCI=0 is reserved */	if(!mode_is(hdlc, MODE_FR))		return -EINVAL;	/* Only meaningfull on FR */	while(*pvc_p) {		if (netdev_dlci(&(*pvc_p)->netdev) == dlci)			break;		pvc_p = &(*pvc_p)->next;	}	if (create) {		/* Create PVC */		if (*pvc_p != NULL)			return -EEXIST;		pvc = *pvc_p = kmalloc(sizeof(pvc_device), GFP_KERNEL);		if (!pvc) {			printk(KERN_WARNING "%s: Memory squeeze on "			       "hdlc_fr_pvc()\n", hdlc_to_name(hdlc));			return -ENOBUFS;		}		memset(pvc, 0, sizeof(pvc_device));		pvc->netdev.hard_start_xmit = pvc_xmit;		pvc->netdev.get_stats = pvc_get_stats;		pvc->netdev.open = pvc_open;		pvc->netdev.stop = pvc_close;		pvc->netdev.change_mtu = pvc_change_mtu;		pvc->netdev.mtu = HDLC_MAX_MTU;		pvc->netdev.type = ARPHRD_DLCI;		pvc->netdev.hard_header_len = 16;		pvc->netdev.hard_header = fr_hard_header;		pvc->netdev.tx_queue_len = 0;		pvc->netdev.flags = IFF_POINTOPOINT;		pvc->master = hdlc;		*(u16*)pvc->netdev.dev_addr = htons(dlci);		dlci_to_q922(pvc->netdev.broadcast, dlci);		pvc->netdev.addr_len = 2;		pvc->netdev.irq = hdlc_to_dev(hdlc)->irq;		result = dev_alloc_name(&pvc->netdev, "pvc%d");		if (result < 0) {			kfree(pvc);			*pvc_p = NULL;			return result;		}		if (register_netdevice(&pvc->netdev) != 0) {			kfree(pvc);			*pvc_p = NULL;			return -EIO;		}		if (!mode_is(hdlc, MODE_SOFT) && hdlc->create_pvc) {			result = hdlc->create_pvc(pvc);			if (result) {				unregister_netdevice(&pvc->netdev);				kfree(pvc);				*pvc_p = NULL;				return result;			}		}		hdlc->lmi.state |= LINK_STATE_CHANGED;		hdlc->pvc_count++;		return 0;	}	if (*pvc_p == NULL)		/* Delete PVC */		return -ENOENT;	pvc = *pvc_p;	if (pvc->netdev.flags & IFF_UP)		return -EBUSY;		/* PVC in use */	if (!mode_is(hdlc, MODE_SOFT) && hdlc->destroy_pvc)		hdlc->destroy_pvc(pvc);	hdlc->lmi.state |= LINK_STATE_CHANGED;	hdlc->pvc_count--;	*pvc_p = pvc->next;	unregister_netdevice(&pvc->netdev);	kfree(pvc);	return 0;}static int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){	hdlc_device *hdlc = dev_to_hdlc(dev);	switch(cmd) {	case HDLCGMODE:		ifr->ifr_ifru.ifru_ivalue = hdlc->mode;		return 0;	case HDLCSMODE:		return hdlc_set_mode(hdlc, ifr->ifr_ifru.ifru_ivalue);	case HDLCPVC:		return hdlc_fr_pvc(hdlc, ifr->ifr_ifru.ifru_ivalue);	default:		if (hdlc->ioctl != NULL)			return hdlc->ioctl(hdlc, ifr, cmd);	}	return -EINVAL;}static int hdlc_init(struct net_device *dev){	hdlc_device *hdlc = dev_to_hdlc(dev);	memset(&(hdlc->stats), 0, sizeof(struct net_device_stats));	dev->get_stats = hdlc_get_stats;	dev->open = hdlc_open;	dev->stop = hdlc_close;	dev->hard_start_xmit = hdlc_xmit;	dev->do_ioctl = hdlc_ioctl;	dev->change_mtu = hdlc_change_mtu;	dev->mtu = HDLC_MAX_MTU;	dev->type = ARPHRD_RAWHDLC;	dev->hard_header_len = 16;	dev->flags = IFF_POINTOPOINT | IFF_NOARP;	return 0;}int register_hdlc_device(hdlc_device *hdlc){	int result;	struct net_device *dev = hdlc_to_dev(hdlc);	dev->init = hdlc_init;	dev->priv = &hdlc->syncppp_ptr;	hdlc->syncppp_ptr = &hdlc->pppdev;	hdlc->pppdev.dev = dev;	hdlc->mode = MODE_NONE;	hdlc->lmi.T391 = 10;	/* polling verification timer */	hdlc->lmi.T392 = 15;	/* link integrity verification polling timer */	hdlc->lmi.N391 = 6;	/* full status polling counter */	hdlc->lmi.N392 = 3;	/* error threshold */	hdlc->lmi.N393 = 4;	/* monitored events count */	result = dev_alloc_name(dev, "hdlc%d");	if (result<0)		return result;	result = register_netdev(dev);	if (result != 0)		return -EIO;	MOD_INC_USE_COUNT;	return 0;}void unregister_hdlc_device(hdlc_device *hdlc){	destroy_pvc_list(hdlc);	unregister_netdev(hdlc_to_dev(hdlc));	MOD_DEC_USE_COUNT;}MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");MODULE_DESCRIPTION("HDLC support module");MODULE_LICENSE("GPL");EXPORT_SYMBOL(hdlc_netif_rx);EXPORT_SYMBOL(register_hdlc_device);EXPORT_SYMBOL(unregister_hdlc_device);static int __init hdlc_module_init(void){	printk(KERN_INFO "%s\n", version);	return 0;}module_init(hdlc_module_init);

⌨️ 快捷键说明

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