blob: 440db9b9d86599d9d7a053b9fd947f5c5cfe4d9b [file] [log] [blame]
Julian Hall8cff2b82020-11-23 18:12:17 +01001/*
Julian Hall7d7b24c2021-08-13 13:40:38 +01002 * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
Julian Hall8cff2b82020-11-23 18:12:17 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Julian Hall7d7b24c2021-08-13 13:40:38 +01007#include <ctype.h>
Julian Hall8cff2b82020-11-23 18:12:17 +01008#include <string.h>
Julian Hall8cff2b82020-11-23 18:12:17 +01009#include "service_name.h"
10
11/*
12 * Structure to hold result of parsing the service name. Sets
13 * indices and length of the following fields. Lengths are set to zero
14 * if field is not present.
15 */
16struct sn_parsed_fields
17{
Julian Hall7d7b24c2021-08-13 13:40:38 +010018 size_t authority_pos;
19 size_t authority_len;
20 size_t service_pos;
21 size_t service_len;
22 size_t version_pos;
23 size_t version_len;
24 size_t instance_pos;
25 size_t instance_len;
Julian Hall8cff2b82020-11-23 18:12:17 +010026};
27
28/*
29 * Find the lengthof the current field, up to the specified separator or end
30 * of the service name.
31 */
32static size_t field_len(const char *sn, size_t from, size_t len, char separator)
33{
Julian Hall7d7b24c2021-08-13 13:40:38 +010034 size_t field_len = 0;
35 size_t pos = from;
Julian Hall8cff2b82020-11-23 18:12:17 +010036
Julian Hall7d7b24c2021-08-13 13:40:38 +010037 while (pos < len) {
Julian Hall8cff2b82020-11-23 18:12:17 +010038
Julian Hall7d7b24c2021-08-13 13:40:38 +010039 if (sn[pos] == separator) break;
Julian Hall8cff2b82020-11-23 18:12:17 +010040
Julian Hall7d7b24c2021-08-13 13:40:38 +010041 ++pos;
42 ++field_len;
43 }
Julian Hall8cff2b82020-11-23 18:12:17 +010044
Julian Hall7d7b24c2021-08-13 13:40:38 +010045 return field_len;
Julian Hall8cff2b82020-11-23 18:12:17 +010046}
47
48/*
49 * Find the next field in the service name after the specified separator from the
50 * specified position.
51 */
52static bool find_next(const char *sn, size_t from, size_t len, char separator, size_t *next)
53{
Julian Hall7d7b24c2021-08-13 13:40:38 +010054 bool found = false;
55 size_t pos = from;
Julian Hall8cff2b82020-11-23 18:12:17 +010056
Julian Hall7d7b24c2021-08-13 13:40:38 +010057 while (pos < len) {
Julian Hall8cff2b82020-11-23 18:12:17 +010058
Julian Hall7d7b24c2021-08-13 13:40:38 +010059 if (sn[pos] == separator) {
60 *next = pos + 1;
61 found = (*next < len);
62 break;
63 }
Julian Hall8cff2b82020-11-23 18:12:17 +010064
Julian Hall7d7b24c2021-08-13 13:40:38 +010065 ++pos;
66 }
Julian Hall8cff2b82020-11-23 18:12:17 +010067
Julian Hall7d7b24c2021-08-13 13:40:38 +010068 return found;
Julian Hall8cff2b82020-11-23 18:12:17 +010069}
70
71/*
72 * Parse the service name. Returns true if is a legal service
73 * name and mandatory fields are present;
74 */
75static bool sn_parse(const char *sn, struct sn_parsed_fields *fields)
76{
Julian Hall7d7b24c2021-08-13 13:40:38 +010077 size_t sn_len = strlen(sn);
78 size_t field_pos = 0;
Julian Hall8cff2b82020-11-23 18:12:17 +010079
Julian Hall7d7b24c2021-08-13 13:40:38 +010080 fields->authority_pos = 0;
81 fields->authority_len = 0;
82 fields->service_pos = 0;
83 fields->service_len = 0;
84 fields->version_pos = 0;
85 fields->version_len = 0;
86 fields->instance_pos = 0;
87 fields->instance_len = 0;
Julian Hall8cff2b82020-11-23 18:12:17 +010088
Julian Hall7d7b24c2021-08-13 13:40:38 +010089 /* Absorb urn: if present */
90 if (memcmp("urn", &sn[field_pos], strlen("urn")) == 0) {
91 if (!find_next(sn, field_pos, sn_len, ':', &field_pos)) return false;
92 }
Julian Hall8cff2b82020-11-23 18:12:17 +010093
Julian Hall7d7b24c2021-08-13 13:40:38 +010094 /* Check it is a service name */
95 if (memcmp("sn", &sn[field_pos], strlen("sn")) != 0) {
96 /* Not a service name */
97 return false;
98 }
Julian Hall8cff2b82020-11-23 18:12:17 +010099
Julian Hall7d7b24c2021-08-13 13:40:38 +0100100 /* Expect the authority field */
101 if (find_next(sn, field_pos, sn_len, ':', &field_pos)) {
102 fields->authority_pos = field_pos;
103 fields->authority_len = field_len(sn, field_pos, sn_len, ':');
104 }
105 else {
106 /* Missing mandatory authority field */
107 return false;
108 }
Julian Hall8cff2b82020-11-23 18:12:17 +0100109
Julian Hall7d7b24c2021-08-13 13:40:38 +0100110 /* Expect the service field */
111 if (find_next(sn, field_pos, sn_len, ':', &field_pos)) {
112 fields->service_pos = field_pos;
113 fields->service_len = field_len(sn, field_pos, sn_len, ':');
Julian Hall8cff2b82020-11-23 18:12:17 +0100114
Julian Hall7d7b24c2021-08-13 13:40:38 +0100115 /* Check for the optional version */
116 if (find_next(sn, field_pos, field_pos + fields->service_len, '.', &field_pos)) {
117 fields->version_pos = field_pos;
118 fields->version_len = field_len(sn, field_pos, sn_len, ':');
119 }
120 }
121 else {
122 /* Missing mandatory service field */
123 return false;
124 }
Julian Hall8cff2b82020-11-23 18:12:17 +0100125
Julian Hall7d7b24c2021-08-13 13:40:38 +0100126 /* Check for optional instance */
127 if (find_next(sn, field_pos, sn_len, ':', &field_pos)) {
128 fields->instance_pos = field_pos;
129 fields->instance_len = sn_len - field_pos;
130 }
Julian Hall8cff2b82020-11-23 18:12:17 +0100131
Julian Hall7d7b24c2021-08-13 13:40:38 +0100132 return true;
Julian Hall8cff2b82020-11-23 18:12:17 +0100133}
134
135bool sn_is_valid(const char *sn)
136{
Julian Hall7d7b24c2021-08-13 13:40:38 +0100137 struct sn_parsed_fields fields;
138 return sn_parse(sn, &fields);
Julian Hall8cff2b82020-11-23 18:12:17 +0100139}
140
141bool sn_check_authority(const char *sn, const char *auth)
142{
Julian Hall7d7b24c2021-08-13 13:40:38 +0100143 bool matched = false;
144 struct sn_parsed_fields fields;
Julian Hall8cff2b82020-11-23 18:12:17 +0100145
Julian Hall7d7b24c2021-08-13 13:40:38 +0100146 if (sn_parse(sn, &fields) && fields.authority_len) {
Julian Hall8cff2b82020-11-23 18:12:17 +0100147
Julian Hall7d7b24c2021-08-13 13:40:38 +0100148 matched = (memcmp(auth, &sn[fields.authority_pos], strlen(auth)) == 0);
149 }
Julian Hall8cff2b82020-11-23 18:12:17 +0100150
Julian Hall7d7b24c2021-08-13 13:40:38 +0100151 return matched;
Julian Hall8cff2b82020-11-23 18:12:17 +0100152}
153
154bool sn_check_service(const char *sn, const char *service)
155{
Julian Hall7d7b24c2021-08-13 13:40:38 +0100156 bool matched = false;
157 struct sn_parsed_fields fields;
Julian Hall8cff2b82020-11-23 18:12:17 +0100158
Julian Hall7d7b24c2021-08-13 13:40:38 +0100159 if (sn_parse(sn, &fields) && fields.service_len) {
Julian Hall8cff2b82020-11-23 18:12:17 +0100160
Julian Hall7d7b24c2021-08-13 13:40:38 +0100161 matched = (memcmp(service, &sn[fields.service_pos], strlen(service)) == 0);
162 }
Julian Hall8cff2b82020-11-23 18:12:17 +0100163
Julian Hall7d7b24c2021-08-13 13:40:38 +0100164 return matched;
Julian Hall8cff2b82020-11-23 18:12:17 +0100165}
166
167unsigned int sn_get_service_instance(const char *sn)
168{
Julian Hall7d7b24c2021-08-13 13:40:38 +0100169 unsigned int instance = 0;
Julian Hall8cff2b82020-11-23 18:12:17 +0100170
Julian Hall7d7b24c2021-08-13 13:40:38 +0100171 struct sn_parsed_fields fields;
Julian Hall8cff2b82020-11-23 18:12:17 +0100172
Julian Hall7d7b24c2021-08-13 13:40:38 +0100173 if (sn_parse(sn, &fields) && fields.instance_len) {
Julian Hall8cff2b82020-11-23 18:12:17 +0100174
Julian Hall7d7b24c2021-08-13 13:40:38 +0100175 /* Instance must be expressed as a decimal */
176 unsigned int multiplier = 1;
Julian Hall8cff2b82020-11-23 18:12:17 +0100177
Julian Hall7d7b24c2021-08-13 13:40:38 +0100178 for (size_t i = 0; i < fields.instance_len; i++) {
179
180 size_t digit_index = fields.instance_pos + fields.instance_len - 1 - i;
181 char digit = sn[digit_index];
182
Imre Kis45df16f2023-03-24 13:27:10 +0100183 if (isdigit((int)digit)) {
Julian Hall7d7b24c2021-08-13 13:40:38 +0100184
185 instance += ((digit - '0') * multiplier);
186 multiplier *= 10;
187 }
188 else {
189
190 /* Invalid instance string */
191 instance = 0;
192 break;
193 }
194 }
195 }
196
197 return instance;
Julian Hall8cff2b82020-11-23 18:12:17 +0100198}
199
200size_t sn_read_service(const char *sn, char *buf, size_t buf_len)
201{
Julian Hall7d7b24c2021-08-13 13:40:38 +0100202 size_t field_len = 0;
Julian Hall8cff2b82020-11-23 18:12:17 +0100203
Julian Hall7d7b24c2021-08-13 13:40:38 +0100204 memset(buf, 0, buf_len);
205 struct sn_parsed_fields fields;
Julian Hall8cff2b82020-11-23 18:12:17 +0100206
Julian Hall7d7b24c2021-08-13 13:40:38 +0100207 if (sn_parse(sn, &fields) && fields.service_len && (fields.service_len < buf_len)) {
Julian Hall8cff2b82020-11-23 18:12:17 +0100208
Julian Hall7d7b24c2021-08-13 13:40:38 +0100209 field_len = fields.service_len;
210 memcpy(buf, &sn[fields.service_pos], field_len);
211 buf[field_len] = '\0';
212 }
Julian Hall8cff2b82020-11-23 18:12:17 +0100213
Julian Hall7d7b24c2021-08-13 13:40:38 +0100214 return field_len;
Julian Hall8cff2b82020-11-23 18:12:17 +0100215}