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

📄 irnet_ppp.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
#endif /* FLUSH_TO_PPP */      err = 0;      break;    case FIONREAD:      DEBUG(FS_INFO, "FIONREAD\n");      val = 0;      if(put_user(val, (int *) arg))	break;      err = 0;      break;    default:      DERROR(FS_ERROR, "Unsupported ioctl (0x%X)\n", cmd);      err = -ENOIOCTLCMD;    }  DEXIT(FS_TRACE, " - err = 0x%X\n", err);  return err;}/************************** PPP CALLBACKS **************************//* * This are the functions that the generic PPP driver in the kernel * will call to communicate to us. *//*------------------------------------------------------------------*//* * Prepare the ppp frame for transmission over the IrDA socket. * We make sure that the header space is enough, and we change ppp header * according to flags passed by pppd. * This is not a callback, but just a helper function used in ppp_irnet_send() */static inline struct sk_buff *irnet_prepare_skb(irnet_socket *	ap,		  struct sk_buff *	skb){  unsigned char *	data;  int			proto;		/* PPP protocol */  int			islcp;		/* Protocol == LCP */  int			needaddr;	/* Need PPP address */  DENTER(PPP_TRACE, "(ap=0x%X, skb=0x%X)\n",	 (unsigned int) ap, (unsigned int) skb);  /* Extract PPP protocol from the frame */  data  = skb->data;  proto = (data[0] << 8) + data[1];  /* LCP packets with codes between 1 (configure-request)   * and 7 (code-reject) must be sent as though no options   * have been negotiated. */  islcp = (proto == PPP_LCP) && (1 <= data[2]) && (data[2] <= 7);  /* compress protocol field if option enabled */  if((data[0] == 0) && (ap->flags & SC_COMP_PROT) && (!islcp))    skb_pull(skb,1);  /* Check if we need address/control fields */  needaddr = 2*((ap->flags & SC_COMP_AC) == 0 || islcp);  /* Is the skb headroom large enough to contain all IrDA-headers? */  if((skb_headroom(skb) < (ap->max_header_size + needaddr)) ||      (skb_shared(skb)))    {      struct sk_buff *	new_skb;      DEBUG(PPP_INFO, "Reallocating skb\n");      /* Create a new skb */      new_skb = skb_realloc_headroom(skb, ap->max_header_size + needaddr);      /* We have to free the original skb anyway */      dev_kfree_skb(skb);      /* Did the realloc succeed ? */      DABORT(new_skb == NULL, NULL, PPP_ERROR, "Could not realloc skb\n");      /* Use the new skb instead */      skb = new_skb;    }  /* prepend address/control fields if necessary */  if(needaddr)    {      skb_push(skb, 2);      skb->data[0] = PPP_ALLSTATIONS;      skb->data[1] = PPP_UI;    }  DEXIT(PPP_TRACE, "\n");  return skb;}/*------------------------------------------------------------------*//* * Send a packet to the peer over the IrTTP connection. * Returns 1 iff the packet was accepted. * Returns 0 iff packet was not consumed. * If the packet was not accepted, we will call ppp_output_wakeup * at some later time to reactivate flow control in ppp_generic. */static intppp_irnet_send(struct ppp_channel *	chan,	       struct sk_buff *		skb){  irnet_socket *	self = (struct irnet_socket *) chan->private;  int			ret;  DENTER(PPP_TRACE, "(channel=0x%X, ap/self=0x%X)\n",	 (unsigned int) chan, (unsigned int) self);  /* Check if things are somewhat valid... */  DASSERT(self != NULL, 0, PPP_ERROR, "Self is NULL !!!\n");  /* Check if we are connected */  if(!(test_bit(0, &self->ttp_open)))    {#ifdef CONNECT_IN_SEND      /* Let's try to connect one more time... */      /* Note : we won't be connected after this call, but we should be       * ready for next packet... */      /* If we are already connecting, this will fail */      irda_irnet_connect(self);#endif /* CONNECT_IN_SEND */      DEBUG(PPP_INFO, "IrTTP not ready ! (%d-%d)\n",	    self->ttp_open, self->ttp_connect);      /* Note : we can either drop the packet or block the packet.       *       * Blocking the packet allow us a better connection time,       * because by calling ppp_output_wakeup() we can have       * ppp_generic resending the LCP request immediately to us,       * rather than waiting for one of pppd periodic transmission of       * LCP request.       *       * On the other hand, if we block all packet, all those periodic       * transmissions of pppd accumulate in ppp_generic, creating a       * backlog of LCP request. When we eventually connect later on,       * we have to transmit all this backlog before we can connect       * proper (if we don't timeout before).       *       * The current strategy is as follow :       * While we are attempting to connect, we block packets to get       * a better connection time.       * If we fail to connect, we drain the queue and start dropping packets       */#ifdef BLOCK_WHEN_CONNECT      /* If we are attempting to connect */      if(test_bit(0, &self->ttp_connect))	{	  /* Blocking packet, ppp_generic will retry later */	  return 0;	}#endif /* BLOCK_WHEN_CONNECT */      /* Dropping packet, pppd will retry later */      dev_kfree_skb(skb);      return 1;    }  /* Check if the queue can accept any packet, otherwise block */  if(self->tx_flow != FLOW_START)    DRETURN(0, PPP_INFO, "IrTTP queue full (%d skbs)...\n",	    skb_queue_len(&self->tsap->tx_queue));  /* Prepare ppp frame for transmission */  skb = irnet_prepare_skb(self, skb);  DABORT(skb == NULL, 1, PPP_ERROR, "Prepare skb for Tx failed.\n");  /* Send the packet to IrTTP */  ret = irttp_data_request(self->tsap, skb);  if(ret < 0)    {      /*          * > IrTTPs tx queue is full, so we just have to       * > drop the frame! You might think that we should       * > just return -1 and don't deallocate the frame,       * > but that is dangerous since it's possible that       * > we have replaced the original skb with a new       * > one with larger headroom, and that would really       * > confuse do_dev_queue_xmit() in dev.c! I have       * > tried :-) DB        * Correction : we verify the flow control above (self->tx_flow),       * so we come here only if IrTTP doesn't like the packet (empty,       * too large, IrTTP not connected). In those rare cases, it's ok       * to drop it, we don't want to see it here again...       * Jean II       */      DERROR(PPP_ERROR, "IrTTP doesn't like this packet !!! (0x%X)\n", ret);      dev_kfree_skb(skb);    }  DEXIT(PPP_TRACE, "\n");  return 1;	/* Packet has been consumed */}/*------------------------------------------------------------------*//* * Take care of the ioctls that ppp_generic doesn't want to deal with... * Note : we are also called from dev_irnet_ioctl(). */static intppp_irnet_ioctl(struct ppp_channel *	chan,		unsigned int		cmd,		unsigned long		arg){  irnet_socket *	ap = (struct irnet_socket *) chan->private;  int			err;  int			val;  u32			accm[8];  DENTER(PPP_TRACE, "(channel=0x%X, ap=0x%X, cmd=0x%X)\n",	 (unsigned int) chan, (unsigned int) ap, cmd);  /* Basic checks... */  DASSERT(ap != NULL, -ENXIO, PPP_ERROR, "ap is NULL...\n");  err = -EFAULT;  switch(cmd)    {      /* PPP flags */    case PPPIOCGFLAGS:      val = ap->flags | ap->rbits;      if(put_user(val, (int *) arg))	break;      err = 0;      break;    case PPPIOCSFLAGS:      if(get_user(val, (int *) arg))	break;      ap->flags = val & ~SC_RCV_BITS;      ap->rbits = val & SC_RCV_BITS;      err = 0;      break;      /* Async map stuff - all dummy to please pppd */    case PPPIOCGASYNCMAP:      if(put_user(ap->xaccm[0], (u32 *) arg))	break;      err = 0;      break;    case PPPIOCSASYNCMAP:      if(get_user(ap->xaccm[0], (u32 *) arg))	break;      err = 0;      break;    case PPPIOCGRASYNCMAP:      if(put_user(ap->raccm, (u32 *) arg))	break;      err = 0;      break;    case PPPIOCSRASYNCMAP:      if(get_user(ap->raccm, (u32 *) arg))	break;      err = 0;      break;    case PPPIOCGXASYNCMAP:      if(copy_to_user((void *) arg, ap->xaccm, sizeof(ap->xaccm)))	break;      err = 0;      break;    case PPPIOCSXASYNCMAP:      if(copy_from_user(accm, (void *) arg, sizeof(accm)))	break;      accm[2] &= ~0x40000000U;		/* can't escape 0x5e */      accm[3] |= 0x60000000U;		/* must escape 0x7d, 0x7e */      memcpy(ap->xaccm, accm, sizeof(ap->xaccm));      err = 0;      break;      /* Max PPP frame size */    case PPPIOCGMRU:      if(put_user(ap->mru, (int *) arg))	break;      err = 0;      break;    case PPPIOCSMRU:      if(get_user(val, (int *) arg))	break;      if(val < PPP_MRU)	val = PPP_MRU;      ap->mru = val;      err = 0;      break;    default:      DEBUG(PPP_INFO, "Unsupported ioctl (0x%X)\n", cmd);      err = -ENOIOCTLCMD;    }  DEXIT(PPP_TRACE, " - err = 0x%X\n", err);  return err;}/************************** INITIALISATION **************************//* * Module initialisation and all that jazz... *//*------------------------------------------------------------------*//* * Hook our device callbacks in the filesystem, to connect our code * to /dev/irnet */intppp_irnet_init(void){  int err = 0;  DENTER(MODULE_TRACE, "()\n");  /* Allocate ourselves as a minor in the misc range */  err = misc_register(&irnet_misc_device);  DEXIT(MODULE_TRACE, "\n");  return err;}/*------------------------------------------------------------------*//* * Cleanup at exit... */voidppp_irnet_cleanup(void){  DENTER(MODULE_TRACE, "()\n");  /* De-allocate /dev/irnet minor in misc range */  misc_deregister(&irnet_misc_device);  DEXIT(MODULE_TRACE, "\n");}#ifdef MODULE/*------------------------------------------------------------------*//* * Module main entry point */intinit_module(void){  int err;  /* Initialise both parts... */  err = irda_irnet_init();  if(!err)    err = ppp_irnet_init();  return err;}/*------------------------------------------------------------------*//* * Module exit */voidcleanup_module(void){  irda_irnet_cleanup();  return ppp_irnet_cleanup();}#endif /* MODULE */MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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