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

📄 slip.c

📁 完整的1.0代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Add an ARP-entry for this device's broadcast address. Not used. */static voidsl_add_arp(unsigned long addr, struct sk_buff *skb, struct device *dev){#ifdef CONFIG_AX25	struct slip *sl=&sl_ctrl[dev->base_addr];		if(sl->mode&SL_MODE_AX25)		arp_add(addr,((char *) skb->data)+8,dev);#endif		}/* Rebuild the MAC-level header.  Not used by SLIP. */static intsl_rebuild_header(void *buff, struct device *dev){#ifdef CONFIG_AX25  struct slip *sl=&sl_ctrl[dev->base_addr];    if(sl->mode&SL_MODE_AX25)  	return ax25_rebuild_header(buff,dev);#endif    return(0);}/* Open the low-level part of the SLIP channel. Easy! */static intsl_open(struct device *dev){  struct slip *sl;  unsigned char *p;  unsigned long l;  sl = &sl_ctrl[dev->base_addr];  if (sl->tty == NULL) {	DPRINTF((DBG_SLIP, "SLIP: channel %d not connected!\n", sl->line));	return(-ENXIO);  }  sl->dev = dev;  /*   * Allocate the SLIP frame buffers:   *   * mem_end	Top of frame buffers   * mem_start	Start of frame buffers   * rmem_end	Top of RECV frame buffer   * rmem_start	Start of RECV frame buffer   */  l = (dev->mtu * 2);/* * allow for arrival of larger UDP packets, even if we say not to * also fixes a bug in which SunOS sends 512-byte packets even with * an MSS of 128 */  if (l < (576 * 2))    l = 576 * 2;  p = (unsigned char *) kmalloc(l + 4, GFP_KERNEL);  if (p == NULL) {	DPRINTF((DBG_SLIP, "SLIP: no memory for SLIP XMIT buffer!\n"));	return(-ENOMEM);  }    sl->mtu		= dev->mtu;  sl->dev->mem_start	= (unsigned long) p;  sl->dev->mem_end	= (unsigned long) (sl->dev->mem_start + l);  p = (unsigned char *) kmalloc(l + 4, GFP_KERNEL);  if (p == NULL) {	DPRINTF((DBG_SLIP, "SLIP: no memory for SLIP RECV buffer!\n"));	return(-ENOMEM);  }  sl->dev->rmem_start	= (unsigned long) p;  sl->dev->rmem_end	= (unsigned long) (sl->dev->rmem_start + l);  sl->xbuff		= (unsigned char *) sl->dev->mem_start;  sl->rbuff		= (unsigned char *) sl->dev->rmem_start;  sl->rend		= (unsigned char *) sl->dev->rmem_end;  sl->rhead		= sl->rbuff;  sl->escape		= 0;  sl->sending		= 0;  sl->rcount		= 0;  p = (unsigned char *) kmalloc(l + 4, GFP_KERNEL);  if (p == NULL) {  	kfree((unsigned char *)sl->dev->mem_start);	DPRINTF((DBG_SLIP, "SLIP: no memory for SLIP COMPRESS buffer!\n"));	return(-ENOMEM);  }  sl->cbuff		= p;  sl->slcomp = slhc_init(16, 16);  if (sl->slcomp == NULL) {  	kfree((unsigned char *)sl->dev->mem_start);  	kfree((unsigned char *)sl->dev->rmem_start);  	kfree(sl->cbuff);	DPRINTF((DBG_SLIP, "SLIP: no memory for SLCOMP!\n"));	return(-ENOMEM);  }  dev->flags|=IFF_UP;  /* Needed because address '0' is special */  if(dev->pa_addr==0)  	dev->pa_addr=ntohl(0xC0000001);  DPRINTF((DBG_SLIP, "SLIP: channel %d opened.\n", sl->line));  return(0);}/* Close the low-level part of the SLIP channel. Easy! */static intsl_close(struct device *dev){  struct slip *sl;  sl = &sl_ctrl[dev->base_addr];  if (sl->tty == NULL) {	DPRINTF((DBG_SLIP, "SLIP: channel %d not connected!\n", sl->line));	return(-EBUSY);  }  sl_free(sl);  /* Free all SLIP frame buffers. */  kfree(sl->rbuff);  kfree(sl->xbuff);  kfree(sl->cbuff);  slhc_free(sl->slcomp);  sl_initialize(sl, dev);  DPRINTF((DBG_SLIP, "SLIP: channel %d closed.\n", sl->line));  return(0);}/* * Handle the 'receiver data ready' interrupt. * This function is called by the 'tty_io' module in the kernel when * a block of SLIP data has been received, which can now be decapsulated * and sent on to some IP layer for further processing. */static voidslip_recv(struct tty_struct *tty){  unsigned char buff[128];  unsigned char *p;  struct slip *sl;  int count, error=0;    DPRINTF((DBG_SLIP, "SLIP: slip_recv(%d) called\n", tty->line));  if ((sl = sl_find(tty)) == NULL) return;	/* not connected */  if(sl->mtu!=sl->dev->mtu)	/* Argh! mtu change time! - costs us the packet part received at the change */  	sl_changedmtu(sl);  	  /* Suck the bytes out of the TTY queues. */  do {	count = tty_read_raw_data(tty, buff, 128);	if (count <= 0)	{		count= - count;		if(count)			error=1;		break;	}	p = buff;#ifdef OLD		while (count--) {		c = *p++;		if (sl->escape) {			if (c == ESC_ESC)				sl_enqueue(sl, ESC);			else if (c == ESC_END)				sl_enqueue(sl, END);			else				printk ("SLIP: received wrong character\n");			sl->escape = 0;		} else {			if (c == ESC)				sl->escape = 1;			else if (c == END) {				if (sl->rcount > 2) sl_bump(sl);				sl_dequeue(sl, sl->rcount);				sl->rcount = 0;			} else	sl_enqueue(sl, c);		}	}#else	if(sl->mode & SL_MODE_SLIP6)		slip_unesc6(sl,buff,count,error);	else		slip_unesc(sl,buff,count,error);#endif		  } while(1);  }/* * Open the high-level part of the SLIP channel.   * This function is called by the TTY module when the * SLIP line discipline is called for.  Because we are * sure the tty line exists, we only have to link it to * a free SLIP channel... */static intslip_open(struct tty_struct *tty){  struct slip *sl;  /* First make sure we're not already connected. */  if ((sl = sl_find(tty)) != NULL) {	DPRINTF((DBG_SLIP, "SLIP: TTY %d already connected to %s !\n",					tty->line, sl->dev->name));	return(-EEXIST);  }  /* OK.  Find a free SLIP channel to use. */  if ((sl = sl_alloc()) == NULL) {	DPRINTF((DBG_SLIP, "SLIP: TTY %d not connected: all channels in use!\n",						tty->line));	return(-ENFILE);  }  sl->tty = tty;  tty_read_flush(tty);  tty_write_flush(tty);  /* Perform the low-level SLIP initialization. */  (void) sl_open(sl->dev);  DPRINTF((DBG_SLIP, "SLIP: TTY %d connected to %s.\n",				tty->line, sl->dev->name));  /* Done.  We have linked the TTY line to a channel. */  return(sl->line);} static struct enet_statistics *sl_get_stats(struct device *dev){    static struct enet_statistics stats;    struct slip *sl;    struct slcompress *comp;    /* Find the correct SLIP channel to use. */    sl = &sl_ctrl[dev->base_addr];    if (! sl)      return NULL;    memset(&stats, 0, sizeof(struct enet_statistics));    stats.rx_packets = sl->rpacket;    stats.rx_over_errors = sl->roverrun;    stats.tx_packets = sl->spacket;    stats.tx_dropped = sl->sbusy;    stats.rx_errors = sl->errors;    comp = sl->slcomp;    if (comp) {      stats.rx_fifo_errors = comp->sls_i_compressed;      stats.rx_dropped = comp->sls_i_tossed;      stats.tx_fifo_errors = comp->sls_o_compressed;      stats.collisions = comp->sls_o_misses;    }    return (&stats);}/* * Close down a SLIP channel. * This means flushing out any pending queues, and then restoring the * TTY line discipline to what it was before it got hooked to SLIP * (which usually is TTY again). */static voidslip_close(struct tty_struct *tty){  struct slip *sl;  /* First make sure we're connected. */  if ((sl = sl_find(tty)) == NULL) {	DPRINTF((DBG_SLIP, "SLIP: TTY %d not connected !\n", tty->line));	return;  }  (void) dev_close(sl->dev);  DPRINTF((DBG_SLIP, "SLIP: TTY %d disconnected from %s.\n",					tty->line, sl->dev->name));}  /************************************************************************  *			STANDARD SLIP ENCAPSULATION			*  ************************************************************************  *  */  int slip_esc(unsigned char *s, unsigned char *d, int len) {     int count = 0;      /*      * Send an initial END character to flush out any      * data that may have accumulated in the receiver      * due to line noise.      */      d[count++] = END;      /*      * For each byte in the packet, send the appropriate      * character sequence, according to the SLIP protocol.      */      while(len-- > 0) {     	switch(*s) {     	case END:     	    d[count++] = ESC;     	    d[count++] = ESC_END; 	    break; 	case ESC:     	    d[count++] = ESC;     	    d[count++] = ESC_ESC; 	    break; 	default: 	    d[count++] = *s; 	} 	++s;     }     d[count++] = END;     return(count); }  void slip_unesc(struct slip *sl, unsigned char *s, int count, int error) {     int i;      for (i = 0; i < count; ++i, ++s) { 	switch(*s) { 	case ESC: 	    sl->flags |= SLF_ESCAPE; 	    break; 	case ESC_ESC: 	    if (sl->flags & SLF_ESCAPE) 	    	sl_enqueue(sl, ESC); 	    else 	        sl_enqueue(sl, *s);	    sl->flags &= ~SLF_ESCAPE; 	    break;	case ESC_END: 	    if (sl->flags & SLF_ESCAPE)	    	sl_enqueue(sl, END);	    else 	        sl_enqueue(sl, *s);	    sl->flags &= ~SLF_ESCAPE;	    break;	case END: 	    if (sl->rcount > 2)  	    	sl_bump(sl); 	    sl_dequeue(sl, sl->rcount); 	    sl->rcount = 0; 	    sl->flags &= ~(SLF_ESCAPE | SLF_ERROR); 	    break; 	default: 	    sl_enqueue(sl, *s); 	    sl->flags &= ~SLF_ESCAPE; 	}     }     if (error)     	sl->flags |= SLF_ERROR; }  /************************************************************************  *			 6 BIT SLIP ENCAPSULATION			*  ************************************************************************  *  */  int slip_esc6(unsigned char *s, unsigned char *d, int len) {     int count = 0;     int i;     unsigned short v = 0;     short bits = 0;      /*      * Send an initial END character to flush out any      * data that may have accumulated in the receiver      * due to line noise.      */      d[count++] = 0x70;      /*      * Encode the packet into printable ascii characters      */      for (i = 0; i < len; ++i) {     	v = (v << 8) | s[i];     	bits += 8;     	while (bits >= 6) {     	    unsigned char c;      	    bits -= 6;     	    c = 0x30 + ((v >> bits) & 0x3F);     	    d[count++] = c; 	}     }     if (bits) {     	unsigned char c;      	c = 0x30 + ((v << (6 - bits)) & 0x3F);     	d[count++] = c;     }     d[count++] = 0x70;     return(count); }  void slip_unesc6(struct slip *sl, unsigned char *s, int count, int error) {     int i;     unsigned char c;      for (i = 0; i < count; ++i, ++s) {     	if (*s == 0x70) { 	    if (sl->rcount > 8) {	/* XXX must be 2 for compressed slip */ #ifdef NOTDEF 	        printk("rbuff %02x %02x %02x %02x\n", 	            sl->rbuff[0], 	            sl->rbuff[1], 	            sl->rbuff[2], 	            sl->rbuff[3] 	        ); #endif 	    	sl_bump(sl); 	    } 	    sl_dequeue(sl, sl->rcount); 	    sl->rcount = 0; 	    sl->flags &= ~(SLF_ESCAPE | SLF_ERROR); /* SLF_ESCAPE not used */ 	    sl->xbits = 0; 	} else if (*s >= 0x30 && *s < 0x70) { 	    sl->xdata = (sl->xdata << 6) | ((*s - 0x30) & 0x3F); 	    sl->xbits += 6; 	    if (sl->xbits >= 8) { 	    	sl->xbits -= 8; 	    	c = (unsigned char)(sl->xdata >> sl->xbits); 		sl_enqueue(sl, c); 	    }  	}     }     if (error)     	sl->flags |= SLF_ERROR; }#ifdef CONFIG_AX25int sl_set_mac_address(struct device *dev, void *addr){	int err=verify_area(VERIFY_READ,addr,7);	if(err)		return err;	memcpy_fromfs(dev->dev_addr,addr,7);	/* addr is an AX.25 shifted ASCII mac address */	return 0;}#endif/* Perform I/O control on an active SLIP channel. */static intslip_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg){  struct slip *sl;  int err;  /* First make sure we're connected. */  if ((sl = sl_find(tty)) == NULL) {	DPRINTF((DBG_SLIP, "SLIP: ioctl: TTY %d not connected !\n", tty->line));	return(-EINVAL);  }  DPRINTF((DBG_SLIP, "SLIP: ioctl(%d, 0x%X, 0x%X)\n", tty->line, cmd, arg));  switch(cmd) {	case SIOCGIFNAME:		err=verify_area(VERIFY_WRITE, arg, 16);		if(err)			return -err;		memcpy_tofs(arg, sl->dev->name, strlen(sl->dev->name) + 1);		return(0);	case SIOCGIFENCAP:		err=verify_area(VERIFY_WRITE,arg,sizeof(long));		put_fs_long(sl->mode,(long *)arg);		return(0);	case SIOCSIFENCAP:		err=verify_area(VERIFY_READ,arg,sizeof(long));		sl->mode=get_fs_long((long *)arg);#ifdef CONFIG_AX25				if(sl->mode & SL_MODE_AX25)		{			sl->dev->addr_len=7;	/* sizeof an AX.25 addr */			sl->dev->hard_header_len=17;	/* We don't do digipeaters */			sl->dev->type=3;		/* AF_AX25 not an AF_INET device */		}		else		{			sl->dev->addr_len=0;	/* No mac addr in slip mode */			sl->dev->hard_header_len=0;			sl->dev->type=0;		}#endif				return(0);	case SIOCSIFHWADDR:#ifdef CONFIG_AX25			return sl_set_mac_address(sl->dev,arg);#endif	default:		return(-EINVAL);  }  return(-EINVAL);}/* Initialize the SLIP driver.  Called by DDI. */intslip_init(struct device *dev){  struct slip *sl;  int i;#ifdef CONFIG_AX25    static char ax25_bcast[7]={'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};  static char ax25_test[7]={'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};#endif  sl = &sl_ctrl[dev->base_addr];  if (already++ == 0) {	printk("SLIP: version %s (%d channels)\n",				SLIP_VERSION, SL_NRUNIT);	printk("CSLIP: code copyright 1989 Regents of the University of California\n");#ifdef CONFIG_AX25	printk("AX25: KISS encapsulation enabled\n");#endif		/* Fill in our LDISC request block. */	sl_ldisc.flags	= 0;	sl_ldisc.open	= slip_open;	sl_ldisc.close	= slip_close;	sl_ldisc.read	= NULL;	sl_ldisc.write	= NULL;	sl_ldisc.ioctl	= (int (*)(struct tty_struct *, struct file *,				   unsigned int, unsigned long)) slip_ioctl;	sl_ldisc.select = NULL;	sl_ldisc.handler = slip_recv;	if ((i = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0)		printk("ERROR: %d\n", i);  }  /* Set up the "SLIP Control Block". */  sl_initialize(sl, dev);  /* Clear all statistics. */  sl->rcount		= 0;			/* SLIP receiver count	*/  sl->rpacket		= 0;			/* #frames received	*/  sl->roverrun		= 0;			/* "overrun" counter	*/  sl->spacket		= 0;			/* #frames sent out	*/  sl->sbusy		= 0;			/* "xmit busy" counter	*/  sl->errors		= 0;			/* not used at present	*/  /* Finish setting up the DEVICE info. */  dev->mtu		= SL_MTU;  dev->hard_start_xmit	= sl_xmit;  dev->open		= sl_open;  dev->stop		= sl_close;  dev->hard_header	= sl_header;  dev->add_arp		= sl_add_arp;  dev->type_trans	= sl_type_trans;  dev->get_stats	= sl_get_stats;#ifdef HAVE_SET_MAC_ADDR#ifdef CONFIG_AX25  dev->set_mac_address  = sl_set_mac_address;#endif#endif  dev->hard_header_len	= 0;  dev->addr_len		= 0;  dev->type		= 0;#ifdef CONFIG_AX25    memcpy(dev->broadcast,ax25_bcast,7);		/* Only activated in AX.25 mode */  memcpy(dev->dev_addr,ax25_test,7);		/*    ""      ""       ""    "" */#endif    dev->queue_xmit	= dev_queue_xmit;  dev->rebuild_header	= sl_rebuild_header;  for (i = 0; i < DEV_NUMBUFFS; i++)		dev->buffs[i] = NULL;  /* New-style flags. */  dev->flags		= 0;  dev->family		= AF_INET;  dev->pa_addr		= 0;  dev->pa_brdaddr	= 0;  dev->pa_mask		= 0;  dev->pa_alen		= sizeof(unsigned long);  return(0);}

⌨️ 快捷键说明

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