diff options
author | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 2002-06-25 00:21:33 +0000 |
---|---|---|
committer | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 2002-06-25 00:21:33 +0000 |
commit | 08ca93d09ad9b6ea6b0c3561370d42c9e8df653b (patch) | |
tree | 8ec387a81cdd737537d5b8b24909290f43b4afe5 /sys | |
parent | 4052ea3919a763a084b4e76e7180fe68b6865a5b (diff) |
Make udp_input() a bit more readable by farming out the IPsec input
policy checking to a separate routine. Also, add missing checks for
multicast sockets, pointed out by sam@errno.com
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/udp_usrreq.c | 153 |
1 files changed, 86 insertions, 67 deletions
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index fb1cfb25539..644969a468c 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_usrreq.c,v 1.79 2002/06/20 03:49:02 deraadt Exp $ */ +/* $OpenBSD: udp_usrreq.c,v 1.80 2002/06/25 00:21:32 angelos Exp $ */ /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */ /* @@ -112,6 +112,7 @@ int udpcksum = 1; static void udp_detach(struct inpcb *); static void udp_notify(struct inpcb *, int); static struct mbuf *udp_saveopt(caddr_t, int, int); +int udp_check_ipsec(struct mbuf *, struct inpcb *, union sockaddr_union, int); #ifndef UDBHASHSIZE #define UDBHASHSIZE 128 @@ -150,33 +151,89 @@ udp6_input(mp, offp, proto) } #endif +#ifdef IPSEC +int +udp_check_ipsec(m, inp, srcsa,iphlen) + struct mbuf *m; + struct inpcb *inp; + union sockaddr_union srcsa; + int iphlen; +{ + struct m_tag *mtag; + struct tdb_ident *tdbi; + struct tdb *tdb; + int error, s; + + mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); + s = splnet(); + if (mtag != NULL) { + tdbi = (struct tdb_ident *)(mtag + 1); + tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto); + } else + tdb = NULL; + ipsp_spd_lookup(m, srcsa.sa.sa_family, iphlen, &error, + IPSP_DIRECTION_IN, tdb, inp); + if (error) { + splx(s); + return -1; + } + + /* Latch SA only if the socket is connected. */ + if (inp->inp_tdb_in != tdb && + (inp->inp_socket->so_state & SS_ISCONNECTED)) { + if (tdb) { + tdb_add_inp(tdb, inp, 1); + if (inp->inp_ipo == NULL) { + inp->inp_ipo = ipsec_add_policy(inp, + srcsa.sa.sa_family, IPSP_DIRECTION_OUT); + if (inp->inp_ipo == NULL) { + splx(s); + return -1; + } + } + if (inp->inp_ipo->ipo_dstid == NULL && + tdb->tdb_srcid != NULL) { + inp->inp_ipo->ipo_dstid = tdb->tdb_srcid; + tdb->tdb_srcid->ref_count++; + } + if (inp->inp_ipsec_remotecred == NULL && + tdb->tdb_remote_cred != NULL) { + inp->inp_ipsec_remotecred = + tdb->tdb_remote_cred; + tdb->tdb_remote_cred->ref_count++; + } + if (inp->inp_ipsec_remoteauth == NULL && + tdb->tdb_remote_auth != NULL) { + inp->inp_ipsec_remoteauth = + tdb->tdb_remote_auth; + tdb->tdb_remote_auth->ref_count++; + } + } else { /* Just reset */ + TAILQ_REMOVE(&inp->inp_tdb_in->tdb_inp_in, inp, + inp_tdb_in_next); + inp->inp_tdb_in = NULL; + } + } + splx(s); + return 0; +} +#endif /* IPSEC */ + void udp_input(struct mbuf *m, ...) { - register struct ip *ip; - register struct udphdr *uh; - register struct inpcb *inp; + struct ip *ip; + struct udphdr *uh; + struct inpcb *inp; struct mbuf *opts = 0; struct ip save_ip; int iphlen, len; va_list ap; u_int16_t savesum; - union { - struct sockaddr sa; - struct sockaddr_in sin; -#ifdef INET6 - struct sockaddr_in6 sin6; -#endif /* INET6 */ - } srcsa, dstsa; + union sockaddr_union srcsa, dstsa; #ifdef INET6 struct ip6_hdr *ipv6; #endif /* INET6 */ -#ifdef IPSEC - struct m_tag *mtag; - struct tdb_ident *tdbi; - struct tdb *tdb; - int error, s; -#endif /* IPSEC */ va_start(ap, m); iphlen = va_arg(ap, int); @@ -426,6 +483,12 @@ udp_input(struct mbuf *m, ...) if (last != NULL) { struct mbuf *n; +#ifdef IPSEC + if (udp_check_ipsec(m, inp, srcsa, + iphlen) == -1) + goto bad; +#endif /*IPSEC */ + if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { opts = NULL; #ifdef INET6 @@ -467,6 +530,11 @@ udp_input(struct mbuf *m, ...) goto bad; } +#ifdef IPSEC + if (udp_check_ipsec(m, inp, srcsa, iphlen) == -1) + goto bad; +#endif /*IPSEC */ + opts = NULL; #ifdef INET6 if (ipv6 && (inp->inp_flags & IN6P_CONTROLOPTS)) @@ -527,57 +595,8 @@ udp_input(struct mbuf *m, ...) } #ifdef IPSEC - mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); - s = splnet(); - if (mtag != NULL) { - tdbi = (struct tdb_ident *)(mtag + 1); - tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto); - } else - tdb = NULL; - ipsp_spd_lookup(m, srcsa.sa.sa_family, iphlen, &error, - IPSP_DIRECTION_IN, tdb, inp); - if (error) { - splx(s); + if (udp_check_ipsec(m, inp, srcsa, iphlen) == -1) goto bad; - } - - /* Latch SA only if the socket is connected */ - if (inp->inp_tdb_in != tdb && - (inp->inp_socket->so_state & SS_ISCONNECTED)) { - if (tdb) { - tdb_add_inp(tdb, inp, 1); - if (inp->inp_ipo == NULL) { - inp->inp_ipo = ipsec_add_policy(inp, - srcsa.sa.sa_family, IPSP_DIRECTION_OUT); - if (inp->inp_ipo == NULL) { - splx(s); - goto bad; - } - } - if (inp->inp_ipo->ipo_dstid == NULL && - tdb->tdb_srcid != NULL) { - inp->inp_ipo->ipo_dstid = tdb->tdb_srcid; - tdb->tdb_srcid->ref_count++; - } - if (inp->inp_ipsec_remotecred == NULL && - tdb->tdb_remote_cred != NULL) { - inp->inp_ipsec_remotecred = - tdb->tdb_remote_cred; - tdb->tdb_remote_cred->ref_count++; - } - if (inp->inp_ipsec_remoteauth == NULL && - tdb->tdb_remote_auth != NULL) { - inp->inp_ipsec_remoteauth = - tdb->tdb_remote_auth; - tdb->tdb_remote_auth->ref_count++; - } - } else { /* Just reset */ - TAILQ_REMOVE(&inp->inp_tdb_in->tdb_inp_in, inp, - inp_tdb_in_next); - inp->inp_tdb_in = NULL; - } - } - splx(s); #endif /*IPSEC */ opts = NULL; |