/* * Copyright (c) 2017 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef struct metis_control_main_state { KeystoreParams *keystoreParams; CCNxPortal *controlPortal; MetisControlState *controlState; } MetisControlMainState; static void _displayForwarderLogo(void) { printf("%s\n", metisAbout_About()); printf(" __ __ _ _\n"); printf(" | \\/ | ___ | |_ (_) ___\n"); printf(" | |\\/| | / _ \\| __|| |/ __|\n"); printf(" | | | || __/| |_ | |\\__ \\\n"); printf(" |_| |_| \\___| \\__||_||___/\n"); printf("\n"); } static void _displayUsage(char *programName) { printf("Usage: %s -h\n", programName); printf(" %s [--k|--keystore ] [--p|--password ] [commands]\n", programName); printf("\n"); printf("Metis is the CCNx 1.0 forwarder, which runs on each end system and as a software forwarder\n"); printf("on intermediate systems. metis_control is the program to configure the forwarder, metis_daemon.\n"); printf("\n"); printf("Options:\n"); printf("-h = This help screen\n"); printf("-k | --keystore = Specify the path of the PKCS12 keystore (default ~/.ccnx/.ccnx_keystore.p12)\n"); printf("-p | --password = keystore password (default to prompt user)\n"); printf("commands = configuration line to send to metis (use 'help' for list)\n"); printf("\n"); } static int _parseArgs(int argc, char *argv[], char **keystorePath, char **keystorePassword, PARCList *commandList) { static struct option longFormOptions[] = { { "help", no_argument, 0, 'h' }, { "keystore", required_argument, 0, 'k' }, { "password", required_argument, 0, 'p' }, { 0, 0, 0, 0 } }; int c; while (1) { // getopt_long stores the option index here. int optionIndex = 0; c = getopt_long(argc, argv, "hk:p:", longFormOptions, &optionIndex); // Detect the end of the options. if (c == -1) { break; } switch (c) { case 'k': *keystorePath = optarg; break; case 'p': *keystorePassword = optarg; break; case 'h': default: _displayUsage(argv[0]); return 0; } } // Any remaining parameters get put in the command list. if (optind < argc) { while (optind < argc) { parcList_Add(commandList, argv[optind]); optind++; } } return 1; } static CCNxMetaMessage * _writeAndReadMessage(void *mainStatePtr, CCNxMetaMessage *msg) { assertNotNull(mainStatePtr, "Parameter mainStatePtr must be non-null"); assertNotNull(msg, "Parameter msg must be non-null"); MetisControlMainState *mainState = mainStatePtr; if (ccnxPortal_Send(mainState->controlPortal, msg, CCNxStackTimeout_Never)) { CCNxMetaMessage *result = ccnxPortal_Receive(mainState->controlPortal, CCNxStackTimeout_Never); assertTrue(result != NULL, "Error reading response from Portal: (%d) %s\nb", errno, strerror(errno)); return result; } return NULL; } static CCNxPortal * _createPortalWithKeystore(const char *keystoreName, const char *keystorePassword) { PARCIdentityFile *identityFile = parcIdentityFile_Create(keystoreName, keystorePassword); PARCIdentity *identity = parcIdentity_Create(identityFile, PARCIdentityFileAsPARCIdentity); CCNxPortalFactory *portalFactory = ccnxPortalFactory_Create(identity); CCNxPortal *result = ccnxPortalFactory_CreatePortal(portalFactory, ccnxPortalRTA_Message); ccnxPortalFactory_Release(&portalFactory); parcIdentity_Release(&identity); parcIdentityFile_Release(&identityFile); return result; } static MetisControlMainState _openKeyStore(char *keystorePath, char *keystorePassword) { MetisControlMainState mainState; if (keystorePassword == NULL) { keystorePassword = ccnxKeystoreUtilities_ReadPassword(); mainState.keystoreParams = ccnxKeystoreUtilities_OpenFile(keystorePath, keystorePassword); parcMemory_Deallocate((void *) &keystorePassword); } else { mainState.keystoreParams = ccnxKeystoreUtilities_OpenFile(keystorePath, keystorePassword); } return mainState; } int main(int argc, char *argv[]) { _displayForwarderLogo(); if (argc == 2 && strcmp("-h", argv[1]) == 0) { _displayUsage(argv[0]); exit(EXIT_SUCCESS); } char *keystorePath = NULL; char *keystorePassword = NULL; PARCList *commands = parcList(parcArrayList_Create(NULL), PARCArrayListAsPARCList); // Extract optional keystore and password, and optional commands. if (!_parseArgs(argc, argv, &keystorePath, &keystorePassword, commands)) { parcList_Release(&commands); exit(EXIT_FAILURE); } if (keystorePath == NULL) { printf("No keystore specified. Will try default.\n"); } else { printf("Using keystore: %s\n", keystorePath); } parcSecurity_Init(); MetisControlMainState mainState = _openKeyStore(keystorePath, keystorePassword); if (mainState.keystoreParams == NULL) { printf("Could not open keystore '%s'\n", keystorePath == NULL ? "~/.ccnx/.ccnx_keystore.p12" : keystorePath); exit(EXIT_FAILURE); } mainState.controlPortal = _createPortalWithKeystore(ccnxKeystoreUtilities_GetFileName(mainState.keystoreParams), ccnxKeystoreUtilities_GetPassword(mainState.keystoreParams)); parcSecurity_Fini(); mainState.controlState = metisControlState_Create(&mainState, _writeAndReadMessage); metisControlState_RegisterCommand(mainState.controlState, metisControlRoot_HelpCreate(mainState.controlState)); metisControlState_RegisterCommand(mainState.controlState, metisControlRoot_Create(mainState.controlState)); if (parcList_Size(commands) > 0) { metisControlState_DispatchCommand(mainState.controlState, commands); } else { metisControlState_Interactive(mainState.controlState); } parcList_Release(&commands); metisControlState_Destroy(&mainState.controlState); keystoreParams_Destroy(&mainState.keystoreParams); ccnxPortal_Release(&mainState.controlPortal); return EXIT_SUCCESS; }