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?
This commit is contained in:
Bjoern A. Zeeb 2009-02-08 09:27:07 +00:00
parent 0bc4c01d56
commit 97aa4a517a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=188306
9 changed files with 68 additions and 238 deletions

View File

@ -218,9 +218,7 @@ ip_ipsec_mtu(struct mbuf *m, int mtu)
&ipsecerror);
if (sp != NULL) {
/* count IPsec header size */
ipsechdr = ipsec4_hdrsiz(m,
IPSEC_DIR_OUTBOUND,
NULL);
ipsechdr = ipsec_hdrsiz(m, IPSEC_DIR_OUTBOUND, NULL);
/*
* find the correct route for outer IPv4

View File

@ -1050,7 +1050,7 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */
break;
req = mtod(m, caddr_t);
error = ipsec4_set_policy(inp, sopt->sopt_name, req,
error = ipsec_set_policy(inp, sopt->sopt_name, req,
m->m_len, (sopt->sopt_td != NULL) ?
sopt->sopt_td->td_ucred : NULL);
m_freem(m);
@ -1171,7 +1171,7 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
req = mtod(m, caddr_t);
len = m->m_len;
}
error = ipsec4_get_policy(sotoinpcb(so), req, len, &m);
error = ipsec_get_policy(sotoinpcb(so), req, len, &m);
if (error == 0)
error = soopt_mcopyout(sopt, m); /* XXX */
if (error == 0)

View File

@ -1744,7 +1744,7 @@ ipsec_hdrsiz_tcp(struct tcpcb *tp)
m->m_pkthdr.len = m->m_len =
sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
tcpip_fillheaders(inp, ip6, th);
hdrsiz = ipsec6_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp);
hdrsiz = ipsec_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp);
} else
#endif /* INET6 */
{
@ -1752,7 +1752,7 @@ ipsec_hdrsiz_tcp(struct tcpcb *tp)
th = (struct tcphdr *)(ip + 1);
m->m_pkthdr.len = m->m_len = sizeof(struct tcpiphdr);
tcpip_fillheaders(inp, ip, th);
hdrsiz = ipsec4_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp);
hdrsiz = ipsec_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp);
}
m_free(m);

View File

@ -457,7 +457,7 @@ ip6_forward(struct mbuf *m, int srcrt)
sp = ipsec_getpolicybyaddr(mcopy, IPSEC_DIR_OUTBOUND,
IP_FORWARDING, &ipsecerror);
if (sp) {
ipsechdrsiz = ipsec6_hdrsiz(mcopy,
ipsechdrsiz = ipsec_hdrsiz(mcopy,
IPSEC_DIR_OUTBOUND, NULL);
if (ipsechdrsiz < mtu)
mtu -= ipsechdrsiz;

View File

@ -341,9 +341,7 @@ ip6_ipsec_mtu(struct mbuf *m)
&ipsecerror);
if (sp != NULL) {
/* count IPsec header size */
ipsechdr = ipsec4_hdrsiz(m,
IPSEC_DIR_OUTBOUND,
NULL);
ipsechdr = ipsec_hdrsiz(m, IPSEC_DIR_OUTBOUND, NULL);
/*
* find the correct route for outer IPv4

View File

@ -1799,7 +1799,7 @@ do { \
if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */
break;
req = mtod(m, caddr_t);
error = ipsec6_set_policy(in6p, optname, req,
error = ipsec_set_policy(in6p, optname, req,
m->m_len, (sopt->sopt_td != NULL) ?
sopt->sopt_td->td_ucred : NULL);
m_freem(m);
@ -2024,7 +2024,7 @@ do { \
req = mtod(m, caddr_t);
len = m->m_len;
}
error = ipsec6_get_policy(in6p, req, len, mp);
error = ipsec_get_policy(in6p, req, len, mp);
if (error == 0)
error = soopt_mcopyout(sopt, m); /* XXX */
if (error == 0 && m)

View File

@ -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 @@ ipsec_deepcopy_policy(struct secpolicy *src)
/* 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? */
result = ipsec46_in_reject(m, inp);
if (result)
V_ipsec6stat.ips_in_polvio++;
/* 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);
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.

View File

@ -374,9 +374,9 @@ extern int ipsec_copy_policy
extern u_int ipsec_get_reqlevel __P((struct ipsecrequest *));
extern int ipsec_in_reject __P((struct secpolicy *, struct mbuf *));
extern int ipsec4_set_policy __P((struct inpcb *inp, int optname,
extern int ipsec_set_policy __P((struct inpcb *inp, int optname,
caddr_t request, size_t len, struct ucred *cred));
extern int ipsec4_get_policy __P((struct inpcb *inpcb, caddr_t request,
extern int ipsec_get_policy __P((struct inpcb *inpcb, caddr_t request,
size_t len, struct mbuf **mp));
extern int ipsec_delete_pcbpolicy __P((struct inpcb *));
extern int ipsec4_in_reject __P((struct mbuf *, struct inpcb *));
@ -386,7 +386,7 @@ struct tcpcb;
extern int ipsec_chkreplay __P((u_int32_t, struct secasvar *));
extern int ipsec_updatereplay __P((u_int32_t, struct secasvar *));
extern size_t ipsec4_hdrsiz __P((struct mbuf *, u_int, struct inpcb *));
extern size_t ipsec_hdrsiz __P((struct mbuf *, u_int, struct inpcb *));
extern size_t ipsec_hdrsiz_tcp __P((struct tcpcb *));
union sockaddr_union;

View File

@ -50,16 +50,8 @@ extern int ip6_ipsec_ecn;
struct inpcb;
extern int ipsec6_set_policy __P((struct inpcb *inp, int optname,
caddr_t request, size_t len, struct ucred *cred));
extern int ipsec6_get_policy
__P((struct inpcb *inp, caddr_t request, size_t len, struct mbuf **mp));
extern int ipsec6_in_reject __P((struct mbuf *, struct inpcb *));
struct tcp6cb;
extern size_t ipsec6_hdrsiz __P((struct mbuf *, u_int, struct inpcb *));
struct ip6_hdr;
extern const char *ipsec6_logpacketstr __P((struct ip6_hdr *, u_int32_t));