Security CBOR conversion
[platform/upstream/iotivity.git] / resource / csdk / security / provisioning / sample / provisioningclient.c
1 /******************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *****************************************************************/
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <unistd.h>
24
25 #include "logger.h"
26 #include "oic_malloc.h"
27 #include "oic_string.h"
28 #include "ocprovisioningmanager.h"
29 #include "oxmjustworks.h"
30 #include "oxmrandompin.h"
31 #include "securevirtualresourcetypes.h"
32 #include "srmutility.h"
33 #include "pmtypes.h"
34
35 #ifdef __cplusplus
36 extern "C"
37 {
38 #endif //__cplusplus
39
40 // declaration(s) for provisioning client using C-level provisioning API
41 // user input definition for main loop on provisioning client
42 #define _10_DISCOV_ALL_DEVS_    10
43 #define _11_DISCOV_UNOWN_DEVS_  11
44 #define _12_DISCOV_OWN_DEVS_    12
45 #define _20_REGIST_DEVS_        20
46 #define _30_PROVIS_PAIR_DEVS_   30
47 #define _31_PROVIS_CRED_        31
48 #define _32_PROVIS_ACL_         32
49 #define _33_PROVIS_DP_           33
50 #define _34_CHECK_LINK_STATUS_  34
51 #define _40_UNLINK_PAIR_DEVS_   40
52 #define _50_REMOVE_SELEC_DEV_   50
53 #define _99_EXIT_PRVN_CLT_      99
54
55 #define ACL_RESRC_MAX_NUM   16
56 #define ACL_RESRC_MAX_LEN   128
57 #define ACL_PEMISN_CNT      5
58 #define DISCOVERY_TIMEOUT   10  // 10 sec
59 #define CALLBACK_TIMEOUT    60  // 1 min
60 #define TAG "provisioningclient"
61
62 static const char* ACL_PEMISN[5] = {"CREATE", "READ", "WRITE", "DELETE", "NOTIFY"};
63 static const char* SVR_DB_FILE_NAME = "oic_svr_db_client.dat";
64         // '_' for separaing from the same constant variable in |srmresourcestrings.c|
65 static const char* PRVN_DB_FILE_NAME = "oic_prvn_mng.db";
66 static const OicSecPrm_t  SUPPORTED_PRMS[1] =
67 {
68     PRM_PRE_CONFIGURED,
69 };
70
71 // |g_ctx| means provision manager application context and
72 // the following, includes |un/own_list|, could be variables, which |g_ctx| has,
73 // for accessing all function(s) for these, they are declared on global domain
74 static const char* g_ctx = "Provision Manager Client Application Context";
75 static char* g_svr_fname;
76 static char* g_prvn_fname;
77 static OCProvisionDev_t* g_own_list;
78 static OCProvisionDev_t* g_unown_list;
79 static int g_own_cnt;
80 static int g_unown_cnt;
81 static bool g_doneCB;
82
83 // function declaration(s) for calling them before implementing
84 static OicSecAcl_t* createAcl(const int);
85 static OicSecPdAcl_t* createPdAcl(const int);
86 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t*, const int);
87 static int printDevList(const OCProvisionDev_t*);
88 static size_t printUuidList(const OCUuidList_t*);
89 static int printResultList(const OCProvisionResult_t*, const int);
90 static void printUuid(const OicUuid_t*);
91 static FILE* fopen_prvnMng(const char*, const char*);
92 static int waitCallbackRet(void);
93 static int selectTwoDiffNum(int*, int*, const int, const char*);
94
95 // callback function(s) for provisioning client using C-level provisioning API
96 static void ownershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
97 {
98     if(!hasError)
99     {
100         OIC_LOG_V(INFO, TAG, "Ownership Transfer SUCCEEDED - ctx: %s", (char*) ctx);
101     }
102     else
103     {
104         OIC_LOG_V(ERROR, TAG, "Ownership Transfer FAILED - ctx: %s", (char*) ctx);
105         printResultList((const OCProvisionResult_t*) arr, nOfRes);
106     }
107     g_doneCB = true;
108 }
109
110 static void provisionPairwiseCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
111 {
112     if(!hasError)
113     {
114         OIC_LOG_V(INFO, TAG, "Provision Pairwise SUCCEEDED - ctx: %s", (char*) ctx);
115     }
116     else
117     {
118         OIC_LOG_V(ERROR, TAG, "Provision Pairwise FAILED - ctx: %s", (char*) ctx);
119         printResultList((const OCProvisionResult_t*) arr, nOfRes);
120     }
121     g_doneCB = true;
122 }
123
124 static void provisionCredCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
125 {
126     if(!hasError)
127     {
128         OIC_LOG_V(INFO, TAG, "Provision Credential SUCCEEDED - ctx: %s", (char*) ctx);
129     }
130     else
131     {
132         OIC_LOG_V(ERROR, TAG, "Provision Credential FAILED - ctx: %s", (char*) ctx);
133         printResultList((const OCProvisionResult_t*) arr, nOfRes);
134     }
135     g_doneCB = true;
136 }
137
138 static void provisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
139 {
140     if(!hasError)
141     {
142         OIC_LOG_V(INFO, TAG, "Provision ACL SUCCEEDED - ctx: %s", (char*) ctx);
143     }
144     else
145     {
146         OIC_LOG_V(ERROR, TAG, "Provision ACL FAILED - ctx: %s", (char*) ctx);
147         printResultList((const OCProvisionResult_t*) arr, nOfRes);
148     }
149     g_doneCB = true;
150 }
151
152 static void provisionDPCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
153 {
154     if(!hasError)
155     {
156         OIC_LOG_V(INFO, TAG, "Provision Direct-Pairing SUCCEEDED - ctx: %s", (char*) ctx);
157     }
158     else
159     {
160         OIC_LOG_V(ERROR, TAG, "Provision Direct-Pairing FAILED - ctx: %s", (char*) ctx);
161         printResultList((const OCProvisionResult_t*) arr, nOfRes);
162     }
163     g_doneCB = true;
164 }
165
166 static void unlinkDevicesCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
167 {
168     if(!hasError)
169     {
170         OIC_LOG_V(INFO, TAG, "Unlink Devices SUCCEEDED - ctx: %s", (char*) ctx);
171     }
172     else
173     {
174         OIC_LOG_V(ERROR, TAG, "Unlink Devices FAILED - ctx: %s", (char*) ctx);
175         printResultList((const OCProvisionResult_t*) arr, nOfRes);
176     }
177     g_doneCB = true;
178 }
179
180 static void removeDeviceCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
181 {
182     if(!hasError)
183     {
184         OIC_LOG_V(INFO, TAG, "Remove Device SUCCEEDED - ctx: %s", (char*) ctx);
185     }
186     else
187     {
188         OIC_LOG_V(ERROR, TAG, "Remove Device FAILED - ctx: %s", (char*) ctx);
189         printResultList((const OCProvisionResult_t*) arr, nOfRes);
190     }
191     g_doneCB = true;
192 }
193
194 static void inputPinCB(char* pin, size_t len)
195 {
196     if(!pin || OXM_RANDOM_PIN_SIZE>=len)
197     {
198         OIC_LOG(ERROR, TAG, "inputPinCB invalid parameters");
199         return;
200     }
201
202     printf("   > INPUT PIN: ");
203     for(int ret=0; 1!=ret; )
204     {
205         ret = scanf("%8s", pin);
206         for( ; 0x20<=getchar(); );  // for removing overflow garbages
207                                     // '0x20<=code' is character region
208     }
209 }
210
211 // function(s) for provisioning client using C-level provisioning API
212 static int initProvisionClient(void)
213 {
214     // initialize persistent storage for SVR DB
215     static OCPersistentStorage pstStr =
216     {
217         .open = fopen_prvnMng,
218         .read = fread,
219         .write = fwrite,
220         .close = fclose,
221         .unlink = unlink
222     };
223     if(OC_STACK_OK != OCRegisterPersistentStorageHandler(&pstStr))
224     {
225         OIC_LOG(ERROR, TAG, "OCRegisterPersistentStorageHandler error");
226         return -1;
227     }
228
229     // initialize OC stack and provisioning manager
230     if(OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
231     {
232         OIC_LOG(ERROR, TAG, "OCStack init error");
233         return -1;
234     }
235
236     if (access(PRVN_DB_FILE_NAME, F_OK) != -1)
237     {
238         printf("************************************************************\n");
239         printf("************Provisioning DB file already exists.************\n");
240         printf("************************************************************\n");
241     }
242     else
243     {
244         printf("*************************************************************\n");
245         printf("************No provisioning DB file, creating new************\n");
246         printf("*************************************************************\n");
247     }
248
249     if(OC_STACK_OK != OCInitPM(PRVN_DB_FILE_NAME))
250     {
251         OIC_LOG(ERROR, TAG, "OC_PM init error");
252         return -1;
253     }
254
255     // register callback function(s) to each OxM
256     OTMCallbackData_t otmcb =
257     {
258         .loadSecretCB = LoadSecretJustWorksCallback,
259         .createSecureSessionCB = CreateSecureSessionJustWorksCallback,
260         .createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload,
261         .createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload
262     };
263     if(OC_STACK_OK != OCSetOwnerTransferCallbackData(OIC_JUST_WORKS, &otmcb))
264     {
265         OIC_LOG(ERROR, TAG, "OCSetOwnerTransferCallbackData error: OIC_JUST_WORKS");
266         return -1;
267     }
268     otmcb.loadSecretCB = InputPinCodeCallback;
269     otmcb.createSecureSessionCB = CreateSecureSessionRandomPinCallback;
270     otmcb.createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
271     otmcb.createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
272     if(OC_STACK_OK != OCSetOwnerTransferCallbackData(OIC_RANDOM_DEVICE_PIN, &otmcb))
273     {
274         OIC_LOG(ERROR, TAG, "OCSetOwnerTransferCallbackData error: OIC_RANDOM_DEVICE_PIN");
275         return -1;
276     }
277     SetInputPinCB(inputPinCB);
278
279     return 0;
280 }
281
282 static int discoverAllDevices(void)
283 {
284     // delete un/owned device lists before updating them
285     if(g_own_list)
286     {
287         OCDeleteDiscoveredDevices(g_own_list);
288         g_own_list = NULL;
289     }
290     if(g_unown_list)
291     {
292         OCDeleteDiscoveredDevices(g_unown_list);
293         g_unown_list = NULL;
294     }
295
296     // call |OCGetDevInfoFromNetwork| API actually
297     printf("   Discovering All Un/Owned Devices on Network..\n");
298     if(OC_STACK_OK != OCGetDevInfoFromNetwork(DISCOVERY_TIMEOUT, &g_own_list, &g_unown_list))
299     {
300         OIC_LOG(ERROR, TAG, "OCGetDevInfoFromNetwork API error");
301         return -1;
302     }
303
304     // display the discovered un/owned lists
305     printf("   > Discovered Owned Devices\n");
306     g_own_cnt = printDevList(g_own_list);
307     printf("   > Discovered Unowned Devices\n");
308     g_unown_cnt = printDevList(g_unown_list);
309
310     return 0;
311 }
312
313
314 static int discoverUnownedDevices(void)
315 {
316     // delete unowned device list before updating it
317     if(g_unown_list)
318     {
319         OCDeleteDiscoveredDevices(g_unown_list);
320         g_unown_list = NULL;
321     }
322
323     // call |OCDiscoverUnownedDevices| API actually
324     printf("   Discovering Only Unowned Devices on Network..\n");
325     if(OC_STACK_OK != OCDiscoverUnownedDevices(DISCOVERY_TIMEOUT, &g_unown_list))
326     {
327         OIC_LOG(ERROR, TAG, "OCDiscoverUnownedDevices API error");
328         return -1;
329     }
330
331     // display the discovered unowned list
332     printf("   > Discovered Unowned Devices\n");
333     g_unown_cnt = printDevList(g_unown_list);
334
335     return 0;
336 }
337
338 static int discoverOwnedDevices(void)
339 {
340     // delete owned device list before updating it
341     if(g_own_list)
342     {
343         OCDeleteDiscoveredDevices(g_own_list);
344         g_own_list = NULL;
345     }
346
347     // call |OCDiscoverOwnedDevices| API actually
348     printf("   Discovering Only Owned Devices on Network..\n");
349     if(OC_STACK_OK != OCDiscoverOwnedDevices(DISCOVERY_TIMEOUT, &g_own_list))
350     {
351         OIC_LOG(ERROR, TAG, "OCDiscoverOwnedDevices API error");
352         return -1;
353     }
354
355     // display the discovered owned list
356     printf("   > Discovered Owned Devices\n");
357     g_own_cnt = printDevList(g_own_list);
358
359     return 0;
360 }
361
362 static int registerDevices(void)
363 {
364     // check |unown_list| for registering devices
365     if(!g_unown_list || 0>=g_unown_cnt)
366     {
367         printf("   > Unowned Device List, to Register Devices, is Empty\n");
368         printf("   > Please Discover Unowned Devices first, with [10|11] Menu\n");
369         return 0;  // normal case
370     }
371
372     // call |OCDoOwnershipTransfer| API actually
373     // calling this API with callback actually acts like blocking
374     // for error checking, the return value saved and printed
375     g_doneCB = false;
376     printf("   Registering All Discovered Unowned Devices..\n");
377     OCStackResult rst = OCDoOwnershipTransfer((void*) g_ctx, g_unown_list, ownershipTransferCB);
378     if(OC_STACK_OK != rst)
379     {
380         OIC_LOG_V(ERROR, TAG, "OCDoOwnershipTransfer API error: %d", rst);
381         return -1;
382     }
383     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
384     {
385         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
386         return -1;
387     }
388
389     // display the registered result
390     printf("   > Registered Discovered Unowned Devices\n");
391     printf("   > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
392
393     return 0;
394 }
395
396 static int provisionPairwise(void)
397 {
398     // check |own_list| for provisioning pairwise devices
399     if(!g_own_list || 2>g_own_cnt)
400     {
401         printf("   > Owned Device List, to Provision the Pairwise, is Empty\n");
402         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
403         return 0;  // normal case
404     }
405
406     // select two devices for provisioning pairwise devices
407     int dev_num[2] = {0};
408     if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Linking Devices"))
409     {
410         OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
411         return -1;  // not need to 'goto' |ERROR| before allocating |acl|
412     }
413
414     // create ACL(s) for each selected device
415     OicSecAcl_t* acl[2] = {0};
416     for(int i=0; 2>i; ++i)
417     {
418         acl[i] = createAcl(dev_num[i]);
419         if(!acl[i])
420         {
421             OIC_LOG(ERROR, TAG, "createAcl error return");
422             goto PVPWS_ERROR;
423         }
424     }
425
426     // call |OCProvisionPairwiseDevices| API actually
427     // calling this API with callback actually acts like blocking
428     // for error checking, the return value saved and printed
429     g_doneCB = false;
430     printf("   Provisioning Selected Pairwise Devices..\n");
431     OCStackResult rst =
432             OCProvisionPairwiseDevices((void*) g_ctx,
433                     SYMMETRIC_PAIR_WISE_KEY, OWNER_PSK_LENGTH_128,
434                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]), acl[0],
435                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]), acl[1],
436                     provisionPairwiseCB);
437     if(OC_STACK_OK != rst)
438     {
439         OIC_LOG_V(ERROR, TAG, "OCProvisionPairwiseDevices API error: %d", rst);
440         goto PVPWS_ERROR;
441     }
442     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
443     {
444         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
445         goto PVPWS_ERROR;
446     }
447     OCDeleteACLList(acl[0]);
448     OCDeleteACLList(acl[1]);
449
450     // display the pairwise-provisioned result
451     printf("   > Provisioned Selected Pairwise Devices\n");
452     printf("   > Please Check Device's Status for the Linked Result, with [33] Menu\n");
453
454     return 0;
455
456 PVPWS_ERROR:
457     OCDeleteACLList(acl[0]);
458     OCDeleteACLList(acl[1]);
459     return -1;
460 }
461
462 static int provisionCred(void)
463 {
464     // check |own_list| for provisioning pairwise credentials
465     if(!g_own_list || 2>g_own_cnt)
466     {
467         printf("   > Owned Device List, to Provision Credentials, is Empty\n");
468         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
469         return 0;  // normal case
470     }
471
472     // select two devices for provisioning pairwise credentials
473     int dev_num[2] = {0};
474     if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Linking CRED(s)"))
475     {
476         OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
477         return -1;
478     }
479
480     printf("   Select PSK length..\n");
481     printf("   1 - 128bit(Default)\n");
482     printf("   2 - 256bit\n");
483     int sizeOption = 0;
484
485     for(int ret=0; 1!=ret; )
486     {
487          ret = scanf("%d",&sizeOption);
488          for( ; 0x20<=getchar(); );  // for removing overflow garbages
489                                     // '0x20<=code' is character region
490     }
491     size_t size = 0;
492
493     switch(sizeOption)
494     {
495         case 1:
496         {
497             size = OWNER_PSK_LENGTH_128;
498             break;
499         }
500         case 2:
501         {
502             size = OWNER_PSK_LENGTH_256;
503             break;
504         }
505         default:
506         {
507             size = OWNER_PSK_LENGTH_128;
508             break;
509         }
510     }
511
512
513     // call |OCProvisionCredentials| API actually
514     // calling this API with callback actually acts like blocking
515     // for error checking, the return value saved and printed
516     g_doneCB = false;
517     printf("   Provisioning Selected Pairwise Credentials..\n");
518     OCStackResult rst =
519             OCProvisionCredentials((void*) g_ctx,
520                     SYMMETRIC_PAIR_WISE_KEY, size,
521                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]),
522                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]),
523                     provisionCredCB);
524     if(OC_STACK_OK != rst)
525     {
526         OIC_LOG_V(ERROR, TAG, "OCProvisionCredentials API error: %d", rst);
527         return -1;
528     }
529     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
530     {
531         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
532         return -1;
533     }
534
535     // display the CRED-provisioned result
536     printf("   > Provisioned Selected Pairwise Crendentials\n");
537     printf("   > Please Check Device's Status for the Linked Result, with [33] Menu\n");
538
539     return 0;
540 }
541
542 static int provisionAcl(void)
543 {
544     // check |own_list| for provisioning access control list
545     if(!g_own_list || 1>g_own_cnt)
546     {
547         printf("   > Owned Device List, to Provision ACL, is Empty\n");
548         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
549         return 0;  // normal case
550     }
551
552     // select device for provisioning access control list
553     int dev_num = 0;
554     for( ; ; )
555     {
556         printf("   > Enter Device Number, for Provisioning ACL: ");
557         for(int ret=0; 1!=ret; )
558         {
559             ret = scanf("%d", &dev_num);
560             for( ; 0x20<=getchar(); );  // for removing overflow garbages
561                                         // '0x20<=code' is character region
562         }
563         if(0<dev_num && g_own_cnt>=dev_num)
564         {
565             break;
566         }
567         printf("     Entered Wrong Number. Please Enter Again\n");
568     }
569
570     // create ACL for selected device
571     OicSecAcl_t* acl = NULL;
572     acl = createAcl(dev_num);
573     if(!acl)
574     {
575         OIC_LOG(ERROR, TAG, "createAcl error return");
576         goto PVACL_ERROR;
577     }
578
579     // call |OCProvisionACL| API actually
580     // calling this API with callback actually acts like blocking
581     // for error checking, the return value saved and printed
582     g_doneCB = false;
583     printf("   Provisioning Selected ACL..\n");
584     OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*) g_own_list, dev_num);
585     if(!dev)
586     {
587         OIC_LOG(ERROR, TAG, "provisionAcl: device instance empty");
588         goto PVACL_ERROR;
589     }
590     OCStackResult rst = OCProvisionACL((void*) g_ctx, dev, acl, provisionAclCB);
591     if(OC_STACK_OK != rst)
592     {
593         OIC_LOG_V(ERROR, TAG, "OCProvisionACL API error: %d", rst);
594         goto PVACL_ERROR;
595     }
596     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
597     {
598         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
599         goto PVACL_ERROR;
600     }
601     OCDeleteACLList(acl);  // after here |acl| points nothing
602
603     // display the ACL-provisioned result
604     printf("   > Provisioned Selected ACL\n");
605
606     return 0;
607
608 PVACL_ERROR:
609     OCDeleteACLList(acl);  // after here |acl| points nothing
610     return -1;
611 }
612
613 static int provisionDirectPairing(void)
614 {
615     // check |own_list| for provisioning direct-pairing
616     if(!g_own_list || 1>g_own_cnt)
617     {
618         printf("   > Owned Device List, to Provision ACL, is Empty\n");
619         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
620         return 0;  // normal case
621     }
622
623     // select device for provisioning direct-pairing
624     int dev_num = 0;
625     for( ; ; )
626     {
627         printf("   > Enter Device Number, for Provisioning Direct-Pairing: ");
628         for(int ret=0; 1!=ret; )
629         {
630             ret = scanf("%d", &dev_num);
631             for( ; 0x20<=getchar(); );  // for removing overflow garbages
632                                         // '0x20<=code' is character region
633         }
634         if(0<dev_num && g_own_cnt>=dev_num)
635         {
636             break;
637         }
638         printf("     Entered Wrong Number. Please Enter Again\n");
639     }
640
641     // create Direct-Pairing Configuration(PIN, PDACL) for selected device
642     // TODO: default acl -> input from user !
643     OicSecPconf_t pconf;
644     memset(&pconf, 0, sizeof(OicSecPconf_t));
645
646     // set enable dp
647     pconf.edp = true;
648
649     // set default supported PRM types
650     pconf.prmLen = sizeof(SUPPORTED_PRMS)/sizeof(OicSecPrm_t);
651     pconf.prm = (OicSecPrm_t *)OICCalloc(pconf.prmLen, sizeof(OicSecPrm_t));
652     if(pconf.prm)
653     {
654         for (size_t i=0; i<pconf.prmLen; i++)
655         {
656             pconf.prm[i] = SUPPORTED_PRMS[i];
657         }
658     }
659     else
660     {
661         OIC_LOG(ERROR, TAG, "create prm error return");
662         goto PVDP_ERROR;
663     }
664
665     // set default pin
666     const char DP_DEFAULT_PIN[] = "00000000";
667     memcpy(pconf.pin.val, DP_DEFAULT_PIN, DP_PIN_LENGTH);
668
669     // set default pdacl
670     pconf.pdacls = createPdAcl(dev_num);
671     if(!pconf.pdacls)
672     {
673         OIC_LOG(ERROR, TAG, "createPdAcl error return");
674         goto PVDP_ERROR;
675     }
676
677     // call |OCProvisionDirectPairing| API actually
678     // calling this API with callback actually acts like blocking
679     // for error checking, the return value saved and printed
680     g_doneCB = false;
681     printf("   Atempt Direct-Pairing Provisioning (PIN : [%s])..\n", (char*)pconf.pin.val);
682     OCStackResult rst = OCProvisionDirectPairing((void*) g_ctx,
683                                        getDevInst((const OCProvisionDev_t*) g_own_list, dev_num),
684                                        &pconf, provisionDPCB);
685     if(OC_STACK_OK != rst)
686     {
687         OIC_LOG_V(ERROR, TAG, "OCProvisionDirectPairing API error: %d", rst);
688         if (OC_STACK_UNAUTHORIZED_REQ == rst)
689         {
690             OIC_LOG(ERROR, TAG, "Target Server NOT Support Direct-Pairing !!! (DPC == false)");
691         }
692         goto PVDP_ERROR;
693     }
694     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
695     {
696         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
697         goto PVDP_ERROR;
698     }
699     OCDeletePdAclList(pconf.pdacls);
700
701     // display the PCONF-provisioned result
702     printf("   > SUCCESS to provision Direct-Pairing !!\n");
703
704     return 0;
705
706 PVDP_ERROR:
707     OCDeletePdAclList(pconf.pdacls);  // after here |acl| points nothing
708     return -1;
709 }
710
711 static int checkLinkedStatus(void)
712 {
713     // check |own_list| for checking selected link status on PRVN DB
714     if(!g_own_list || 1>g_own_cnt)
715     {
716         printf("   > Owned Device List, to Check Linked Status on PRVN DB, is Empty\n");
717         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
718         return 0;  // normal case
719     }
720
721     // select device for checking selected link status on PRVN DB
722     int dev_num = 0;
723     for( ; ; )
724     {
725         printf("   > Enter Device Number, for Checking Linked Status on PRVN DB: ");
726         for(int ret=0; 1!=ret; )
727         {
728             ret = scanf("%d", &dev_num);
729             for( ; 0x20<=getchar(); );  // for removing overflow garbages
730                                         // '0x20<=code' is character region
731         }
732         if(0<dev_num && g_own_cnt>=dev_num)
733         {
734             break;
735         }
736         printf("     Entered Wrong Number. Please Enter Again\n");
737     }
738
739     // call |OCGetLinkedStatus| API actually
740     printf("   Checking Selected Link Status on PRVN DB..\n");
741     OCUuidList_t* dvid_lst = NULL;
742     size_t dvid_cnt = 0;
743     OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*)g_own_list, dev_num);
744     if(!dev || !dev->doxm)
745     {
746         OIC_LOG(ERROR, TAG, "checkLinkedStatus: device instance empty");
747         goto CKLST_ERROR;
748     }
749
750     if(OC_STACK_OK !=
751             OCGetLinkedStatus(
752                     &dev->doxm->deviceID,
753                     &dvid_lst, &dvid_cnt))  // allow empty list
754     {
755         OIC_LOG(ERROR, TAG, "OCGetLinkedStatus API error");
756         goto CKLST_ERROR;
757     }
758
759     // display the linked status result
760     printf("   > Checked Selected Link Status on PRVN DB\n");
761     if(!dvid_lst || !dvid_cnt)  // |size_t| is unsigned
762     {
763         printf("     Linked Device List is Empty..\n");
764         return 0;  // normal case
765     }
766     if(dvid_cnt != printUuidList((const OCUuidList_t*) dvid_lst))
767     {
768         OIC_LOG(ERROR, TAG, "printUuidList error return");
769         goto CKLST_ERROR;
770     }
771     OCDeleteUuidList(dvid_lst);
772
773     return 0;
774
775 CKLST_ERROR:
776     OCDeleteUuidList(dvid_lst);
777     return -1;
778 }
779
780 static int unlinkPairwise(void)
781 {
782     // check |own_list| for unlinking pairwise devices
783     if(!g_own_list || 2>g_own_cnt)
784     {
785         printf("   > Owned Device List, to Unlink the Pairwise, is Empty\n");
786         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
787         return 0;  // normal case
788     }
789
790     // select two devices for unlinking pairwise devices
791     int dev_num[2] = {0};
792     if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Unlinking Devices"))
793     {
794         OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
795         return -1;
796     }
797
798     // call |OCUnlinkDevices| API actually
799     // calling this API with callback actually acts like blocking
800     // for error checking, the return value saved and printed
801     g_doneCB = false;
802     printf("   Unlinking Selected Pairwise Devices..\n");
803     OCStackResult rst =
804             OCUnlinkDevices((void*) g_ctx,
805                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]),
806                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]),
807                     unlinkDevicesCB);
808     if(OC_STACK_OK != rst)
809     {
810         OIC_LOG_V(ERROR, TAG, "OCUnlinkDevices API error: %d", rst);
811         return -1;
812     }
813     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
814     {
815         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
816         return -1;
817     }
818
819     // display the pairwise-unlinked result
820     printf("   > Unlinked Selected Pairwise Devices\n");
821     printf("   > Please Check Device's Status for the Unlinked Result, with [33] Menu\n");
822
823     return 0;
824 }
825
826 static int removeDevice(void)
827 {
828     // check |own_list| for removing device
829     if(!g_own_list || 1>g_own_cnt)
830     {
831         printf("   > Owned Device List, to Remove Device, is Empty\n");
832         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
833         return 0;  // normal case
834     }
835
836     // select device for removing it
837     int dev_num = 0;
838     for( ; ; )
839     {
840         printf("   > Enter Device Number, for Removing Device: ");
841         for(int ret=0; 1!=ret; )
842         {
843             ret = scanf("%d", &dev_num);
844             for( ; 0x20<=getchar(); );  // for removing overflow garbages
845                                         // '0x20<=code' is character region
846         }
847         if(0<dev_num && g_own_cnt>=dev_num)
848         {
849             break;
850         }
851         printf("     Entered Wrong Number. Please Enter Again\n");
852     }
853
854     // call |OCRemoveDevice| API actually
855     // calling this API with callback actually acts like blocking
856     // for error checking, the return value saved and printed
857     g_doneCB = false;
858     printf("   Removing Selected Owned Device..\n");
859     OCStackResult rst =
860             OCRemoveDevice((void*) g_ctx, DISCOVERY_TIMEOUT,
861                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num), removeDeviceCB);
862     if(OC_STACK_OK != rst)
863     {
864         OIC_LOG_V(ERROR, TAG, "OCRemoveDevice API error: %d", rst);
865         return -1;
866     }
867     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
868     {
869         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
870         return -1;
871     }
872
873     // display the removed result
874     printf("   > Removed Selected Owned Device\n");
875     printf("   > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
876
877     return 0;
878 }
879
880 static OicSecAcl_t* createAcl(const int dev_num)
881 {
882     if(0>=dev_num || g_own_cnt<dev_num)
883     {
884         OIC_LOG(ERROR, TAG, "createAcl invalid parameters");
885         return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
886     }
887
888     // allocate memory for |acl| struct
889     printf("   **** Create ACL for the Selected Device[%d]\n", dev_num);
890     OicSecAcl_t* acl = (OicSecAcl_t*) OICCalloc(1, sizeof(OicSecAcl_t));
891     if(!acl)
892     {
893         OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
894         return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
895     }
896
897     // enter |subject| device number
898     int num = 0;
899     for( ; ; )
900     {
901         printf("   > [A] Enter Subject Device Number: ");
902         for(int ret=0; 1!=ret; )
903         {
904             ret = scanf("%d", &num);
905             for( ; 0x20<=getchar(); );  // for removing overflow garbages
906                                         // '0x20<=code' is character region
907         }
908         if(0<num && g_own_cnt>=num && dev_num!=num)
909         {
910             break;
911         }
912         printf("     Entered Wrong Number. Please Enter Again\n");
913     }
914
915     OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*)g_own_list, num);
916     if(!dev || !dev->doxm)
917     {
918         OIC_LOG(ERROR, TAG, "createAcl: device instance empty");
919         goto CRACL_ERROR;
920     }
921     memcpy(&acl->subject, &dev->doxm->deviceID, UUID_LENGTH);
922
923     // enter number of |resources| in 'accessed' device
924     for( ; ; )
925     {
926         printf("   > [B] Enter Number of Accessed Resources (under 16): ");
927                 // '16' is |ACL_RESRC_MAX_NUM|
928         for(int ret=0; 1!=ret; )
929         {
930             ret = scanf("%d", &num);
931             for( ; 0x20<=getchar(); );  // for removing overflow garbages
932                                         // '0x20<=code' is character region
933         }
934         if(0<num && ACL_RESRC_MAX_NUM>=num)
935         {
936             break;
937         }
938         printf("     Entered Wrong Number. Please Enter under 16 Again\n");
939                 // '16' is |ACL_RESRC_MAX_NUM|
940     }
941
942     // enter actually each 'accessed' |resources| name
943     printf("         Enter Each Accessed Resource Name (each under 128 char)\n");
944             // '128' is ACL_RESRC_MAX_LEN
945     acl->resourcesLen = (unsigned) num;
946     acl->resources = (char**) OICCalloc(acl->resourcesLen, sizeof(char*));
947     if(!acl->resources)
948     {
949         OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
950         goto CRACL_ERROR;
951     }
952     char rsrc_in[ACL_RESRC_MAX_LEN+1] = {0};  // '1' for null termination
953     for(int i=0; acl->resourcesLen>(unsigned)i; ++i)
954     {
955         printf("         Enter Accessed Resource[%d] Name: ", i+1);
956         for(int ret=0; 1!=ret; )
957         {
958             ret = scanf("%128s", rsrc_in);  // '128' is ACL_RESRC_MAX_LEN
959             for( ; 0x20<=getchar(); );  // for removing overflow garbages
960                                         // '0x20<=code' is character region
961         }
962         size_t len = strlen(rsrc_in)+1;  // '1' for null termination
963         char* rsrc = (char*) OICCalloc(len, sizeof(char));
964         if(!rsrc)
965         {
966             OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
967             goto CRACL_ERROR;
968         }
969         OICStrcpy(rsrc, len, rsrc_in);
970         acl->resources[i] = rsrc;  // after here, |rsrc| points nothing
971     }
972
973     // enter |permission| for this access
974     printf("   > [C] Enter Permission for This Access\n");
975     uint16_t pmsn = PERMISSION_FULL_CONTROL;  // default full permission
976     uint16_t pmsn_msk = PERMISSION_CREATE;  // default permission mask
977     for(int i=0; ACL_PEMISN_CNT>i; ++i)
978     {
979         char ans = 0;
980         for( ; ; )
981         {
982             printf("         Enter %s Permission (y/n): ", ACL_PEMISN[i]);
983             for(int ret=0; 1!=ret; )
984             {
985                 ret = scanf("%c", &ans);
986                 for( ; 0x20<=getchar(); );  // for removing overflow garbages
987                                             // '0x20<=code' is character region
988             }
989             if('y'==ans || 'Y'==ans || 'n'==ans|| 'N'==ans)
990             {
991                 ans &= ~0x20;  // for masking lower case, 'y/n'
992                 break;
993             }
994             printf("         Entered Wrong Answer. Please Enter 'y/n' Again\n");
995         }
996         if('N' == ans)  // masked lower case, 'n'
997         {
998             pmsn -= pmsn_msk;
999         }
1000         pmsn_msk <<= 1;
1001     }
1002     acl->permission = pmsn;
1003
1004     // enter |owner| device number
1005     int own_num = 0;
1006     for( ; ; )
1007     {
1008         printf("   > [D] Enter Owner Device Number: ");
1009         for(int ret=0; 1!=ret; )
1010         {
1011             ret = scanf("%d", &own_num);
1012             for( ; 0x20<=getchar(); );  // for removing overflow garbages
1013                                         // '0x20<=code' is character region
1014         }
1015         if(0<own_num && g_own_cnt>=own_num)
1016         {
1017             break;
1018         }
1019         printf("         Entered Wrong Number. Please Enter Again\n");
1020     }
1021     acl->ownersLen = 1;
1022     acl->owners = (OicUuid_t*) OICCalloc(1, sizeof(OicUuid_t));
1023     if(!acl->owners)
1024     {
1025         OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1026         goto CRACL_ERROR;
1027     }
1028
1029     dev = getDevInst((const OCProvisionDev_t*)g_own_list, own_num);
1030     if(!dev || !dev->doxm)
1031     {
1032         OIC_LOG(ERROR, TAG, "createAcl: device instance empty");
1033         goto CRACL_ERROR;
1034     }
1035     memcpy(acl->owners, &dev->doxm->deviceID, UUID_LENGTH);
1036     printf("\n");
1037
1038     return acl;
1039
1040 CRACL_ERROR:
1041     OCDeleteACLList(acl);  // after here |acl| points nothing
1042     return NULL;
1043 }
1044
1045 static OicSecPdAcl_t* createPdAcl(const int dev_num)
1046 {
1047     if(0>=dev_num || g_own_cnt<dev_num)
1048     {
1049         OIC_LOG(ERROR, TAG, "createAcl invalid parameters");
1050         return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
1051     }
1052
1053     // allocate memory for |pdacl| struct
1054     printf("   **** Create PDACL for the Selected Device[%d]\n", dev_num);
1055     OicSecPdAcl_t* pdAcl = (OicSecPdAcl_t*) OICCalloc(1, sizeof(OicSecPdAcl_t));
1056     if(!pdAcl)
1057     {
1058         OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1059         return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
1060     }
1061
1062
1063     // number of resources
1064     char rsrc_in[][ACL_RESRC_MAX_LEN+1] = {"*", "/rsrc/*"};
1065     pdAcl->resourcesLen = 1;
1066
1067     // resource
1068     int num = pdAcl->resourcesLen;
1069     pdAcl->resources = (char**) OICCalloc(num, sizeof(char*));
1070     if(!pdAcl->resources)
1071     {
1072         OIC_LOG(ERROR, TAG, "createPdAcl: OICCalloc error return");
1073         goto CRPDACL_ERROR;
1074     }
1075     for(int i=0; num>i; ++i)
1076     {
1077         size_t len = strlen(rsrc_in[i])+1;  // '1' for null termination
1078         char* rsrc = (char*) OICCalloc(len, sizeof(char));
1079         if(!rsrc)
1080         {
1081             OIC_LOG(ERROR, TAG, "createPdAcl: OICCalloc error return");
1082             goto CRPDACL_ERROR;
1083         }
1084         OICStrcpy(rsrc, len, rsrc_in[i]);
1085         pdAcl->resources[i] = rsrc;  // after here, |rsrc| points nothing
1086     }
1087
1088     // permission
1089     pdAcl->permission = PERMISSION_FULL_CONTROL;
1090
1091     return pdAcl;
1092
1093 CRPDACL_ERROR:
1094     OCDeletePdAclList(pdAcl);
1095     return NULL;
1096 }
1097
1098 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t* dev_lst, const int dev_num)
1099 {
1100     if(!dev_lst || 0>=dev_num)
1101     {
1102         printf("     Device List is Empty..\n");
1103         return NULL;
1104     }
1105
1106     OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
1107     for(int i=0; lst; )
1108     {
1109         if(dev_num == ++i)
1110         {
1111             return lst;
1112         }
1113         lst = lst->next;
1114     }
1115
1116     return NULL;  // in here |lst| is always |NULL|
1117 }
1118
1119 static int printDevList(const OCProvisionDev_t* dev_lst)
1120 {
1121     if(!dev_lst)
1122     {
1123         printf("     Device List is Empty..\n\n");
1124         return 0;
1125     }
1126
1127     OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
1128     int lst_cnt = 0;
1129     for( ; lst; )
1130     {
1131         printf("     [%d] ", ++lst_cnt);
1132         printUuid((const OicUuid_t*) &lst->doxm->deviceID);
1133         printf("\n");
1134         lst = lst->next;
1135     }
1136     printf("\n");
1137
1138     return lst_cnt;
1139 }
1140
1141 static size_t printUuidList(const OCUuidList_t* uid_lst)
1142 {
1143     if(!uid_lst)
1144     {
1145         printf("     Device List is Empty..\n\n");
1146         return 0;
1147     }
1148
1149     OCUuidList_t* lst = (OCUuidList_t*) uid_lst;
1150     size_t lst_cnt = 0;
1151     for( ; lst; )
1152     {
1153         printf("     [%zu] ", ++lst_cnt);
1154         printUuid((const OicUuid_t*) &lst->dev);
1155         printf("\n");
1156         lst = lst->next;
1157     }
1158     printf("\n");
1159
1160     return lst_cnt;
1161 }
1162
1163 static int printResultList(const OCProvisionResult_t* rslt_lst, const int rslt_cnt)
1164 {
1165     if(!rslt_lst || 0>=rslt_cnt)
1166     {
1167         printf("     Device List is Empty..\n\n");
1168         return 0;
1169     }
1170
1171     int lst_cnt = 0;
1172     for( ; rslt_cnt>lst_cnt; ++lst_cnt)
1173     {
1174         printf("     [%d] ", lst_cnt+1);
1175         printUuid((const OicUuid_t*) &rslt_lst[lst_cnt].deviceId);
1176         printf(" - result: %d\n", rslt_lst[lst_cnt].res);
1177     }
1178     printf("\n");
1179
1180     return lst_cnt;
1181 }
1182
1183 static void printUuid(const OicUuid_t* uid)
1184 {
1185     for(int i=0; i<UUID_LENGTH; )
1186     {
1187         printf("%02X", (*uid).id[i++]);
1188         if(i==4 || i==6 || i==8 || i==10)  // canonical format for UUID has '8-4-4-4-12'
1189         {
1190             printf("-");
1191         }
1192     }
1193 }
1194
1195 static FILE* fopen_prvnMng(const char* path, const char* mode)
1196 {
1197     (void)path;  // unused |path| parameter
1198
1199     // input |g_svr_db_fname| internally by force, not using |path| parameter
1200     // because |OCPersistentStorage::open| is called |OCPersistentStorage| internally
1201     // with its own |SVR_DB_FILE_NAME|
1202     return fopen(SVR_DB_FILE_NAME, mode);
1203 }
1204
1205 static int waitCallbackRet(void)
1206 {
1207     for(int i=0; !g_doneCB && CALLBACK_TIMEOUT>i; ++i)
1208     {
1209         sleep(1);
1210         if(OC_STACK_OK != OCProcess())
1211         {
1212             OIC_LOG(ERROR, TAG, "OCStack process error");
1213             return -1;
1214         }
1215     }
1216
1217     return 0;
1218 }
1219
1220 static int selectTwoDiffNum(int* a, int* b, const int max, const char* str)
1221 {
1222     if(!a || !b || 2>=max || !str)
1223     {
1224         return -1;
1225     }
1226
1227     for( ; ; )
1228     {
1229         for(int i=0; 2>i; ++i)
1230         {
1231             int* num = 0==i?a:b;
1232             for( ; ; )
1233             {
1234                 printf("   > Enter Device[%d] Number, %s: ", i+1, str);
1235                 for(int ret=0; 1!=ret; )
1236                 {
1237                     ret = scanf("%d", num);
1238                     for( ; 0x20<=getchar(); );  // for removing overflow garbages
1239                                                 // '0x20<=code' is character region
1240                 }
1241                 if(0<*num && max>=*num)
1242                 {
1243                     break;
1244                 }
1245                 printf("     Entered Wrong Number. Please Enter Again\n");
1246             }
1247         }
1248         if(*a != *b)
1249         {
1250             printf("\n");
1251             return 0;
1252         }
1253     }
1254
1255     return -1;
1256 }
1257
1258 static void printMenu(void)
1259 {
1260     printf("************************************************************\n");
1261     printf("****** OIC Provisioning Client with using C-level API ******\n");
1262     printf("************************************************************\n\n");
1263
1264     printf("** [A] DISCOVER DEVICES ON NETWORK\n");
1265     printf("** 10. Discover All Un/Owned Devices on Network\n");
1266     printf("** 11. Discover Only Unowned Devices on Network\n");
1267     printf("** 12. Discover Only Owned Devices on Network\n\n");
1268
1269     printf("** [B] REGISTER/OWN ALL DISCOVERED UNOWNED DEVICES\n");
1270     printf("** 20. Register/Own All Discovered Unowned Devices\n\n");
1271
1272     printf("** [C] PROVISION/LINK PAIRWISE THINGS\n");
1273     printf("** 30. Provision/Link Pairwise Things\n");
1274     printf("** 31. Provision Credentials for Pairwise Things\n");
1275     printf("** 32. Provision the Selected Access Control List(ACL)\n");
1276     printf("** 33. Provision Direct-Pairing Configuration\n");
1277     printf("** 34. Check Linked Status of the Selected Device on PRVN DB\n\n");
1278
1279     printf("** [D] UNLINK PAIRWISE THINGS\n");
1280     printf("** 40. Unlink Pairwise Things\n\n");
1281
1282     printf("** [E] REMOVE THE SELECTED DEVICE\n");
1283     printf("** 50. Remove the Selected Device\n\n");
1284
1285     printf("** [F] EXIT PROVISIONING CLIENT\n");
1286     printf("** 99. Exit Provisionong Client\n\n");
1287
1288     printf("************************************************************\n\n");
1289 }
1290
1291 #if 0 // Code for enabling path configuration for PDB and SVR DBf
1292 static void printUsage(void)
1293 {
1294     printf("\n");
1295     printf("OIC Provisioning Client with using C-level API\n");
1296     printf("Usage: provisioningclient [option]...\n");
1297     printf("\n");
1298     printf("  -h                           print help for this provisioning client\n");
1299     printf("  -p=[prvn_db_file_path/name]  input PRVN DB file path and name\n");
1300     printf("                               if not exists, will load default DB file\n");
1301     printf("                               (default: |oic_prvn_mng.db| on working dir)\n");
1302     printf("                               (ex. -p=oic_prvn_mng.db)\n");
1303     printf("  -s=[svr_db_file_path/name]   input SVR DB file path and name\n");
1304     printf("                               if not exists, will load default DB file\n");
1305     printf("                               (default: |oic_svr_db_client.json| on working dir)\n");
1306     printf("                               (ex. -s=oic_svr_db_client.json)\n");
1307     printf("\n");
1308 }
1309 #endif
1310
1311 // main function for provisioning client using C-level provisioning API
1312 int main()
1313 {
1314     // initialize provisioning client
1315     if(initProvisionClient())
1316     {
1317         OIC_LOG(ERROR, TAG, "ProvisionClient init error");
1318         goto PMCLT_ERROR;
1319     }
1320
1321     // main loop for provisioning manager
1322     int mn_num = 0;
1323     for( ; ; )
1324     {
1325         printf("\n");
1326         printMenu();
1327         printf(">> Enter Menu Number: ");
1328         for(int ret=0; 1!=ret; )
1329         {
1330             ret = scanf("%d", &mn_num);
1331             for( ; 0x20<=getchar(); );  // for removing overflow garbages
1332                                         // '0x20<=code' is character region
1333         }
1334         printf("\n");
1335         switch(mn_num)
1336         {
1337         case _10_DISCOV_ALL_DEVS_:
1338             if(discoverAllDevices())
1339             {
1340                 OIC_LOG(ERROR, TAG, "_10_DISCOV_ALL_DEVS_: error");
1341             }
1342             break;
1343         case _11_DISCOV_UNOWN_DEVS_:
1344             if(discoverUnownedDevices())
1345             {
1346                 OIC_LOG(ERROR, TAG, "_11_DISCOV_UNOWN_DEVS_: error");
1347             }
1348             break;
1349         case _12_DISCOV_OWN_DEVS_:
1350             if(discoverOwnedDevices())
1351             {
1352                 OIC_LOG(ERROR, TAG, "_12_DISCOV_OWN_DEVS_: error");
1353             }
1354             break;
1355         case _20_REGIST_DEVS_:
1356             if(registerDevices())
1357             {
1358                 OIC_LOG(ERROR, TAG, "_20_REGIST_DEVS_: error");
1359             }
1360             break;
1361         case _30_PROVIS_PAIR_DEVS_:
1362             if(provisionPairwise())
1363             {
1364                 OIC_LOG(ERROR, TAG, "_30_PROVIS_PAIR_DEVS_: error");
1365             }
1366             break;
1367         case _31_PROVIS_CRED_:
1368             if(provisionCred())
1369             {
1370                 OIC_LOG(ERROR, TAG, "_31_PROVIS_CRED_: error");
1371             }
1372             break;
1373         case _32_PROVIS_ACL_:
1374             if(provisionAcl())
1375             {
1376                 OIC_LOG(ERROR, TAG, "_32_PROVIS_ACL_: error");
1377             }
1378             break;
1379         case _33_PROVIS_DP_:
1380             if(provisionDirectPairing())
1381             {
1382                 OIC_LOG(ERROR, TAG, "_33_PROVIS_DP_: error");
1383             }
1384             break;
1385         case _34_CHECK_LINK_STATUS_:
1386             if(checkLinkedStatus())
1387             {
1388                 OIC_LOG(ERROR, TAG, "_34_CHECK_LINK_STATUS_: error");
1389             }
1390             break;
1391         case _40_UNLINK_PAIR_DEVS_:
1392             if(unlinkPairwise())
1393             {
1394                 OIC_LOG(ERROR, TAG, "_40_UNLINK_PAIR_DEVS_: error");
1395             }
1396             break;
1397         case _50_REMOVE_SELEC_DEV_:
1398             if(removeDevice())
1399             {
1400                 OIC_LOG(ERROR, TAG, "_50_REMOVE_SELEC_DEV_: error");
1401             }
1402             break;
1403         case _99_EXIT_PRVN_CLT_:
1404             goto PMCLT_ERROR;
1405         default:
1406             printf(">> Entered Wrong Number. Please Enter Again\n\n");
1407             break;
1408         }
1409     }
1410
1411 PMCLT_ERROR:
1412     if(OC_STACK_OK != OCStop())
1413     {
1414         OIC_LOG(ERROR, TAG, "OCStack stop error");
1415     }
1416     OCDeleteDiscoveredDevices(g_own_list);  // after here |g_own_list| points nothing
1417     OCDeleteDiscoveredDevices(g_unown_list);  // after here |g_unown_list| points nothing
1418
1419     if(g_svr_fname)
1420     {
1421         OICFree(g_svr_fname);  // after here |g_svr_fname| points nothing
1422     }
1423     if(g_prvn_fname)
1424     {
1425         OICFree(g_prvn_fname);  // after here |g_prvn_fname| points nothing
1426     }
1427     return 0;  // always return normal case
1428 }
1429
1430 #ifdef __cplusplus
1431 }
1432 #endif //__cplusplus