vdetelweb: wrong char count on write+it looped if the switch terminated during svdete...
[vde.git] / vdetelweb / telnet.c
blob7bb51cb2962c5712f6109c8ea9835f4cadbe92ad
1 /*
2 * VDETELWEB: VDE telnet and WEB interface
4 * telnet.c: telnet module
5 *
6 * Copyright 2005,2007 Renzo Davoli University of Bologna - Italy
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, version 2 of the License.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * $Id$
25 #define _GNU_SOURCE
26 #include <config.h>
27 #include <stdio.h>
28 #include <signal.h>
29 #include <stdarg.h>
30 #include <syslog.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <ctype.h>
34 #include <errno.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/poll.h>
38 #include <linux/un.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
41 #include <arpa/telnet.h>
42 #include <string.h>
43 #include <getopt.h>
44 #include "vdetelweb.h"
45 #include <libvdehist.h>
46 #include <lwipv6.h>
48 #define TELNET_TCP_PORT 23
50 void telnetdata(int fn,int fd,int vdefd)
52 struct vdehiststat *vdehst=status[fn];
53 if (vdehist_term_to_mgmt(vdehst) != 0) {
54 int termfd=vdehist_gettermfd(vdehst);
55 int mgmtfd=vdehist_getmgmtfd(vdehst);
56 delpfd(pfdsearch(termfd));
57 lwip_close(termfd);
58 if (mgmtfd >= 0) {
59 delpfd(mgmtfd);
60 close(mgmtfd);
62 vdehist_free(vdehst);
66 void telnet_vdedata(int fn,int fd,int vdefd)
68 struct vdehiststat *vdehst=status[fn];
69 vdehist_mgmt_to_term(vdehst);
73 char *telnet_logincmd(char *cmd,int len,struct vdehiststat *st)
75 int histstatus=vdehist_getstatus(st);
76 int termfd=vdehist_gettermfd(st);
77 switch (histstatus) {
78 case HIST_NOCMD:
79 while (cmd[len-1] == '\n')
80 cmd[--len]=0;
81 if (strcmp(cmd,"admin") != 0) {
82 lwip_write(termfd,"login incorrect\r\n\r\nLogin: ",26);
83 } else {
84 lwip_write(termfd,"Password: ",11);
85 vdehist_setstatus(st,HIST_PASSWDFLAG);
87 break;
88 case HIST_PASSWDFLAG:
89 case HIST_PASSWDFLAG+1:
90 case HIST_PASSWDFLAG+2:
91 while (cmd[len-1] == '\n')
92 cmd[--len]=0;
93 if (!sha1passwdok(cmd)) {
94 histstatus++;
95 vdehist_setstatus(st,histstatus);
96 if (histstatus < (HIST_PASSWDFLAG + 3))
97 lwip_write(termfd,"\r\nlogin incorrect\r\n\r\nPassword: ",30);
98 else
99 return "logout";
100 } else {
101 int newfn;
102 int flags;
103 int mgmtfd;
104 vdehist_setstatus(st,HIST_COMMAND);
105 mgmtfd=openextravdem();
106 if (mgmtfd >= 0) {
107 vdehist_setmgmtfd(st,mgmtfd);
108 flags = fcntl(mgmtfd, F_GETFL);
109 flags |= O_NONBLOCK;
110 fcntl(mgmtfd, F_SETFL, flags);
111 newfn=addpfd(mgmtfd,telnet_vdedata);
112 status[newfn]=st;
113 } else
114 return "logout";
115 lwip_write(termfd,"\r\n",2);
116 lwip_write(termfd,prompt,strlen(prompt));
119 return NULL;
123 void telnetaccept(int fn,int fd,int vdefd)
125 struct sockaddr_in cli_addr;
126 int newsockfd;
127 unsigned int clilen;
128 int newfn;
130 clilen = sizeof(cli_addr);
131 newsockfd = lwip_accept(fd, (struct sockaddr *) &cli_addr, &clilen);
133 if (newsockfd < 0) {
134 printlog(LOG_ERR,"telnet accept err: %s",strerror(errno));
137 newfn=addpfd(newsockfd,telnetdata);
138 status[newfn]=vdehist_new(newsockfd,-1);
139 lwip_write(newsockfd,banner,strlen(banner));
140 lwip_write(newsockfd,"\r\nLogin: ",9);
143 void telnet_init(int vdefd)
145 int sockfd;
146 struct sockaddr_in serv_addr;
147 vdehist_termread=lwip_read;
148 vdehist_termwrite=lwip_write;
149 vdehist_logincmd=telnet_logincmd;
150 sockfd=lwip_socket(AF_INET, SOCK_STREAM, 0);
152 if (!sockfd) {
153 printlog(LOG_ERR,"telnet socket err: %s",strerror(errno));
156 bzero((char *) &serv_addr, sizeof(serv_addr));
157 serv_addr.sin_family = AF_INET;
158 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
159 serv_addr.sin_port = htons(TELNET_TCP_PORT);
161 if (lwip_bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
162 printlog(LOG_ERR,"telnet bind err: %s",strerror(errno));
165 lwip_listen(sockfd, 5);
167 addpfd(sockfd,telnetaccept);