config.c 10.1 KB
Newer Older
1
2
3
4
/* Copyright 2001,2002 Roger Dingledine, Matej Pfajfar. */
/* See LICENSE for licensing information */
/* $Id$ */

Roger Dingledine's avatar
Roger Dingledine committed
5
6
7
8
9
10
11
12
/**
 * config.c 
 * Routines for loading the configuration file.
 *
 * Matej Pfajfar <mp292@cam.ac.uk>
 */

#include "or.h"
Nick Mathewson's avatar
Nick Mathewson committed
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <string.h>

const char * 
basename(const char *filename)
{
  char *result;
  /* XXX This won't work on windows. */
  result = strrchr(filename, '/');
  if (result)
    return result;
  else
    return filename;
}
Roger Dingledine's avatar
Roger Dingledine committed
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

/* loads the configuration file */
int getconfig(char *conf_filename, config_opt_t *options)
{
  FILE *cf = NULL;
  int retval = 0;
  
  if ((!conf_filename) || (!options))
    return -1;
  
  /* load config file */
  cf = open_config(conf_filename);
  if (!cf)
  {
    log(LOG_ERR,"Could not open configuration file %s.",conf_filename);
    return -1;
  }
  retval = parse_config(cf,options);
  if (retval)
    return -1;

  return 0;
}

