~ubuntu-branches/debian/experimental/ion/experimental

« back to all changes in this revision

Viewing changes to ams/library/amscommon.c

  • Committer: Package Import Robot
  • Author(s): Leo Iannacone
  • Date: 2012-02-01 09:46:31 UTC
  • Revision ID: package-import@ubuntu.com-20120201094631-qpfwehc1b7ftkjgx
Tags: upstream-2.5.3~dfsg1
ImportĀ upstreamĀ versionĀ 2.5.3~dfsg1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
        amscommon.c:    common functions used by libams, amsd,
 
3
                        and the transport service adapters.
 
4
 
 
5
        Author: Scott Burleigh, JPL
 
6
 
 
7
        Copyright (c) 2005, California Institute of Technology.
 
8
        ALL RIGHTS RESERVED.  U.S. Government Sponsorship
 
9
        acknowledged.
 
10
                                                                        */
 
11
#include "amscommon.h"
 
12
 
 
13
#define EPOCH_OFFSET_1958       (378691200)
 
14
#define MAX_GW_EID              (255)
 
15
 
 
16
extern void     destroyAmsEndpoint(LystElt elt, void *userdata);
 
17
 
 
18
static void     eraseContinuum(Continuum *contin)
 
19
{
 
20
        if (contin == NULL)
 
21
        {
 
22
                return;
 
23
        }
 
24
 
 
25
        if (contin->name)
 
26
        {
 
27
                MRELEASE(contin->name);
 
28
        }
 
29
 
 
30
        if (contin->description)
 
31
        {
 
32
                MRELEASE(contin->description);
 
33
        }
 
34
 
 
35
        MRELEASE(contin);
 
36
}
 
37
 
 
38
void    eraseSubject(Venture *venture, Subject *subj)
 
39
{
 
40
        if (venture == NULL || subj == NULL)
 
41
        {
 
42
                return;
 
43
        }
 
44
 
 
45
        if (subj->elt)          /*      Must remove from hashtable.     */
 
46
        {
 
47
                lyst_delete(subj->elt);
 
48
        }
 
49
 
 
50
        if (subj->name)
 
51
        {
 
52
                MRELEASE(subj->name);
 
53
        }
 
54
 
 
55
        if (subj->description)
 
56
        {
 
57
                MRELEASE(subj->description);
 
58
        }
 
59
 
 
60
        if (subj->symmetricKeyName)
 
61
        {
 
62
                MRELEASE(subj->symmetricKeyName);
 
63
        }
 
64
 
 
65
        if (subj->authorizedSenders)
 
66
        {
 
67
                lyst_destroy(subj->authorizedSenders);
 
68
        }
 
69
 
 
70
        if (subj->authorizedReceivers)
 
71
        {
 
72
                lyst_destroy(subj->authorizedReceivers);
 
73
        }
 
74
 
 
75
        if (subj->modules)
 
76
        {
 
77
                lyst_destroy(subj->modules);
 
78
        }
 
79
 
 
80
        venture->subjects[subj->nbr] = NULL;
 
81
        MRELEASE(subj);
 
82
}
 
83
 
 
84
void    eraseRole(Venture *venture, AppRole *role)
 
85
{
 
86
        if (venture == NULL || role == NULL)
 
87
        {
 
88
                return;
 
89
        }
 
90
 
 
91
        if (role->name)
 
92
        {
 
93
                MRELEASE(role->name);
 
94
        }
 
95
 
 
96
        if (role->publicKeyName)
 
97
        {
 
98
                MRELEASE(role->publicKeyName);
 
99
        }
 
100
 
 
101
        if (role->privateKeyName)
 
102
        {
 
103
                MRELEASE(role->privateKeyName);
 
104
        }
 
105
 
 
106
        venture->roles[role->nbr] = NULL;
 
107
        MRELEASE(role);
 
108
}
 
109
 
 
110
void    eraseMsgspace(Venture *venture, Subject *msgspace)
 
111
{
 
112
        if (venture == NULL || msgspace == NULL)
 
113
        {
 
114
                return;
 
115
        }
 
116
 
 
117
        if (msgspace->gwEid)
 
118
        {
 
119
                MRELEASE(msgspace->gwEid);
 
120
        }
 
121
 
 
122
        if (msgspace->symmetricKeyName)
 
123
        {
 
124
                MRELEASE(msgspace->symmetricKeyName);
 
125
        }
 
126
 
 
127
        if (msgspace->authorizedSenders)
 
128
        {
 
129
                lyst_destroy(msgspace->authorizedSenders);
 
130
        }
 
131
 
 
132
        if (msgspace->authorizedReceivers)
 
133
        {
 
134
                lyst_destroy(msgspace->authorizedReceivers);
 
135
        }
 
136
 
 
137
        if (msgspace->modules)
 
138
        {
 
139
                lyst_destroy(msgspace->modules);
 
140
        }
 
141
 
 
142
        venture->msgspaces[0 - msgspace->nbr] = NULL;
 
143
        MRELEASE(msgspace);
 
144
}
 
145
 
 
146
static void     eraseModule(Module *module)
 
147
{
 
148
        LystElt elt;
 
149
        LystElt nextElt;
 
150
 
 
151
        if (module->amsEndpoints)
 
152
        {
 
153
                for (elt = lyst_first(module->amsEndpoints); elt; elt = nextElt)
 
154
                {
 
155
                        nextElt = lyst_next(elt);
 
156
                        lyst_delete(elt);
 
157
                }
 
158
 
 
159
                lyst_destroy(module->amsEndpoints);
 
160
        }
 
161
 
 
162
        if (module->subjects)
 
163
        {
 
164
                for (elt = lyst_first(module->subjects); elt; elt = nextElt)
 
165
                {
 
166
                        nextElt = lyst_next(elt);
 
167
                        lyst_delete(elt);
 
168
                }
 
169
 
 
170
                lyst_destroy(module->subjects);
 
171
        }
 
172
 
 
173
        clearMamsEndpoint(&module->mamsEndpoint);
 
174
        module->role = NULL;
 
175
        MRELEASE(module);
 
176
}
 
177
 
 
178
void    eraseUnit(Venture *venture, Unit *unit)
 
179
{
 
180
        Cell    *cell;
 
181
        int     i;
 
182
        Unit    *superunit;
 
183
        LystElt elt;
 
184
        LystElt nextElt;
 
185
        Unit    *subunit;
 
186
 
 
187
        if (venture == NULL || unit == NULL)
 
188
        {
 
189
                return;
 
190
        }
 
191
 
 
192
        if (unit->name)
 
193
        {
 
194
                MRELEASE(unit->name);
 
195
        }
 
196
 
 
197
        /*      Erase all local cell data.                              */
 
198
 
 
199
        cell = unit->cell;
 
200
        clearMamsEndpoint(&cell->mamsEndpoint);
 
201
        for (i = 1; i <= MAX_MODULE_NBR; i++)
 
202
        {
 
203
                if (cell->modules[i])
 
204
                {
 
205
                        eraseModule(cell->modules[i]);
 
206
                }
 
207
        }
 
208
 
 
209
        /*      Reattach erased unit's subunits directly to its
 
210
         *      superunit, if any.                                      */
 
211
 
 
212
        superunit = unit->superunit;
 
213
        for (elt = lyst_first(unit->subunits); elt; elt = nextElt)
 
214
        {
 
215
                nextElt = lyst_next(elt);
 
216
                subunit = (Unit *) lyst_data(elt);
 
217
                lyst_delete(subunit->inclusionElt);
 
218
                if (superunit)
 
219
                {
 
220
                        subunit->inclusionElt =
 
221
                                lyst_insert_last(superunit->subunits, subunit);
 
222
                }
 
223
                else
 
224
                {
 
225
                        subunit->inclusionElt = NULL;
 
226
                }
 
227
 
 
228
                subunit->superunit = superunit;
 
229
        }
 
230
 
 
231
        lyst_destroy(unit->subunits);
 
232
 
 
233
        /*      Detach erased unit from its own superunit.              */
 
234
 
 
235
        if (unit->inclusionElt)
 
236
        {
 
237
                lyst_delete(unit->inclusionElt);
 
238
        }
 
239
 
 
240
        unit->superunit = NULL;
 
241
 
 
242
        /*      Erase the unit object itself.                           */
 
243
 
 
244
        venture->units[unit->nbr] = NULL;
 
245
        MRELEASE(unit);
 
246
}
 
247
 
 
248
void    eraseVenture(Venture *venture)
 
249
{
 
250
        int     i;
 
251
 
 
252
        if (venture == NULL)
 
253
        {
 
254
                return;
 
255
        }
 
256
 
 
257
        lockMib();
 
258
        if (venture->authorityName)
 
259
        {
 
260
                MRELEASE(venture->authorityName);
 
261
        }
 
262
 
 
263
        for (i = 0; i <= MAX_UNIT_NBR; i++)
 
264
        {
 
265
                eraseUnit(venture, venture->units[i]);
 
266
        }
 
267
 
 
268
        for (i = 1; i <= MAX_ROLE_NBR; i++)
 
269
        {
 
270
                if (venture->roles[i])
 
271
                {
 
272
                        eraseRole(venture, venture->roles[i]);
 
273
                }
 
274
        }
 
275
 
 
276
        for (i = 0; i <= MAX_SUBJ_NBR; i++)
 
277
        {
 
278
                if (venture->subjects[i])
 
279
                {
 
280
                        eraseSubject(venture, venture->subjects[i]);
 
281
                }
 
282
        }
 
283
 
 
284
        for (i = 0; i < SUBJ_LIST_CT; i++)
 
285
        {
 
286
                if (venture->subjLysts[i])
 
287
                {
 
288
                        lyst_destroy(venture->subjLysts[i]);
 
289
                }
 
290
        }
 
291
 
 
292
        for (i = 1; i <= MAX_CONTIN_NBR; i++)
 
293
        {
 
294
                if (venture->msgspaces[i])
 
295
                {
 
296
                        eraseMsgspace(venture, venture->msgspaces[i]);
 
297
                }
 
298
        }
 
299
 
 
300
        (_mib(NULL))->ventures[venture->nbr] = NULL;
 
301
        MRELEASE(venture);
 
302
        unlockMib();
 
303
}
 
304
 
 
305
static void     eraseMib(AmsMib *mib)
 
306
{
 
307
        int     i;
 
308
 
 
309
        /*      Note: no need to lockMib() because this function
 
310
         *      is called only from inside _mib(), which has
 
311
         *      already called lockMib().                               */
 
312
 
 
313
        if (mib->csPublicKeyName)
 
314
        {
 
315
                MRELEASE(mib->csPublicKeyName);
 
316
        }
 
317
 
 
318
        if (mib->csPrivateKeyName)
 
319
        {
 
320
                MRELEASE(mib->csPrivateKeyName);
 
321
        }
 
322
 
 
323
        if (mib->amsEndpointSpecs)
 
324
        {
 
325
                lyst_destroy(mib->amsEndpointSpecs);
 
326
        }
 
327
 
 
328
        if (mib->applications)
 
329
        {
 
330
                lyst_destroy(mib->applications);
 
331
        }
 
332
 
 
333
        if (mib->csEndpoints)
 
334
        {
 
335
                lyst_destroy(mib->csEndpoints);
 
336
        }
 
337
 
 
338
        for (i = 1; i <= MAX_CONTIN_NBR; i++)
 
339
        {
 
340
                if (mib->continua[i])
 
341
                {
 
342
                        eraseContinuum(mib->continua[i]);
 
343
                }
 
344
        }
 
345
 
 
346
        for (i = 1; i <= MAX_VENTURE_NBR; i++)
 
347
        {
 
348
                if (mib->ventures[i])
 
349
                {
 
350
                        eraseVenture(mib->ventures[i]);
 
351
                }
 
352
        }
 
353
 
 
354
        MRELEASE(mib);
 
355
}
 
356
 
 
357
static void     eraseAmsEpspec(AmsEpspec *amses)
 
358
{
 
359
        MRELEASE(amses);
 
360
}
 
361
 
 
362
static void     destroyAmsEpspec(LystElt elt, void *userdata)
 
363
{
 
364
        AmsEpspec       *amses = (AmsEpspec *) lyst_data(elt);
 
365
 
 
366
        eraseAmsEpspec(amses);
 
367
}
 
368
 
 
369
void    eraseApp(AmsApp *app)
 
