Coverage Report

Created: 2026-07-16 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open62541_15/src/server/ua_server_utils.c
Line
Count
Source
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
 *
5
 *    Copyright 2016-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
6
 *    Copyright 2016 (c) Lorenz Haas
7
 *    Copyright 2017 (c) frax2222
8
 *    Copyright 2017 (c) Florian Palm
9
 *    Copyright 2017-2018 (c) Stefan Profanter, fortiss GmbH
10
 *    Copyright 2017 (c) Julian Grothoff
11
 */
12
13
#include "ua_server_internal.h"
14
15
/****************************/
16
/* Custom DataType Handling */
17
/****************************/
18
19
const UA_DataTypeArray *
20
21.7k
serverCustomTypes(UA_Server *server) {
21
21.7k
    if(server->customTypes_internalSize == 0)
22
21.7k
        return server->config.customDataTypes;
23
0
    server->customTypes_internal[server->customTypes_internalSize-1].next = server->config.customDataTypes;
24
0
    return server->customTypes_internal;
25
21.7k
}
26
27
const UA_DataTypeArray *
28
0
UA_Server_getDataTypes(UA_Server *server) {
29
0
    lockServer(server);
30
0
    const UA_DataTypeArray * out = serverCustomTypes(server);
31
0
    unlockServer(server);
32
0
    return out;
33
0
}
34
35
const UA_DataType *
36
0
UA_Server_findDataType(UA_Server *server, const UA_NodeId *typeId) {
37
0
    return UA_findDataTypeWithCustom(typeId, serverCustomTypes(server));
38
0
}
39
40
/* DataTypes need a stable pointer. So we allocate an array of 64 datatypes.
41
 * When that is full we move the server->customTypes_internal into a
42
 * heap-structure that gets cleaned up with the server lifecycle. */