50
51
int getoptions(int argc, char **argv, or_options_t *options)
/**
52

53
54
55
A replacement for getargs() and getconfig() which uses the <popt> library to parse
both command-line arguments and configuration files. A specific configuration file
may be specified using the --ConfigFile option. If one is not specified, then the
56
57
58
59
configuration files at /etc/<cmd>rc and ~/.<cmd>rc will be loaded in that order so
user preferences will override the ones specified in /etc.

The --ConfigFile (-f) option may only be used on the command-line. All other command-line
60
options may also be specified in configuration files. <popt> aliases are enabled
61
62
63
so a user can define their own options in the /etc/popt or ~/.popt files as outlined
in "man popt" pages.

64
65
66
67
68
69
70
RETURN VALUE: 0 on success, non-zero on error
**/
{
   char *ConfigFile;
   int Verbose;
   int code;
   poptContext optCon;
Roger Dingledine's avatar
Roger Dingledine committed
71
   const char *cmd;
72
73
   struct poptOption opt_tab[] =
   {
74
      { "APPort",          'a',  POPT_ARG_INT,     &options->APPort,
75
         0, "application proxy port",                          "<port>" },
76
      { "CoinWeight",      'w',  POPT_ARG_FLOAT,   &options->CoinWeight,
77
         0, "coin weight used in determining routes",          "<weight>" },
78
      { "ConfigFile",      'f',  POPT_ARG_STRING,  &ConfigFile,
79
         0, "user specified configuration file",               "<file>" },
80
      { "LogLevel",        'l',  POPT_ARG_STRING,  &options->LogLevel,
81
         0, "emerg|alert|crit|err|warning|notice|info|debug",  "<level>" },
82
      { "MaxConn",         'm',  POPT_ARG_INT,     &options->MaxConn,
83
         0, "maximum number of incoming connections",          "<max>" },
84
      { "OPPort",          'o',  POPT_ARG_INT,     &options->OPPort,
85
         0, "onion proxy port",                                "<port>" },
86
      { "ORPort",          'p',  POPT_ARG_INT,     &options->ORPort,
87
         0, "onion router port",                               "<port>" },
88
89
      { "DirPort",         'd',  POPT_ARG_INT,     &options->DirPort,
         0, "directory server port",                           "<port>" },
90
      { "PrivateKeyFile",  'k',  POPT_ARG_STRING,  &options->PrivateKeyFile,
91
         0, "maximum number of incoming connections",          "<file>" },
92
      { "RouterFile",      'r',  POPT_ARG_STRING,  &options->RouterFile,
93
         0, "local port on which the onion proxy is running",  "<file>" },
94
      { "TrafficShaping",  't',  POPT_ARG_INT,     &options->TrafficShaping,
95
         0, "which traffic shaping policy to use",             "<policy>" },
96
      { "LinkPadding",     'P',  POPT_ARG_INT,     &options->LinkPadding,
97
98
99
100
101
         0, "whether to use link padding",                     "<padding>" },
      { "DirRebuildPeriod",'D',  POPT_ARG_INT,     &options->DirRebuildPeriod,
         0, "how many seconds between directory rebuilds",     "<rebuildperiod>" },
      { "DirFetchPeriod",  'F',  POPT_ARG_INT,     &options->DirFetchPeriod,
         0, "how many seconds between directory fetches",     "<fetchperiod>" },
102
103
      { "KeepalivePeriod", 'K',  POPT_ARG_INT,     &options->KeepalivePeriod,
         0, "how many seconds between keepalives",            "<keepaliveperiod>" },
104
105
106
//      { "ReconnectPeriod", 'e',  POPT_ARG_INT,     &options->ReconnectPeriod,
//         0, "how many seconds between retrying all OR connections", "<reconnectperiod>" },
      { "Role",            'R',  POPT_ARG_INT,     &options->Role,
107
108
         0, "4-bit global role id",                            "<role>" },
      { "Verbose",         'v',  POPT_ARG_NONE,    &Verbose,
109
         0, "display options selected before execution",       NULL },
110
111
112
113
114
115
116
117
      POPT_AUTOHELP  /* handles --usage and --help automatically */
      POPT_TABLEEND  /* marks end of table */
   };
   cmd = basename(argv[0]);
   optCon = poptGetContext(cmd,argc,(const char **)argv,opt_tab,0);

   poptReadDefaultConfig(optCon,0);       /* read <popt> alias definitions */

118
119
120
   /* assign default option values */

   bzero(options,sizeof(or_options_t));
121
   options->LogLevel = "debug";
122
123
   options->loglevel = LOG_DEBUG;
   options->CoinWeight = 0.8;
124
   options->LinkPadding = 0;
125
126
   options->DirRebuildPeriod = 600;
   options->DirFetchPeriod = 6000;
127
   options->KeepalivePeriod = 300;
128
//   options->ReconnectPeriod = 6001;
Roger Dingledine's avatar
cleanup    
Roger Dingledine committed
129
   options->Role = ROLE_OR_LISTEN | ROLE_OR_CONNECT_ALL | ROLE_OP_LISTEN | ROLE_AP_LISTEN;
130
131

   code = poptGetNextOpt(optCon);         /* first we handle command-line args */
132
   if ( code == -1 )
133
   {
134
      if ( ConfigFile )                   /* handle user-specified config file */
135
136
137
         code = poptReadOptions(optCon,ConfigFile);
      else                                /* load Default configuration files */
         code = poptReadDefaultOptions(cmd,optCon);
138
139
   }

140
   switch(code)                           /* error checking */
141
   {
142
   case INT_MIN:
143
      log(LOG_ERR, "%s: Unable to open configuration file.\n", ConfigFile);
144
      break;
145
146
   case -1:
      code = 0;
147
      break;
148
   default:
Bruce Montrose's avatar
Bruce Montrose committed
149
      poptPrintUsage(optCon, stderr, 0);
150
      log(LOG_ERR, "%s: %s\n", poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(code));
151
      break;
152
153
154
155
   }

   poptFreeContext(optCon);

156
157
158
159
160
161
   if ( code ) return code;      /* return here if we encountered any problems */

   /* Display options upon user request */

   if ( Verbose )                      
   {
162
      printf("LogLevel=%s, Role=%d\n",
163
             options->LogLevel,
164
             options->Role);
165
166
167
      printf("RouterFile=%s, PrivateKeyFile=%s\n",
             options->RouterFile,
             options->PrivateKeyFile);
168
      printf("ORPort=%d, OPPort=%d, APPort=%d DirPort=%d\n",
169
             options->ORPort,options->OPPort,
170
             options->APPort,options->DirPort);
171
      printf("CoinWeight=%6.4f, MaxConn=%d, TrafficShaping=%d, LinkPadding=%d\n",
172
173
             options->CoinWeight,
             options->MaxConn,
174
175
             options->TrafficShaping,
             options->LinkPadding);
176
      printf("DirRebuildPeriod=%d, DirFetchPeriod=%d KeepalivePeriod=%d\n",
177
             options->DirRebuildPeriod,
178
179
             options->DirFetchPeriod,
             options->KeepalivePeriod);
180
181
   }

182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
   /* Validate options */

   if ( options->LogLevel )
   {
      if (!strcmp(options->LogLevel,"emerg"))
         options->loglevel = LOG_EMERG;
      else if (!strcmp(options->LogLevel,"alert"))
         options->loglevel = LOG_ALERT;
      else if (!strcmp(options->LogLevel,"crit"))
         options->loglevel = LOG_CRIT;
      else if (!strcmp(options->LogLevel,"err"))
         options->loglevel = LOG_ERR;
      else if (!strcmp(options->LogLevel,"warning"))
         options->loglevel = LOG_WARNING;
      else if (!strcmp(options->LogLevel,"notice"))
         options->loglevel = LOG_NOTICE;
      else if (!strcmp(options->LogLevel,"info"))
         options->loglevel = LOG_INFO;
      else if (!strcmp(options->LogLevel,"debug"))
         options->loglevel = LOG_DEBUG;
      else
      {
         log(LOG_ERR,"LogLevel must be one of emerg|alert|crit|err|warning|notice|info|debug.");
         code = -1;
      }
   }

209
   if ( options->Role < 0 || options->Role > 63 )
210
   {
211
      log(LOG_ERR,"Role option must be an integer between 0 and 63 (inclusive).");
212
213
214
      code = -1;
   }

215
216
217
218
219
220
   if ( options->RouterFile == NULL )
   {
      log(LOG_ERR,"RouterFile option required, but not found.");
      code = -1;
   }

221
   if ( ROLE_IS_OR(options->Role) && options->PrivateKeyFile == NULL )
222
   {
223
      log(LOG_ERR,"PrivateKeyFile option required for OR, but not found.");
224
225
226
      code = -1;
   }

227
   if ( (options->Role & ROLE_OR_LISTEN) && options->ORPort < 1 )
228
229
230
231
232
   {
      log(LOG_ERR,"ORPort option required and must be a positive integer value.");
      code = -1;
   }

233
   if ( (options->Role & ROLE_OP_LISTEN) && options->OPPort < 1 )
234
235
236
237
238
   {
      log(LOG_ERR,"OPPort option required and must be a positive integer value.");
      code = -1;
   }

239
   if ( (options->Role & ROLE_AP_LISTEN) && options->APPort < 1 )
240
241
242
243
244
   {
      log(LOG_ERR,"APPort option required and must be a positive integer value.");
      code = -1;
   }

245
246
247
248
249
250
   if ( (options->Role & ROLE_DIR_LISTEN) && options->DirPort < 1 )
   {
      log(LOG_ERR,"DirPort option required and must be a positive integer value.");
      code = -1;
   }

251
252
   if ( (options->Role & ROLE_AP_LISTEN) &&
        (options->CoinWeight < 0.0 || options->CoinWeight >= 1.0) )
253
   {
254
      log(LOG_ERR,"CoinWeight option must be a value from 0.0 upto 1.0, but not including 1.0.");
255
256
257
258
259
260
261
262
263
      code = -1;
   }

   if ( options->MaxConn <= 0 )
   {
      log(LOG_ERR,"MaxConn option must be a non-zero positive integer.");
      code = -1;
   }

264
265
266
267
268
269
   if ( options->MaxConn >= MAXCONNECTIONS )
   {
      log(LOG_ERR,"MaxConn option must be less than %d.", MAXCONNECTIONS);
      code = -1;
   }

270
271
272
273
274
275
   if ( options->TrafficShaping != 0 && options->TrafficShaping != 1 )
   {
      log(LOG_ERR,"TrafficShaping option must be either 0 or 1.");
      code = -1;
   }

276
277
278
279
280
281
   if ( options->LinkPadding != 0 && options->LinkPadding != 1 )
   {
      log(LOG_ERR,"LinkPadding option must be either 0 or 1.");
      code = -1;
   }

282
283
284
285
286
287
288
289
290
291
292
293
   if ( options->DirRebuildPeriod < 1)
   {
      log(LOG_ERR,"DirRebuildPeriod option must be positive.");
      code = -1;
   }

   if ( options->DirFetchPeriod < 1)
   {
      log(LOG_ERR,"DirFetchPeriod option must be positive.");
      code = -1;
   }

294
295
296
297
298
299
   if ( options->KeepalivePeriod < 1)
   {
      log(LOG_ERR,"KeepalivePeriod option must be positive.");
      code = -1;
   }

300
   return code;
301
302
}