/* * read_pfkey_msg: * * Get a PF_KEY message from the socket using the global file descriptor * 'keysock'. Data is stored in the global buffer 'msg_buf'. The function * returns a pointer to the next PF_KEY message. Note that this is not * necessarily at the start of 'msg_buf'. NULL is returned for errors. */ static struct sadb_msg * read_pfkey_msg(void) { static uint64_t *offset; static int len; struct sadb_msg *retval; /* Assume offset and len are initialized to NULL and 0 */ if ((offset == NULL) || (offset - len == msg_buf)) { /* read a new block from the socket. */ len = read(keysock, &msg_buf, sizeof (msg_buf)); if (len == -1) { sckmd_log(LOG_ERR, "PF_KEY read: %s\n", strerror(errno)); offset = NULL; return (NULL); } offset = msg_buf; len = SADB_8TO64(len); } retval = (struct sadb_msg *)offset; offset += retval->sadb_msg_len; if (offset > msg_buf + len) { sckmd_log(LOG_ERR, "PF_KEY read: message corruption, " "message length %d exceeds boundary %d\n", SADB_64TO8(retval->sadb_msg_len), SADB_64TO8((msg_buf + len) - (uint64_t *)retval)); offset = NULL; return (NULL); } return (retval); }
/* ARGSUSED */ int main(int argc, char *argv[]) { int s, rc; uint64_t buf[1024]; /* PF_KEY likes 64-bit alignment. */ sadb_msg_t *samsg; sadb_x_ereg_t *ereg; boolean_t ah_ack, esp_ack; pid_t pid = getpid(); s = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); if (s == -1) err(-1, "socket(PF_KEY)"); /* Base message. */ samsg = (sadb_msg_t *)buf; ereg = (sadb_x_ereg_t *)(samsg + 1); samsg->sadb_msg_version = PF_KEY_V2; samsg->sadb_msg_type = SADB_REGISTER; samsg->sadb_msg_errno = 0; samsg->sadb_msg_satype = SADB_SATYPE_UNSPEC; samsg->sadb_msg_reserved = 0; samsg->sadb_msg_seq = 1; samsg->sadb_msg_pid = pid; samsg->sadb_msg_len = SADB_8TO64(sizeof (*samsg) + sizeof (*ereg)); /* extended REGISTER so we can listen for extended ACQUIREs. */ ereg->sadb_x_ereg_len = SADB_8TO64(sizeof (*ereg)); ereg->sadb_x_ereg_exttype = SADB_X_EXT_EREG; ereg->sadb_x_ereg_satypes[0] = SADB_SATYPE_ESP; ereg->sadb_x_ereg_satypes[1] = SADB_SATYPE_AH; ereg->sadb_x_ereg_satypes[2] = SADB_SATYPE_UNSPEC; rc = write(s, buf, sizeof (*samsg) + sizeof (*ereg)); if (rc == -1) err(-1, "Extended register write error"); /* * Extended REGISTER expects a regular REGISTER reply for EACH protocol * requested. In our case, AH and ESP. */ do { do { rc = read(s, buf, sizeof (buf)); if (rc == -1) err(-1, "Extended register read error"); } while (samsg->sadb_msg_seq != 1 || samsg->sadb_msg_pid != pid || samsg->sadb_msg_type != SADB_REGISTER); if (samsg->sadb_msg_errno != 0) { if (samsg->sadb_msg_errno == EPROTONOSUPPORT) { warn("Protocol %d not supported.", samsg->sadb_msg_satype); } else { errno = samsg->sadb_msg_errno; err(-1, "Extended REGISTER returned"); } } switch (samsg->sadb_msg_satype) { case SADB_SATYPE_ESP: esp_ack = B_TRUE; break; case SADB_SATYPE_AH: ah_ack = B_TRUE; break; default: err(-1, "Bad satype in extended register ACK %d.", samsg->sadb_msg_satype); } } while (!esp_ack || !ah_ack); /* Expect this loop to never end. This program ends via signal. */ do { rc = read(s, buf, sizeof (buf)); } while (rc != -1); err(-1, "PF_KEY read error"); }