PageRenderTime 24ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/release_2_18/dnrd/src/args.c

#
C | 351 lines | 279 code | 26 blank | 46 comment | 22 complexity | fbafdf733cc022ebb86a1f4bac4cfeb2 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * args.c - data and functions dealing with command-line argument processing.
  3. *
  4. * Copyright (C) 1998 Brad M. Garcia <garsh@home.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. */
  20. #include <stdarg.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <unistd.h>
  24. #if defined(__GNU_LIBRARY__)
  25. # include <getopt.h>
  26. #endif
  27. #include <sys/socket.h>
  28. #include <netinet/in.h>
  29. #include <arpa/inet.h>
  30. #include <string.h>
  31. #include <pwd.h>
  32. #include "args.h"
  33. #include "common.h"
  34. #include "lib.h"
  35. #include "cache.h"
  36. /*
  37. * Definitions for both long and short forms of our options.
  38. * See man page for getopt for more details.
  39. */
  40. #if defined(__GNU_LIBRARY__)
  41. static struct option long_options[] =
  42. {
  43. {"address", 1, 0, 'a'},
  44. {"load-balance", 0, 0, 'b'},
  45. {"cache", 1, 0, 'c'},
  46. {"debug", 0, 0, 'd'},
  47. {"help", 0, 0, 'h'},
  48. {"ignore", 0, 0, 'i'},
  49. #ifdef ENABLE_PIDFILE
  50. {"kill", 0, 0, 'k'},
  51. #endif
  52. {"log", 0, 0, 'l'},
  53. {"max-sock", 1, 0, 'M'},
  54. #ifndef EXCLUDE_MASTER
  55. {"master", 1, 0, 'm'},
  56. #endif
  57. {"retry", 1, 0, 'r'},
  58. {"server", 1, 0, 's'},
  59. {"timeout", 1, 0, 't'},
  60. {"uid", 1, 0, 'u'},
  61. {"version", 0, 0, 'v'},
  62. {"dnrd-root", 1, 0, 'R'},
  63. {0, 0, 0, 0}
  64. };
  65. #endif /* __GNU_LIBRARY__ */
  66. #ifndef EXCLUDE_MASTER
  67. #define MASTERPARM "m:"
  68. #else
  69. #define MASTERPARM
  70. #endif
  71. #ifdef ENABLE_PIDFILE
  72. #define PIDPARM "k"
  73. #else
  74. #define PIDPARM
  75. #endif
  76. const char short_options[] = "a:bc:dhi" PIDPARM "l" MASTERPARM "M:r:R:s:t:u:v";
  77. /*
  78. * give_help()
  79. *
  80. * Abstract: Prints out the version number and a usage statement.
  81. */
  82. static void give_help()
  83. {
  84. printf("dnrd version %s\n", version);
  85. printf("\nusage: %s [options]\n", progname);
  86. printf(" Valid options are\n");
  87. printf(
  88. #ifdef __GNU_LIBRARY__
  89. " -a, --address=LOCALADDRESS\n"
  90. " Only bind to the port on the given address,\n"
  91. " rather than all local addresses\n"
  92. " -b, --load-balance Round-Robin load balance forwarding servers\n"
  93. " -c, --cache=off|[LOW:]HIGH\n"
  94. " Turn off cache or tune the low/high water marks\n"
  95. " -d, --debug Turn on debugging - run in foreground.\n"
  96. " -h, --help Print this message, then exit.\n"
  97. " -i, --ignore Ignore cache for disabled servers\n"
  98. #ifdef ENABLE_PIDFILE
  99. " -k, --kill Kill a running daemon.\n"
  100. #endif
  101. " -l, --log Send all messages to syslog.\n"
  102. #ifndef EXCLUDE_MASTER
  103. " -m, --master=off|hosts Turn off master or use /etc/hosts file\n"
  104. #endif
  105. " -M, --max-sock=N Set maximum number of open sockets to N\n"
  106. " -r, --retry=N Set retry interval to N seconds\n"
  107. " -s, --server=IPADDR(:domain)\n"
  108. " Set the DNS server. You can specify an\n"
  109. " optional domain name, in which case a DNS\n"
  110. " request will only be sent to that server for\n"
  111. " names in that domain.\n"
  112. " (Can be used more than once for multiple or\n"
  113. " backup servers)\n"
  114. " -t, --timeout=N Set forward DNS server timeout to N\n"
  115. " -u, --uid=ID Username or numeric id to switch to\n"
  116. " -R, --dnrd-root=DIR The dnrd root directory. dnrd will chroot to\n"
  117. " this dir.\n"
  118. " -v, --version Print out the version number and exit.\n"
  119. #else /* __GNU_LIBRARY__ */
  120. " -a IPADDR Only bind to the port on the given address, rather than all\n"
  121. " local addresses\n"
  122. " -b Round-Robin load balance forwarding servers\n"
  123. " -c off|[LOW:]HIGH\n"
  124. " Turn off caching or tune the low/high water marks"
  125. " -d Turn on debugging - run in foreground.\n"
  126. " -h Print this message, then exit.\n"
  127. " -i Ignore cache for disabled servers\n"
  128. #ifdef ENABLE_PIDFILE
  129. " -k Kill a running daemon.\n"
  130. #endif
  131. " -l Send all messages to syslog.\n"
  132. #ifndef EXCLUDE_MASTER
  133. " -m off|hosts\n"
  134. " Turn off master or use /etc/hosts file\n"
  135. #endif
  136. " -M N Set maximum number of open sockets to N\n"
  137. " -r N Set retry interval to N seconds\n"
  138. " -s IPADDR(:domain)\n"
  139. " Set the DNS server. You can specify an optional domain name,\n"
  140. " in which case a DNS request will only be sent to that server\n"
  141. " for names in that domain. (Can be used more than once for\n"
  142. " multiple or backup servers)\n"
  143. " -t N Set forward DNS server timeout to N\n"
  144. " -u ID Username or numeric id to switch to\n"
  145. " -R DIR The dnrd root directory. dnrd will chroot to this dir.\n"
  146. " -v Print out the version number and exit.\n"
  147. #endif /* __GNU_LIBRARY__ */
  148. "\n");
  149. }
  150. /*
  151. * parse_args()
  152. *
  153. * In: argc - number of command-line arguments.
  154. * argv - string array containing command-line arguments.
  155. *
  156. * Returns: an index into argv where we stopped parsing arguments.
  157. *
  158. * Abstract: Parses command-line arguments. In some cases, it will
  159. * set the appropriate global variables and return. Otherwise,
  160. * it performs the appropriate action and exits.
  161. *
  162. * Assumptions: Currently, we check to make sure that there are no arguments
  163. * other than the defined options, so the return value is
  164. * pretty useless and should be ignored.
  165. */
  166. int parse_args(int argc, char **argv)
  167. {
  168. static int load_balance = 0;
  169. int c;
  170. /* int gotdomain = 0;*/
  171. progname = strrchr(argv[0], '/');
  172. if (!progname) progname = argv[0];
  173. while(1) {
  174. #if defined(__GNU_LIBRARY__)
  175. c = getopt_long(argc, argv, short_options, long_options, 0);
  176. #else
  177. c = getopt(argc, argv, short_options);
  178. #endif
  179. if (c == -1) break;
  180. switch(c) {
  181. case 'a': {
  182. if (!inet_aton(optarg, &recv_addr.sin_addr)) {
  183. log_msg(LOG_ERR, "%s: Bad ip address \"%s\"\n",
  184. progname, optarg);
  185. exit(-1);
  186. }
  187. break;
  188. }
  189. case 'b': {
  190. load_balance = 1;
  191. break;
  192. }
  193. case 'c': {
  194. copy_string(cache_param, optarg, sizeof(cache_param));
  195. break;
  196. }
  197. case 'd': {
  198. opt_debug++;
  199. break;
  200. }
  201. case 'h': {
  202. give_help();
  203. exit(0);
  204. break;
  205. }
  206. case 'i' : {
  207. ignore_inactive_cache_hits = 1;
  208. break;
  209. }
  210. #ifdef ENABLE_PIDFILE
  211. case 'k': {
  212. if (!kill_current()) {
  213. printf("No %s daemon found. Exiting.\n", progname);
  214. }
  215. exit(0);
  216. break;
  217. }
  218. #endif
  219. case 'l': {
  220. gotterminal = 0;
  221. break;
  222. }
  223. #ifndef EXCLUDE_MASTER
  224. case 'm': {
  225. copy_string(master_param, optarg, sizeof(master_param));
  226. break;
  227. }
  228. #endif
  229. case 'M': {
  230. max_sockets = atoi(optarg);
  231. log_debug(1, "Setting maximum number of open sockets to %i",
  232. max_sockets);
  233. break;
  234. }
  235. case 'r': {
  236. if ((reactivate_interval = atoi(optarg)))
  237. log_debug(1, "Setting retry interval to %i seconds.",
  238. reactivate_interval);
  239. else
  240. log_debug(1, "Retry=0. Will never deactivate servers.");
  241. break;
  242. }
  243. case 's': {
  244. domnode_t *p;
  245. char *s,*sep = strchr(optarg, (int)':');
  246. if (sep) { /* is a domain specified? */
  247. s = make_cname(strnlwr(sep+1,200),200);
  248. *sep = 0;
  249. if ( (p=search_domnode(domain_list, s)) == NULL) {
  250. p=add_domain(domain_list, load_balance, s, 200);
  251. log_debug(1, "Added domain %s %s load balancing", sep+1,
  252. load_balance ? "with" : "without");
  253. } else {
  254. free(s);
  255. }
  256. } else p=domain_list;
  257. if (!add_srv(last_srvnode(p->srvlist), optarg)) {
  258. log_msg(LOG_ERR, "%s: Bad ip address \"%s\"\n",
  259. progname, optarg);
  260. exit(-1);
  261. } else {
  262. log_debug(1, "Server %s added to domain %s", optarg,
  263. sep ? sep+1:"(default)");
  264. }
  265. if (p->roundrobin != load_balance) {
  266. p->roundrobin =load_balance;
  267. log_debug(1, "Turned on load balancing for domain %s",
  268. cname2asc(p->domain));
  269. }
  270. if (sep) *sep = ':';
  271. break;
  272. }
  273. case 't': {
  274. if ((forward_timeout = atoi(optarg)))
  275. log_debug(1, "Setting timeout value to %i seconds.",
  276. forward_timeout);
  277. else
  278. log_debug(1, "Timeout=0. Servers will never timeout.");
  279. break;
  280. }
  281. case 'u': {
  282. char *ep;
  283. struct passwd *pwent;
  284. daemonuid = (uid_t)strtoul(optarg, &ep, 10);
  285. pwent = *ep ? getpwnam(optarg) : getpwuid(daemonuid);
  286. if (!pwent) {
  287. log_msg(LOG_ERR, "%s: Bad uid \"%s\"\n", progname, optarg);
  288. exit(-1);
  289. }
  290. daemonuid = pwent->pw_uid;
  291. daemongid = pwent->pw_gid;
  292. break;
  293. }
  294. case 'v': {
  295. printf("dnrd version %s\n\n", version);
  296. exit(0);
  297. break;
  298. }
  299. case 'p': {
  300. strncpy(dnrd_root, optarg, sizeof(dnrd_root));
  301. log_debug(1, "Using %s as chroot");
  302. break;
  303. }
  304. case ':': {
  305. log_msg(LOG_ERR, "%s: Missing parameter for \"%s\"\n",
  306. progname, argv[optind]);
  307. exit(-1);
  308. break;
  309. }
  310. case '?':
  311. default: {
  312. /* getopt_long will print "unrecognized option" for us */
  313. give_help();
  314. exit(-1);
  315. break;
  316. }
  317. }
  318. }
  319. if (optind != argc) {
  320. log_msg(LOG_ERR, "%s: Unknown parameter \"%s\"\n",
  321. progname, argv[optind]);
  322. exit(-1);
  323. }
  324. return optind;
  325. }