370
{
 
371
        if (app == NULL)
 
372
        {
 
373
                return;
 
374
        }
 
375
 
 
376
        if (app->name)
 
377
        {
 
378
                MRELEASE(app->name);
 
379
        }
 
380
 
 
381
        if (app->publicKeyName)
 
382
        {
 
383
                MRELEASE(app->publicKeyName);
 
384
        }
 
385
 
 
386
        if (app->privateKeyName)
 
387
        {
 
388
                MRELEASE(app->privateKeyName);
 
389
        }
 
390
 
 
391
        MRELEASE(app);
 
392
}
 
393
 
 
394
static void     destroyApplication(LystElt elt, void *userdata)
 
395
{
 
396
        AmsApp  *app = (AmsApp *) lyst_data(elt);
 
397
 
 
398
        eraseApp(app);
 
399
}
 
400
 
 
401
static void     eraseCsEndpoint(MamsEndpoint *ep)
 
402
{
 
403
        clearMamsEndpoint(ep);
 
404
        MRELEASE(ep);
 
405
}
 
406
 
 
407
static void     destroyCsEndpoint(LystElt elt, void *userdata)
 
408
{
 
409
        MamsEndpoint    *ep = (MamsEndpoint *) lyst_data(elt);
 
410
 
 
411
        eraseCsEndpoint(ep);
 
412
}
 
413
 
 
414
#ifdef UDPTS
 
415
extern void             udptsLoadTs(TransSvc *ts);
 
416
#endif
 
417
#ifdef DGRTS
 
418
extern void             dgrtsLoadTs(TransSvc *ts);
 
419
#endif
 
420
#ifdef VMQTS
 
421
extern void             vmqtsLoadTs(TransSvc *ts);
 
422
#endif
 
423
#ifdef TCPTS
 
424
extern void             tcptsLoadTs(TransSvc *ts);
 
425
#endif
 
426
 
 
427
static void     addTs(AmsMib *mib, TsLoadFn loadTs)
 
428
{
 
429
        int             idx;
 
430
        TransSvc        *ts;
 
431
 
 
432
        /*      Note: no need to lockMib() because this function
 
433
         *      is called only from inside initializeMib(), which
 
434
         *      is only called from inside _mib(), which has
 
435
         *      already called lockMib().                               */
 
436
 
 
437
        idx = mib->transportServiceCount;
 
438
        ts = &(mib->transportServices[idx]);
 
439
        loadTs(ts);     /*      Execute the transport service loader.   */
 
440
        mib->transportServiceCount++;
 
441
}
 
442
 
 
443
static int      initializeMib(AmsMib *mib, int continuumNbr, char *ptsName,
 
444
                        char *pubkeyname, char *privkeyname)
 
445
{
 
446
        int                     amsMemory = getIonMemoryMgr();
 
447
        int                     i;
 
448
        int                     length;
 
449
 
 
450
        /*      Note: transport service loaders in this table appear
 
451
         *      in descending order of preference.  "Preference"
 
452
         *      corresponds broadly to nominal throughput rate.         */
 
453
 
 
454
        static TsLoadFn         transportServiceLoaders[] =
 
455
                                {
 
456
#ifdef UDPTS
 
457
                                        udptsLoadTs,
 
458
#endif
 
459
#ifdef DGRTS
 
460
                                        dgrtsLoadTs,
 
461
#endif
 
462
#ifdef VMQTS
 
463
                                        vmqtsLoadTs,
 
464
#endif
 
465
#ifdef TCPTS
 
466
                                        tcptsLoadTs
 
467
#endif
 
468
                                };
 
469
 
 
470
        static int              transportServiceCount =
 
471
                                        sizeof transportServiceLoaders /
 
472
                                        sizeof(TsLoadFn);
 
473
 
 
474
        /*      Note: no need to lockMib() because this function
 
475
         *      is called only from inside _mib(), which has already
 
476
         *      called lockMib().                                       */
 
477
 
 
478
        if (transportServiceCount > TS_INDEX_LIMIT)
 
479
        {
 
480
                putErrmsg("Transport service table overflow.", NULL);
 
481
                return -1;
 
482
        }
 
483
 
 
484
        for (i = 0; i < transportServiceCount; i++)
 
485
        {
 
486
                addTs(mib, transportServiceLoaders[i]);
 
487
                if (strcmp(mib->transportServices[i].name, ptsName) == 0)
 
488
                {
 
489
                        mib->pts = &(mib->transportServices[i]);
 
490
                }
 
491
        }
 
492
 
 
493
        if (mib->pts == NULL)
 
494
        {
 
495
                putErrmsg("No loader for primary transport service.", ptsName);
 
496
                return -1;
 
497
        }
 
498
 
 
499
        mib->amsEndpointSpecs = lyst_create_using(amsMemory);
 
500
        CHKERR(mib->amsEndpointSpecs);
 
501
        lyst_delete_set(mib->amsEndpointSpecs, destroyAmsEpspec, NULL);
 
502
        mib->applications = lyst_create_using(amsMemory);
 
503
        CHKERR(mib->applications);
 
504
        lyst_delete_set(mib->applications, destroyApplication, NULL);
 
505
        mib->csEndpoints = lyst_create_using(amsMemory);
 
506
        CHKERR(mib->csEndpoints);
 
507
        lyst_delete_set(mib->csEndpoints, destroyCsEndpoint, NULL);
 
508
        mib->localContinuumNbr = continuumNbr;
 
509
        if (pubkeyname)
 
510
        {
 
511
                length = strlen(pubkeyname) + 1;
 
512
                mib->csPublicKeyName = MTAKE(length);
 
513
                CHKERR(mib->csPublicKeyName);
 
514
                memcpy(mib->csPublicKeyName, pubkeyname, length);
 
515
        }
 
516
 
 
517
        if (privkeyname)
 
518
        {
 
519
                length = strlen(privkeyname) + 1;
 
520
                mib->csPrivateKeyName = MTAKE(length);
 
521
                CHKERR(mib->csPrivateKeyName);
 
522
                memcpy(mib->csPrivateKeyName, privkeyname, length);
 
523
        }
 
524
 
 
525
        if (createContinuum(continuumNbr, "local", 0, "this continuum") == NULL)
 
526
        {
 
527
                putErrmsg("Can't create local continuum object.", NULL);
 
528
                return -1;
 
529
        }
 
530
 
 
531
        return 0;
 
532
}
 
533
 
 
534
static int      initializeMemMgt(int continuumNbr)
 
535
{
 
536
        IonParms        ionParms;
 
537
 
 
538
        if (ionAttach() == 0)
 
539
        {
 
540
                return 0;               /*      ION is already started. */
 
541
        }
 
542
 
 
543
        writeMemo("[i] ION not started yet.  Starting ION from inside AMS.");
 
544
        if (readIonParms(NULL, &ionParms) < 0)
 
545
        {
 
546
                putErrmsg("AMS can't load ION parameters.", NULL);
 
547
                ionDetach();
 
548
                return -1;
 
549
        }
 
550
 
 
551
        if (ionInitialize(&ionParms, continuumNbr) < 0)
 
552
        {
 
553
                putErrmsg("AMS can't start ION.", itoa(continuumNbr));
 
554
                ionDetach();
 
555
                return -1;
 
556
        }
 
557
 
 
558
        return 0;
 
559
}
 
560
 
 
561
static void     _mibLock(int lock)
 
562
{
 
563
        static ResourceLock     mibLock;
 
564
 
 
565
        /*      The MIB is shared among threads, so access to it must
 
566
         *      be mutexed.                                             */
 
567
 
 
568
        if (initResourceLock(&mibLock) == 0)
 
569
        {
 
570
                switch (lock)
 
571
                {
 
572
                case -1:
 
573
                        killResourceLock(&mibLock);
 
574
                        break;
 
575
 
 
576
                case 0:
 
577
                        unlockResource(&mibLock);
 
578
                        break;
 
579
 
 
580
                default:
 
581
                        lockResource(&mibLock);
 
582
                }
 
583
        }
 
584
}
 
585
 
 
586
void    lockMib()
 
587
{
 
588
        _mibLock(1);
 
589
}
 
590
 
 
591
void    unlockMib()
 
592
{
 
593
        _mibLock(0);
 
594
}
 
595
 
 
596
AmsMib  *_mib(AmsMibParameters *parms)
 
597
{
 
598
        static AmsMib   *mib = NULL;
 
599
 
 
600
        if (parms)
 
601
        {
 
602
                lockMib();
 
603
                if (parms->continuumNbr == 0)   /*      Terminating.    */
 
604
                {
 
605
                        if (mib)
 
606
                        {
 
607
                                eraseMib(mib);
 
608
                                mib = NULL;
 
609
                        }
 
610
 
 
611
                        _mibLock(-1);
 
612
                        return mib;
 
613
                }
 
614
                else                            /*      Initializing.   */
 
615
                {
 
616
                        if (mib)
 
617
                        {
 
618
                                writeMemo("[i] AMS MIB already created.");
 
619
                        }
 
620
                        else
 
621
                        {
 
622
                                if (parms->continuumNbr < 1
 
623
                                || parms->continuumNbr > MAX_CONTIN_NBR
 
624
                                || parms->ptsName == NULL)
 
625
                                {
 
626
                                        putErrmsg("Invalid MIB parms.", NULL);
 
627
                                        _mibLock(-1);
 
628
                                        return mib;
 
629
                                }
 
630
 
 
631
                                if (initializeMemMgt(parms->continuumNbr) < 0)
 
632
                                {
 
633
                                        putErrmsg("Can't attach to ION.", NULL);
 
634
                                        _mibLock(-1);
 
635
                                        return mib;
 
636
                                }
 
637
 
 
638
                                mib = (AmsMib *) MTAKE(sizeof(AmsMib));
 
639
                                if (mib == NULL)
 
640
                                {
 
641
                                        putErrmsg("Can't create MIB.",
 
642
                                                        parms->ptsName);
 
643
                                        ionDetach();
 
644
                                        _mibLock(-1);
 
645
                                        return mib;
 
646
                                }
 
647
 
 
648
                                memset((char *) mib, 0, sizeof(AmsMib));
 
649
                                if (initializeMib(mib, parms->continuumNbr,
 
650
                                                parms->ptsName,
 
651
                                                parms->publicKeyName,
 
652
                                                parms->privateKeyName) < 0)
 
653
                                {
 
654
                                        putErrmsg("Can't initialize MIB.",
 
655
                                                        parms->ptsName);
 
656
                                        eraseMib(mib);
 
657
                                        ionDetach();
 
658
                                        mib = NULL;
 
659
                                        _mibLock(-1);
 
660
                                        return mib;
 
661
                                }
 
662
                        }
 
663
                }
 
664
 
 
665
                unlockMib();
 
666
        }
 
667
 
 
668
        return mib;
 
669
}
 
670
 
 
671
char    *_rejectionMemos(int idx)
 
672
{
 
673
        static char     *memos[] =      {
 
674
                                "not rejected",
 
675
                                "duplicate registrar",
 
676
                                "no cell census",
 
677
                                "cell is full",
 
678
                                "no such unit",
 
679
                                "unknown"
 
680
                                        };
 
681
        if (idx < 0 || idx > 4)
 
682
        {
 
683
                return memos[5];
 
684
        }
 
685
 
 
686
        return memos[idx];
 
687
}
 
688
 
 
689
/*      *       *       Checksum computation    *       *       *       */
 
690
 
 
691
unsigned short  computeAmsChecksum(unsigned char *cursor, int pduLength)
 
692
{
 
693
        unsigned int    sum = 0;
 
694
        unsigned short  addend;
 
695
 
 
696
        while (pduLength > 0)
 
697
        {
 
698
                addend = *cursor;
 
699
                addend <<= 8;   /*      Low-order byte is now zero pad. */
 
700
                cursor++;
 
701
                pduLength--;
 
702
                if (pduLength > 0)      /*      Replace pad with byte.  */
 
703
                {
 
704
                        addend += *cursor;
 
705
                        cursor++;
 
706
                        pduLength--;
 
707
                }
 
708
 
 
709
                sum += addend;          /*      Okay if it overflows.   */
 
710
        }
 
711
 
 
712
        return sum & 0x0000ffff;
 
713
}
 
714
 
 
715
/*      *       *       Conditions      *       *       *       *       */
 
716
 
 
717
int     time_to_stop(Llcv llcv)
 
718
{
 
719
        return 1;
 
720
}
 
721
 
 
722
int     llcv_reply_received(Llcv llcv)
 
723
{
 
724
        return (lyst_compare_get(llcv->list) == NULL ? 1 : 0);
 
725
}
 
