- updated man pages
[opensuse:smpppd.git] / smpppd / frontend.cc
1
2
3 /*
4  *  Author: Arvin Schnell <arvin@suse.de>
5  */
6
7
8 #include <stdio.h>
9 #include <unistd.h>
10 #include <fcntl.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <errno.h>
14 #include <signal.h>
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <sys/wait.h>
18 #include <netinet/in.h>
19 #include <netdb.h>
20 #include <arpa/inet.h>
21
22 #include "../config.h"
23 #include "frontend.h"
24 #include "utils.h"
25 #include "config.h"
26 #include "log.h"
27
28
29 Socket::Socket (int fd, struct sockaddr_in clientname)
30     : Stream (fd),
31       clientname (clientname)
32 {
33 }
34
35
36 Socket::~Socket ()
37 {
38 }
39
40
41 Frontend::Frontend (int fd, struct sockaddr_in clientname)
42     : Socket (fd, clientname)
43 {
44     want_ifcfgs = false;
45
46     want_status = false;
47     want_providers = false;
48     want_config = false;
49     want_log = false;
50     want_rxtx_bytes = false;
51
52     survive_me = false;
53 }
54
55
56 void
57 Frontend::write_ifcfgs ()
58 {
59     write_line ("BEGIN LIST IFCFGS %zd", ifcfgs.size ());
60     for (Ifcfgs::const_iterator it = ifcfgs.begin (); it != ifcfgs.end (); it++) {
61         bool u = (*it)->backend;
62         write_line ("%c %s %s", u ? 'u' : 'd', qande ((*it)->ifcfg).c_str (),
63                     qande ((*it)->ifcfg_menu).c_str ());
64     }
65     write_line ("END LIST IFCFGS");
66 }
67
68
69 void
70 Frontend::write_status (const Ifcfg& ifcfg)
71 {
72     write_line ("BEGIN STATUS %s", ifcfg.ifcfg.c_str ());
73
74     write_line ("ifcfg-filename = %s", qande (ifcfg.ifcfg).c_str ());
75
76     const ConnectionConfig* c = ifcfg.config;
77     if (c) {
78         write_line ("config-ok = 1");
79         write_line ("provider-filename = %s", qande (c->get_provider_filename ()).c_str ());
80         write_line ("demand = %d", c->is_demand ());
81         write_line ("ask-password = %d", c->is_ask_password ());
82     } else {
83         write_line ("config-ok = 0");
84         write_line ("provider-filename = ");
85         write_line ("demand = 0");
86         write_line ("ask-password = 0");
87     }
88
89     const Backend* b = ifcfg.backend;
90     if (b) {
91         write_line ("status = %d", b->get_status ());
92         write_line ("action-flags = 0x%02x", b->get_action_flags ());
93         write_line ("max-channels = %d", b->get_max_channels ());
94         write_line ("num-channels = %d", b->get_num_channels ());
95         write_line ("debug = %d", b->get_debug ());
96     } else {
97         write_line ("status = 0");
98         write_line ("action-flags = 0x01");
99         write_line ("max-channels = 0");
100         write_line ("num-channels = 0");
101         write_line ("debug = 0");
102     }
103
104     write_line ("END STATUS");
105 }
106
107
108 void
109 Frontend::write_providers (const Ifcfg& ifcfg)
110 {
111     const int n = ifcfg.providerlist.size ();
112     write_line ("BEGIN LIST PROVIDERS %s %d", ifcfg.ifcfg.c_str (), n);
113     for (int i = 0; i < n; i++) {
114         bool a = ifcfg.config && ifcfg.config->get_provider_filename () ==
115             ifcfg.providerlist[i]->filename;
116         write_line ("%c %s %s", a ? 'a' : 'i', qande (ifcfg.providerlist[i]->filename).c_str (),
117                     qande (ifcfg.providerlist[i]->menuname).c_str ());
118     }
119     write_line ("END LIST PROVIDERS");
120 }
121
122
123 void
124 Frontend::write_rxtx_bytes (const Ifcfg& ifcfg)
125 {
126     bytes_t rx_bytes = 0;
127     bytes_t tx_bytes = 0;
128
129     if (ifcfg.backend) {
130         rx_bytes = ifcfg.backend->get_rx_bytes ();
131         tx_bytes = ifcfg.backend->get_tx_bytes ();
132     }
133
134     write_line ("BEGIN RXTX BYTES %s", ifcfg.ifcfg.c_str ());
135     write_line ("%llu %llu", rx_bytes, tx_bytes);
136     write_line ("END RXTX BYTES");
137 }
138
139
140 void
141 Frontend::write_config (const Ifcfg& ifcfg)
142 {
143     std::list <string> config;
144     if (ifcfg.config)
145         ifcfg.config->list_config (&config);
146     write_line ("BEGIN CONFIG %s", ifcfg.ifcfg.c_str ());
147     for (std::list <string>::const_iterator it = config.begin ();
148          it != config.end (); it++)
149         write_line ("%s", (*it).c_str ());
150     write_line ("END CONFIG");
151 }
152
153
154 void
155 Frontend::write_log (const Ifcfg& ifcfg)
156 {
157     write_line ("BEGIN LIST LOG %s %zd", ifcfg.ifcfg.c_str (), ifcfg.log.size ());
158     for (MyLog::const_iterator it = ifcfg.log.begin (); it != ifcfg.log.end (); it++)
159         write_line ("%s", (*it).c_str ());
160     write_line ("END LIST LOG");
161 }
162
163
164 void
165 Frontend::append_log (const Ifcfg& ifcfg, const char* text)
166 {
167     write_line ("BEGIN APPEND LOG %s 1", ifcfg.ifcfg.c_str ());
168     write_line ("%s", text);
169     write_line ("END APPEND LOG");
170 }
171
172
173 void
174 Frontend::handle_command (const string& command)
175 {
176     dprintf ("got command: <%s>\n", command.c_str ());
177
178     // authentication
179
180     if (strncmp ("response = ", command.c_str (), 11) == 0) {
181         string tmp = command;
182         tmp.erase (0, 11);
183         tmp = rmspaces (tmp);
184         if (!auth.check_response (config.password.c_str (), tmp.c_str ())) {
185             write_line ("error: failed to authenticated");
186             dprintf ("error, client failed to authenticated\n");
187             close_when_tx_buffer_empty = true; // FIXME: lock him forever
188             return;
189         }
190         authenticated = true;
191         write_line ("SuSE Meta pppd (smpppd), Version " VERSION);
192         return;
193     }
194
195     if (!authenticated) {
196         write_line ("error: failed to authenticated");
197         close_when_tx_buffer_empty = true;
198         return;
199     }
200
201     vector <string> args = parse (command);
202
203     // start, dialin, hangup and stop
204
205     if ((args.size () == 2 || args.size () == 3) && args[0] == "start") {
206         Ifcfg* tmp = ifcfgs.find (args[1]);
207         if (!tmp)
208             write_line ("error: unknown ifcfg");
209         else {
210             switch (args.size ())
211             {
212                 case 2:
213                     if (tmp->config->is_ask_password ())
214                         write_line ("error: password required");
215                     else {
216                         write_line ("ok");
217                         tmp->start ();
218                     }
219
220                 case 3:
221                     if (!tmp->config->is_ask_password ())
222                         write_line ("error: no password required");
223                     else {
224                         write_line ("ok");
225                         tmp->start (args[2]);
226                     }
227             }
228         }
229         return;
230     }
231
232     if (args.size () == 2 && args[0] == "dialin") {
233         Ifcfg* tmp = ifcfgs.find (args[1]);
234         if (!tmp)
235             write_line ("error: unknown ifcfg");
236         else {
237             write_line ("ok");
238             tmp->dialin ();
239         }
240         return;
241     }
242
243     if (args.size () == 2 && args[0] == "hangup") {
244         Ifcfg* tmp = ifcfgs.find (args[1]);
245         if (!tmp)
246             write_line ("error: unknown ifcfg");
247         else {
248             write_line ("ok");
249             tmp->hangup ();
250         }
251         return;
252     }
253
254     if (args.size () == 2 && args[0] == "stop") {
255         Ifcfg* tmp = ifcfgs.find (args[1]);
256         if (!tmp)
257             write_line ("error: unknown ifcfg");
258         else {
259             write_line ("ok");
260             tmp->stop ();
261         }
262         return;
263     }
264
265     if (args.size () == 3 && args[0] == "channels") {
266         Ifcfg* tmp = ifcfgs.find (args[1]);
267         if (!tmp)
268             write_line ("error: unknown ifcfg");
269         else {
270             write_line ("ok");
271             tmp->set_channels (atoi (args[2].c_str ()));
272         }
273         return;
274     }
275
276     // status
277
278     if (args.size () == 2 && args[0] == "list-status") {
279         Ifcfg* tmp = ifcfgs.find (args[1]);
280         if (!tmp)
281             write_line ("error: unknown ifcfg");
282         else {
283             write_line ("ok");
284             write_status (*tmp);
285         }
286         return;
287     }
288
289     if (args.size () == 2 && args[0] == "want-status") {
290         write_line ("ok");
291         want_status = args[1] == "1";
292         if (want_status)
293             for (Ifcfgs::const_iterator it = ifcfgs.begin ();
294                  it != ifcfgs.end (); it++)
295                 write_status (*(*it));
296         return;
297     }
298
299     // ifcfgs
300
301     if (command == "list-ifcfgs") {
302         write_line ("ok");
303         write_ifcfgs ();
304         return;
305     }
306
307     if (args.size () == 2 && args[0] == "want-ifcfgs") {
308         write_line ("ok");
309         want_ifcfgs = args[1] == "1";
310         if (want_ifcfgs)
311             for (Ifcfgs::const_iterator it = ifcfgs.begin ();
312                  it != ifcfgs.end (); it++)
313                 write_log (*(*it));
314         return;
315     }
316
317     // providers
318
319     if (args.size () == 2 && args[0] == "list-providers") {
320         Ifcfg* tmp = ifcfgs.find (args[1]);
321         if (!tmp)
322             write_line ("error: unknown ifcfg");
323         else {
324             write_line ("ok");
325             write_providers (*tmp);
326         }
327         return;
328     }
329
330     if (args.size () == 2 && args[0] == "want-providers") {
331         write_line ("ok");
332         want_providers = args[1] == "1";
333         if (want_providers)
334             for (Ifcfgs::const_iterator it = ifcfgs.begin ();
335                  it != ifcfgs.end (); it++)
336                 write_providers (*(*it));
337         return;
338     }
339
340     if (args.size () == 3 && args[0] == "select-provider") {
341         Ifcfg* tmp = ifcfgs.find (args[1]);
342         if (!tmp)
343             write_line ("error: unknown ifcfg");
344         else if (tmp->backend)
345             write_line ("error: backend is running");
346         else {
347             tmp->select_provider (args[2]);
348             write_line ("ok");
349         }
350         return;
351     }
352
353     // log
354
355     if (args.size () == 2 && args[0] == "list-log") {
356         Ifcfg* tmp = ifcfgs.find (args[1]);
357         if (!tmp)
358             write_line ("error: unknown ifcfg");
359         else {
360             write_line ("ok");
361             write_log (*tmp);
362         }
363         return;
364     }
365
366     if (args.size () == 2 && args[0] == "want-log") {
367         write_line ("ok");
368         want_log = args[1] == "1";
369         if (want_log)
370             for (Ifcfgs::const_iterator it = ifcfgs.begin ();
371                  it != ifcfgs.end (); it++)
372                 write_log (*(*it));
373         return;
374     }
375
376     // config
377
378     if (args.size () == 2 && args[0] == "list-config") {
379         Ifcfg* tmp = ifcfgs.find (args[1]);
380         if (!tmp) {
381             write_line ("error: unknown ifcfg");
382             return;
383         }
384         write_line ("ok");
385         write_config (*tmp);
386         return;
387     }
388
389     if (args.size () == 2 && args[0] == "want-config") {
390         write_line ("ok");
391         want_config = args[1] == "1";
392         if (want_config)
393             for (Ifcfgs::const_iterator it = ifcfgs.begin ();
394                  it != ifcfgs.end (); it++)
395                 write_config (*(*it));
396         return;
397     }
398
399     // rxtx bytes
400
401     if (args.size () == 2 && args[0] == "want-rxtx-bytes") {
402         write_line ("ok");
403         want_rxtx_bytes = args[1] == "1";
404         return;
405     }
406
407     // debug
408
409     if (args.size () == 2 && args[0] == "debug") {
410         write_line ("ok");
411         config.debug = args[1] == "1";
412         // FIXME: also change backends
413         return;
414     }
415
416     // misc
417
418     if (command == "ping") {
419         write_line ("pong");
420         return;
421     }
422
423     if (args.size () == 2 && args[0] == "lang") {
424         write_line ("ok");
425         return;
426     }
427
428     if (args.size () == 2 && args[0] == "survive-me") {
429         write_line ("ok");
430         survive_me = args[1] == "1";
431         return;
432     }
433
434     if (command == "quit") {
435         write_line ("ok");
436         close_when_tx_buffer_empty = true;
437         return;
438     }
439
440     write_line ("error: unknown command");
441 }
442
443
444 Frontends::~Frontends ()
445 {
446     for (const_iterator it = begin (); it != end (); it++)
447         delete (*it);
448 }
449
450
451 void
452 Frontends::write_ifcfgs ()
453 {
454     for (const_iterator it = begin (); it != end (); it++)
455         if ((*it)->want_ifcfgs)
456             (*it)->write_ifcfgs ();
457 }
458
459
460 void
461 Frontends::write_status (const Ifcfg& ifcfg)
462 {
463     for (const_iterator it = begin (); it != end (); it++)
464         if ((*it)->want_status)
465             (*it)->write_status (ifcfg);
466 }
467
468
469 void
470 Frontends::write_providers (const Ifcfg& ifcfg)
471 {
472     for (const_iterator it = begin (); it != end (); it++)
473         if ((*it)->want_providers)
474             (*it)->write_providers (ifcfg);
475 }
476
477
478 void
479 Frontends::write_rxtx_bytes (const Ifcfg& ifcfg)
480 {
481     for (const_iterator it = begin (); it != end (); it++)
482         if ((*it)->want_rxtx_bytes)
483             (*it)->write_rxtx_bytes (ifcfg);
484 }
485
486
487 void
488 Frontends::write_config (const Ifcfg& ifcfg)
489 {
490     for (const_iterator it = begin (); it != end (); it++)
491         if ((*it)->want_config)
492             (*it)->write_config (ifcfg);
493 }
494
495
496 void
497 Frontends::append_log (const Ifcfg& ifcfg, const char* text)
498 {
499     for (const_iterator it = begin (); it != end (); it++)
500         if ((*it)->want_log)
501             (*it)->append_log (ifcfg, text);
502 }
503
504
505 void
506 Frontends::prepare_select (fd_set* read_fd_set, fd_set* write_fd_set) const
507 {
508     for (const_iterator it = begin (); it != end (); it++)
509         (*it)->prepare_select (read_fd_set, write_fd_set);
510 }
511
512
513 void
514 Frontends::handle_select (fd_set* read_fd_set, fd_set* write_fd_set)
515 {
516     for (const_iterator it = begin (); it != end (); it++)
517         (*it)->handle_select (read_fd_set, write_fd_set);
518 }