diff options
-rw-r--r-- | sys/net/encap.c | 668 | ||||
-rw-r--r-- | sys/net/encap.h | 196 | ||||
-rw-r--r-- | sys/netinet/ip_ah.c | 17 | ||||
-rw-r--r-- | sys/netinet/ip_ah.h | 3 | ||||
-rw-r--r-- | sys/netinet/ip_ahhmacmd5.c | 28 | ||||
-rw-r--r-- | sys/netinet/ip_ahhmacsha1.c | 24 | ||||
-rw-r--r-- | sys/netinet/ip_ahmd5.c | 26 | ||||
-rw-r--r-- | sys/netinet/ip_ahsha1.c | 22 | ||||
-rw-r--r-- | sys/netinet/ip_esp.c | 18 | ||||
-rw-r--r-- | sys/netinet/ip_esp.h | 26 | ||||
-rw-r--r-- | sys/netinet/ip_esp3des.c | 10 | ||||
-rw-r--r-- | sys/netinet/ip_esp3desmd5.c | 12 | ||||
-rw-r--r-- | sys/netinet/ip_espdes.c | 10 | ||||
-rw-r--r-- | sys/netinet/ip_espdesmd5.c | 12 | ||||
-rw-r--r-- | sys/netinet/ip_ip4.c | 6 | ||||
-rw-r--r-- | sys/netinet/ip_ip4.h | 14 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.c | 61 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.h | 33 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 41 |
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; } |