~ubuntu-branches/ubuntu/quantal/wvdial/quantal

0.1.1 by Martin Pitt
Import upstream version 1.54.0
1
// copyright: (C) 2000 by SuSE GmbH
2
// author: arvin@suse.de
3
// WvStreamsified by Patrick Patterson (ppatters@nit.ca)
4
5
#include <stdio.h>
6
#include <stdlib.h>
7
#include <unistd.h>
8
#include <stdlib.h>
9
#include <errno.h>
10
#include <string.h>
11
#include <regex.h>
12
#include <netdb.h>
13
#include <net/route.h>
14
#include <sys/socket.h>
15
#include <sys/types.h>
16
#include <sys/stat.h>
17
#include <fcntl.h>
18
19
#include "wvdialmon.h"
20
21
22
23
WvDialMon::WvDialMon()
24
    : log( "WvDial", WvLog::Debug ),
25
      err( log.split( WvLog::Error ) ),
26
      buffer("")
27
{
28
    // executename = WvString( "" );
29
    connectmsg = WvString( "Connected... Press Ctrl-C to disconnect\n" );
30
    
31
    // usleep_time = 1000;
32
    do_check_dfr = 0;
33
    do_check_dns = 0;
34
    
35
    route_fd = (FILE *) 0;
36
    
37
    buffer.setsize(100);
38
    
39
    regcomp( &rx_status, "status *= *", REG_EXTENDED );
40
    regcomp( &rx_quote, "\\\"[^\\\"]+\\\"", REG_EXTENDED );
41
    regcomp( &rx_namesrv, "nameserver *[0-9]+.[0-9]+.[0-9]+.[0-9]+", REG_EXTENDED );
42
    
43
    reset();
44
}
45
46
47
48
WvDialMon::~WvDialMon()
49
{
50
    regfree( &rx_status );
51
    regfree( &rx_quote );
52
    regfree( &rx_namesrv );
53
}
54
55
56
void WvDialMon::setdnstests (WvString dnstest1, WvString dnstest2)
57
{
58
    WvDialMon::dnstest1 = dnstest1;
59
    WvDialMon::dnstest2 = dnstest2;
60
}
61
62
63
void WvDialMon::reset()
64
{
65
    _auth_failed = 0;
66
}
67
68
const int WvDialMon::auth_failed()
69
{
70
    return _auth_failed;
71
}
72
73
74
int WvDialMon::get_quotedtext(char *dest, const char *line)
75
{
76
    regmatch_t rm[1];
77
    
78
    if( regexec( &rx_quote, line, 1, &rm[0], 0 ) == REG_NOMATCH ) 
79
    {
80
	err("***** no quoted text found in `%s' *****\n", line );
81
	return 0;
82
    }
83
    
84
    int s = rm[0].rm_so, e = rm[0].rm_eo;
85
    strncpy (dest, &line[s], e-s);
86
    dest[e-s] = '\0';
87
    
88
    return 1;
89
}
90
91
char *WvDialMon::analyse_line(const char *line)
92
{
93
    regmatch_t rm[1];
94
    
95
    if (line == NULL )
96
        return NULL;
97
98
    // PAP stuff
99
    // 
100
    if (strstr(line, "AuthReq") != NULL)
101
	log("Authentication (PAP) started\n");
102
    
103
    if (strstr(line, "AuthAck") != NULL)
104
	log("Authentication (PAP) successful\n");
105
    
106
    if (strstr(line, "AuthNak") != NULL) {
107
	log("Authentication (PAP) failed");
108
	
109
	char buf[strlen(line)];
110
	if( get_quotedtext( buf, line ) )
111
	    log(" (Message: %s )\n", buf);
112
	
113
	_auth_failed = 1;
114
    }
115
    
116
    
117
    // CHAP stuff
118
    // 
119
    if (strstr(line, "CHAP Challenge") != NULL)
120
	log("Authentication (CHAP) started\n");
121
    
122
    if (strstr(line, "CHAP Success") != NULL)
123
	log("Authentication (CHAP) successful\n");
124
    
125
    if (strstr(line, "CHAP Failure") != NULL) {
126
	log("Authentication (CHAP) failed");
127
	
128
	char buf[strlen(line)];
129
	if( get_quotedtext( buf, line ) )
130
	    log(" (Message: %s )\n", buf);
131
	
132
	_auth_failed = 1;
133
    }
134
    
135
    
136
    // IP stuff
137
    // 
138
    if (!strncmp(line, "local  IP address", 17)     ||
139
	!strncmp(line, "remote IP address", 17)     ||
140
	!strncmp(line, "primary   DNS address", 20) ||
141
	!strncmp(line, "secondary DNS address", 20)   )
142
    {
143
	log("%s\n",line);
144
    }
145
    
146
    // Script stuff
147
    // 
148
    if (strncmp(line, "Script", 6) == 0) 
149
    {
150
	if (strstr(line, "/etc/ppp/ip-up") != NULL && strstr(line, "finished") != NULL) 
151
	{    
152
	    if( regexec( &rx_status, line, 1, &rm[0], 0 ) == 0 ) 
153
	    {
154
		const char *p = &line[ rm[0].rm_eo ];
155
		
156
		// err("***** status is `%s' *****\n", p2 );
157
158
		if (strcmp( p, "0x0") == 0) 
159
		{
160
		    
161
		    log("Script /etc/ppp/ip-up run successful\n");
162
		    
163
		    if( do_check_dfr ) 
164
		    {
165
			if( check_dfr() )
166
			    log( "Default route Ok.\n" );
167
			else
168
			    log( "Default route failure.\n" );
169
		    }
170
		    
171
		    if( do_check_dns ) 
172
		    {
173
			if( check_dns() )
174
			    log( "Nameserver (DNS) Ok.\n" );
175
			else
176
			    log( "Nameserver (DNS) failure, the connection may not work.\n" );
177
		    }
178
		    
179
		    log( "%s\n", connectmsg );
180
		    
181
		    //	  execute whatever the user wants to
182
		    //
183
		    //  	  if( executename.len() > 0 ) {
184
		    //
185
		    //  	    fflush(stdout);
186
		    //  	    fflush(stderr);
187
		    //
188
		    //  	    pid_t pid = fork();
189
		    //
190
		    //  	    if( pid == (pid_t) 0 ) { // we are the child
191
		    //
192
		    //  	      int devnullr = open("/dev/null",O_RDONLY,0);
193
		    //  	      dup2(devnullr, fileno(stdin));
194
		    //  	      close(devnullr);
195
		    //
196
		    //  	      int devnullw = open("/dev/null",O_WRONLY,0);
197
		    //  	      dup2(devnullw, fileno(stdout));
198
		    //  	      dup2(devnullw, fileno(stderr));
199
		    //  	      close(devnullw);
200
		    //  	      fflush(stdout);
201
		    //  	      fflush(stderr);
202
		    //
203
		    //  	      for( int tty = 3; tty < 256; tty++ )
204
		    //  		close(tty);
205
		    //
206
		    //  	      usleep( usleep_time );
207
		    //
208
		    //  	      // executename = Netscape -remote "reload()", macht probleme
209
		    //  	      // wenn mehrere netscapes auf dem xserver laufen (dann
210
		    //  	      // empfängt zufällig einer die message)
211
		    //
212
		    //  	      const char *new_argv[4];
213
		    //  	      new_argv[0] = "sh";
214
		    //  	      new_argv[1] = "-c";
215
		    //  	      new_argv[2] = executename;
216
		    //  	      new_argv[3] = NULL;
217
		    //
218
		    //  	      execv( "/bin/sh", (char *const *) new_argv );
219
		    //
220
		    //  	      fprintf( stderr, "exec failed: %s\n", strerror(errno) );
221
		    //  	    }
222
		    //
223
		    //	    if( pid < (pid_t) 0 ) // the fork failed
224
		    //	      fprintf( stderr, "error: can't fork child process\n" );
225
		    //	    else
226
		    //	      output( "Started `", executename, "' successfully\n" );
227
		    //
228
		    //	  }
229
		    
230
		} 
231
		else
232
		{
233
		    log("Script /etc/ppp/ip-up failed (return value: %s )\n", p);
234
		}
235
236
	    } 
237
	    else 
238
	    {
239
		// fprintf( stderr, "***** no status found *****\n" );
240
	    }
241
	    
242
	}
243
	
244
	if (strstr(line, "/etc/ppp/ip-down") != NULL && strstr(line, "started") != NULL)
245
	    log("Script /etc/ppp/ip-down started\n");
246
    }
247
    
248
    
249
    // TermReq stuff
250
    // 
251
    if (strstr(line, "LCP TermReq") != NULL) 
252
    {
253
	log("Terminate Request");
254
255
	char buf[strlen(line)];
256
	if( get_quotedtext( buf, line ) )
257
	    log(" (Message: %s )\n", buf);
258
    }
259
    
260
    
261
    // connect time stuff
262
    // 
263
    if (strncmp(line, "Connect time", 12) == 0)
264
	log("%s\n",line);
265
    
266
    
267
    // interface stuff
268
    // 
269
    if (strncmp(line, "Using interface", 15) == 0)
270
	log("%s\n", line);
271
    
272
    // terminate stuff
273
    // 
274
    if( strncmp(line,"Terminating", 11 ) == 0 )
275
	log("%s\n",line);
276
    
277
    
278
    return buffer.edit();
279
}
280
281
282
283
/********* taken from pppd ************/
284
285
#define KVERSION(j,n,p)	((j)*1000000 + (n)*1000 + (p))
286
287
#define SET_SA_FAMILY(addr, family)			\
288
	memset ((char *) &(addr), '\0', sizeof(addr));	\
289
    addr.sa_family = (family);
290
291
#define SIN_ADDR(x)	(((struct sockaddr_in *) (&(x)))->sin_addr.s_addr)
292
293
#define ROUTE_MAX_COLS	12
294
295
/********************************************************************
296
 *
297
 * close_route_table - close the interface to the route table
298
 */
299
300
void WvDialMon::close_route_table ()
301
{
302
    if (route_fd != (FILE *) 0) 
303
    {
304
	fclose (route_fd);
305
	route_fd = (FILE *) 0;
306
    }
307
}
308
309
/********************************************************************
310
 *
311
 * open_route_table - open the interface to the route table
312
 */
313
314
static char route_delims[] = " \t\n";
315
316
int WvDialMon::open_route_table ()
317
{
318
    char path[] = "/proc/net/route";
319
    
320
    close_route_table();
321
    
322
    route_fd = fopen (path, "r");
323
    if (route_fd == NULL) {
324
	log( "can't read %s\n", path );
325
	return 0;
326
    }
327
    
328
    route_dev_col = 0;		/* default to usual columns */
329
    route_dest_col = 1;
330
    route_gw_col = 2;
331
    route_flags_col = 3;
332
    route_mask_col = 7;
333
    route_num_cols = 8;
334
    
335
    /* parse header line */
336
    if (fgets(route_buffer, sizeof(route_buffer), route_fd) != 0) 
337
    {
338
	char *p = route_buffer, *q;
339
	int col;
340
	for (col = 0; col < ROUTE_MAX_COLS; ++col) 
341
	{
342
	    int used = 1;
343
	    if ((q = strtok(p, route_delims)) == 0)
344
		break;
345
	    if (strcasecmp(q, "iface") == 0)
346
		route_dev_col = col;
347
	    else if (strcasecmp(q, "destination") == 0)
348
		route_dest_col = col;
349
	    else if (strcasecmp(q, "gateway") == 0)
350
		route_gw_col = col;
351
	    else if (strcasecmp(q, "flags") == 0)
352
		route_flags_col = col;
353
	    else if (strcasecmp(q, "mask") == 0)
354
		route_mask_col = col;
355
	    else
356
		used = 0;
357
	    if (used && col >= route_num_cols)
358
		route_num_cols = col + 1;
359
	    p = NULL;
360
	}
361
    }
362
    
363
    return 1;
364
}
365
366
/********************************************************************
367
 *
368
 * read_route_table - read the next entry from the route table
369
 */
370
371
int WvDialMon::read_route_table(struct rtentry *rt)
372
{
373
    char *cols[ROUTE_MAX_COLS], *p;
374
    int col;
375
    
376
    memset (rt, '\0', sizeof (struct rtentry));
377
    
378
    if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
379
	return 0;
380
    
381
    p = route_buffer;
382
    for (col = 0; col < route_num_cols; ++col) {
383
	cols[col] = strtok(p, route_delims);
384
	if (cols[col] == NULL)
385
	    return 0;		/* didn't get enough columns */
386
	p = NULL;
387
    }
388
    
389
    SET_SA_FAMILY (rt->rt_dst,     AF_INET);
390
    SET_SA_FAMILY (rt->rt_gateway, AF_INET);
391
    
392
    SIN_ADDR(rt->rt_dst) = strtoul(cols[route_dest_col], NULL, 16);
393
    SIN_ADDR(rt->rt_gateway) = strtoul(cols[route_gw_col], NULL, 16);
394
    SIN_ADDR(rt->rt_genmask) = strtoul(cols[route_mask_col], NULL, 16);
395
    
396
    rt->rt_flags = (short) strtoul(cols[route_flags_col], NULL, 16);
397
    rt->rt_dev   = cols[route_dev_col];
398
    
399
    return 1;
400
}
401
402
/********************************************************************
403
 *
404
 * defaultroute_exists - determine if there is a default route
405
 */
406
407
int WvDialMon::defaultroute_exists (struct rtentry *rt)
408
{
409
    int result = 0;
410
    
411
    if (!open_route_table())
412
	return 0;
413
    
414
    while (read_route_table(rt) != 0) 
415
    {
416
	if ((rt->rt_flags & RTF_UP) == 0)
417
	    continue;
418
	
419
	if (kernel_version > KVERSION(2,1,0) && SIN_ADDR(rt->rt_genmask) != 0)
420
	    continue;
421
	if (SIN_ADDR(rt->rt_dst) == 0L) 
422
	{
423
	    result = 1;
424
	    break;
425
	}
426
    }
427
    
428
    close_route_table();
429
    return result;
430
}
431
432
int WvDialMon::check_dfr()
433
{
434
    struct rtentry def_rt;
435
    
436
    if( !defaultroute_exists( &def_rt ) )
437
	return 0;
438
    
439
    // FIXME: check if the gateway is set correct
440
    // 
441
    return 1;
442
}
443
444
int WvDialMon::check_dns_name( const char *name )
445
{
446
    struct hostent *hp;
447
    hp = gethostbyname( name );
448
    if( hp == NULL ) 
449
    {
450
	log( "warning, can't find address for `%s`\n", name );
451
	return 0;
452
    }
453
    
454
    // err("***** official name for `%s' is `%s' *****\n", name, hp->h_name );
455
    // 
456
    return 1;
457
}
458
459
int WvDialMon::check_dns()
460
{
461
  char name[] = "/etc/resolv.conf";
462
    
463
    FILE *fin = fopen( name, "r" );
464
    if( fin == NULL ) {
465
	log( "warning, can't read `%s`\n", name );
466
	return 0;
467
    }
468
    
469
    const int size = 100;
470
    char line[size];
471
    
472
    regmatch_t rm[1];
473
    int found_namesrv = 0;
474
    
475
    while( fgets( line, size, fin ) != NULL ) 
476
    {
477
	if( line[0] == '\n' || line[0] == '#' )
478
	    continue;
479
	
480
	if( line[ strlen(line)-1 ] == '\n' )
481
	    line[ strlen(line)-1 ] = '\0';
482
	
483
	if( regexec( &rx_namesrv, line, 1, &rm[0], 0 ) == 0 ) 
484
	{
485
	    found_namesrv = 1;
486
	    break;
487
	}
488
	
489
    }
490
    
491
    fclose( fin );
492
    
493
    if( !found_namesrv ) 
494
    {
495
	log( "warning, no nameserver found `%s`\n",name);
496
	return 0;
497
    }
498
    
499
    if (!check_dns_name ((const char* ) dnstest1) || !check_dns_name ((const char* ) dnstest2)) 
500
    {
501
	log( "warning, address lookup does not work\n" );
502
	return 0;
503
    }
504
    
505
    return 1;
506
}
507