summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/net/encap.c668
-rw-r--r--sys/net/encap.h196
-rw-r--r--sys/netinet/ip_ah.c17
-rw-r--r--sys/netinet/ip_ah.h3
-rw-r--r--sys/netinet/ip_ahhmacmd5.c28
-rw-r--r--sys/netinet/ip_ahhmacsha1.c24
-rw-r--r--sys/netinet/ip_ahmd5.c26
-rw-r--r--sys/netinet/ip_ahsha1.c22
-rw-r--r--sys/netinet/ip_esp.c18
-rw-r--r--sys/netinet/ip_esp.h26
-rw-r--r--sys/netinet/ip_esp3des.c10
-rw-r--r--sys/netinet/ip_esp3desmd5.c12
-rw-r--r--sys/netinet/ip_espdes.c10
-rw-r--r--sys/netinet/ip_espdesmd5.c12
-rw-r--r--sys/netinet/ip_ip4.c6
-rw-r--r--sys/netinet/ip_ip4.h14
-rw-r--r--sys/netinet/ip_ipsp.c61
-rw-r--r--sys/netinet/ip_ipsp.h33
-rw-r--r--sys/netinet/ip_output.c41
19 files changed, 772 insertions, 455 deletions
diff --git a/sys/net/encap.c b/sys/net/encap.c
index acd9a4e179c..898ff599dcf 100644
--- a/sys/net/encap.c
+++ b/sys/net/encap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: encap.c,v 1.4 1997/06/17 23:25:53 deraadt Exp $ */
+/* $OpenBSD: encap.c,v 1.5 1997/06/25 07:53:19 provos Exp $ */
/*
* The author of this code is John Ioannidis, ji@tla.org,
@@ -62,65 +62,65 @@ struct sockaddr encap_src = { 2, PF_ENCAP, };
struct sockproto encap_proto = { PF_ENCAP, };
struct protosw encapsw[] = {
-{ SOCK_RAW, &encapdomain, 0, PR_ATOMIC|PR_ADDR,
- raw_input, encap_output, raw_ctlinput, 0,
- encap_usrreq,
- encap_init, 0, 0, 0,
-},
+ { SOCK_RAW, &encapdomain, 0, PR_ATOMIC|PR_ADDR,
+ raw_input, encap_output, raw_ctlinput, 0,
+ encap_usrreq,
+ encap_init, 0, 0, 0,
+ },
};
struct domain encapdomain =
- { AF_ENCAP, "encapsulation", 0, 0, 0,
- encapsw, &encapsw[sizeof(encapsw)/sizeof(encapsw[0])], 0,
- rn_inithead, 16, sizeof(struct sockaddr_encap)};
+{ AF_ENCAP, "encapsulation", 0, 0, 0,
+ encapsw, &encapsw[sizeof(encapsw)/sizeof(encapsw[0])], 0,
+ rn_inithead, 16, sizeof(struct sockaddr_encap)};
void
encap_init()
{
- struct xformsw *xsp;
-
- for (xsp = xformsw; xsp < xformswNXFORMSW; xsp++)
- {
- printf("encap_init: attaching <%s>\n", xsp->xf_name);
- (*(xsp->xf_attach))();
- }
+ struct xformsw *xsp;
+
+ for (xsp = xformsw; xsp < xformswNXFORMSW; xsp++)
+ {
+ printf("encap_init: attaching <%s>\n", xsp->xf_name);
+ (*(xsp->xf_attach))();
+ }
}
/*ARGSUSED*/
int
encap_usrreq(register struct socket *so, int req, struct mbuf *m, struct mbuf *nam, struct mbuf *control)
{
- register int error = 0;
- register struct rawcb *rp = sotorawcb(so);
- int s;
-
- if (req == PRU_ATTACH)
- {
- MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK);
- if ((so->so_pcb = (caddr_t)rp))
- bzero(so->so_pcb, sizeof(*rp));
-
- }
- s = splnet();
- error = raw_usrreq(so, req, m, nam, control);
- rp = sotorawcb(so);
- if ((req == PRU_ATTACH) && rp)
+ register int error = 0;
+ register struct rawcb *rp = sotorawcb(so);
+ int s;
+
+ if (req == PRU_ATTACH)
+ {
+ MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK);
+ if ((so->so_pcb = (caddr_t)rp))
+ bzero(so->so_pcb, sizeof(*rp));
+ }
+
+ s = splnet();
+ error = raw_usrreq(so, req, m, nam, control);
+ rp = sotorawcb(so);
+ if ((req == PRU_ATTACH) && rp)
+ {
+ /* int af = rp->rcb_proto.sp_protocol; */
+
+ if (error)
{
- /* int af = rp->rcb_proto.sp_protocol; */
-
- if (error)
- {
- free((caddr_t)rp, M_PCB);
- splx(s);
- return error;
- }
- rp->rcb_faddr = &encap_src;
- soisconnected(so);
- so->so_options |= SO_USELOOPBACK;
+ free((caddr_t)rp, M_PCB);
+ splx(s);
+ return error;
}
- splx(s);
- return error;
+ rp->rcb_faddr = &encap_src;
+ soisconnected(so);
+ so->so_options |= SO_USELOOPBACK;
+ }
+ splx(s);
+ return error;
}
int
@@ -128,264 +128,376 @@ int
encap_output(struct mbuf *m, ...)
#else
encap_output(m, va_alist)
- register struct mbuf *m;
- va_dcl
+register struct mbuf *m;
+va_dcl
#endif
{
#define SENDERR(e) do { error = e; goto flush;} while (0)
- struct socket *so;
- int len, emlen, error = 0, nspis, i;
- struct encap_msghdr *emp;
- struct ifnet *ifp;
- struct ifaddr *ifa;
- struct sockaddr_encap *sen, *sen2;
- struct sockaddr_in *sin;
- struct tdb *tdbp, *tprev;
- va_list ap;
-
- va_start(ap, m);
- so = va_arg(ap, struct socket *);
- va_end(ap);
-
- if ((m == 0) || ((m->m_len < sizeof(int32_t)) &&
- (m = m_pullup(m, sizeof(int32_t))) == 0))
- return ENOBUFS;
-
- if ((m->m_flags & M_PKTHDR) == 0)
- panic("encap_output");
-
- len = m->m_pkthdr.len;
- emp = mtod(m, struct encap_msghdr *);
- emlen = emp->em_msglen;
- if ((len < emlen))
- SENDERR(EINVAL);
-
- if (m->m_len < emlen)
- {
- m = m_pullup(m, emlen);
- if (m == NULL)
- SENDERR(ENOBUFS);
+ struct socket *so;
+ int len, emlen, error = 0, nspis, i;
+ struct encap_msghdr *emp;
+ struct ifnet *ifp;
+ struct ifaddr *ifa;
+ struct sockaddr_encap *sen, *sen2;
+ struct sockaddr_in *sin;
+ struct tdb *tdbp, *tprev;
+ va_list ap;
+ u_int32_t spi;
+
+ va_start(ap, m);
+ so = va_arg(ap, struct socket *);
+ va_end(ap);
+
+ if ((m == 0) || ((m->m_len < sizeof(int32_t)) &&
+ (m = m_pullup(m, sizeof(int32_t))) == 0))
+ return ENOBUFS;
+
+ if ((m->m_flags & M_PKTHDR) == 0)
+ panic("encap_output");
+
+ len = m->m_pkthdr.len;
+ emp = mtod(m, struct encap_msghdr *);
+ emlen = emp->em_msglen;
+ if ((len < emlen))
+ SENDERR(EINVAL);
+
+ if (m->m_len < emlen)
+ {
+ m = m_pullup(m, emlen);
+ if (m == NULL)
+ SENDERR(ENOBUFS);
- emp = mtod(m, struct encap_msghdr *);
- }
+ emp = mtod(m, struct encap_msghdr *);
+ }
- switch (emp->em_type)
- {
- case EMT_IFADDR:
- if (emp->em_ifn >= nencap)
- SENDERR(ENODEV);
- /*
- * Set the default source address for an encap interface
- */
-
- ifp = &(enc_softc[emp->em_ifn].enc_if);
+ switch (emp->em_type)
+ {
+ case EMT_IFADDR:
+ if (emp->em_ifn >= nencap)
+ SENDERR(ENODEV);
+
+ /*
+ * Set the default source address for an encap interface
+ */
+
+ ifp = &(enc_softc[emp->em_ifn].enc_if);
- if ((ifp->if_addrlist.tqh_first == NULL) ||
- (ifp->if_addrlist.tqh_first->ifa_addr == NULL) ||
- (ifp->if_addrlist.tqh_first->ifa_addr->sa_family != AF_ENCAP))
- {
- MALLOC(ifa, struct ifaddr *, sizeof (struct ifaddr) + 2*SENT_DEFIF_LEN, M_IFADDR, M_WAITOK);
- if (ifa == NULL)
- SENDERR(ENOBUFS);
- bzero((caddr_t)ifa, sizeof (struct ifaddr) + 2*SENT_DEFIF_LEN);
- sen = (struct sockaddr_encap *)(ifa + 1);
- sen2 = (struct sockaddr_encap *)((caddr_t)sen + SENT_DEFIF_LEN);
- ifa->ifa_addr = (struct sockaddr *)sen;
- ifa->ifa_dstaddr = (struct sockaddr *)sen2;
- ifa->ifa_ifp = ifp;
- TAILQ_INSERT_HEAD(&(ifp->if_addrlist), ifa, ifa_list);
- }
- else
- {
- sen = (struct sockaddr_encap *)((&(ifp->if_addrlist))->tqh_first->ifa_addr);
- sen2 = (struct sockaddr_encap *)((&(ifp->if_addrlist))->tqh_first->ifa_dstaddr);
- }
-
- sen->sen_family = AF_ENCAP;
- sen->sen_len = SENT_DEFIF_LEN;
- sen->sen_type = SENT_DEFIF;
- sin = (struct sockaddr_in *) &(sen->sen_dfl);
- sin->sin_len = sizeof(*sin);
- sin->sin_family = AF_INET;
- sin->sin_addr = emp->em_ifa;
-
- *sen2 = *sen;
+ if ((ifp->if_addrlist.tqh_first == NULL) ||
+ (ifp->if_addrlist.tqh_first->ifa_addr == NULL) ||
+ (ifp->if_addrlist.tqh_first->ifa_addr->sa_family != AF_ENCAP))
+ {
+ MALLOC(ifa, struct ifaddr *, sizeof (struct ifaddr) +
+ 2 * SENT_DEFIF_LEN, M_IFADDR, M_WAITOK);
+ if (ifa == NULL)
+ SENDERR(ENOBUFS);
- break;
+ bzero((caddr_t)ifa, sizeof (struct ifaddr) +
+ 2 * SENT_DEFIF_LEN);
+ sen = (struct sockaddr_encap *)(ifa + 1);
+ sen2 = (struct sockaddr_encap *)((caddr_t)sen +
+ SENT_DEFIF_LEN);
+ ifa->ifa_addr = (struct sockaddr *)sen;
+ ifa->ifa_dstaddr = (struct sockaddr *)sen2;
+ ifa->ifa_ifp = ifp;
+ TAILQ_INSERT_HEAD(&(ifp->if_addrlist), ifa, ifa_list);
+ }
+ else
+ {
+ sen = (struct sockaddr_encap *)((&(ifp->if_addrlist))->tqh_first->ifa_addr);
+ sen2 = (struct sockaddr_encap *)((&(ifp->if_addrlist))->tqh_first->ifa_dstaddr);
+ }
+
+ sen->sen_family = AF_ENCAP;
+ sen->sen_len = SENT_DEFIF_LEN;
+ sen->sen_type = SENT_DEFIF;
+ sin = (struct sockaddr_in *) &(sen->sen_dfl);
+ sin->sin_len = sizeof(*sin);
+ sin->sin_family = AF_INET;
+ sin->sin_addr = emp->em_ifa;
+
+ *sen2 = *sen;
+
+ break;
- case EMT_SETSPI:
- if (emp->em_if >= nencap)
- SENDERR(ENODEV);
- tdbp = gettdb(emp->em_spi, emp->em_dst);
+ case EMT_SETSPI:
+ if (emp->em_if >= nencap)
+ SENDERR(ENODEV);
+ tdbp = gettdb(emp->em_spi, emp->em_dst);
+ if (tdbp == NULL)
+ {
+ MALLOC(tdbp, struct tdb *, sizeof (*tdbp), M_TDB, M_WAITOK);
if (tdbp == NULL)
- {
- MALLOC(tdbp, struct tdb *, sizeof (*tdbp), M_TDB, M_WAITOK);
- if (tdbp == NULL)
- SENDERR(ENOBUFS);
-
- bzero((caddr_t)tdbp, sizeof(*tdbp));
-
- tdbp->tdb_spi = emp->em_spi;
- tdbp->tdb_dst = emp->em_dst;
- tdbp->tdb_rcvif = &(enc_softc[emp->em_if].enc_if);
- puttdb(tdbp);
- }
- else
- (*tdbp->tdb_xform->xf_zeroize)(tdbp);
-
- error = tdb_init(tdbp, m);
- ipspkernfs_dirty = 1;
- break;
+ SENDERR(ENOBUFS);
- case EMT_DELSPI:
- if (emp->em_if >= nencap)
- SENDERR(ENODEV);
- tdbp = gettdb(emp->em_spi, emp->em_dst);
- if (tdbp == NULL)
- {
- error = EINVAL;
- break;
- }
-
- if (emp->em_alg != tdbp->tdb_xform->xf_type)
- {
- error = EINVAL;
- break;
- }
-
- error = tdb_delete(tdbp, 0);
+ bzero((caddr_t)tdbp, sizeof(*tdbp));
+
+ tdbp->tdb_spi = emp->em_spi;
+ tdbp->tdb_dst = emp->em_dst;
+ tdbp->tdb_rcvif = &(enc_softc[emp->em_if].enc_if);
+
+ puttdb(tdbp);
+ }
+ else
+ (*tdbp->tdb_xform->xf_zeroize)(tdbp);
+
+ /* Various timers/counters */
+ if (emp->em_relative_hard != 0)
+ {
+ tdbp->tdb_exp_relative = emp->em_relative_hard;
+ tdbp->tdb_flags |= TDBF_RELATIVE;
+ }
+
+ if (emp->em_relative_soft != 0)
+ {
+ tdbp->tdb_soft_relative = emp->em_relative_soft;
+ tdbp->tdb_flags |= TDBF_SOFT_RELATIVE;
+ }
+
+ if (emp->em_first_use_hard != 0)
+ {
+ tdbp->tdb_exp_first_use = emp->em_first_use_hard;
+ tdbp->tdb_flags |= TDBF_FIRSTUSE;
+ }
+
+ if (emp->em_first_use_soft != 0)
+ {
+ tdbp->tdb_soft_first_use = emp->em_first_use_soft;
+ tdbp->tdb_flags |= TDBF_SOFT_FIRSTUSE;
+ }
+
+ if (emp->em_expire_hard != 0)
+ {
+ tdbp->tdb_exp_timeout = emp->em_expire_hard;
+ tdbp->tdb_flags |= TDBF_TIMER;
+ }
+
+ if (emp->em_expire_soft != 0)
+ {
+ tdbp->tdb_soft_timeout = emp->em_expire_soft;
+ tdbp->tdb_flags |= TDBF_SOFT_TIMER;
+ }
+
+ if (emp->em_bytes_hard != 0)
+ {
+ tdbp->tdb_exp_bytes = emp->em_bytes_hard;
+ tdbp->tdb_flags |= TDBF_BYTES;
+ }
+
+ if (emp->em_bytes_soft != 0)
+ {
+ tdbp->tdb_soft_bytes = emp->em_bytes_soft;
+ tdbp->tdb_flags |= TDBF_SOFT_BYTES;
+ }
+
+ if (emp->em_packets_hard != 0)
+ {
+ tdbp->tdb_exp_packets = emp->em_packets_hard;
+ tdbp->tdb_flags |= TDBF_PACKETS;
+ }
+
+ if (emp->em_packets_soft != 0)
+ {
+ tdbp->tdb_soft_packets = emp->em_packets_soft;
+ tdbp->tdb_flags |= TDBF_SOFT_PACKETS;
+ }
+
+ error = tdb_init(tdbp, m);
+ ipspkernfs_dirty = 1;
+ break;
+
+ case EMT_DELSPI:
+ if (emp->em_if >= nencap)
+ SENDERR(ENODEV);
+ tdbp = gettdb(emp->em_spi, emp->em_dst);
+ if (tdbp == NULL)
+ {
+ error = EINVAL;
break;
+ }
- case EMT_DELSPICHAIN:
- if (emp->em_if >= nencap)
- SENDERR(ENODEV);
- tdbp = gettdb(emp->em_spi, emp->em_dst);
- if (tdbp == NULL)
- {
- error = EINVAL;
- break;
- }
-
- if (emp->em_alg != tdbp->tdb_xform->xf_type)
- {
- error = EINVAL;
- break;
- }
-
- error = tdb_delete(tdbp, 1);
- break;
-
- case EMT_GRPSPIS:
- nspis = (emlen - 4) / 12;
- if (nspis * 12 + 4 != emlen)
- SENDERR(EINVAL);
-
- for (i = 0; i < nspis; i++)
- if ((tdbp = gettdb(emp->em_rel[i].emr_spi, emp->em_rel[i].emr_dst)) == NULL)
- SENDERR(ENOENT);
- else
- emp->em_rel[i].emr_tdb = tdbp;
- tprev = emp->em_rel[0].emr_tdb;
- tprev->tdb_inext = NULL;
- for (i = 1; i < nspis; i++)
- {
- tdbp = emp->em_rel[i].emr_tdb;
- tprev->tdb_onext = tdbp;
- tdbp->tdb_inext = tprev;
- tprev = tdbp;
- }
- tprev->tdb_onext = NULL;
- ipspkernfs_dirty = 1;
- error = 0;
+ if (emp->em_alg != tdbp->tdb_xform->xf_type)
+ {
+ error = EINVAL;
break;
+ }
+
+ error = tdb_delete(tdbp, 0);
+ break;
+
+ case EMT_DELSPICHAIN:
+ if (emp->em_if >= nencap)
+ SENDERR(ENODEV);
+ tdbp = gettdb(emp->em_spi, emp->em_dst);
+ if (tdbp == NULL)
+ {
+ error = EINVAL;
+ break;
+ }
- default:
+ if (emp->em_alg != tdbp->tdb_xform->xf_type)
+ {
+ error = EINVAL;
+ break;
+ }
+
+ error = tdb_delete(tdbp, 1);
+ break;
+
+ case EMT_GRPSPIS:
+ nspis = (emlen - 4) / 12;
+ if (nspis * 12 + 4 != emlen)
+ SENDERR(EINVAL);
+
+ for (i = 0; i < nspis; i++)
+ if ((tdbp = gettdb(emp->em_rel[i].emr_spi, emp->em_rel[i].emr_dst)) == NULL)
+ SENDERR(ENOENT);
+ else
+ emp->em_rel[i].emr_tdb = tdbp;
+
+ tprev = emp->em_rel[0].emr_tdb;
+ tprev->tdb_inext = NULL;
+ for (i = 1; i < nspis; i++)
+ {
+ tdbp = emp->em_rel[i].emr_tdb;
+ tprev->tdb_onext = tdbp;
+ tdbp->tdb_inext = tprev;
+ tprev = tdbp;
+ }
+ tprev->tdb_onext = NULL;
+ ipspkernfs_dirty = 1;
+ error = 0;
+ break;
+
+ case EMT_RESERVESPI:
+ spi = reserve_spi(emp->em_spi, emp->em_dst);
+ if (spi == 0)
+ if (emp->em_spi == 0)
+ SENDERR(ENOBUFS);
+ else
SENDERR(EINVAL);
- }
-
- return error;
- flush:
- if (m)
- m_freem(m);
- return error;
+ emp->em_spi = spi;
+
+ /* Send it back to us */
+ if (sbappendaddr(&so->so_rcv, &encap_src, m,
+ (struct mbuf *)0) == 0)
+ SENDERR(ENOBUFS);
+ else
+ sorwakeup(so); /* wakeup */
+
+ error = 0;
+
+ break;
+
+ case EMT_ENABLESPI:
+ tdbp = gettdb(emp->em_spi, emp->em_dst);
+ if (tdbp == NULL)
+ SENDERR(ENOENT);
+
+ /* Clear the INVALID flag */
+ tdbp->tdb_flags &= (~TDBF_INVALID);
+ error = 0;
+
+ break;
+
+ case EMT_DISABLESPI:
+ tdbp = gettdb(emp->em_spi, emp->em_dst);
+ if (tdbp == NULL)
+ SENDERR(ENOENT);
+
+ /* Set the INVALID flag */
+ tdbp->tdb_flags |= TDBF_INVALID;
+ error = 0;
+
+ break;
+
+ default:
+ SENDERR(EINVAL);
+ }
+
+ return error;
+
+flush:
+ if (m)
+ m_freem(m);
+ return error;
}
struct ifaddr *
encap_findgwifa(struct sockaddr *gw)
{
- struct sockaddr_encap *egw = (struct sockaddr_encap *)gw;
- u_char *op = (u_char *)gw;
- int i, j;
- struct ifaddr *retval = loif.if_addrlist.tqh_first;
- union
- {
- struct in_addr ia;
- u_char io[4];
- } iao;
+ struct sockaddr_encap *egw = (struct sockaddr_encap *)gw;
+ u_char *op = (u_char *)gw;
+ int i, j;
+ struct ifaddr *retval = loif.if_addrlist.tqh_first;
+ union
+ {
+ struct in_addr ia;
+ u_char io[4];
+ } iao;
- switch (egw->sen_type)
- {
- case SENT_IPSP:
- return enc_softc[egw->sen_ipsp_ifn].enc_if.if_addrlist.tqh_first;
- break;
-
- case SENT_IP4:
- /*
- * Pretty-much standard options walking code.
- * Repeated elsewhere as necessary
- */
-
- for (i = SENT_IP4_LEN; i < egw->sen_len;)
- switch (op[i])
- {
- case SENO_EOL:
- goto opt_done;
-
- case SENO_NOP:
- i++;
- continue;
+ switch (egw->sen_type)
+ {
+ case SENT_IPSP:
+ return enc_softc[egw->sen_ipsp_ifn].enc_if.if_addrlist.tqh_first;
+ break;
+
+ case SENT_IP4:
+ /*
+ * Pretty-much standard options walking code.
+ * Repeated elsewhere as necessary
+ */
+
+ for (i = SENT_IP4_LEN; i < egw->sen_len;)
+ switch (op[i])
+ {
+ case SENO_EOL:
+ goto opt_done;
+
+ case SENO_NOP:
+ i++;
+ continue;
+
+ case SENO_IFN:
+ if (op[i+1] != 3)
+ {
+ return NULL;
+ }
+ retval = enc_softc[op[i+2]].enc_if.if_addrlist.tqh_first;
+ goto opt_done;
+
+ case SENO_IFIP4A:
+ if (op[i+1] != 6) /* XXX -- IPv4 address */
+ {
+ return NULL;
+ }
+ iao.io[0] = op[i+2];
+ iao.io[1] = op[i+3];
+ iao.io[2] = op[i+4];
+ iao.io[3] = op[i+5];
+
+ for (j = 0; j < nencap; j++)
+ {
+ struct ifaddr *ia = (struct ifaddr *)enc_softc[j].enc_if.if_addrlist.tqh_first;
- case SENO_IFN:
- if (op[i+1] != 3)
- {
- return NULL;
- }
- retval = enc_softc[op[i+2]].enc_if.if_addrlist.tqh_first;
- goto opt_done;
+ struct sockaddr_in *si = (struct sockaddr_in *)ia->ifa_addr;
- case SENO_IFIP4A:
- if (op[i+1] != 6) /* XXX -- IPv4 address */
+ if ((si->sin_family == AF_INET) && (si->sin_addr.s_addr == iao.ia.s_addr))
{
- return NULL;
+ retval = ia;
+ goto opt_done;
}
- iao.io[0] = op[i+2];
- iao.io[1] = op[i+3];
- iao.io[2] = op[i+4];
- iao.io[3] = op[i+5];
-
- for (j = 0; j < nencap; j++)
- {
- struct ifaddr *ia = (struct ifaddr *)enc_softc[j].enc_if.if_addrlist.tqh_first;
-
- struct sockaddr_in *si = (struct sockaddr_in *)ia->ifa_addr;
-
- if ((si->sin_family == AF_INET) && (si->sin_addr.s_addr == iao.ia.s_addr))
- {
- retval = ia;
- goto opt_done;
- }
- }
- i += 6;
- break;
-
- default:
- if (op[i+1] == 0)
- return NULL;
- i += op[i+i];
- }
- opt_done:
- break;
- }
- return retval;
+ }
+ i += 6;
+ break;
+
+ default:
+ if (op[i+1] == 0)
+ return NULL;
+ i += op[i+i];
+ }
+ opt_done:
+ break;
+ }
+ return retval;
}
diff --git a/sys/net/encap.h b/sys/net/encap.h
index 328d29eabe7..d5b28c8a942 100644
--- a/sys/net/encap.h
+++ b/sys/net/encap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: encap.h,v 1.3 1997/06/17 23:25:54 deraadt Exp $ */
+/* $OpenBSD: encap.h,v 1.4 1997/06/25 07:53:20 provos Exp $ */
/*
* The author of this code is John Ioannidis, ji@tla.org,
@@ -49,43 +49,44 @@
struct sockaddr_encap
{
- u_int8_t sen_len; /* length */
- u_int8_t sen_family; /* AF_ENCAP */
- u_int16_t sen_type; /* see SENT_* */
- union
+ u_int8_t sen_len; /* length */
+ u_int8_t sen_family; /* AF_ENCAP */
+ u_int16_t sen_type; /* see SENT_* */
+ union
+ {
+ u_int8_t Data[16]; /* other stuff mapped here */
+ struct sockaddr Dfl; /* SENT_DEFIF */
+ struct /* SENT_SA */
{
- u_int8_t Data[16]; /* other stuff mapped here */
- struct sockaddr Dfl; /* SENT_DEFIF */
- struct /* SENT_SA */
- {
- struct sockaddr Src;
- struct sockaddr Dst;
- } Sa;
+ struct sockaddr Src;
+ struct sockaddr Dst;
+ } Sa;
#ifdef INET
- struct /* SENT_SAIN */
- {
- struct sockaddr_in Src;
- struct sockaddr_in Dst;
- } Sin;
- struct /* SENT_IP4 */
- {
- struct in_addr Src;
- struct in_addr Dst;
- u_int16_t Sport;
- u_int16_t Dport;
- u_int8_t Proto;
- u_int8_t Filler[3];
- } Sip4;
- struct /* SENT_IPSP */
- {
- struct in_addr Src;
- struct in_addr Dst;
- u_int32_t Spi;
- u_int8_t Ifn;
- u_int8_t Filler[3];
- } Sipsp;
+ struct /* SENT_SAIN */
+ {
+ struct sockaddr_in Src;
+ struct sockaddr_in Dst;
+ } Sin;
+ struct /* SENT_IP4 */
+ {
+ struct in_addr Src;
+ struct in_addr Dst;
+ u_int16_t Sport;
+ u_int16_t Dport;
+ u_int8_t Proto;
+ u_int8_t Filler[3];
+ } Sip4;
+ struct /* SENT_IPSP */
+ {
+ struct in_addr Src;
+ struct in_addr Dst;
+ u_int32_t Spi;
+ u_int8_t Ifn;
+ u_int8_t Filler[3];
+ } Sipsp;
+
#endif
- } Sen;
+ } Sen;
};
#define sen_data Sen.Data
@@ -170,37 +171,92 @@ struct enc_softc
struct encap_msghdr
{
- u_int16_t em_msglen; /* message length */
- u_int8_t em_version; /* for future expansion */
- u_int8_t em_type; /* message type */
- union
+ u_int16_t em_msglen; /* message length */
+ u_int8_t em_version; /* for future expansion */
+ u_int8_t em_type; /* message type */
+ union
+ {
+ struct
+ {
+ struct in_addr Ia;
+ u_int8_t Ifn;
+ u_int8_t xxx[3]; /* makes life a lot easier */
+ } Ifa;
+
+ struct
{
- struct
- {
- struct in_addr Ia;
- u_int8_t Ifn;
- u_int8_t xxx[3]; /* makes life a lot easier */
- } Ifa;
-
- struct
- {
- u_int32_t Spi; /* SPI */
- struct in_addr Dst; /* Destination address */
- u_int32_t If; /* enc i/f for input */
- int32_t Alg; /* Algorithm to use */
- u_int8_t Dat[1]; /* Data */
- } Xfm;
-
- struct
- {
- u_int32_t emr_spi; /* SPI */
- struct in_addr emr_dst; /* Dest */
- struct tdb * emr_tdb; /* used internally! */
-
- } Rel[EM_MAXRELSPIS];
- } Eu;
+ u_int32_t Spi; /* SPI */
+ struct in_addr Dst; /* Destination address */
+ u_int64_t Relative_Hard; /* Expire relative to creation */
+ u_int64_t Relative_Soft;
+ u_int64_t First_Use_Hard; /* Expire relative to first use */
+ u_int64_t First_Use_Soft;
+ u_int64_t Expire_Hard; /* Expire at fixed point in time */
+ u_int64_t Expire_Soft;
+ u_int64_t Bytes_Hard; /* Expire after bytes recved/sent */
+ u_int64_t Bytes_Soft;
+ u_int64_t Packets_Hard; /* Expire after packets recved/sent */
+ u_int64_t Packets_Soft;
+ u_int32_t If; /* enc i/f for input */
+ int32_t Alg; /* Algorithm to use */
+ u_int8_t Dat[1]; /* Data */
+ } Xfm;
+
+ /*
+ * For expiration notifications, the kernel fills in
+ * Notification_Type, Spi and Dst. No direct response is expected.
+ *
+ * For SA Requests, the kernel fills in
+ * Notification_Type, MsgID, Spi, Seclevel, Dst (and optionally
+ * Protocol, Src, Sport, Dport and UserID).
+ *
+ * The response should have the same values in all the fields
+ * and:
+ * Spi/Spi2/Spi3 will hold the SPIs for the three seclevels
+ * UserID can optionally hold the peer's UserID (if applicable)
+ */
+ struct /* kernel->userland notifications */
+ {
+ u_int32_t Notification_Type;
+#define NOTIFY_SOFT_EXPIRE 0 /* Soft expiration of SA */
+#define NOTIFY_HARD_EXPIRE 1 /* Hard expiration of SA */
+#define NOTIFY_REQUEST_SA 2 /* Establish an SA */
+ u_int32_t MsgID; /* Request ID */
+ u_int32_t Spi;
+ u_int32_t Spi2;
+ u_int32_t Spi3;
+ u_int8_t Seclevel[3]; /* see netinet/in_pcb.h */
+ u_int8_t Protocol; /* Transport mode for which protocol */
+ struct in_addr Dst; /* Peer */
+ struct in_addr Src; /* Might have our local address */
+ u_int16_t Sport; /* Source port */
+ u_int16_t Dport; /* Destination port */
+ u_int8_t UserID[1]; /* Might be used to indicate user */
+ } Notify;
+
+ struct
+ {
+ u_int32_t emr_spi; /* SPI */
+ struct in_addr emr_dst; /* Dest */
+ struct tdb *emr_tdb; /* used internally! */
+
+ } Rel[EM_MAXRELSPIS];
+ } Eu;
};
+#define em_not_type Eu.Notify.Notification_Type
+#define em_not_spi Eu.Notify.Spi
+#define em_not_spi2 Eu.Notify.Spi2
+#define em_not_spi3 Eu.Notify.Spi3
+#define em_not_src Eu.Notify.Src
+#define em_not_dst Eu.Notify.Dst
+#define em_not_seclevel Eu.Notify.Seclevel
+#define em_not_userid Eu.Notify.UserID
+#define em_not_msgid Eu.Notify.MsgID
+#define em_not_sport Eu.Notify.Sport
+#define em_not_dport Eu.Notify.Dport
+#define em_not_protocol Eu.Notify.Protocol
+
#define em_ifa Eu.Ifa.Ia
#define em_ifn Eu.Ifa.Ifn
@@ -209,6 +265,16 @@ struct encap_msghdr
#define em_if Eu.Xfm.If
#define em_alg Eu.Xfm.Alg
#define em_dat Eu.Xfm.Dat
+#define em_relative_hard Eu.Xfm.Relative_Hard
+#define em_relative_soft Eu.Xfm.Relative_Soft
+#define em_first_use_hard Eu.Xfm.First_Use_Hard
+#define em_first_use_soft Eu.Xfm.First_Use_Soft
+#define em_expire_hard Eu.Xfm.Expire_Hard
+#define em_expire_soft Eu.Xfm.Expire_Soft
+#define em_bytes_hard Eu.Xfm.Bytes_Hard
+#define em_bytes_soft Eu.Xfm.Bytes_Soft
+#define em_packets_hard Eu.Xfm.Packets_Hard
+#define em_packets_soft Eu.Xfm.Packets_Soft
#define em_rel Eu.Rel
@@ -217,6 +283,10 @@ struct encap_msghdr
#define EMT_GRPSPIS 3 /* Group SPIs (output order) */
#define EMT_DELSPI 4 /* delete an SPI */
#define EMT_DELSPICHAIN 5 /* delete an SPI chain starting from */
+#define EMT_RESERVESPI 6 /* Give us an SPI */
+#define EMT_ENABLESPI 7 /* Enable an SA */
+#define EMT_DISABLESPI 8 /* Disable an SA */
+#define EMT_NOTIFY 9 /* kernel->userland key mgmt not. */
#define EM_MINLEN 8 /* count!!! */
#define EMT_IFADDR_LEN 12
diff --git a/sys/netinet/ip_ah.c b/sys/netinet/ip_ah.c
index cd550282775..d012fbdeba8 100644
--- a/sys/netinet/ip_ah.c
+++ b/sys/netinet/ip_ah.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ah.c,v 1.5 1997/06/24 12:15:19 provos Exp $ */
+/* $OpenBSD: ip_ah.c,v 1.6 1997/06/25 07:53:21 provos Exp $ */
/*
* The author of this code is John Ioannidis, ji@tla.org,
@@ -123,6 +123,17 @@ ah_input(register struct mbuf *m, int iphlen)
return;
}
+ if (tdbp->tdb_flags & TDBF_INVALID)
+ {
+#ifdef ENCDEBUG
+ if (encdebug)
+ printf("ah_input: spi=%x is no longer/yet valid\n", ahp->ah_spi);
+#endif /* ENCDEBUG */
+ m_freem(m);
+ ahstat.ahs_invalid++;
+ return;
+ }
+
if (tdbp->tdb_xform == NULL)
{
#ifdef ENCDEBUG
@@ -136,6 +147,10 @@ ah_input(register struct mbuf *m, int iphlen)
m->m_pkthdr.rcvif = tdbp->tdb_rcvif;
+ /* Register first use */
+ if (tdbp->tdb_first_use == 0)
+ tdbp->tdb_first_use = time.tv_sec;
+
m = (*(tdbp->tdb_xform->xf_input))(m, tdbp);
if (m == NULL)
diff --git a/sys/netinet/ip_ah.h b/sys/netinet/ip_ah.h
index 25af64cf1a8..da9840e14e7 100644
--- a/sys/netinet/ip_ah.h
+++ b/sys/netinet/ip_ah.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ah.h,v 1.6 1997/06/20 05:41:47 provos Exp $ */
+/* $OpenBSD: ip_ah.h,v 1.7 1997/06/25 07:53:21 provos Exp $ */
/*
* The author of this code is John Ioannidis, ji@tla.org,
@@ -55,6 +55,7 @@ struct ahstat
u_int32_t ahs_badauthl; /* bad authenticator length */
u_int32_t ahs_input; /* Input AH packets */
u_int32_t ahs_output; /* Output AH packets */
+ u_int32_t ahs_invalid; /* Trying to use an invalid TDB */
};
#define AHHMACMD5_KMAX 64 /* max 512 bits key */
diff --git a/sys/netinet/ip_ahhmacmd5.c b/sys/netinet/ip_ahhmacmd5.c
index 243c5b6e408..3a3bd949caf 100644
--- a/sys/netinet/ip_ahhmacmd5.c
+++ b/sys/netinet/ip_ahhmacmd5.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ahhmacmd5.c,v 1.11 1997/06/24 20:57:24 provos Exp $ */
+/* $OpenBSD: ip_ahhmacmd5.c,v 1.12 1997/06/25 07:53:22 provos Exp $ */
/*
* The author of this code is John Ioannidis, ji@tla.org,
@@ -239,24 +239,28 @@ ahhmacmd5_input(struct mbuf *m, struct tdb *tdb)
switch (optval)
{
case IPOPT_EOL:
+ MD5Update(&ctx, ipseczeroes, 1);
+ off = ip->ip_hl << 2;
+ break;
+
case IPOPT_NOP:
MD5Update(&ctx, ipseczeroes, 1);
off++;
- continue;
-
+ break;
+
case IPOPT_SECURITY:
case 133:
case 134:
optval = ((u_int8_t *)ip)[off + 1];
MD5Update(&ctx, (u_int8_t *)ip + off, optval);
off += optval;
- continue;
-
+ break;
+
default:
optval = ((u_int8_t *)ip)[off + 1];
MD5Update(&ctx, ipseczeroes, optval);
off += optval;
- continue;
+ break;
}
}
@@ -360,8 +364,8 @@ ahhmacmd5_input(struct mbuf *m, struct tdb *tdb)
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);
+ tdb->tdb_cur_packets++;
+ tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2);
return m;
}
@@ -511,11 +515,11 @@ ahhmacmd5_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, str
*mp = m;
/* Update the counters */
- tdb->tdb_packets++;
- tdb->tdb_bytes += ip->ip_len - (ip->ip_hl << 2) - AH_FLENGTH -
- xd->amx_alen;
+ tdb->tdb_cur_packets++;
+ tdb->tdb_cur_bytes += ip->ip_len - (ip->ip_hl << 2) - AH_FLENGTH -
+ xd->amx_alen;
if (xd->amx_wnd >= 0)
- tdb->tdb_bytes -= HMACMD5_RPLENGTH;
+ tdb->tdb_cur_bytes -= HMACMD5_RPLENGTH;
return 0;
}
diff --git a/sys/netinet/ip_ahhmacsha1.c b/sys/netinet/ip_ahhmacsha1.c
index bd2003e52fe..ac9b056a010 100644
--- a/sys/netinet/ip_ahhmacsha1.c
+++ b/sys/netinet/ip_ahhmacsha1.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ahhmacsha1.c,v 1.9 1997/06/24 20:57:25 provos Exp $ */
+/* $OpenBSD: ip_ahhmacsha1.c,v 1.10 1997/06/25 07:53:22 provos Exp $ */
/*
* The author of this code is John Ioannidis, ji@tla.org,
@@ -240,10 +240,14 @@ ahhmacsha1_input(struct mbuf *m, struct tdb *tdb)
switch (optval)
{
case IPOPT_EOL:
+ SHA1Update(&ctx, ipseczeroes, 1);
+ off = ip->ip_hl << 2;
+ break;
+
case IPOPT_NOP:
SHA1Update(&ctx, ipseczeroes, 1);
off++;
- continue;
+ break;
case IPOPT_SECURITY:
case 133:
@@ -251,13 +255,13 @@ ahhmacsha1_input(struct mbuf *m, struct tdb *tdb)
optval = ((u_int8_t *)ip)[off + 1];
SHA1Update(&ctx, (u_int8_t *)ip + off, optval);
off += optval;
- continue;
+ break;
default:
optval = ((u_int8_t *)ip)[off + 1];
SHA1Update(&ctx, ipseczeroes, optval);
off += optval;
- continue;
+ break;
}
}
@@ -363,8 +367,8 @@ ahhmacsha1_input(struct mbuf *m, struct tdb *tdb)
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);
+ tdb->tdb_cur_packets++;
+ tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2);
return m;
}
@@ -516,11 +520,11 @@ ahhmacsha1_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, st
*mp = m;
/* Update the counters */
- tdb->tdb_packets++;
- tdb->tdb_bytes += ip->ip_len - (ip->ip_hl << 2) - AH_FLENGTH -
- xd->amx_alen;
+ tdb->tdb_cur_packets++;
+ tdb->tdb_cur_bytes += ip->ip_len - (ip->ip_hl << 2) - AH_FLENGTH -
+ xd->amx_alen;
if (xd->amx_wnd >= 0)
- tdb->tdb_bytes -= HMACSHA1_RPLENGTH;
+ tdb->tdb_cur_bytes -= HMACSHA1_RPLENGTH;
return 0;
}
diff --git a/sys/netinet/ip_ahmd5.c b/sys/netinet/ip_ahmd5.c
index ce3a9143220..e19b596f172 100644
--- a/sys/netinet/ip_ahmd5.c
+++ b/sys/netinet/ip_ahmd5.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ahmd5.c,v 1.8 1997/06/24 20:57:25 provos Exp $ */
+/* $OpenBSD: ip_ahmd5.c,v 1.9 1997/06/25 07:53:23 provos Exp $ */
/*
* The author of this code is John Ioannidis, ji@tla.org,
@@ -195,24 +195,28 @@ ahmd5_input(struct mbuf *m, struct tdb *tdb)
switch (optval)
{
case IPOPT_EOL:
+ MD5Update(&ctx, ipseczeroes, 1);
+ off = ip->ip_hl << 2;
+ break;
+
case IPOPT_NOP:
MD5Update(&ctx, ipseczeroes, 1);
off++;
- continue;
-
+ break;
+
case IPOPT_SECURITY:
case 133:
case 134:
optval = ((u_int8_t *)ip)[off + 1];
MD5Update(&ctx, (u_int8_t *)ip + off, optval);
off += optval;
- continue;
-
+ break;
+
default:
optval = ((u_int8_t *)ip)[off + 1];
MD5Update(&ctx, ipseczeroes, optval);
off += optval;
- continue;
+ break;
}
}
@@ -280,8 +284,8 @@ ahmd5_input(struct mbuf *m, struct tdb *tdb)
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);
+ tdb->tdb_cur_packets++;
+ tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2);
return m;
}
@@ -403,9 +407,9 @@ ahmd5_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, struct
*mp = m;
/* Update the counters */
- tdb->tdb_packets++;
- tdb->tdb_bytes += ip->ip_len - (ip->ip_hl << 2) - AH_FLENGTH -
- xd->amx_alen;
+ tdb->tdb_cur_packets++;
+ tdb->tdb_cur_bytes += ip->ip_len - (ip->ip_hl << 2) - AH_FLENGTH -
+ xd->amx_alen;
return 0;
}
diff --git a/sys/netinet/ip_ahsha1.c b/sys/netinet/ip_ahsha1.c
index b7cc04425f0..61bece49bc2 100644
--- a/sys/netinet/ip_ahsha1.c
+++ b/sys/netinet/ip_ahsha1.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ahsha1.c,v 1.4 1997/06/24 20:57:26 provos Exp $ */
+/* $OpenBSD: ip_ahsha1.c,v 1.5 1997/06/25 07:53:23 provos Exp $ */
/*
* The author of this code is John Ioannidis, ji@tla.org,
@@ -194,10 +194,14 @@ ahsha1_input(struct mbuf *m, struct tdb *tdb)
switch (IPOPT_NUMBER(optval))
{
case IPOPT_EOL:
+ SHA1Update(&ctx, ipseczeroes, 1);
+ off = ip->ip_hl << 2;
+ break;
+
case IPOPT_NOP:
SHA1Update(&ctx, ipseczeroes, 1);
off++;
- continue;
+ break;
case IPOPT_SECURITY:
case 133:
@@ -205,13 +209,13 @@ ahsha1_input(struct mbuf *m, struct tdb *tdb)
optval = ((u_int8_t *)ip)[off + 1];
SHA1Update(&ctx, (u_int8_t *)ip + off, optval);
off += optval;
- continue;
+ break;
default:
optval = ((u_int8_t *)ip)[off + 1];
SHA1Update(&ctx, ipseczeroes, optval);
off += optval;
- continue;
+ break;
}
}
@@ -279,8 +283,8 @@ ahsha1_input(struct mbuf *m, struct tdb *tdb)
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);
+ tdb->tdb_cur_packets++;
+ tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2);
return m;
}
@@ -402,9 +406,9 @@ ahsha1_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, struct
*mp = m;
/* Update the counters */
- tdb->tdb_packets++;
- tdb->tdb_bytes += ip->ip_len - (ip->ip_hl << 2) - AH_FLENGTH -
- xd->amx_alen;
+ tdb->tdb_cur_packets++;
+ tdb->tdb_cur_bytes += ip->ip_len - (ip->ip_hl << 2) - AH_FLENGTH -
+ xd->amx_alen;
return 0;
}
diff --git a/sys/netinet/ip_esp.c b/sys/netinet/ip_esp.c
index 0c76415d20c..dad0caaaa96 100644
--- a/sys/netinet/ip_esp.c
+++ b/sys/netinet/ip_esp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_esp.c,v 1.5 1997/06/21 00:09:16 deraadt Exp $ */
+/* $OpenBSD: ip_esp.c,v 1.6 1997/06/25 07:53:24 provos Exp $ */
/*
* The author of this code is John Ioannidis, ji@tla.org,
@@ -120,6 +120,17 @@ esp_input(register struct mbuf *m, int iphlen)
return;
}
+ if (tdbp->tdb_flags & TDBF_INVALID)
+ {
+#ifdef ENCDEBUG
+ if (encdebug);
+ printf("esp_input: spi=%x is not longer/yet valid\n", spi);
+#endif
+ m_freem(m);
+ espstat.esps_invalid++;
+ return;
+ }
+
if (tdbp->tdb_xform == NULL)
{
#ifdef ENCDEBUG
@@ -133,6 +144,11 @@ esp_input(register struct mbuf *m, int iphlen)
m->m_pkthdr.rcvif = tdbp->tdb_rcvif;
+ /* Register first use */
+ if (tdbp->tdb_first_use == 0)
+ tdbp->tdb_first_use = time.tv_sec;
+
+
m = (*(tdbp->tdb_xform->xf_input))(m, tdbp);
if (m == NULL)
diff --git a/sys/netinet/ip_esp.h b/sys/netinet/ip_esp.h
index 10a5b7d3aff..e7798ff8d04 100644
--- a/sys/netinet/ip_esp.h
+++ b/sys/netinet/ip_esp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_esp.h,v 1.6 1997/06/20 05:41:50 provos Exp $ */
+/* $OpenBSD: ip_esp.h,v 1.7 1997/06/25 07:53:24 provos Exp $ */
/*
* The author of this code is John Ioannidis, ji@tla.org,
@@ -72,17 +72,18 @@ struct esp
struct espstat
{
- u_long esps_hdrops; /* packet shorter than header shows */
- u_long esps_notdb;
- u_long esps_badkcr;
- u_long esps_qfull;
- u_long esps_noxform;
- u_long esps_badilen;
- u_long esps_wrap; /* Replay counter wrapped around */
- u_long esps_badauth; /* Only valid for transforms with auth */
- u_long esps_replay; /* Possible packet replay detected */
- u_long esps_input; /* Input ESP packets */
- u_long esps_output; /* Output ESP packets */
+ u_int32_t esps_hdrops; /* packet shorter than header shows */
+ u_int32_t esps_notdb;
+ u_int32_t esps_badkcr;
+ u_int32_t esps_qfull;
+ u_int32_t esps_noxform;
+ u_int32_t esps_badilen;
+ u_int32_t esps_wrap; /* Replay counter wrapped around */
+ u_int32_t esps_badauth; /* Only valid for transforms with auth */
+ u_int32_t esps_replay; /* Possible packet replay detected */
+ u_int32_t esps_input; /* Input ESP packets */
+ u_int32_t esps_output; /* Output ESP packets */
+ u_int32_t esps_invalid; /* Trying to use an invalid TDB */
};
struct espdes_xdata
@@ -202,4 +203,3 @@ struct esp3desmd5_xdata
struct espstat espstat;
#endif
-
diff --git a/sys/netinet/ip_esp3des.c b/sys/netinet/ip_esp3des.c
index 3cb89280283..175a2594c8a 100644
--- a/sys/netinet/ip_esp3des.c
+++ b/sys/netinet/ip_esp3des.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_esp3des.c,v 1.5 1997/06/24 20:57:27 provos Exp $ */
+/* $OpenBSD: ip_esp3des.c,v 1.6 1997/06/25 07:53:25 provos Exp $ */
/*
* The author of this code is John Ioannidis, ji@tla.org,
@@ -300,8 +300,8 @@ esp3des_input(struct mbuf *m, struct tdb *tdb)
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) + blk[6] + 2;
+ tdb->tdb_cur_packets++;
+ tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) + blk[6] + 2;
return m;
}
@@ -476,8 +476,8 @@ esp3des_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, struc
*mp = m;
/* Update the counters */
- tdb->tdb_packets++;
- tdb->tdb_bytes += rlen + padding;
+ tdb->tdb_cur_packets++;
+ tdb->tdb_cur_bytes += rlen + padding;
return 0;
}
diff --git a/sys/netinet/ip_esp3desmd5.c b/sys/netinet/ip_esp3desmd5.c
index d6f1ecb3eed..d52969c457b 100644
--- a/sys/netinet/ip_esp3desmd5.c
+++ b/sys/netinet/ip_esp3desmd5.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_esp3desmd5.c,v 1.9 1997/06/24 20:57:28 provos Exp $ */
+/* $OpenBSD: ip_esp3desmd5.c,v 1.10 1997/06/25 07:53:25 provos Exp $ */
/*
* The author of this code is John Ioannidis, ji@tla.org,
@@ -509,9 +509,9 @@ esp3desmd5_input(struct mbuf *m, struct tdb *tdb)
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;
+ tdb->tdb_cur_packets++;
+ tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) + padsize +
+ 2 + ESP3DESMD5_ALEN;
return m;
}
@@ -772,8 +772,8 @@ esp3desmd5_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, st
*mp = m;
/* Update the counters */
- tdb->tdb_packets++;
- tdb->tdb_bytes += rlen + padding;
+ tdb->tdb_cur_packets++;
+ tdb->tdb_cur_bytes += rlen + padding;
return 0;
}
diff --git a/sys/netinet/ip_espdes.c b/sys/netinet/ip_espdes.c
index fd85253f793..d0b925c4aa0 100644
--- a/sys/netinet/ip_espdes.c
+++ b/sys/netinet/ip_espdes.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_espdes.c,v 1.7 1997/06/24 20:57:28 provos Exp $ */
+/* $OpenBSD: ip_espdes.c,v 1.8 1997/06/25 07:53:26 provos Exp $ */
/*
* The author of this code is John Ioannidis, ji@tla.org,
@@ -287,8 +287,8 @@ espdes_input(struct mbuf *m, struct tdb *tdb)
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) + blk[6] + 2;
+ tdb->tdb_cur_packets++;
+ tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) + blk[6] + 2;
return m;
}
@@ -460,8 +460,8 @@ espdes_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, struct
*mp = m;
/* Update the counters */
- tdb->tdb_packets++;
- tdb->tdb_bytes += rlen + padding;
+ tdb->tdb_cur_packets++;
+ tdb->tdb_cur_bytes += rlen + padding;
return 0;
}
diff --git a/sys/netinet/ip_espdesmd5.c b/sys/netinet/ip_espdesmd5.c
index 7ef8b91bc08..2700e34b888 100644
--- a/sys/netinet/ip_espdesmd5.c
+++ b/sys/netinet/ip_espdesmd5.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_espdesmd5.c,v 1.9 1997/06/24 20:57:29 provos Exp $ */
+/* $OpenBSD: ip_espdesmd5.c,v 1.10 1997/06/25 07:53:26 provos Exp $ */
/*
* The author of this code is John Ioannidis, ji@tla.org,
@@ -493,9 +493,9 @@ espdesmd5_input(struct mbuf *m, struct tdb *tdb)
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 + ESPDESMD5_ALEN;
+ tdb->tdb_cur_packets++;
+ tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) + padsize +
+ 2 + ESPDESMD5_ALEN;
return m;
}
@@ -754,8 +754,8 @@ espdesmd5_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, str
iphlen - sizeof(struct ip));
/* Update the counters */
- tdb->tdb_packets++;
- tdb->tdb_bytes += rlen + padding;
+ tdb->tdb_cur_packets++;
+ tdb->tdb_cur_bytes += rlen + padding;
*mp = m;
return 0;
diff --git a/sys/netinet/ip_ip4.c b/sys/netinet/ip_ip4.c
index ba5cedcc307..ff113083e91 100644
--- a/sys/netinet/ip_ip4.c
+++ b/sys/netinet/ip_ip4.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ip4.c,v 1.8 1997/06/24 12:15:25 provos Exp $ */
+/* $OpenBSD: ip_ip4.c,v 1.9 1997/06/25 07:53:27 provos Exp $ */
/*
* The author of this code is John Ioannidis, ji@tla.org,
@@ -208,8 +208,8 @@ ipe4_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, struct m
*mp = m;
/* Update the counters */
- tdb->tdb_packets++;
- tdb->tdb_bytes += ntohs(ipo->ip_len) - (ipo->ip_hl << 2);
+ tdb->tdb_cur_packets++;
+ tdb->tdb_cur_bytes += ntohs(ipo->ip_len) - (ipo->ip_hl << 2);
return 0;
diff --git a/sys/netinet/ip_ip4.h b/sys/netinet/ip_ip4.h
index 1912e858097..d489d3c1dc3 100644
--- a/sys/netinet/ip_ip4.h
+++ b/sys/netinet/ip_ip4.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ip4.h,v 1.5 1997/06/20 05:41:52 provos Exp $ */
+/* $OpenBSD: ip_ip4.h,v 1.6 1997/06/25 07:53:27 provos Exp $ */
/*
* The author of this code is John Ioannidis, ji@tla.org,
@@ -40,12 +40,12 @@ struct ip4_xencap
struct ip4stat
{
- u_long ip4s_ipackets; /* total input packets */
- u_long ip4s_opackets; /* total output packets */
- u_long ip4s_hdrops; /* packet shorter than header shows */
- u_long ip4s_badlen;
- u_long ip4s_notip4;
- u_long ip4s_qfull;
+ u_int32_t ip4s_ipackets; /* total input packets */
+ u_int32_t ip4s_opackets; /* total output packets */
+ u_int32_t ip4s_hdrops; /* packet shorter than header shows */
+ u_int32_t ip4s_badlen;
+ u_int32_t ip4s_notip4;
+ u_int32_t ip4s_qfull;
};
#define IP4_SAME_TTL 0
diff --git a/sys/netinet/ip_ipsp.c b/sys/netinet/ip_ipsp.c
index 1388be11ed6..99bbddb5ebe 100644
--- a/sys/netinet/ip_ipsp.c
+++ b/sys/netinet/ip_ipsp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.c,v 1.9 1997/06/24 12:15:25 provos Exp $ */
+/* $OpenBSD: ip_ipsp.c,v 1.10 1997/06/25 07:53:28 provos Exp $ */
/*
* The author of this code is John Ioannidis, ji@tla.org,
@@ -57,6 +57,8 @@
#include <netinet/ip_ah.h>
#include <netinet/ip_esp.h>
+#include <dev/rndvar.h>
+
int tdb_init __P((struct tdb *, struct mbuf *));
int ipsp_kern __P((int, char **, int));
@@ -71,7 +73,8 @@ int encdebug = 1;
struct xformsw xformsw[] = {
{ XF_IP4, 0, "IPv4 Simple Encapsulation",
ipe4_attach, ipe4_init, ipe4_zeroize,
- (struct mbuf * (*)(struct mbuf *, struct tdb *))ipe4_input, ipe4_output, },
+ (struct mbuf * (*)(struct mbuf *, struct tdb *))ipe4_input,
+ ipe4_output, },
{ XF_AHMD5, XFT_AUTH, "Keyed MD5 Authentication",
ahmd5_attach, ahmd5_init, ahmd5_zeroize,
ahmd5_input, ahmd5_output, },
@@ -106,6 +109,49 @@ static char *ipspkernfs = NULL;
int ipspkernfs_dirty = 1;
/*
+ * Reserve an SPI; the SA is not valid yet though. Zero is reserved as
+ * an error return value. If tspi is not zero, we try to allocate that
+ * SPI.
+ */
+
+u_int32_t
+reserve_spi(u_int32_t tspi, struct in_addr src)
+{
+ struct tdb *tdbp;
+ u_int32_t spi = tspi; /* Don't change */
+
+ while (1)
+ {
+ while (spi == 0) /* Get a new SPI */
+ get_random_bytes((void *)&spi, sizeof(spi));
+
+ /* Check whether we're using this SPI already */
+ if (gettdb(spi, src) != (struct tdb *) NULL)
+ {
+ if (tspi != 0) /* If one was proposed, report error */
+ return 0;
+
+ spi = 0;
+ continue;
+ }
+
+ MALLOC(tdbp, struct tdb *, sizeof(*tdbp), M_TDB, M_WAITOK);
+ if (tdbp == NULL)
+ return 0;
+
+ bzero((caddr_t)tdbp, sizeof(*tdbp));
+
+ tdbp->tdb_spi = spi;
+ tdbp->tdb_dst = src;
+ tdbp->tdb_flags |= TDBF_INVALID;
+
+ puttdb(tdbp);
+
+ return spi;
+ }
+}
+
+/*
* An IPSP SAID is really the concatenation of the SPI found in the
* packet and the destination address of the packet. When we receive
* an IPSP packet, we need to look up its tunnel descriptor block,
@@ -132,9 +178,11 @@ void
puttdb(struct tdb *tdbp)
{
int hashval;
+
hashval = ((tdbp->tdb_spi + tdbp->tdb_dst.s_addr) % TDB_HASHMOD);
tdbp->tdb_hnext = tdbh[hashval];
tdbh[hashval] = tdbp;
+
ipspkernfs_dirty = 1;
}
@@ -188,14 +236,17 @@ tdb_init(struct tdb *tdbp, struct mbuf *m)
#ifdef ENCDEBUG
if (encdebug)
- printf("tdbinit: no alg %d for spi %x, addr %x\n", alg, tdbp->tdb_spi, ntohl(tdbp->tdb_dst.s_addr));
+ printf("tdbinit: no alg %d for spi %x, addr %x\n", alg, tdbp->tdb_spi,
+ ntohl(tdbp->tdb_dst.s_addr));
#endif
-
+
+ /* Record establishment time */
+ tdbp->tdb_established = time.tv_sec;
+
m_freem(m);
return EINVAL;
}
-
int
ipsp_kern(int off, char **bufp, int len)
{
diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h
index b9c9c27e64d..2bf82d5b554 100644
--- a/sys/netinet/ip_ipsp.h
+++ b/sys/netinet/ip_ipsp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.h,v 1.7 1997/06/24 12:15:26 provos Exp $ */
+/* $OpenBSD: ip_ipsp.h,v 1.8 1997/06/25 07:53:28 provos Exp $ */
/*
* The author of this code is John Ioannidis, ji@tla.org,
@@ -34,20 +34,34 @@ struct tdb /* tunnel descriptor block */
struct tdb *tdb_inext; /* next in input (prev!) */
u_int32_t tdb_spi; /* SPI to use */
u_int32_t tdb_flags; /* Flags related to this TDB */
-#define TDBF_UNIQUE 0x0001 /* This should not be used by others */
-#define TDBF_TIMER 0x0002 /* Check the timers */
-#define TDBF_BYTES 0x0004 /* Check the byte counters */
-#define TDBF_PACKETS 0x0008 /* Check the packet counters */
-#define TDBF_INVALID 0x0010 /* This SPI is no longer valid */
- u_int64_t tdb_packets; /* Expire after so many packets s|r */
+#define TDBF_UNIQUE 0x00001 /* This should not be used by others */
+#define TDBF_TIMER 0x00002 /* Absolute expiration timer in use */
+#define TDBF_BYTES 0x00004 /* Check the byte counters */
+#define TDBF_PACKETS 0x00008 /* Check the packet counters */
+#define TDBF_INVALID 0x00010 /* This SPI is not valid yet/anymore */
+#define TDBF_FIRSTUSE 0x00020 /* Expire after first use */
+#define TDBF_RELATIVE 0x00040 /* Expire after X secs from establ. */
+#define TDBF_SOFT_TIMER 0x00080 /* Soft expiration */
+#define TDBF_SOFT_BYTES 0x00100 /* Soft expiration */
+#define TDBF_SOFT_PACKETS 0x00200 /* Soft expiration */
+#define TDBF_SOFT_FIRSTUSE 0x00400 /* Soft expiration */
+#define TDBF_SOFT_RELATIVE 0x00800 /* Soft expiration */
+ u_int64_t tdb_exp_packets; /* Expire after so many packets s|r */
u_int64_t tdb_soft_packets; /* Expiration warning */
u_int64_t tdb_cur_packets; /* Current number of packets s|r'ed */
- u_int64_t tdb_bytes; /* Expire after so many bytes passed */
+ u_int64_t tdb_exp_bytes; /* Expire after so many bytes passed */
u_int64_t tdb_soft_bytes; /* Expiration warning */
u_int64_t tdb_cur_bytes; /* Current count of bytes */
- u_int64_t tdb_timeout; /* When does the SPI expire */
+ u_int64_t tdb_exp_timeout; /* When does the SPI expire */
u_int64_t tdb_soft_timeout; /* Send a soft-expire warning */
u_int64_t tdb_established; /* When was the SPI established */
+ u_int64_t tdb_soft_relative ; /* Soft warning */
+ u_int64_t tdb_exp_relative; /* Expire if tdb_established +
+ tdb_exp_relative <= curtime */
+ u_int64_t tdb_first_use; /* When was it first used */
+ u_int64_t tdb_soft_first_use; /* Soft warning */
+ u_int64_t tdb_exp_first_use; /* Expire if tdb_first_use +
+ tdb_exp_first_use <= curtime */
struct in_addr tdb_dst; /* dest address for this SPI */
struct ifnet *tdb_rcvif; /* related rcv encap interface */
struct xformsw *tdb_xform; /* transformation to use */
@@ -116,6 +130,7 @@ extern int encdebug;
struct tdb *tdbh[TDB_HASHMOD];
extern struct xformsw xformsw[], *xformswNXFORMSW;
+extern u_int32_t reserve_spi(u_int32_t, struct in_addr);
extern struct tdb *gettdb(u_int32_t, struct in_addr);
extern void puttdb(struct tdb *);
extern int tdb_delete(struct tdb *, int);
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index e82ca8a8592..d420438f7dc 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_output.c,v 1.13 1997/06/24 12:15:27 provos Exp $ */
+/* $OpenBSD: ip_output.c,v 1.14 1997/06/25 07:53:29 provos Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@@ -44,6 +44,7 @@
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/systm.h>
+#include <sys/kernel.h>
#include <net/if.h>
#include <net/route.h>
@@ -161,8 +162,8 @@ ip_output(m0, va_alist)
dst->sen_ip_dst = ip->ip_dst;
dst->sen_proto = ip->ip_p;
- if (m->m_len < hlen + 2*sizeof(u_int16_t)) {
- if ((m = m_pullup(m, hlen + 2*sizeof(u_int16_t))) == 0)
+ if (m->m_len < hlen + 2 * sizeof(u_int16_t)) {
+ if ((m = m_pullup(m, hlen + 2 * sizeof(u_int16_t))) == 0)
goto bad;
ip = mtod(m, struct ip *);
}
@@ -191,7 +192,7 @@ ip_output(m0, va_alist)
#ifdef ENCDEBUG
if (encdebug)
printf("ip_output: no gw or gw data not IPSP\n");
-#endif ENCDEBUG
+#endif /* ENCDEBUG */
m_freem(m);
RTFREE(re->re_rt);
return EHOSTUNREACH;
@@ -211,7 +212,9 @@ ip_output(m0, va_alist)
if (encdebug)
printf("ip_output: interface %s has no default address\n",
ifp->if_xname);
-#endif ENCDEBUG
+#endif /* ENCDEBUG */
+ m_freem(m);
+ RTFREE(re->re_rt);
return ENXIO;
}
@@ -220,7 +223,7 @@ ip_output(m0, va_alist)
if (encdebug)
printf("ip_output: %s does not have AF_ENCAP address\n",
ifp->if_xname);
-#endif ENCDEBUG
+#endif /* ENCDEBUG */
m_freem(m);
RTFREE(re->re_rt);
return EHOSTDOWN;
@@ -231,7 +234,7 @@ ip_output(m0, va_alist)
if (encdebug)
printf("ip_output: %s does not have SENT_DEFIF address\n",
ifp->if_xname);
-#endif ENCDEBUG
+#endif /* ENCDEBUG */
m_freem(m);
RTFREE(re->re_rt);
return EHOSTDOWN;
@@ -280,15 +283,33 @@ ip_output(m0, va_alist)
#ifdef ENCDEBUG
if (encdebug)
printf("ip_output: tdb=0x%x, tdb->tdb_xform=0x%x, tdb->tdb_xform->xf_output=%x\n", tdb, tdb->tdb_xform, tdb->tdb_xform->xf_output);
-#endif ENCDEBUG
+#endif /* ENCDEBUG */
while (tdb && tdb->tdb_xform) {
m0 = NULL;
+
+ /* Check if the SPI is invalid */
+ if (tdb->tdb_flags & TDBF_INVALID)
+ {
+#ifdef ENCDEBUG
+ if (encdebug)
+ printf("ip_output: attempt to use invalid SPI %08x", tdb->tdb_spi);
+#endif /* ENCDEBUG */
+ m_freem(m);
+ RTFREE(re->re_rt);
+ return ENXIO;
+ }
+
#ifdef ENCDEBUG
if (encdebug)
printf("ip_output: calling %s\n",
tdb->tdb_xform->xf_name);
-#endif ENCDEBUG
+#endif /* ENCDEBUG */
+
+ /* Register first use */
+ if (tdb->tdb_first_use == 0)
+ tdb->tdb_first_use = time.tv_sec;
+
error = (*(tdb->tdb_xform->xf_output))(m, gw, tdb, &mp);
if (mp == NULL)
error = EFAULT;
@@ -335,7 +356,7 @@ no_encap:
* and is still up. If not, free it and try again.
*/
if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
- dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
+ dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
RTFREE(ro->ro_rt);
ro->ro_rt = (struct rtentry *)0;
}