1 1.1 christos /* srp.h 2 1.1 christos * 3 1.1 christos * Copyright (c) 2018-2024 Apple Inc. All rights reserved. 4 1.1 christos * 5 1.1 christos * Licensed under the Apache License, Version 2.0 (the "License"); 6 1.1 christos * you may not use this file except in compliance with the License. 7 1.1 christos * You may obtain a copy of the License at 8 1.1 christos * 9 1.1 christos * https://www.apache.org/licenses/LICENSE-2.0 10 1.1 christos * 11 1.1 christos * Unless required by applicable law or agreed to in writing, software 12 1.1 christos * distributed under the License is distributed on an "AS IS" BASIS, 13 1.1 christos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 1.1 christos * See the License for the specific language governing permissions and 15 1.1 christos * limitations under the License. 16 1.1 christos * 17 1.1 christos * Service Registration Protocol common definitions 18 1.1 christos */ 19 1.1 christos 20 1.1 christos #ifndef __SRP_H 21 1.1 christos #define __SRP_H 22 1.1 christos 23 1.1 christos #ifdef __cplusplus 24 1.1 christos extern "C" { 25 1.1 christos #endif 26 1.1 christos 27 1.1 christos #ifndef THREAD_DEVKIT_ADK 28 1.1 christos #include <netinet/in.h> 29 1.1 christos #endif 30 1.1 christos #include <stdint.h> 31 1.1 christos #include <stdbool.h> 32 1.1 christos #include <string.h> 33 1.1 christos #ifdef POSIX_BUILD 34 1.1 christos #include <limits.h> 35 1.1 christos #include <sys/param.h> 36 1.1 christos #endif 37 1.1 christos #ifdef MALLOC_DEBUG_LOGGING 38 1.1 christos # define MDNS_NO_STRICT 1 39 1.1 christos #endif 40 1.1 christos 41 1.1 christos #include "srp-features.h" // for feature flags 42 1.1 christos 43 1.1 christos 44 1.1 christos #ifdef __clang__ 45 1.1 christos #define NULLABLE _Nullable 46 1.1 christos #define NONNULL _Nonnull 47 1.1 christos #define UNUSED __unused 48 1.1 christos #else 49 1.1 christos #define NULLABLE 50 1.1 christos #define NONNULL 51 1.1 christos #define UNUSED __attribute__((unused)) 52 1.1 christos #ifdef POSIX_BUILD 53 1.1 christos #else 54 1.1 christos #define SRP_CRYPTO_MBEDTLS 1 55 1.1 christos #endif // POSIX_BUILD 56 1.1 christos #endif 57 1.1 christos 58 1.1 christos #define INT64_HEX_STRING_MAX 17 // Maximum size of an int64_t printed as hex, including NUL termination 59 1.1 christos 60 1.1 christos #ifdef __clang__ 61 1.1 christos #pragma clang diagnostic push 62 1.1 christos #pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" 63 1.1 christos #endif 64 1.1 christos //====================================================================================================================== 65 1.1 christos 66 1.1 christos #ifdef __clang__ 67 1.1 christos #pragma clang diagnostic pop 68 1.1 christos #endif 69 1.1 christos 70 1.1 christos #include "srp-log.h" // For log functions 71 1.1 christos 72 1.1 christos #define SRP_OBJ_REF_COUNT_LIMIT 10000 73 1.1 christos 74 1.1 christos #ifdef __clang__ 75 1.1 christos #define FILE_TRIM(x) (strrchr(x, '/') + 1) 76 1.1 christos #else 77 1.1 christos #define FILE_TRIM(x) (x) 78 1.1 christos #endif 79 1.1 christos 80 1.1 christos #ifdef THREAD_DEVKIT_ADK 81 1.1 christos #define FINALIZED(x) 82 1.1 christos #define CREATED(x) 83 1.1 christos #else 84 1.1 christos #define FINALIZED(x) ((x)++) 85 1.1 christos #define CREATED(x) ((x)++) 86 1.1 christos #endif // THREAD_DEVKIT_ADK 87 1.1 christos 88 1.1 christos #ifdef DEBUG_VERBOSE 89 1.1 christos #ifdef __clang_analyzer__ 90 1.1 christos #define RELEASE_BASE(x, object_type, file, line) \ 91 1.1 christos object_type ## _finalize(x) 92 1.1 christos #else 93 1.1 christos #define RELEASE_BASE(x, object_type, file, line) do { \ 94 1.1 christos if ((x) != NULL) { \ 95 1.1 christos if ((x)->ref_count == 0) { \ 96 1.1 christos FAULT("ALLOC: release after finalize at %2.2d: %p (%10s): %s:%d", \ 97 1.1 christos (x)->ref_count, (void *)(x), # x, FILE_TRIM(file), line); \ 98 1.1 christos abort(); \ 99 1.1 christos } else if ((x)->ref_count > SRP_OBJ_REF_COUNT_LIMIT) { \ 100 1.1 christos FAULT("ALLOC: release at %2.2d: %p (%10s): %s:%d", \ 101 1.1 christos (x)->ref_count, (void *)(x), # x, FILE_TRIM(file), line); \ 102 1.1 christos abort(); \ 103 1.1 christos } else { \ 104 1.1 christos INFO("ALLOC: release at %2.2d: %p (%10s): %s:%d", \ 105 1.1 christos (x)->ref_count, (void *)(x), # x, FILE_TRIM(file), line); \ 106 1.1 christos --(x)->ref_count; \ 107 1.1 christos if ((x)->ref_count == 0) { \ 108 1.1 christos INFO("ALLOC: finalize: %p (%10s): %s:%d", \ 109 1.1 christos (void *)(x), # x, FILE_TRIM(file), line); \ 110 1.1 christos FINALIZED(object_type##_finalized); \ 111 1.1 christos object_type##_finalize(x); \ 112 1.1 christos } \ 113 1.1 christos } \ 114 1.1 christos } \ 115 1.1 christos } while (0) 116 1.1 christos 117 1.1 christos #endif // __clang_analyzer__ 118 1.1 christos #define RETAIN_BASE(x, object_type, file, line) do { \ 119 1.1 christos if ((x) != NULL) { \ 120 1.1 christos INFO("ALLOC: retain at %2.2d: %p (%10s): %s:%d", \ 121 1.1 christos (x)->ref_count, (void *)(x), # x, FILE_TRIM(file), line); \ 122 1.1 christos if ((x)->ref_count == 0) { \ 123 1.1 christos CREATED(object_type##_created); \ 124 1.1 christos } \ 125 1.1 christos ++((x)->ref_count); \ 126 1.1 christos if ((x)->ref_count > SRP_OBJ_REF_COUNT_LIMIT) { \ 127 1.1 christos FAULT("ALLOC: retain at %2.2d: %p (%10s): %s:%d", \ 128 1.1 christos (x)->ref_count, (void *)(x), # x, FILE_TRIM(file), line); \ 129 1.1 christos abort(); \ 130 1.1 christos } \ 131 1.1 christos } \ 132 1.1 christos } while (0) 133 1.1 christos #define RELEASE(x, object_type) RELEASE_BASE(x, object_type, file, line) 134 1.1 christos #define RETAIN(x, object_type) RETAIN_BASE(x, object_type, file, line) 135 1.1 christos #define RELEASE_HERE(x, object_type) RELEASE_BASE(x, object_type, __FILE__, __LINE__) 136 1.1 christos #define RETAIN_HERE(x, object_type) RETAIN_BASE(x, object_type, __FILE__, __LINE__) 137 1.1 christos #else // DEBUG_VERBOSE 138 1.1 christos #ifdef __clang_analyzer__ 139 1.1 christos #define RELEASE(x, object_type) object_type ## _finalize(x) 140 1.1 christos #define RELEASE_HERE(x, object_type) object_type ## _finalize(x) 141 1.1 christos #define RETAIN(x, object_type) 142 1.1 christos #define RETAIN_HERE(x, object_tyoe) 143 1.1 christos #else 144 1.1 christos #define RELEASE(x, object_type) do { \ 145 1.1 christos if ((x)->ref_count == 0) { \ 146 1.1 christos FAULT("ALLOC: release after finalize at %2.2d: %p (%10s): %s:%d", \ 147 1.1 christos (x)->ref_count, (void *)(x), # x, FILE_TRIM(file), line); \ 148 1.1 christos abort(); \ 149 1.1 christos } \ 150 1.1 christos if ((x)->ref_count > SRP_OBJ_REF_COUNT_LIMIT) { \ 151 1.1 christos FAULT("ALLOC: release at %2.2d: %p (%10s): %s:%d", \ 152 1.1 christos (x)->ref_count, (void *)(x), # x, FILE_TRIM(file), line); \ 153 1.1 christos abort(); \ 154 1.1 christos } \ 155 1.1 christos if (--(x)->ref_count == 0) { \ 156 1.1 christos FINALIZED(object_type##_finalized); \ 157 1.1 christos object_type ## _finalize(x); \ 158 1.1 christos (void)file; (void)line; \ 159 1.1 christos } \ 160 1.1 christos } while (0) 161 1.1 christos #define RETAIN(x, object_type) do { \ 162 1.1 christos (x)->ref_count++; \ 163 1.1 christos if (--(x)->ref_count == 0) { \ 164 1.1 christos CREATED(object_type##_created); \ 165 1.1 christos } \ 166 1.1 christos if ((x)->ref_count > SRP_OBJ_REF_COUNT_LIMIT) { \ 167 1.1 christos FAULT("ALLOC: retain at %2.2d: %p (%10s): %s:%d", \ 168 1.1 christos (x)->ref_count, (void *)(x), # x, FILE_TRIM(file), line); \ 169 1.1 christos abort(); \ 170 1.1 christos } \ 171 1.1 christos } while (0) 172 1.1 christos #define RELEASE_HERE(x, object_type) do { \ 173 1.1 christos if ((x)->ref_count == 0) { \ 174 1.1 christos FAULT("ALLOC: release after finalize at %2.2d: %p (%10s)", \ 175 1.1 christos (x)->ref_count, (void *)(x), # x); \ 176 1.1 christos abort(); \ 177 1.1 christos } \ 178 1.1 christos if ((x)->ref_count > SRP_OBJ_REF_COUNT_LIMIT) { \ 179 1.1 christos FAULT("ALLOC: release at %2.2d: %p (%10s)", \ 180 1.1 christos (x)->ref_count, (void *)(x), # x); \ 181 1.1 christos abort(); \ 182 1.1 christos } \ 183 1.1 christos if (--(x)->ref_count == 0) { \ 184 1.1 christos FINALIZED(object_type##_finalized); \ 185 1.1 christos object_type ## _finalize(x); \ 186 1.1 christos } \ 187 1.1 christos } while (0) 188 1.1 christos #define RETAIN_HERE(x, object_type) do { \ 189 1.1 christos (x)->ref_count++; \ 190 1.1 christos if (--(x)->ref_count == 0) { \ 191 1.1 christos CREATED(object_type##_created); \ 192 1.1 christos } \ 193 1.1 christos if ((x)->ref_count > SRP_OBJ_REF_COUNT_LIMIT) { \ 194 1.1 christos FAULT("ALLOC: retain at %2.2d: %p (%10s)", \ 195 1.1 christos (x)->ref_count, (void *)(x), # x); \ 196 1.1 christos abort(); \ 197 1.1 christos } \ 198 1.1 christos } while (0) 199 1.1 christos #endif 200 1.1 christos #endif // DEBUG_VERBOSE 201 1.1 christos 202 1.1 christos #define THREAD_ENTERPRISE_NUMBER ((uint64_t)44970) 203 1.1 christos #define THREAD_SRP_SERVER_ANYCAST_OPTION 0x5c 204 1.1 christos #define THREAD_SRP_SERVER_OPTION 0x5d 205 1.1 christos #define THREAD_PREF_ID_OPTION 0x9d 206 1.1 christos 207 1.1 christos #define IS_SRP_SERVICE(service) \ 208 1.1 christos ((cti_service)->enterprise_number == THREAD_ENTERPRISE_NUMBER && \ 209 1.1 christos (cti_service)->service_type == THREAD_SRP_SERVER_OPTION && \ 210 1.1 christos (cti_service)->service_version == 1 && \ 211 1.1 christos (cti_service)->server_length == 18) 212 1.1 christos #define IS_SRP_ANYCAST_SERVICE(service) \ 213 1.1 christos ((cti_service)->enterprise_number == THREAD_ENTERPRISE_NUMBER && \ 214 1.1 christos (cti_service)->service_type == THREAD_SRP_SERVER_ANYCAST_OPTION && \ 215 1.1 christos (cti_service)->service_version == 1 && \ 216 1.1 christos (cti_service)->service_length == 2) 217 1.1 christos #define IS_PREF_ID_SERVICE(service) \ 218 1.1 christos ((cti_service)->enterprise_number == THREAD_ENTERPRISE_NUMBER && \ 219 1.1 christos (cti_service)->service_type == THREAD_PREF_ID_OPTION && \ 220 1.1 christos (cti_service)->service_version == 1 && \ 221 1.1 christos (cti_service)->server_length == 9) 222 1.1 christos 223 1.1 christos #ifdef MALLOC_DEBUG_LOGGING 224 1.1 christos void *debug_malloc(size_t len, const char *file, int line); 225 1.1 christos void *debug_calloc(size_t count, size_t len, const char *file, int line); 226 1.1 christos char *debug_strdup(const char *s, const char *file, int line); 227 1.1 christos void debug_free(void *p, const char *file, int line); 228 1.1 christos 229 1.1 christos #define malloc(x) debug_malloc(x, __FILE__, __LINE__) 230 1.1 christos #define calloc(c, y) debug_calloc(c, y, __FILE__, __LINE__) 231 1.1 christos #define strdup(s) debug_strdup(s, __FILE__, __LINE__) 232 1.1 christos #define free(p) debug_free(p, __FILE__, __LINE__) 233 1.1 christos #endif 234 1.1 christos 235 1.1 christos typedef struct srp_key srp_key_t; 236 1.1 christos 237 1.1 christos // This function compares two IPv6 prefixes, up to the specified prefix length (in bytes). 238 1.1 christos // return: -1 if prefix_a < prefix_b 239 1.1 christos // 0 if prefix_a == prefix_b 240 1.1 christos // 1 if prefix_a > prefix_b. 241 1.1 christos static inline int 242 1.1 christos in6prefix_compare(const struct in6_addr *prefix_a, const struct in6_addr *prefix_b, size_t len) 243 1.1 christos { 244 1.1 christos return memcmp(prefix_a, prefix_b, len); 245 1.1 christos } 246 1.1 christos 247 1.1 christos // This function compares two full IPv6 addresses. 248 1.1 christos // return: -1 if addr_a < addr_b 249 1.1 christos // 0 if addr_a == addr_b 250 1.1 christos // 1 if addr_a > addr_b. 251 1.1 christos static inline int 252 1.1 christos in6addr_compare(const struct in6_addr *addr_a, const struct in6_addr *addr_b) 253 1.1 christos { 254 1.1 christos return in6prefix_compare(addr_a, addr_b, sizeof (*addr_a)); 255 1.1 christos } 256 1.1 christos 257 1.1 christos // This function copies the data into a, up to len bytes or sizeof(*a), whichever is less. 258 1.1 christos // if there are uninitialized bytes remaining in a, sets those to zero. 259 1.1 christos static inline void 260 1.1 christos in6prefix_copy_from_data(struct in6_addr *prefix, const uint8_t *data, size_t len) 261 1.1 christos { 262 1.1 christos size_t copy_len = sizeof(*prefix) < len ? sizeof(*prefix): len; 263 1.1 christos if (copy_len > 0) { 264 1.1 christos memcpy(prefix, data, copy_len); 265 1.1 christos } 266 1.1 christos if (copy_len != sizeof(*prefix)) { 267 1.1 christos memset((char *)prefix + copy_len, 0, sizeof(*prefix) - copy_len); 268 1.1 christos } 269 1.1 christos } 270 1.1 christos 271 1.1 christos // This function copies prefix src, into prefix dst, up to len bytes. 272 1.1 christos static inline void 273 1.1 christos in6prefix_copy(struct in6_addr *dst, const struct in6_addr *src, size_t len) 274 1.1 christos { 275 1.1 christos in6prefix_copy_from_data(dst, (const uint8_t*)src, len); 276 1.1 christos } 277 1.1 christos 278 1.1 christos // This function copies full IPv6 address src into dst. 279 1.1 christos static inline void 280 1.1 christos in6addr_copy(struct in6_addr *dst, const struct in6_addr *src) 281 1.1 christos { 282 1.1 christos memcpy(dst, src, sizeof(*dst)); 283 1.1 christos } 284 1.1 christos 285 1.1 christos // This function zeros the full IPv6 address 286 1.1 christos static inline void 287 1.1 christos in6addr_zero(struct in6_addr *addr) 288 1.1 christos { 289 1.1 christos memset(addr, 0, sizeof(*addr)); 290 1.1 christos } 291 1.1 christos 292 1.1 christos // Returns true if this is a Thread mesh-local anycast address. 293 1.1 christos extern const uint8_t thread_anycast_preamble[7]; 294 1.1 christos extern const uint8_t thread_rloc_preamble[6]; 295 1.1 christos 296 1.1 christos static inline bool 297 1.1 christos is_thread_mesh_anycast_address(const struct in6_addr *addr) 298 1.1 christos { 299 1.1 christos // Thread 1.3.0 section 5.2.2.2 Anycast Locator (ALOC) 300 1.1 christos if (!memcmp(&addr->s6_addr[8], thread_anycast_preamble, sizeof(thread_anycast_preamble))) { 301 1.1 christos return true; 302 1.1 christos } 303 1.1 christos return false; 304 1.1 christos } 305 1.1 christos 306 1.1 christos static inline bool 307 1.1 christos is_thread_mesh_rloc_address(const struct in6_addr *addr) 308 1.1 christos { 309 1.1 christos // Thread 1.3.0 section 5.2.2.1 Routing Locator (RLOC) 310 1.1 christos if (!memcmp(&addr->s6_addr[8], thread_rloc_preamble, sizeof(thread_rloc_preamble))) { 311 1.1 christos return true; 312 1.1 christos } 313 1.1 christos return false; 314 1.1 christos } 315 1.1 christos 316 1.1 christos static inline bool 317 1.1 christos is_thread_mesh_synthetic_address(const struct in6_addr *addr) 318 1.1 christos { 319 1.1 christos return is_thread_mesh_anycast_address(addr) || is_thread_mesh_rloc_address(addr); 320 1.1 christos } 321 1.1 christos 322 1.1 christos static inline bool 323 1.1 christos is_thread_mesh_synthetic_or_link_local(const struct in6_addr *addr) 324 1.1 christos { 325 1.1 christos return (is_thread_mesh_anycast_address(addr) || is_thread_mesh_rloc_address(addr) || 326 1.1 christos (addr->s6_addr[0] == 0xfe && (addr->s6_addr[1] & 0xc0) == 0x80)); 327 1.1 christos } 328 1.1 christos 329 1.1 christos #ifndef _SRP_STRICT_DISPOSE_TEMPLATE 330 1.1 christos #define _SRP_STRICT_DISPOSE_TEMPLATE(PTR, FUNCTION) \ 331 1.1 christos do { \ 332 1.1 christos if (*(PTR) != NULL) { \ 333 1.1 christos FUNCTION(*PTR); \ 334 1.1 christos *(PTR) = NULL; \ 335 1.1 christos } \ 336 1.1 christos } while(0) 337 1.1 christos #endif 338 1.1 christos 339 1.1 christos #ifndef DNSServiceRefSourceForget 340 1.1 christos #define DNSServiceRefSourceForget(PTR) _SRP_STRICT_DISPOSE_TEMPLATE(PTR, DNSServiceRefDeallocate) 341 1.1 christos #endif 342 1.1 christos 343 1.1 christos 344 1.1 christos /*! 345 1.1 christos * @brief 346 1.1 christos * Check the required condition, if the required condition is not met go to the label specified. 347 1.1 christos * 348 1.1 christos * @param ASSERTION 349 1.1 christos * The condition that must be met before continue. 350 1.1 christos * 351 1.1 christos * @param EXCEPTION_LABEL 352 1.1 christos * The label to go to when the required condition ASSERTION is not met. 353 1.1 christos * 354 1.1 christos * @param ACTION 355 1.1 christos * The extra action to take before go to the EXCEPTION_LABEL label when ASSERTION is not met. 356 1.1 christos * 357 1.1 christos * @discussion 358 1.1 christos * Example: 359 1.1 christos * require_action_quiet( 360 1.1 christos * foo == NULL, // required to be true 361 1.1 christos * exit, // if not met goto label 362 1.1 christos * ret = -1; ERROR("foo should not be NULL") // before exiting 363 1.1 christos * ) ; 364 1.1 christos */ 365 1.1 christos #ifndef require_action_quiet 366 1.1 christos #define require_action_quiet(ASSERTION, EXCEPTION_LABEL, ACTION) \ 367 1.1 christos do { \ 368 1.1 christos if (__builtin_expect(!(ASSERTION), 0)) \ 369 1.1 christos { \ 370 1.1 christos { \ 371 1.1 christos ACTION; \ 372 1.1 christos } \ 373 1.1 christos goto EXCEPTION_LABEL; \ 374 1.1 christos } \ 375 1.1 christos } while(0) 376 1.1 christos #endif // #ifndef require_action 377 1.1 christos 378 1.1 christos #ifndef require_quiet 379 1.1 christos #define require_quiet(ASSERTION, EXCEPTION_LABEL) \ 380 1.1 christos do { \ 381 1.1 christos if (__builtin_expect(!(ASSERTION), 0)) \ 382 1.1 christos { \ 383 1.1 christos goto EXCEPTION_LABEL; \ 384 1.1 christos } \ 385 1.1 christos } while(0) 386 1.1 christos #endif // #ifndef require_action 387 1.1 christos 388 1.1 christos /*! 389 1.1 christos * @brief 390 1.1 christos * Check the required condition, if the required condition is not met go to the label specified. 391 1.1 christos * 392 1.1 christos * @param ASSERTION 393 1.1 christos * The condition that must be met before continue. 394 1.1 christos * 395 1.1 christos * @param EXCEPTION_LABEL 396 1.1 christos * The label to go to when the required condition ASSERTION is not met. 397 1.1 christos * 398 1.1 christos * @param ACTION 399 1.1 christos * The extra action to take before go to the EXCEPTION_LABEL label when ASSERTION is not met. 400 1.1 christos * 401 1.1 christos * @discussion 402 1.1 christos * Example: 403 1.1 christos * require_action( 404 1.1 christos * foo == NULL, // required to be true 405 1.1 christos * exit, // if not met goto label 406 1.1 christos * ret = -1; ERROR("foo should not be NULL") // before exiting 407 1.1 christos * ) ; 408 1.1 christos */ 409 1.1 christos #ifndef require_action 410 1.1 christos #define require_action(ASSERTION, EXCEPTION_LABEL, ACTION) \ 411 1.1 christos do { \ 412 1.1 christos if (__builtin_expect(!(ASSERTION), 0)) \ 413 1.1 christos { \ 414 1.1 christos { \ 415 1.1 christos ACTION; \ 416 1.1 christos } \ 417 1.1 christos goto EXCEPTION_LABEL; \ 418 1.1 christos } \ 419 1.1 christos } while(0) 420 1.1 christos #endif // #ifndef require_action 421 1.1 christos 422 1.1 christos /*! 423 1.1 christos * @brief 424 1.1 christos * Check the required condition, if the required condition is not met, do the ACTION. It is usually used as DEBUG macro. 425 1.1 christos * 426 1.1 christos * @param ASSERTION 427 1.1 christos * The condition that must be met before continue. 428 1.1 christos * 429 1.1 christos * @param ACTION 430 1.1 christos * The extra action to take when ASSERTION is not met. 431 1.1 christos * 432 1.1 christos * @discussion 433 1.1 christos * Example: 434 1.1 christos * verify_action( 435 1.1 christos * foo == NULL, // required to be true 436 1.1 christos * ERROR("foo should not be NULL") // action to take if required is false 437 1.1 christos * ) ; 438 1.1 christos */ 439 1.1 christos #undef verify_action 440 1.1 christos #define verify_action(ASSERTION, ACTION) \ 441 1.1 christos if (__builtin_expect(!(ASSERTION), 0)) { \ 442 1.1 christos ACTION; \ 443 1.1 christos } \ 444 1.1 christos else do {} while (0) 445 1.1 christos 446 1.1 christos // Print true or false based on boolean value: 447 1.1 christos static inline const char *bool_str(bool tf) { 448 1.1 christos if (tf) return "true"; 449 1.1 christos return "false"; 450 1.1 christos } 451 1.1 christos 452 1.1 christos 453 1.1 christos #ifdef __cplusplus 454 1.1 christos } // extern "C" 455 1.1 christos #endif 456 1.1 christos 457 1.1 christos #ifndef THREAD_DEVKIT_ADK 458 1.1 christos // Object type external definitions 459 1.1 christos #define OBJECT_TYPE(x) extern int x##_created, x##_finalized, old_##x##_created, old_##x##_finalized; 460 1.1 christos #include "object-types.h" 461 1.1 christos #endif // !THREAD_DEVKIT_ADK 462 1.1 christos 463 1.1 christos #endif // __SRP_H 464 1.1 christos 465 1.1 christos // Local Variables: 466 1.1 christos // mode: C 467 1.1 christos // tab-width: 4 468 1.1 christos // c-file-style: "bsd" 469 1.1 christos // c-basic-offset: 4 470 1.1 christos // fill-column: 108 471 1.1 christos // indent-tabs-mode: nil 472 1.1 christos // End: 473