43
static UA_StatusCode
44
0
addDataType(UA_Server *server, UA_DataType *dt) {
45
    /* Allocate the space for the new DataType */
46
0
#define TYPES_LIST_SIZE 64
47
0
    UA_DataTypeArray *current = NULL;
48
0
    if(server->customTypes_internalSize > 0)
49
0
        current = &server->customTypes_internal[server->customTypes_internalSize-1];
50
0
    if(!current || current->typesSize == TYPES_LIST_SIZE) {
51
        /* Increase the list-of-lists size */
52
0
        UA_DataTypeArray *lol = (UA_DataTypeArray*)
53
0
            UA_realloc(server->customTypes_internal,
54
0
                       sizeof(UA_DataTypeArray) * (server->customTypes_internalSize+1));
55
0
        if(!lol)
56
0
            return UA_STATUSCODE_BADOUTOFMEMORY;
57
0
        memset(&lol[server->customTypes_internalSize], 0, sizeof(UA_DataTypeArray));
58
0
        server->customTypes_internal = lol;
59
0
        server->customTypes_internalSize++;
60
61
        /* Update the next-pointers for the internal DataTypeArray */
62
0
        for(size_t i = 0; i < server->customTypes_internalSize-1; i++)
63
0
            lol[i].next = &lol[i+1];
64
65
        /* Add a new types list. With the space for the datatypes already appended */
66
0
        current = &server->customTypes_internal[server->customTypes_internalSize-1];
67
0
        current->types = (UA_DataType*)UA_calloc(TYPES_LIST_SIZE, sizeof(UA_DataType));
68
0
        current->typesSize = 0;
69
0
        if(!current->types) {
70
0
            server->customTypes_internalSize--;
71
0
            return UA_STATUSCODE_BADOUTOFMEMORY;
72
0
        }
73
0
    }
74
75
    /* Move the datatype into the stable location in the server */
76
0
    current->types[current->typesSize] = *dt;
77
0
    current->typesSize++;
78
0
    return UA_STATUSCODE_GOOD;
79
0
}
80
81
UA_StatusCode
82
UA_Server_addDataType(UA_Server *server, const UA_NodeId parentNodeId,
83
0
                      const UA_DataType *type) {
84
    /* Check that the type does not already exist. We do not allow changes to
85
     * DataTypes once they are set. */
86
0
    if(UA_Server_findDataType(server, &type->typeId))
87
0
        return UA_STATUSCODE_BADNODEIDEXISTS;
88
89
    /* Make a copy of the UA_DataType */
90
0
    UA_DataType dt2;
91
0
    UA_StatusCode res = UA_DataType_copy(type, &dt2);
92
0
    if(res != UA_STATUSCODE_GOOD)
93
0
        return res;
94
95
    /* Add the UA_DataType to the server */
96
0
    res = addDataType(server, &dt2);
97
0
    if(res != UA_STATUSCODE_GOOD)
98
0
        UA_DataType_clear(&dt2);
99
0
    return res;
100
0
}
101
102
UA_StatusCode
103
UA_Server_addDataTypeFromDescription(UA_Server *server,
104
0
                                     const UA_ExtensionObject *description) {
105
    /* Translate into a new UA_DataType */
106
0
    UA_DataType dt;
107
0
    UA_StatusCode res =
108
0
        UA_DataType_fromDescription(&dt, description, serverCustomTypes(server));
109
0
    if(res != UA_STATUSCODE_GOOD)
110
0
        return res;
111
112
    /* Check that the type does not already exist. We do not allow changes to
113
     * DataTypes once they are set. */
114
0
    if(UA_Server_findDataType(server, &dt.typeId)) {
115
0
        UA_DataType_clear(&dt);
116
0
        return UA_STATUSCODE_BADNODEIDEXISTS;
117
0
    }
118
119
    /* Add the UA_DataType to the server */
120
0
    res = addDataType(server, &dt);
121
0
    if(res != UA_STATUSCODE_GOOD)
122
0
        UA_DataType_clear(&dt);
123
0
    return res;
124
0
}
125
126
/********************************/
127
/* Information Model Operations */
128
/********************************/
129
130
struct ReturnTypeContext {
131
    UA_Server *server;
132
    UA_UInt32 attributeMask;
133
    UA_ReferenceTypeSet references;
134
    UA_BrowseDirection referenceDirections;
135
};
136
137
static void *
138
15.4M
returnFirstType(void *context, UA_ReferenceTarget *t) {
139
15.4M
    struct ReturnTypeContext *ctx = (struct ReturnTypeContext*)context;
140
    /* Don't release the node that is returned.
141
     * Continues to iterate if NULL is returned. */
142
15.4M
    return (void *)(uintptr_t)UA_NODESTORE_GETFROMREF_SELECTIVE(
143
15.4M
        ctx->server, t->targetId, ctx->attributeMask, ctx->references,
144
15.4M
        ctx->referenceDirections);
145
15.4M
}
146
147
const UA_Node *
148
getNodeType(UA_Server *server, const UA_NodeHead *head,
149
            UA_UInt32 attributeMask, UA_ReferenceTypeSet references,
150
15.4M
            UA_BrowseDirection referenceDirections) {
151
    /* The reference to the parent is different for variable and variabletype */
152
15.4M
    UA_Byte parentRefIndex;
153
15.4M
    UA_Boolean inverse;
154
15.4M
    switch(head->nodeClass) {
155
1.30M
    case UA_NODECLASS_OBJECT:
156
15.1M
    case UA_NODECLASS_VARIABLE:
157
15.1M
        parentRefIndex = UA_REFERENCETYPEINDEX_HASTYPEDEFINITION;
158
15.1M
        inverse = false;
159
15.1M
        break;
160
0
    case UA_NODECLASS_OBJECTTYPE:
161
326k
    case UA_NODECLASS_VARIABLETYPE:
162
326k
    case UA_NODECLASS_REFERENCETYPE:
163
326k
    case UA_NODECLASS_DATATYPE:
164
326k
        parentRefIndex = UA_REFERENCETYPEINDEX_HASSUBTYPE;
165
326k
        inverse = true;
166
326k
        break;
167
0
    default:
168
0
        return NULL;
169
15.4M
    }
170
171
15.4M
    struct ReturnTypeContext ctx;
172
15.4M
    ctx.server = server;
173
15.4M
    ctx.attributeMask = attributeMask;
174
15.4M
    ctx.references = references;
175
15.4M
    ctx.referenceDirections = referenceDirections;
176
177
    /* Return the first matching candidate */
178
31.3M
    for(size_t i = 0; i < head->referencesSize; ++i) {
179
31.3M
        UA_NodeReferenceKind *rk = &head->references[i];
180
31.3M
        if(rk->isInverse != inverse)
181
14.9M
            continue;
182
16.3M
        if(rk->referenceTypeIndex != parentRefIndex)
183
954k
            continue;
184
15.4M
        const UA_Node *type = (const UA_Node*)
185
15.4M
            UA_NodeReferenceKind_iterate(rk, returnFirstType, &ctx);
186
15.4M
        if(type)
187
15.4M
            return type;
188
15.4M
    }
189
190
17.6k
    return NULL;
191
15.4M
}
192
193
UA_Boolean
194
9.65k
UA_Node_hasSubTypeOrInstances(const UA_NodeHead *head) {
195
30.2k
    for(size_t i = 0; i < head->referencesSize; ++i) {
196
20.6k
        if(head->references[i].isInverse == false &&
197
10.9k
           head->references[i].referenceTypeIndex == UA_REFERENCETYPEINDEX_HASSUBTYPE)
198
2
            return true;
199
20.6k
        if(head->references[i].isInverse == true &&
200
9.65k
           head->references[i].referenceTypeIndex == UA_REFERENCETYPEINDEX_HASTYPEDEFINITION)
201
1
            return true;
202
20.6k
    }
203
9.65k
    return false;
204
9.65k
}
205
206
UA_StatusCode
207
getTypeAndInterfaceHierarchy(UA_Server *server, const UA_NodeId *leafNode,
208
                             UA_Boolean includeLeaf, UA_NodeId **typeHierarchy,
209
8.80M
                             size_t *typeHierarchySize) {
210
8.80M
    UA_ReferenceTypeSet hastype = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASTYPEDEFINITION);
