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

📄 isdn_net.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	skb = alloc_skb(hl + len, GFP_ATOMIC);	if (skb)		skb_reserve(skb, hl);	else 		printk("isdn out of mem at %s:%d!\n", __FILE__, __LINE__);	return skb;}/* cisco hdlck device private ioctls */static intisdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){	isdn_net_local *lp = (isdn_net_local *) dev->priv;	unsigned long len = 0;	unsigned long expires = 0;	int tmp = 0;	int period = lp->cisco_keepalive_period;	s8 debserint = lp->cisco_debserint;	int rc = 0;	if (lp->p_encap != ISDN_NET_ENCAP_CISCOHDLCK)		return -EINVAL;	switch (cmd) {		/* get/set keepalive period */		case SIOCGKEEPPERIOD:			len = (unsigned long)sizeof(lp->cisco_keepalive_period);			if (copy_to_user(ifr->ifr_data,				&lp->cisco_keepalive_period, len))				rc = -EFAULT;			break;		case SIOCSKEEPPERIOD:			tmp = lp->cisco_keepalive_period;			len = (unsigned long)sizeof(lp->cisco_keepalive_period);			if (copy_from_user(&period, ifr->ifr_data, len))				rc = -EFAULT;			if ((period > 0) && (period <= 32767))				lp->cisco_keepalive_period = period;			else				rc = -EINVAL;			if (!rc && (tmp != lp->cisco_keepalive_period)) {				expires = (unsigned long)(jiffies +					lp->cisco_keepalive_period * HZ);				mod_timer(&lp->cisco_timer, expires);				printk(KERN_INFO "%s: Keepalive period set "					"to %d seconds.\n",					lp->name, lp->cisco_keepalive_period);			}			break;		/* get/set debugging */		case SIOCGDEBSERINT:			len = (unsigned long)sizeof(lp->cisco_debserint);			if (copy_to_user(ifr->ifr_data,				&lp->cisco_debserint, len))				rc = -EFAULT;			break;		case SIOCSDEBSERINT:			len = (unsigned long)sizeof(lp->cisco_debserint);			if (copy_from_user(&debserint,				ifr->ifr_data, len))				rc = -EFAULT;			if ((debserint >= 0) && (debserint <= 64))				lp->cisco_debserint = debserint;			else				rc = -EINVAL;			break;		default:			rc = -EINVAL;			break;	}	return (rc);}/* called via cisco_timer.function */static voidisdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data){	isdn_net_local *lp = (isdn_net_local *) data;	struct sk_buff *skb;	unsigned char *p;	unsigned long last_cisco_myseq = lp->cisco_myseq;	int myseq_diff = 0;	if (!(lp->flags & ISDN_NET_CONNECTED) || lp->dialstate) {		printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);		return;	}	lp->cisco_myseq++;	myseq_diff = (lp->cisco_myseq - lp->cisco_mineseen);	if ((lp->cisco_line_state) && ((myseq_diff >= 3)||(myseq_diff <= -3))) {		/* line up -> down */		lp->cisco_line_state = 0;		printk (KERN_WARNING				"UPDOWN: Line protocol on Interface %s,"				" changed state to down\n", lp->name);		/* should stop routing higher-level data accross */	} else if ((!lp->cisco_line_state) &&		(myseq_diff >= 0) && (myseq_diff <= 2)) {		/* line down -> up */		lp->cisco_line_state = 1;		printk (KERN_WARNING				"UPDOWN: Line protocol on Interface %s,"				" changed state to up\n", lp->name);		/* restart routing higher-level data accross */	}	if (lp->cisco_debserint)		printk (KERN_DEBUG "%s: HDLC "			"myseq %lu, mineseen %lu%c, yourseen %lu, %s\n",			lp->name, last_cisco_myseq, lp->cisco_mineseen,			((last_cisco_myseq == lp->cisco_mineseen) ? '*' : 040),			lp->cisco_yourseq,			((lp->cisco_line_state) ? "line up" : "line down"));	skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);	if (!skb)		return;	p = skb_put(skb, 4 + 14);	/* cisco header */	p += put_u8 (p, CISCO_ADDR_UNICAST);	p += put_u8 (p, CISCO_CTRL);	p += put_u16(p, CISCO_TYPE_SLARP);	/* slarp keepalive */	p += put_u32(p, CISCO_SLARP_KEEPALIVE);	p += put_u32(p, lp->cisco_myseq);	p += put_u32(p, lp->cisco_yourseq);	p += put_u16(p, 0xffff); // reliablity, always 0xffff	isdn_net_write_super(lp, skb);	lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ;		add_timer(&lp->cisco_timer);}static voidisdn_net_ciscohdlck_slarp_send_request(isdn_net_local *lp){	struct sk_buff *skb;	unsigned char *p;	skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);	if (!skb)		return;	p = skb_put(skb, 4 + 14);	/* cisco header */	p += put_u8 (p, CISCO_ADDR_UNICAST);	p += put_u8 (p, CISCO_CTRL);	p += put_u16(p, CISCO_TYPE_SLARP);	/* slarp request */	p += put_u32(p, CISCO_SLARP_REQUEST);	p += put_u32(p, 0); // address	p += put_u32(p, 0); // netmask	p += put_u16(p, 0); // unused	isdn_net_write_super(lp, skb);}static void isdn_net_ciscohdlck_connected(isdn_net_local *lp){	lp->cisco_myseq = 0;	lp->cisco_mineseen = 0;	lp->cisco_yourseq = 0;	lp->cisco_keepalive_period = ISDN_TIMER_KEEPINT;	lp->cisco_last_slarp_in = 0;	lp->cisco_line_state = 0;	lp->cisco_debserint = 0;	/* send slarp request because interface/seq.no.s reset */	isdn_net_ciscohdlck_slarp_send_request(lp);	init_timer(&lp->cisco_timer);	lp->cisco_timer.data = (unsigned long) lp;	lp->cisco_timer.function = isdn_net_ciscohdlck_slarp_send_keepalive;	lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ;	add_timer(&lp->cisco_timer);}static void isdn_net_ciscohdlck_disconnected(isdn_net_local *lp){	del_timer(&lp->cisco_timer);}static voidisdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp){	struct sk_buff *skb;	unsigned char *p;	struct in_device *in_dev = NULL;	u32 addr = 0;		/* local ipv4 address */	u32 mask = 0;		/* local netmask */	if ((in_dev = lp->netdev->dev.ip_ptr) != NULL) {		/* take primary(first) address of interface */		struct in_ifaddr *ifa = in_dev->ifa_list;		if (ifa != NULL) {			addr = ifa->ifa_local;			mask = ifa->ifa_mask;		}	}	skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);	if (!skb)		return;	p = skb_put(skb, 4 + 14);	/* cisco header */	p += put_u8 (p, CISCO_ADDR_UNICAST);	p += put_u8 (p, CISCO_CTRL);	p += put_u16(p, CISCO_TYPE_SLARP);	/* slarp reply, send own ip/netmask; if values are nonsense remote	 * should think we are unable to provide it with an address via SLARP */	p += put_u32(p, CISCO_SLARP_REPLY);	p += put_u32(p, addr);	// address	p += put_u32(p, mask);	// netmask	p += put_u16(p, 0);	// unused	isdn_net_write_super(lp, skb);}static voidisdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb){	unsigned char *p;	int period;	u32 code;	u32 my_seq, addr;	u32 your_seq, mask;	u32 local;	u16 unused;	if (skb->len < 14)		return;	p = skb->data;	p += get_u32(p, &code);		switch (code) {	case CISCO_SLARP_REQUEST:		lp->cisco_yourseq = 0;		isdn_net_ciscohdlck_slarp_send_reply(lp);		break;	case CISCO_SLARP_REPLY:		addr = ntohl(*(u32 *)p);		mask = ntohl(*(u32 *)(p+4));		if (mask != 0xfffffffc)			goto slarp_reply_out;		if ((addr & 3) == 0 || (addr & 3) == 3)			goto slarp_reply_out;		local = addr ^ 3;		printk(KERN_INFO "%s: got slarp reply: "			"remote ip: %d.%d.%d.%d, "			"local ip: %d.%d.%d.%d "			"mask: %d.%d.%d.%d\n",		       lp->name,		       HIPQUAD(addr),		       HIPQUAD(local),		       HIPQUAD(mask));		break;  slarp_reply_out:		 printk(KERN_INFO "%s: got invalid slarp "				 "reply (%d.%d.%d.%d/%d.%d.%d.%d) "				 "- ignored\n", lp->name,				 HIPQUAD(addr), HIPQUAD(mask));		break;	case CISCO_SLARP_KEEPALIVE:		period = (int)((jiffies - lp->cisco_last_slarp_in				+ HZ/2 - 1) / HZ);		if (lp->cisco_debserint &&				(period != lp->cisco_keepalive_period) &&				lp->cisco_last_slarp_in) {			printk(KERN_DEBUG "%s: Keepalive period mismatch - "				"is %d but should be %d.\n",				lp->name, period, lp->cisco_keepalive_period);		}		lp->cisco_last_slarp_in = jiffies;		p += get_u32(p, &my_seq);		p += get_u32(p, &your_seq);		p += get_u16(p, &unused);		lp->cisco_yourseq = my_seq;		lp->cisco_mineseen = your_seq;		break;	}}static voidisdn_net_ciscohdlck_receive(isdn_net_local *lp, struct sk_buff *skb){	unsigned char *p; 	u8 addr; 	u8 ctrl; 	u16 type;		if (skb->len < 4)		goto out_free;	p = skb->data;	p += get_u8 (p, &addr);	p += get_u8 (p, &ctrl);	p += get_u16(p, &type);	skb_pull(skb, 4);		if (addr != CISCO_ADDR_UNICAST && addr != CISCO_ADDR_BROADCAST) {		printk(KERN_WARNING "%s: Unknown Cisco addr 0x%02x\n",		       lp->name, addr);		goto out_free;	}	if (ctrl != CISCO_CTRL) {		printk(KERN_WARNING "%s: Unknown Cisco ctrl 0x%02x\n",		       lp->name, ctrl);		goto out_free;	}	switch (type) {	case CISCO_TYPE_SLARP:		isdn_net_ciscohdlck_slarp_in(lp, skb);		goto out_free;	case CISCO_TYPE_CDP:		if (lp->cisco_debserint)			printk(KERN_DEBUG "%s: Received CDP packet. use "				"\"no cdp enable\" on cisco.\n", lp->name);		goto out_free;	default:		/* no special cisco protocol */		skb->protocol = htons(type);		netif_rx(skb);		return;	} out_free:	kfree_skb(skb);}/* * Got a packet from ISDN-Channel. */static voidisdn_net_receive(struct net_device *ndev, struct sk_buff *skb){	isdn_net_local *lp = (isdn_net_local *) ndev->priv;	isdn_net_local *olp = lp;	/* original 'lp' */#ifdef CONFIG_ISDN_X25	struct concap_proto *cprot = lp -> netdev -> cprot;#endif	lp->transcount += skb->len;	lp->stats.rx_packets++;	lp->stats.rx_bytes += skb->len;	if (lp->master) {		/* Bundling: If device is a slave-device, deliver to master, also		 * handle master's statistics and hangup-timeout		 */		ndev = lp->master;		lp = (isdn_net_local *) ndev->priv;		lp->stats.rx_packets++;		lp->stats.rx_bytes += skb->len;	}	skb->dev = ndev;	skb->pkt_type = PACKET_HOST;	skb->mac.raw = skb->data;#ifdef ISDN_DEBUG_NET_DUMP	isdn_dumppkt("R:", skb->data, skb->len, 40);#endif	switch (lp->p_encap) {		case ISDN_NET_ENCAP_ETHER:			/* Ethernet over ISDN */			olp->huptimer = 0;			lp->huptimer = 0;			skb->protocol = isdn_net_type_trans(skb, ndev);			break;		case ISDN_NET_ENCAP_UIHDLC:			/* HDLC with UI-frame (for ispa with -h1 option) */			olp->huptimer = 0;			lp->huptimer = 0;			skb_pull(skb, 2);			/* Fall through */		case ISDN_NET_ENCAP_RAWIP:			/* RAW-IP without MAC-Header */			olp->huptimer = 0;			lp->huptimer = 0;			skb->protocol = htons(ETH_P_IP);			break;		case ISDN_NET_ENCAP_CISCOHDLCK:			isdn_net_ciscohdlck_receive(lp, skb);			return;		case ISDN_NET_ENCAP_CISCOHDLC:			/* CISCO-HDLC IP with type field and  fake I-frame-header */			skb_pull(skb, 2);			/* Fall through */		case ISDN_NET_ENCAP_IPTYP:			/* IP with type field */			olp->huptimer = 0;			lp->huptimer = 0;			skb->protocol = *(unsigned short *) &(skb->data[0]);			skb_pull(skb, 2);			if (*(unsigned short *) skb->data == 0xFFFF)				skb->protocol = htons(ETH_P_802_3);			break;#ifdef CONFIG_ISDN_PPP		case ISDN_NET_ENCAP_SYNCPPP:			/* huptimer is done in isdn_ppp_push_higher */			isdn_ppp_receive(lp->netdev, olp, skb);			return;#endif		default:#ifdef CONFIG_ISDN_X25		  /* try if there are generic sync_device receiver routines */			if(cprot) if(cprot -> pops)				if( cprot -> pops -> data_ind){					cprot -> pops -> data_ind(cprot,skb);					return;				};#endif /* CONFIG_ISDN_X25 */			printk(KERN_WARNING "%s: unknown encapsulation, dropping\n",			       lp->name);			kfree_skb(skb);			return;	}	netif_rx(skb);	return;}/* * A packet arrived via ISDN. Search interface-chain for a corresponding * interface. If found, deliver packet to receiver-function and return 1, * else return 0. */intisdn_net_rcv_skb(int idx, struct sk_buff *skb){	isdn_net_dev *p = dev->rx_netdev[idx];	if (p) {		isdn_net_local *lp = p->local;		if ((lp->flags & ISDN_NET_CONNECTED) &&		    (!lp->dialstate)) {			isdn_net_receive(&p->dev, skb);			return 1;		}	}	return 0;}static intmy_eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,	      void *daddr, void *saddr, unsigned len){	struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);	/*	 * Set the protocol type. For a packet of type ETH_P_802_3 we	 * put the length here instead. It is up to the 802.2 layer to	 * carry protocol information.	 */	if (type != ETH_P_802_3)

⌨️ 快捷键说明

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