Monday, April 2, 2012

Collect [line] stats from SpeedTouch 510 ADSL modem

Collect [line] stats from SpeedTouch 510 ADSL modem

#include <stdio.h>
#include <unistd.h>
#include <error.h>
#include <errno.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <regex.h>
#include <locale.h>

#define MAXLINE         1024

static int alarm_flag = 0;
static struct sigaction act1, oact1;

int input_timeout(int, unsigned int);
int readline(int, char *, size_t);
int mkconnectsock(char *, int, int);
void alarm_function(int);
void isip4addr(char *);

int main(int argc, char *argv[]) {
 FILE *fpout = {0};
 char line[MAXLINE];
 char c;
 char *ptr = NULL;
 char *ipaddr = "10.0.0.138";
 char *comtab[2] = { "adsl info", "exit" };
 int comtabsize = 2;
 int ipport = 23;
 int conntimeout = 10;
 int sockid, bread;
 int i, state;

 i = state = 0;

 /* this is a quick hack.. Not a program...! */
 if(argc == 1)
  error(1, 0, "Usage: %s ip4address", "adslinfo");
 else {
  isip4addr(argv[1]);
  ipaddr = argv[1];
 }

 /* connect & setup write descrip. */
 sockid = mkconnectsock(ipaddr, ipport, conntimeout);
 if((fpout = fdopen(sockid, "w")) == NULL)
  error(1, 0, "Error - fdopen()");

 /* skipping the first [telnet] connection block.. */
 /*         SOH         ETX         SOH         ETX */
 /* 377 373 001 377 373 003 377 373 001 377 373 003 */
 for(i = 0; i < 12; i++)
  if((bread = recv(sockid, &c, 1, 0)) == -1)
   error(1, 0, "Error - recv(): first 12 bytes");

 /* w're not event driven.. */
 fprintf(fpout, "%s", "\r\f"), fflush(fpout);
 fprintf(fpout, "%s", "\r\f"), fflush(fpout);

 /* issue commands */
 for(i = 0; i < comtabsize; i++) {
  fprintf(fpout, "%s\r\f", comtab[i]), fflush(fpout);

  while(readline(sockid, line, sizeof(line)) > 0) {
   if(line[0] == '=' && line[1] == '>')
    break;
   if(line[0] == 'M' && line[1] == 'o')
    state = 1;

   if(state == 1)
    for(ptr = line; *ptr; ptr++)
     if(*ptr != '\r')
      printf("%c", *ptr);
  }
 }

 return 0;
}

int mkconnectsock(char *ipstr, int port, int tmout) {
 int sockid = -1;
 struct sockaddr_in pin;
 struct hostent *nlp_host;

 if((nlp_host = gethostbyname(ipstr)) == 0)
  error(1, 0, "Error - resolving host: %s", ipstr);

 memset(&pin, '\0', sizeof(pin));
 pin.sin_family = AF_INET;
 pin.sin_addr.s_addr = htonl(INADDR_ANY);
 pin.sin_addr.s_addr = ((struct in_addr *)(nlp_host->h_addr))->s_addr;
 pin.sin_port = htons(port);

 if((sockid = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  error(1, 0, "Error - socket(%d)", sockid);

 /* set up alarm */
 act1.sa_handler = alarm_function;
 sigemptyset(&act1.sa_mask);
 act1.sa_flags = 0;
#ifdef SA_INTERRUPT
 act1.sa_flags |= SA_INTERRUPT;
#endif
 if(sigaction(SIGALRM, &act1, &oact1) < 0)
  error(1, 0, "Error - sigaction()");

 /* connect .... */
 alarm(tmout);
 if(connect(sockid, (void *)&pin, sizeof(pin)) != 0)
  error(1, 0, "Error - connect()");
 alarm(0);

 /* interrupted connect */
 if(alarm_flag == 1)
  error(1, 0, "Error - connect(): timeout");

 return sockid;
}

int input_timeout(int filedes, unsigned int seconds) {
 fd_set set;
 struct timeval timeout;

 FD_ZERO(&set);
 FD_SET(filedes, &set);
 timeout.tv_sec = seconds;
 timeout.tv_usec = 0;

 /* `0' on: timeout, `1' on: input available, `-1' on: error */
 return select(FD_SETSIZE, &set, NULL, NULL, &timeout);
}

void alarm_function(int signo) {
 alarm_flag = 1;
}

void isip4addr(char *str) {
 char ipexpr[] = "^([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})$";
 regex_t re = {0};

 setlocale(LC_ALL, "");
 if(regcomp(&re, ipexpr, REG_EXTENDED) != 0)
  error(1, 0, "Error - Unable to compile regex:\n%s\n", ipexpr);

 if(regexec(&re, str, 0, NULL, 0) != 0)
  error(1, 0, "Error - Invalid ip4 address: %s", str);

 regfree(&re);
 return;
}

int readline(int fd, char *bufptr, size_t len) {
 char *bufx = bufptr;
 static char *bp;
 static int cnt = 0;
 static char b[1500];
 char c;

 while(--len > 0) {
  if(--cnt <= 0) {
   cnt = recv(fd, b, sizeof(b), 0);
   if(cnt < 0) {
    if(errno == EINTR) {
     len++;
     continue;
    }
    return -1;
   }
   if(cnt == 0)
    return 0;
   bp = b;
  }
  c = *bp++;
  *bufptr++ = c;
  if(c == '\n') {
   *bufptr = '\0';
   return bufptr - bufx;
  }
 }

 return -1;
}

No comments:

Post a Comment