summaryrefslogtreecommitdiffstats
path: root/sys/netipsec/ipsec.c
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2009-02-08 09:27:07 +0000
committerbz <bz@FreeBSD.org>2009-02-08 09:27:07 +0000
commit8d30abae87cd5c2bd5618798ba40d8ce75dc3804 (patch)
treec3f4f5918e20a04942f107b193a1f461e54b06cb /sys/netipsec/ipsec.c
parent128fcdf861ec5a57a865a9821336441d8d211111 (diff)
downloadFreeBSD-src-8d30abae87cd5c2bd5618798ba40d8ce75dc3804.zip
FreeBSD-src-8d30abae87cd5c2bd5618798ba40d8ce75dc3804.tar.gz
Try to remove/assimilate as much of formerly IPv4/6 specific
(duplicate) code in sys/netipsec/ipsec.c and fold it into common, INET/6 independent functions. The file local functions ipsec4_setspidx_inpcb() and ipsec6_setspidx_inpcb() were 1:1 identical after the change in r186528. Rename to ipsec_setspidx_inpcb() and remove the duplicate. Public functions ipsec[46]_get_policy() were 1:1 identical. Remove one copy and merge in the factored out code from ipsec_get_policy() into the other. The public function left is now called ipsec_get_policy() and callers were adapted. Public functions ipsec[46]_set_policy() were 1:1 identical. Rename file local ipsec_set_policy() function to ipsec_set_policy_internal(). Remove one copy of the public functions, rename the other to ipsec_set_policy() and adapt callers. Public functions ipsec[46]_hdrsiz() were logically identical (ignoring one questionable assert in the v6 version). Rename the file local ipsec_hdrsiz() to ipsec_hdrsiz_internal(), the public function to ipsec_hdrsiz(), remove the duplicate copy and adapt the callers. The v6 version had been unused anyway. Cleanup comments. Public functions ipsec[46]_in_reject() were logically identical apart from statistics. Move the common code into a file local ipsec46_in_reject() leaving vimage+statistics in small AF specific wrapper functions. Note: unfortunately we already have a public ipsec_in_reject(). Reviewed by: sam Discussed with: rwatson (renaming to *_internal) MFC after: 26 days X-MFC: keep wrapper functions for public symbols?
Diffstat (limited to 'sys/netipsec/ipsec.c')
-rw-r--r--sys/netipsec/ipsec.c270
1 files changed, 56 insertions, 214 deletions
diff --git a/sys/netipsec/ipsec.c b/sys/netipsec/ipsec.c
index c8d27d2..00ce8de 100644
--- a/sys/netipsec/ipsec.c
+++ b/sys/netipsec/ipsec.c
@@ -228,10 +228,7 @@ SYSCTL_V_STRUCT(V_NET, vnet_ipsec, _net_inet6_ipsec6, IPSECCTL_STATS,
"IPsec IPv6 statistics.");
#endif /* INET6 */
-static int ipsec4_setspidx_inpcb __P((struct mbuf *, struct inpcb *));
-#ifdef INET6
-static int ipsec6_setspidx_inpcb __P((struct mbuf *, struct inpcb *));
-#endif
+static int ipsec_setspidx_inpcb __P((struct mbuf *, struct inpcb *));
static int ipsec_setspidx __P((struct mbuf *, struct secpolicyindex *, int));
static void ipsec4_get_ulp __P((struct mbuf *m, struct secpolicyindex *, int));
static int ipsec4_setspidx_ipaddr __P((struct mbuf *, struct secpolicyindex *));
@@ -241,11 +238,7 @@ static int ipsec6_setspidx_ipaddr __P((struct mbuf *, struct secpolicyindex *));
#endif
static void ipsec_delpcbpolicy __P((struct inpcbpolicy *));
static struct secpolicy *ipsec_deepcopy_policy __P((struct secpolicy *src));
-static int ipsec_set_policy __P((struct secpolicy **pcb_sp,
- int optname, caddr_t request, size_t len, struct ucred *cred));
-static int ipsec_get_policy __P((struct secpolicy *pcb_sp, struct mbuf **mp));
static void vshiftl __P((unsigned char *, int, int));
-static size_t ipsec_hdrsiz __P((struct secpolicy *));
MALLOC_DEFINE(M_IPSEC_INPCB, "inpcbpolicy", "inpcb-resident ipsec policy");
@@ -358,7 +351,7 @@ static struct secpolicy *
ipsec_getpolicybysock(struct mbuf *m, u_int dir, struct inpcb *inp, int *error)
{
INIT_VNET_IPSEC(curvnet);
- struct inpcbpolicy *pcbsp = NULL;
+ struct inpcbpolicy *pcbsp;
struct secpolicy *currsp = NULL; /* Policy on socket. */
struct secpolicy *sp;
@@ -369,20 +362,11 @@ ipsec_getpolicybysock(struct mbuf *m, u_int dir, struct inpcb *inp, int *error)
("invalid direction %u", dir));
/* Set spidx in pcb. */
- if (inp->inp_vflag & INP_IPV6PROTO) {
-#ifdef INET6
- *error = ipsec6_setspidx_inpcb(m, inp);
- pcbsp = inp->inp_sp;
-#else
- *error = EINVAL; /* Should not happen. */
-#endif
- } else {
- *error = ipsec4_setspidx_inpcb(m, inp);
- pcbsp = inp->inp_sp;
- }
+ *error = ipsec_setspidx_inpcb(m, inp);
if (*error)
return (NULL);
+ pcbsp = inp->inp_sp;
IPSEC_ASSERT(pcbsp != NULL, ("null pcbsp"));
switch (dir) {
case IPSEC_DIR_INBOUND:
@@ -538,7 +522,7 @@ ipsec4_checkpolicy(struct mbuf *m, u_int dir, u_int flag, int *error,
}
static int
-ipsec4_setspidx_inpcb(struct mbuf *m, struct inpcb *inp)
+ipsec_setspidx_inpcb(struct mbuf *m, struct inpcb *inp)
{
int error;
@@ -561,33 +545,6 @@ ipsec4_setspidx_inpcb(struct mbuf *m, struct inpcb *inp)
return (error);
}
-#ifdef INET6
-static int
-ipsec6_setspidx_inpcb(struct mbuf *m, struct inpcb *inp)
-{
- int error;
-
- IPSEC_ASSERT(inp != NULL, ("null inp"));
- IPSEC_ASSERT(inp->inp_sp != NULL, ("null inp_sp"));
- IPSEC_ASSERT(inp->inp_sp->sp_out != NULL && inp->inp_sp->sp_in != NULL,
- ("null sp_in || sp_out"));
-
- error = ipsec_setspidx(m, &inp->inp_sp->sp_in->spidx, 1);
- if (error == 0) {
- inp->inp_sp->sp_in->spidx.dir = IPSEC_DIR_INBOUND;
- inp->inp_sp->sp_out->spidx = inp->inp_sp->sp_in->spidx;
- inp->inp_sp->sp_out->spidx.dir = IPSEC_DIR_OUTBOUND;
- } else {
- bzero(&inp->inp_sp->sp_in->spidx,
- sizeof(inp->inp_sp->sp_in->spidx));
- bzero(&inp->inp_sp->sp_out->spidx,
- sizeof(inp->inp_sp->sp_in->spidx));
- }
-
- return (error);
-}
-#endif
-
/*
* Configure security policy index (src/dst/proto/sport/dport)
* by looking at the content of mbuf.
@@ -1036,8 +993,8 @@ fail:
/* Set policy and IPsec request if present. */
static int
-ipsec_set_policy(struct secpolicy **pcb_sp, int optname, caddr_t request,
- size_t len, struct ucred *cred)
+ipsec_set_policy_internal(struct secpolicy **pcb_sp, int optname,
+ caddr_t request, size_t len, struct ucred *cred)
{
INIT_VNET_IPSEC(curvnet);
struct sadb_x_policy *xpl;
@@ -1056,7 +1013,7 @@ ipsec_set_policy(struct secpolicy **pcb_sp, int optname, caddr_t request,
kdebug_sadb_x_policy((struct sadb_ext *)xpl));
/* Check policy type. */
- /* ipsec_set_policy() accepts IPSEC, ENTRUST and BYPASS. */
+ /* ipsec_set_policy_internal() accepts IPSEC, ENTRUST and BYPASS. */
if (xpl->sadb_x_policy_type == IPSEC_POLICY_DISCARD
|| xpl->sadb_x_policy_type == IPSEC_POLICY_NONE)
return (EINVAL);
@@ -1084,30 +1041,8 @@ ipsec_set_policy(struct secpolicy **pcb_sp, int optname, caddr_t request,
return (0);
}
-static int
-ipsec_get_policy(struct secpolicy *pcb_sp, struct mbuf **mp)
-{
- INIT_VNET_IPSEC(curvnet);
-
- /* Sanity check. */
- if (pcb_sp == NULL || mp == NULL)
- return (EINVAL);
-
- *mp = key_sp2msg(pcb_sp);
- if (!*mp) {
- ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
- return (ENOBUFS);
- }
-
- (*mp)->m_type = MT_DATA;
- KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
- printf("%s:\n", __func__); kdebug_mbuf(*mp));
-
- return (0);
-}
-
int
-ipsec4_set_policy(struct inpcb *inp, int optname, caddr_t request,
+ipsec_set_policy(struct inpcb *inp, int optname, caddr_t request,
size_t len, struct ucred *cred)
{
INIT_VNET_IPSEC(curvnet);
@@ -1135,11 +1070,11 @@ ipsec4_set_policy(struct inpcb *inp, int optname, caddr_t request,
return (EINVAL);
}
- return (ipsec_set_policy(pcb_sp, optname, request, len, cred));
+ return (ipsec_set_policy_internal(pcb_sp, optname, request, len, cred));
}
int
-ipsec4_get_policy(struct inpcb *inp, caddr_t request, size_t len,
+ipsec_get_policy(struct inpcb *inp, caddr_t request, size_t len,
struct mbuf **mp)
{
INIT_VNET_IPSEC(curvnet);
@@ -1168,7 +1103,21 @@ ipsec4_get_policy(struct inpcb *inp, caddr_t request, size_t len,
return (EINVAL);
}
- return (ipsec_get_policy(pcb_sp, mp));
+ /* Sanity check. Should be an IPSEC_ASSERT. */
+ if (pcb_sp == NULL)
+ return (EINVAL);
+
+ *mp = key_sp2msg(pcb_sp);
+ if (!*mp) {
+ ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
+ return (ENOBUFS);
+ }
+
+ (*mp)->m_type = MT_DATA;
+ KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
+ printf("%s:\n", __func__); kdebug_mbuf(*mp));
+
+ return (0);
}
/* Delete policy in PCB. */
@@ -1192,73 +1141,6 @@ ipsec_delete_pcbpolicy(struct inpcb *inp)
return (0);
}
-#ifdef INET6
-int
-ipsec6_set_policy(struct inpcb *inp, int optname, caddr_t request,
- size_t len, struct ucred *cred)
-{
- INIT_VNET_IPSEC(curvnet);
- struct sadb_x_policy *xpl;
- struct secpolicy **pcb_sp;
-
- /* Sanity check. */
- if (inp == NULL || request == NULL)
- return (EINVAL);
- if (len < sizeof(*xpl))
- return (EINVAL);
- xpl = (struct sadb_x_policy *)request;
-
- /* Select direction. */
- switch (xpl->sadb_x_policy_dir) {
- case IPSEC_DIR_INBOUND:
- pcb_sp = &inp->inp_sp->sp_in;
- break;
- case IPSEC_DIR_OUTBOUND:
- pcb_sp = &inp->inp_sp->sp_out;
- break;
- default:
- ipseclog((LOG_ERR, "%s: invalid direction=%u\n", __func__,
- xpl->sadb_x_policy_dir));
- return (EINVAL);
- }
-
- return (ipsec_set_policy(pcb_sp, optname, request, len, cred));
-}
-
-int
-ipsec6_get_policy(struct inpcb *inp, caddr_t request, size_t len,
- struct mbuf **mp)
-{
- INIT_VNET_IPSEC(curvnet);
- struct sadb_x_policy *xpl;
- struct secpolicy *pcb_sp;
-
- /* Sanity check. */
- if (inp == NULL || request == NULL || mp == NULL)
- return (EINVAL);
- IPSEC_ASSERT(inp->inp_sp != NULL, ("null inp_sp"));
- if (len < sizeof(*xpl))
- return (EINVAL);
- xpl = (struct sadb_x_policy *)request;
-
- /* Select direction. */
- switch (xpl->sadb_x_policy_dir) {
- case IPSEC_DIR_INBOUND:
- pcb_sp = inp->inp_sp->sp_in;
- break;
- case IPSEC_DIR_OUTBOUND:
- pcb_sp = inp->inp_sp->sp_out;
- break;
- default:
- ipseclog((LOG_ERR, "%s: invalid direction=%u\n", __func__,
- xpl->sadb_x_policy_dir));
- return (EINVAL);
- }
-
- return (ipsec_get_policy(pcb_sp, mp));
-}
-#endif
-
/*
* Return current level.
* Either IPSEC_LEVEL_USE or IPSEC_LEVEL_REQUIRE are always returned.
@@ -1437,15 +1319,9 @@ ipsec_in_reject(struct secpolicy *sp, struct mbuf *m)
return (0); /* Valid. */
}
-/*
- * Check AH/ESP integrity.
- * This function is called from tcp_input(), udp_input(),
- * and {ah,esp}4_input for tunnel mode.
- */
-int
-ipsec4_in_reject(struct mbuf *m, struct inpcb *inp)
+static int
+ipsec46_in_reject(struct mbuf *m, struct inpcb *inp)
{
- INIT_VNET_IPSEC(curvnet);
struct secpolicy *sp;
int error;
int result;
@@ -1464,8 +1340,6 @@ ipsec4_in_reject(struct mbuf *m, struct inpcb *inp)
if (sp != NULL) {
result = ipsec_in_reject(sp, m);
- if (result)
- V_ipsec4stat.ips_in_polvio++;
KEY_FREESP(&sp);
} else {
result = 0; /* XXX Should be panic?
@@ -1474,6 +1348,24 @@ ipsec4_in_reject(struct mbuf *m, struct inpcb *inp)
return (result);
}
+/*
+ * Check AH/ESP integrity.
+ * This function is called from tcp_input(), udp_input(),
+ * and {ah,esp}4_input for tunnel mode.
+ */
+int
+ipsec4_in_reject(struct mbuf *m, struct inpcb *inp)
+{
+ INIT_VNET_IPSEC(curvnet);
+ int result;
+
+ result = ipsec46_in_reject(m, inp);
+ if (result)
+ V_ipsec4stat.ips_in_polvio++;
+
+ return (result);
+}
+
#ifdef INET6
/*
* Check AH/ESP integrity.
@@ -1484,31 +1376,12 @@ int
ipsec6_in_reject(struct mbuf *m, struct inpcb *inp)
{
INIT_VNET_IPSEC(curvnet);
- struct secpolicy *sp = NULL;
- int error;
int result;
- /* Sanity check. */
- if (m == NULL)
- return (0); /* XXX Should be panic? */
-
- /* Get SP for this packet.
- * When we are called from ip_forward(), we call
- * ipsec_getpolicybyaddr() with IP_FORWARDING flag.
- */
- if (inp == NULL)
- sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error);
- else
- sp = ipsec_getpolicybysock(m, IPSEC_DIR_INBOUND, inp, &error);
+ result = ipsec46_in_reject(m, inp);
+ if (result)
+ V_ipsec6stat.ips_in_polvio++;
- if (sp != NULL) {
- result = ipsec_in_reject(sp, m);
- if (result)
- V_ipsec6stat.ips_in_polvio++;
- KEY_FREESP(&sp);
- } else {
- result = 0;
- }
return (result);
}
#endif
@@ -1519,7 +1392,7 @@ ipsec6_in_reject(struct mbuf *m, struct inpcb *inp)
* NOTE: SP passed is freed in this function.
*/
static size_t
-ipsec_hdrsiz(struct secpolicy *sp)
+ipsec_hdrsiz_internal(struct secpolicy *sp)
{
INIT_VNET_IPSEC(curvnet);
struct ipsecrequest *isr;
@@ -1577,9 +1450,12 @@ ipsec_hdrsiz(struct secpolicy *sp)
return (size);
}
-/* This function is called from ip_forward() and ipsec4_hdrsize_tcp(). */
+/*
+ * This function is called from ipsec_hdrsiz_tcp(), ip_ipsec_mtu(),
+ * disabled ip6_ipsec_mtu() and ip6_forward().
+ */
size_t
-ipsec4_hdrsiz(struct mbuf *m, u_int dir, struct inpcb *inp)
+ipsec_hdrsiz(struct mbuf *m, u_int dir, struct inpcb *inp)
{
INIT_VNET_IPSEC(curvnet);
struct secpolicy *sp;
@@ -1598,7 +1474,7 @@ ipsec4_hdrsiz(struct mbuf *m, u_int dir, struct inpcb *inp)
sp = ipsec_getpolicybysock(m, dir, inp, &error);
if (sp != NULL) {
- size = ipsec_hdrsiz(sp);
+ size = ipsec_hdrsiz_internal(sp);
KEYDEBUG(KEYDEBUG_IPSEC_DATA,
printf("%s: size:%lu.\n", __func__,
(unsigned long)size));
@@ -1612,40 +1488,6 @@ ipsec4_hdrsiz(struct mbuf *m, u_int dir, struct inpcb *inp)
return (size);
}
-#ifdef INET6
-/* This function is called from ipsec6_hdrsize_tcp(),
- * and maybe from ip6_forward().
- */
-size_t
-ipsec6_hdrsiz(struct mbuf *m, u_int dir, struct inpcb *inp)
-{
- INIT_VNET_IPSEC(curvnet);
- struct secpolicy *sp;
- int error;
- size_t size;
-
- IPSEC_ASSERT(m != NULL, ("null mbuf"));
- IPSEC_ASSERT(inp == NULL || inp->inp_socket != NULL,
- ("socket w/o inpcb"));
-
- /* Get SP for this packet. */
- /* XXX Is it right to call with IP_FORWARDING. */
- if (inp == NULL)
- sp = ipsec_getpolicybyaddr(m, dir, IP_FORWARDING, &error);
- else
- sp = ipsec_getpolicybysock(m, dir, inp, &error);
-
- if (sp == NULL)
- return (0);
- size = ipsec_hdrsiz(sp);
- KEYDEBUG(KEYDEBUG_IPSEC_DATA,
- printf("%s: size:%lu.\n", __func__, (unsigned long)size));
- KEY_FREESP(&sp);
-
- return (size);
-}
-#endif /*INET6*/
-
/*
* Check the variable replay window.
* ipsec_chkreplay() performs replay check before ICV verification.
OpenPOWER on IntegriCloud