diff options
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/encap.c | 668 | ||||
-rw-r--r-- | sys/net/encap.h | 196 |
2 files changed, 523 insertions, 341 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 |