📄 pfkey.c
字号:
u_int32_t seq;
{
int len;
if (policylen != sizeof(struct sadb_x_policy)) {
__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
return -1;
}
if ((len = pfkey_send_x4(so, SADB_X_SPDSETIDX,
src, prefs, dst, prefd, proto,
0, 0,
policy, policylen, seq)) < 0)
return -1;
return len;
}
/*
* sending SADB_SPDFLUSH message to the kernel.
* OUT:
* positive: success and return length sent.
* -1 : error occured, and set errno.
*/
int
pfkey_send_spdflush(so)
int so;
{
int len;
if ((len = pfkey_send_x3(so, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC)) < 0)
return -1;
return len;
}
/*
* sending SADB_SPDDUMP message to the kernel.
* OUT:
* positive: success and return length sent.
* -1 : error occured, and set errno.
*/
int
pfkey_send_spddump(so)
int so;
{
int len;
if ((len = pfkey_send_x3(so, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC)) < 0)
return -1;
return len;
}
/* sending SADB_ADD or SADB_UPDATE message to the kernel */
static int
pfkey_send_x1(so, type, satype, mode, src, dst, spi, reqid, wsize,
keymat, e_type, e_keylen, a_type, a_keylen, flags,
l_alloc, l_bytes, l_addtime, l_usetime, seq)
int so;
u_int type, satype, mode;
struct sockaddr *src, *dst;
u_int32_t spi, reqid;
u_int wsize;
caddr_t keymat;
u_int e_type, e_keylen, a_type, a_keylen, flags;
u_int32_t l_alloc, l_bytes, l_addtime, l_usetime, seq;
{
struct sadb_msg *newmsg;
int len;
caddr_t p;
int plen;
caddr_t ep;
/* validity check */
if (src == NULL || dst == NULL) {
__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
return -1;
}
if (src->sa_family != dst->sa_family) {
__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
return -1;
}
switch (src->sa_family) {
case AF_INET:
plen = sizeof(struct in_addr) << 3;
break;
case AF_INET6:
plen = sizeof(struct in6_addr) << 3;
break;
default:
__ipsec_errcode = EIPSEC_INVAL_FAMILY;
return -1;
}
switch (satype) {
case SADB_SATYPE_ESP:
if (e_type == SADB_EALG_NONE) {
__ipsec_errcode = EIPSEC_NO_ALGS;
return -1;
}
break;
case SADB_SATYPE_AH:
if (e_type != SADB_EALG_NONE) {
__ipsec_errcode = EIPSEC_INVAL_ALGS;
return -1;
}
if (a_type == SADB_AALG_NONE) {
__ipsec_errcode = EIPSEC_NO_ALGS;
return -1;
}
break;
case SADB_X_SATYPE_IPCOMP:
if (e_type == SADB_X_CALG_NONE) {
__ipsec_errcode = EIPSEC_INVAL_ALGS;
return -1;
}
if (a_type != SADB_AALG_NONE) {
__ipsec_errcode = EIPSEC_NO_ALGS;
return -1;
}
break;
default:
__ipsec_errcode = EIPSEC_INVAL_SATYPE;
return -1;
}
/* create new sadb_msg to reply. */
len = sizeof(struct sadb_msg)
+ sizeof(struct sadb_sa)
+ sizeof(struct sadb_x_sa2)
+ sizeof(struct sadb_address)
+ PFKEY_ALIGN8(src->sa_len)
+ sizeof(struct sadb_address)
+ PFKEY_ALIGN8(dst->sa_len)
+ sizeof(struct sadb_lifetime)
+ sizeof(struct sadb_lifetime);
if (e_type != SADB_EALG_NONE)
len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(e_keylen));
if (a_type != SADB_AALG_NONE)
len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(a_keylen));
if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
__ipsec_set_strerror(strerror(errno));
return -1;
}
ep = ((caddr_t)newmsg) + len;
p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len,
satype, seq, getpid());
if (!p) {
free(newmsg);
return -1;
}
p = pfkey_setsadbsa(p, ep, spi, wsize, a_type, e_type, flags);
if (!p) {
free(newmsg);
return -1;
}
p = pfkey_setsadbxsa2(p, ep, mode, reqid);
if (!p) {
free(newmsg);
return -1;
}
p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen,
IPSEC_ULPROTO_ANY);
if (!p) {
free(newmsg);
return -1;
}
p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen,
IPSEC_ULPROTO_ANY);
if (!p) {
free(newmsg);
return -1;
}
if (e_type != SADB_EALG_NONE) {
p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_ENCRYPT,
keymat, e_keylen);
if (!p) {
free(newmsg);
return -1;
}
}
if (a_type != SADB_AALG_NONE) {
p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_AUTH,
keymat + e_keylen, a_keylen);
if (!p) {
free(newmsg);
return -1;
}
}
/* set sadb_lifetime for destination */
p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD,
l_alloc, l_bytes, l_addtime, l_usetime);
if (!p) {
free(newmsg);
return -1;
}
p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_SOFT,
l_alloc, l_bytes, l_addtime, l_usetime);
if (!p || p != ep) {
free(newmsg);
return -1;
}
/* send message */
len = pfkey_send(so, newmsg, len);
free(newmsg);
if (len < 0)
return -1;
__ipsec_errcode = EIPSEC_NO_ERROR;
return len;
}
/* sending SADB_DELETE or SADB_GET message to the kernel */
static int
pfkey_send_x2(so, type, satype, mode, src, dst, spi)
int so;
u_int type, satype, mode;
struct sockaddr *src, *dst;
u_int32_t spi;
{
struct sadb_msg *newmsg;
int len;
caddr_t p;
int plen;
caddr_t ep;
/* validity check */
if (src == NULL || dst == NULL) {
__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
return -1;
}
if (src->sa_family != dst->sa_family) {
__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
return -1;
}
switch (src->sa_family) {
case AF_INET:
plen = sizeof(struct in_addr) << 3;
break;
case AF_INET6:
plen = sizeof(struct in6_addr) << 3;
break;
default:
__ipsec_errcode = EIPSEC_INVAL_FAMILY;
return -1;
}
/* create new sadb_msg to reply. */
len = sizeof(struct sadb_msg)
+ sizeof(struct sadb_sa)
+ sizeof(struct sadb_address)
+ PFKEY_ALIGN8(src->sa_len)
+ sizeof(struct sadb_address)
+ PFKEY_ALIGN8(dst->sa_len);
if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
__ipsec_set_strerror(strerror(errno));
return -1;
}
ep = ((caddr_t)newmsg) + len;
p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0,
getpid());
if (!p) {
free(newmsg);
return -1;
}
p = pfkey_setsadbsa(p, ep, spi, 0, 0, 0, 0);
if (!p) {
free(newmsg);
return -1;
}
p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen,
IPSEC_ULPROTO_ANY);
if (!p) {
free(newmsg);
return -1;
}
p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen,
IPSEC_ULPROTO_ANY);
if (!p || p != ep) {
free(newmsg);
return -1;
}
/* send message */
len = pfkey_send(so, newmsg, len);
free(newmsg);
if (len < 0)
return -1;
__ipsec_errcode = EIPSEC_NO_ERROR;
return len;
}
/*
* sending SADB_REGISTER, SADB_FLUSH, SADB_DUMP or SADB_X_PROMISC message
* to the kernel
*/
static int
pfkey_send_x3(so, type, satype)
int so;
u_int type, satype;
{
struct sadb_msg *newmsg;
int len;
caddr_t p;
caddr_t ep;
/* validity check */
switch (type) {
case SADB_X_PROMISC:
if (satype != 0 && satype != 1) {
__ipsec_errcode = EIPSEC_INVAL_SATYPE;
return -1;
}
break;
default:
switch (satype) {
case SADB_SATYPE_UNSPEC:
case SADB_SATYPE_AH:
case SADB_SATYPE_ESP:
case SADB_X_SATYPE_IPCOMP:
break;
default:
__ipsec_errcode = EIPSEC_INVAL_SATYPE;
return -1;
}
}
/* create new sadb_msg to send. */
len = sizeof(struct sadb_msg);
if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
__ipsec_set_strerror(strerror(errno));
return -1;
}
ep = ((caddr_t)newmsg) + len;
p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0,
getpid());
if (!p || p != ep) {
free(newmsg);
return -1;
}
/* send message */
len = pfkey_send(so, newmsg, len);
free(newmsg);
if (len < 0)
return -1;
__ipsec_errcode = EIPSEC_NO_ERROR;
return len;
}
/* sending SADB_X_SPDADD message to the kernel */
static int
pfkey_send_x4(so, type, src, prefs, dst, prefd, proto,
ltime, vtime, policy, policylen, seq)
int so;
struct sockaddr *src, *dst;
u_int type, prefs, prefd, proto;
u_int64_t ltime, vtime;
char *policy;
int policylen;
u_int32_t seq;
{
struct sadb_msg *newmsg;
int len;
caddr_t p;
int plen;
caddr_t ep;
/* validity check */
if (src == NULL || dst == NULL) {
__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
return -1;
}
if (src->sa_family != dst->sa_family) {
__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
return -1;
}
switch (src->sa_family) {
case AF_INET:
plen = sizeof(struct in_addr) << 3;
break;
case AF_INET6:
plen = sizeof(struct in6_addr) << 3;
break;
default:
__ipsec_errcode = EIPSEC_INVAL_FAMILY;
return -1;
}
if (prefs > plen || prefd > plen) {
__ipsec_errcode = EIPSEC_INVAL_PREFIXLEN;
return -1;
}
/* create new sadb_msg to reply. */
len = sizeof(struct sadb_msg)
+ sizeof(struct sadb_address)
+ PFKEY_ALIGN8(src->sa_len)
+ sizeof(struct sadb_address)
+ PFKEY_ALIGN8(src->sa_len)
+ sizeof(struct sadb_lifetime)
+ policylen;
if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
__ipsec_set_strerror(strerror(errno));
return -1;
}
ep = ((caddr_t)newmsg) + len;
p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len,
SADB_SATYPE_UNSPEC, seq, getpid());
if (!p) {
free(newmsg);
return -1;
}
p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto);
if (!p) {
free(newmsg);
return -1;
}
p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto);
if (!p) {
free(newmsg);
return -1;
}
p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD,
0, 0, ltime, vtime);
if (!p || p + policylen != ep) {
free(newmsg);
return -1;
}
memcpy(p, policy, policylen);
/* send message */
len = pfkey_send(so, newmsg, len);
free(newmsg);
if (len < 0)
return -1;
__ipsec_errcode = EIPSEC_NO_ERROR;
return len;
}
/* sending SADB_X_SPDGET or SADB_X_SPDDELETE message to the kernel */
static int
pfkey_send_x5(so, type, spid)
int so;
u_int type;
u_int32_t spid;
{
struct sadb_msg *newmsg;
struct sadb_x_policy xpl;
int len;
caddr_t p;
caddr_t ep;
/* create new sadb_msg to reply. */
len = sizeof(struct sadb_msg)
+ sizeof(xpl);
if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
__ipsec_set_strerror(strerror(errno));
return -1;
}
ep = ((caddr_t)newmsg) + len;
p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len,
SADB_SATYPE_UNSPEC, 0, getpid());
if (!p) {
free(newmsg);
return -1;
}
if (p + sizeof(xpl) != ep) {
free(newmsg);
return -1;
}
memset(&xpl, 0, sizeof(xpl));
xpl.sadb_x_policy_len = PFKEY_UNIT64(sizeof(xpl));
xpl.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
xpl.sadb_x_policy_id = spid;
memcpy(p, &xpl, sizeof(xpl));
/* send message */
len = pfkey_send(so, newmsg, len);
free(newmsg);
if (len < 0)
return -1;
__ipsec_errcode = EIPSEC_NO_ERROR;
return len;
}
/*
* open a socket.
* OUT:
* -1: fail.
* others : success and return value of socket.
*/
int
pfkey_open()
{
int so;
const int bufsiz = 128 * 1024; /*is 128K enough?*/
if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
__ipsec_set_strerror(strerror(errno));
return -1;
}
/*
* This is a temporary workaround for KAME PR 154.
* Don't really care even if it fails.
*/
(void)setsockopt(so, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz));
(void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -