PageRenderTime 52ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/wvdial-1.61/wvdialmon.cc

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