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

📄 syncppp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
			sppp_print_bytes ((u8*) (h+1), len-4);		printk (">\n");	}	if (len > ntohs (h->len))		len = ntohs (h->len);	switch (h->type) {	default:		/* Unknown packet type -- send Code-Reject packet. */		sppp_cp_send (sp, PPP_LCP, LCP_CODE_REJ, ++sp->pp_seq,			skb->len, h);		break;	case LCP_CONF_REQ:		if (len < 4) {			if (sp->pp_flags & PP_DEBUG)				printk (KERN_DEBUG"%s: invalid lcp configure request packet length: %d bytes\n",					dev->name, len);			break;		}		if (len>4 && !sppp_lcp_conf_parse_options (sp, h, len, &rmagic))			goto badreq;		if (rmagic == sp->lcp.magic) {			/* Local and remote magics equal -- loopback? */			if (sp->pp_loopcnt >= MAXALIVECNT*5) {				printk (KERN_WARNING "%s: loopback\n",					dev->name);				sp->pp_loopcnt = 0;				if (dev->flags & IFF_UP) {					if_down (dev);				}			} else if (sp->pp_flags & PP_DEBUG)				printk (KERN_DEBUG "%s: conf req: magic glitch\n",					dev->name);			++sp->pp_loopcnt;			/* MUST send Conf-Nack packet. */			rmagic = ~sp->lcp.magic;			opt[0] = LCP_OPT_MAGIC;			opt[1] = sizeof (opt);			opt[2] = rmagic >> 24;			opt[3] = rmagic >> 16;			opt[4] = rmagic >> 8;			opt[5] = rmagic;			sppp_cp_send (sp, PPP_LCP, LCP_CONF_NAK,				h->ident, sizeof (opt), &opt);badreq:			switch (sp->lcp.state) {			case LCP_STATE_OPENED:				/* Initiate renegotiation. */				sppp_lcp_open (sp);				/* fall through... */			case LCP_STATE_ACK_SENT:				/* Go to closed state. */				sp->lcp.state = LCP_STATE_CLOSED;				sp->ipcp.state = IPCP_STATE_CLOSED;			}			break;		}		/* Send Configure-Ack packet. */		sp->pp_loopcnt = 0;		if (sp->lcp.state != LCP_STATE_OPENED) {			sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK,					h->ident, len-4, h+1);		}		/* Change the state. */		switch (sp->lcp.state) {		case LCP_STATE_CLOSED:			sp->lcp.state = LCP_STATE_ACK_SENT;			break;		case LCP_STATE_ACK_RCVD:			sp->lcp.state = LCP_STATE_OPENED;			sppp_ipcp_open (sp);			break;		case LCP_STATE_OPENED:			/* Remote magic changed -- close session. */			sp->lcp.state = LCP_STATE_CLOSED;			sp->ipcp.state = IPCP_STATE_CLOSED;			/* Initiate renegotiation. */			sppp_lcp_open (sp);			/* Send ACK after our REQ in attempt to break loop */			sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK,					h->ident, len-4, h+1);			sp->lcp.state = LCP_STATE_ACK_SENT;			break;		}		break;	case LCP_CONF_ACK:		if (h->ident != sp->lcp.confid)			break;		sppp_clear_timeout (sp);		if ((sp->pp_link_state != SPPP_LINK_UP) &&		    (dev->flags & IFF_UP)) {			/* Coming out of loopback mode. */			sp->pp_link_state=SPPP_LINK_UP;			printk (KERN_INFO "%s: protocol up\n", dev->name);		}		switch (sp->lcp.state) {		case LCP_STATE_CLOSED:			sp->lcp.state = LCP_STATE_ACK_RCVD;			sppp_set_timeout (sp, 5);			break;		case LCP_STATE_ACK_SENT:			sp->lcp.state = LCP_STATE_OPENED;			sppp_ipcp_open (sp);			break;		}		break;	case LCP_CONF_NAK:		if (h->ident != sp->lcp.confid)			break;		p = (u8*) (h+1);		if (len>=10 && p[0] == LCP_OPT_MAGIC && p[1] >= 4) {			rmagic = (u32)p[2] << 24 |				(u32)p[3] << 16 | p[4] << 8 | p[5];			if (rmagic == ~sp->lcp.magic) {				int newmagic;				if (sp->pp_flags & PP_DEBUG)					printk (KERN_DEBUG "%s: conf nak: magic glitch\n",						dev->name);				get_random_bytes(&newmagic, sizeof(newmagic));				sp->lcp.magic += newmagic;			} else				sp->lcp.magic = rmagic;			}		if (sp->lcp.state != LCP_STATE_ACK_SENT) {			/* Go to closed state. */			sp->lcp.state = LCP_STATE_CLOSED;			sp->ipcp.state = IPCP_STATE_CLOSED;		}		/* The link will be renegotiated after timeout,		 * to avoid endless req-nack loop. */		sppp_clear_timeout (sp);		sppp_set_timeout (sp, 2);		break;	case LCP_CONF_REJ:		if (h->ident != sp->lcp.confid)			break;		sppp_clear_timeout (sp);		/* Initiate renegotiation. */		sppp_lcp_open (sp);		if (sp->lcp.state != LCP_STATE_ACK_SENT) {			/* Go to closed state. */			sp->lcp.state = LCP_STATE_CLOSED;			sp->ipcp.state = IPCP_STATE_CLOSED;		}		break;	case LCP_TERM_REQ:		sppp_clear_timeout (sp);		/* Send Terminate-Ack packet. */		sppp_cp_send (sp, PPP_LCP, LCP_TERM_ACK, h->ident, 0, NULL);		/* Go to closed state. */		sp->lcp.state = LCP_STATE_CLOSED;		sp->ipcp.state = IPCP_STATE_CLOSED;		/* Initiate renegotiation. */		sppp_lcp_open (sp);		break;	case LCP_TERM_ACK:	case LCP_CODE_REJ:	case LCP_PROTO_REJ:		/* Ignore for now. */		break;	case LCP_DISC_REQ:		/* Discard the packet. */		break;	case LCP_ECHO_REQ:		if (sp->lcp.state != LCP_STATE_OPENED)			break;		if (len < 8) {			if (sp->pp_flags & PP_DEBUG)				printk (KERN_WARNING "%s: invalid lcp echo request packet length: %d bytes\n",					dev->name, len);			break;		}		if (ntohl (*(long*)(h+1)) == sp->lcp.magic) {			/* Line loopback mode detected. */			printk (KERN_WARNING "%s: loopback\n", dev->name);			if_down (dev);			/* Shut down the PPP link. */			sp->lcp.state = LCP_STATE_CLOSED;			sp->ipcp.state = IPCP_STATE_CLOSED;			sppp_clear_timeout (sp);			/* Initiate negotiation. */			sppp_lcp_open (sp);			break;		}		*(long*)(h+1) = htonl (sp->lcp.magic);		sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REPLY, h->ident, len-4, h+1);		break;	case LCP_ECHO_REPLY:		if (h->ident != sp->lcp.echoid)			break;		if (len < 8) {			if (sp->pp_flags & PP_DEBUG)				printk (KERN_WARNING "%s: invalid lcp echo reply packet length: %d bytes\n",					dev->name, len);			break;		}		if (ntohl (*(long*)(h+1)) != sp->lcp.magic)		sp->pp_alivecnt = 0;		break;	}}/* * Handle incoming Cisco keepalive protocol packets. */static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb){	struct cisco_packet *h;	struct net_device *dev = sp->pp_if;	if (!pskb_may_pull(skb, sizeof(struct cisco_packet))	    || (skb->len != CISCO_PACKET_LEN		&& skb->len != CISCO_BIG_PACKET_LEN)) {		if (sp->pp_flags & PP_DEBUG)			printk (KERN_WARNING "%s: invalid cisco packet length: %d bytes\n",				dev->name,  skb->len);		return;	}	h = (struct cisco_packet *)skb->data;	skb_pull(skb, sizeof(struct cisco_packet*));	if (sp->pp_flags & PP_DEBUG)		printk (KERN_WARNING "%s: cisco input: %d bytes <%xh %xh %xh %xh %xh-%xh>\n",			dev->name,  skb->len,			ntohl (h->type), h->par1, h->par2, h->rel,			h->time0, h->time1);	switch (ntohl (h->type)) {	default:		if (sp->pp_flags & PP_DEBUG)			printk (KERN_WARNING "%s: unknown cisco packet type: 0x%x\n",				dev->name,  ntohl (h->type));		break;	case CISCO_ADDR_REPLY:		/* Reply on address request, ignore */		break;	case CISCO_KEEPALIVE_REQ:		sp->pp_alivecnt = 0;		sp->pp_rseq = ntohl (h->par1);		if (sp->pp_seq == sp->pp_rseq) {			/* Local and remote sequence numbers are equal.			 * Probably, the line is in loopback mode. */			int newseq;			if (sp->pp_loopcnt >= MAXALIVECNT) {				printk (KERN_WARNING "%s: loopback\n",					dev->name);				sp->pp_loopcnt = 0;				if (dev->flags & IFF_UP) {					if_down (dev);				}			}			++sp->pp_loopcnt;			/* Generate new local sequence number */			get_random_bytes(&newseq, sizeof(newseq));			sp->pp_seq ^= newseq;			break;		}		sp->pp_loopcnt = 0;		if (sp->pp_link_state==SPPP_LINK_DOWN &&		    (dev->flags & IFF_UP)) {			sp->pp_link_state=SPPP_LINK_UP;			printk (KERN_INFO "%s: protocol up\n", dev->name);		}		break;	case CISCO_ADDR_REQ:		/* Stolen from net/ipv4/devinet.c -- SIOCGIFADDR ioctl */		{		struct in_device *in_dev;		struct in_ifaddr *ifa;		u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */#ifdef CONFIG_INET		rcu_read_lock();		if ((in_dev = __in_dev_get_rcu(dev)) != NULL)		{			for (ifa=in_dev->ifa_list; ifa != NULL;				ifa=ifa->ifa_next) {				if (strcmp(dev->name, ifa->ifa_label) == 0) 				{					addr = ifa->ifa_local;					mask = ifa->ifa_mask;					break;				}			}		}		rcu_read_unlock();#endif				/* I hope both addr and mask are in the net order */		sppp_cisco_send (sp, CISCO_ADDR_REPLY, addr, mask);		break;		}	}}/* * Send PPP LCP packet. */static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type,	u8 ident, u16 len, void *data){	struct ppp_header *h;	struct lcp_header *lh;	struct sk_buff *skb;	struct net_device *dev = sp->pp_if;	skb=alloc_skb(dev->hard_header_len+PPP_HEADER_LEN+LCP_HEADER_LEN+len,		GFP_ATOMIC);	if (skb==NULL)		return;	skb_reserve(skb,dev->hard_header_len);		h = (struct ppp_header *)skb_put(skb, sizeof(struct ppp_header));	h->address = PPP_ALLSTATIONS;        /* broadcast address */	h->control = PPP_UI;                 /* Unnumbered Info */	h->protocol = htons (proto);         /* Link Control Protocol */	lh = (struct lcp_header *)skb_put(skb, sizeof(struct lcp_header));	lh->type = type;	lh->ident = ident;	lh->len = htons (LCP_HEADER_LEN + len);	if (len)		memcpy(skb_put(skb,len),data, len);	if (sp->pp_flags & PP_DEBUG) {		printk (KERN_WARNING "%s: %s output <%s id=%xh len=%xh",			dev->name, 			proto==PPP_LCP ? "lcp" : "ipcp",			proto==PPP_LCP ? sppp_lcp_type_name (lh->type) :			sppp_ipcp_type_name (lh->type), lh->ident,			ntohs (lh->len));		if (len)			sppp_print_bytes ((u8*) (lh+1), len);		printk (">\n");	}	sp->obytes += skb->len;	/* Control is high priority so it doesn't get queued behind data */	skb->priority=TC_PRIO_CONTROL;	skb->dev = dev;	skb_queue_tail(&tx_queue, skb);}/* * Send Cisco keepalive packet. */static void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2){	struct ppp_header *h;	struct cisco_packet *ch;	struct sk_buff *skb;	struct net_device *dev = sp->pp_if;	u32 t = jiffies * 1000/HZ;	skb=alloc_skb(dev->hard_header_len+PPP_HEADER_LEN+CISCO_PACKET_LEN,		GFP_ATOMIC);	if(skb==NULL)		return;			skb_reserve(skb, dev->hard_header_len);	h = (struct ppp_header *)skb_put (skb, sizeof(struct ppp_header));	h->address = CISCO_MULTICAST;	h->control = 0;	h->protocol = htons (CISCO_KEEPALIVE);	ch = (struct cisco_packet*)skb_put(skb, CISCO_PACKET_LEN);	ch->type = htonl (type);	ch->par1 = htonl (par1);	ch->par2 = htonl (par2);	ch->rel = -1;	ch->time0 = htons ((u16) (t >> 16));	ch->time1 = htons ((u16) t);	if (sp->pp_flags & PP_DEBUG)		printk (KERN_WARNING "%s: cisco output: <%xh %xh %xh %xh %xh-%xh>\n",			dev->name,  ntohl (ch->type), ch->par1,			ch->par2, ch->rel, ch->time0, ch->time1);	sp->obytes += skb->len;	skb->priority=TC_PRIO_CONTROL;	skb->dev = dev;	skb_queue_tail(&tx_queue, skb);}/** *	sppp_close - close down a synchronous PPP or Cisco HDLC link *	@dev: The network device to drop the link of * *	This drops the logical interface to the channel. It is not *	done politely as we assume we will also be dropping DTR. Any *	timeouts are killed. */int sppp_close (struct net_device *dev){	struct sppp *sp = (struct sppp *)sppp_of(dev);	unsigned long flags;	spin_lock_irqsave(&sp->lock, flags);	sp->pp_link_state = SPPP_LINK_DOWN;	sp->lcp.state = LCP_STATE_CLOSED;	sp->ipcp.state = IPCP_STATE_CLOSED;	sppp_clear_timeout (sp);	spin_unlock_irqrestore(&sp->lock, flags);	return 0;}EXPORT_SYMBOL(sppp_close);/** *	sppp_open - open a synchronous PPP or Cisco HDLC link *	@dev:	Network device to activate *	 *	Close down any existing synchronous session and commence *	from scratch. In the PPP case this means negotiating LCP/IPCP *	and friends, while for Cisco HDLC we simply need to start sending *	keepalives */int sppp_open (struct net_device *dev){	struct sppp *sp = (struct sppp *)sppp_of(dev);	unsigned long flags;	sppp_close(dev);	spin_lock_irqsave(&sp->lock, flags);	if (!(sp->pp_flags & PP_CISCO)) {		sppp_lcp_open (sp);	}	sp->pp_link_state = SPPP_LINK_DOWN;	spin_unlock_irqrestore(&sp->lock, flags);	sppp_flush_xmit();	return 0;}EXPORT_SYMBOL(sppp_open);/** *	sppp_reopen - notify of physical link loss *	@dev: Device that lost the link * *	This function informs the synchronous protocol code that *	the underlying link died (for example a carrier drop on X.21) * *	We increment the magic numbers to ensure that if the other end *	failed to notice we will correctly start a new session. It happens *	do to the nature of telco circuits is that you can lose carrier on *	one endonly. * *	Having done this we go back to negotiating. This function may *	be called from an interrupt context. */ int sppp_reopen (struct net_device *dev){	struct sppp *sp = (struct sppp *)sppp_of(dev);	unsigned long flags;	sppp_close(dev);	spin_lock_irqsave(&sp->lock, flags);	if (!(sp->pp_flags & PP_CISCO))	{		sp->lcp.magic = jiffies;		++sp->pp_seq;		sp->lcp.state = LCP_STATE_CLOSED;		sp->ipcp.state = IPCP_STATE_CLOSED;		/* Give it a moment for the line to settle then go */		sppp_set_timeout (sp, 1);	} 	sp->pp_link_state=SPPP_LINK_DOWN;	spin_unlock_irqrestore(&sp->lock, flags);	return 0;}EXPORT_SYMBOL(sppp_reopen);/** *	sppp_change_mtu - Change the link MTU *	@dev:	Device to change MTU on *	@new_mtu: New MTU * *	Change the MTU on the link. This can only be called with *	the link down. It returns an error if the link is up or *	the mtu is out of range. */ static int sppp_change_mtu(struct net_device *dev, int new_mtu){

⌨️ 快捷键说明

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