Files: ae008179f033c8409c69b13787a539351bace626 / sslh-main.c
5109 bytesRaw
1 | /* |
2 | # main: processing of command line options and start the main loop. |
3 | # |
4 | # Copyright (C) 2007-2011 Yves Rutschle |
5 | # |
6 | # This program is free software; you can redistribute it |
7 | # and/or modify it under the terms of the GNU General Public |
8 | # License as published by the Free Software Foundation; either |
9 | # version 2 of the License, or (at your option) any later |
10 | # version. |
11 | # |
12 | # This program is distributed in the hope that it will be |
13 | # useful, but WITHOUT ANY WARRANTY; without even the implied |
14 | # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
15 | # PURPOSE. See the GNU General Public License for more |
16 | # details. |
17 | # |
18 | # The full text for the General Public License is here: |
19 | # http://www.gnu.org/licenses/gpl.html |
20 | |
21 | */ |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | const char* USAGE_STRING = |
45 | "sslh " VERSION "\n" \ |
46 | "usage:\n" \ |
47 | "\tsslh [-v] [-i] [-V] [-f] [-n]\n" |
48 | "\t[-t <timeout>] [-P <pidfile>] -u <username> -p <add> [-p <addr> ...] \n" \ |
49 | "%s\n\n" \ |
50 | "-v: verbose\n" \ |
51 | "-V: version\n" \ |
52 | "-f: foreground\n" \ |
53 | "-n: numeric output\n" \ |
54 | "-t: timeout before connecting to SSH.\n" \ |
55 | "-p: address and port to listen on.\n Can be used several times to bind to several addresses.\n" \ |
56 | "--[ssh,ssl,...]: where to connect connections from corresponding protocol.\n" \ |
57 | "-P: PID file. Default: /var/run/sslh.pid.\n" \ |
58 | "-i: Run as a inetd service.\n" \ |
59 | ""; |
60 | |
61 | void print_usage(void) |
62 | { |
63 | int i; |
64 | char *prots = ""; |
65 | |
66 | for (i = 0; i < num_known_protocols; i++) |
67 | asprintf(&prots, "%s\t[--%s <addr>]\n", prots, protocols[i].description); |
68 | |
69 | fprintf(stderr, USAGE_STRING, prots); |
70 | } |
71 | |
72 | void parse_cmdline(int argc, char* argv[]) |
73 | { |
74 | int c, affected = 0; |
75 | struct option const_options[] = { |
76 | { "inetd", no_argument, &inetd, 1 }, |
77 | { "foreground", no_argument, &foreground, 1 }, |
78 | { "verbose", no_argument, &verbose, 1 }, |
79 | { "numeric", no_argument, &numeric, 1 }, |
80 | { "user", required_argument, 0, 'u' }, |
81 | { "pidfile", required_argument, 0, 'P' }, |
82 | { "timeout", required_argument, 0, 't' }, |
83 | { "listen", required_argument, 0, 'p' }, |
84 | }; |
85 | struct option all_options[ARRAY_SIZE(const_options) + num_known_protocols + 1]; |
86 | struct addrinfo *addr, **a; |
87 | |
88 | memset(all_options, 0, sizeof(all_options)); |
89 | memcpy(all_options, const_options, sizeof(const_options)); |
90 | append_protocols(all_options, ARRAY_SIZE(const_options), protocols, num_known_protocols); |
91 | |
92 | while ((c = getopt_long_only(argc, argv, "t:T:p:VP:", all_options, NULL)) != -1) { |
93 | if (c == 0) continue; |
94 | |
95 | if (c >= PROT_SHIFT) { |
96 | affected++; |
97 | protocols[c - PROT_SHIFT].affected = 1; |
98 | resolve_name(&addr, optarg); |
99 | protocols[c - PROT_SHIFT].saddr= *addr; |
100 | continue; |
101 | } |
102 | |
103 | switch (c) { |
104 | |
105 | case 't': |
106 | probing_timeout = atoi(optarg); |
107 | break; |
108 | |
109 | case 'p': |
110 | /* find the end of the listen list */ |
111 | for (a = &addr_listen; *a; a = &((*a)->ai_next)); |
112 | /* append the specified addresses */ |
113 | resolve_name(a, optarg); |
114 | |
115 | break; |
116 | |
117 | case 'V': |
118 | printf("%s %s\n", server_type, VERSION); |
119 | exit(0); |
120 | |
121 | case 'u': |
122 | user_name = optarg; |
123 | break; |
124 | |
125 | case 'P': |
126 | pid_file = optarg; |
127 | break; |
128 | |
129 | default: |
130 | print_usage(); |
131 | exit(2); |
132 | } |
133 | } |
134 | |
135 | if (!affected) { |
136 | fprintf(stderr, "At least one target protocol must be specified.\n"); |
137 | exit(2); |
138 | } |
139 | |
140 | if (!addr_listen) { |
141 | fprintf(stderr, "No listening address specified; use at least one -p option\n"); |
142 | exit(1); |
143 | } |
144 | |
145 | } |
146 | |
147 | int main(int argc, char *argv[]) |
148 | { |
149 | |
150 | extern char *optarg; |
151 | extern int optind; |
152 | int res, num_addr_listen; |
153 | |
154 | int *listen_sockets; |
155 | |
156 | /* Init defaults */ |
157 | pid_file = "/var/run/sslh.pid"; |
158 | user_name = "nobody"; |
159 | foreground = 0; |
160 | |
161 | parse_cmdline(argc, argv); |
162 | |
163 | if (inetd) |
164 | { |
165 | verbose = 0; |
166 | start_shoveler(0); |
167 | exit(0); |
168 | } |
169 | |
170 | if (verbose) |
171 | printsettings(); |
172 | |
173 | num_addr_listen = start_listen_sockets(&listen_sockets, addr_listen); |
174 | |
175 | if (!foreground) |
176 | if (fork() > 0) exit(0); /* Detach */ |
177 | |
178 | setup_signals(); |
179 | |
180 | drop_privileges(user_name); |
181 | |
182 | /* New session -- become group leader */ |
183 | if (getuid() == 0) { |
184 | res = setsid(); |
185 | CHECK_RES_DIE(res, "setsid: already process leader"); |
186 | } |
187 | |
188 | write_pid_file(pid_file); |
189 | |
190 | /* Open syslog connection */ |
191 | setup_syslog(argv[0]); |
192 | |
193 | main_loop(listen_sockets, num_addr_listen); |
194 | |
195 | return 0; |
196 | } |
197 |
Built with git-ssb-web