726
 
 
727
/*      *       *       MIB lookup functions    *       *       *       */
 
728
 
 
729
static LystElt  findApplication(char *appName)
 
730
{
 
731
        LystElt elt;
 
732
        AmsApp  *app;
 
733
 
 
734
        lockMib();
 
735
        for (elt = lyst_first((_mib(NULL))->applications); elt;
 
736
                        elt = lyst_next(elt))
 
737
        {
 
738
                app = (AmsApp *) lyst_data(elt);
 
739
                if (strcmp(app->name, appName) == 0)
 
740
                {
 
741
                        unlockMib();
 
742
                        return elt;
 
743
                }
 
744
        }
 
745
 
 
746
        unlockMib();
 
747
        return NULL;
 
748
}
 
749
 
 
750
AmsApp  *lookUpApplication(char *appName)
 
751
{
 
752
        LystElt elt;
 
753
 
 
754
        elt = findApplication(appName);
 
755
        if (elt)
 
756
        {
 
757
                return (AmsApp *) lyst_data(elt);
 
758
        }
 
759
 
 
760
        return NULL;
 
761
}
 
762
 
 
763
static int      hashSubjectName(char *name)
 
764
{
 
765
        /*      Hash function adapted from Dr. Dobbs, April 1996.       */
 
766
 
 
767
        int             length = strlen(name);
 
768
        int             i = 0;
 
769
        unsigned int    h = 0;
 
770
        unsigned int    g = 0;
 
771
 
 
772
        for (i = 0; i < length; i++, name++)
 
773
        {
 
774
                h = (h << 4) + *name;
 
775
                g = h & 0xf0000000;
 
776
                if (g)
 
777
                {
 
778
                        h ^= g >> 24;
 
779
                }
 
780
 
 
781
                h &= ~g;
 
782
        }
 
783
        
 
784
        return h % SUBJ_LIST_CT;
 
785
}
 
786
 
 
787
Subject *lookUpSubject(Venture *venture, char *subjectName)
 
788
{
 
789
        int     idx;
 
790
        LystElt elt;
 
791
        Subject *subject;
 
792
 
 
793
        idx = hashSubjectName(subjectName);
 
794
        for (elt = lyst_first(venture->subjLysts[idx]); elt;
 
795
                        elt = lyst_next(elt))
 
796
        {
 
797
                subject = (Subject *) lyst_data(elt);
 
798
                if (strcmp(subject->name, subjectName) == 0)
 
799
                {
 
800
                        return subject;
 
801
                }
 
802
        }
 
803
 
 
804
        return NULL;
 
805
}
 
806
 
 
807
AppRole *lookUpRole(Venture *venture, char *roleName)
 
808
{
 
809
        int     i;
 
810
        AppRole *role;
 
811
 
 
812
        for (i = 1; i <= MAX_ROLE_NBR; i++)
 
813
        {
 
814
                role = venture->roles[i];
 
815
                if (role == NULL)
 
816
                {
 
817
                        continue;
 
818
                }
 
819
 
 
820
                if (strcmp(role->name, roleName) == 0)
 
821
                {
 
822
                        return role;
 
823
                }
 
824
        }
 
825
 
 
826
        return NULL;
 
827
}
 
828
 
 
829
Venture *lookUpVenture(char *appName, char *authName)
 
830
{
 
831
        int     i;
 
832
        Venture *venture;
 
833
 
 
834
        if (appName == NULL || authName == NULL)
 
835
        {
 
836
                return NULL;
 
837
        }
 
838
 
 
839
        lockMib();
 
840
        for (i = 1; i <= MAX_VENTURE_NBR; i++)
 
841
        {
 
842
                venture = (_mib(NULL))->ventures[i];
 
843
                if (venture == NULL)    /*      Number not in use.      */
 
844
                {
 
845
                        continue;
 
846
                }
 
847
 
 
848
                if (strcmp(venture->app->name, appName) == 0
 
849
                && strcmp(venture->authorityName, authName) == 0)
 
850
                {
 
851
                        unlockMib();
 
852
                        return venture;
 
853
                }
 
854
        }
 
855
 
 
856
        unlockMib();
 
857
        return NULL;
 
858
}
 
859
 
 
860
Unit    *lookUpUnit(Venture *venture, char *unitName)
 
861
{
 
862
        int     i;
 
863
        Unit    *unit;
 
864
 
 
865
        for (i = 0; i <= MAX_UNIT_NBR; i++)
 
866
        {
 
867
                unit = venture->units[i];
 
868
                if (unit == NULL)       /*      Number not in use.      */
 
869
                {
 
870
                        continue;
 
871
                }
 
872
 
 
873
                if (strcmp(unit->name, unitName) == 0)
 
874
                {
 
875
                        return unit;
 
876
                }
 
877
        }
 
878
 
 
879
        return NULL;
 
880
}
 
881
 
 
882
int     lookUpContinuum(char *contName)
 
883
{
 
884
        int             i;
 
885
        Continuum       *continuum;
 
886
 
 
887
        lockMib();
 
888
        for (i = 1; i <= MAX_CONTIN_NBR; i++)
 
889
        {
 
890
                continuum = (_mib(NULL))->continua[i];
 
891
                if (continuum == NULL)
 
892
                {
 
893
                        continue;       /*      Undefined continuum.    */
 
894
                }
 
895
 
 
896
                if (strcmp(continuum->name, contName) == 0)
 
897
                {
 
898
                        unlockMib();
 
899
                        return i;
 
900
                }
 
901
        }
 
902
 
 
903
        unlockMib();
 
904
        return -1;
 
905
}
 
906
 
 
907
static int      getKey(char *keyName, int *authKeyLen, char *authKey)
 
908
{
 
909
        int     keyLen;
 
910
 
 
911
        keyLen = sec_get_key(keyName, authKeyLen, authKey);
 
912
        if (keyLen <= 0)
 
913
        {
 
914
                return -1;
 
915
        }
 
916
 
 
917
        *authKeyLen = keyLen;
 
918
        return 0;
 
919
}
 
920
 
 
921
static int      getAuthenticationParms(int ventureNbr, int unitNbr, int roleNbr,
 
922
                        Venture **venture, Unit **unit, int sending,
 
923
                        char **authName, char *authKey, int *authKeyLen)
 
924
{
 
925
        AmsMib  *mib = _mib(NULL);
 
926
        AppRole *role = NULL;
 
927
        char    *keyName;
 
928
 
 
929
        *venture = NULL;
 
930
        *unit = NULL;
 
931
        *authName = NULL;
 
932
        lockMib();
 
933
        if (ventureNbr > 0)
 
934
        {
 
935
                if (ventureNbr > MAX_VENTURE_NBR
 
936
                || (*venture = mib->ventures[ventureNbr]) == NULL)
 
937
                {
 
938
                        writeMemoNote("[?] MAMS msg from unknown msgspace",
 
939
                                        itoa(ventureNbr));
 
940
                        unlockMib();
 
941
                        return 0;
 
942
                }
 
943
 
 
944
                if (unitNbr > MAX_UNIT_NBR
 
945
                || (*unit = (*venture)->units[unitNbr]) == NULL)
 
946
                {
 
947
                        writeMemoNote("[?] MAMS msg from unknown cell",
 
948
                                        itoa(unitNbr));
 
949
                        unlockMib();
 
950
                        return 0;
 
951
                }
 
952
        }
 
953
 
 
954
        if (roleNbr > 0)
 
955
        {
 
956
                if (roleNbr > MAX_ROLE_NBR || *venture == NULL
 
957
                || (role = (*venture)->roles[roleNbr]) == NULL)
 
958
                {
 
959
                        writeMemoNote("[?] MAMS message dropped; unknown role",
 
960
                                        itoa(roleNbr));
 
961
                        unlockMib();
 
962
                        return 0;
 
963
                }
 
964
        }
 
965
 
 
966
        if (role)               /*      Sender is module.               */
 
967
        {
 
968
                *authName = role->name;
 
969
                if (sending)
 
970
                {
 
971
                        keyName = role->privateKeyName;
 
972
                        if (keyName == NULL)
 
973
                        {
 
974
                                *authKeyLen = 0;
 
975
                        }
 
976
                        else if (getKey(keyName, authKeyLen, authKey) < 0)
 
977
                        {
 
978
                                writeMemoNote("[?] Can't get role private key", 
 
979
                                        role->privateKeyName);
 
980
                        }
 
981
                }
 
982
                else
 
983
                {
 
984
                        keyName = role->publicKeyName;
 
985
                        if (keyName == NULL)
 
986
                        {
 
987
                                *authKeyLen = 0;
 
988
                        }
 
989
                        else if (getKey(keyName, authKeyLen, authKey) < 0)
 
990
                        {
 
991
                                writeMemoNote("[?] Can't get role public key", 
 
992
                                        role->publicKeyName);
 
993
                        }
 
994
                }
 
995
        }
 
996
        else if (*venture)      /*      Sender is registrar.            */
 
997
        {
 
998
                *authName = (*venture)->app->name;
 
999
                if (sending)
 
1000
                {
 
1001
                        keyName = (*venture)->app->privateKeyName;
 
1002
                        if (keyName == NULL)
 
1003
                        {
 
1004
                                *authKeyLen = 0;
 
1005
                        }
 
1006
                        else if (getKey(keyName, authKeyLen, authKey) < 0)
 
1007
                        {
 
1008
                                writeMemoNote("[?] Can't get app private key", 
 
1009
                                        (*venture)->app->privateKeyName);
 
1010
                        }
 
1011
                }
 
1012
                else
 
1013
                {
 
1014
                        keyName = (*venture)->app->publicKeyName;
 
1015
                        if (keyName == NULL)
 
1016
                        {
 
1017
                                *authKeyLen = 0;
 
1018
                        }
 
1019
                        else if (getKey(keyName, authKeyLen, authKey) < 0)
 
1020
                        {
 
1021
                                writeMemoNote("[?] Can't get app public key", 
 
1022
                                        (*venture)->app->publicKeyName);
 
1023
                        }
 
1024
                }
 
1025
        }
 
1026
        else                    /*      Sender is CS.           */
 
1027
        {
 
1028
                *authName = mib->continua[mib->localContinuumNbr]->name;
 
1029
                if (sending)
 
1030
                {
 
1031
                        keyName = mib->csPrivateKeyName;
 
1032
                        if (keyName == NULL)
 
1033
                        {
 
1034
                                *authKeyLen = 0;
 
1035
                        }
 
1036
                        else if (getKey(keyName, authKeyLen, authKey) < 0)
 
1037
                        {
 
1038
                                writeMemoNote("[?] Can't get CS private key", 
 
1039
                                        mib->csPrivateKeyName);
 
1040
                        }
 
1041
                }
 
1042
                else
 
1043
                {
 
1044
                        keyName = mib->csPublicKeyName;
 
1045
                        if (keyName == NULL)
 
1046
                        {
 
1047
                                *authKeyLen = 0;
 
1048
                        }
 
1049
                        else if (getKey(keyName, authKeyLen, authKey) < 0)
 
1050
                        {
 
1051
                                writeMemoNote("[?] Can't get CS public key", 
 
1052
                                        mib->csPublicKeyName);
 
1053
                        }
 
1054
                }
 
1055
        }
 
1056
 
 
1057
        unlockMib();
 
1058
        return 0;
 
1059
}
 
1060
 
 
1061
/*      *       *       MIB loading functions   *       *       *       */
 
1062
 
 
1063
static RamsNetProtocol  parseGwEid(char *gwEidString, char **gwEid,
 
1064
                                char *gwEidBuffer)
 