211
8.80M
    UA_ReferenceTypeSet hassubtype = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE);
212
8.80M
    UA_ReferenceTypeSet hasinterface = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASINTERFACE);
213
214
    /* Initialize the tree and add the leaf */
215
8.80M
    RefTree rt;
216
8.80M
    UA_StatusCode res = RefTree_init(&rt);
217
8.80M
    if(res != UA_STATUSCODE_GOOD)
218
0
        return res;
219
8.80M
    res = RefTree_addNodeId(&rt, leafNode, NULL);
220
8.80M
    if(res != UA_STATUSCODE_GOOD)
221
0
        goto errout;
222
223
    /* Get all types */
224
8.80M
    res = browseRecursiveRefTree(server, &rt, UA_BROWSEDIRECTION_FORWARD, &hastype,
225
8.80M
                                 UA_NODECLASS_OBJECTTYPE | UA_NODECLASS_VARIABLETYPE);
226
8.80M
    if(res != UA_STATUSCODE_GOOD)
227
0
        goto errout;
228
229
    /* Get all super types */
230
8.80M
    res = browseRecursiveRefTree(server, &rt, UA_BROWSEDIRECTION_INVERSE, &hassubtype,
231
8.80M
                                 UA_NODECLASS_OBJECTTYPE | UA_NODECLASS_VARIABLETYPE);
232
8.80M
    if(res != UA_STATUSCODE_GOOD)
233
0
        goto errout;
234
235
    /* Get all interfaces */
236
8.80M
    res = browseRecursiveRefTree(server, &rt, UA_BROWSEDIRECTION_FORWARD, &hasinterface,
237
8.80M
                                 UA_NODECLASS_OBJECTTYPE | UA_NODECLASS_VARIABLETYPE);
238
239
8.80M
 errout:
240
8.80M
    if(res != UA_STATUSCODE_GOOD || rt.size == 0) {
241
0
        RefTree_clear(&rt);
242
0
        return res;
243
0
    }
244
245
    /* Make the array of ExpandedNodeId into an array of NodeId */
246
8.80M
    UA_NodeId *outArray = (UA_NodeId*)rt.targets;
247
8.80M
    size_t pos = 0;
248
26.9M
    for(size_t i = 0; i < rt.size; i++) {
249
18.1M
        UA_NodeId *n = &outArray[pos];
250
18.1M
        UA_ExpandedNodeId *e = &rt.targets[i];
251
18.1M
        if(!UA_ExpandedNodeId_isLocal(e)) {
252
0
            UA_ExpandedNodeId_clear(e);
253
0
            continue;
254
0
        }
255
18.1M
        *n = e->nodeId;
256
18.1M
        UA_String_clear(&e->namespaceUri);
257
18.1M
        pos++;
258
18.1M
    }
