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

📄 isdn_net.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
	ch->addr = CISCO_ADDR_UNICAST;	ch->ctrl = 0;	ch->type = htons(CISCO_TYPE_SLARP);	s = (cisco_slarp *)skb_put(skb, sizeof(cisco_slarp));	if (is_reply) {		s->code = htonl(CISCO_SLARP_REPLY);		memset(&s->slarp.reply.ifaddr, 0, sizeof(__u32));		memset(&s->slarp.reply.netmask, 0, sizeof(__u32));	} else {		lp->cisco_myseq++;		s->code = htonl(CISCO_SLARP_KEEPALIVE);		s->slarp.keepalive.my_seq = htonl(lp->cisco_myseq);		s->slarp.keepalive.your_seq = htonl(lp->cisco_yourseq);	}	s->rel = 0xffff;	s->t1 = t >> 16;	s->t0 = t & 0xffff;	isdn_net_write_super(lp, skb);}static voidisdn_net_slarp_in(isdn_net_local *lp, struct sk_buff *skb){	cisco_slarp *s = (cisco_slarp *)skb->data;	switch (ntohl(s->code)) {		case CISCO_SLARP_REQUEST:			isdn_net_slarp_send(lp, 1);			break;		case CISCO_SLARP_REPLY:			/* Ignore replies */			break;		case CISCO_SLARP_KEEPALIVE:			lp->cisco_yourseq = s->slarp.keepalive.my_seq;			if (ntohl(s->slarp.keepalive.my_seq == lp->cisco_myseq)) {				if (lp->cisco_loop++ == 2) {					printk(KERN_WARNING "%s: Keepalive Loop\n",					       lp->name);					lp->cisco_myseq ^= jiffies;				}			} else				lp->cisco_loop = 0;			break;	}	kfree_skb(skb);}/* * Called every 10 sec. via timer-interrupt if * any network-interface has Cisco-Keepalive-Encapsulation * and is online. * Send Keepalive-Packet and re-schedule. */voidisdn_net_slarp_out(void){	isdn_net_dev *p = dev->netdev;	int anymore = 0;	while (p) {		isdn_net_local *l = p->local;		if ((l->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) &&		    (l->flags & ISDN_NET_CONNECTED) &&		    (!l->dialstate)                           ) {			anymore = 1;			isdn_net_slarp_send(l, 0);		}		p = (isdn_net_dev *) p->next;	}	isdn_timer_ctrl(ISDN_TIMER_KEEPALIVE, anymore);}/* * 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_PPP	int proto = PPP_PROTOCOL(skb->data);#endif#ifdef CONFIG_ISDN_X25	struct concap_proto *cprot = lp -> netdev -> cprot;#endif	cisco_hdr *ch;	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:			ch = (cisco_hdr *)skb->data;			if ((ch->addr != CISCO_ADDR_UNICAST) &&			    (ch->addr != CISCO_ADDR_BROADCAST)  ) {				printk(KERN_WARNING "%s: Unknown Cisco addr 0x%02x\n",				       lp->name, ch->addr);				kfree_skb(skb);				return;			}			if (ch->ctrl != 0) {				printk(KERN_WARNING "%s: Unknown Cisco ctrl 0x%02x\n",				       lp->name, ch->ctrl);				kfree_skb(skb);				return;			}			switch (ntohs(ch->type)) {				case CISCO_TYPE_INET:					skb_pull(skb, 4);					skb->protocol = htons(ETH_P_IP);					break;				case CISCO_TYPE_SLARP:					skb_pull(skb, 4);					isdn_net_slarp_in(olp, skb);					return;				default:					printk(KERN_WARNING "%s: Unknown Cisco type 0x%04x\n",					       lp->name, ch->type);					kfree_skb(skb);					return;			}			break;		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:			/*			 * If encapsulation is syncppp, don't reset			 * huptimer on LCP packets.			 */			if (proto != PPP_LCP) {				olp->huptimer = 0;				lp->huptimer = 0;			}			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)		eth->h_proto = htons(type);	else		eth->h_proto = htons(len);	/*	 * Set the source hardware address.	 */	if (saddr)		memcpy(eth->h_source, saddr, dev->addr_len);	else		memcpy(eth->h_source, dev->dev_addr, dev->addr_len);	/*	 * Anyway, the loopback-device should never use this function...	 */	if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {		memset(eth->h_dest, 0, dev->addr_len);		return ETH_HLEN /*(dev->hard_header_len)*/;	}	if (daddr) {		memcpy(eth->h_dest, daddr, dev->addr_len);		return ETH_HLEN /*dev->hard_header_len*/;	}	return -ETH_HLEN /*dev->hard_header_len*/;}/* *  build an header *  depends on encaps that is being used. */static intisdn_net_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,		void *daddr, void *saddr, unsigned plen){	isdn_net_local *lp = dev->priv;	ushort len = 0;	switch (lp->p_encap) {		case ISDN_NET_ENCAP_ETHER:			len = my_eth_header(skb, dev, type, daddr, saddr, plen);			break;#ifdef CONFIG_ISDN_PPP		case ISDN_NET_ENCAP_SYNCPPP:			/* stick on a fake header to keep fragmentation code happy. */			len = IPPP_MAX_HEADER;			skb_push(skb,len);			break;#endif		case ISDN_NET_ENCAP_RAWIP:			printk(KERN_WARNING "isdn_net_header called with RAW_IP!\n");			len = 0;			break;		case ISDN_NET_ENCAP_IPTYP:			/* ethernet type field */			*((ushort *) skb_push(skb, 2)) = htons(type);			len = 2;			break;		case ISDN_NET_ENCAP_UIHDLC:			/* HDLC with UI-Frames (for ispa with -h1 option) */			*((ushort *) skb_push(skb, 2)) = htons(0x0103);			len = 2;			break;		case ISDN_NET_ENCAP_CISCOHDLC:			skb_push(skb, 4);			skb->data[0] = 0x0f;			skb->data[1] = 0x00;			*((ushort *) & skb->data[2]) = htons(type);			len = 4;			break;#ifdef CONFIG_ISDN_X25		default:		  /* try if there are generic concap protocol routines */			if( lp-> netdev -> cprot ){				printk(KERN_WARNING "isdn_net_header called with concap_proto!\n");				len = 0;				break;			}			break;#endif /* CONFIG_ISDN_X25 */	}	return len;}/* We don't need to send arp, because we have point-to-point connections. */static intisdn_net_rebuild_header(struct sk_buff *skb){	struct net_device *dev = skb->dev;	isdn_net_local *lp = dev->priv;	int ret = 0;	if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {		struct ethhdr *eth = (struct ethhdr *) skb->data;		/*		 *      Only ARP/IP is currently supported		 */		if (eth->h_proto != htons(ETH_P_IP)) {			printk(KERN_WARNING			       "isdn_net: %s don't know how to resolve type %d addresses?\n",			       dev->name, (int) eth->h_proto);			memcpy(eth->h_source, dev->dev_addr, dev->addr_len);			return 0;		}		/*		 *      Try to get ARP to resolve the header.		 */#ifdef CONFIG_INET		ret = arp_find(eth->h_dest, skb);#endif	}	return ret;}/* * Interface-setup. (just after registering a new interface) */static intisdn_net_init(struct net_device *ndev){	ushort max_hlhdr_len = 0;	isdn_net_local *lp = (isdn_net_local *) ndev->priv;	int drvidx,	 i;	if (ndev == NULL) {		printk(KERN_WARNING "isdn_net_init: dev = NULL!\n");		return -ENODEV;	}	if (ndev->priv == NULL) {		printk(KERN_WARNING "isdn_net_init: dev->priv = NULL!\n");		return -ENODEV;	}	ether_setup(ndev);	lp->org_hhc = ndev->hard_header_cache;	lp->org_hcu = ndev->header_cache_update;	/* Setup the generic properties */	ndev->hard_header = NULL;	ndev->hard_header_cache = NULL;	ndev->header_cache_update = NULL;	ndev->mtu = 1500;	ndev->flags = IFF_NOARP|IFF_POINTOPOINT;	ndev->type = ARPHRD_ETHER;	ndev->addr_len = ETH_ALEN;	/* for clients with MPPP maybe higher values better */	ndev->tx_queue_len = 30;	for (i = 0; i < ETH_ALEN; i++)		ndev->broadcast[i] = 0xff;	/* The ISDN-specific entries in the device structure. */	ndev->open = &isdn_net_open;	ndev->hard_start_xmit = &isdn_net_start_xmit;	/*	 *  up till binding we ask the protocol layer to reserve as much	 *  as we might need for HL layer	 */	for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)		if (dev->drv[drvidx])			if (max_hlhdr_len < dev->drv[drvidx]->interface->hl_hdrlen)				max_hlhdr_len = dev->drv[drvidx]->interface->hl_hdrlen;	ndev->hard_header_len = ETH_HLEN + max_hlhdr_len;	ndev->stop = &isdn_net_close;	ndev->get_stats = &isdn_net_get_stats;	ndev->rebuild_header = &isdn_net_rebuild_header;#ifdef CONFIG_ISDN_PPP	ndev->do_ioctl = isdn_ppp_dev_ioctl;#endif	return 0;}static voidisdn_net_swapbind(int drvidx){	isdn_net_dev *p;#ifdef ISDN_DEBUG_NET_ICALL	printk(KERN_DEBUG "n_fi: swapping ch of %d\n", drvidx);#endif	p = dev->netdev;	while (p) {		if (p->local->pre_device == drvidx)			switch (p->local->pre_channel) {				case 0:					p->local->pre_channel = 1;					break;				case 1:					p->local->pre_channel = 0;					break;			}		p = (isdn_net_dev *) p->next;	}}static voidisdn_net_swap_usage(int i1, int i2){	int u1 = dev->usage[i1] & ISDN_USAGE_EXCLUSIVE;	int u2 = dev->usage[i2] & ISDN_USAGE_EXCLUSIVE;#ifdef ISDN_DEBUG_NET_ICALL	printk(KERN_DEBUG "n_fi: usage of %d and %d\n", i1, i2);#endif	dev->usage[i1] &= ~ISDN_USAGE_EXCLUSIVE;	dev->usage[i1] |= u2;	dev->usage[i2] &= ~ISDN_USAGE_EXCLUSIVE;	dev->usage[i2] |= u1;	isdn_info_update();}/* * An incoming call-request has arrived. * Search the interface-chain for an appropriate interface. * If found, connect the interface to the ISDN-channel and initiate * D- and B-Channel-setup. If secure-flag is set, accept only * configured phone-numbers. If callback-flag is set, initiate * callback-dialing. * * Return-Value: 0 = No appropriate interface for this call. *               1 = Call accepted *               2 = Reject call, wait cbdelay, then call back *               3 = Reject call *               4 = Wait cbdelay, then call back *               5 = No appropriate interface for this call, *                   would eventually match if CID was longer. */intisdn_net_find_icall(int di, int ch, int idx, setup_parm *setup){	char *eaz;	int si1;

⌨️ 快捷键说明

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