| 
             /* * Transmit a packet (called by the kernel) */ int snull_tx(struct sk_buff *skb, struct net_device *dev) {  int len;  char *data;  struct snull_priv *priv = (struct snull_priv *) dev->priv;
   #ifndef LINUX_24  if (dev->tbusy || skb == NULL) {   PDEBUG("tint for %p, tbusy %ld, skb %p\n", dev, dev->tbusy, skb);   snull_tx_timeout (dev);   if (skb == NULL)    return 0;  }  #endif
   len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;  data = skb->data;  dev->trans_start = jiffies; /* save the timestamp */
   /* Remember the skb, so we can free it at interrupt time */  priv->skb = skb;
   /* actual deliver of data is device-specific, and not shown here */  snull_hw_tx(data, len, dev);
   return 0; /* Our simple device can not fail */ }
  /* * Transmit a packet (low level interface) */ void snull_hw_tx(char *buf, int len, struct net_device *dev) {  /*  * This function deals with hw details. This interface loops  * back the packet to the other snull interface (if any).  * In other words, this function implements the snull behaviour,  * while all other procedures are rather device-independent  */  struct iphdr *ih;  struct net_device *dest;  struct snull_priv *priv;  u32 *saddr, *daddr;
   /* I am paranoid. Ain't I? */  if (len < sizeof(struct ethhdr) + sizeof(struct iphdr)) {   printk("snull: Hmm... packet too short (%i octets)\n",len);   return;  }
   if (0) { /* enable this conditional to look at the data */   int i;   PDEBUG("len is %i\n" KERN_DEBUG "data:",len);   for (i=14 ; i<len; i++)    printk(" %02x",buf[i]&0xff);    printk("\n");  } 
             |