259
260
8.80M
    *typeHierarchySize = pos;
261
8.80M
    *typeHierarchy = outArray;
262
8.80M
    return UA_STATUSCODE_GOOD;
263
8.80M
}
264
265
UA_StatusCode
266
getAllInterfaces(UA_Server *server, const UA_NodeId *objectNode,
267
947k
                 UA_NodeId **interfaceNodes, size_t *interfaceNodesSize) {
268
947k
    UA_ReferenceTypeSet hastype = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASTYPEDEFINITION);
269
947k
    UA_ReferenceTypeSet hassubtype = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE);
270
947k
    UA_ReferenceTypeSet hasinterface = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASINTERFACE);
271
272
    /* Initialize the tree and add the leaf */
273
947k
    size_t beforeInterfaces = 0;
274
947k
    RefTree rt;
275
947k
    UA_StatusCode res = RefTree_init(&rt);
276
947k
    if(res != UA_STATUSCODE_GOOD)
277
0
        return res;
278
947k
    res = RefTree_addNodeId(&rt, objectNode, NULL);
279
947k
    if(res != UA_STATUSCODE_GOOD)
280
0
        goto errout;
281
282
    /* Get all types */
283
947k
    res = browseRecursiveRefTree(server, &rt, UA_BROWSEDIRECTION_FORWARD, &hastype,
284
947k
                                 UA_NODECLASS_OBJECTTYPE | UA_NODECLASS_VARIABLETYPE);
285
947k
    if(res != UA_STATUSCODE_GOOD)
286
0
        goto errout;
287
288
    /* Get all super types */
289
947k
    res = browseRecursiveRefTree(server, &rt, UA_BROWSEDIRECTION_INVERSE, &hassubtype,
290
947k
                                 UA_NODECLASS_OBJECTTYPE | UA_NODECLASS_VARIABLETYPE);
291
947k
    if(res != UA_STATUSCODE_GOOD)
292
0
        goto errout;
293
294
    /* Get all interfaces */
295
947k
    beforeInterfaces = rt.size; /* Return only the interfaces */
296
947k
    res = browseRecursiveRefTree(server, &rt, UA_BROWSEDIRECTION_FORWARD, &hasinterface,
297
947k
                                 UA_NODECLASS_OBJECTTYPE | UA_NODECLASS_VARIABLETYPE);
298
299
947k
 errout:
300
947k
    if(res != UA_STATUSCODE_GOOD || rt.size == 0) {
301
0
        RefTree_clear(&rt);
302
0
        return res;
303
0
    }
304
305
    /* Make the array of ExpandedNodeId into an array of NodeId */
306
947k
    UA_NodeId *outArray = (UA_NodeId*)rt.targets;
307
947k
    size_t pos = 0;
308
3.87M
    for(size_t i = 0; i < rt.size; i++) {
309
2.93M
        UA_NodeId *n = &outArray[pos];
310
2.93M
        UA_ExpandedNodeId *e = &rt.targets[i];
311
2.93M
        if(i < beforeInterfaces || !UA_ExpandedNodeId_isLocal(e)) {
312
2.93M
            UA_ExpandedNodeId_clear(e);
313
2.93M
            continue;
314
2.93M
        }
315
0
        *n = e->nodeId;
316
0
        UA_String_clear(&e->namespaceUri);
317
0
        pos++;
318
0
    }
319
320
    /* No interfaces found */
321
947k
    if(pos == 0) {
322
947k
        RefTree_clear(&rt);
323
947k
        outArray = NULL;
324
947k
    }
325
326
947k
    *interfaceNodesSize = pos;
327
947k
    *interfaceNodes = outArray;
328
947k
    return UA_STATUSCODE_GOOD;