1065
{
 
1066
        char            *atSign = NULL;
 
1067
        RamsNetProtocol protocol = RamsNoProtocol;      /*      default */
 
1068
        unsigned short  portNbr;
 
1069
        unsigned int    ipAddress;
 
1070
 
 
1071
        if (gwEidString == NULL || gwEid == NULL)
 
1072
        {
 
1073
                return protocol;
 
1074
        }
 
1075
 
 
1076
        *gwEid = NULL;                                  /*      default */
 
1077
        atSign = strchr(gwEidString, '@');
 
1078
        if (atSign == NULL)                     /*      Malformed.      */
 
1079
        {
 
1080
                return protocol;
 
1081
        }
 
1082
 
 
1083
        *gwEid = atSign + 1;
 
1084
        if (**gwEid == '\0'     /*      Endpoint ID is a NULL string.   */
 
1085
        || strlen(*gwEid) > MAX_GW_EID)         /*      Invalid.        */
 
1086
        {
 
1087
                return protocol;
 
1088
        }
 
1089
 
 
1090
        *atSign = '\0';
 
1091
        if (strcmp(gwEidString, "bp") == 0)
 
1092
        {
 
1093
                protocol = RamsBp;
 
1094
        }
 
1095
        else if (strcmp(gwEidString, "udp") == 0)
 
1096
        {
 
1097
                protocol = RamsUdp;
 
1098
 
 
1099
                /*      Must convert to canonical hostnbr:portnbr
 
1100
                 *      form to enable recvfrom lookup to succeed.      */
 
1101
 
 
1102
                parseSocketSpec(*gwEid, &portNbr, &ipAddress);
 
1103
                isprintf(gwEidBuffer, MAX_GW_EID + 1, "%u:%hu", ipAddress,
 
1104
                                portNbr);
 
1105
                *gwEid = gwEidBuffer;
 
1106
        }
 
1107
 
 
1108
        *atSign = '@';          /*      Restore original string.        */
 
1109
        return protocol;
 
1110
}
 
1111
 
 
1112
static void     destroyFanModule(LystElt elt, void *userdata)
 
1113
{
 
1114
        FanModule       *fan = (FanModule *) lyst_data(elt);
 
1115
 
 
1116
        MRELEASE(fan);
 
1117
}
 
1118
 
 
1119
Subject *createSubject(Venture *venture, int nbr, char *name,
 
1120
                char *description, char *symmetricKeyName,
 
1121
                char *marshalFnName, char *unmarshalFnName)
 
1122
{
 
1123
        int     amsMemory = getIonMemoryMgr();
 
1124
        int     length;
 
1125
        Subject *subj;
 
1126
        int     idx;
 
1127
 
 
1128
        CHKNULL(venture);
 
1129
        CHKNULL(nbr >= 0);
 
1130
        CHKNULL(nbr <= MAX_SUBJ_NBR);
 
1131
        CHKNULL(venture->subjects[nbr] == NULL);
 
1132
        CHKNULL(name);
 
1133
        length = strlen(name);
 
1134
        CHKNULL(length <= MAX_SUBJ_NAME);
 
1135
        subj = (Subject *) MTAKE(sizeof(Subject));
 
1136
        CHKNULL(subj);
 
1137
        memset((char *) subj, 0, sizeof(Subject));
 
1138
        subj->nbr = nbr;
 
1139
        subj->isContinuum = 0;
 
1140
        length += 1;
 
1141
        subj->name = MTAKE(length);
 
1142
        CHKNULL(subj->name);
 
1143
        istrcpy(subj->name, name, length);
 
1144
        if (description)
 
1145
        {
 
1146
                length = strlen(description) + 1;
 
1147
                subj->description = MTAKE(length);
 
1148
                CHKNULL(subj->description);
 
1149
                istrcpy(subj->description, description, length);
 
1150
        }
 
1151
 
 
1152
        if (symmetricKeyName)
 
1153
        {
 
1154
                length = strlen(symmetricKeyName) + 1;
 
1155
                subj->symmetricKeyName = MTAKE(length);
 
1156
                CHKNULL(subj->symmetricKeyName);
 
1157
                memcpy(subj->symmetricKeyName, symmetricKeyName, length);
 
1158
        }
 
1159
 
 
1160
        if (marshalFnName)
 
1161
        {
 
1162
                length = strlen(marshalFnName) + 1;
 
1163
                subj->marshalFnName = MTAKE(length);
 
1164
                CHKNULL(subj->marshalFnName);
 
1165
                memcpy(subj->marshalFnName, marshalFnName, length);
 
1166
        }
 
1167
 
 
1168
        if (unmarshalFnName)
 
1169
        {
 
1170
                length = strlen(unmarshalFnName) + 1;
 
1171
                subj->unmarshalFnName = MTAKE(length);
 
1172
                CHKNULL(subj->unmarshalFnName);
 
1173
                memcpy(subj->unmarshalFnName, unmarshalFnName, length);
 
1174
        }
 
1175
 
 
1176
        subj->authorizedSenders = NULL;
 
1177
        subj->authorizedReceivers = NULL;
 
1178
        subj->modules = lyst_create_using(amsMemory);
 
1179
        CHKNULL(subj->modules);
 
1180
        lyst_delete_set(subj->modules, destroyFanModule, NULL);
 
1181
        venture->subjects[nbr] = subj;
 
1182
        idx = hashSubjectName(name);
 
1183
        subj->elt = lyst_insert_last(venture->subjLysts[idx], subj);
 
1184
        CHKNULL(subj->elt);
 
1185
        return subj;
 
1186
}
 
1187
 
 
1188
AppRole *createRole(Venture *venture, int nbr, char *name, char *publicKeyName,
 
1189
                char *privateKeyName)
 
1190
{
 
1191
        int     length;
 
1192
        AppRole *role;
 
1193
 
 
1194
        CHKNULL(venture);
 
1195
        CHKNULL(nbr > 0);
 
1196
        CHKNULL(nbr <= MAX_ROLE_NBR);
 
1197
        CHKNULL(venture->roles[nbr] == NULL);
 
1198
        CHKNULL(name);
 
1199
        length = strlen(name);
 
1200
        CHKNULL(length <= MAX_ROLE_NAME);
 
1201
        role = (AppRole *) MTAKE(sizeof(AppRole));
 
1202
        CHKNULL(role);
 
1203
        memset((char *) role, 0, sizeof(AppRole));
 
1204
        role->nbr = nbr;
 
1205
        length += 1;
 
1206
        role->name = MTAKE(length);
 
1207
        CHKNULL(role->name);
 
1208
        istrcpy(role->name, name, length);
 
1209
        if (publicKeyName)
 
1210
        {
 
1211
                length = strlen(publicKeyName) + 1;
 
1212
                role->publicKeyName = MTAKE(length);
 
1213
                CHKNULL(role->publicKeyName);
 
1214
                memcpy(role->publicKeyName, publicKeyName, length);
 
1215
        }
 
1216
 
 
1217
        if (privateKeyName)
 
1218
        {
 
1219
                length = strlen(privateKeyName) + 1;
 
1220
                role->privateKeyName = MTAKE(length);
 
1221
                CHKNULL(role->privateKeyName);
 
1222
                memcpy(role->privateKeyName, privateKeyName, length);
 
1223
        }
 
1224
 
 
1225
        venture->roles[nbr] = role;
 
1226
        return role;
 
1227
}
 
1228
 
 
1229
static void     deleteAuthorization(char *roleName, Lyst *authorizations)
 
1230
{
 
1231
        LystElt elt;
 
1232
        char    *name;
 
1233
        int     result;
 
1234
 
 
1235
        CHKVOID(roleName);
 
1236
        for (elt = lyst_first(*authorizations); elt; elt = lyst_next(elt))
 
1237
        {
 
1238
                name = (char *) lyst_data(elt);
 
1239
                result = strcmp(name, roleName);
 
1240
                if (result < 0)         /*      Try the next one.       */
 
1241
                {
 
1242
                        continue;
 
1243
                }
 
1244
 
 
1245
                if (result == 0)
 
1246
                {
 
1247
                        break;
 
1248
                }
 
1249
 
 
1250
                return;                 /*      Already deleted.        */
 
1251
        }
 
1252
 
 
1253
        name = (char *) lyst_data(elt);
 
1254
        MRELEASE(name);
 
1255
        lyst_delete(elt);
 
1256
        if (lyst_length(*authorizations) == 0)
 
1257
        {
 
1258
                lyst_destroy(*authorizations);
 
1259
                *authorizations = NULL;
 
1260
        }
 
1261
}
 
1262
 
 
1263
void    deleteAuthorizedSender(Subject *subj, char *senderRoleName)
 
1264
{
 
1265
        CHKVOID(subj);
 
1266
        deleteAuthorization(senderRoleName, &subj->authorizedSenders);
 
1267
}
 
1268
 
 
1269
void    deleteAuthorizedReceiver(Subject *subj, char *receiverRoleName)
 
1270
{
 
1271
        CHKVOID(subj);
 
1272
        deleteAuthorization(receiverRoleName, &subj->authorizedReceivers);
 
1273
}
 
1274
 
 
1275
static void     destroyAuthorization(LystElt elt, void *userdata)
 
1276
{
 
1277
        char    *roleName = (char *) lyst_data(elt);
 
1278
 
 
1279
        MRELEASE(roleName);
 
1280
}
 
1281
 
 
1282
static int      addAuthorization(Venture *venture, char *roleName,
 
1283
                        Lyst *authorizations)
 
1284
{
 
1285
        LystElt elt;
 
1286
        char    *name;
 
1287
        int     result;
 
1288
        int     length;
 
1289
 
 
1290
        CHKERR(venture);
 
1291
        CHKERR(roleName);
 
1292
        if (lookUpRole(venture, roleName) == NULL)
 
1293
        {
 
1294
                return -1;
 
1295
        }
 
1296
 
 
1297
        if (*authorizations == NULL)
 
1298
        {
 
1299
                *authorizations = lyst_create_using(getIonMemoryMgr());
 
1300
                CHKERR(*authorizations);
 
1301
                lyst_delete_set(*authorizations, destroyAuthorization,
 
1302
                                NULL);
 
1303
        }
 
1304
 
 
1305
        for (elt = lyst_first(*authorizations); elt; elt = lyst_next(elt))
 
1306
        {
 
1307
                name = (char *) lyst_data(elt);
 
1308
                result = strcmp(name, roleName);
 
1309
                if (result < 0)         /*      Try the next one.       */
 
1310
                {
 
1311
                        continue;
 
1312
                }
 
1313
 
 
1314
                if (result == 0)
 
1315
                {
 
1316
                        return 0;       /*      Already in list.        */
 
1317
                }
 
1318
 
 
1319
                break;                  /*      Insert before this one. */
 
1320
        }
 
1321
 
 
1322
        length = strlen(roleName);
 
1323
        name = MTAKE(length + 1);
 
1324
        CHKERR(name);
 
1325
        istrcpy(name, roleName, length + 1);
 
1326
        if (elt)
 
1327
        {
 
1328
                elt = lyst_insert_before(elt, name);
 
1329
        }
 
1330
        else
 
1331
        {
 
1332
                elt = lyst_insert_last(*authorizations, name);
 
1333
        }
 
1334
 
 
1335
        if (elt == NULL)
 
1336
        {
 
1337
                MRELEASE(name);
 
1338
                return -1;
 
1339
        }
 
1340
 
 
1341
        return 0;
 
1342
}
 
1343
 
 
1344
int     addAuthorizedSender(Venture *venture, Subject *subj,
 
1345
                char *senderRoleName)
 
1346
{
 
1347
        CHKERR(subj);
 
1348
        return addAuthorization(venture, senderRoleName,
 
1349
                        &(subj->authorizedSenders));
 
1350
}
 
1351
 
 
1352
int     addAuthorizedReceiver(Venture *venture, Subject *subj,
 
1353
                char *receiverRoleName)
 
1354
{
 
1355
        CHKERR(subj);
 
1356
        return addAuthorization(venture, receiverRoleName,
 
1357
                        &(subj->authorizedReceivers));
 
1358
}
 
1359
 
 
1360
LystElt createApp(char *name, char *publicKeyName, char *privateKeyName)
 
1361
{
 
1362
        int     length;
 
1363
        AmsApp  *app;
 
1364
        LystElt elt;
 
1365
 
 
1366
        CHKNULL(name);
 
1367
        length = strlen(name);
 
1368
        CHKNULL(length <= MAX_APP_NAME);
 
1369
        app = (AmsApp *) MTAKE(sizeof(AmsApp));
 
1370
        CHKNULL(app);
 
1371
        memset((char *) app, 0, sizeof(AmsApp));
 
1372
        length += 1;
 
1373
        app->name = MTAKE(length);
 
1374
        CHKNULL(app->name);
 
1375
        istrcpy(app->name, name, length);
 
1376
        if (publicKeyName)
 
1377
        {
 
1378
                length = strlen(publicKeyName) + 1;
 
1379
                app->publicKeyName = MTAKE(length);
 
1380
                CHKNULL(app->publicKeyName);
 
1381
                memcpy(app->publicKeyName, publicKeyName, length);
 
1382
        }
 
1383
 
 
1384
        if (privateKeyName)
 
1385
        {
 
1386
                length = strlen(privateKeyName) + 1;
 
1387
                app->privateKeyName = MTAKE(length);
 
1388
                CHKNULL(app->privateKeyName);
 
1389
                memcpy(app->privateKeyName, privateKeyName, length);
 
1390
        }
 
1391
 
 
1392
        lockMib();
 
1393
        elt = lyst_insert_last((_mib(NULL))->applications, app);
 
1394
        unlockMib();
 
1395
        CHKNULL(elt);
 
1396
        return elt;
 
1397
}
 
