summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAngelos D. Keromytis <angelos@cvs.openbsd.org>2002-06-25 00:21:33 +0000
committerAngelos D. Keromytis <angelos@cvs.openbsd.org>2002-06-25 00:21:33 +0000
commit08ca93d09ad9b6ea6b0c3561370d42c9e8df653b (patch)
tree8ec387a81cdd737537d5b8b24909290f43b4afe5 /sys
parent4052ea3919a763a084b4e76e7180fe68b6865a5b (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.c153
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;