void key_setsadbsens(void) { struct sadb_sens m_sens; u_char buf[64]; u_int s, i, slen, ilen, len; /* make sens & integ */ s = htonl(0x01234567); i = htonl(0x89abcdef); slen = sizeof(s); ilen = sizeof(i); memcpy(buf, &s, slen); memcpy(buf + slen, &i, ilen); len = sizeof(m_sens) + PFKEY_ALIGN8(slen) + PFKEY_ALIGN8(ilen); m_sens.sadb_sens_len = PFKEY_UNIT64(len); m_sens.sadb_sens_exttype = SADB_EXT_SENSITIVITY; m_sens.sadb_sens_dpd = 1; m_sens.sadb_sens_sens_level = 2; m_sens.sadb_sens_sens_len = PFKEY_ALIGN8(slen); m_sens.sadb_sens_integ_level = 3; m_sens.sadb_sens_integ_len = PFKEY_ALIGN8(ilen); m_sens.sadb_sens_reserved = 0; key_setsadbextbuf(m_buf, m_len, (caddr_t)&m_sens, sizeof(struct sadb_sens), buf, slen + ilen); m_len += len; }
void key_setsadbprop(void) { struct sadb_prop m_prop; struct sadb_comb *m_comb; u_char buf[256]; u_int len = sizeof(m_prop) + sizeof(m_comb) * 2; /* make prop & comb */ m_prop.sadb_prop_len = PFKEY_UNIT64(len); m_prop.sadb_prop_exttype = SADB_EXT_PROPOSAL; m_prop.sadb_prop_replay = 0; m_prop.sadb_prop_reserved[0] = 0; m_prop.sadb_prop_reserved[1] = 0; m_prop.sadb_prop_reserved[2] = 0; /* the 1st is ESP DES-CBC HMAC-MD5 */ m_comb = (struct sadb_comb *)buf; m_comb->sadb_comb_auth = SADB_AALG_MD5HMAC; m_comb->sadb_comb_encrypt = SADB_EALG_DESCBC; m_comb->sadb_comb_flags = 0; m_comb->sadb_comb_auth_minbits = 8; m_comb->sadb_comb_auth_maxbits = 96; m_comb->sadb_comb_encrypt_minbits = 64; m_comb->sadb_comb_encrypt_maxbits = 64; m_comb->sadb_comb_reserved = 0; m_comb->sadb_comb_soft_allocations = 0; m_comb->sadb_comb_hard_allocations = 0; m_comb->sadb_comb_soft_bytes = 0; m_comb->sadb_comb_hard_bytes = 0; m_comb->sadb_comb_soft_addtime = 0; m_comb->sadb_comb_hard_addtime = 0; m_comb->sadb_comb_soft_usetime = 0; m_comb->sadb_comb_hard_usetime = 0; /* the 2st is ESP 3DES-CBC and AH HMAC-SHA1 */ m_comb = (struct sadb_comb *)(buf + sizeof(*m_comb)); m_comb->sadb_comb_auth = SADB_AALG_SHA1HMAC; m_comb->sadb_comb_encrypt = SADB_EALG_3DESCBC; m_comb->sadb_comb_flags = 0; m_comb->sadb_comb_auth_minbits = 8; m_comb->sadb_comb_auth_maxbits = 96; m_comb->sadb_comb_encrypt_minbits = 64; m_comb->sadb_comb_encrypt_maxbits = 64; m_comb->sadb_comb_reserved = 0; m_comb->sadb_comb_soft_allocations = 0; m_comb->sadb_comb_hard_allocations = 0; m_comb->sadb_comb_soft_bytes = 0; m_comb->sadb_comb_hard_bytes = 0; m_comb->sadb_comb_soft_addtime = 0; m_comb->sadb_comb_hard_addtime = 0; m_comb->sadb_comb_soft_usetime = 0; m_comb->sadb_comb_hard_usetime = 0; key_setsadbextbuf(m_buf, m_len, (caddr_t)&m_prop, sizeof(struct sadb_prop), buf, sizeof(*m_comb) * 2); m_len += len; }
void key_setspirange(void) { struct sadb_spirange m_spi; m_spi.sadb_spirange_len = PFKEY_UNIT64(sizeof(m_spi)); m_spi.sadb_spirange_exttype = SADB_EXT_SPIRANGE; m_spi.sadb_spirange_min = 0x00001000; m_spi.sadb_spirange_max = 0x00002000; m_spi.sadb_spirange_reserved = 0; memcpy(m_buf + m_len, &m_spi, sizeof(struct sadb_spirange)); m_len += sizeof(struct sadb_spirange); }
void key_setsadblft(u_int ext, u_int time) { struct sadb_lifetime m_lft; m_lft.sadb_lifetime_len = PFKEY_UNIT64(sizeof(m_lft)); m_lft.sadb_lifetime_exttype = ext; m_lft.sadb_lifetime_allocations = 0x2; m_lft.sadb_lifetime_bytes = 0x1000; m_lft.sadb_lifetime_addtime = time; m_lft.sadb_lifetime_usetime = 0x0020; memcpy(m_buf + m_len, &m_lft, sizeof(struct sadb_lifetime)); m_len += sizeof(struct sadb_lifetime); }
static void sendkeyshort(u_int type) { struct sadb_msg msg; msg.sadb_msg_version = PF_KEY_V2; msg.sadb_msg_type = type; msg.sadb_msg_errno = 0; msg.sadb_msg_satype = SADB_SATYPE_UNSPEC; msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); msg.sadb_msg_reserved = 0; msg.sadb_msg_seq = 0; msg.sadb_msg_pid = getpid(); sendkeymsg((char *)&msg, sizeof(msg)); }
void key_setsadbaddr(u_int ext, u_int af, caddr_t str) { struct sadb_address m_addr; u_int len; struct addrinfo hints, *res; const char *serv; int plen; switch (af) { case AF_INET: plen = sizeof(struct in_addr) << 3; break; case AF_INET6: plen = sizeof(struct in6_addr) << 3; break; default: /* XXX bark */ exit(1); } /* make sockaddr buffer */ memset(&hints, 0, sizeof(hints)); hints.ai_family = af; hints.ai_socktype = SOCK_DGRAM; /*dummy*/ hints.ai_flags = AI_NUMERICHOST; serv = (ext == SADB_EXT_ADDRESS_PROXY ? "0" : "4660"); /*0x1234*/ if (getaddrinfo(str, serv, &hints, &res) != 0 || res->ai_next) { /* XXX bark */ exit(1); } len = sizeof(struct sadb_address) + PFKEY_ALIGN8(res->ai_addrlen); m_addr.sadb_address_len = PFKEY_UNIT64(len); m_addr.sadb_address_exttype = ext; m_addr.sadb_address_proto = (ext == SADB_EXT_ADDRESS_PROXY ? 0 : IPPROTO_TCP); m_addr.sadb_address_prefixlen = plen; m_addr.sadb_address_reserved = 0; key_setsadbextbuf(m_buf, m_len, (caddr_t)&m_addr, sizeof(struct sadb_address), (caddr_t)res->ai_addr, res->ai_addrlen); m_len += len; freeaddrinfo(res); }
void key_setsadbsa(void) { struct sadb_sa m_sa; m_sa.sadb_sa_len = PFKEY_UNIT64(sizeof(struct sadb_sa)); m_sa.sadb_sa_exttype = SADB_EXT_SA; m_sa.sadb_sa_spi = htonl(0x12345678); m_sa.sadb_sa_replay = 4; m_sa.sadb_sa_state = 0; m_sa.sadb_sa_auth = SADB_AALG_MD5HMAC; m_sa.sadb_sa_encrypt = SADB_EALG_DESCBC; m_sa.sadb_sa_flags = 0; memcpy(m_buf + m_len, &m_sa, sizeof(struct sadb_sa)); m_len += sizeof(struct sadb_sa); }
void key_setsadbkey(u_int ext, caddr_t str) { struct sadb_key m_key; u_int keylen = strlen(str); u_int len; len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen); m_key.sadb_key_len = PFKEY_UNIT64(len); m_key.sadb_key_exttype = ext; m_key.sadb_key_bits = keylen * 8; m_key.sadb_key_reserved = 0; key_setsadbextbuf(m_buf, m_len, (caddr_t)&m_key, sizeof(struct sadb_key), str, keylen); m_len += len; }
void key_setsadbid(u_int ext, caddr_t str) { struct sadb_ident m_id; u_int idlen = strlen(str), len; len = sizeof(m_id) + PFKEY_ALIGN8(idlen); m_id.sadb_ident_len = PFKEY_UNIT64(len); m_id.sadb_ident_exttype = ext; m_id.sadb_ident_type = SADB_IDENTTYPE_USERFQDN; m_id.sadb_ident_reserved = 0; m_id.sadb_ident_id = getpid(); key_setsadbextbuf(m_buf, m_len, (caddr_t)&m_id, sizeof(struct sadb_ident), str, idlen); m_len += len; }
int setsockopt_bypass(int fd, int family) { struct sadb_x_policy policy; int level, optname; switch (family) { case AF_INET: level = IPPROTO_IP; optname = IP_IPSEC_POLICY; break; #ifdef INET6 case AF_INET6: level = IPPROTO_IPV6; optname = IPV6_IPSEC_POLICY; break; #endif default: plog(PLOG_INTERR, PLOGLOC, NULL, "unsupported address family (%d)\n", family); return -1; } memset(&policy, 0, sizeof(policy)); policy.sadb_x_policy_len = PFKEY_UNIT64(sizeof(policy)); policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY; policy.sadb_x_policy_type = IPSEC_POLICY_BYPASS; policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND; if (setsockopt(fd, level, optname, &policy, sizeof(policy)) == -1) { plog(PLOG_INTERR, PLOGLOC, 0, "setsockopt: %s\n", strerror(errno)); return -1; } policy.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND; if (setsockopt(fd, level, optname, &policy, sizeof(policy)) == -1) { plog(PLOG_INTERR, PLOGLOC, 0, "setsockopt: %s\n", strerror(errno)); return -1; } return 0; }
/* * send message to the socket. */ static int key_sendup0(struct rawcb *rp, struct mbuf *m, int promisc, int canwait) { struct keycb *kp = (struct keycb *)rp; struct mbuf *n; int error = 0; if (canwait) { if (kp->kp_queue) { for (n = kp->kp_queue; n && n->m_nextpkt; n = n->m_nextpkt) ; n->m_nextpkt = m; m = kp->kp_queue; kp->kp_queue = NULL; } else m->m_nextpkt = NULL; /* just for safety */ } else m->m_nextpkt = NULL; for (; m && error == 0; m = n) { n = m->m_nextpkt; if (promisc) { struct sadb_msg *pmsg; M_PREPEND(m, sizeof(struct sadb_msg), M_NOWAIT); if (m && m->m_len < sizeof(struct sadb_msg)) m = m_pullup(m, sizeof(struct sadb_msg)); if (!m) { pfkeystat.in_nomem++; error = ENOBUFS; goto recovery; } m->m_pkthdr.len += sizeof(*pmsg); pmsg = mtod(m, struct sadb_msg *); bzero(pmsg, sizeof(*pmsg)); pmsg->sadb_msg_version = PF_KEY_V2; pmsg->sadb_msg_type = SADB_X_PROMISC; pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); /* pid and seq? */ pfkeystat.in_msgtype[pmsg->sadb_msg_type]++; } if (canwait && sbspace(&rp->rcb_socket->so_rcv) < m->m_pkthdr.len) { error = EAGAIN; goto recovery; } m->m_nextpkt = NULL; if (!sbappendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src, m, NULL)) { pfkeystat.in_nomem++; error = ENOBUFS; goto recovery; } else { sorwakeup(rp->rcb_socket); error = 0; } } return (error); recovery: if (kp->kp_queue) { /* * insert m to the head of queue, as normally mbuf on the queue * is less important than others. */ if (m) { m->m_nextpkt = kp->kp_queue; kp->kp_queue = m; } } else { /* recover the queue */ if (!m) { /* first ENOBUFS case */ kp->kp_queue = n; } else { kp->kp_queue = m; m->m_nextpkt = n; } } return (error); }
void key_setsadbmsg(u_int type) { struct sadb_msg m_msg; memset(&m_msg, 0, sizeof(m_msg)); m_msg.sadb_msg_version = PF_KEY_V2; m_msg.sadb_msg_type = type; m_msg.sadb_msg_errno = 0; m_msg.sadb_msg_satype = SADB_SATYPE_ESP; #if 0 m_msg.sadb_msg_reserved = 0; #endif m_msg.sadb_msg_seq = 0; m_msg.sadb_msg_pid = getpid(); m_len = sizeof(struct sadb_msg); memcpy(m_buf, &m_msg, m_len); switch (type) { case SADB_GETSPI: /*<base, address(SD), SPI range>*/ key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "10.0.3.4"); key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "127.0.0.1"); key_setspirange(); /*<base, SA(*), address(SD)>*/ break; case SADB_ADD: /* <base, SA, (lifetime(HSC),) address(SD), (address(P),) key(AE), (identity(SD),) (sensitivity)> */ key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1"); case SADB_UPDATE: key_setsadbsa(); key_setsadblft(SADB_EXT_LIFETIME_HARD, 10); key_setsadblft(SADB_EXT_LIFETIME_SOFT, 5); key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1"); key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4"); /* XXX key_setsadbkey(SADB_EXT_KEY_AUTH, "abcde"); */ key_setsadbkey(SADB_EXT_KEY_AUTH, "1234567812345678"); key_setsadbkey(SADB_EXT_KEY_ENCRYPT, "12345678"); key_setsadbid(SADB_EXT_IDENTITY_SRC, "*****@*****.**"); key_setsadbid(SADB_EXT_IDENTITY_DST, "*****@*****.**"); key_setsadbsens(); /* <base, SA, (lifetime(HSC),) address(SD), (address(P),) (identity(SD),) (sensitivity)> */ break; case SADB_DELETE: /* <base, SA(*), address(SDP)> */ key_setsadbsa(); key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1"); key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4"); key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1"); /* <base, SA(*), address(SDP)> */ break; case SADB_GET: /* <base, SA(*), address(SDP)> */ key_setsadbsa(); key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1"); key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4"); key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1"); /* <base, SA, (lifetime(HSC),) address(SD), (address(P),) key(AE), (identity(SD),) (sensitivity)> */ break; case SADB_ACQUIRE: /* <base, address(SD), (address(P),) (identity(SD),) (sensitivity,) proposal> */ key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1"); key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4"); key_setsadbaddr(SADB_EXT_ADDRESS_PROXY, AF_INET6, "3ffe::1"); key_setsadbid(SADB_EXT_IDENTITY_SRC, "*****@*****.**"); key_setsadbid(SADB_EXT_IDENTITY_DST, "*****@*****.**"); key_setsadbsens(); key_setsadbprop(); /* <base, address(SD), (address(P),) (identity(SD),) (sensitivity,) proposal> */ break; case SADB_REGISTER: /* <base> */ /* <base, supported> */ break; case SADB_EXPIRE: case SADB_FLUSH: break; case SADB_DUMP: break; case SADB_X_PROMISC: /* <base> */ /* <base, base(, others)> */ break; case SADB_X_PCHANGE: break; /* for SPD management */ case SADB_X_SPDFLUSH: case SADB_X_SPDDUMP: break; case SADB_X_SPDADD: #if 0 { struct sadb_x_policy m_policy; m_policy.sadb_x_policy_len = PFKEY_UNIT64(sizeof(m_policy)); m_policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY; m_policy.sadb_x_policy_type = SADB_X_PL_IPSEC; m_policy.sadb_x_policy_esp_trans = 1; m_policy.sadb_x_policy_ah_trans = 2; m_policy.sadb_x_policy_esp_network = 3; m_policy.sadb_x_policy_ah_network = 4; m_policy.sadb_x_policy_reserved = 0; memcpy(m_buf + m_len, &m_policy, sizeof(struct sadb_x_policy)); m_len += sizeof(struct sadb_x_policy); } #endif case SADB_X_SPDDELETE: key_setsadbaddr(SADB_EXT_ADDRESS_SRC, AF_INET, "192.168.1.1"); key_setsadbaddr(SADB_EXT_ADDRESS_DST, AF_INET, "10.0.3.4"); break; } ((struct sadb_msg *)m_buf)->sadb_msg_len = PFKEY_UNIT64(m_len); }
/* * Generate 'spi' array with SPIs matching 'satype', 'srcs', and 'dsts'. * Return value is dynamically generated array of SPIs, also number of * SPIs through num_spi pointer. * On any error, set *num_spi to 0 and return NULL. */ uint32_t * sendkeymsg_spigrep(unsigned int satype, struct addrinfo *srcs, struct addrinfo *dsts, int *num_spi) { struct sadb_msg msg, *m; char *buf; size_t len; ssize_t l; u_char rbuf[1024 * 32]; caddr_t mhp[SADB_EXT_MAX + 1]; struct sadb_address *saddr; struct sockaddr *s; struct addrinfo *a; struct sadb_sa *sa; uint32_t *spi = NULL; int max_spi = 0, fail = 0; *num_spi = 0; if (f_notreally) { return NULL; } { struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 0; if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { perror("setsockopt"); return NULL; } } msg.sadb_msg_version = PF_KEY_V2; msg.sadb_msg_type = SADB_DUMP; msg.sadb_msg_errno = 0; msg.sadb_msg_satype = satype; msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); msg.sadb_msg_reserved = 0; msg.sadb_msg_seq = 0; msg.sadb_msg_pid = getpid(); buf = (char *)&msg; len = sizeof(msg); if (f_verbose) { kdebug_sadb(&msg); printf("\n"); } if (f_hexdump) { int i; for (i = 0; i < len; i++) { if (i % 16 == 0) printf("%08x: ", i); printf("%02x ", buf[i] & 0xff); if (i % 16 == 15) printf("\n"); } if (len % 16) printf("\n"); } if ((l = send(so, buf, len, 0)) < 0) { perror("send"); return NULL; } m = (struct sadb_msg *)rbuf; do { if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) { perror("recv"); fail = 1; break; } if (PFKEY_UNUNIT64(m->sadb_msg_len) != l) { warnx("invalid keymsg length"); fail = 1; break; } if (f_verbose) { kdebug_sadb(m); printf("\n"); } if (m->sadb_msg_type != SADB_DUMP) { warnx("unexpected message type"); fail = 1; break; } if (m->sadb_msg_errno != 0) { warnx("error encountered"); fail = 1; break; } /* match satype */ if (m->sadb_msg_satype != satype) continue; pfkey_align(m, mhp); pfkey_check(mhp); /* match src */ saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; if (saddr == NULL) continue; s = (struct sockaddr *)(saddr + 1); for (a = srcs; a; a = a->ai_next) if (memcmp(a->ai_addr, s, a->ai_addrlen) == 0) break; if (a == NULL) continue; /* match dst */ saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; if (saddr == NULL) continue; s = (struct sockaddr *)(saddr + 1); for (a = dsts; a; a = a->ai_next) if (memcmp(a->ai_addr, s, a->ai_addrlen) == 0) break; if (a == NULL) continue; if (*num_spi >= max_spi) { max_spi += 512; spi = realloc(spi, max_spi * sizeof(uint32_t)); } sa = (struct sadb_sa *)mhp[SADB_EXT_SA]; if (sa != NULL) spi[(*num_spi)++] = (uint32_t)ntohl(sa->sadb_sa_spi); m = (struct sadb_msg *)((caddr_t)m + PFKEY_UNUNIT64(m->sadb_msg_len)); if (f_verbose) { kdebug_sadb(m); printf("\n"); } } while (m->sadb_msg_seq); if (fail) { free(spi); *num_spi = 0; return NULL; } return spi; }
static void __dead promisc(void) { struct sadb_msg msg; u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ ssize_t l; msg.sadb_msg_version = PF_KEY_V2; msg.sadb_msg_type = SADB_X_PROMISC; msg.sadb_msg_errno = 0; msg.sadb_msg_satype = 1; msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); msg.sadb_msg_reserved = 0; msg.sadb_msg_seq = 0; msg.sadb_msg_pid = getpid(); if ((l = send(so, &msg, sizeof(msg), 0)) < 0) { err(1, "send"); } while (1) { struct sadb_msg *base; if ((l = recv(so, rbuf, sizeof(*base), MSG_PEEK)) < 0) { err(1, "recv"); } if (l != sizeof(*base)) continue; base = (struct sadb_msg *)rbuf; if ((l = recv(so, rbuf, PFKEY_UNUNIT64(base->sadb_msg_len), 0)) < 0) { err(1, "recv"); } printdate(); if (f_hexdump) { int i; for (i = 0; i < l; i++) { if (i % 16 == 0) printf("%08x: ", i); printf("%02x ", rbuf[i] & 0xff); if (i % 16 == 15) printf("\n"); } if (l % 16) printf("\n"); } /* adjust base pointer for promisc mode */ if (base->sadb_msg_type == SADB_X_PROMISC) { if ((ssize_t)sizeof(*base) < l) base++; else base = NULL; } if (base) { kdebug_sadb(base); printf("\n"); fflush(stdout); } } }
// This function fills in policy0 and policylen0 according to the given parameters // The full implementation can be found in racoon // direction IPSEC_DIR_INBOUND | IPSEC_DIR_OUTBOUND int getsadbpolicy(caddr_t *policy0, int *policylen0, int direction, struct sockaddr *src, struct sockaddr *dst, u_int mode, int cmd) { struct sadb_x_policy *xpl; struct sadb_x_ipsecrequest *xisr; struct saproto *pr; caddr_t policy, p; int policylen; int xisrlen, src_len, dst_len; u_int satype; HIP_DEBUG("\n"); /* get policy buffer size */ policylen = sizeof(struct sadb_x_policy); if (cmd != SADB_X_SPDDELETE) { xisrlen = sizeof(*xisr); xisrlen += (sysdep_sa_len(src) + sysdep_sa_len(dst)); policylen += PFKEY_ALIGN8(xisrlen); } /* make policy structure */ policy = malloc(policylen); if (!policy) { HIP_ERROR("Cannot allocate memory for policy\n"); return -ENOMEM; } xpl = (struct sadb_x_policy *)policy; xpl->sadb_x_policy_len = PFKEY_UNIT64(policylen); xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY; xpl->sadb_x_policy_type = IPSEC_POLICY_IPSEC; xpl->sadb_x_policy_dir = direction; xpl->sadb_x_policy_id = 0; //xpl->sadb_x_policy_priority = PRIORITY_DEFAULT; if (cmd == SADB_X_SPDDELETE) goto end; xisr = (struct sadb_x_ipsecrequest *)(xpl + 1); xisr->sadb_x_ipsecrequest_proto = SADB_SATYPE_ESP; xisr->sadb_x_ipsecrequest_mode = mode; xisr->sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE; xisr->sadb_x_ipsecrequest_reqid = 0; p = (caddr_t)(xisr + 1); xisrlen = sizeof(*xisr); src_len = sysdep_sa_len(src); dst_len = sysdep_sa_len(dst); xisrlen += src_len + dst_len; memcpy(p, src, src_len); p += src_len; memcpy(p, dst, dst_len); p += dst_len; xisr->sadb_x_ipsecrequest_len = PFKEY_ALIGN8(xisrlen); end: *policy0 = policy; *policylen0 = policylen; return 0; }