1398
 
 
1399
Subject *createMsgspace(Venture *venture, int continNbr, char *gwEidString,
 
1400
                char *symmetricKeyName)
 
1401
{
 
1402
        int             amsMemory = getIonMemoryMgr();
 
1403
        Subject         *msgspace;
 
1404
        RamsNetProtocol ramsProtocol;
 
1405
        char            *gwEid;
 
1406
        char            gwEidBuffer[MAX_GW_EID + 1];
 
1407
        int             length;
 
1408
 
 
1409
        CHKNULL(venture);
 
1410
        CHKNULL(continNbr > 0);
 
1411
        CHKNULL(continNbr <= MAX_CONTIN_NBR);
 
1412
        CHKNULL((_mib(NULL))->continua[continNbr] != NULL);
 
1413
        CHKNULL(venture->msgspaces[continNbr] == NULL);
 
1414
        msgspace = (Subject *) MTAKE(sizeof(Subject));
 
1415
        CHKNULL(msgspace);
 
1416
        memset((char *) msgspace, 0, sizeof(Subject));
 
1417
        msgspace->nbr = 0 - continNbr;  /*      Negative subj number.   */
 
1418
        msgspace->isContinuum = 1;
 
1419
        ramsProtocol = parseGwEid(gwEidString, &gwEid, gwEidBuffer);
 
1420
        if (ramsProtocol == RamsNoProtocol)
 
1421
        {
 
1422
                ramsProtocol = RamsBp;
 
1423
                isprintf(gwEidBuffer, sizeof gwEidBuffer, "ipn:%d.%d",
 
1424
                                continNbr, venture->nbr);
 
1425
                gwEid = gwEidBuffer;
 
1426
        }
 
1427
 
 
1428
        length = strlen(gwEid) + 1;
 
1429
        msgspace->gwEid = MTAKE(length);
 
1430
        CHKNULL(msgspace->gwEid);
 
1431
        istrcpy(msgspace->gwEid, gwEid, length);
 
1432
        if (symmetricKeyName)
 
1433
        {
 
1434
                length = strlen(symmetricKeyName) + 1;
 
1435
                msgspace->symmetricKeyName = MTAKE(length);
 
1436
                CHKNULL(msgspace->symmetricKeyName);
 
1437
                memcpy(msgspace->symmetricKeyName, symmetricKeyName, length);
 
1438
        }
 
1439
 
 
1440
        msgspace->authorizedSenders = NULL;
 
1441
        msgspace->authorizedReceivers = NULL;
 
1442
        msgspace->modules = lyst_create_using(amsMemory);
 
1443
        CHKNULL(msgspace->modules);
 
1444
        lyst_delete_set(msgspace->modules, destroyFanModule, NULL);
 
1445
        venture->msgspaces[continNbr] = msgspace;
 
1446
        return msgspace;
 
1447
}
 
1448
 
 
1449
static void     destroySubjOfInterest(LystElt elt, void *userdata)
 
1450
{
 
1451
        SubjOfInterest  *subj = (SubjOfInterest *) lyst_data(elt);
 
1452
 
 
1453
        lyst_destroy(subj->subscriptions);
 
1454
        lyst_destroy(subj->invitations);
 
1455
        lyst_delete(subj->fanElt);
 
1456
        MRELEASE(subj);
 
1457
}
 
1458
 
 
1459
static Module   *createModule(Cell *cell, int moduleNbr)
 
1460
{
 
1461
        int     amsMemory = getIonMemoryMgr();
 
1462
        Module  *module;
 
1463
 
 
1464
        module = (Module *) MTAKE(sizeof(Module));
 
1465
        CHKNULL(module);
 
1466
        memset((char *) module, 0, sizeof(Module));
 
1467
        module->unitNbr = cell->unit->nbr;
 
1468
        module->nbr = moduleNbr;
 
1469
        module->role = NULL;
 
1470
        module->amsEndpoints = lyst_create_using(amsMemory);
 
1471
        CHKNULL(module->amsEndpoints);
 
1472
        lyst_delete_set(module->amsEndpoints, destroyAmsEndpoint, NULL);
 
1473
        module->subjects = lyst_create_using(amsMemory);
 
1474
        CHKNULL(module->subjects);
 
1475
        lyst_delete_set(module->subjects, destroySubjOfInterest, NULL);
 
1476
        cell->modules[moduleNbr] = module;
 
1477
        return module;
 
1478
}
 
1479
 
 
1480
static Unit     *initializeUnit(Venture *venture, int nbr, char *name,
 
1481
                        int length, int resyncPeriod, Unit *superunit,
 
1482
                        Lyst subunits)
 
1483
{
 
1484
        Unit    *unit;
 
1485
        int     nameLen;
 
1486
        Cell    *cell;
 
1487
        int     i;
 
1488
        LystElt elt;
 
1489
        LystElt nextElt;
 
1490
        Unit    *subunit;
 
1491
 
 
1492
        unit = (Unit *) MTAKE(sizeof(Unit));
 
1493
        CHKNULL(unit);
 
1494
        memset((char *) unit, 0, sizeof(Unit));
 
1495
        unit->cell = &(unit->cellData);
 
1496
        cell = unit->cell;
 
1497
        cell->unit = unit;
 
1498
        unit->nbr = nbr;
 
1499
        nameLen = length + 1;
 
1500
        unit->name = MTAKE(nameLen);
 
1501
        CHKNULL(unit->name);
 
1502
        istrcpy(unit->name, name, nameLen);
 
1503
 
 
1504
        /*      Initialize cell data of unit.                           */
 
1505
 
 
1506
        for (i = 1; i <= MAX_MODULE_NBR; i++)
 
1507
        {
 
1508
                if (createModule(cell, i) < 0)
 
1509
                {
 
1510
                        eraseUnit(venture, unit);
 
1511
                        return NULL;
 
1512
                }
 
1513
        }
 
1514
 
 
1515
        cell->resyncPeriod = resyncPeriod;
 
1516
 
 
1517
        /*      Insert new unit as subunit of its superunit.            */
 
1518
 
 
1519
        unit->superunit = superunit;
 
1520
        if (superunit != NULL)
 
1521
        {
 
1522
                unit->inclusionElt = lyst_insert_last(superunit->subunits,
 
1523
                                unit);
 
1524
                CHKNULL(unit->inclusionElt);
 
1525
        }
 
1526
 
 
1527
        /*      Assert new unit as superunit of its subunits.           */
 
1528
 
 
1529
        for (elt = lyst_first(subunits); elt; elt = nextElt)
 
1530
        {
 
1531
                nextElt = lyst_next(elt);
 
1532
                subunit = (Unit *) lyst_data(elt);
 
1533
                if (subunit->superunit != superunit)
 
1534
                {
 
1535
                        /*      This is a subunit of some subunit of
 
1536
                         *      the new unit, not of the new unit
 
1537
                         *      directly.                               */
 
1538
 
 
1539
                        lyst_delete(elt);
 
1540
                        continue;
 
1541
                }
 
1542
 
 
1543
                /*      Detach this unit from its current superunit
 
1544
                 *      (the new module's superunit) and insert it as
 
1545
                 *      a subunit of the new unit.                      */
 
1546
 
 
1547
                lyst_delete(subunit->inclusionElt);
 
1548
                subunit->inclusionElt = elt;
 
1549
                subunit->superunit = unit;
 
1550
        }
 
1551
 
 
1552
        unit->subunits = subunits;
 
1553
        venture->units[nbr] = unit;
 
1554
        return unit;
 
1555
}
 
1556
 
 
1557
Unit    *createUnit(Venture *venture, int nbr, char *name, int resyncPeriod)
 
1558
{
 
1559
        int     namelen;
 
1560
        int     i;
 
1561
        Lyst    subunits;
 
1562
        int     bestLength;
 
1563
        Unit    *superunit;
 
1564
        Unit    *unit;
 
1565
        int     j;
 
1566
 
 
1567
        CHKNULL(venture);
 
1568
        CHKNULL(nbr > 0);
 
1569
        CHKNULL(nbr <= MAX_UNIT_NBR);
 
1570
        CHKNULL(venture->units[nbr] == NULL);
 
1571
        CHKNULL(name);
 
1572
        namelen = strlen(name);
 
1573
        CHKNULL(namelen > 0);
 
1574
        CHKNULL(namelen <= MAX_UNIT_NAME);
 
1575
        CHKNULL(resyncPeriod >= 0);
 
1576
 
 
1577
        /*      Unit whose name is the longest prefix of the new
 
1578
         *      unit's name is the new unit's superunit.  Every
 
1579
         *      unit whose name is prefixed by the new unit's name
 
1580
         *      is a candidate subunit of the new unit.                 */
 
1581
 
 
1582
        subunits = lyst_create_using(getIonMemoryMgr());
 
1583
        CHKNULL(subunits);
 
1584
        bestLength = 0;
 
1585
        superunit = venture->units[0];  /*      Default is root cell.   */
 
1586
        for (i = 0; i <= MAX_UNIT_NBR; i++)
 
1587
        {
 
1588
                if ((unit = venture->units[i]) == NULL) continue;
 
1589
                for (j= 0;; j++)
 
1590
                {
 
1591
                        if (unit->name[j] == '\0')
 
1592
                        {
 
1593
                                if (j > bestLength)
 
1594
                                {
 
1595
                                        /*      May be the superunit.   */
 
1596
 
 
1597
                                        bestLength = j;
 
1598
                                        superunit = unit;
 
1599
                                }
 
1600
 
 
1601
                                break;
 
1602
                        }
 
1603
 
 
1604
                        if (name[j] == '\0')
 
1605
                        {
 
1606
                                /*      May be a subunit.               */
 
1607
 
 
1608
                                if (lyst_insert_last(subunits, unit) == NULL)
 
1609
                                {
 
1610
                                        lyst_destroy(subunits);
 
1611
                                        return NULL;
 
1612
                                }
 
1613
 
 
1614
                                break;
 
1615
                        }
 
1616
 
 
1617
                        if (unit->name[j] != name[j])
 
1618
                        {
 
1619
                                break;
 
1620
                        }
 
1621
                }
 
1622
        }
 
1623
 
 
1624
        if (bestLength == namelen)      /*      Perfect match for name. */
 
1625
        {
 
1626
                writeMemoNote("[?] Duplicate unit name", name);
 
1627
                lyst_destroy(subunits);
 
1628
                return NULL;
 
1629
        }
 
1630
 
 
1631
        unit = initializeUnit(venture, nbr, name, namelen, resyncPeriod,
 
1632
                        superunit, subunits);
 
1633
        if (unit == NULL)
 
1634
        {
 
1635
                lyst_destroy(subunits);
 
1636
        }
 
1637
 
 
1638
        return unit;
 
1639
}
 
1640
 
 
1641
static Venture  *createVenture2(int nbr, char *appname, char *authname,
 
1642
                        char *gwEidString, int ramsNetIsTree,
 
1643
                        int rootCellResyncPeriod)
 
