From 6e79d83bde76cc1e88a4d6bf487189769ef11465 Mon Sep 17 00:00:00 2001 From: Niels Provos Date: Tue, 24 Jun 1997 12:15:28 +0000 Subject: handle IP options in AH + allow IP options in outgoing encapsulated packets + usage counters for later use with keymanagement processes --- sys/netinet/ip_esp3desmd5.c | 81 ++++++++++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 26 deletions(-) (limited to 'sys/netinet/ip_esp3desmd5.c') diff --git a/sys/netinet/ip_esp3desmd5.c b/sys/netinet/ip_esp3desmd5.c index 749ca56b7fe..45b4153be6b 100644 --- a/sys/netinet/ip_esp3desmd5.c +++ b/sys/netinet/ip_esp3desmd5.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_esp3desmd5.c,v 1.7 1997/06/21 00:09:17 deraadt Exp $ */ +/* $OpenBSD: ip_esp3desmd5.c,v 1.8 1997/06/24 12:15:23 provos Exp $ */ /* * The author of this code is John Ioannidis, ji@tla.org, @@ -508,6 +508,11 @@ esp3desmd5_input(struct mbuf *m, struct tdb *tdb) *ip = ipo; ip->ip_sum = in_cksum(m, sizeof (struct ip)); + /* Update the counters */ + tdb->tdb_packets++; + tdb->tdb_bytes += NTOHS(ip->ip_len) - (ip->ip_hl << 2) + padsize + + 2 + ESP3DESMD5_ALEN; + return m; } @@ -521,9 +526,10 @@ esp3desmd5_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, st u_int32_t spi; struct mbuf *mi, *mo, *ms; u_char *pad, *idat, *odat; - u_char iv[ESP3DESMD5_IVS], blk[8], auth[ESP3DESMD5_ALEN]; + u_char iv[ESP3DESMD5_IVS], blk[8], auth[ESP3DESMD5_ALEN], opts[40]; MD5_CTX ctx; - + int iphlen; + espstat.esps_output++; m = m_pullup(m, sizeof (struct ip)); /* Get IP header in one mbuf */ if (m == NULL) @@ -531,7 +537,25 @@ esp3desmd5_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, st ip = mtod(m, struct ip *); spi = tdb->tdb_spi; - + iphlen = ip->ip_hl << 2; + + /* + * If options are present, pullup the IP header, the options + * and one DES block (8 bytes) of data. + */ + if (iphlen != sizeof(struct ip)) + { + m = m_pullup(m, iphlen + 8); + if (m == NULL) + return ENOBUFS; + + ip = mtod(m, struct ip *); + + /* Keep the options */ + bcopy(mtod(m, u_char *) + sizeof(struct ip), opts, + iphlen - sizeof(struct ip)); + } + xd = (struct esp3desmd5_xdata *)tdb->tdb_xdata; ilen = ntohs(ip->ip_len); /* Size of the packet */ ohlen = sizeof (u_int32_t) + xd->edx_ivlen; /* size of plaintext ESP */ @@ -555,7 +579,7 @@ esp3desmd5_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, st #endif /* Raw payload length */ - rlen = ESP3DESMD5_RPLENGTH + ilen - sizeof (struct ip); + rlen = ESP3DESMD5_RPLENGTH + ilen - iphlen; padding = ((8 - ((rlen + 2) % 8)) % 8) + 2; @@ -598,8 +622,7 @@ esp3desmd5_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, st printf("esp3desmd5_output: MD5'ing %d bytes\n", mi->m_len); #endif if (mi == m) - MD5Update(&ctx, (u_char *)mi->m_data + sizeof(struct ip), - mi->m_len - sizeof(struct ip)); + MD5Update(&ctx, (u_char *)mi->m_data + iphlen, mi->m_len - iphlen); else MD5Update(&ctx, (u_char *)mi->m_data, mi->m_len); mi = mi->m_next; @@ -615,35 +638,33 @@ esp3desmd5_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, st * here we construct the whole packet before starting encrypting. */ - m = m_pullup(m, sizeof(struct ip) + ESP3DESMD5_RPLENGTH + + m = m_pullup(m, iphlen + ESP3DESMD5_RPLENGTH + sizeof(u_int32_t) + xd->edx_ivlen); if (m == NULL) return ENOBUFS; /* Copy data if necessary */ - if (m->m_len - sizeof(struct ip)) + if (m->m_len - iphlen) { #ifdef ENCDEBUG if (encdebug) printf("esp3desmd5_output: pushing data\n"); #endif - ms = m_copym(m, sizeof(struct ip), m->m_len - sizeof(struct ip), - M_DONTWAIT); + ms = m_copym(m, iphlen, m->m_len - iphlen, M_DONTWAIT); if (ms == NULL) return ENOBUFS; ms->m_next = m->m_next; m->m_next = ms; - m->m_len = sizeof(struct ip); + m->m_len = iphlen; } /* Copy SPI, IV (or not) and replay counter */ - bcopy((caddr_t)&spi, mtod(m, caddr_t) + sizeof (struct ip), - sizeof (u_int32_t)); - bcopy((caddr_t)iv, mtod(m, caddr_t) + sizeof (struct ip) + - sizeof (u_int32_t), xd->edx_ivlen); - bcopy((caddr_t)&rplc, mtod(m, caddr_t) + sizeof(struct ip) + - sizeof(u_int32_t) + xd->edx_ivlen, ESP3DESMD5_RPLENGTH); + bcopy((caddr_t)&spi, mtod(m, caddr_t) + iphlen, sizeof (u_int32_t)); + bcopy((caddr_t)iv, mtod(m, caddr_t) + iphlen + sizeof (u_int32_t), + xd->edx_ivlen); + bcopy((caddr_t)&rplc, mtod(m, caddr_t) + iphlen + sizeof(u_int32_t) + + xd->edx_ivlen, ESP3DESMD5_RPLENGTH); #ifdef ENCDEBUG if (encdebug) @@ -677,10 +698,9 @@ esp3desmd5_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, st m->m_pkthdr.len); #endif - ilen = olen = m->m_len - sizeof (struct ip) - sizeof(u_int32_t) - - xd->edx_ivlen; - idat = odat = mtod(m, u_char *) + sizeof (struct ip) + - sizeof(u_int32_t) + xd->edx_ivlen; + ilen = olen = m->m_len - iphlen - sizeof(u_int32_t) - xd->edx_ivlen; + idat = odat = mtod(m, u_char *) + iphlen + sizeof(u_int32_t) + + xd->edx_ivlen; i = 0; mi = mo = m; @@ -711,7 +731,7 @@ esp3desmd5_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, st des_ecb3_encrypt(blk, blk, (caddr_t)(xd->edx_eks[0]), (caddr_t)(xd->edx_eks[1]), (caddr_t)(xd->edx_eks[2]), 1); - for (i=0; i<8; i++) + for (i = 0; i < 8; i++) { while (olen == 0) { @@ -740,11 +760,20 @@ esp3desmd5_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, st bcopy(iv, xd->edx_iv, ESP3DESMD5_IVS); /* New IV */ /* Fix the length and the next protocol, copy back and off we go */ - ipo.ip_len = htons(sizeof (struct ip) + ohlen + rlen + padding + - ESP3DESMD5_ALEN); + ipo.ip_len = htons(iphlen + ohlen + rlen + padding + ESP3DESMD5_ALEN); ipo.ip_p = IPPROTO_ESP; bcopy((caddr_t)&ipo, mtod(m, caddr_t), sizeof(struct ip)); - + + /* Copy back the options, if existing */ + if (iphlen != sizeof(struct ip)) + bcopy(opts, mtod(m, caddr_t) + sizeof(struct ip), + iphlen - sizeof(struct ip)); + *mp = m; + + /* Update the counters */ + tdb->tdb_packets++; + tdb->tdb_bytes += rlen + padding; + return 0; } -- cgit v1.2.3