Connect to cisco router with c++ via serial interface
-
15-07-2021 - |
Pergunta
I want to connect to Cisco router from my c++ application. Need it in order to get interface status. My linux station (Ubuntu) and the router connected via serial interface.
connected from puty or minicom or Console Connections work.
for example:
root@test:/etc/minicom# cu -l /dev/ttyS0 -s 9600
Connected.
Router#show int summary
*: interface is up
IHQ: pkts in input hold queue IQD: pkts dropped from input queue
OHQ: pkts in output hold queue OQD: pkts dropped from output queue
RXBS: rx rate (bits/sec) RXPS: rx rate (pkts/sec)
TXBS: tx rate (bits/sec) TXPS: tx rate (pkts/sec)
TRTL: throttle count
Now i tried to do the same with C++ (or C) , but read hang.
My c code:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <iostream>
#include<stdio.h>
#include<sys/ioctl.h>
#include<unistd.h>
#include<fcntl.h>
using namespace std;
int fd1;
int fd2;
char *buff, *buffer, *bufptr;
int wr, rd, nbytes, tries;
int configure_port(int fd) // configure the port
{
struct termios port_settings; // structure to store the port settings in
bzero(&port_settings, sizeof(port_settings));
cfsetispeed(&port_settings, B9600); // set baud rates
cfsetospeed(&port_settings, B9600);
port_settings.c_cflag &= ~PARENB; // set no parity, stop bits, data bits
port_settings.c_cflag &= ~CSTOPB;
port_settings.c_cflag &= ~CSIZE;
port_settings.c_cflag |= CS8;
tcsetattr(fd, TCSANOW, &port_settings); // apply the settings to the port
return (fd);
}
int main() {
fd1 = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd1 == -1) {
perror("open_port: Unable to open /dev/ttyS0 – ");
} else {
fcntl(fd1, F_SETFL, 0);
}
printf("Port 1 has been sucessfully opened and %d is the file description\n",fd1);
configure_port(fd1);
wr = write(fd1, "\r", 1);
cout << " wr status " << wr << endl;
wr = write(fd1, "\r", 1);
cout << " wr status " << wr << endl;
wr = write(fd1, "ena\r", 4);
cout << " wr status " << wr << endl;
wr = write(fd1, "show int sum\r", 13);
cout << " wr status " << wr << endl;
rd = read(fd1, buff, 50);
cout << " rd status " << rd << endl;
cout << rd << endl;
return 0;
}
Solução 2
This work - probably sleep was missing.
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <iostream>
#include<stdio.h>
#include<sys/ioctl.h>
#include<unistd.h>
#include<fcntl.h>
using namespace std;
int set_interface_attribs(int fd, int speed, int parity) {
struct termios tty;
memset(&tty, 0, sizeof tty);
if (tcgetattr(fd, &tty) != 0) {
printf("err");//error_message("error %d from tcgetattr", errno);
return -1;
}
cfsetospeed(&tty, speed);
cfsetispeed(&tty, speed);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
// disable IGNBRK for mismatched speed tests; otherwise receive break
// as \000 chars
tty.c_iflag &= ~IGNBRK; // ignore break signal
tty.c_lflag = 0; // no signaling chars, no echo,
// no canonical processing
tty.c_oflag = 0; // no remapping, no delays
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
tty.c_cflag |= (CLOCAL | CREAD); // ignore modem controls,
// enable reading
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
tty.c_cflag |= parity;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
printf("err");//error_message("error %d from tcsetattr", errno);
return -1;
}
return 0;
}
void set_blocking(int fd, int should_block) {
struct termios tty;
memset(&tty, 0, sizeof tty);
if (tcgetattr(fd, &tty) != 0) {
printf("err");//error_message("error %d from tggetattr", errno);
return;
}
tty.c_cc[VMIN] = should_block ? 1 : 0;
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
if (tcsetattr(fd, TCSANOW, &tty) != 0)
printf("err");//error_message("error %d setting term attributes", errno);
}
int main(int argc, char **argv) {
char *portname = "/dev/ttyS0";
int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0) {
printf("err");//error_message("error %d opening %s: %s", errno, portname,strerror(errno));
return -1;
}
set_interface_attribs(fd, B9600, 0); // set speed to 115,200 bps, 8n1 (no parity)
set_blocking(fd, 0); // set no blocking
write(fd, "\r", 1); // send 7 character greeting
write(fd, "\r", 1);
usleep(100000);
char buf[1000];
write(fd, "ena\r", 4);
memset(&buf, 0, sizeof buf);
usleep(100000);
write(fd, "show int sum\r", 15);
sleep(1);
memset(&buf, 0, sizeof buf);
int n = read(fd, buf, sizeof buf); // read up to 100 characters if ready to read
cout << " n " << n << endl;
cout << " buf " << buf << endl;
close(fd);
}
Outras dicas
You aren't zeroing your port_settings
struct first before modifying it. That's surely a bug, though it may not be the source of your problems. Have you tried building one of the dozens of "termios sample programs" available on the intnernet for comparison?
You should use SNMP to get interface status/statistics instead of connecting to serial console.
This is exact purpose what was SNMP designed for.