1644
{
 
1645
        AmsMib          *mib = _mib(NULL);
 
1646
        int             amsMemory = getIonMemoryMgr();
 
1647
        int             length;
 
1648
        LystElt         elt;
 
1649
        AmsApp          *app;
 
1650
        int             i;
 
1651
        Venture         *venture;
 
1652
        int             authnameLen;
 
1653
        RamsNetProtocol ramsProtocol;
 
1654
        char            *gwEid;
 
1655
        char            gwEidBuffer[MAX_GW_EID + 1];
 
1656
        AppRole         *gatewayRole;
 
1657
        AppRole         *shutdownRole;
 
1658
        Subject         *allSubjects;
 
1659
        Lyst            subunits;
 
1660
        Unit            *rootUnit;
 
1661
        Subject         *msgspace;      /*      In local continuum.     */
 
1662
 
 
1663
        CHKNULL(nbr > 0);
 
1664
        CHKNULL(nbr <= MAX_VENTURE_NBR);
 
1665
        CHKNULL(mib->ventures[nbr] == NULL);
 
1666
        CHKNULL(appname);
 
1667
        CHKNULL(authname);
 
1668
        length = strlen(authname);
 
1669
        CHKNULL(length <= MAX_AUTH_NAME);
 
1670
        CHKNULL(rootCellResyncPeriod >= 0);
 
1671
        for (elt = lyst_first(mib->applications); elt; elt = lyst_next(elt))
 
1672
        {
 
1673
                app = (AmsApp *) lyst_data(elt);
 
1674
                if (strcmp(app->name, appname) == 0)
 
1675
                {
 
1676
                        break;
 
1677
                }
 
1678
        }
 
1679
 
 
1680
        if (elt == NULL)
 
1681
        {
 
1682
                writeMemoNote("[?] Adding venture for unknown application",
 
1683
                                appname);
 
1684
                return NULL;
 
1685
        }
 
1686
 
 
1687
        venture = (Venture *) MTAKE(sizeof(Venture));
 
1688
        CHKNULL(venture);
 
1689
        memset((char *) venture, 0, sizeof(Venture));
 
1690
        venture->nbr = nbr;
 
1691
        venture->app = app;
 
1692
        authnameLen = length + 1;
 
1693
        venture->authorityName = MTAKE(authnameLen);
 
1694
        CHKNULL(venture->authorityName);
 
1695
        istrcpy(venture->authorityName, authname, authnameLen);
 
1696
        for (i = 0; i < SUBJ_LIST_CT; i++)
 
1697
        {
 
1698
                venture->subjLysts[i] = lyst_create_using(amsMemory);
 
1699
                CHKNULL(venture->subjLysts[i]);
 
1700
        }
 
1701
 
 
1702
        ramsProtocol = parseGwEid(gwEidString, &gwEid, gwEidBuffer);
 
1703
        if (ramsProtocol == RamsNoProtocol)
 
1704
        {
 
1705
                ramsProtocol = RamsBp;
 
1706
        }
 
1707
 
 
1708
        venture->gwProtocol = ramsProtocol;
 
1709
        venture->ramsNetIsTree = ramsNetIsTree;
 
1710
        mib->ventures[nbr] = venture;
 
1711
 
 
1712
        /*      Automatically create venture's RAMS gateway role.       */
 
1713
 
 
1714
        gatewayRole = createRole(venture, 1, "RAMS", NULL, NULL);
 
1715
        shutdownRole = createRole(venture, MAX_ROLE_NBR, "stop", NULL, NULL);
 
1716
        if (gatewayRole == NULL || shutdownRole == NULL)
 
1717
        {
 
1718
                eraseVenture(venture);
 
1719
                putErrmsg("Can't create standard roles for venture.",
 
1720
                                appname);
 
1721
                return NULL;
 
1722
        }
 
1723
 
 
1724
        /*      Automatically create venture's "all subjects" subject.  */
 
1725
 
 
1726
        allSubjects = createSubject(venture, 0, "everything",
 
1727
                        "messages on all subjects", NULL, NULL, NULL);
 
1728
        if (allSubjects == NULL)
 
1729
        {
 
1730
                eraseVenture(venture);
 
1731
                putErrmsg("Can't create 'everything' subject for venture.",
 
1732
                                appname);
 
1733
                return NULL;
 
1734
        }
 
1735
 
 
1736
        /*      Automatically create venture's root unit.               */
 
1737
 
 
1738
        subunits = lyst_create_using(amsMemory);
 
1739
        CHKNULL(subunits);
 
1740
        rootUnit = initializeUnit(venture, 0, "", 0, rootCellResyncPeriod,
 
1741
                        NULL, subunits);
 
1742
        if (rootUnit == NULL)
 
1743
        {
 
1744
                putErrmsg("Can't initialize root unit for venture.", appname);
 
1745
                lyst_destroy(subunits);
 
1746
                eraseVenture(venture);
 
1747
                return NULL;
 
1748
        }
 
1749
 
 
1750
        /*      Automatically create the local message space.           */
 
1751
 
 
1752
        msgspace = createMsgspace(venture, mib->localContinuumNbr, gwEidString,
 
1753
                        NULL);
 
1754
        if (msgspace == NULL)
 
1755
        {
 
1756
                putErrmsg("Can't create local msgspace for venture.", appname);
 
1757
                eraseVenture(venture);
 
1758
                return NULL;
 
1759
        }
 
1760
 
 
1761
        return venture;
 
1762
}
 
1763
 
 
1764
Venture *createVenture(int nbr, char *appname, char *authname,
 
1765
                char *gwEidString, int ramsNetIsTree, int rootCellResyncPeriod)
 
1766
{
 
1767
        Venture *result;
 
1768
 
 
1769
        lockMib();
 
1770
        result = createVenture2(nbr, appname, authname, gwEidString,
 
1771
                        ramsNetIsTree, rootCellResyncPeriod);
 
1772
        unlockMib();
 
1773
        return result;
 
1774
}
 
1775
 
 
1776
static Continuum        *createContinuum2(int nbr, char *name, int isNeighbor,
 
1777
                                char *description)
 
1778
{
 
1779
        AmsMib          *mib = _mib(NULL);
 
1780
        int             length;
 
1781
        Continuum       *contin;
 
1782
        int             nameLen;
 
1783
        int             descLen = 0;
 
1784
 
 
1785
        CHKNULL(nbr > 0);
 
1786
        CHKNULL(nbr <= MAX_CONTIN_NBR);
 
1787
        CHKNULL(mib->continua[nbr] == NULL);
 
1788
        CHKNULL(name);
 
1789
        length = strlen(name);
 
1790
        CHKNULL(length <= MAX_SUBJ_NAME);
 
1791
        contin = (Continuum *) MTAKE(sizeof(Continuum));
 
1792
        CHKNULL(contin);
 
1793
        memset((char *) contin, 0, sizeof(Continuum));
 
1794
        contin->nbr = nbr;
 
1795
        contin->isNeighbor = 1 - (isNeighbor == 0);
 
1796
        nameLen = length + 1;
 
1797
        contin->name = MTAKE(nameLen);
 
1798
        CHKNULL(contin->name);
 
1799
        istrcpy(contin->name, name, nameLen);
 
1800
        if (description)
 
1801
        {
 
1802
                descLen = strlen(description) + 1;
 
1803
                contin->description = MTAKE(descLen);
 
1804
                CHKNULL(contin->description);
 
1805
                istrcpy(contin->description, description, descLen);
 
1806
        }
 
1807
 
 
1808
        mib->continua[nbr] = contin;
 
1809
        return contin;
 
1810
}
 
1811
 
 
1812
Continuum       *createContinuum(int nbr, char *name, int isNeighbor,
 
1813
                        char *description)
 
1814
{
 
1815
        Continuum       *result;
 
1816
 
 
1817
        lockMib();
 
1818
        result = createContinuum2(nbr, name, isNeighbor, description);
 
1819
        unlockMib();
 
1820
        return result;
 
1821
}
 
1822
 
 
1823
LystElt createCsEndpoint(char *endpointSpec, LystElt nextElt)
 
1824
{
 
1825
        AmsMib          *mib = _mib(NULL);
 
1826
        int             len;
 
1827
        char            endpointName[MAX_EP_NAME + 1];
 
1828
        MamsEndpoint    *ep;
 
1829
        LystElt         elt;
 
1830
 
 
1831
        /*      Note: no need to lockMib() because this function
 
1832
         *      is called only from inside loadMib, which has
 
1833
         *      already called lockMib().                               */
 
1834
 
 
1835
        CHKNULL(endpointSpec);
 
1836
        if (mib->pts->csepNameFn(endpointSpec, endpointName) < 0)
 
1837
        {
 
1838
                putErrmsg("Can't compute CS endpoint name.", endpointSpec);
 
1839
                return NULL;
 
1840
        }
 
1841
 
 
1842
        len = strlen(endpointName);
 
1843
        ep = (MamsEndpoint *) MTAKE(sizeof(MamsEndpoint));
 
1844
        CHKNULL(ep);
 
1845
        memset((char *) ep, 0, sizeof(MamsEndpoint));
 
1846
        if (constructMamsEndpoint(ep, len, endpointName) < 0)
 
1847
        {
 
1848
                putErrmsg("Can't construct MAMS endpoint for CS.", NULL);
 
1849
                eraseCsEndpoint(ep);
 
1850
                return NULL;
 
1851
        }
 
1852
 
 
1853
        if (nextElt)
 
1854
        {
 
1855
                elt = lyst_insert_before(nextElt, ep);
 
1856
        }
 
1857
        else
 
1858
        {
 
1859
                elt = lyst_insert_last(mib->csEndpoints, ep);
 
1860
        }
 
1861
 
 
1862
        CHKNULL(elt);
 
1863
        return elt;
 
1864
}
 
1865
 
 
1866
LystElt createAmsEpspec(char *tsname, char *epspec)
 
