1 #include 2 3 #include "debug.h" 4 #include "ip.h" 5 #include "modem_core.h" 6 7 #include "nvt.h" 8 9 void nvt_init_config(nvt_vars *vars) { 10 int i; 11 12 vars->binary_xmit = FALSE; 13 vars->binary_recv = FALSE; 14 for (i = 0; i < 256; i++) 15 vars->term[i] = 0; 16 } 17 18 unsigned char get_nvt_cmd_response(unsigned char action, unsigned char type) { 19 unsigned char rc = 0; 20 21 if(type == TRUE) { 22 switch (action) { 23 case NVT_DO: 24 rc = NVT_WILL; 25 break; 26 case NVT_DONT: 27 rc = NVT_WONT; 28 break; 29 case NVT_WILL: 30 rc = NVT_DO; 31 break; 32 case NVT_WONT: 33 rc = NVT_DONT; 34 break; 35 } 36 } else { 37 switch (action) { 38 case NVT_DO: 39 case NVT_DONT: 40 rc = NVT_WONT; 41 break; 42 case NVT_WILL: 43 case NVT_WONT: 44 rc = NVT_DONT; 45 break; 46 } 47 } 48 return rc; 49 } 50 51 int parse_nvt_subcommand(dce_config *cfg, int fd, nvt_vars *vars, unsigned char *data, int len) { 52 // overflow issue, again... 53 nvt_option opt = data[2]; 54 unsigned char resp[100]; 55 unsigned char *response = resp + 3; 56 int resp_len = 0; 57 int response_len = 0; 58 char tty_type[] = "VT100"; 59 int rc; 60 char buf[50]; 61 int slen = 0; 62 63 for (rc = 2; rc < len - 1; rc++) { 64 if (NVT_IAC == data[rc]) 65 if (NVT_SE == data[rc + 1]) { 66 rc += 2; 67 break; 68 } 69 } 70 71 if (rc > 5 && (NVT_SB_SEND == data[3])) { 72 switch(opt) { 73 case NVT_OPT_TERMINAL_TYPE: 74 case NVT_OPT_X_DISPLAY_LOCATION: // should not have to have these 75 case NVT_OPT_ENVIRON: // but telnet seems to expect. 76 case NVT_OPT_NEW_ENVIRON: // them. 77 case NVT_OPT_TERMINAL_SPEED: 78 response[response_len++] = NVT_SB_IS; 79 switch(opt) { 80 case NVT_OPT_TERMINAL_TYPE: 81 slen = strlen(tty_type); 82 strncpy((char *)response + response_len, tty_type, slen); 83 response_len += slen; 84 break; 85 case NVT_OPT_TERMINAL_SPEED: 86 sprintf(buf, "%i,%i", cfg->port_speed, cfg->port_speed); 87 slen = strlen(buf); 88 strncpy((char *)response + response_len, buf, slen); 89 response_len += slen; 90 break; 91 default: 92 break; 93 } 94 break; 95 default: 96 break; 97 } 98 } 99 100 if (response_len) { 101 resp[resp_len++] = NVT_IAC; 102 resp[resp_len++] = NVT_SB; 103 resp[resp_len++] = opt; 104 resp_len += response_len; 105 resp[resp_len++] = NVT_IAC; 106 resp[resp_len++] = NVT_SE; 107 ip_write(fd, resp, resp_len); 108 } 109 return rc; 110 } 111 112 void get_action(char *txt, nvt_command action) { 113 switch (action) { 114 case NVT_WILL: 115 strcpy(txt, "WILL"); 116 break; 117 case NVT_WONT: 118 strcpy(txt, "WONT"); 119 break; 120 case NVT_DO: 121 strcpy(txt, "DO"); 122 break; 123 case NVT_DONT: 124 strcpy(txt, "DONT"); 125 break; 126 default: 127 strcpy(txt, "UNKNOWN"); 128 break; 129 } 130 } 131 132 int send_nvt_command(int fd, nvt_vars *vars, nvt_command action, nvt_option opt) { 133 unsigned char cmd[3]; 134 char txt[20]; 135 136 get_action(txt, action); 137 LOG(LOG_DEBUG, "Sending NVT command: %s %d", txt, opt); 138 cmd[0] = NVT_IAC; 139 cmd[1] = action; 140 cmd[2] = opt; 141 142 ip_write(fd, cmd, 3); 143 vars->term[opt] = action; 144 145 return 0; 146 } 147 148 int parse_nvt_command(dce_config *cfg, int fd, nvt_vars *vars, nvt_command action, nvt_option opt) { 149 int accept = FALSE; 150 char txt[20]; 151 int resp; 152 153 get_action(txt, action); 154 LOG(LOG_DEBUG, "Received NVT command: %s %d", txt, opt); 155 switch (opt) { 156 case NVT_OPT_TRANSMIT_BINARY : 157 switch (action) { 158 case NVT_DO: 159 if(!dce_get_parity(cfg)) { 160 LOG(LOG_INFO, "Enabling telnet binary xmit"); 161 vars->binary_xmit = TRUE; 162 accept = TRUE; 163 } 164 break; 165 case NVT_DONT: 166 LOG(LOG_INFO, "Disabling telnet binary xmit"); 167 vars->binary_xmit = FALSE; 168 accept = TRUE; 169 break; 170 case NVT_WILL: 171 if(!dce_get_parity(cfg)) { 172 LOG(LOG_INFO, "Enabling telnet binary recv"); 173 vars->binary_recv = TRUE; 174 accept = TRUE; 175 } 176 break; 177 case NVT_WONT: 178 LOG(LOG_INFO, "Disabling telnet binary recv"); 179 vars->binary_recv = FALSE; 180 accept = TRUE; 181 break; 182 default: 183 break; 184 } 185 resp = get_nvt_cmd_response(action, accept); 186 break; 187 case NVT_OPT_NAWS: 188 case NVT_OPT_TERMINAL_TYPE: 189 case NVT_OPT_SUPPRESS_GO_AHEAD: 190 case NVT_OPT_ECHO: 191 case NVT_OPT_X_DISPLAY_LOCATION: // should not have to have these 192 case NVT_OPT_ENVIRON: // but telnet seems to expect. 193 case NVT_OPT_NEW_ENVIRON: // them. 194 case NVT_OPT_TERMINAL_SPEED: 195 resp = get_nvt_cmd_response(action, TRUE); 196 break; 197 default: 198 resp = get_nvt_cmd_response(action, FALSE); 199 break; 200 } 201 send_nvt_command(fd, vars, resp, opt); 202 return 0; 203 }