From: Egor Date: Wed, 11 May 2022 12:12:39 +0000 (+0300) Subject: add VERSION/ADMIN/LUSERS/TIME X-Git-Url: https://git.patchysicp.xyz/?a=commitdiff_plain;h=f231706b5252921fa97822a7bbc5e7e8cce282d7;p=patchyircd.git add VERSION/ADMIN/LUSERS/TIME --- diff --git a/config.h b/config.h index 45ff1f9..7b990e9 100644 --- a/config.h +++ b/config.h @@ -5,3 +5,12 @@ #define SUPPORT_IPV4 #define SUPPORT_IPV6 #define MAX_NICKLEN 32 +#ifndef ADMINLOC1 +#define ADMINLOC1 "Location 1" +#endif +#ifndef ADMINLOC2 +#define ADMINLOC2 "Location 2" +#endif +#ifndef ADMINEMAIL +#define ADMINEMAIL "admin@example.com" +#endif diff --git a/irc.c b/irc.c index e8ded31..72f8f20 100644 --- a/irc.c +++ b/irc.c @@ -240,9 +240,6 @@ int processPacket(struct client_data *client, char *source, char *command, int a abort(); // Send welcome newUser(client); - } else if(strcmp(command, "MOTD") == 0) { - // Send welcome - sendMOTD(client); } else if(strcmp(command, "OPER") == 0) { if (!is_registered(client)) return err_notregistered(client), sendbuf(client), 0; @@ -404,6 +401,40 @@ int processPacket(struct client_data *client, char *source, char *command, int a return 1; } else if(strcmp(command, "PONG") == 0) { // Do nothing + // Server Queries and Commands + } else if(strcmp(command, "MOTD") == 0) { + if (!is_registered(client)) + return err_notregistered(client), sendbuf(client), 0; + if (args[0] && strcmp(args[0], hostname) != 0) + return err_nosuchserver(client, args[0]), sendbuf(client), 0; + // Send welcome + sendMOTD(client); + } else if(strcmp(command, "VERSION") == 0) { + if (!is_registered(client)) + return err_notregistered(client), sendbuf(client), 0; + if (args[0] && strcmp(args[0], hostname) != 0) + return err_nosuchserver(client, args[0]), sendbuf(client), 0; + rpl_version(client, "v0.0.1", "PatchyIRCD v0.0.1"), sendbuf(client); + rpl_isupport(client), sendbuf(client); + } else if(strcmp(command, "ADMIN") == 0) { + if (!is_registered(client)) + return err_notregistered(client), sendbuf(client), 0; + if (args[0] && strcmp(args[0], hostname) != 0) + return err_nosuchserver(client, args[0]), sendbuf(client), 0; + rpl_adminme(client), sendbuf(client); + rpl_adminloc1(client, ADMINLOC1), sendbuf(client); + rpl_adminloc2(client, ADMINLOC2), sendbuf(client); + rpl_adminemail(client, ADMINEMAIL), sendbuf(client); + } else if(strcmp(command, "LUSERS") == 0) { + if (!is_registered(client)) + return err_notregistered(client), sendbuf(client), 0; + sendLUSERS(client); + } else if(strcmp(command, "TIME") == 0) { + if (!is_registered(client)) + return err_notregistered(client), sendbuf(client), 0; + if (args[0] && strcmp(args[0], hostname) != 0) + return err_nosuchserver(client, args[0]), sendbuf(client), 0; + rpl_time(client, get_time()), sendbuf(client); } else if(strcmp(command, "MODE") == 0) { if (!is_registered(client)) return err_notregistered(client), sendbuf(client), 0; @@ -698,6 +729,7 @@ int processPacket(struct client_data *client, char *source, char *command, int a append_str(&databuf, "\r\n"); } sendbuf(client); + // User-Based Queries } else if(strcmp(command, "WHO") == 0) { if (!is_registered(client)) return err_notregistered(client), sendbuf(client), 0; @@ -816,14 +848,43 @@ void newUser(struct client_data *client) { rpl_created(client), sendbuf(client); rpl_myinfo(client), sendbuf(client); rpl_isupport(client), sendbuf(client); - copy_strf(&databuf, ":%s 251 %s :This server exists\n", hostname, client->nick); - sendbuf(client); - copy_strf(&databuf, ":%s 252 %s :Jannies don't exist\n", hostname, client->nick); - sendbuf(client); - copy_strf(&databuf, ":%s 221 %s %s\r\n", hostname, client->nick, format_umodes(client)); - sendbuf(client); + sendLUSERS(client); + rpl_umodeis(client), sendbuf(client); sendMOTD(client); } +void sendLUSERS(struct client_data *client) +{ + int total = 0; + int registered = 0; + int invisible = 0; + int ops = 0; + int channels = 0; + struct trie_find *f = NULL; + if (trie_findfirst(&f, &client_map) == 1) + do { + struct client_data *cl = f->n->value; + registered++; + if (cl->umode & UMODE_INVISIBLE) + invisible++; + if (cl->umode & UMODE_OPER) + ops++; + } while (trie_findnext(&f) == 1); + if (trie_findfirst(&f, &client_map) == 1) + do { + channels++; + } while (trie_findnext(&f) == 1); + for (int i = 0; i < CLIENTS; i++) + if (clients[i]) + total++; + + rpl_luserclient(client, registered, invisible, 1), sendbuf(client); + rpl_luserop(client, ops), sendbuf(client); + rpl_luserunknown(client, total-registered), sendbuf(client); + rpl_luserchannels(client, channels), sendbuf(client); + rpl_luserme(client, registered, 0), sendbuf(client); + rpl_localusers(client, registered, CLIENTS), sendbuf(client); + rpl_globalusers(client, registered, CLIENTS), sendbuf(client); +} void sendMOTD(struct client_data *client) { copy_strf(&databuf, ":%s 375 %s :PatchySICP /MOTD\n", hostname, client->nick); diff --git a/irc.h b/irc.h index 95df9ce..f9100b9 100644 --- a/irc.h +++ b/irc.h @@ -8,6 +8,7 @@ int parsePacket(struct client_data *client); int processPacket(struct client_data *client, char *source, char *command, int argc, char *args[]); void newUser(struct client_data *client); +void sendLUSERS(struct client_data *client); void sendMOTD(struct client_data *client); void setNick(struct client_data *client, char* nickname); struct client_data *findClient(const char *nickname); diff --git a/ircfmt.c b/ircfmt.c index 73bb403..2bb239b 100644 --- a/ircfmt.c +++ b/ircfmt.c @@ -1,6 +1,8 @@ #include "ircfmt.h" extern struct dynarr databuf; extern const char *hostname; +extern const char *format_umodes(struct client_data *cl); + void msg_nick(struct client_data *src, const char *newnick) { copy_strf(&databuf, ":%s!%s@%s NICK %s\r\n", @@ -105,20 +107,79 @@ void rpl_isupport(struct client_data *client) // 005 copy_strf(&databuf, ":%s 005 %s CASEMAPPING=rfc1459 NICKLEN=%u EXCEPTS=e INVEX=I MAXTARGETS=1 CHANMODES=beI,k,l,Pimnst CHANTYPES=#& PREFIX=(ov)@+ STATUSMSG=@+ :are supported by this server\n", hostname, client->nick, MAX_NICKLEN-1); } -// 010 RPL_BOUNC -// 221 RPL_UMODEIS -// 251 RPL_LUSERCLIENT -// 252 RPL_LUSEROP -// 253 RPL_LUSERUNKNOWN -// 254 RPL_LUSERCHANNELS -// 255 RPL_LUSERME -// 256 RPL_ADMINME -// 257 RPL_ADMINLOC1 -// 258 RPL_ADMINLOC2 -// 259 RPL_ADMINEMAIL -// 263 RPL_TRYAGAIN -// 265 RPL_LOCALUSERS -// 266 RPL_GLOBALUSERS +#if 0 +void rpl_bounce(struct client_data *client, const char *host, const char *port, const char *info) // 010 +{ + copy_strf(&databuf, ":%s 010 %s %s %s :%s\r\n", + hostname, client->nick, host, port, info); +} +#endif +void rpl_umodeis(struct client_data *client) // 221 +{ + copy_strf(&databuf, ":%s 221 %s %s\r\n", hostname, client->nick, format_umodes(client)); +} +void rpl_luserclient(struct client_data *client, int users, int invisible, int servers) // 251 +{ + copy_strf(&databuf, ":%s 251 %s :There are %u users and %u invisible on %u servers\r\n", + hostname, client->nick, users, invisible, servers); +} +void rpl_luserop(struct client_data *client, int ops) // 252 +{ + copy_strf(&databuf, ":%s 252 %s %u :operator(s) online\r\n", + hostname, client->nick, ops); +} +void rpl_luserunknown(struct client_data *client, int unk) // 253 +{ + copy_strf(&databuf, ":%s 253 %s %u :unknown connection(s)\r\n", + hostname, client->nick, unk); +} +void rpl_luserchannels(struct client_data *client, int channels) // 254 +{ + copy_strf(&databuf, ":%s 254 %s %u :channels formed\r\n", + hostname, client->nick, channels); +} +void rpl_luserme(struct client_data *client, int clients, int servers) // 255 +{ + copy_strf(&databuf, ":%s 255 %s :I have %u clients and %u servers\r\n", + hostname, client->nick, clients, servers); +} +void rpl_adminme(struct client_data *client) // 256 +{ + copy_strf(&databuf, ":%s 256 %s %s :Administrative info\r\n", + hostname, client->nick, hostname); +} +void rpl_adminloc1(struct client_data *client, const char *loc) // 257 +{ + copy_strf(&databuf, ":%s 257 %s :%s\r\n", + hostname, client->nick, loc); +} +void rpl_adminloc2(struct client_data *client, const char *loc) // 258 +{ + copy_strf(&databuf, ":%s 258 %s :%s\r\n", + hostname, client->nick, loc); +} +void rpl_adminemail(struct client_data *client, const char *email) // 259 +{ + copy_strf(&databuf, ":%s 259 %s :%s\r\n", + hostname, client->nick, email); +} +#if 0 +void rpl_tryagain(struct client_data *client, const char *command) // 263 +{ + copy_strf(&databuf, ":%s 263 %s %s :Please wait a while and try again\r\n", + hostname, client->nick, command); +} +#endif +void rpl_localusers(struct client_data *client, int current, int max) // 266 +{ + copy_strf(&databuf, ":%s 265 %s :Current local users %u, max %u\r\n", + hostname, client->nick, current, max, current, max); +} +void rpl_globalusers(struct client_data *client, int current, int max) // 267 +{ + copy_strf(&databuf, ":%s 266 %s %u %u :Current global users %u, max %u\r\n", + hostname, client->nick, current, max, current, max); +} // 276 RPL_WHOISCERTFP // 300 RPL_NONE // 301 RPL_AWAY @@ -166,7 +227,11 @@ void rpl_topicwhotime(struct client_data *client, struct channel *chan) // 333 // 347 RPL_ENDOFINVEXLIST // 348 RPL_EXCEPTLIST // 349 RPL_ENDOFEXCEPTLIST -// 351 RPL_VERSION +void rpl_version(struct client_data *client, const char *ver, const char *comments) // 351 +{ + copy_strf(&databuf, ":%s 351 %s %s %s :%s\r\n", hostname, client->nick, + ver, hostname, comments); +} int rpl_namreply(struct client_data *client, struct channel *chan, struct client_data *cl) // 353 { if (!cl) { @@ -216,6 +281,14 @@ void rpl_endofnames(struct client_data *client, const char *channel) // 366 // 381 RPL_YOUREOPER // 382 RPL_REHASHING // 391 RPL_TIME +void rpl_time(struct client_data *client, time_t ts) // 391 +{ + // FIXME: 64-bit time_t support + char buf[26]; + strcpy(buf, ctime(&ts)); + buf[24] = '\0'; + copy_strf(&databuf, ":%s 391 %s %s :%s\r\n", hostname, client->nick, ts, buf); +} #if 0 void err_unknownerror(struct client_data *client, const char *command, const char *msg) // 400 { @@ -226,12 +299,10 @@ void err_nosuchnick(struct client_data *client, const char *nick) // 401 { copy_strf(&databuf, ":%s 401 %s %s :No such nick/channel\r\n", hostname, client->nick, nick); } -#if 0 void err_nosuchserver(struct client_data *client, const char *server) // 402 { copy_strf(&databuf, ":%s 402 %s %s :No such server\r\n", hostname, client->nick, server); } -#endif void err_nosuchchannel(struct client_data *client, const char *channel) // 403 { copy_strf(&databuf, ":%s 403 %s %s :No such channel\r\n", hostname, client->nick, channel); diff --git a/ircfmt.h b/ircfmt.h index 91a88f0..cb68b00 100644 --- a/ircfmt.h +++ b/ircfmt.h @@ -20,20 +20,20 @@ void rpl_yourhost(struct client_data *client); // 002 void rpl_created(struct client_data *client); // 003 void rpl_myinfo(struct client_data *client); // 004 void rpl_isupport(struct client_data *client); // 005 -// 010 RPL_BOUNC -// 221 RPL_UMODEIS -// 251 RPL_LUSERCLIENT -// 252 RPL_LUSEROP -// 253 RPL_LUSERUNKNOWN -// 254 RPL_LUSERCHANNELS -// 255 RPL_LUSERME -// 256 RPL_ADMINME -// 257 RPL_ADMINLOC1 -// 258 RPL_ADMINLOC2 -// 259 RPL_ADMINEMAIL -// 263 RPL_TRYAGAIN -// 265 RPL_LOCALUSERS -// 266 RPL_GLOBALUSERS +void rpl_bounce(struct client_data *client, const char *host, const char *port, const char *info); // 010 +void rpl_umodeis(struct client_data *client); // 221 +void rpl_luserclient(struct client_data *client, int users, int invisible, int servers); // 251 +void rpl_luserop(struct client_data *client, int ops); // 252 +void rpl_luserunknown(struct client_data *client, int unk); // 253 +void rpl_luserchannels(struct client_data *client, int channels); // 254 +void rpl_luserme(struct client_data *client, int clients, int servers); // 255 +void rpl_adminme(struct client_data *client); // 256 +void rpl_adminloc1(struct client_data *client, const char *loc); // 257 +void rpl_adminloc2(struct client_data *client, const char *loc); // 258 +void rpl_adminemail(struct client_data *client, const char *email); // 259 +void rpl_tryagain(struct client_data *client, const char *command); // 263 +void rpl_localusers(struct client_data *client, int current, int max); // 266 +void rpl_globalusers(struct client_data *client, int current, int max); // 267 // 276 RPL_WHOISCERTFP // 300 RPL_NONE // 301 RPL_AWAY @@ -68,7 +68,7 @@ void rpl_topicwhotime(struct client_data *client, struct channel *chan); // 333 // 347 RPL_ENDOFINVEXLIST // 348 RPL_EXCEPTLIST // 349 RPL_ENDOFEXCEPTLIST -// 351 RPL_VERSION +void rpl_version(struct client_data *client, const char *ver, const char *comments); // 351 int rpl_namreply(struct client_data *client, struct channel *chan, struct client_data *cl); // 353 void rpl_endofnames(struct client_data *client, const char *channel); // 366 // 364 RPL_LINKS @@ -85,7 +85,7 @@ void rpl_endofnames(struct client_data *client, const char *channel); // 366 // 379 RPL_WHOISMODES // 381 RPL_YOUREOPER // 382 RPL_REHASHING -// 391 RPL_TIME +void rpl_time(struct client_data *client, time_t ts); // 391 void err_unknownerror(struct client_data *client, const char *command, const char *msg); // 400 void err_nosuchnick(struct client_data *client, const char *nick); // 401 void err_nosuchserver(struct client_data *client, const char *server); // 402 diff --git a/main.c b/main.c index e6f8262..fe2638f 100644 --- a/main.c +++ b/main.c @@ -1,3 +1,4 @@ +#include #include "common.h" #include "net.h" #include "irc.h" @@ -182,6 +183,7 @@ int main() { SOCKET listeners[4]; struct tls *listeners_tls[4]; int listener_count = 0; + setlocale(LC_ALL, "C"); puts("[PatchyIRCD]: Starting up..."); fflush(stdout); @@ -228,6 +230,7 @@ int main() { return fprintf(stderr, "tls_server error\n"), 1; if (tls_configure(tls_ctx, tls_cfg) == -1) return fprintf(stderr, "tls_configure: %s\n", tls_error(tls_ctx)), 1; + tls_config_free(tls_cfg); #ifdef SUPPORT_IPV4 serverAddrV4.sin_port = htons(LISTENING_PORT_TLS);