diff options
| author | Franklin Wei <git@fwei.tk> | 2015-12-24 14:57:16 -0500 |
|---|---|---|
| committer | Franklin Wei <git@fwei.tk> | 2015-12-24 14:57:16 -0500 |
| commit | 460d13ccd6242da9d25558aac6ffb7c6e9df03a6 (patch) | |
| tree | dc872bc1a5afb940ec9ca2e0ab706bee811ef7e1 | |
| parent | f1e708a631d7d5fbe6fc2f74e5f681d6a6786b4e (diff) | |
| download | netcosm-460d13ccd6242da9d25558aac6ffb7c6e9df03a6.zip netcosm-460d13ccd6242da9d25558aac6ffb7c6e9df03a6.tar.gz netcosm-460d13ccd6242da9d25558aac6ffb7c6e9df03a6.tar.bz2 netcosm-460d13ccd6242da9d25558aac6ffb7c6e9df03a6.tar.xz | |
stuff
| -rw-r--r-- | Makefile | 6 | ||||
| -rw-r--r-- | src/client.c | 151 | ||||
| -rw-r--r-- | src/netcosm.h | 106 | ||||
| -rw-r--r-- | src/server.c | 156 | ||||
| -rw-r--r-- | src/telnet.c | 12 | ||||
| -rw-r--r-- | src/telnet.h | 29 |
6 files changed, 337 insertions, 123 deletions
@@ -2,12 +2,12 @@ CC = gcc OUT = build PLATFORM = unix -NETCOSM_OBJ = src/server.o src/client.o src/auth.o src/telnet.o src/util.o +NETCOSM_OBJ = src/server.o src/client.o src/auth.o src/telnet.o src/util.o src/room.o world.o -CFLAGS = -O3 -g -I src/ -I target/$(PLATFORM) -Wall -Wextra +CFLAGS = -Og -g -I src/ -I target/$(PLATFORM) -Wall -Wextra -Wshadow -Wpedantic LDFLAGS = -lgcrypt -all: $(OUT)/$(PLATFORM).bin +all: $(OUT)/$(PLATFORM).bin Makefile $(OUT)/$(PLATFORM).bin: $(NETCOSM_OBJ) Makefile mkdir -p $(OUT) diff --git a/src/client.c b/src/client.c index d64846c..8006154 100644 --- a/src/client.c +++ b/src/client.c @@ -2,7 +2,9 @@ static int client_fd, to_parent, from_parent; -static volatile sig_atomic_t output_locked = 0, done_printing; +static room_id client_room; + +static volatile sig_atomic_t output_locked = 0; void out_raw(const unsigned char *buf, size_t len) { @@ -15,7 +17,6 @@ try_again: output_locked = 1; write(client_fd, buf, len); output_locked = 0; - done_printing = 1; } else goto try_again; @@ -32,10 +33,36 @@ void __attribute__((format(printf,1,2))) out(const char *fmt, ...) out_raw((unsigned char*)buf, len); } +static volatile sig_atomic_t request_complete; + +static void signal_master(void) +{ + request_complete = 0; + sigset_t block, old; + + sigemptyset(&block); + sigaddset(&block, SIGUSR2); + sigprocmask(SIG_BLOCK, &block, &old); + + kill(getppid(), SIGUSR1); + + /* wait for a signal */ + printf("Waiting for signal.\n"); + + sigsuspend(&old); + sigprocmask(SIG_SETMASK, &old, NULL); + + errno = 0; + printf("Spinning until completed flag set.\n"); + /* spin until we're done handling the request */ + while(!request_complete) usleep(1); + printf("Request completely done.\n"); +} + void send_master(unsigned char cmd) { write(to_parent, &cmd, 1); - kill(getppid(), SIGUSR1); + signal_master(); } #define BUFSZ 128 @@ -51,10 +78,6 @@ tryagain: if(read(client_fd, buf, BUFSZ - 1) < 0) error("lost connection"); buf[BUFSZ - 1] = '\0'; - const unsigned char ctrlc[] = { 0xff, 0xf4, 0xff, 0xfd, 0x06 }; - - if(!memcmp(buf, ctrlc, sizeof(ctrlc))) - exit(0); printf("Read '%s'\n", buf); if(buf[0] & 0x80) @@ -68,6 +91,16 @@ tryagain: return buf; } +/* still not encrypted, but a bit more secure than echoing the pass */ +char *client_read_password(void) +{ + telnet_echo_off(); + char *ret = client_read(); + telnet_echo_on(); + out("\n"); + return ret; +} + void all_upper(char *s) { while(*s) @@ -77,10 +110,17 @@ void all_upper(char *s) } } -void sigusr2_handler(int s) +void sigusr2_handler(int s, siginfo_t *info, void *vp) { (void) s; - printf("got SIGUSR2\n"); + (void) vp; + + sig_printf("got SIGUSR2\n"); + + /* we only listen to requests from our parent */ + if(info->si_pid != getppid()) + return; + unsigned char cmd; read(from_parent, &cmd, 1); unsigned char buf[MSG_MAX + 1]; @@ -88,32 +128,40 @@ void sigusr2_handler(int s) { case REQ_BCASTMSG: { - printf("reading...\n"); - size_t len = read(from_parent, buf, MSG_MAX); - printf("done reading\n"); + sig_printf("reading...\n"); + ssize_t len = read(from_parent, buf, MSG_MAX); + sig_printf("done reading\n"); buf[MSG_MAX] = '\0'; out_raw(buf, len); break; } case REQ_KICK: { - size_t len = read(from_parent, buf, MSG_MAX); + ssize_t len = read(from_parent, buf, MSG_MAX); buf[MSG_MAX] = '\0'; out_raw(buf, len); exit(EXIT_SUCCESS); } + case REQ_NOP: + break; default: - fprintf(stderr, "WARNING: client process received unknown request\n"); + sig_printf("WARNING: client process received unknown code %d\n", cmd); break; } + + sig_printf("Client finishes handling request.\n"); + + request_complete = 1; } void client_change_state(int state) { + printf("Client requesting state transition\n"); unsigned char cmdcode = REQ_CHANGESTATE; write(to_parent, &cmdcode, sizeof(cmdcode)); write(to_parent, &state, sizeof(state)); - kill(getppid(), SIGUSR1); + signal_master(); + printf("State transition completed.\n"); } void client_change_user(const char *user) @@ -121,7 +169,7 @@ void client_change_user(const char *user) unsigned char cmdcode = REQ_CHANGEUSER; write(to_parent, &cmdcode, sizeof(cmdcode)); write(to_parent, user, strlen(user) + 1); - kill(getppid(), SIGUSR1); + signal_master(); } #define WSPACE " \t\r\n" @@ -134,7 +182,14 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from) output_locked = 0; - signal(SIGUSR2, sigusr2_handler); + struct sigaction sa; + + sigemptyset(&sa.sa_mask); + + sa.sa_flags = SA_RESTART | SA_SIGINFO; + sa.sa_sigaction = sigusr2_handler; + if(sigaction(SIGUSR2, &sa, NULL) < 0) + error("sigaction"); telnet_init(); @@ -142,6 +197,8 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from) printf("New client %s\n", ip); printf("Total clients: %d\n", total); +auth: + out("NetCosm " NETCOSM_VERSION "\n"); if(total > 1) out("%d clients connected.\n", total); @@ -164,11 +221,8 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from) out("login: "); current_user = client_read(); remove_cruft(current_user); - telnet_echo_off(); out("Password: "); - char *pass = client_read(); - telnet_echo_on(); - out("\n"); + char *pass = client_read_password(); client_change_state(STATE_CHECKING); struct authinfo_t auth = auth_check(current_user, pass); memset(pass, 0, strlen(pass)); @@ -177,7 +231,6 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from) authlevel = auth.authlevel; if(auth.success) { - client_change_state(STATE_LOGGEDIN); out("Access Granted.\n\n"); break; } @@ -198,6 +251,8 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from) bool admin = (authlevel == PRIV_ADMIN); if(admin) client_change_state(STATE_ADMIN); + else + client_change_state(STATE_LOGGEDIN); /* authenticated */ printf("Authenticated as %s\n", current_user); @@ -220,6 +275,9 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from) if(!strcmp(tok, "USER")) { char *what = strtok_r(NULL, WSPACE, &save); + if(!what) + goto next_cmd; + all_upper(what); if(!strcmp(what, "DEL")) @@ -253,7 +311,20 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from) out("New Password (_DO_NOT_USE_A_VALUABLE_PASSWORD_): "); /* BAD BAD BAD BAD BAD BAD BAD CLEARTEXT PASSWORDS!!! */ - char *pass = client_read(); + char *pass = client_read_password(); + + out("Verify Password: "); + char *pass2 = client_read_password(); + + if(strcmp(pass, pass2)) + { + memset(pass, 0, strlen(pass)); + memset(pass2, 0, strlen(pass2)); + free(pass); + free(pass2); + out("Failure.\n"); + goto next_cmd; + } out("Admin privileges [y/N]? "); char *allow_admin = client_read(); @@ -281,19 +352,19 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from) else if(!strcmp(tok, "CLIENT")) { char *what = strtok_r(NULL, WSPACE, &save); - all_upper(what); if(!what) { out("Usage: CLIENT <LIST|KICK> <PID>\n"); + goto next_cmd; } + + all_upper(what); + if(!strcmp(what, "LIST")) { - done_printing = 0; unsigned char cmd_code = REQ_LISTCLIENTS; write(to_parent, &cmd_code, sizeof(cmd_code)); - kill(getppid(), SIGUSR1); - waitpid(-1, NULL, 0); - while(!done_printing); + signal_master(); } else if(!strcmp(what, "KICK")) { @@ -307,7 +378,8 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from) char buf[128]; int len = snprintf(buf, sizeof(buf), "You were kicked.\n"); write(to_parent, buf, len); - kill(getppid(), SIGUSR1); + signal_master(); + printf("Success.\n"); } else out("Usage: CLIENT KICK <PID>\n"); @@ -330,7 +402,26 @@ void client_main(int fd, struct sockaddr_in *addr, int total, int to, int from) unsigned char cmd_code = REQ_BCASTMSG; write(to_parent, &cmd_code, sizeof(cmd_code)); dprintf(to_parent, "%s says %s", current_user, what); - kill(getppid(), SIGUSR1); + signal_master(); + } + else if(!strcmp(tok, "DATE")) + { + time_t t = time(NULL); + out("%s", ctime(&t)); + } + else if(!strcmp(tok, "LOGOUT")) + { + out("Logged out.\n"); + goto auth; + } + else if(!strcmp(tok, "LOOK")) + { + //out(room_get(client_room)->data.desc); + //out("\n"); + } + else if(!strcmp(tok, "WAIT")) + { + send_master(REQ_WAIT); } next_cmd: diff --git a/src/netcosm.h b/src/netcosm.h index 16ace01..ac2c72c 100644 --- a/src/netcosm.h +++ b/src/netcosm.h @@ -30,21 +30,106 @@ #define PRIV_USER 0 #define PRIV_ADMIN 1337 +/* child<->master commands */ +/* children might not implement all of these */ +#define REQ_NOP 0 +#define REQ_BCASTMSG 1 +#define REQ_LISTCLIENTS 2 +#define REQ_CHANGESTATE 3 +#define REQ_CHANGEUSER 4 +#define REQ_HANG 5 +#define REQ_KICK 6 +#define REQ_WAIT 7 + +/* child states */ +#define STATE_INIT 0 +#define STATE_AUTH 1 +#define STATE_CHECKING 2 +#define STATE_LOGGEDIN 3 +#define STATE_ADMIN 4 +#define STATE_FAILED 5 + +/* for convenience when writing world specs */ +#define NONE_N NULL +#define NONE_NE NULL +#define NONE_E NULL +#define NONE_SE NULL +#define NONE_S NULL +#define NONE_SW NULL +#define NONE_W NULL +#define NONE_NW NULL +#define NONE_UP NULL +#define NONE_DN NULL + struct authinfo_t { bool success; const char *user; int authlevel; }; +/* logged in users are identified by the PID of the process serving them */ +struct user_t { + pid_t pid; +}; + +enum direction_t { DIR_N = 0, DIR_NE, DIR_E, DIR_SE, DIR_S, DIR_SW, DIR_W, DIR_NW, DIR_UP, DIR_DOWN, NUM_DIRECTIONS }; + +struct item_t { + const char *class; + +}; + +struct verb_t { + const char *name; + + /* toks is strtok_r's pointer */ + void (*execute)(const char *toks); +}; + +typedef int room_id; + +/* the data we get from a world module */ +struct roomdata_t { + const char *uniq_id; + const char *name; + const char *desc; + + const char *adjacent[NUM_DIRECTIONS]; + + void (*hook_init)(room_id id); + void (*hook_enter)(room_id room, pid_t player); + void (*hook_say)(room_id room, pid_t player, const char *msg); + void (*hook_leave)(room_id room, pid_t player); +}; + +struct room_t { + room_id id; + struct roomdata_t data; + + room_id adjacent[NUM_DIRECTIONS]; + + /* arrays instead of linked lists because insertion should be rare for these */ + struct item_t *items; + size_t items_sz; + + struct verb_t *verbs; + size_t verbs_sz; +}; + +extern const struct roomdata_t netcosm_world[]; +extern const size_t netcosm_world_sz; + void client_main(int sock, struct sockaddr_in *addr, int, int to_parent, int from_parent); void __attribute__((noreturn)) error(const char *fmt, ...); void first_run_setup(void); struct authinfo_t auth_check(const char*, const char*); -/* add or change a user */ +/* add or change a user, NOT reentrant */ bool add_change_user(const char *user2, const char *pass2, int level); bool auth_remove(const char*); + void telnet_handle_command(const unsigned char*); + #define ARRAYLEN(x) (sizeof(x)/sizeof(x[0])) void out(const char *fmt, ...) __attribute__((format(printf,1,2))); @@ -56,21 +141,6 @@ void telnet_echo_off(void); void remove_cruft(char*); -/* child<->master commands */ -/* children might not implement all of these */ -#define REQ_NOP 0 -#define REQ_BCASTMSG 1 -#define REQ_LISTCLIENTS 2 -#define REQ_CHANGESTATE 3 -#define REQ_CHANGEUSER 4 -#define REQ_HANG 5 -#define REQ_KICK 6 - -#define STATE_INIT 0 -#define STATE_AUTH 1 -#define STATE_CHECKING 2 -#define STATE_LOGGEDIN 3 -#define STATE_ADMIN 4 -#define STATE_FAILED 5 - void auth_list_users(void); +void world_init(const struct roomdata_t *data, size_t sz); +void sig_printf(const char *fmt, ...); diff --git a/src/server.c b/src/server.c index 46d0ac4..abbad30 100644 --- a/src/server.c +++ b/src/server.c @@ -36,12 +36,13 @@ void __attribute__((noreturn)) error(const char *fmt, ...) /* assume int is atomic */ volatile int num_clients = 0; -struct child_data { +static struct child_data { pid_t pid; int readpipe[2]; int outpipe[2]; int state; + room_id room; char *user; struct in_addr addr; @@ -50,7 +51,7 @@ struct child_data { struct child_data *next; } *child_data; -void sigchld_handler(int s, siginfo_t *info, void *vp) +static void sigchld_handler(int s, siginfo_t *info, void *vp) { (void) s; (void) info; @@ -86,15 +87,15 @@ void sigchld_handler(int s, siginfo_t *info, void *vp) int port; -void handle_client(int fd, struct sockaddr_in *addr, - int num_clients, int to, int from) +static void handle_client(int fd, struct sockaddr_in *addr, + int nclients, int to, int from) { - client_main(fd, addr, num_clients, to, from); + client_main(fd, addr, nclients, to, from); } int server_socket; -void serv_cleanup(void) +static void serv_cleanup(void) { write(STDOUT_FILENO, "Shutdown server.\n", strlen("Shutdown server.\n")); if(shutdown(server_socket, SHUT_RDWR) > 0) @@ -102,31 +103,28 @@ void serv_cleanup(void) close(server_socket); } -void sigint_handler(int s) +static void sigint_handler(int s) { (void) s; serv_cleanup(); } -void write_client(int child_pipe, struct child_data *iter) -{ - char buf[128]; - printf("writing ip\n"); - char *ip = inet_ntoa(iter->addr); - int len = snprintf(buf, sizeof(buf), "Client %s PID %d\n", ip, iter->pid); - write(child_pipe, buf, len); -} - -void req_pass_msg(unsigned char *data, size_t datalen, +static void req_pass_msg(unsigned char *data, size_t datalen, struct child_data *sender, struct child_data *child) { (void) sender; + if(sender->pid != child->pid) + { + unsigned char cmd = REQ_BCASTMSG; + write(child->outpipe[1], &cmd, 1); + } + write(child->outpipe[1], data, datalen); kill(child->pid, SIGUSR2); } -void req_send_clientinfo(unsigned char *data, size_t datalen, +static void req_send_clientinfo(unsigned char *data, size_t datalen, struct child_data *sender, struct child_data *child) { (void) data; @@ -148,29 +146,33 @@ void req_send_clientinfo(unsigned char *data, size_t datalen, else len = snprintf(buf, sizeof(buf), "Client %s PID %d [%s]\n", inet_ntoa(child->addr), child->pid, state[child->state]); - write(sender->outpipe[1], buf, len); -} -void req_signal_sender(struct child_data *sender) -{ - kill(sender->pid, SIGUSR2); + write(sender->outpipe[1], buf, len); } -void req_change_state(unsigned char *data, size_t datalen, +static void req_change_state(unsigned char *data, size_t datalen, struct child_data *sender, struct child_data *child) { (void) child; if(datalen == sizeof(sender->state)) { sender->state = *((int*)data); + printf("State changed to %d\n", sender->state); } else - printf("State data is of the wrong size.\n"); + { + printf("State data is of the wrong size\n"); + for(size_t i = 0; i < datalen; ++i) + printf("%02x\n", data[i]); + } } -void req_change_user(unsigned char *data, size_t datalen, +static void req_change_user(unsigned char *data, size_t datalen, struct child_data *sender, struct child_data *child) { + (void) data; + (void) datalen; + (void) child; if(sender->user) free(sender->user); sender->user = strdup((char*)data); @@ -182,9 +184,10 @@ void req_change_user(unsigned char *data, size_t datalen, // while(1); //} -void req_kick_client(unsigned char *data, size_t datalen, +static void req_kick_client(unsigned char *data, size_t datalen, struct child_data *sender, struct child_data *child) { + (void) sender; if(datalen >= sizeof(pid_t)) { pid_t kicked_pid = *((pid_t*)data); @@ -198,6 +201,11 @@ void req_kick_client(unsigned char *data, size_t datalen, } } +static void req_wait(struct child_data *sender) +{ + sleep(10); +} + static const struct child_request { unsigned char code; @@ -212,26 +220,40 @@ static const struct child_request { void (*finalize)(struct child_data *sender); - /* what byte to write back to the sender if != REQ_NOP */ + /* byte to write back to the sender */ unsigned char cmd_to_send; } requests[] = { - { REQ_NOP, false, CHILD_NONE, NULL, NULL, REQ_NOP}, - { REQ_BCASTMSG, true, CHILD_ALL, req_pass_msg, NULL, REQ_BCASTMSG}, - { REQ_LISTCLIENTS, false, CHILD_ALL, req_send_clientinfo, req_signal_sender, REQ_BCASTMSG}, - { REQ_CHANGESTATE, true, CHILD_SENDER, req_change_state, NULL, REQ_NOP }, - { REQ_CHANGEUSER, true, CHILD_SENDER, req_change_user, NULL, REQ_NOP }, + { REQ_NOP, false, CHILD_NONE, NULL, NULL, REQ_NOP }, + { REQ_BCASTMSG, true, CHILD_ALL, req_pass_msg, NULL, REQ_BCASTMSG }, + { REQ_LISTCLIENTS, false, CHILD_ALL, req_send_clientinfo, NULL, REQ_BCASTMSG }, + { REQ_CHANGESTATE, true, CHILD_SENDER, req_change_state, NULL, REQ_NOP }, + { REQ_CHANGEUSER, true, CHILD_SENDER, req_change_user, NULL, REQ_NOP }, //{ REQ_HANG, false, CHILD_SENDER, req_hang, NULL, REQ_NOP }, - { REQ_KICK, true, CHILD_ALL, req_kick_client, NULL, REQ_NOP }, + { REQ_KICK, true, CHILD_ALL, req_kick_client, NULL, REQ_NOP }, + { REQ_WAIT, false, CHILD_NONE, NULL, req_wait, REQ_NOP }, }; +void sig_printf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + char buf[128]; + int len = vsnprintf(buf, sizeof(buf), fmt, ap); + + write(STDOUT_FILENO, buf, len); + + va_end(ap); +} + /* SIGUSR1 is used by children to communicate with the master process */ /* the master handles commands that involve multiple children, i.e. message passing, listing clients, etc. */ -void sigusr1_handler(int s, siginfo_t *info, void *vp) +static void sigusr1_handler(int s, siginfo_t *info, void *vp) { (void) s; (void) vp; pid_t sender_pid = info->si_pid; - printf("PID %d sends a client request\n", sender_pid); + sig_printf("PID %d sends a client request\n", sender_pid); unsigned char cmd, data[MSG_MAX + 1]; const struct child_request *req = NULL; @@ -261,18 +283,17 @@ void sigusr1_handler(int s, siginfo_t *info, void *vp) } if(!req) { - printf("Unknown request.\n"); + sig_printf("Unknown request.\n"); return; } - printf("Got command %d\n", cmd); + sig_printf("Got command %d\n", cmd); if(req->havedata) { datalen = read(iter->readpipe[0], data, sizeof(data)); } - if(req->cmd_to_send) - write(sender->outpipe[1], &req->cmd_to_send, 1); + write(sender->outpipe[1], &req->cmd_to_send, 1); switch(req->which) { @@ -321,10 +342,18 @@ void sigusr1_handler(int s, siginfo_t *info, void *vp) finish: - if(req->finalize) + if(req && req->finalize) req->finalize(sender); - printf("finished handling client request\n"); + if(sender) + kill(sender->pid, SIGUSR2); + else + sig_printf("WARN: unknown child sent request.\n"); + + if(!req) + sig_printf("WARN: unknown request, request ignored\n"); + + sig_printf("finished handling client request\n"); } void init_signals(void) @@ -352,13 +381,17 @@ void init_signals(void) error("sigaction"); } -int main(int argc, char *argv[]) +static void check_userfile(void) +{ + if(access(USERFILE, F_OK) < 0) + first_run_setup(); + + if(access(USERFILE, R_OK | W_OK) < 0) + error("cannot access "USERFILE); +} + +static int server_bind(void) { - if(argc != 2) - port = PORT; - else - port = strtol(argv[1], NULL, 0); - srand(time(0)); int sock = socket(AF_INET, SOCK_STREAM, 0); if(sock<0) @@ -381,17 +414,27 @@ int main(int argc, char *argv[]) if(listen(sock, BACKLOG) < 0) error("listen"); - server_socket = sock; + return sock; +} + +int main(int argc, char *argv[]) +{ + if(argc != 2) + port = PORT; + else + port = strtol(argv[1], NULL, 0); + + srand(time(0)); + + server_socket = server_bind(); /* set up signal handlers for SIGCHLD, SIGUSR1, and SIGINT */ - /* SIGUSR1 is used for broadcast signalling */ + /* SIGUSR1 is used for broadcast signaling */ init_signals(); - if(access(USERFILE, F_OK) < 0) - first_run_setup(); + check_userfile(); - if(access(USERFILE, R_OK | W_OK) < 0) - error("cannot access "USERFILE); + world_init(netcosm_world, netcosm_world_sz); child_data = NULL; @@ -401,7 +444,7 @@ int main(int argc, char *argv[]) { struct sockaddr_in client; socklen_t client_len = sizeof(client); - int new_sock = accept(sock, (struct sockaddr*) &client, &client_len); + int new_sock = accept(server_socket, (struct sockaddr*) &client, &client_len); if(new_sock < 0) error("accept"); @@ -421,9 +464,10 @@ int main(int argc, char *argv[]) if(!pid) { + /* child */ close(readpipe[0]); close(outpipe[1]); - close(sock); + close(server_socket); printf("Child with PID %d spawned\n", getpid()); diff --git a/src/telnet.c b/src/telnet.c index 1838b45..377f5cf 100644 --- a/src/telnet.c +++ b/src/telnet.c @@ -37,7 +37,14 @@ void telnet_handle_command(const unsigned char *buf) goto found; } } - printf("??? "); + switch(c) + { + case IP: + exit(0); + default: + break; + } + printf("???: %d ", c); found: ++buf; @@ -74,8 +81,9 @@ void telnet_init(void) IAC, DONT, NAWS, IAC, WONT, STATUS, IAC, DONT, STATUS, - IAC, DO, ECHO, + IAC, DO, ECHO, IAC, WONT, ECHO, + IAC, DONT, LINEMODE, }; out_raw(init_seq, ARRAYLEN(init_seq)); } diff --git a/src/telnet.h b/src/telnet.h index 475cfce..11d1a42 100644 --- a/src/telnet.h +++ b/src/telnet.h @@ -1,20 +1,21 @@ /* commands */ - -#define IAC 255 +#define IAC 255 #define DONT 254 -#define DO 253 +#define DO 253 #define WONT 252 #define WILL 251 -#define SB 250 -#define GA 249 -#define EL 248 -#define EC 247 -#define AYT 246 -#define NOP 241 -#define SE 240 +#define SB 250 +#define GA 249 +#define EL 248 +#define EC 247 +#define AYT 246 +#define IP 244 +#define NOP 241 +#define SE 240 /* options */ -#define ECHO 1 -#define SGA 3 -#define STATUS 5 -#define NAWS 31 +#define ECHO 1 +#define SGA 3 +#define STATUS 5 +#define NAWS 31 +#define LINEMODE 34 |