From 702e4b75cd00bb3940b42fee715fbe45e4ad0933 Mon Sep 17 00:00:00 2001 From: emanuel Date: Fri, 5 Mar 2021 15:26:27 +0000 Subject: [PATCH] DENM permissions --- src/cam.c | 2 +- src/cam.h | 2 +- src/denm.c | 77 ++++++++++++++++++++++++++++++++++++++++++-- src/denm.h | 12 ++++++- src/facilities.c | 24 ++++++++++---- src/infrastructure.c | 2 +- src/infrastructure.h | 3 +- 7 files changed, 108 insertions(+), 14 deletions(-) diff --git a/src/cam.c b/src/cam.c index 88091d2..3c2973e 100644 --- a/src/cam.c +++ b/src/cam.c @@ -262,7 +262,7 @@ void lightship_reset_timer(lightship_t* lightship) { pthread_mutex_unlock(&lightship->lock); } -int check_cam(void* fc, BTPDataIndication_t *bdi, CAM_t* cam) { +int check_cam(void* fc, BTPDataIndication_t *bdi, CAM_t* cam, ServiceSpecificPermissions_t* ssp) { int rv = 0; lightship_t *lightship = ((facilities_t*) fc)->lightship; diff --git a/src/cam.h b/src/cam.h index 40c663b..dd0bfb5 100644 --- a/src/cam.h +++ b/src/cam.h @@ -34,7 +34,7 @@ lightship_t* lightship_init(); int lightship_check(lightship_t *lightship); void lightship_reset_timer(lightship_t *lightship); -int check_cam(void* fc, BTPDataIndication_t* bdi, CAM_t* cam); +int check_cam(void* fc, BTPDataIndication_t* bdi, CAM_t* cam, ServiceSpecificPermissions_t* ssp); void* ca_service(void* fc); #endif diff --git a/src/denm.c b/src/denm.c index 894dfe4..fcc0619 100644 --- a/src/denm.c +++ b/src/denm.c @@ -14,7 +14,64 @@ #define syslog_debug(msg, ...) #endif -static enum EVENT_CHECK_RESULT event_check(den_t *den, DENM_t *denm) { + +const cc_ssp_bm_t CC_SSP_BM_MAP[] = { + {"trafficCondition", 1, 0x800000}, + {"accident", 2, 0x400000}, + {"roadworks", 3, 0x200000}, + {"adverseWeatherCondition-Adhesion", 6, 0x100000}, + {"hazardousLocation-SurfaceCondition", 9, 0x080000}, + {"hazardousLocation-ObstacleOnTheRoad", 10, 0x040000}, + {"hazardousLocation-AnimalOnTheRoad", 11, 0x020000}, + {"humanPresenceOnTheRoad", 12, 0x010000}, + {"wrongWayDriving", 14, 0x008000}, + {"rescueAndRecoveryWorkInProgress", 15, 0x004000}, + {"adverseWeatherCondition-ExtremeWeatherCondition", 17, 0x002000}, + {"adverseWeatherCondition-Visibility", 18, 0x001000}, + {"adverseWeatherCondition-Precipitation", 19, 0x000800}, + {"slowVehicle", 26, 0x000400}, + {"dangerousEndOfQueue", 27, 0x000200}, + {"vehicleBreakdown", 91, 0x000100}, + {"postCrash", 92, 0x000080}, + {"humanProblem", 93, 0x000040}, + {"stationaryVehicle", 94, 0x000020}, + {"emergencyVehicleApproaching", 95, 0x000010}, + {"hazardousLocation-DangerousCurve", 96, 0x000008}, + {"collisionRisk", 97, 0x000004}, + {"signalViolation", 98, 0x000002}, + {"dangerousSituation", 99, 0x000001}, +}; + +static int permissions_check(int cause_code, uint8_t* permissions, uint8_t permissions_len) { + /* DENM SSP scheme + * + * byte | description + * --------------------------------- + * 0 | SSP version control + * 1-3 | Service-specific parameter + * 3-40 | Reserved + */ + + if (permissions_len < 4) { + syslog_debug("[facilities] [den] permissions length too small"); + return 0; + } + + uint32_t perms_int = (*((uint32_t*) permissions)) >> 8; + + uint32_t perm_val; + for (int i = 0; i < 24; ++i) { + if (cause_code == CC_SSP_BM_MAP[i].cause_code) { + perm_val = CC_SSP_BM_MAP[i].bitmap_val; + } + } + + if ((perm_val & perms_int) == perm_val) return 1; + else return 0; + +} + +static enum EVENT_CHECK_RESULT event_check(den_t *den, DENM_t *denm, ServiceSpecificPermissions_t* ssp) { int rv = 0; uint64_t e_detection_time, e_reference_time; @@ -25,6 +82,20 @@ static enum EVENT_CHECK_RESULT event_check(den_t *den, DENM_t *denm) { return EVENT_INVALID; } + // Check if event cause code type is permitted by the issuing ticket + if (ssp && denm->denm.situation) { + if ( + !permissions_check( + denm->denm.situation->eventType.causeCode, + ssp->choice.bitmapSsp.buf, + ssp->choice.bitmapSsp.size + ) + ) { + return EVENT_INVALID; + } + } + + struct timespec systemtime; clock_gettime(CLOCK_REALTIME, &systemtime); long now = (long) (systemtime.tv_sec * 1000 + systemtime.tv_nsec / 1E6); @@ -256,9 +327,9 @@ static int event_update(den_t *den, DENM_t *denm, int64_t* id) { else return 0; // Event updated } -int event_manage(den_t *den, DENM_t *denm, int64_t* id) { +int event_manage(den_t *den, DENM_t *denm, int64_t* id, ServiceSpecificPermissions_t* ssp) { int rv = 0; - switch (rv = event_check(den, denm)) { + switch (rv = event_check(den, denm, ssp)) { case EVENT_NEW: syslog_debug("[facilities] [den] new event received"); if (event_add(den, denm, id)) { diff --git a/src/denm.h b/src/denm.h index e0e5233..4203fe1 100644 --- a/src/denm.h +++ b/src/denm.h @@ -5,6 +5,7 @@ #include #include #include +#include enum EVENT_STATE { EVENT_ACTIVE, @@ -49,14 +50,23 @@ enum EVENT_CHECK_RESULT { EVENT_NUMBER_EXCEEDED }; +typedef struct cc_ssp_bm { + const char* cause_type; + const int cause_code; + const uint32_t bitmap_val; +} cc_ssp_bm_t; + + /** * Evaluate a DENM event. * Does all the checks to a DENM and adds it to the database. *Don't* free the DENM struct after calling this function * @param den the DEN service struct * @param denm the DENM to evaluate + * @param id message intra ITS-S identitifier + * @param ssp permissions * @return 0 if event OK, 1 if event NOK */ -int event_manage(den_t* den, DENM_t* denm, int64_t* id); +int event_manage(den_t* den, DENM_t* denm, int64_t* id, ServiceSpecificPermissions_t* ssp); void* den_service(void* fc); diff --git a/src/facilities.c b/src/facilities.c index 0d251dd..2152630 100644 --- a/src/facilities.c +++ b/src/facilities.c @@ -80,11 +80,17 @@ static int transport_indication(facilities_t *facilities, void* responder, uint8 goto cleanup; } + // Get permisisons + ServiceSpecificPermissions_t* ssp = NULL; + if (bdi->gnPermissions) { + ssp = &bdi->gnPermissions->ssp; + } + // Manage message switch (bdi->destinationPort) { case Port_cam: - check_cam(facilities, bdi, its_msg); + check_cam(facilities, bdi, its_msg, ssp); break; case Port_denm: @@ -96,9 +102,13 @@ static int transport_indication(facilities_t *facilities, void* responder, uint8 free(xml_denm); #endif int64_t id = -1; - event_manage(facilities->den, its_msg, &id); - + event_manage(facilities->den, its_msg, &id, ssp); break; + + case Port_ivim: + service_eval(facilities->infrastructure, SERVICE_IVI, its_msg, &id, ssp); + break; + default: break; } @@ -120,7 +130,9 @@ static int transport_indication(facilities_t *facilities, void* responder, uint8 pthread_cond_signal(&facilities->tx_queue->trigger); cleanup: - if (bdi->destinationPort != Port_denm) ASN_STRUCT_FREE(*its_msg_descriptor, its_msg); + if (bdi->destinationPort != Port_denm && bdi->destinationPort != Port_ivim) { + ASN_STRUCT_FREE(*its_msg_descriptor, its_msg); + } ASN_STRUCT_FREE(asn_DEF_BTPDataIndication, bdi); ASN_STRUCT_FREE(asn_DEF_FacilitiesDataIndication, fdi); @@ -204,7 +216,7 @@ static int facilities_request(facilities_t *facilities, void* responder, uint8_t if (fdreq->choice.singleMessage.itssMessageType == ItssMessageType_denm) { managed_msg = true; - uint8_t event_type = event_manage(facilities->den, its_msg, &id); + uint8_t event_type = event_manage(facilities->den, its_msg, &id, NULL); // Do not free its_msg! event_manage takes care of the msg // id will get set to another val if EVENT NEW or UPDATE or CANCELLATION or NEGATION if (event_type != EVENT_NEW && @@ -243,7 +255,7 @@ static int facilities_request(facilities_t *facilities, void* responder, uint8_t } else if (fdreq->choice.singleMessage.itssMessageType == ItssMessageType_ivim) { managed_msg = true; - uint8_t service_type = service_eval(facilities->infrastructure, SERVICE_IVI, its_msg, &id); + uint8_t service_type = service_eval(facilities->infrastructure, SERVICE_IVI, its_msg, &id, NULL); if (service_type != SERVICE_NEW && service_type != SERVICE_UPDATE && diff --git a/src/infrastructure.c b/src/infrastructure.c index 544f267..f9ba623 100644 --- a/src/infrastructure.c +++ b/src/infrastructure.c @@ -312,7 +312,7 @@ static int service_update(infrastructure_t* infrastructure, enum SERVICE_TYPE ty else return 0; // Event updated } -enum SERVICE_EVAL_RESULT service_eval(infrastructure_t* infrastructure, enum SERVICE_TYPE type, void* its_msg, int64_t* id) { +enum SERVICE_EVAL_RESULT service_eval(infrastructure_t* infrastructure, enum SERVICE_TYPE type, void* its_msg, int64_t* id, ServiceSpecificPermissions_t* ssp) { int rv = 0; switch (rv = service_check(infrastructure, type, its_msg)) { case SERVICE_NEW: diff --git a/src/infrastructure.h b/src/infrastructure.h index b726f8d..60789ef 100644 --- a/src/infrastructure.h +++ b/src/infrastructure.h @@ -5,6 +5,7 @@ #include #include #include +#include enum SERVICE_STATE { SERVICE_ACTIVE, @@ -61,7 +62,7 @@ enum SERVICE_EVAL_RESULT { SERVICE_NUMBER_EXCEEDED }; -enum SERVICE_EVAL_RESULT service_eval(infrastructure_t* infrastructure, enum SERVICE_TYPE type, void* its_msg, int64_t* id); +enum SERVICE_EVAL_RESULT service_eval(infrastructure_t* infrastructure, enum SERVICE_TYPE type, void* its_msg, int64_t* id, ServiceSpecificPermissions_t* ssp); void* infrastructure_service(void* fc);