+int
+pk_sendget_inbound_sastats(ike_session_t *session)
+{
+ u_int32_t max_stats;
+ u_int32_t seq;
+
+ if (!session) {
+ plog(ASL_LEVEL_DEBUG, "invalid args in %s \n", __FUNCTION__);
+ return -1;
+ }
+
+ session->traffic_monitor.num_in_curr_req = 0;
+ bzero(session->traffic_monitor.in_curr_req, sizeof(session->traffic_monitor.in_curr_req));
+ max_stats = (sizeof(session->traffic_monitor.in_curr_req) / sizeof(session->traffic_monitor.in_curr_req[0]));
+
+ // get list of SAs
+ if ((session->traffic_monitor.num_in_curr_req = ike_session_get_sas_for_stats(session,
+ IPSEC_DIR_INBOUND,
+ &seq,
+ session->traffic_monitor.in_curr_req,
+ max_stats))) {
+ u_int64_t session_ids[] = {(u_int64_t)session, 0};
+
+ //plog(ASL_LEVEL_DEBUG, "about to call %s\n", __FUNCTION__);
+
+ if (pfkey_send_getsastats(lcconf->sock_pfkey,
+ seq,
+ session_ids,
+ 1,
+ IPSEC_DIR_INBOUND,
+ session->traffic_monitor.in_curr_req,
+ session->traffic_monitor.num_in_curr_req) < 0) {
+ return -1;
+ }
+ //plog(ASL_LEVEL_DEBUG, "%s successful\n", __FUNCTION__);
+
+ return session->traffic_monitor.num_in_curr_req;
+ }
+ return 0;
+}
+
+int
+pk_sendget_outbound_sastats(ike_session_t *session)
+{
+ u_int32_t max_stats;
+ u_int32_t seq;
+
+ if (!session) {
+ plog(ASL_LEVEL_DEBUG, "invalid args in %s \n", __FUNCTION__);
+ return -1;
+ }
+
+ session->traffic_monitor.num_out_curr_req = 0;
+ bzero(session->traffic_monitor.out_curr_req, sizeof(session->traffic_monitor.out_curr_req));
+ max_stats = (sizeof(session->traffic_monitor.out_curr_req) / sizeof(session->traffic_monitor.out_curr_req[0]));
+
+ // get list of SAs
+ if ((session->traffic_monitor.num_out_curr_req = ike_session_get_sas_for_stats(session,
+ IPSEC_DIR_OUTBOUND,
+ &seq,
+ session->traffic_monitor.out_curr_req,
+ max_stats))) {
+ u_int64_t session_ids[] = {(u_int64_t)session, 0};
+
+ //plog(ASL_LEVEL_DEBUG, "about to call %s\n", __FUNCTION__);
+
+ if (pfkey_send_getsastats(lcconf->sock_pfkey,
+ seq,
+ session_ids,
+ 1,
+ IPSEC_DIR_OUTBOUND,
+ session->traffic_monitor.out_curr_req,
+ session->traffic_monitor.num_out_curr_req) < 0) {
+ return -1;
+ }
+ //plog(ASL_LEVEL_DEBUG, "%s successful\n", __FUNCTION__);
+
+ return session->traffic_monitor.num_out_curr_req;
+ }
+ return 0;
+}
+
+/*
+ * receive GETSPDSTAT from kernel.
+ */
+static int
+pk_recvgetsastat(mhp)
+caddr_t *mhp;
+{
+ struct sadb_msg *msg;
+ struct sadb_session_id *session_id;
+ struct sadb_sastat *stat_resp;
+ ike_session_t *session;
+
+ /* validity check */
+ if (mhp[0] == NULL ||
+ mhp[SADB_EXT_SESSION_ID] == NULL ||
+ mhp[SADB_EXT_SASTAT] == NULL) {
+ plog(ASL_LEVEL_ERR,
+ "inappropriate sadb getsastat response.\n");
+ return -1;
+ }
+ msg = ALIGNED_CAST(struct sadb_msg *)mhp[0]; // Wcast-align fix (void*) - mhp contains pointers to structs in an aligned buffer
+ session_id = ALIGNED_CAST(struct sadb_session_id *)mhp[SADB_EXT_SESSION_ID];
+ stat_resp = ALIGNED_CAST(struct sadb_sastat *)mhp[SADB_EXT_SASTAT];
+
+ /* the message has to be processed or not ? */
+ if (msg->sadb_msg_pid != getpid()) {
+ plog(ASL_LEVEL_DEBUG,
+ "%s message is not interesting "
+ "because pid %d is not mine.\n",
+ s_pfkey_type(msg->sadb_msg_type),
+ msg->sadb_msg_pid);
+ return -1;
+ }
+ if (!session_id->sadb_session_id_v[0]) {
+ plog(ASL_LEVEL_DEBUG,
+ "%s message is bad "
+ "because session-id[0] is invalid.\n",
+ s_pfkey_type(msg->sadb_msg_type));
+ return -1;
+ }
+ session = ALIGNED_CAST(__typeof__(session))session_id->sadb_session_id_v[0];
+
+ if (!stat_resp->sadb_sastat_list_len) {
+ plog(ASL_LEVEL_DEBUG,
+ "%s message is bad "
+ "because it has no sastats.\n",
+ s_pfkey_type(msg->sadb_msg_type));
+ return -1;
+ }
+
+ ike_session_update_traffic_idle_status(session,
+ stat_resp->sadb_sastat_dir,
+ (struct sastat *)(stat_resp + 1),
+ stat_resp->sadb_sastat_list_len);
+ return 0;
+}
+