329
947k
}
330
331
/* Get the node, make the changes and release */
332
UA_StatusCode
333
editNode(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
334
         UA_UInt32 attributeMask, UA_ReferenceTypeSet references,
335
         UA_BrowseDirection referenceDirections,
336
14.8M
         UA_EditNodeCallback callback, void *data) {
337
14.8M
    UA_Node *node =
338
14.8M
        UA_NODESTORE_GET_EDIT_SELECTIVE(server, nodeId, attributeMask,
339
14.8M
                                        references, referenceDirections);
340
14.8M
    if(!node)
341
12.5k
        return UA_STATUSCODE_BADNODEIDUNKNOWN;
342
14.8M
    UA_StatusCode retval = callback(server, session, node, data);
343
14.8M
    UA_NODESTORE_RELEASE(server, node);
344
14.8M
    return retval;
345
14.8M
}
346
347
/**************************/
348
/* Certificate Validation */
349
/**************************/
350
351
UA_StatusCode
352
validateCertificate(UA_Server *server, UA_CertificateGroup *cg,
353
                    UA_SecureChannel *channel, UA_Session *session,
354
                    const char *logPrefix,
355
                    const UA_ApplicationDescription *ad,
356
0
                    const UA_ByteString certificate) {
357
    /* Verify the ApplicationUri */
358
0
    UA_StatusCode res = UA_STATUSCODE_GOOD;
359
0
    if(ad) {
360
0
        res = UA_CertificateUtils_verifyApplicationUri(&certificate,
361
0
                                                       &ad->applicationUri);
362
0
        if(res != UA_STATUSCODE_GOOD) {
363
0
            if(server->config.allowAllCertificateUris <= UA_RULEHANDLING_WARN) {
364
0
                if(session) {
365
0
                    UA_LOG_ERROR_SESSION(server->config.logging, session,
366
0
                                         "%s: The client's ApplicationUri "
367
0
                                         "could not be verified against the "
368
0
                                         "ApplicationUri %S from the client's "
369
0
                                         "ApplicationDescription", logPrefix,
370
0
                                         ad->applicationUri);
371
0
                } else if(channel) {
372
0
                    UA_LOG_ERROR_CHANNEL(server->config.logging, channel,
373
0
                                         "%s: The client certificate's ApplicationUri "
374
0
                                         "could not be verified against the "
375
0
                                         "ApplicationUri %S from the client's "
376
0
                                         "ApplicationDescription", logPrefix,
377
0
                                         ad->applicationUri);
378
0
                } else {
379
0
                    UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER,
380
0
                                 "%s: The server certificate's ApplicationUri "
381
0
                                 "could not be verified against the "
382
0
                                 "ApplicationUri %S from its "
383
0
                                 "ApplicationDescription", logPrefix,
384
0
                                 ad->applicationUri);
385
0
                }
386
0
            }
387
0
            if(server->config.allowAllCertificateUris <= UA_RULEHANDLING_ABORT)
388
0
                return UA_STATUSCODE_BADCERTIFICATEINVALID;
389
0
        }
390
0
    }
391
392
0
    if(!cg->verifyCertificate) {
393
0
        UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER,
394
0
                     "%s: Could not validate the certificate "
395
0
                     "as the CertificateGroup is not configured", logPrefix);
396
0
        return UA_STATUSCODE_BADINTERNALERROR;
397
0
    }
398
399
    /* Validate in the CertificateGroup */
400
0
    res = cg->verifyCertificate(cg, &certificate);
401
0
    if(res != UA_STATUSCODE_GOOD) {
402
0
        const char *descr = UA_StatusCode_name(res);
403
0
        if(session) {
404
0
            UA_LOG_ERROR_SESSION(server->config.logging, session,
405
0
                                 "%s: The client certificate failed the verification "
406
0
                                 "in the CertificateGroup with StatusCode %s",
407
0
                                 logPrefix, descr);
408
0
        } else if(channel) {
409
0
            UA_LOG_ERROR_CHANNEL(server->config.logging, channel,
410
0
                                 "%s: The client certificate failed the verification "
411
0
                                 "in the CertificateGroup with StatusCode %s",
412
0
                                 logPrefix, descr);
413
0
        } else {
414
0
            UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER,
415
0
                         "%s: The client certificate failed the verification "
416
0
                         "in the CertificateGroup with StatusCode %s",
417
0
                         logPrefix, descr);
418
0
        }
419
0
    }
420
0
    return res;
