diff options
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/in.h | 4 | ||||
-rw-r--r-- | sys/netinet/in_pcb.c | 4 | ||||
-rw-r--r-- | sys/netinet/in_pcb.h | 5 | ||||
-rw-r--r-- | sys/netinet/ip_ah.c | 30 | ||||
-rw-r--r-- | sys/netinet/ip_esp.c | 30 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.c | 149 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.h | 15 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 85 | ||||
-rw-r--r-- | sys/netinet/tcp_input.c | 52 | ||||
-rw-r--r-- | sys/netinet/tcp_var.h | 3 | ||||
-rw-r--r-- | sys/netinet/udp_usrreq.c | 39 | ||||
-rw-r--r-- | sys/netinet/udp_var.h | 3 |
12 files changed, 353 insertions, 66 deletions
diff --git a/sys/netinet/in.h b/sys/netinet/in.h index 38bd73db826..d58c46f1bc5 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in.h,v 1.20 1999/03/24 02:31:03 cmetz Exp $ */ +/* $OpenBSD: in.h,v 1.21 1999/03/27 21:04:21 provos Exp $ */ /* $NetBSD: in.h,v 1.20 1996/02/13 23:41:47 christos Exp $ */ /* @@ -379,6 +379,8 @@ struct ip_opts { #define ICMPV6_FILTER 38 /* struct icmpv6_filter; get/set filter */ #define ICMP6_FILTER ICMP6_FILTER +#define IPSEC_OUTSA 39 /* set the outbound SA for a socket */ + /* * Security levels - IPsec, not IPSO */ diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 23c656d635b..66fc00db939 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.c,v 1.31 1999/03/24 02:28:21 cmetz Exp $ */ +/* $OpenBSD: in_pcb.c,v 1.32 1999/03/27 21:04:18 provos Exp $ */ /* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */ /* @@ -529,6 +529,8 @@ in_pcbdetach(v) ip_freemoptions(inp->inp_moptions); #ifdef IPSEC /* XXX IPsec cleanup here */ + if (inp->inp_tdb) + TAILQ_REMOVE(&inp->inp_tdb->tdb_inp, inp, inp_tdb_next); #endif s = splnet(); LIST_REMOVE(inp, inp_hash); diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index 176ce07a742..cb753c3ae82 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.h,v 1.16 1999/03/24 02:33:02 cmetz Exp $ */ +/* $OpenBSD: in_pcb.h,v 1.17 1999/03/27 21:04:19 provos Exp $ */ /* $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $ */ /* @@ -40,6 +40,7 @@ #include <netinet6/ipv6.h> #include <netinet6/ipv6_var.h> #include <netinet6/icmpv6.h> +#include <netinet/ip_ipsp.h> union inpaddru { struct in6_addr iau_addr6; @@ -99,6 +100,8 @@ struct inpcb { #define SR_FAILED 1 /* Negotiation failed permanently */ #define SR_SUCCESS 2 /* SA successfully established */ #define SR_WAIT 3 /* Waiting for SA */ + TAILQ_ENTRY(inpcb) inp_tdb_next; + struct tdb *inp_tdb; /* If tdb_dst matches our dst, use */ int inp_fflowinfo; /* Foreign flowlabel & priority */ int inp_csumoffset; struct icmpv6_filter inp_filter; diff --git a/sys/netinet/ip_ah.c b/sys/netinet/ip_ah.c index afa4cbe472b..4fdb5d29813 100644 --- a/sys/netinet/ip_ah.c +++ b/sys/netinet/ip_ah.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ah.c,v 1.18 1999/02/24 23:45:46 angelos Exp $ */ +/* $OpenBSD: ip_ah.c,v 1.19 1999/03/27 21:04:19 provos Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -238,6 +238,32 @@ ah_input(register struct mbuf *m, int iphlen) return; } + if (ipo->ip_p == IPPROTO_TCP || ipo->ip_p == IPPROTO_UDP) + { + struct tdb_ident *tdbi = NULL; + if (tdbp->tdb_bind_out) + { + tdbi = m->m_pkthdr.tdbi; + if (!(m->m_flags & M_PKTHDR)) + { + DPRINTF(("ah_input(): mbuf is not a packet header!\n")); + } + if (!tdbi || !(m->m_flags & (M_CONF|M_AUTH))) + MALLOC(tdbi, struct tdb_ident *, sizeof(struct tdb_ident), + M_TEMP, M_NOWAIT); + + if (!tdbi) + goto no_mem; + + tdbi->spi = tdbp->tdb_bind_out->tdb_spi; + tdbi->dst = tdbp->tdb_bind_out->tdb_dst; + tdbi->proto = tdbp->tdb_bind_out->tdb_sproto; + } + + m->m_pkthdr.tdbi = tdbi; + no_mem: + } + /* Packet is authentic */ m->m_flags |= M_AUTH; @@ -277,6 +303,8 @@ ah_input(register struct mbuf *m, int iphlen) if (IF_QFULL(ifq)) { IF_DROP(ifq); + if (m->m_pkthdr.tdbi) + free(m->m_pkthdr.tdbi, M_TEMP); m_freem(m); ahstat.ahs_qfull++; splx(s); diff --git a/sys/netinet/ip_esp.c b/sys/netinet/ip_esp.c index f2da8435264..b099bdd1579 100644 --- a/sys/netinet/ip_esp.c +++ b/sys/netinet/ip_esp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_esp.c,v 1.18 1999/02/24 23:45:49 angelos Exp $ */ +/* $OpenBSD: ip_esp.c,v 1.19 1999/03/27 21:04:19 provos Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -237,6 +237,32 @@ esp_input(register struct mbuf *m, int iphlen) return; } + if (ipo->ip_p == IPPROTO_TCP || ipo->ip_p == IPPROTO_UDP) + { + struct tdb_ident *tdbi = NULL; + if (tdbp->tdb_bind_out) + { + tdbi = m->m_pkthdr.tdbi; + if (!(m->m_flags & M_PKTHDR)) + { + DPRINTF(("esp_input(): mbuf is not a packet header!\n")); + } + if (!tdbi || !(m->m_flags & (M_CONF|M_AUTH))) + MALLOC(tdbi, struct tdb_ident *, sizeof(struct tdb_ident), + M_TEMP, M_NOWAIT); + + if (!tdbi) + goto no_mem; + + tdbi->spi = tdbp->tdb_bind_out->tdb_spi; + tdbi->dst = tdbp->tdb_bind_out->tdb_dst; + tdbi->proto = tdbp->tdb_bind_out->tdb_sproto; + } + + m->m_pkthdr.tdbi = tdbi; + no_mem: + } + /* Packet is confidental */ m->m_flags |= M_CONF; @@ -276,6 +302,8 @@ esp_input(register struct mbuf *m, int iphlen) if (IF_QFULL(ifq)) { IF_DROP(ifq); + if (m->m_pkthdr.tdbi) + free(m->m_pkthdr.tdbi, M_TEMP); m_freem(m); espstat.esps_qfull++; splx(s); diff --git a/sys/netinet/ip_ipsp.c b/sys/netinet/ip_ipsp.c index 21ba455bca3..a6eef7e135a 100644 --- a/sys/netinet/ip_ipsp.c +++ b/sys/netinet/ip_ipsp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ipsp.c,v 1.38 1999/03/24 17:00:47 niklas Exp $ */ +/* $OpenBSD: ip_ipsp.c,v 1.39 1999/03/27 21:04:19 provos Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -184,6 +184,7 @@ check_ipsec_policy(struct inpcb *inp, u_int32_t daddr) struct sockaddr_encap *dst; u_int8_t sa_require, sa_have; int error, i; + struct tdb *tdb = NULL; if (inp == NULL || ((so = inp->inp_socket) == 0)) return (EINVAL); @@ -191,59 +192,60 @@ check_ipsec_policy(struct inpcb *inp, u_int32_t daddr) /* If IPSEC is not required just use what we got */ if (!(sa_require = inp->inp_secrequire)) return 0; - - bzero((caddr_t) re, sizeof(*re)); - dst = (struct sockaddr_encap *) &re->re_dst; - dst->sen_family = PF_KEY; - dst->sen_len = SENT_IP4_LEN; - dst->sen_type = SENT_IP4; - dst->sen_ip_src = inp->inp_laddr; - dst->sen_ip_dst.s_addr = inp->inp_faddr.s_addr ? - inp->inp_faddr.s_addr : daddr; - dst->sen_proto = so->so_proto->pr_protocol; - switch (dst->sen_proto) + + if (!inp->inp_tdb) { - case IPPROTO_UDP: - case IPPROTO_TCP: + bzero((caddr_t) re, sizeof(*re)); + dst = (struct sockaddr_encap *) &re->re_dst; + dst->sen_family = PF_KEY; + dst->sen_len = SENT_IP4_LEN; + dst->sen_type = SENT_IP4; + dst->sen_ip_src = inp->inp_laddr; + dst->sen_ip_dst.s_addr = inp->inp_faddr.s_addr ? + inp->inp_faddr.s_addr : daddr; + dst->sen_proto = so->so_proto->pr_protocol; + switch (dst->sen_proto) + { + case IPPROTO_UDP: + case IPPROTO_TCP: dst->sen_sport = inp->inp_lport; dst->sen_dport = inp->inp_fport; break; - default: + default: dst->sen_sport = 0; dst->sen_dport = 0; - } + } - /* Try to find a flow */ - rtalloc((struct route *) re); + /* Try to find a flow */ + rtalloc((struct route *) re); - if (re->re_rt != NULL) - { - struct tdb *tdb; - struct sockaddr_encap *gw; - - gw = (struct sockaddr_encap *) (re->re_rt->rt_gateway); - - if (gw->sen_type == SENT_IPSP) { - sunion.sin.sin_family = AF_INET; - sunion.sin.sin_len = sizeof(struct sockaddr_in); - sunion.sin.sin_addr = gw->sen_ipsp_dst; + if (re->re_rt != NULL) + { + struct sockaddr_encap *gw; - tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi, &sunion, - gw->sen_ipsp_sproto); - - SPI_CHAIN_ATTRIB(sa_have, tdb_onext, tdb); + gw = (struct sockaddr_encap *) (re->re_rt->rt_gateway); + + if (gw->sen_type == SENT_IPSP) { + sunion.sin.sin_family = AF_INET; + sunion.sin.sin_len = sizeof(struct sockaddr_in); + sunion.sin.sin_addr = gw->sen_ipsp_dst; + + tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi, &sunion, + gw->sen_ipsp_sproto); + } + RTFREE(re->re_rt); } - else - sa_have = 0; - - RTFREE(re->re_rt); - - /* Check if our requirements are met */ - if (!(sa_require & ~sa_have)) - return 0; - } - else - sa_have = 0; + } else + tdb = inp->inp_tdb; + + if (tdb) { + SPI_CHAIN_ATTRIB(sa_have, tdb_onext, tdb); + } else + sa_have = 0; + + /* Check if our requirements are met */ + if (!(sa_require & ~sa_have)) + return 0; error = i = 0; @@ -290,6 +292,24 @@ check_ipsec_policy(struct inpcb *inp, u_int32_t daddr) } /* + * Add an inpcb to the list of inpcb which reference this tdb directly. + */ + +void +tdb_add_inp(struct tdb *tdb, struct inpcb *inp) +{ + if (inp->inp_tdb) { + if (inp->inp_tdb == tdb) + return; + TAILQ_REMOVE(&inp->inp_tdb->tdb_inp, inp, inp_tdb_next); + } + inp->inp_tdb = tdb; + TAILQ_INSERT_TAIL(&tdb->tdb_inp, inp, inp_tdb_next); + + DPRINTF(("tdb_add_inp: tdb: %p, inp: %p\n", tdb, inp)); +} + +/* * 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. @@ -659,6 +679,7 @@ tdb_delete(struct tdb *tdbp, int delchain) { u_int8_t *ptr = (u_int8_t *) &tdbp->tdb_dst; struct tdb *tdbpp; + struct inpcb *inp; u_int32_t hashval = tdbp->tdb_sproto + tdbp->tdb_spi, i; for (i = 0; i < SA_LEN(&tdbp->tdb_dst.sa); i++) @@ -706,6 +727,24 @@ tdb_delete(struct tdb *tdbp, int delchain) ipsec_in_use--; } + /* Cleanup SA-Bindings */ + for (tdbpp = TAILQ_FIRST(&tdbp->tdb_bind_in); tdbpp; + tdbpp = TAILQ_FIRST(&tdbp->tdb_bind_in)) + { + TAILQ_REMOVE(&tdbpp->tdb_bind_in, tdbpp, tdb_bind_in_next); + tdbpp->tdb_bind_out = NULL; + } + /* Cleanup inp references */ + for (inp = TAILQ_FIRST(&tdbp->tdb_inp); inp; + inp = TAILQ_FIRST(&tdbp->tdb_inp)) + { + TAILQ_REMOVE(&tdbp->tdb_inp, inp, inp_tdb_next); + inp->inp_tdb = NULL; + } + + if (tdbp->tdb_bind_out) + TAILQ_REMOVE(&tdbp->tdb_bind_out->tdb_bind_in, tdbp, tdb_bind_in_next); + /* removal of a larval SA should not remove the mature SA's expirations */ if ((tdbp->tdb_flags & TDBF_INVALID) == 0) cleanup_expirations(&tdbp->tdb_dst, tdbp->tdb_spi, tdbp->tdb_sproto); @@ -733,6 +772,10 @@ tdb_init(struct tdb *tdbp, u_int16_t alg, struct ipsecinit *ii) tdbp->tdb_established = time.tv_sec; tdbp->tdb_epoch = kernfs_epoch - 1; + /* Init Incoming SA-Binding Queues */ + TAILQ_INIT(&tdbp->tdb_bind_in); + TAILQ_INIT(&tdbp->tdb_inp); + for (xsp = xformsw; xsp < xformswNXFORMSW; xsp++) if (xsp->xf_type == alg) return (*(xsp->xf_init))(tdbp, xsp, ii); @@ -752,7 +795,7 @@ ipsp_kern(int off, char **bufp, int len) { static char buffer[IPSEC_KERNFS_BUFSIZE]; struct flow *flow; - struct tdb *tdb; + struct tdb *tdb, *tdbp; int l, i; if (off == 0) @@ -866,6 +909,22 @@ ipsp_kern(int off, char **bufp, int len) l += sprintf(buffer + l, "\t\tAuthentication = <%s>\n", tdb->tdb_authalgxform->name); + if (tdb->tdb_bind_out) + l += sprintf(buffer + l, + "\tBound SA: SPI = %08x, " + "Destination = %s, Sproto = %u\n", + ntohl(tdb->tdb_bind_out->tdb_spi), + ipsp_address(tdb->tdb_bind_out->tdb_dst), + tdb->tdb_bind_out->tdb_sproto); + for (i = 0, tdbp = TAILQ_FIRST(&tdb->tdb_bind_in); tdbp; + tdbp = TAILQ_NEXT(tdbp, tdb_bind_in_next)) + i++; + + if (i > 0) + l += sprintf(buffer + l, + "\tReferenced by %d incoming SA%s\n", + i, i == 1 ? "" : "s"); + if (tdb->tdb_onext) l += sprintf(buffer + l, "\tNext SA: SPI = %08x, " diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h index f0048366b3c..e963410849f 100644 --- a/sys/netinet/ip_ipsp.h +++ b/sys/netinet/ip_ipsp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ipsp.h,v 1.27 1999/02/25 01:30:49 angelos Exp $ */ +/* $OpenBSD: ip_ipsp.h,v 1.28 1999/03/27 21:04:19 provos Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -43,6 +43,7 @@ */ #include <sys/types.h> +#include <sys/queue.h> #include <netinet/in.h> #include <sys/md5k.h> #include <netinet/ip_sha1.h> @@ -283,10 +284,21 @@ struct tdb /* tunnel descriptor block */ u_int16_t tdb_dstid_type; struct flow *tdb_flow; /* Which flows use this SA */ + + struct tdb *tdb_bind_out; /* Outgoing SA to use */ + TAILQ_HEAD(tdb_bind_head, tdb) tdb_bind_in; + TAILQ_ENTRY(tdb) tdb_bind_in_next; /* Refering Incoming SAs */ + TAILQ_HEAD(tdb_inp_head, inpcb) tdb_inp; }; #define TDB_HASHMOD 257 +struct tdb_ident { + u_int32_t spi; + union sockaddr_union dst; + u_int8_t proto; +}; + struct auth_hash { int type; char *name; @@ -418,6 +430,7 @@ extern char *inet_ntoa4(struct in_addr); extern char *ipsp_address(union sockaddr_union); /* TDB management routines */ +extern void tdb_add_inp(struct tdb *tdb, struct inpcb *inp); extern u_int32_t reserve_spi(u_int32_t, u_int32_t, union sockaddr_union *, union sockaddr_union *, u_int8_t, int *); extern struct tdb *gettdb(u_int32_t, union sockaddr_union *, u_int8_t); diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 311806ea3d8..0c0400c0c1a 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_output.c,v 1.43 1999/03/24 17:00:47 niklas Exp $ */ +/* $OpenBSD: ip_output.c,v 1.44 1999/03/27 21:04:20 provos Exp $ */ /* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */ /* @@ -167,8 +167,7 @@ ip_output(m0, va_alist) /* * Check if the packet needs encapsulation */ - if ((ipsec_in_use != 0) && - !(flags & IP_ENCAPSULATED) && + if (!(flags & IP_ENCAPSULATED) && (inp == NULL || (inp->inp_seclevel[SL_AUTH] != IPSEC_LEVEL_BYPASS || inp->inp_seclevel[SL_ESP_TRANS] != IPSEC_LEVEL_BYPASS || @@ -184,6 +183,20 @@ ip_output(m0, va_alist) sa_require = inp->inp_secrequire; bzero((caddr_t) re, sizeof(*re)); + + /* Check if there was a bound outgoing SA */ + if (inp && inp->inp_tdb && + (inp->inp_tdb->tdb_dst.sin.sin_addr.s_addr == + INADDR_ANY || + !bcmp(&inp->inp_tdb->tdb_dst.sin.sin_addr, + &ip->ip_dst, sizeof(ip->ip_dst)))) { + tdb = inp->inp_tdb; + goto have_tdb; + } + + if (!ipsec_in_use) + goto no_encap; + ddst = (struct sockaddr_encap *) &re->re_dst; ddst->sen_family = PF_KEY; ddst->sen_len = SENT_IP4_LEN; @@ -266,10 +279,6 @@ ip_output(m0, va_alist) goto no_encap; } - ip->ip_len = htons((u_short)ip->ip_len); - ip->ip_off = htons((u_short)ip->ip_off); - ip->ip_sum = 0; - /* * At this point we have an IPSP "gateway" (tunnel) spec. * Use the destination of the tunnel and the SPI to @@ -284,6 +293,12 @@ ip_output(m0, va_alist) tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi, &sunion, gw->sen_ipsp_sproto); + have_tdb: + + ip->ip_len = htons((u_short)ip->ip_len); + ip->ip_off = htons((u_short)ip->ip_off); + ip->ip_sum = 0; + /* * Now we check if this tdb has all the transforms which * are requried by the socket or our default policy. @@ -354,7 +369,8 @@ ip_output(m0, va_alist) if (tdb->tdb_flags & TDBF_INVALID) { DPRINTF(("ip_output(): attempt to use invalid SA %s/%08x/%u\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi), tdb->tdb_sproto)); m_freem(m); - RTFREE(re->re_rt); + if (re->re_rt) + RTFREE(re->re_rt); return ENXIO; } @@ -389,6 +405,8 @@ ip_output(m0, va_alist) /* Check for tunneling */ if (((tdb->tdb_dst.sin.sin_addr.s_addr != + INADDR_ANY && + tdb->tdb_dst.sin.sin_addr.s_addr != ip->ip_dst.s_addr) || (tdb->tdb_flags & TDBF_TUNNELING)) && (tdb->tdb_xform->xf_type != XF_IP4)) @@ -404,7 +422,8 @@ ip_output(m0, va_alist) if (mp == NULL) error = EFAULT; if (error) { - RTFREE(re->re_rt); + if (re->re_rt) + RTFREE(re->re_rt); return error; } m = mp; @@ -427,7 +446,8 @@ ip_output(m0, va_alist) if (error) { if (mp != NULL) m_freem(mp); - RTFREE(re->re_rt); + if (re->re_rt) + RTFREE(re->re_rt); return error; } @@ -444,7 +464,8 @@ ip_output(m0, va_alist) * processed packet. Call ourselves recursively, but * bypass the encap code. */ - RTFREE(re->re_rt); + if (re->re_rt) + RTFREE(re->re_rt); ip = mtod(m, struct ip *); NTOHS(ip->ip_len); NTOHS(ip->ip_off); @@ -953,6 +974,28 @@ ip_ctloutput(op, so, level, optname, mp) } } break; + case IPSEC_OUTSA: +#ifndef IPSEC + error = EINVAL; +#else + if (m == 0 || m->m_len != sizeof(struct tdb_ident)) { + error = EINVAL; + break; + } else { + struct tdb *tdb; + struct tdb_ident *tdbi; + + tdbi = mtod(m, struct tdb_ident *); + tdb = gettdb(tdbi->spi, &tdbi->dst, + tdbi->proto); + if (tdb == NULL) { + error = ESRCH; + break; + } + tdb_add_inp(tdb, inp); + } +#endif /* IPSEC */ + break; case IP_AUTH_LEVEL: case IP_ESP_TRANS_LEVEL: @@ -1082,6 +1125,26 @@ ip_ctloutput(op, so, level, optname, mp) *mtod(m, int *) = optval; break; + case IPSEC_OUTSA: +#ifndef IPSEC + error = EINVAL; +#else + if (inp->inp_tdb == NULL) { + error = ENOENT; + break; + } else { + struct tdb_ident tdbi; + tdbi.spi = inp->inp_tdb->tdb_spi; + tdbi.dst = inp->inp_tdb->tdb_dst; + tdbi.proto = inp->inp_tdb->tdb_sproto; + *mp = m = m_get(M_WAIT, MT_SOOPTS); + m->m_len = sizeof(tdbi); + bcopy((caddr_t)&tdbi, mtod(m, caddr_t), + (unsigned)m->m_len); + } +#endif /* IPSEC */ + break; + case IP_AUTH_LEVEL: case IP_ESP_TRANS_LEVEL: case IP_ESP_NETWORK_LEVEL: diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 1bb0da1d16e..59086ee521b 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.32 1999/02/15 02:39:02 provos Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.33 1999/03/27 21:04:20 provos Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -77,6 +77,10 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. #include <machine/stdarg.h> #include <sys/md5k.h> +#ifdef IPSEC +#include <netinet/ip_ipsp.h> +#endif /* IPSEC */ + #ifdef INET6 #include <sys/domain.h> #include <netinet6/in6_var.h> @@ -437,6 +441,9 @@ tcp_input(m, va_alist) int iphlen; va_list ap; register struct tcphdr *th; +#ifdef IPSEC + struct tdb *tdb = NULL; +#endif /* IPSEC */ #ifdef INET6 struct in6_addr laddr6; unsigned short is_ipv6; /* Type of incoming datagram. */ @@ -449,6 +456,15 @@ tcp_input(m, va_alist) tcpstat.tcps_rcvtotal++; +#ifdef IPSEC + /* Save the last SA which was used to process the mbuf */ + if ((m->m_flags & (M_CONF|M_AUTH)) && m->m_pkthdr.tdbi) { + struct tdb_ident *tdbi = m->m_pkthdr.tdbi; + tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto); + free(m->m_pkthdr.tdbi, M_TEMP); + m->m_pkthdr.tdbi = NULL; + } +#endif /* IPSEC */ #ifdef INET6 /* * Before we do ANYTHING, we have to figure out if it's TCP/IPv6 or @@ -683,6 +699,18 @@ findpcb: * we're committed to it below in TCPS_LISTEN. */ dropsocket++; +#ifdef IPSEC + /* + * We need to copy the required security levels + * from the old pcb. + */ + { + struct inpcb *newinp = (struct inpcb *)so->so_pcb; + bcopy(inp->inp_seclevel, newinp->inp_seclevel, + sizeof(inp->inp_seclevel)); + newinp->inp_secrequire = inp->inp_secrequire; + } +#endif /* IPSEC */ #ifdef INET6 /* * inp still has the OLD in_pcb stuff, set the @@ -748,6 +776,28 @@ findpcb: } } +#ifdef IPSEC + /* Check if this socket requires security for incoming packets */ + if ((inp->inp_seclevel[SL_AUTH] >= IPSEC_LEVEL_REQUIRE && + !(m->m_flags & M_AUTH)) || + (inp->inp_seclevel[SL_ESP_TRANS] >= IPSEC_LEVEL_REQUIRE && + !(m->m_flags & M_CONF))) { +#ifdef notyet +#ifdef INET6 + if (is_ipv6) + ipv6_icmp_error(m, ICMPV6_BLAH, ICMPV6_BLAH, 0); + else +#endif /* INET6 */ + icmp_error(m, ICMP_BLAH, ICMP_BLAH, 0, 0); +#endif /* notyet */ + tcpstat.tcps_rcvnosec++; + goto drop; + } + /* Use tdb_bind_out for this inp's outbound communication */ + if (tdb) + tdb_add_inp(tdb, inp); +#endif /*IPSEC */ + /* * Segment received on connection. * Reset idle time and keep-alive timer. diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index c4c1b2213ec..f7ac9a841b3 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_var.h,v 1.18 1999/02/04 16:12:13 deraadt Exp $ */ +/* $OpenBSD: tcp_var.h,v 1.19 1999/03/27 21:04:21 provos Exp $ */ /* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */ /* @@ -244,6 +244,7 @@ struct tcpstat { u_int32_t tcps_rcvbadsum; /* packets received with ccksum errs */ u_int32_t tcps_rcvbadoff; /* packets received with bad offset */ u_int32_t tcps_rcvmemdrop; /* packets dropped for lack of memory */ + u_int32_t tcps_rcvnosec; /* packets dropped for lack of ipsec */ u_int32_t tcps_rcvshort; /* packets received too short */ u_int32_t tcps_rcvduppack; /* duplicate-only packets received */ u_int64_t tcps_rcvdupbyte; /* duplicate-only bytes received */ diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 48805a76134..ce04a080ad8 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_usrreq.c,v 1.24 1999/03/24 02:59:06 cmetz Exp $ */ +/* $OpenBSD: udp_usrreq.c,v 1.25 1999/03/27 21:04:20 provos Exp $ */ /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */ /* @@ -76,6 +76,8 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. #include <netinet/udp_var.h> #ifdef IPSEC +#include <netinet/ip_ipsp.h> + extern int check_ipsec_policy __P((struct inpcb *, u_int32_t)); #endif @@ -147,6 +149,9 @@ udp_input(m, va_alist) struct ipv6 *ipv6; struct sockaddr_in6 src_v4mapped; #endif /* INET6 */ +#ifdef IPSEC + struct tdb *tdb = NULL; +#endif /* IPSEC */ va_start(ap, m); iphlen = va_arg(ap, int); @@ -154,6 +159,16 @@ udp_input(m, va_alist) udpstat.udps_ipackets++; +#ifdef IPSEC + /* Save the last SA which was used to process the mbuf */ + if ((m->m_flags & (M_CONF|M_AUTH)) && m->m_pkthdr.tdbi) { + struct tdb_ident *tdbi = m->m_pkthdr.tdbi; + tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto); + free(m->m_pkthdr.tdbi, M_TEMP); + m->m_pkthdr.tdbi = NULL; + } +#endif /* IPSEC */ + switch (mtod(m, struct ip *)->ip_v) { case 4: ip = mtod(m, struct ip *); @@ -485,6 +500,28 @@ udp_input(m, va_alist) } } +#ifdef IPSEC + /* Check if this socket requires security for incoming packets */ + if ((inp->inp_seclevel[SL_AUTH] >= IPSEC_LEVEL_REQUIRE && + !(m->m_flags & M_AUTH)) || + (inp->inp_seclevel[SL_ESP_TRANS] >= IPSEC_LEVEL_REQUIRE && + !(m->m_flags & M_CONF))) { +#ifdef notyet +#ifdef INET6 + if (ipv6) + ipv6_icmp_error(m, ICMPV6_BLAH, ICMPV6_BLAH, 0); + else +#endif /* INET6 */ + icmp_error(m, ICMP_BLAH, ICMP_BLAH, 0, 0); +#endif /* notyet */ + udpstat.udps_nosec++; + goto bad; + } + /* Use tdb_bind_out for this inp's outbound communication */ + if (tdb) + tdb_add_inp(tdb, inp); +#endif /*IPSEC */ + if (inp->inp_flags & INP_CONTROLOPTS) { struct mbuf **mp = &opts; diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h index f41b8aa10b5..afc23036d32 100644 --- a/sys/netinet/udp_var.h +++ b/sys/netinet/udp_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_var.h,v 1.7 1999/02/04 16:05:02 deraadt Exp $ */ +/* $OpenBSD: udp_var.h,v 1.8 1999/03/27 21:04:21 provos Exp $ */ /* $NetBSD: udp_var.h,v 1.12 1996/02/13 23:44:41 christos Exp $ */ /* @@ -62,6 +62,7 @@ struct udpstat { u_long udps_badlen; /* data length larger than packet */ u_long udps_noport; /* no socket on port */ u_long udps_noportbcast; /* of above, arrived as broadcast */ + u_long udps_nosec; /* dropped for lack of ipsec */ u_long udps_fullsock; /* not delivered, input socket full */ u_long udps_pcbhashmiss; /* input packets missing pcb hash */ /* output statistics: */ |