kinetic-c  v0.12.0
Seagate Kinetic Protocol Client Library for C
main.c
Go to the documentation of this file.
1 /*
2 * kinetic-c
3 * Copyright (C) 2015 Seagate Technology.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 */
20 
21 #include "kinetic_client.h"
22 #include "kinetic_admin_client.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <getopt.h>
26 
27 typedef enum OptionID {
28  OPT_NONE = 0,
29 
30  // Options with short IDs
31  OPT_HELP = '?',
32  OPT_LOGLEVEL = 'l',
33  OPT_HOST = 'h',
34  OPT_PORT = 'p',
35  OPT_TLSPORT = 't',
36  OPT_IDENTITY = 'i',
37  OPT_KEY = 'k',
38  OPT_VALUE = 'v',
40  OPT_FILE = 'f',
41 
42  // Options with only long IDs
43  OPT_HMACKEY = 200,
45  OPT_PIN = 202,
46  OPT_NEWPIN = 203,
47  OPT_LOGTYPE = 204,
49 
50  // Operations
51  OPT_NOOP = 300,
52  OPT_PUT = 301,
53  OPT_GET = 302,
54  OPT_DELETE = 303,
55  OPT_GETNEXT = 304,
57  OPT_GETLOG = 306,
66  OPT_SETACL = 315,
68 
70 } OptionID;
71 
72 struct UtilConfig {
73  OptionID opID;
74  int logLevel;
75  KineticClient * client;
76  KineticSessionConfig config;
77  KineticSessionConfig adminConfig;
78  KineticSession * session;
79  KineticSession * adminSession;
80 
81  uint8_t hmacKeyData[1024];
82  char pin[32];
83  char newPin[32];
84  int64_t newClusterVersion;
85  char file[256];
86  KineticLogInfo_Type logType;
87  char deviceLogName[64];
88 
89  // KineticEntry and associated buffer data
90  KineticEntry entry;
91  uint8_t keyData[1024];
92  uint8_t tagData[1024];
93  uint8_t newVersionData[1024];
94  uint8_t versionData[1024];
95  uint8_t valueData[KINETIC_OBJ_SIZE];
96 };
97 
98 #define OPT_MIN OPT_NOOP
99 
100 //------------------------------------------------------------------------------
101 // Private Method Declarations
102 static int ParseOptions(
103  const int argc,
104  char** const argv,
105  struct UtilConfig * cfg);
107  struct UtilConfig * cfg);
108 static void ConfigureEntry(
109  struct UtilConfig * cfg,
110  const char * key,
111  const char * tag,
112  const char * version,
113  KineticAlgorithm algorithm,
114  bool force,
115  const char * value);
116 static void PrintLogInfo(KineticLogInfo_Type type, KineticLogInfo* info);
117 static const char* GetOptString(OptionID opt_id);
118 
119 
120 void PrintUsage(const char* exec)
121 {
122  printf("Usage: %s --<cmd> [options...]\n", exec);
123  printf("%s --help\n", exec);
124 
125  // Standard API operations
126  printf("%s --noop"
127  " [--host <ip|hostname>] [--port <port>] [--clusterversion <clusterversion>]\n", exec);
128  printf("%s --put --key <key> --value <value>"
129  " [--host <ip|hostname>] [--port <port>] [--clusterversion <clusterversion>]\n", exec);
130  printf("%s --get --key <key>"
131  " [--host <ip|hostname>] [--port <port>] [--clusterversion <clusterversion>]\n", exec);
132  printf("%s --getnext --key <key>"
133  " [--host <ip|hostname>] [--port <port>] [--clusterversion <clusterversion>]\n", exec);
134  printf("%s --getprevious --key <key>"
135  " [--host <ip|hostname>] [--port <port>] [--clusterversion <clusterversion>]\n", exec);
136  printf("%s --delete --key <key>"
137  " [--host <ip|hostname>] [--port <port>] [--clusterversion <clusterversion>]\n", exec);
138 
139  // Admin API operations
140  printf("%s --getlog --logtype <utilizations|temperatures|capacities|configuration|statistics|messages|limits>"
141  " [--host <ip|hostname>] [--tlsport <tlsport>] [--clusterversion <clusterversion>]\n", exec);
142  printf("%s --getdevicespecificlog --devicelogname <name|ID>"
143  " [--host <ip|hostname>] [--tlsport <tlsport>] [--clusterversion <clusterversion>]\n", exec);
144  printf("%s --setclusterversion --newclusterversion <newclusterversion>"
145  " [--host <ip|hostname>] [--tlsport <tlsport>] [--clusterversion <clusterversion>]\n", exec);
146  printf("%s --seterasepin --pin <oldpin> --newpin <newerasepin>"
147  " [--host <ip|hostname>] [--tlsport <tlsport>] [--clusterversion <clusterversion>]\n", exec);
148  printf("%s --instanterase --pin <erasepin>"
149  " [--host <ip|hostname>] [--tlsport <tlsport>] [--clusterversion <clusterversion>]\n", exec);
150  printf("%s --secureerase --pin <erasepin>"
151  " [--host <ip|hostname>] [--tlsport <tlsport>] [--clusterversion <clusterversion>]\n", exec);
152  printf("%s --setlockpin --pin <oldpin>> <--newpin <newpin>"
153  " [--host <ip|hostname>] [--tlsport <tlsport>] [--clusterversion <clusterversion>]\n", exec);
154  printf("%s --lockdevice --pin <lockpin>"
155  " [--host <ip|hostname>] [--tlsport <tlsport>] [--clusterversion <clusterversion>]\n", exec);
156  printf("%s --unlockdevice --pin <lockpin>"
157  " [--host <ip|hostname>] [--tlsport <tlsport>] [--clusterversion <clusterversion>]\n", exec);
158  printf("%s --setacl --file <acl_json_file>"
159  " [--host <ip|hostname>] [--tlsport <tlsport>] [--clusterversion <clusterversion>]\n", exec);
160  printf("%s --updatefirmware --file <file> --pin <pin>"
161  " [--host <ip|hostname>] [--port <port>] [--clusterversion <clusterversion>] \n", exec);
162 }
163 
164 
165 //------------------------------------------------------------------------------
166 // Main Entry Point Definition
167 int main(int argc, char** argv)
168 {
169  struct UtilConfig cfg;
170  memset(&cfg, 0, sizeof(cfg));
171 
172  // Parse command line options
173  ParseOptions(argc, argv, &cfg);
174  if (cfg.opID == OPT_NONE) {
175  fprintf(stderr, "No operation specified!\n");
176  PrintUsage(argv[0]);
177  exit(1);
178  }
179 
180  // Create a client instance
181  KineticClientConfig client_config = {
182  .logFile = "stdout",
183  .logLevel = cfg.logLevel,
184  };
185  cfg.client = KineticClient_Init(&client_config);
186  if (cfg.client == NULL) {
187  fprintf(stderr, "Failed creating a client instance!\n");
188  return 1;
189  }
190 
191  // Establish a session with the Kinetic Device
192  KineticStatus status = KineticClient_CreateSession(&cfg.config, cfg.client, &cfg.session);
193  if (status != KINETIC_STATUS_SUCCESS) {
194  fprintf(stderr, "Failed connecting to host %s:%d (status: %s)\n",
195  cfg.config.host, cfg.config.port,
197  return 1;
198  }
199 
200  // Establish an admin session with the Kinetic Device
201  cfg.adminConfig.useSsl = true;
202  status = KineticClient_CreateSession(&cfg.adminConfig, cfg.client, &cfg.adminSession);
203  if (status != KINETIC_STATUS_SUCCESS) {
204  fprintf(stderr, "Failed connecting to host %s:%d (status: %s)\n",
205  cfg.config.host, cfg.config.port,
207  return 1;
208  }
209 
210  // Execute the specified operation
211  // ReportConfiguration(cmd, &cfg);
212  status = ExecuteOperation(&cfg);
213  if (status != KINETIC_STATUS_SUCCESS) {
214  fprintf(stderr, "Failed executing operation!\n");
215  return 1;
216  }
217 
218  return 0;
219 }
220 
221 static void PrintEntry(KineticEntry * entry)
222 {
223  assert(entry);
224  entry->key.array.data[entry->key.bytesUsed] = '\0';
225  entry->value.array.data[entry->value.bytesUsed] = '\0';
226  printf(
227  "Kinetic Entry:\n"
228  " key: %s\n"
229  " value: %s\n",
230  (char*)entry->key.array.data,
231  (char*)entry->value.array.data);
232 }
233 
235 {
236  size_t i;
237  switch (type) {
238 
240  printf("Device Utilizations:\n");
241  for (i = 0; i < info->numUtilizations; i++) {
242  printf(" %s: %.2f %%\n",
243  info->utilizations[i].name,
244  info->utilizations[i].value * 100.0f);
245  }
246  break;
247 
249  printf("Device Capacities:\n");
250  printf(" nominalCapacity: %.3f MB\n", info->capacity->nominalCapacityInBytes / (1024.0f * 1024.0f));
251  printf(" portionFull: %.2f %%\n", info->capacity->portionFull * 100.0f);
252  break;
253 
255  printf("Device Temperatures:\n");
256  for (i = 0; i < info->numTemperatures; i++) {
257  printf(" %s: current=%.1f, min=%.1f, max=%.1f, target=%.1f\n",
258  info->temperatures[i].name,
259  info->temperatures[i].current, info->temperatures[i].minimum,
260  info->temperatures[i].maximum, info->temperatures[i].target);
261  }
262  break;
263 
265  printf("Device Configuration:\n");
266  printf(" vendor: %s\n", info->configuration->vendor);
267  printf(" model: %s\n", info->configuration->model);
268  printf(" serialNumber: %s\n", (char*)info->configuration->serialNumber.data);
269  printf(" worldWideName: %s\n", (char*)info->configuration->worldWideName.data);
270  printf(" version: %s\n", info->configuration->version);
271  printf(" compilationDate: %s\n", info->configuration->compilationDate);
272  printf(" sourceHash: %s\n", info->configuration->sourceHash);
273  printf(" protocolVersion: %s\n", info->configuration->protocolVersion);
274  printf(" protocolCompilationDate: %s\n", info->configuration->protocolCompilationDate);
275  printf(" protocolSourceHash: %s\n", info->configuration->protocolSourceHash);
276  for (i = 0; i < info->configuration->numInterfaces; i++) {
278  printf(" interface: %s\n", iface->name);
279  char buf[1024];
280  memset(buf, 0, sizeof(buf));
281  memcpy(buf, iface->MAC.data, iface->MAC.len);
282  printf(" MAC: %s\n", buf);
283  memset(buf, 0, sizeof(buf));
284  memcpy(buf, iface->ipv4Address.data, iface->ipv4Address.len);
285  printf(" ipv4Address: %s\n", buf);
286  memset(buf, 0, sizeof(buf));
287  memcpy(buf, iface->ipv6Address.data, iface->ipv6Address.len);
288  printf(" ipv6Address: %s\n", buf);
289  }
290  printf(" port: %d\n", info->configuration->port);
291  printf(" tlsPort: %d\n", info->configuration->tlsPort);
292  break;
293 
295  printf("Device Statistics:\n");
296  for (i = 0; i < info->numStatistics; i++) {
297  printf(" %s: count=%llu, bytes=%llu\n",
299  (long long)info->statistics[i].count,
300  (long long)info->statistics[i].bytes);
301  }
302  break;
303 
305  printf("Device Log Messages:\n"); {
306  char* msgs = calloc(1, info->messages.len + 1);
307  memcpy(msgs, info->messages.data, info->messages.len);
308  printf(" %s\n", msgs);
309  free(msgs);
310  }
311  break;
312 
314  printf("Device Limits:\n");
315  printf(" maxKeySize: %u\n", info->limits->maxKeySize);
316  printf(" maxValueSize: %u\n", info->limits->maxValueSize);
317  printf(" maxVersionSize: %u\n", info->limits->maxVersionSize);
318  printf(" maxTagSize: %u\n", info->limits->maxTagSize);
319  printf(" maxConnections: %u\n", info->limits->maxConnections);
320  printf(" maxOutstandingReadRequests: %u\n", info->limits->maxOutstandingReadRequests);
321  printf(" maxOutstandingWriteRequests: %u\n", info->limits->maxOutstandingWriteRequests);
322  printf(" maxMessageSize: %u\n", info->limits->maxMessageSize);
323  printf(" maxKeyRangeCount: %u\n", info->limits->maxKeyRangeCount);
324  printf(" maxIdentityCount: %u\n", info->limits->maxIdentityCount);
325  printf(" maxPinSize: %u\n", info->limits->maxPinSize);
326  break;
327 
328  default:
329  fprintf(stderr, "Unknown log type! (%d)\n", type);
330  break;
331  }
332 }
333 
334 static const char* GetOptString(OptionID opt_id)
335 {
336  char* str;
337  switch (opt_id) {
338  case OPT_HELP:
339  str = "help"; break;
340  case OPT_LOGLEVEL:
341  str = "loglevel"; break;
342  case OPT_HOST:
343  str = "host"; break;
344  case OPT_PORT:
345  str = "port"; break;
346  case OPT_TLSPORT:
347  str = "tlsport"; break;
348  case OPT_IDENTITY:
349  str = "identity"; break;
350  case OPT_KEY:
351  str = "key"; break;
352  case OPT_VALUE:
353  str = "value"; break;
354  case OPT_CLUSTERVERSION:
355  str = "clusterversion"; break;
356  case OPT_FILE:
357  str = "file"; break;
358  case OPT_HMACKEY:
359  str = "hmackey"; break;
361  str = "newclusterversion"; break;
362  case OPT_PIN:
363  str = "pin"; break;
364  case OPT_NEWPIN:
365  str = "newpin"; break;
366  case OPT_LOGTYPE:
367  str = "logtype"; break;
368  case OPT_NOOP:
369  str = "noop"; break;
370  case OPT_PUT:
371  str = "put"; break;
372  case OPT_GET:
373  str = "get"; break;
374  case OPT_DELETE:
375  str = "delete"; break;
376  case OPT_GETNEXT:
377  str = "getnext"; break;
378  case OPT_GETPREVIOUS:
379  str = "getprevious"; break;
380  case OPT_GETLOG:
381  str = "getlog"; break;
383  str = "getdevicespecificlog"; break;
384  case OPT_SETERASEPIN:
385  str = "seterasepin"; break;
386  case OPT_INSTANTERASE:
387  str = "instanterase"; break;
388  case OPT_SECUREERASE:
389  str = "secureerase"; break;
390  case OPT_SETLOCKPIN:
391  str = "setlockpin"; break;
392  case OPT_LOCKDEVICE:
393  str = "lockdevice"; break;
394  case OPT_UNLOCKDEVICE:
395  str = "unlockdevice"; break;
397  str = "setclusterversion"; break;
398  case OPT_SETACL:
399  str = "setacl"; break;
400  case OPT_UPDATEFIRMWARE:
401  str = "updatefirmware"; break;
402 
403  default:
404  str = "<UNKNOWN OPTION>"; break;
405  };
406  return str;
407 }
408 
409 
410 //------------------------------------------------------------------------------
411 // Private Method Definitions
412 
414  struct UtilConfig * cfg)
415 {
417  KineticLogInfo * logInfo;
418  ByteArray tmpArray;
419 
420  switch (cfg->opID) {
421 
422  case OPT_NOOP:
423  status = KineticClient_NoOp(cfg->session);
424  if (status == KINETIC_STATUS_SUCCESS) {
425  printf("NoOp operation completed successfully."
426  " Kinetic Device is alive and well!\n"); }
427  break;
428 
429  case OPT_PUT:
430  status = KineticClient_Put(cfg->session, &cfg->entry, NULL);
431  if (status == KINETIC_STATUS_SUCCESS) {
432  printf("Put operation completed successfully."
433  " Your data has been stored!\n");
434  PrintEntry(&cfg->entry);
435  }
436  break;
437 
438  case OPT_GET:
439  status = KineticClient_Get(cfg->session, &cfg->entry, NULL);
440  if (status == KINETIC_STATUS_SUCCESS) {
441  printf("Get executed successfully.\n");
442  PrintEntry(&cfg->entry);
443  }
444  break;
445 
446  case OPT_GETNEXT:
447  status = KineticClient_GetNext(cfg->session, &cfg->entry, NULL);
448  if (status == KINETIC_STATUS_SUCCESS) {
449  printf("GetNext executed successfully.\n");
450  PrintEntry(&cfg->entry);
451  }
452  break;
453 
454  case OPT_GETPREVIOUS:
455  status = KineticClient_GetPrevious(cfg->session, &cfg->entry, NULL);
456  if (status == KINETIC_STATUS_SUCCESS) {
457  printf("GetPrevious executed successfully.\n");
458  PrintEntry(&cfg->entry);
459  }
460  break;
461 
462  case OPT_DELETE:
463  status = KineticClient_Delete(cfg->session, &cfg->entry, NULL);
464  if (status == KINETIC_STATUS_SUCCESS) {
465  printf("Delete executed successfully. The entry has been destroyed!\n");
466  PrintEntry(&cfg->entry);
467  }
468  break;
469 
470  case OPT_GETLOG:
471  status = KineticAdminClient_GetLog(cfg->adminSession, cfg->logType, &logInfo, NULL);
472  if (status == KINETIC_STATUS_SUCCESS) {
473  printf("GetLog executed successfully.\n"
474  "The device log info has been retrieved!\n");
475  PrintLogInfo(cfg->logType, logInfo);
476  }
477  break;
478 
480  if (strlen(cfg->deviceLogName) == 0) {
481  fprintf(stderr, "Device-specific log type requires '--devicelogname' to be set!\n");
482  exit(1);
483  }
484  tmpArray.data = (uint8_t*)cfg->deviceLogName;
485  tmpArray.len = strlen(cfg->deviceLogName);
486  status = KineticAdminClient_GetDeviceSpecificLog(cfg->adminSession, tmpArray, &logInfo, NULL);
487  if (status == KINETIC_STATUS_SUCCESS) {
488  printf("GetDeviceSpecificLog executed successfully."
489  "The device-specific device log info has been retrieved!\n");
490  printf("Device-Specific Log Info:\n");
491  char* dev = calloc(1, logInfo->device->name.len + 1);
492  memcpy(dev, logInfo->device->name.data, logInfo->device->name.len);
493  printf(" %s\n", dev);
494  free(dev);
495  }
496  else if (status == KINETIC_STATUS_NOT_FOUND) {
497  fprintf(stderr, "The specified device-specific log '%s' was not found on the device!\n", cfg->deviceLogName);
498  status = KINETIC_STATUS_SUCCESS;
499  }
500  break;
501 
502  case OPT_SETERASEPIN:
503  status = KineticAdminClient_SetErasePin(cfg->adminSession,
504  ByteArray_Create(cfg->pin, strlen(cfg->pin)),
505  ByteArray_Create(cfg->newPin, strlen(cfg->newPin)));
506  if (status == KINETIC_STATUS_SUCCESS) {
507  printf("SetErasePin executed successfully.\n"
508  "The kinetic device erase pin has been changed!\n"); }
509  break;
510 
511  case OPT_INSTANTERASE:
512  status = KineticAdminClient_InstantErase(cfg->adminSession,
513  ByteArray_Create(cfg->pin, strlen(cfg->pin)));
514  if (status == KINETIC_STATUS_SUCCESS) {
515  printf("InstantErase executed successfully.\n"
516  "The kinetic device has been erased!\n"); }
517  break;
518 
519  case OPT_SECUREERASE:
520  status = KineticAdminClient_SecureErase(cfg->adminSession,
521  ByteArray_Create(cfg->pin, strlen(cfg->pin)));
522  if (status == KINETIC_STATUS_SUCCESS) {
523  printf("SecureErase executed successfully.\n"
524  "The kinetic device has been erased!\n"); }
525  break;
526 
527  case OPT_SETLOCKPIN:
528  status = KineticAdminClient_SetLockPin(cfg->adminSession,
529  ByteArray_Create(cfg->pin, strlen(cfg->pin)),
530  ByteArray_Create(cfg->newPin, strlen(cfg->newPin)));
531  if (status == KINETIC_STATUS_SUCCESS) {
532  printf("SetLockPin executed successfully.\n"
533  "The kinetic device lock/unlock pin has been changed!\n"); }
534  break;
535 
536  case OPT_LOCKDEVICE:
537  status = KineticAdminClient_LockDevice(cfg->adminSession,
538  ByteArray_Create(cfg->pin, strlen(cfg->pin)));
539  if (status == KINETIC_STATUS_SUCCESS) {
540  printf("LockDevice executed successfully.\n"
541  "The kinetic device is now locked!\n"); }
542  break;
543 
544  case OPT_UNLOCKDEVICE:
545  status = KineticAdminClient_UnlockDevice(cfg->adminSession,
546  ByteArray_Create(cfg->pin, strlen(cfg->pin)));
547  if (status == KINETIC_STATUS_SUCCESS) {
548  printf("UnlockDevice executed successfully.\n"
549  "The kinetic device is now unlocked!\n"); }
550  break;
551 
553  status = KineticAdminClient_SetClusterVersion(cfg->adminSession, cfg->newClusterVersion);
554  if (status == KINETIC_STATUS_SUCCESS) {
555  printf("SetClusterVersion executed successfully.\n"
556  "The kinetic device's cluster version has been updated!\n"); }
557  break;
558 
559  case OPT_SETACL:
560  status = KineticAdminClient_SetACL(cfg->adminSession, cfg->file);
561  if (status == KINETIC_STATUS_SUCCESS) {
562  printf("SetACL executed successfully.\n"
563  "The kinetic device ACLs have been replaced!\n"); }
564  break;
565 
566  case OPT_UPDATEFIRMWARE:
567  status = KineticAdminClient_UpdateFirmware(cfg->session, cfg->file);
568  if (status == KINETIC_STATUS_SUCCESS) {
569  printf("SecureErase executed successfully.\n"
570  "The kinetic device has been restored to empty status!\n"); }
571  break;
572 
573  default:
574  fprintf(stderr, "Specified operation '%d' is invalid!\n",
575  (int)cfg->opID);
576  exit(-1);
577  };
578 
579  // Print out status code description if operation was not successful
580  if (status != KINETIC_STATUS_SUCCESS) {
581  fprintf(stderr, "\nERROR: Operation '%s' failed with status '%s'\n",
582  GetOptString(cfg->opID), Kinetic_GetStatusDescription(status));
583  }
584 
585  return status;
586 }
587 
588 void ConfigureEntry(struct UtilConfig * cfg, const char* key, const char* tag,
589  const char* version, KineticAlgorithm algorithm, bool force, const char* value)
590 {
591  assert(cfg != NULL);
592 
593  // Setup to write some test data
594  cfg->entry = (KineticEntry) {
595  .key = ByteBuffer_CreateAndAppendCString(cfg->keyData, sizeof(cfg->keyData), key),
596  .tag = ByteBuffer_CreateAndAppendCString(cfg->tagData, sizeof(cfg->tagData), tag),
597  .newVersion = ByteBuffer_CreateAndAppendCString(cfg->newVersionData, sizeof(cfg->newVersionData), version),
598  .dbVersion = ByteBuffer_Create(cfg->versionData, sizeof(cfg->versionData), 0),
599  .algorithm = algorithm,
600  .value = ByteBuffer_CreateAndAppendCString(cfg->valueData, sizeof(cfg->valueData), value),
601  .force = force,
602  };
603 }
604 
606  const int argc,
607  char** const argv,
608  struct UtilConfig * cfg)
609 {
610  // Create an ArgP processor to parse arguments
611  struct {
612  OptionID opID;
613  int logLevel;
614  char host[HOST_NAME_MAX];
615  int port;
616  int tlsPort;
617  int64_t clusterVersion;
618  int64_t identity;
619  char hmacKey[KINETIC_MAX_KEY_LEN];
620  char logType[64];
621  char deviceLogName[64];
622  char key[64];
623  char version[64];
624  char tag[64];
625  KineticAlgorithm algorithm;
626  bool force;
627  char value[1024];
628  } opts = {
629  .logLevel = 0,
630  .host = "localhost",
631  .port = KINETIC_PORT,
632  .tlsPort = KINETIC_TLS_PORT,
633  .clusterVersion = 0,
634  .identity = 1,
635  .hmacKey = "asdfasdf",
636  .logType = "utilizations",
637  .key = "foo",
638  .tag = "SomeTagValue",
639  .algorithm = KINETIC_ALGORITHM_SHA1,
640  .force = true,
641  .value = "Hello!",
642  };
643 
644  // Create configuration for long format options
645  struct option long_options[] = {
646 
647  // Help
648  {"help", no_argument, 0, OPT_HELP},
649 
650  // Commands
651  {"noop", no_argument, 0, OPT_NOOP},
652  {"put", no_argument, 0, OPT_PUT},
653  {"get", no_argument, 0, OPT_GET},
654  {"delete", no_argument, 0, OPT_DELETE},
655  {"getnext", no_argument, 0, OPT_GETNEXT},
656  {"getprevious", no_argument, 0, OPT_GETPREVIOUS},
657  {"getlog", no_argument, 0, OPT_GETLOG},
658  {"getdevicespecificlog", no_argument, 0, OPT_GETDEVICESPECIFICLOG},
659  {"seterasepin", no_argument, 0, OPT_SETERASEPIN},
660  {"instanterase", no_argument, 0, OPT_INSTANTERASE},
661  {"secureerase", no_argument, 0, OPT_SECUREERASE},
662  {"setlockpin", no_argument, 0, OPT_SETLOCKPIN},
663  {"lockdevice", no_argument, 0, OPT_LOCKDEVICE},
664  {"unlockdevice", no_argument, 0, OPT_UNLOCKDEVICE},
665  {"setclusterversion", no_argument, 0, OPT_SETCLUSTERVERSION},
666  {"setacl", no_argument, 0, OPT_SETACL},
667  {"updatefirmware", no_argument, 0, OPT_UPDATEFIRMWARE},
668 
669  // Options
670  {"loglevel", required_argument, 0, OPT_LOGLEVEL},
671  {"host", required_argument, 0, OPT_HOST},
672  {"port", required_argument, 0, OPT_PORT},
673  {"tlsport", required_argument, 0, OPT_TLSPORT},
674  {"identity", required_argument, 0, OPT_IDENTITY},
675  {"hmackey", required_argument, 0, OPT_HMACKEY},
676  {"clusterversion", required_argument, 0, OPT_CLUSTERVERSION},
677  {"file", required_argument, 0, OPT_FILE},
678  {"newclusterversion", required_argument, 0, OPT_NEWCLUSTERVERSION},
679  {"pin", required_argument, 0, OPT_PIN},
680  {"newpin", required_argument, 0, OPT_NEWPIN},
681  {"logtype", required_argument, 0, OPT_LOGTYPE},
682  {"devicelogname", required_argument, 0, OPT_DEVICELOGNAME},
683  {"key", required_argument, 0, OPT_KEY},
684  {"value", required_argument, 0, OPT_VALUE},
685  {0, 0, 0, 0},
686  };
687 
688  // Parse the options from the command line
689  extern char *optarg;
690  extern int optind;
691  int option, optionIndex = 0;
692  while ((option = getopt_long(argc, argv, "?lhptics:", long_options, &optionIndex)) != -1) {
693  switch (option) {
694  case 0:
695  // If this option, just set the flag
696  if (long_options[optionIndex].flag != 0) {break;}
697  // assert(false);
698  // break;
699  case OPT_LOGLEVEL:
700  opts.logLevel = atoi(optarg);
701  break;
702  case OPT_HOST:
703  strncpy(opts.host, optarg, sizeof(opts.host));
704  break;
705  case OPT_PORT:
706  opts.port = atoi(optarg);
707  break;
708  case OPT_TLSPORT:
709  opts.tlsPort = atoi(optarg);
710  break;
711  case OPT_IDENTITY:
712  opts.identity = atoi(optarg);
713  break;
714  case OPT_HMACKEY:
715  strncpy(opts.hmacKey, optarg, sizeof(opts.hmacKey)-1);
716  break;
717  case OPT_KEY:
718  strncpy(opts.key, optarg, sizeof(opts.key)-1);
719  break;
720  case OPT_VALUE:
721  strncpy(opts.value, optarg, sizeof(opts.value)-1);
722  break;
723  case OPT_CLUSTERVERSION:
724  opts.clusterVersion = (int64_t)atol(optarg);
725  break;
727  cfg->newClusterVersion = (int64_t)atol(optarg);
728  break;
729  case OPT_FILE:
730  strncpy(cfg->file, optarg, sizeof(cfg->file)-1);
731  break;
732  case OPT_PIN:
733  strncpy(cfg->pin, optarg, sizeof(cfg->pin)-1);
734  break;
735  case OPT_NEWPIN:
736  strncpy(cfg->newPin, optarg, sizeof(cfg->newPin)-1);
737  break;
738  case OPT_LOGTYPE:
739  strncpy(opts.logType, optarg, sizeof(opts.logType)-1);
740  break;
741  case OPT_DEVICELOGNAME:
742  strncpy(cfg->deviceLogName, optarg, sizeof(cfg->deviceLogName)-1);
743  break;
744 
745  case OPT_NOOP:
746  case OPT_PUT:
747  case OPT_GET:
748  case OPT_DELETE:
749  case OPT_GETNEXT:
750  case OPT_GETPREVIOUS:
751  case OPT_GETLOG:
753  case OPT_SETERASEPIN:
754  case OPT_INSTANTERASE:
755  case OPT_SECUREERASE:
756  case OPT_SETLOCKPIN:
757  case OPT_LOCKDEVICE:
758  case OPT_UNLOCKDEVICE:
760  case OPT_SETACL:
761  case OPT_UPDATEFIRMWARE:
762  if ((int)opts.opID == 0) {
763  opts.opID = option;
764  break;
765  }
766  fprintf(stderr, "Multiple operations specified!\n");
767  PrintUsage(argv[0]);
768  exit(-1);
769  case OPT_HELP:
770  PrintUsage(argv[0]);
771  exit(0);
772  default:
773  PrintUsage(argv[0]);
774  exit(-1);
775  }
776  }
777 
778  // Configure client
779  cfg->logLevel = opts.logLevel;
780 
781  // Configure session
782  cfg->config = (KineticSessionConfig) {
783  .port = opts.port,
784  .clusterVersion = opts.clusterVersion,
785  .identity = opts.identity,
786  .hmacKey = ByteArray_Create(cfg->hmacKeyData, strlen(opts.hmacKey)),
787  };
788  memcpy(cfg->hmacKeyData, opts.hmacKey, strlen(opts.hmacKey));
789  strncpy(cfg->config.host, opts.host, sizeof(cfg->config.host)-1);
790 
791  // Configure admin session
792  cfg->adminConfig = cfg->config;
793  cfg->adminConfig.port = opts.tlsPort;
794  cfg->adminConfig.useSsl = true;
795 
796  // Populate and configure the entry to be used for operations
797  ConfigureEntry(cfg,
798  opts.key, opts.tag, opts.version, opts.algorithm, opts.force, opts.value);
799 
800  cfg->opID = opts.opID;
801 
802  // Parse log type from string
803  if (strcmp("utilizations", opts.logType) == 0) {
805  }
806  else if (strcmp("temperatures", opts.logType) == 0) {
808  }
809  else if (strcmp("capacities", opts.logType) == 0) {
811  }
812  else if (strcmp("configuration", opts.logType) == 0) {
814  }
815  else if (strcmp("statistics", opts.logType) == 0) {
817  }
818  else if (strcmp("messages", opts.logType) == 0) {
819  cfg->logType = KINETIC_DEVICE_INFO_TYPE_MESSAGES;
820  }
821  else if (strcmp("limits", opts.logType) == 0) {
822  cfg->logType = KINETIC_DEVICE_INFO_TYPE_LIMITS;
823  }
824  else {
825  fprintf(stderr, "Invalid log info type: %s\n", opts.logType);
826  exit(1);
827  }
828 
829  return optind;
830 }
Structure for handling generic arrays of bytes.
Definition: byte_array.h:34
void PrintUsage(const char *exec)
Definition: main.c:120
size_t numStatistics
static int ParseOptions(const int argc, char **const argv, struct UtilConfig *cfg)
Definition: main.c:605
Definition: main.c:40
Operation successful.
KineticStatus KineticClient_CreateSession(KineticSessionConfig *const config, KineticClient *const client, KineticSession **session)
Creates a session with the Kinetic Device per specified configuration.
KineticStatus KineticAdminClient_SetLockPin(KineticSession *const session, ByteArray old_pin, ByteArray new_pin)
Sets the lock PIN of the Kinetic Device.
size_t numTemperatures
Structure used to specify the configuration for a session.
KineticStatus KineticClient_GetPrevious(KineticSession *const session, KineticEntry *const entry, KineticCompletionClosure *closure)
Executes a GETPREVIOUS operation to retrieve the next entry from the Kinetic Device.
KineticStatus KineticAdminClient_UnlockDevice(KineticSession *const session, ByteArray pin)
Executes an UNLOCK operation to unlock the Kinetic device.
#define KINETIC_OBJ_SIZE
Max object/value size.
Definition: kinetic_types.h:47
KineticMessageType messageType
Definition: main.c:51
Definition: main.c:45
Definition: main.c:33
#define KINETIC_MAX_KEY_LEN
Max key length.
Definition: kinetic_types.h:46
Definition: main.c:53
uint32_t maxOutstandingWriteRequests
KineticLogInfo_Capacity * capacity
Log info network interface entry.
KineticStatus KineticClient_NoOp(KineticSession *const session)
Executes a NOOP operation to test whether the Kinetic Device is operational.
OptionID
Definition: main.c:27
KineticLogInfo_Configuration * configuration
KineticStatus KineticClient_Delete(KineticSession *const session, KineticEntry *const entry, KineticCompletionClosure *closure)
Executes a DELETE operation to delete an entry from the Kinetic Device.
KineticAlgorithm
Enumeration of encryption/checksum key algorithms.
Definition: kinetic_types.h:73
uint32_t maxOutstandingReadRequests
ByteArray array
ByteArray holding allocated array w/length = allocated size.
Definition: byte_array.h:54
KineticStatus KineticAdminClient_SetACL(KineticSession *const session, const char *ACLPath)
Executes a SECURITY operation, setting one or more ACLs.
KineticLogInfo_Limits * limits
KineticStatus KineticAdminClient_SetErasePin(KineticSession *const session, ByteArray old_pin, ByteArray new_pin)
Sets the erase PIN of the Kinetic Device.
Definition: main.c:38
Kinetic object instance.
ByteArray messages
const char * Kinetic_GetStatusDescription(KineticStatus status)
Provides a string representation for a KineticStatus code.
Definition: kinetic_types.c:67
KineticLogInfo_Type
Log info type.
The requested object does not exist.
ByteBuffer ByteBuffer_Create(void *data, size_t max_len, size_t used)
Definition: byte_array.c:68
Definition: main.c:69
Definition: main.c:34
Base log info structure which is allocated by client and passed to KineticAdminClient_GetLog.
KineticStatus KineticAdminClient_GetDeviceSpecificLog(KineticSession *const session, ByteArray name, KineticLogInfo **info, KineticCompletionClosure *closure)
Executes a GETLOG operation to retrieve device-specific log info from the Kinetic Device via name/key...
KineticLogInfo_Interface * interfaces
KineticLogInfo_Device * device
#define KINETIC_PORT
Default kinetic port.
Definition: kinetic_types.h:40
KineticStatus KineticAdminClient_InstantErase(KineticSession *const session, ByteArray pin)
Executes an InstantErase operation to erase all data from the Kinetic device.
KineticStatus KineticAdminClient_UpdateFirmware(KineticSession *const session, char const *const fw_path)
Executes a Firmware Download operation to update the firmware on the Kinetic device.
size_t len
Number of bytes in the data field.
Definition: byte_array.h:35
#define KINETIC_TLS_PORT
Default kinetic TLS port.
Definition: kinetic_types.h:41
KineticStatus KineticAdminClient_SecureErase(KineticSession *const session, ByteArray pin)
Executes a SecureErase command to erase all data from the Kinetic device.
KineticLogInfo_Utilization * utilizations
KineticLogInfo_Statistics * statistics
const char * logFile
Path to log file. Specify 'stdout' to log to STDOUT or NULL to disable logging.
KineticLogInfo_Temperature * temperatures
Definition: main.c:31
size_t numUtilizations
ByteBuffer key
Key associated with the object stored on disk.
uint8_t * data
Pointer to an allocated array of data bytes.
Definition: byte_array.h:36
const char * KineticMessageType_GetName(KineticMessageType type)
Provides a string representation for a Kinetic message type.
KineticStatus KineticAdminClient_LockDevice(KineticSession *const session, ByteArray pin)
Executes a LOCK operation to lock the Kinetic device.
Definition: main.c:52
static void PrintLogInfo(KineticLogInfo_Type type, KineticLogInfo *info)
Definition: main.c:234
Status not available (no reponse/status available)
#define HOST_NAME_MAX
Definition: kinetic_types.h:57
ByteArray ByteArray_Create(void *data, size_t len)
Definition: byte_array.c:31
static const char * GetOptString(OptionID opt_id)
Definition: main.c:334
KineticStatus KineticClient_Get(KineticSession *const session, KineticEntry *const entry, KineticCompletionClosure *closure)
Executes a GET operation to retrieve an entry from the Kinetic Device.
KineticStatus
Kinetic status codes.
Definition: main.c:28
KineticStatus KineticClient_Put(KineticSession *const session, KineticEntry *const entry, KineticCompletionClosure *closure)
Executes a PUT operation to store/update an entry on the Kinetic Device.
static void ConfigureEntry(struct UtilConfig *cfg, const char *key, const char *tag, const char *version, KineticAlgorithm algorithm, bool force, const char *value)
Definition: main.c:588
Configuration values for the KineticClient connection.
static KineticStatus ExecuteOperation(struct UtilConfig *cfg)
Definition: main.c:413
KineticClient * KineticClient_Init(KineticClientConfig *config)
Initializes the Kinetic API and configures logging.
size_t bytesUsed
Reflects the number of bytes used from the array
Definition: byte_array.h:55
KineticStatus KineticClient_GetNext(KineticSession *const session, KineticEntry *const entry, KineticCompletionClosure *closure)
Executes a GETNEXT operation to retrieve the next entry from the Kinetic Device.
Definition: main.c:37
static void PrintEntry(KineticEntry *entry)
Definition: main.c:221
int main(int argc, char **argv)
Definition: main.c:167
KineticStatus KineticAdminClient_SetClusterVersion(KineticSession *const session, int64_t version)
Updates the cluster version of the Kinetic Device.
ByteBuffer ByteBuffer_CreateAndAppendCString(void *data, size_t max_len, const char *value)
Definition: byte_array.c:97
KineticStatus KineticAdminClient_GetLog(KineticSession *const session, KineticLogInfo_Type type, KineticLogInfo **info, KineticCompletionClosure *closure)
Executes a GETLOG operation to retrieve specific configuration and/or operational data from the Kinet...
ByteBuffer value
Value data associated with the key.