acpi_cpu: do not apply P_LVLx_LAT rules to latencies returned by _CST
[dragonfly.git] / sbin / tcplay / main.c
1 /*
2  * Copyright (c) 2011 Alex Hornung <alex@alexhornung.com>.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
20  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
22  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/types.h>
31 #include <getopt.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <inttypes.h>
35 #include <errno.h>
36 #include <string.h>
37 #include <signal.h>
38 #include <time.h>
39
40 #include "tcplay.h"
41
42 #ifndef SIGINFO
43 #define SIGINFO SIGUSR1
44 #endif
45
46 static
47 void
48 sig_handler(int sig)
49 {
50         if ((sig == SIGUSR1 || sig == SIGINFO) && (summary_fn != NULL))
51                 summary_fn();
52 }
53
54 static
55 void
56 usage(void)
57 {
58         fprintf(stderr,
59             "usage: tcplay -c -d device [-g] [-a pbkdb_hash] [-b cipher]\n"
60             "              [-f keyfile_hidden] [-k keyfile] [-x pbkdf_hash] [-y cipher]\n"
61             "       tcplay -i -d device [-e] [-f keyfile_hidden] [-k keyfile]\n"
62             "              [-s system_devcie]\n"
63             "       tcplay -m mapping -d device [-e] [-f keyfile_hidden] [-k keyfile]\n"
64             "              [-s system_device]\n"
65             "       tcplay -h | -v\n"
66             "\n"
67             "Valid commands are:\n"
68             " -c, --create\n"
69             "\t Creates a new TC volume on the device specified by -d or --device.\n"
70             " -h, --help\n"
71             "\t Print help message and exit.\n"
72             " -i, --info\n"
73             "\t Gives information about the TC volume specified by -d or --device.\n"
74             " -m <mapping name>, --map=<mapping name>\n"
75             "\t Creates a dm-crypt mapping with the given name for the device\n"
76             "\t specified by -d or --device.\n"
77             " -v, --version\n"
78             "\t Print version message and exit.\n"
79             "\n"
80             "Valid options for --create are:\n"
81             " -a <pbkdf prf algorithm>, --pbkdf-prf=<pbkdf prf algorithm>\n"
82             "\t Specifies which hashing function to use for the PBKDF password\n"
83             "\t derivation when creating a new volume.\n"
84             "\t To see valid options, specify '-a help'.\n"
85             " -b <cipher>, --cipher=<cipher>\n"
86             "\t Specifies which cipher to use when creating a new TC volume.\n"
87             "\t To see valid options, specify '-b help'.\n"
88             " -g, --hidden\n"
89             "\t Specifies that the newly created volume will contain a hidden volume.\n"
90             " -x <pbkdf prf algorithm>, --pbkdf-prf=<pbkdf prf algorithm>\n"
91             "\t Specifies which hashing function to use for the PBKDF password\n"
92             "\t derivation when creating a new hidden volume.  By default, the\n"
93             "\t same as for the outer volume will be used.\n"
94             "\t To see valid options, specify '-x help'.\n"
95             " -y <cipher>, --cipher=<cipher>\n"
96             "\t Specifies which cipher to use when creating a new hidden volume.\n"
97             "\t By default, the same as for the outer volume will be used.\n"
98             "\t To see valid options, specify '-y help'.\n"
99             "\n"
100             "Valid options for --info and --map are:\n"
101             " -e, --protect-hidden\n"
102             "\t Protect a hidden volume when mounting the outer volume.\n"
103             " -s <disk path>, --system-encryption=<disk path>\n"
104             "\t Specifies that the disk (e.g. /dev/da0) is using system encryption.\n"
105             "\n"
106             "Valid options common to all commands are:\n"
107             " -d <device path>, --device=<device path>\n"
108             "\t Specifies the path to the volume to operate on (e.g. /dev/da0s1).\n"
109             " -f <key file>, --keyfile-hidden=<key file>\n"
110             "\t Specifies a key file to use for the hidden volume password derivation.\n"
111             "\t This option is only valid in combination with -e, --protect-hidden\n"
112             "\t or -g, --hidden.\n"
113             " -k <key file>, --keyfile=<key file>\n"
114             "\t Specifies a key file to use for the password derivation, can appear\n"
115             "\t multiple times.\n"
116             );
117
118         exit(1);
119 }
120
121 static struct option longopts[] = {
122         { "create",             no_argument,            NULL, 'c' },
123         { "cipher",             required_argument,      NULL, 'b' },
124         { "cipher-hidden",      required_argument,      NULL, 'y' },
125         { "hidden",             no_argument,            NULL, 'g' },
126         { "pbkdf-prf",          required_argument,      NULL, 'a' },
127         { "pbkdf-prf-hidden",   required_argument,      NULL, 'x' },
128         { "info",               no_argument,            NULL, 'i' },
129         { "map",                required_argument,      NULL, 'm' },
130         { "keyfile",            required_argument,      NULL, 'k' },
131         { "keyfile-hidden",     required_argument,      NULL, 'f' },
132         { "protect-hidden",     no_argument,            NULL, 'e' },
133         { "device",             required_argument,      NULL, 'd' },
134         { "system-encryption",  required_argument,      NULL, 's' },
135         { "version",            no_argument,            NULL, 'v' },
136         { "help",               no_argument,            NULL, 'h' },
137         { NULL,                 0,                      NULL, 0   },
138 };
139
140 int
141 main(int argc, char *argv[])
142 {
143         const char *dev = NULL, *sys_dev = NULL, *map_name = NULL;
144         const char *keyfiles[MAX_KEYFILES];
145         const char *h_keyfiles[MAX_KEYFILES];
146         int nkeyfiles;
147         int n_hkeyfiles;
148         int ch, error;
149         int sflag = 0, info_vol = 0, map_vol = 0, protect_hidden = 0,
150             create_vol = 0, contain_hidden = 0;
151         struct pbkdf_prf_algo *prf = NULL;
152         struct tc_cipher_chain *cipher_chain = NULL;
153         struct pbkdf_prf_algo *h_prf = NULL;
154         struct tc_cipher_chain *h_cipher_chain = NULL;
155
156         if ((error = tc_play_init()) != 0) {
157                 fprintf(stderr, "Initialization failed, exiting.");
158                 exit(1);
159         }
160
161         atexit(check_and_purge_safe_mem);
162         signal(SIGUSR1, sig_handler);
163         signal(SIGINFO, sig_handler);
164
165         nkeyfiles = 0;
166         n_hkeyfiles = 0;
167
168         while ((ch = getopt_long(argc, argv, "a:b:cd:ef:ghik:m:s:vx:y:",
169             longopts, NULL)) != -1) {
170                 switch(ch) {
171                 case 'a':
172                         if (prf != NULL)
173                                 usage();
174                         if ((prf = check_prf_algo(optarg, 0)) == NULL) {
175                                 if (strcmp(optarg, "help") == 0)
176                                         exit(0);
177                                 else
178                                         usage();
179                                 /* NOT REACHED */
180                         }
181                         break;
182                 case 'b':
183                         if (cipher_chain != NULL)
184                                 usage();
185                         if ((cipher_chain = check_cipher_chain(optarg, 0)) == NULL) {
186                                 if (strcmp(optarg, "help") == 0)
187                                         exit(0);
188                                 else
189                                         usage();
190                                 /* NOT REACHED */
191                         }
192                         break;
193                 case 'c':
194                         create_vol = 1;
195                         break;
196                 case 'd':
197                         dev = optarg;
198                         break;
199                 case 'e':
200                         protect_hidden = 1;
201                         break;
202                 case 'f':
203                         h_keyfiles[n_hkeyfiles++] = optarg;
204                         break;
205                 case 'g':
206                         contain_hidden = 1;
207                         break;
208                 case 'i':
209                         info_vol = 1;
210                         break;
211                 case 'k':
212                         keyfiles[nkeyfiles++] = optarg;
213                         break;
214                 case 'm':
215                         map_vol = 1;
216                         map_name = optarg;
217                         break;
218                 case 's':
219                         sflag = 1;
220                         sys_dev = optarg;
221                         break;
222                 case 'v':
223                         printf("tcplay v%d.%d\n", MAJ_VER, MIN_VER);
224                         exit(0);
225                         /* NOT REACHED */
226                 case 'x':
227                         if (h_prf != NULL)
228                                 usage();
229                         if ((h_prf = check_prf_algo(optarg, 0)) == NULL) {
230                                 if (strcmp(optarg, "help") == 0)
231                                         exit(0);
232                                 else
233                                         usage();
234                                 /* NOT REACHED */
235                         }
236                         break;
237                 case 'y':
238                         if (h_cipher_chain != NULL)
239                                 usage();
240                         if ((h_cipher_chain = check_cipher_chain(optarg, 0)) == NULL) {
241                                 if (strcmp(optarg, "help") == 0)
242                                         exit(0);
243                                 else
244                                         usage();
245                                 /* NOT REACHED */
246                         }
247                         break;
248                 case 'h':
249                 case '?':
250                 default:
251                         usage();
252                         /* NOT REACHED */
253                 }
254         }
255
256         argc -= optind;
257         argv += optind;
258
259         /* Check arguments */
260         if (!((map_vol || info_vol || create_vol) && dev != NULL) ||
261             (map_vol && info_vol) ||
262             (map_vol && create_vol) ||
263             (create_vol && info_vol) ||
264             (contain_hidden && !create_vol) ||
265             (sflag && (sys_dev == NULL)) ||
266             (map_vol && (map_name == NULL)) ||
267             (!(protect_hidden || create_vol) && n_hkeyfiles > 0)) {
268                 usage();
269                 /* NOT REACHED */
270         }
271
272         /* Create a new volume */
273         if (create_vol) {
274                 error = create_volume(dev, contain_hidden, keyfiles, nkeyfiles,
275                     h_keyfiles, n_hkeyfiles, prf, cipher_chain, h_prf,
276                     h_cipher_chain, NULL, NULL,
277                     0, 1 /* interactive */);
278                 if (error) {
279                         tc_log(1, "could not create new volume on %s\n", dev);
280                 }
281         } else if (info_vol) {
282                 error = info_volume(dev, sflag, sys_dev, protect_hidden,
283                     keyfiles, nkeyfiles, h_keyfiles, n_hkeyfiles, NULL, NULL,
284                     1 /* interactive */, DEFAULT_RETRIES, 0);
285         } else if (map_vol) {
286                 error = map_volume(map_name,
287                     dev, sflag, sys_dev, protect_hidden,
288                     keyfiles, nkeyfiles, h_keyfiles, n_hkeyfiles, NULL, NULL,
289                     1 /* interactive */, DEFAULT_RETRIES, 0);
290         }
291
292         return error;
293 }