- added pppoatm support
[opensuse:smpppd.git] / smpppd / connection.cc
1
2
3 /*
4  *  Author: Arvin Schnell <arvin@suse.de>
5  */
6
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <sys/stat.h>
12 #include <errno.h>
13 #include <glob.h>
14 #include <stddef.h>
15 #include <string.h>
16 #include <sys/ioctl.h>
17 #include <sys/socket.h>
18 #include <asm/types.h>
19 #include <net/if.h>
20 #include <linux/ppp_defs.h>
21 #include <linux/if_ppp.h>
22
23 #include <iostream>
24 #include <fstream>
25 #include <algorithm>
26
27 using std::cerr;
28
29 #include "link.h"
30 #include "main.h"
31 #include "modem.h"
32 #include "isdn.h"
33 #include "dsl.h"
34 #include "misc.h"
35 #include "utils.h"
36 #include "config.h"
37
38
39 PPPStat::PPPStat ()
40 {
41     fd = socket (AF_INET, SOCK_DGRAM, 0);
42     if (fd < 0) {
43         perror ("socket");
44         fd = -1;
45     }
46 }
47
48
49 PPPStat::~PPPStat ()
50 {
51     if (fd >= 0)
52         close (fd);
53 }
54
55
56 bool
57 PPPStat::get_stat (const char* ifname, long& rx_bytes, long& tx_bytes)
58 {
59     struct ifpppstatsreq req;
60     memset (&req, 0, sizeof (req));
61     req.stats_ptr = (caddr_t) &req.stats;
62     strncpy (req.ifr__name, ifname, sizeof (req.ifr__name));
63
64     if (ioctl (fd, SIOCGPPPSTATS, &req) < 0) {
65         perror ("ioctl(SIOCGPPPSTATS)");
66         return false;
67     }
68
69     rx_bytes = req.stats.p.ppp_ibytes;
70     tx_bytes = req.stats.p.ppp_obytes;
71     return true;
72 }
73
74
75 Connection::Connection ()
76     : ok (false)
77 {
78 #ifndef NDEBUG
79     cerr << __PRETTY_FUNCTION__ << '\n';
80 #endif
81
82     defaultroute = true;
83
84     demand = false;
85     idle_seconds = 0;
86     auto_dns = true;
87     dns1 = dns2 = "";
88
89     username = password = "";
90     ask_password = false;
91
92     rx_bytes = tx_bytes = 0;
93 }
94
95
96 Connection::~Connection ()
97 {
98 #ifndef NDEBUG
99     cerr << __PRETTY_FUNCTION__ << '\n';
100 #endif
101 }
102
103
104 bool
105 Connection::get_rxtx_bytes (long& rx_bytes, long& tx_bytes)
106 {
107     rx_bytes = Connection::rx_bytes;
108     tx_bytes = Connection::tx_bytes;
109     return true;
110 }
111
112
113 bool
114 Connection::read_rxtx_bytes (const char* ifname)
115 {
116     long old_rx_bytes = rx_bytes;
117     long old_tx_bytes = tx_bytes;
118
119     if (!pppstat.get_stat (ifname, rx_bytes, tx_bytes))
120         return false;
121
122 #ifndef NDEBUG
123     cout << "data total = " << rx_bytes << ' ' << tx_bytes << '\n';
124 #endif
125
126     // FIXME: this is hard to understand
127     if (rx_bytes != old_rx_bytes || tx_bytes != old_tx_bytes) {
128         clients.write_rxtx_bytes ();
129         once_equal = false;
130     } else {
131         if (!once_equal) {
132             clients.write_rxtx_bytes ();
133             once_equal = true;
134         }
135     }
136
137     return true;
138 }
139
140
141 Connection*
142 Connection::create (const Interface* inter, const Provider* prov)
143 {
144     Connection* conn = 0;
145
146     switch (inter->mode) {
147
148         case Interface::MODEM:
149             conn = new ::Modem;
150             break;
151
152         case Interface::ISDN:
153             conn = new ::ISDN;
154             break;
155
156         case Interface::DSL:
157             conn = new ::DSL;
158             break;
159
160     }
161
162     if (conn) {
163         conn->read_config (inter, prov);
164 #ifndef NDEBUG
165         conn->dump_config ();
166 #endif
167     }
168
169     return conn;
170 }
171
172
173 void
174 Connection::read_config (const Interface* inter, const Provider* prov)
175 {
176     for (int i = 0; i < 2; i++) {
177
178         const string filename = i == 0 ? inter->filename : prov->filename;
179
180         std::ifstream fin (filename.c_str ());
181         if (!fin) {
182             cerr << "error, can't open `" << filename << "' for reading: "
183                  << strerror (errno) << '\n';
184             return;
185         }
186
187         string line, key, value;
188
189         while (getline (fin, line)) {
190
191             int ret = getkeyvalue (line, key, value);
192
193             if (ret == 0)
194                 continue;
195
196             if (ret == -1) {
197                 cerr << "warning, syntax error in line `" << line << "'\n";
198                 continue;
199             }
200
201             eval_config (key, value);
202
203         }
204     }
205 }
206
207
208 void
209 Connection::eval_config (const string& key, const string& value)
210 {
211     if (key == "DEFAULTROUTE") {
212         defaultroute = value == "yes";
213         return;
214     }
215
216     if (key == "DEMAND") {
217         demand = value == "yes";
218         return;
219     }
220
221     if (key == "IDLETIME") {
222         idle_seconds = atoi (value.c_str ());
223         return;
224     }
225
226     if (key == "AUTODNS") {
227         auto_dns = value == "yes";
228         return;
229     }
230
231     if (key == "DNS1") {
232         dns1 = value;
233         return;
234     }
235
236     if (key == "DNS2") {
237         dns2 = value;
238         return;
239     }
240
241     if (key == "USERNAME") {
242         username = value;
243         return;
244     }
245
246     if (key == "PASSWORD") {
247         password = value;
248         return;
249     }
250
251     if (key == "ASKPASSWORD") {
252         ask_password = value == "yes";
253         return;
254     }
255 }
256
257
258 #ifndef NDEBUG
259 void
260 Connection::dump_config () const
261 {
262     cout << "defaultroute" << (defaultroute ? "yes" : "no") << '\n';
263     cout << "demand = " << (demand ? "yes" : "no") << '\n';
264     cout << "idle seconds = " << idle_seconds << '\n';
265     cout << "auto dns = " << (auto_dns ? "yes" : "no") << '\n';
266     cout << "dns = " << dns1 << ' ' << dns2 << '\n';
267     cout << "username = " << username << '\n';
268     cout << "password = " << password << '\n';
269     cout << "ask password = " << (ask_password ? "yes" : "no") << '\n';
270 }
271 #endif