#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
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;
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;
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;
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);
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);
#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",
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
// 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) {
// 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
{
{
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);
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
// 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
// 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
+#include <locale.h>
#include "common.h"
#include "net.h"
#include "irc.h"
SOCKET listeners[4];
struct tls *listeners_tls[4];
int listener_count = 0;
+ setlocale(LC_ALL, "C");
puts("[PatchyIRCD]: Starting up...");
fflush(stdout);
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);