1867
{
 
1868
        AmsMib          *mib = _mib(NULL);
 
1869
        int             i;
 
1870
        TransSvc        *ts;
 
1871
        AmsEpspec       amses;
 
1872
        AmsEpspec       *amsesPtr;
 
1873
        LystElt         elt;
 
1874
 
 
1875
        /*      Note: no need to lockMib() because this function
 
1876
         *      is called only from inside loadMib, which has
 
1877
         *      already called lockMib().                               */
 
1878
 
 
1879
        CHKNULL(tsname);
 
1880
        CHKNULL(epspec);
 
1881
        if (strlen(epspec) > MAX_EP_SPEC)
 
1882
        {
 
1883
                writeMemoNote("[?] AMS endpoint spec is too long", epspec);
 
1884
                return NULL;
 
1885
        }
 
1886
 
 
1887
        istrcpy(amses.epspec, epspec, sizeof amses.epspec);
 
1888
        amses.ts = NULL;
 
1889
        for (i = 0, ts = mib->transportServices; i < mib->transportServiceCount;
 
1890
                        i++, ts++)
 
1891
        {
 
1892
                if (strcmp(tsname, ts->name) == 0)
 
1893
                {
 
1894
                        amses.ts = ts;
 
1895
                        break;
 
1896
                }
 
1897
        }
 
1898
 
 
1899
        if (amses.ts == NULL)
 
1900
        {
 
1901
                writeMemoNote("[?] Unknown transport service for AMS endpoint \
 
1902
spec", tsname);
 
1903
                return NULL;
 
1904
        }
 
1905
 
 
1906
        amsesPtr = (AmsEpspec *) MTAKE(sizeof(AmsEpspec));
 
1907
        CHKNULL(amsesPtr);
 
1908
        memcpy((char *) amsesPtr, &amses, sizeof(AmsEpspec));
 
1909
        elt = lyst_insert_last(mib->amsEndpointSpecs, amsesPtr);
 
1910
        CHKNULL(elt);
 
1911
        return elt;
 
1912
}
 
1913
 
 
1914
/*      *       *       MIB management functions        *       *       */
 
1915
 
 
1916
int     computeModuleId(int roleNbr, int unitNbr, int moduleNbr)
 
1917
{
 
1918
        unsigned int    moduleId;
 
1919
 
 
1920
        moduleId = (roleNbr << 24) + (unitNbr << 8) + moduleNbr;
 
1921
        return (int) moduleId;
 
1922
}
 
1923
 
 
1924
int     parseModuleId(int memo, int *roleNbr, int *unitNbr, int *moduleNbr)
 
1925
{
 
1926
        unsigned int    moduleId = (unsigned int) memo;
 
1927
 
 
1928
        CHKERR(roleNbr);
 
1929
        CHKERR(unitNbr);
 
1930
        CHKERR(moduleNbr);
 
1931
        *roleNbr = (moduleId >> 24) & 0x000000ff;
 
1932
        if (*roleNbr < 1 || *roleNbr > MAX_ROLE_NBR)
 
1933
        {
 
1934
                writeMemoNote("[?] Role nbr invalid", itoa(*roleNbr));
 
1935
                return -1;
 
1936
        }
 
1937
 
 
1938
        *unitNbr = (moduleId >> 8) & 0x0000ffff;
 
1939
        if (*unitNbr > MAX_UNIT_NBR)
 
1940
        {
 
1941
                writeMemoNote("[?] Unit nbr invalid", itoa(*unitNbr));
 
1942
                return -1;
 
1943
        }
 
1944
 
 
1945
        *moduleNbr = moduleId & 0x000000ff;
 
1946
        if (*moduleNbr < 1 || *moduleNbr > MAX_MODULE_NBR)
 
1947
        {
 
1948
                writeMemoNote("[?] Module nbr invalid", itoa(*moduleNbr));
 
1949
                return -1;
 
1950
        }
 
1951
 
 
1952
        return 0;
 
1953
}
 
1954
 
 
1955
char    *parseString(char **cursor, int *bytesRemaining, int *len)
 
1956
{
 
1957
        char    *string = *cursor;
 
1958
 
 
1959
        *len = 0;
 
1960
        while (*bytesRemaining > 0)
 
1961
        {
 
1962
                if (**cursor == '\0')   /*      End of string.          */
 
1963
                {
 
1964
                        (*cursor)++;    /*      Skip over the NULL.     */
 
1965
                        (*bytesRemaining)--;
 
1966
                        return string;
 
1967
                }
 
1968
 
 
1969
                /*      This is one of the characters of the string.    */
 
1970
 
 
1971
                (*cursor)++;
 
1972
                (*bytesRemaining)--;
 
1973
                (*len)++;
 
1974
        }
 
1975
 
 
1976
        return NULL;            /*      Not a NULL-terminated string.   */
 
1977
}
 
1978
 
 
1979
int     constructMamsEndpoint(MamsEndpoint *endpoint, int eptLength, char *ept)
 
1980
{
 
1981
        int     result;
 
1982
 
 
1983
        endpoint->ept = MTAKE(eptLength + 1);
 
1984
        CHKERR(endpoint->ept);
 
1985
        memcpy(endpoint->ept, ept, eptLength);
 
1986
        endpoint->ept[eptLength] = '\0';
 
1987
 
 
1988
        /*      The primary transport service's endpoint parsing
 
1989
         *      function examines the endpoint name text and fills
 
1990
         *      in the tsep of the endpoint.                            */
 
1991
 
 
1992
        lockMib();
 
1993
        result = ((_mib(NULL))->pts->parseMamsEndpointFn)(endpoint); 
 
1994
        unlockMib();
 
1995
        if (result < 0)
 
1996
        {
 
1997
                writeMemoNote("[?] Can't parse endpoint name", ept);
 
1998
                return -1;
 
1999
        }
 
2000
 
 
2001
        return 0;
 
2002
}
 
2003
 
 
2004
void    clearMamsEndpoint(MamsEndpoint *ep)
 
2005
{
 
2006
        lockMib();
 
2007
        (_mib(NULL))->pts->clearMamsEndpointFn(ep);
 
2008
        unlockMib();
 
2009
        ep->tsep = NULL;
 
2010
        if (ep->ept)
 
2011
        {
 
2012
                MRELEASE(ep->ept);
 
2013
                ep->ept = NULL;
 
2014
        }
 
2015
}
 
2016
 
 
2017
int     rememberModule(Module *module, AppRole *role, int eptLength, char *ept)
 
2018
{
 
2019
        if (constructMamsEndpoint(&(module->mamsEndpoint), eptLength, ept))
 
2020
        {
 
2021
                putErrmsg("Can't store module's MAMS endpoint.", NULL);
 
2022
                return -1;
 
2023
        }
 
2024
 
 
2025
        module->role = role;
 
2026
        return 0;
 
2027
}
 
2028
 
 
2029
void    forgetModule(Module *module)
 
2030
{
 
2031
        LystElt elt;
 
2032
        LystElt nextElt;
 
2033
 
 
2034
        for (elt = lyst_first(module->amsEndpoints); elt; elt = nextElt)
 
2035
        {
 
2036
                nextElt = lyst_next(elt);
 
2037
                lyst_delete(elt);
 
2038
        }
 
2039
 
 
2040
        for (elt = lyst_first(module->subjects); elt; elt = nextElt)
 
2041
        {
 
2042
                nextElt = lyst_next(elt);
 
2043
                lyst_delete(elt);
 
2044
        }
 
2045
 
 
2046
        clearMamsEndpoint(&module->mamsEndpoint);
 
2047
        module->role = NULL;
 
2048
}
 
2049
 
 
2050
/*      *       *       MAMS message transmission *     *       *       */
 
2051
 
 
2052
int     sendMamsMsg(MamsEndpoint *endpoint, MamsInterface *tsif,
 
2053
                MamsPduType type, unsigned int memo,
 
2054
                unsigned short supplementLength, char *supplement)
 
2055
{
 
2056
        Venture         *venture;
 
2057
        Unit            *unit;
 
2058
        char            *authName;
 
2059
        char            authKey[32];
 
2060
        int             authKeyLen = sizeof authKey; 
 
2061
        int             authNameLen;
 
2062
        int             nonce;
 
2063
        unsigned char   authenticator[AUTHENTICAT_LEN];
 
2064
        int             encryptLength;
 
2065
        int             authenticatorLength = 0;
 
2066
        time_t          unixTime;
 
2067
        unsigned int    u4;
 
2068
        unsigned char   timeTag[5];
 
2069
        int             msgLength;
 
2070
        unsigned char   *msg;
 
2071
        unsigned short  u2;
 
2072
        unsigned short  checksum;
 
2073
        int             result;
 
2074
 
 
2075
        CHKERR(endpoint);
 
2076
        CHKERR(tsif);
 
2077
        if (getAuthenticationParms(tsif->ventureNbr, tsif->unitNbr,
 
2078
                        tsif->roleNbr, &venture, &unit, 1, &authName, authKey,
 
2079
                        &authKeyLen))
 
2080
        {
 
2081
                putErrmsg("Can't get authentication parameters.", NULL);
 
2082
                return -1;
 
2083
        }
 
2084
 
 
2085
        if (authName == NULL)           /*      Invalid parameters.     */
 
2086
        {
 
2087
                return 0;               /*      Don't send message.     */
 
2088
        }
 
2089
        
 
2090
        if (authKeyLen > 0)
 
2091
        {
 
2092
                authNameLen = strlen(authName);
 
2093
                if (authNameLen == 0 || authNameLen > (AUTHENTICAT_LEN - 9))
 
2094
                {
 
2095
                        putErrmsg("Bad authentication name.", authName);
 
2096
                        return -1;
 
2097
                }
 
2098
 
 
2099
                encryptLength = authNameLen + 4;
 
2100
                nonce = rand();
 
2101
                memcpy(authenticator, (char *) &nonce, 4);/*    Clear.  */
 
2102
                memcpy(authenticator + 4, (char *) &nonce, 4);
 
2103
                istrcpy((char *) (authenticator + 8), authName,
 
2104
                                sizeof authenticator - 8);
 
2105
                encryptUsingPrivateKey((char *) (authenticator + 4),
 
2106
                                &encryptLength, authKey, authKeyLen,
 
2107
                                (char *) (authenticator + 4), encryptLength);
 
2108
                authenticatorLength = encryptLength + 4;
 
2109
        }
 
2110
 
 
2111
        /*      Time tag is CCSDS Unsegmented Time (CUC) with preamble.
 
2112
         *      The preamble (P-field) is always a single octet whose
 
2113
         *      bits have the following significance:
 
2114
         *              0       no extension
 
2115
         *              001     time code ID (Epoch 1958 TAI)
 
2116
         *              11      indicates 4 octets of coarse time (sec)
 
2117
         *              00      indicates 0 octets of fine time
 
2118
         *      Note that the CCSDS spec actually requires TAI time for
 
2119
         *      time code 001, but the operating system only gives us
 
2120
         *      UTC, so the time tags inserted here will be in error by
 
2121
         *      some number of leap seconds.  For the purposes of AMS
 
2122
         *      this error is not significant.                          */
 
2123
 
 
2124
        unixTime = time(NULL);                  /*      Epoch 1970.     */
 
2125
        u4 = unixTime + EPOCH_OFFSET_1958;      /*      Now epoch 1958. */
 
2126
        u4 = htonl(u4);
 
2127
        timeTag[0] = 28;                        /*      Preamble.       */
 
2128
        memcpy(timeTag + 1, (char *) &u4, 4);   /*      Coarse time.    */
 
2129
 
 
2130
        /*      12 bytes of message length are fixed by specification.
 
2131
         *      5 bytes are time tag, which in the JPL implementation
 
2132
         *      is always of length 5.  2 bytes are checksum, which
 
2133
         *      in the JPL implementation is always present.            */
 
2134
 
 
2135
        msgLength = 12 + 5 + authenticatorLength + supplementLength + 2;
 
2136
        msg = MTAKE(msgLength);
 
2137
        CHKERR(msg);
 
2138
 
 
2139
        /*      Construct the message.  First octet is two bits of
 
2140
         *      version number (which is always 00 for now) followed
 
2141
         *      by checksum flag (always 1 in this implementation of
 
2142
         *      MAMS) followed by 5 bits of MPDU type.                  */
 
2143
 
 
2144
        u4 = type;
 
2145
        *msg = 0x20 + (u4 & 0x0000001f);
 
2146
        *(msg + 1) = tsif->ventureNbr;
 
2147
        u2 = tsif->unitNbr;
 
2148
        u2 = htons(u2);
 
2149
        memcpy(msg + 2, (char *) &u2, 2);
 
2150
        *(msg + 4) = tsif->roleNbr;
 
2151
        *(msg + 5) = authenticatorLength;
 
2152
        u2 = supplementLength;
 
2153
        u2 = htons(u2);
 
2154
        memcpy(msg + 6, (char *) &u2, 2);
 
2155
        u4 = htonl(memo);
 
2156
        memcpy(msg + 8, (char *) &u4, 4);
 
2157
        memcpy(msg + 12, timeTag, 5);
 
2158
 
 
2159
        /*      Optionally append digital signature to header.          */
 
2160
 
 
2161
        if (authenticatorLength > 0)
 
2162
        {
 
2163
                memcpy(msg + 17, authenticator, authenticatorLength);
 
2164
        }
 
2165
 
 
2166
        /*      Append supplementary data to message.                   */
 
2167
 
 
2168
        if (supplementLength > 0)
 
2169
        {
 
2170
                memcpy(msg + 17 + authenticatorLength, supplement,
 
2171
                                supplementLength);
 
2172
        }
 
2173
 
 
2174
        /*      For this implementation, always append checksum to
 
2175
         *      message.                                                */
 
2176
 
 
2177
        checksum = computeAmsChecksum(msg, msgLength - 2);
 
2178
        checksum = htons(checksum);
 
2179
        memcpy(msg + (msgLength -2), (char *) &checksum, 2);
 
2180
 
 
2181
        /*      Send the message.                                       */
 
2182
 
 
2183
        lockMib();
 
2184
        result = (_mib(NULL))->pts->sendMamsFn(endpoint, tsif, (char *) msg,
 
2185
                        msgLength);
 
2186
        unlockMib();
 
2187
        MRELEASE(msg);
 
2188
        return result;
 
2189
}
 
2190
 
 
2191
/*      *       *       Event queueing functions        *       *       */
 
2192
 
 
2193
int     enqueueMamsEvent(Llcv eventsQueue, AmsEvt *evt, char *ancillaryBlock,
 
2194
                int responseNbr)
 
2195
{
 
2196
        long    queryNbr;
 
2197
        LystElt elt;
 
2198
 
 
2199
        llcv_lock(eventsQueue);
 
2200
 
 
2201
        /*      Events that shut down event loops are inserted at
 
2202
         *      the start of the events queue, for immediate handling.  */
 
2203
 
 
2204
        if (evt->type == CRASH_EVT)
 
2205
        {
 
2206
                elt = lyst_insert_first(eventsQueue->list, evt);
 
2207
                llcv_unlock(eventsQueue);
 
2208
                if (elt == NULL)
 
2209
                {
 
2210
                        putErrmsg("Can't insert event.", NULL);
 
2211
                        return -1;
 
2212
                }
 
2213
 
 
2214
                llcv_signal(eventsQueue, time_to_stop);
 
2215
                return 0;
 
2216
        }
 
2217
 
 
2218
        /*      A hack, which works in the absence of a Lyst user
 
2219
         *      data variable.  In order to make the current query
 
2220
         *      ID number accessible to an llcv condition function,
 
2221
         *      we stuff it into the "compare" function pointer in
 
2222
         *      the Lyst structure.                                     */
 
2223
 
 
2224
        queryNbr = (long) lyst_compare_get(eventsQueue->list);
 
2225
        if (queryNbr != 0)      /*      Need response to specfic msg.   */
 
2226
        {
 
2227
                if (responseNbr == queryNbr)    /*      This is it.     */
 
2228
                {
 
2229
                        elt = lyst_insert_first(eventsQueue->list, evt);
 
2230
                        if (elt)        /*      Must erase query nbr.   */
 
2231
                        {
 
2232
                                lyst_compare_set(eventsQueue->list, NULL);
 
2233
                                llcv_signal_while_locked(eventsQueue,
 
2234
                                                llcv_reply_received);
 
2235
                        }
 
2236
                }
 
2237
                else    /*      This isn't it; deal with it later.      */
 
2238
                {
 
2239
                        elt = lyst_insert_last(eventsQueue->list, evt);
 
2240
                }
 
2241
        }
 
2242
        else    /*      Any event is worth waking up the thread for.    */
 
2243
        {
 
2244
                elt = lyst_insert_last(eventsQueue->list, evt);
 
2245
                if (elt)
 
2246
                {
 
2247
                        llcv_signal_while_locked(eventsQueue,
 
2248
                                        llcv_lyst_not_empty);
 
2249
                }
 
2250
        }
 
2251
 
 
2252
        llcv_unlock(eventsQueue);
 
2253
        if (elt == NULL)
 
2254
        {
 
2255
                putErrmsg("Can't insert event.", NULL);
 
2256
                return -1;
 
2257
        }
 
2258
 
 
2259
        return 0;
 
2260
}
 
2261
 
 
2262
int     enqueueMamsMsg(Llcv eventsQueue, int length, unsigned char *msgBuffer)
 
2263
{
 
2264
        unsigned int    preamble;       /*      Describes time tag.     */
 
2265
        int             timeCode;
 
2266
        int             coarseTimeLength;
 
2267
        int             fineTimeLength;
 
2268
        int             expectedLength;
 
2269
        unsigned int    u4;
 
2270
        unsigned char   *cursor;
 
2271
        MamsMsg         msg;
 
2272
        unsigned short  checksum;
 
2273
        unsigned short  u2;
 
2274
        int             authenticatorLength;
 
2275
        unsigned char   *authenticator = NULL;
 
2276
        unsigned char   *supplement;
 
2277
        Venture         *venture;
 
2278
        Unit            *unit;
 
2279
        char            *authName;
 
2280
        char            authKey[32];
 
2281
        int             authKeyLen = sizeof authKey;
 
2282
        int             authNameLen;
 
2283
        unsigned char   nonce[4];
 
2284
        int             decryptLength;
 
2285
        AmsEvt          *evt;
 
2286
 
 
2287
        CHKERR(eventsQueue);
 
2288
        CHKERR(length >= 0);
 
2289
        CHKERR(msgBuffer);
 
2290
        if (length < 14)
 
2291
        {
 
2292
                writeMemoNote("[?] MAMS msg header incomplete", itoa(length));
 
2293
                return -1;
 
2294
        }
 
2295
 
 
2296
        /*      First get time tag, since its size affects the
 
2297
         *      location of the authenticator and supplement.           */
 
2298
 
 
2299
        preamble = *(msgBuffer + 12);           /*      "P-field."      */
 
2300
        timeCode = (preamble >> 4) & 0x07;
 
2301
        if (timeCode != 1)
 
2302
        {
 
2303
                writeMemoNote("[?] Unknown time code in MAMS msg header",
 
2304
                                itoa(timeCode));
 
2305
                return -1;
 
2306
        }
 
2307
 
 
2308
        coarseTimeLength = ((preamble >> 2) & 0x03) + 1;
 
2309
        fineTimeLength = preamble & 0x03;
 
2310
        expectedLength = 12 + 1 + coarseTimeLength + fineTimeLength;
 
2311
        if (length < expectedLength)
 
2312
        {
 
2313
                writeMemo("[?] MAMS message truncated.");
 
2314
                return -1;
 
2315
        }
 
2316
 
 
2317
        u4 = 0;
 
2318
        cursor = msgBuffer + 13;                /*      After preamble. */
 
2319
        while (coarseTimeLength > 0)
 
2320
        {
 
2321
                u4 += *cursor;
 
2322
                u4 <<= 1;
 
2323
                cursor++;
 
2324
                coarseTimeLength--;
 
2325
        }
 
2326
 
 
2327
        u4 = ntohl(u4);                         /*      Epoch 1958.     */
 
2328
        msg.timeTag = u4 - EPOCH_OFFSET_1958;   /*      Now epoch 1970. */
 
2329
        while (fineTimeLength > 0)
 
2330
        {
 
2331
                cursor++;               /*      Ignore fine time.       */
 
2332
                fineTimeLength--;
 
2333
        }
 
2334
 
 
2335
        /*      Now look for checksum.                                  */
 
2336
 
 
2337
        if (*msgBuffer & 0x20)          /*      Checksum present.       */
 
2338
        {
 
2339
                expectedLength += 2;
 
2340
                if (length < expectedLength)
 
2341
                {
 
2342
                        writeMemo("[?] MAMS message truncated.");
 
2343
                        return -1;
 
2344
                }
 
2345
 
 
2346
                memcpy((char *) &checksum, msgBuffer + (length - 2), 2);
 
2347
                checksum = ntohs(checksum);
 
2348
                if (checksum != computeAmsChecksum(msgBuffer, length - 2))
 
2349
                {
 
2350
                        writeMemo("[?] Checksum failed, MAMS msg discarded.");
 
2351
                        return -1;
 
2352
                }
 
2353
        }
 
2354
 
 
2355
        /*      Now extract the rest of the MAMS message.               */
 
2356
 
 
2357
        msg.type = *msgBuffer & 0x1f;
 
2358
        msg.ventureNbr = *(msgBuffer + 1);
 
2359
        memcpy((char *) &u2, msgBuffer + 2, 2);
 
2360
        u2 = ntohs(u2);
 
2361
        msg.unitNbr = u2;
 
2362
        msg.roleNbr = *(msgBuffer + 4);
 
2363
        authenticatorLength = *(msgBuffer + 5);
 
2364
        expectedLength += authenticatorLength;
 
2365
        if (authenticatorLength > 0)
 
2366
        {
 
2367
                authenticator = cursor; /*      Starts after time tag.  */
 
2368
                cursor += authenticatorLength;
 
2369
        }
 
2370
 
 
2371
        memcpy((char *) &u2, msgBuffer + 6, 2);
 
2372
        u2 = ntohs(u2);
 
2373
        msg.supplementLength = u2;
 
2374
        expectedLength += msg.supplementLength;
 
2375
        supplement = cursor;    /*      After time tag, authenticator.  */
 
2376
        if (length != expectedLength)
 
2377
        {
 
2378
                length -= expectedLength;
 
2379
                writeMemoNote("[?] MAMS message length error", itoa(length));
 
2380
                return -1;
 
2381
        }
 
2382
 
 
2383
        if (getAuthenticationParms(msg.ventureNbr, msg.unitNbr, msg.roleNbr,
 
2384
                        &venture, &unit, 0, &authName, authKey, &authKeyLen))
 
2385
        {
 
2386
                putErrmsg("Can't get authentication parameters.", NULL);
 
2387
                return -1;
 
2388
        }
 
2389
 
 
2390
        if (authName == NULL)           /*      Invalid parameters.     */
 
2391
        {
 
2392
                return 0;               /*      Don't deliver message.  */
 
2393
        }
 
2394
        
 
2395
        if (authKeyLen > 0)
 
2396
        {
 
2397
                /*      Authentication is required.                     */
 
2398
 
 
2399
                authNameLen = strlen(authName);
 
2400
                CHKERR(authNameLen > 0);
 
2401
                CHKERR(authNameLen <= (AUTHENTICAT_LEN - 9));
 
2402
                if (authenticatorLength != authNameLen + 8)
 
2403
                {
 
2404
                        writeMemo("[?] MAMS msg discarded; bad authenticator.");
 
2405
                        return -1;
 
2406
                }
 
2407
 
 
2408
                memcpy(nonce, authenticator, 4);
 
2409
                decryptUsingPublicKey((char *) (authenticator + 4),
 
2410
                                &decryptLength, authKey, authKeyLen,
 
2411
                                (char *) (authenticator + 4),
 
2412
                                authenticatorLength - 4);
 
2413
                if (memcmp(nonce, authenticator + 4, 4) != 0
 
2414
                || memcmp(authName, authenticator + 8, authNameLen) != 0)
 
2415
                {
 
2416
                        writeMemo("[?] MAMS msg discarded; auth. failed.");
 
2417
                        return -1;
 
2418
                }
 
2419
        }
 
2420
 
 
2421
        /*      Construct message event, enqueue, and signal arrival.   */
 
2422
 
 
2423
        memcpy((char *) &u4, msgBuffer + 8, 4);
 
2424
        u4 = ntohl(u4);
 
2425
        msg.memo = u4;
 
2426
        if (msg.supplementLength > 0)
 
2427
        {
 
2428
                msg.supplement = MTAKE(msg.supplementLength);
 
2429
                CHKERR(msg.supplement);
 
2430
                memcpy(msg.supplement, supplement, msg.supplementLength);
 
2431
        }
 
2432
        else
 
2433
        {
 
2434
                msg.supplement = NULL;
 
2435
        }
 
2436
 
 
2437
        evt = MTAKE(1 + sizeof(MamsMsg));
 
2438
        CHKERR(evt);
 
2439
        evt->type = MAMS_MSG_EVT;
 
2440
        memcpy(evt->value, (char *) &msg, sizeof(MamsMsg));
 
2441
        if (enqueueMamsEvent(eventsQueue, evt, msg.supplement, msg.memo))
 
2442
        {
 
2443
                putErrmsg("Can't enqueue MAMS message.", NULL);
 
2444
                MRELEASE(evt);
 
2445
                if (msg.supplement)
 
2446
                {
 
2447
                        MRELEASE(msg.supplement);
 
2448
                }
 
2449
 
 
2450
                return -1;
 
2451
        }
 
2452
 
 
2453
        return 0;
 
2454
}
 
2455
 
 
2456
int     enqueueMamsCrash(Llcv eventsQueue, char *text)
 
2457
{
 
2458
        int     textLength;
 
2459
        char    *silence = "";
 
2460
        AmsEvt  *evt;
 
2461
 
 
2462
        if (text == NULL)
 
2463
        {
 
2464
                textLength = 0;
 
2465
                text = silence;
 
2466
        }
 
2467
        else
 
2468
        {
 
2469
                textLength = strlen(text);
 
2470
        }
 
2471
 
 
2472
        evt = (AmsEvt *) MTAKE(1 + textLength + 1);
 
2473
        CHKERR(evt);
 
2474
        evt->type = CRASH_EVT;
 
2475
        memcpy(evt->value, text, textLength);
 
2476
        evt->value[textLength] = '\0';
 
2477
        if (enqueueMamsEvent(eventsQueue, evt, NULL, 0))
 
2478
        {
 
2479
                putErrmsg("Can't enqueue MAMS crash.", NULL);
 
2480
                MRELEASE(evt);
 
2481
                return -1;
 
2482
        }
 
2483
 
 
2484
        return 0;
 
2485
}
 
2486
 
 
2487
int     enqueueMamsStubEvent(Llcv eventsQueue, int eventType)
 
2488
{
 
2489
        AmsEvt  *evt;
 
2490
 
 
2491
        evt = (AmsEvt *) MTAKE(sizeof(AmsEvt));
 
2492
        CHKERR(evt);
 
2493
        evt->type = eventType;
 
2494
        if (enqueueMamsEvent(eventsQueue, evt, NULL, 0))
 
2495
        {
 
2496
                putErrmsg("Can't enqueue stub event.", NULL);
 
2497
                MRELEASE(evt);
 
2498
                return -1;
 
2499
        }
 
2500
 
 
2501
        return 0;
 
2502
}
 
2503
 
 
2504
void    recycleEvent(AmsEvt *evt)
 
2505
{
 
2506
        MamsMsg *msg;
 
2507
 
 
2508
        if (evt == NULL) return;
 
2509
        if (evt->type == MAMS_MSG_EVT)
 
2510
        {
 
2511
                msg = (MamsMsg *) (evt->value);
 
2512
                if (msg->supplement)
 
2513
                {
 
2514
                        MRELEASE(msg->supplement);
 
2515
                }
 
2516
        }
 
2517
 
 
2518
        MRELEASE(evt);
 
2519
}
 
2520
 
 
2521
void    destroyEvent(LystElt elt, void *userdata)
 
2522
{
 
2523
        AmsEvt  *evt = (AmsEvt *) lyst_data(elt);
 
2524
 
 
2525
        recycleEvent(evt);
 
2526
}