421
0
}
422
423
/*********************************/
424
/* Default attribute definitions */
425
/*********************************/
426
427
const UA_ObjectAttributes UA_ObjectAttributes_default = {
428
    0,                      /* specifiedAttributes */
429
    {{0, NULL}, {0, NULL}}, /* displayName */
430
    {{0, NULL}, {0, NULL}}, /* description */
431
    0, 0,                   /* writeMask (userWriteMask) */
432
    0                       /* eventNotifier */
433
};
434
435
const UA_VariableAttributes UA_VariableAttributes_default = {
436
    0,                           /* specifiedAttributes */
437
    {{0, NULL}, {0, NULL}},      /* displayName */
438
    {{0, NULL}, {0, NULL}},      /* description */
439
    0, 0,                        /* writeMask (userWriteMask) */
440
    {NULL, UA_VARIANT_DATA,
441
     0, NULL, 0, NULL},          /* value */
442
    {0, UA_NODEIDTYPE_NUMERIC,
443
     {UA_NS0ID_BASEDATATYPE}},   /* dataType */
444
    UA_VALUERANK_ANY,            /* valueRank */
445
    0, NULL,                     /* arrayDimensions */
446
    UA_ACCESSLEVELMASK_READ |    /* accessLevel */
447
    UA_ACCESSLEVELMASK_STATUSWRITE |
448
    UA_ACCESSLEVELMASK_TIMESTAMPWRITE,
449
    0,                           /* userAccessLevel */
450
    0.0,                         /* minimumSamplingInterval */
451
    false                        /* historizing */
452
};
453
454
const UA_MethodAttributes UA_MethodAttributes_default = {
455
    0,                      /* specifiedAttributes */
456
    {{0, NULL}, {0, NULL}}, /* displayName */
457
    {{0, NULL}, {0, NULL}}, /* description */
458
    0, 0,                   /* writeMask (userWriteMask) */
459
    true, true              /* executable (userExecutable) */
460
};
461
462
const UA_ObjectTypeAttributes UA_ObjectTypeAttributes_default = {
463
    0,                      /* specifiedAttributes */
464
    {{0, NULL}, {0, NULL}}, /* displayName */
465
    {{0, NULL}, {0, NULL}}, /* description */
466
    0, 0,                   /* writeMask (userWriteMask) */
467
    false                   /* isAbstract */
468
};
469
470
const UA_VariableTypeAttributes UA_VariableTypeAttributes_default = {
471
    0,                           /* specifiedAttributes */
472
    {{0, NULL}, {0, NULL}},      /* displayName */
473
    {{0, NULL}, {0, NULL}},      /* description */
474
    0, 0,                        /* writeMask (userWriteMask) */
475
    {NULL, UA_VARIANT_DATA,
476
     0, NULL, 0, NULL},          /* value */
477
    {0, UA_NODEIDTYPE_NUMERIC,
478
     {UA_NS0ID_BASEDATATYPE}},   /* dataType */
479
    UA_VALUERANK_ANY,            /* valueRank */
480
    0, NULL,                     /* arrayDimensions */
481
    false                        /* isAbstract */
482
};
483
484
const UA_ReferenceTypeAttributes UA_ReferenceTypeAttributes_default = {
485
    0,                      /* specifiedAttributes */
486
    {{0, NULL}, {0, NULL}}, /* displayName */
487
    {{0, NULL}, {0, NULL}}, /* description */
488
    0, 0,                   /* writeMask (userWriteMask) */
489
    false,                  /* isAbstract */
490
    false,                  /* symmetric */
491
    {{0, NULL}, {0, NULL}}  /* inverseName */
492
};
493
494
const UA_DataTypeAttributes UA_DataTypeAttributes_default = {
495
    0,                      /* specifiedAttributes */
496
    {{0, NULL}, {0, NULL}}, /* displayName */
497
    {{0, NULL}, {0, NULL}}, /* description */
498
    0, 0,                   /* writeMask (userWriteMask) */
499
    false                   /* isAbstract */
500
};
501
502
const UA_ViewAttributes UA_ViewAttributes_default = {
503
    0,                      /* specifiedAttributes */
504
    {{0, NULL}, {0, NULL}}, /* displayName */
505
    {{0, NULL}, {0, NULL}}, /* description */
506
    0, 0,                   /* writeMask (userWriteMask) */
507
    false,                  /* containsNoLoops */
508
    0                       /* eventNotifier */
509
};
510