esp = (struct esp_old *) ((u_int8_t *) ip + (ip->ip_hl << 2)); } else esp = (struct esp_old *) (ip + 1);
}  esp = (struct esp_old *) ((u_int8_t *) ip + (ip->ip_hl << 2));
esp_old_input(struct mbuf *m, struct tdb *tdb){    struct esp_old_xdata *xd;    struct ip *ip, ipo;    u_char iv[ESP_3DES_IVS], niv[ESP_3DES_IVS], blk[ESP_3DES_BLKS], opts[40];    u_char *idat, *odat;    struct esp_old *esp;    struct ifnet *rcvif;    int ohlen, plen, ilen, olen, i, blks;    struct mbuf *mi, *mo;    xd = (struct esp_old_xdata *) tdb->tdb_xdata;    switch (xd->edx_enc_algorithm)    {	case ALG_ENC_DES:	    blks = ESP_DES_BLKS;	    break;	case ALG_ENC_3DES:	    blks = ESP_3DES_BLKS;	    break;	default:            log(LOG_ALERT,                "esp_old_input(): unsupported algorithm %d in SA %x/%08x",                xd->edx_enc_algorithm, tdb->tdb_dst, ntohl(tdb->tdb_spi));            m_freem(m);            return NULL;    }    rcvif = m->m_pkthdr.rcvif;    if (rcvif == NULL)    {#ifdef ENCDEBUG	if (encdebug)	  printf("esp_old_input(): receive interface is NULL!!!\n");#endif /* ENCDEBUG */	rcvif = &enc_softc;    }    if (m->m_len < sizeof(struct ip))    {	if ((m = m_pullup(m, sizeof(struct ip))) == NULL)	{#ifdef ENCDEBUG	    if (encdebug)	      printf("esp_old_input(): m_pullup() failed\n");#endif /* ENCDEBUG */	    espstat.esps_hdrops++;	    return NULL;	}    }    ip = mtod(m, struct ip *);    ohlen = (ip->ip_hl << 2) + ESP_OLD_FLENGTH;    /* Make sure the IP header, any IP options, and the ESP header are here */    if (m->m_len < ohlen + blks)    {	if ((m = m_pullup(m, ohlen + blks)) == NULL)	{#ifdef ENCDEBUG            if (encdebug)              printf("esp_old_input(): m_pullup() failed\n");#endif /* ENCDEBUG */            espstat.esps_hdrops++;            return NULL;	}	ip = mtod(m, struct ip *);	esp = (struct esp_old *) ((u_int8_t *) ip + (ip->ip_hl << 2));    }    else      esp = (struct esp_old *) (ip + 1);    ipo = *ip;    /* Skip the IP header, IP options, SPI and IV */    plen = m->m_pkthdr.len - (ip->ip_hl << 2) - sizeof(u_int32_t) -	   xd->edx_ivlen;    if (plen & (blks - 1))    {#ifdef ENCDEBUG	if (encdebug)	  printf("esp_old_input(): payload not a multiple of %d octets for packet from %x to %x, spi %08x\n", blks, ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi));#endif /* ENCDEBUG */	espstat.esps_badilen++;	m_freem(m);	return NULL;    }    ilen = m->m_len - (ip->ip_hl << 2) - sizeof(u_int32_t) - 4;    idat = mtod(m, unsigned char *) + (ip->ip_hl << 2) + sizeof(u_int32_t) + 4;    /* Get the IV */    iv[0] = esp->esp_iv[0];    iv[1] = esp->esp_iv[1];    iv[2] = esp->esp_iv[2];    iv[3] = esp->esp_iv[3];    if (xd->edx_ivlen == 4)		/* Half-IV */    {	iv[4] = ~esp->esp_iv[0];	iv[5] = ~esp->esp_iv[1];	iv[6] = ~esp->esp_iv[2];	iv[7] = ~esp->esp_iv[3];    }    else    {	iv[4] = esp->esp_iv[4];	iv[5] = esp->esp_iv[5];	iv[6] = esp->esp_iv[6];	iv[7] = esp->esp_iv[7];	/* Adjust the lengths accordingly */	ilen -= 4;	idat += 4;    }    olen = ilen;    odat = idat;    mi = mo = m;    i = 0;    /*     * At this point:     *   plen is # of encapsulated payload octets     *   ilen is # of octets left in this mbuf     *   idat is first encapsulated payload octed in this mbuf     *   same for olen and odat     *   iv contains the IV.     *   mi and mo point to the first mbuf     *     * From now on until the end of the mbuf chain:     *   . move the next eight octets of the chain into blk[]     *     (ilen, idat, and mi are adjusted accordingly)     *     and save it back into iv[]     *   . decrypt blk[], xor with iv[], put back into chain     *     (olen, odat, amd mo are adjusted accordingly)     *   . repeat     */    while (plen > 0)		/* while not done */    {	while (ilen == 0)	/* we exhausted previous mbuf */	{	    mi = mi->m_next;	    if (mi == NULL)	      panic("esp_old_input(): bad chain (i)\n");	    ilen = mi->m_len;	    idat = (u_char *) mi->m_data;	}	blk[i] = niv[i] = *idat++;	i++;	ilen--;	if (i == blks)	{	    switch (xd->edx_enc_algorithm)	    {		case ALG_ENC_DES:	    	    des_ecb_encrypt(blk, blk, (caddr_t) (xd->edx_eks[0]), 0);		    break;		case ALG_ENC_3DES:		    des_ecb3_encrypt(blk, blk, (caddr_t) (xd->edx_eks[2]),                             	     (caddr_t) (xd->edx_eks[1]),                             	     (caddr_t) (xd->edx_eks[0]), 0);		    break;	    }	    for (i = 0; i < blks; i++)	    {		while (olen == 0)		{		    mo = mo->m_next;		    if (mo == NULL)		      panic("esp_old_input(): bad chain (o)\n");		    olen = mo->m_len;		    odat = (u_char *) mo->m_data;		}		*odat = blk[i] ^ iv[i];		iv[i] = niv[i];		blk[i] = *odat++; /* needed elsewhere */		olen--;	    }	    i = 0;	}	plen--;    }    /* Save the options */    m_copydata(m, sizeof(struct ip), (ipo.ip_hl << 2) - sizeof(struct ip),	       (caddr_t) opts);    /*     * Now, the entire chain has been decrypted. As a side effect,     * blk[7] contains the next protocol, and blk[6] contains the     * amount of padding the original chain had. Chop off the     * appropriate parts of the chain, and return.     */    m_adj(m, -blk[6] - 2);    m_adj(m, 4 + xd->edx_ivlen);    if (m->m_len < (ipo.ip_hl << 2))    {	m = m_pullup(m, (ipo.ip_hl << 2));	if (m == NULL)	{#ifdef ENCDEBUG	    if (encdebug)	      printf("esp_old_input(): m_pullup() failed for packet from %x to %x, SA %x/%08x\n", ipo.ip_src, ipo.ip_dst, tdb->tdb_dst, ntohl(tdb->tdb_spi));#endif /* ENCDEBUG */	    return NULL;	}    }    ip = mtod(m, struct ip *);    ipo.ip_p = blk[7];    ipo.ip_id = htons(ipo.ip_id);    ipo.ip_off = 0;    ipo.ip_len += (ipo.ip_hl << 2) - sizeof(u_int32_t) - xd->edx_ivlen -		  blk[6] - 2;    ipo.ip_len = htons(ipo.ip_len);    ipo.ip_sum = 0;    *ip = ipo;    /* Copy the options back */    m_copyback(m, sizeof(struct ip), (ipo.ip_hl << 2) - sizeof(struct ip),	       (caddr_t) opts);    ip->ip_sum = in_cksum(m, (ip->ip_hl << 2));    /* Update the counters */    tdb->tdb_cur_packets++;    tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) + blk[6] + 2;    espstat.esps_ibytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) + blk[6] + 2;    /* Notify on expiration */    if (tdb->tdb_flags & TDBF_SOFT_PACKETS)      if (tdb->tdb_cur_packets >= tdb->tdb_soft_packets)      {	  encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb);	  tdb->tdb_flags &= ~TDBF_SOFT_PACKETS;      }      else	if (tdb->tdb_flags & TDBF_SOFT_BYTES)	  if (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)	  {	      encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb);	      tdb->tdb_flags &= ~TDBF_SOFT_BYTES;	  }        if (tdb->tdb_flags & TDBF_PACKETS)      if (tdb->tdb_cur_packets >= tdb->tdb_exp_packets)      {	  encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb);	  tdb_delete(tdb, 0);      }      else	if (tdb->tdb_flags & TDBF_BYTES)	  if (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)	  {	      encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb);	      tdb_delete(tdb, 0);	  }	        return m;}