]> jfr.im git - irc/evilnet/x3.git/blobdiff - src/opserv.c
make it so that lamers do not affect users above inviteme level in the channel
[irc/evilnet/x3.git] / src / opserv.c
index be3d10b2867d8f6149737f0c55e352dbd0fa74de..cd0617f5be603eff8db26570adbfa9ce8302c18d 100644 (file)
 #include "nickserv.h"
 #include "modcmd.h"
 #include "modules.h"
+#include "proto.h"
 #include "opserv.h"
 #include "timeq.h"
 #include "saxdb.h"
 #include "shun.h"
 
-#include <regex.h>
+#include <tre/regex.h>
 
 #ifdef HAVE_SYS_TIMES_H
 #include <sys/times.h>
 #define KEY_OFFLINE "offline"
 #define KEY_ROUTINGPLAN "routingplan"
 #define KEY_ROUTINGPLAN_OPTIONS "routingplan_options"
+#define KEY_DEFCON1 "DefCon1"
+#define KEY_DEFCON2 "DefCon2"
+#define KEY_DEFCON3 "DefCon3"
+#define KEY_DEFCON4 "DefCon4"
+#define KEY_DEFCON_LEVEL "DefConLevel"
+#define KEY_DEFCON_CHANMODES "DefConChanModes"
+#define KEY_DEFCON_SESSION_LIMIT "DefConSessionLimit"
+#define KEY_DEFCON_TIMEOUT "DefConTimeOut"
+#define KEY_DEFCON_GLOBAL "GlobalOnDefcon"
+#define KEY_DEFCON_GLOBAL_MORE "GlobalOnDefconMore"
+#define KEY_DEFCON_MESSAGE "DefconMessage"
+#define KEY_DEFCON_OFF_MESSAGE "DefConOffMessage"
+#define KEY_DEFCON_GLINE_DURATION "DefConGlineExpire"
+#define KEY_DEFCON_GLINE_REASON "DefConGlineReason"
 
 /* Routing karma values: */
 /* What value we start out with when new servers are added: */
@@ -159,19 +174,30 @@ static const struct message_entry msgtab[] = {
     { "OSMSG_HOP_DONE", "Halfopped the requested lusers." },
     { "OSMSG_HOPALL_DONE", "Halfopped everyone on $b%s$b." },
     { "OSMSG_WHOIS_IDENT",      "%s (%s@%s) from %d.%d.%d.%d" },
-    { "OSMSG_WHOIS_NICK",       "Nick       : %s" },
-    { "OSMSG_WHOIS_HOST",       "Host       : %s@%s" },
-    { "OSMSG_WHOIS_FAKEHOST",   "Fakehost   : %s" },
-    { "OSMSG_WHOIS_CRYPT_HOST", "Crypt Host : %s" },
-    { "OSMSG_WHOIS_CRYPT_IP",   "Crypt IP   : %s" },
-    { "OSMSG_WHOIS_IP",         "Real IP    : %s" },
-    { "OSMSG_WHOIS_MODES",      "Modes      : +%s " },
-    { "OSMSG_WHOIS_INFO",       "Info       : %s" },
-    { "OSMSG_WHOIS_NUMERIC",    "Numnick    : %s" },
-    { "OSMSG_WHOIS_SERVER",     "Server     : %s" },
-    { "OSMSG_WHOIS_NICK_AGE",   "Nick Age   : %s" },
-    { "OSMSG_WHOIS_ACCOUNT",    "Account    : %s" },
-    { "OSMSG_WHOIS_CHANNELS",   "Channels   : %s" },
+    { "OSMSG_WHOIS_NICK",       "Nick         : %s" },
+    { "OSMSG_WHOIS_HOST",       "Host         : %s@%s" },
+    { "OSMSG_WHOIS_FAKEHOST",   "Fakehost     : %s" },
+    { "OSMSG_WHOIS_CRYPT_HOST", "Crypt Host   : %s" },
+    { "OSMSG_WHOIS_CRYPT_IP",   "Crypt IP     : %s" },
+    { "OSMSG_WHOIS_IP",         "Real IP      : %s" },
+    { "OSMSG_WHOIS_COUNTRY",    "Country      : %s" },
+   { "OSMSG_WHOIS_COUNTRY_CODE","Country Code : %s" },
+    { "OSMSG_WHOIS_CITY",       "City         : %s" },
+    { "OSMSG_WHOIS_REGION",     "Region/State : %s" },
+    { "OSMSG_WHOIS_POSTAL_CODE","Postal Code  : %s" },
+    { "OSMSG_WHOIS_LATITUDE",   "Latitude     : %f" },
+    { "OSMSG_WHOIS_LONGITUDE",  "Longitude    : %f" },
+    { "OSMSG_WHOIS_MAP",        "Map          : %s" },
+    { "OSMSG_WHOIS_DMA_CODE",   "DMA Code     : %d" },
+    { "OSMSG_WHOIS_AREA_CODE",  "Area Code    : %d" },
+    { "OSMSG_WHOIS_MODES",      "Modes        : +%s " },
+    { "OSMSG_WHOIS_INFO",       "Info         : %s" },
+    { "OSMSG_WHOIS_NUMERIC",    "Numnick      : %s" },
+    { "OSMSG_WHOIS_SERVER",     "Server       : %s" },
+    { "OSMSG_WHOIS_NICK_AGE",   "Nick Age     : %s" },
+    { "OSMSG_WHOIS_ACCOUNT",    "Account      : %s" },
+    { "OSMSG_WHOIS_PRIVS",      "IRCd Privs   : %s" },
+    { "OSMSG_WHOIS_CHANNELS",   "Channels     : %s" },
     { "OSMSG_WHOIS_HIDECHANS",  "Channel list omitted for your sanity." },
     { "OSMSG_UNBAN_DONE", "Ban(s) removed from channel %s." },
     { "OSMSG_CHANNEL_VOICED", "All users on %s voiced." },
@@ -288,7 +314,7 @@ static const struct message_entry msgtab[] = {
     { "OSMSG_ROUTINGPLAN_NAME",  "$b%s:$b" },
     { "OSMSG_ROUTINGPLAN_SERVER","      %s:%d <-- %s[%d/%s] (%s)" }, 
     { "OSMSG_ADDPLAN_SUCCESS", "Added new routing plan '%s'." },
-    { "OSMSG_ADDPLAN_FAILURE", "Could not add new plan '%s' (does it already exist?)." },
+    { "OSMSG_ADDPLAN_FAILED", "Could not add new plan '%s' (does it already exist?)." },
     { "OSMSG_INVALID_PLAN", "That routing plan name is not valid." },
     { "OSMSG_PLAN_DELETED", "The routing plan was sucessfully deleted." },
     { "OSMSG_PLAN_NOT_FOUND", "There is no routing plan called '%s'." },
@@ -362,11 +388,43 @@ static const struct message_entry msgtab[] = {
     { "OSMSG_INVALID_REGEX", "Invalid regex: %s: %s (%d)" },
     { "OSMSG_TRACK_DISABLED", "Tracking is not currently compiled into X3" },
     { "OSMSG_MAXUSERS_RESET", "Max clients has been reset to $b%d$b" },
+
+    { "OSMSG_DEFCON_INVALID", "DefCon level %d is invalid, please choose a value between 1 and 5" },
+    { "OSMSG_DEFCON_ALLOWING_ALL", "DefCon is at level 5 and allowing everything" },
+    { "OSMSG_DEFCON_DISALLOWING", "DefCon is at level %d and enforcing:" },
+    { "OSMSG_DEFCON_NO_NEW_CHANNELS", "No Channel Registrations" },
+    { "OSMSG_DEFCON_NO_NEW_NICKS", "No Nickname/Account Registrations" },
+    { "OSMSG_DEFCON_NO_MODE_CHANGE", "No Channel Mode Changes" },
+    { "OSMSG_DEFCON_NO_NEW_CLIENTS", "No New Clients" },
+    { "OSMSG_DEFCON_FORCE_CHANMODES", "Forcing Channel Mode(s): %s" },
+    { "OSMSG_DEFCON_REDUCE_SESSION", "Forcing Reduced Session: %d" },
+    { "OSMSG_DEFCON_OPER_ONLY", "Allowing Services Communication With Opers Only" },
+    { "OSMSG_DEFCON_SILENT_OPER_ONLY", "Allowing Services Communication With Opers Only AND Silently Ignoring Regular Users" },
+    { "OSMSG_DEFCON_GLINE_NEW_CLIENTS", "Glining New Clients" },
+    { "OSMSG_DEFCON_SHUN_NEW_CLIENTS", "Shunning New Clients" },
+    { "OSMSG_DEFCON_NO_NEW_MEMOS", "Disallowing New Memos" },
+
+    { "OSMSG_PRIV_UNKNOWN", "Unknown privilege flag %s, see /msg $O HELP PRIVFLAGS for a flag list" },
+    { "OSMSG_PRIV_SET",     "Privilege flag %s has been %sset" },
+
     { NULL, NULL }
 };
 
 #define OPSERV_SYNTAX() svccmd_send_help_brief(user, opserv, cmd)
 
+int DefConLevel = 5;
+int DefCon[6];
+int DefConTimeOut;
+int GlobalOnDefcon = 0;
+int GlobalOnDefconMore = 0;
+int DefConGlineExpire;
+int DefConModesSet = 0;
+unsigned int DefConSessionLimit;
+char *DefConChanModes;
+char *DefConGlineReason;
+char *DefConMessage;
+char *DefConOffMessage;
+
 extern void add_track_user(struct userNode *user);
 typedef int (*discrim_search_func)(struct userNode *match, void *extra);
 
@@ -524,6 +582,212 @@ opserv_free_user_alert(void *data)
 #define opserv_alert(format...) do { if (opserv_conf.alert_channel) send_channel_notice(opserv_conf.alert_channel , opserv , ## format); } while (0)
 
 
+char *defconReverseModes(const char *modes)
+{
+    char *newmodes = NULL;
+    unsigned int i = 0;
+    if (!modes) {
+        return NULL;
+    }
+    if (!(newmodes = malloc(sizeof(char) * strlen(modes) + 1))) {
+        return NULL;
+    }
+    for (i = 0; i < strlen(modes); i++) {
+        if (modes[i] == '+')
+            newmodes[i] = '-';
+        else if (modes[i] == '-')
+            newmodes[i] = '+';
+        else
+            newmodes[i] = modes[i];
+    }
+    newmodes[i] = '\0';
+    return newmodes;
+}
+
+int checkDefCon(int level)
+{
+    return DefCon[DefConLevel] & level;
+}
+
+void showDefConSettings(struct userNode *user, struct svccmd *cmd)
+{
+    if (DefConLevel == 5) {
+        reply("OSMSG_DEFCON_ALLOWING_ALL");
+        return;
+    } else
+        reply("OSMSG_DEFCON_DISALLOWING", DefConLevel);
+
+    if (checkDefCon(DEFCON_NO_NEW_CHANNELS))
+        reply("OSMSG_DEFCON_NO_NEW_CHANNELS");
+
+    if (checkDefCon(DEFCON_NO_NEW_NICKS))
+        reply("OSMSG_DEFCON_NO_NEW_NICKS");
+
+    if (checkDefCon(DEFCON_NO_MODE_CHANGE))
+        reply("OSMSG_DEFCON_NO_MODE_CHANGE");
+
+    if (checkDefCon(DEFCON_FORCE_CHAN_MODES) && (DefConChanModes))
+        reply("OSMSG_DEFCON_FORCE_CHANMODES", DefConChanModes);
+
+    if (checkDefCon(DEFCON_REDUCE_SESSION))
+        reply("OSMSG_DEFCON_REDUCE_SESSION", DefConSessionLimit);
+
+    if (checkDefCon(DEFCON_NO_NEW_CLIENTS))
+        reply("OSMSG_DEFCON_NO_NEW_CLIENTS");
+
+    if (checkDefCon(DEFCON_OPER_ONLY))
+        reply("OSMSG_DEFCON_OPER_ONLY");
+
+    if (checkDefCon(DEFCON_SILENT_OPER_ONLY))
+        reply("OSMSG_DEFCON_SILENT_OPER_ONLY");
+
+    if (checkDefCon(DEFCON_GLINE_NEW_CLIENTS))
+        reply("OSMSG_DEFCON_GLINE_NEW_CLIENTS");
+
+    if (checkDefCon(DEFCON_SHUN_NEW_CLIENTS))
+        reply("OSMSG_DEFCON_SHUN_NEW_CLIENTS");
+
+    if (checkDefCon(DEFCON_NO_NEW_MEMOS))
+        reply("OSMSG_DEFCON_NO_NEW_MEMOS");
+
+    return;
+}
+
+void do_mass_mode(char *modes)
+{
+    dict_iterator_t it;
+
+    if (!modes)
+        return;
+
+    for (it = dict_first(channels); it; it = iter_next(it)) {
+        struct chanNode *chan = iter_data(it);
+
+        irc_mode(opserv, chan, modes);
+    }
+
+}
+
+void DefConProcess(struct userNode *user)
+{
+    char *newmodes;
+
+    if (GlobalOnDefcon)
+        global_message_args(MESSAGE_RECIPIENT_LUSERS, "DEFCON_NETWORK_CHANGED", DefConLevel);
+
+    if (GlobalOnDefconMore && GlobalOnDefcon)
+        global_message(MESSAGE_RECIPIENT_LUSERS, DefConMessage);
+
+    if ((DefConLevel == 5) && !GlobalOnDefconMore && !GlobalOnDefcon)
+        global_message(MESSAGE_RECIPIENT_LUSERS, DefConOffMessage);
+
+    if (user)
+       global_message_args(MESSAGE_RECIPIENT_OPERS, "DEFCON_OPER_LEVEL_CHANGE", user->nick, DefConLevel);
+    else
+       global_message_args(MESSAGE_RECIPIENT_OPERS, "DEFCON_TIMEOUT_LEVEL_CHANGE", DefConLevel);
+
+    if (checkDefCon(DEFCON_FORCE_CHAN_MODES)) {
+        if (DefConChanModes && !DefConModesSet) {
+            if (DefConChanModes[0] == '+' || DefConChanModes[0] == '-') {
+                do_mass_mode(DefConChanModes);
+                DefConModesSet = 1;
+            }
+        }
+    } else {
+        if (DefConChanModes && (DefConModesSet != 0)) {
+            if (DefConChanModes[0] == '+' || DefConChanModes[0] == '-') {
+                if ((newmodes = defconReverseModes(DefConChanModes))) {
+                    do_mass_mode(newmodes);
+                    free(newmodes);
+                }
+                DefConModesSet = 0;
+            }
+        }
+    }
+
+    return;
+}
+
+void
+defcon_timeout(UNUSED_ARG(void *data))
+{
+    DefConLevel = 5;
+    DefConProcess(NULL);
+}
+
+static MODCMD_FUNC(cmd_defcon)
+{
+    if ((argc < 2) || (atoi(argv[1]) == DefConLevel)) {
+        showDefConSettings(user, cmd);
+        return 1;
+    }
+
+    if ((atoi(argv[1]) < 1) || (atoi(argv[1]) > 5)) {
+        reply("OSMSG_DEFCON_INVALID", atoi(argv[1]));
+        return 0;
+    }
+
+    DefConLevel = atoi(argv[1]);
+    showDefConSettings(user, cmd);
+
+    if (DefConTimeOut > 0) {
+        timeq_del(0, defcon_timeout, NULL, TIMEQ_IGNORE_DATA & TIMEQ_IGNORE_WHEN);
+        timeq_add(now + DefConTimeOut, defcon_timeout, NULL);
+    }
+
+    DefConProcess(user);
+    return 1;
+}
+
+/* TODO
+static MODCMD_FUNC(cmd_privallow)
+{
+//privallow servername/username +/-flag (global is set in conf)
+}
+
+static MODCMD_FUNC(cmd_privdissallow)
+{
+//privdisallow servername/username +/-flag (global is set in conf)
+}
+
+static MODCMD_FUNC(cmd_privlist)
+{
+//privlist servername/user (global with none)
+}
+*/
+
+static MODCMD_FUNC(cmd_privset)
+{
+    struct userNode *target;
+    char *flag;
+    int add = PRIV_ADD;
+
+    flag = argv[2];
+    if (*flag == '-') {
+        add = PRIV_DEL;
+        flag++;    
+    } else if (*flag == '+') {
+        add = PRIV_ADD;
+        flag++;
+    }
+
+    target = GetUserH(argv[1]);
+    if (!target) {
+        reply("MSG_NICK_UNKNOWN", argv[1]);
+        return 0;
+    }
+
+    if (check_priv(flag)) {
+        irc_privs(target, flag, add);
+        reply("OSMSG_PRIV_SET", argv[2], (add == 1) ? "" : "un");
+    } else {
+        reply("OSMSG_PRIV_UNKNOWN", argv[2]);
+        return 0;
+    }
+
+    return 1;
+}
+
 /* A lot of these commands are very similar to what ChanServ can do,
  * but OpServ can do them even on channels that aren't registered.
  */
@@ -667,9 +931,7 @@ static MODCMD_FUNC(cmd_warn)
     dict_insert(opserv_chan_warn, strdup(argv[1]), reason);
     reply("OSMSG_WARN_ADDED", argv[1], reason);
     if (dict_find(channels, argv[1], NULL)) {
-        message = alloca(strlen(reason) + strlen(argv[1]) + 55);
-        sprintf(message, "Channel activity warning for channel %s: %s", argv[1], reason);
-        global_message(MESSAGE_RECIPIENT_OPERS, message);
+        global_message_args(MESSAGE_RECIPIENT_OPERS, "OSMSG_CHANNEL_ACTIVITY_WARN" argv[1], reason);
     }
     return 1;
 }
@@ -1558,6 +1820,32 @@ static MODCMD_FUNC(cmd_whois)
     reply("OSMSG_WHOIS_CRYPT_HOST", target->crypthost);
     reply("OSMSG_WHOIS_CRYPT_IP", target->cryptip);
     reply("OSMSG_WHOIS_IP", irc_ntoa(&target->ip));
+
+    if (target->city) {
+        reply("OSMSG_WHOIS_COUNTRY", target->country_name);
+        reply("OSMSG_WHOIS_COUNTRY_CODE", target->country_code);
+        reply("OSMSG_WHOIS_CITY", target->city);
+        reply("OSMSG_WHOIS_REGION", target->region);
+
+        reply("OSMSG_WHOIS_POSTAL_CODE", target->postal_code);
+        reply("OSMSG_WHOIS_LATITUDE", target->latitude);
+        reply("OSMSG_WHOIS_LONGITUDE", target->longitude);
+        /* Only show a map url if we have a city, latitude and longitude.
+         * Theres not much point of latitude and longitude coordinates are
+         * returned but no city, the coordinates are useless.
+         */
+        if (target->latitude && target->longitude && target->city) {
+            char map_url[MAXLEN];
+            snprintf(map_url, sizeof(map_url), "http://www.mapquest.com/maps/map.adp?searchtype=address&formtype=address&latlongtype=decimal&latitude=%f&longitude=%f",
+                     target->latitude, target->longitude);
+            reply("OSMSG_WHOIS_MAP", map_url);
+        }
+        reply("OSMSG_WHOIS_DMA_CODE", target->dma_code);
+        reply("OSMSG_WHOIS_AREA_CODE", target->area_code);
+    } else if (target->country_name) {
+        reply("OSMSG_WHOIS_COUNTRY", target->country_name);
+    }
+  
     if (target->modes) {
         bpos = 0;
 #define buffer_cat(str) (herelen = strlen(str), memcpy(buffer+bpos, str, herelen), bpos += herelen)
@@ -1587,6 +1875,9 @@ static MODCMD_FUNC(cmd_whois)
 #endif
     reply("OSMSG_WHOIS_SERVER", target->uplink->name);
     reply("OSMSG_WHOIS_ACCOUNT", (target->handle_info ? target->handle_info->handle : "Not authenticated"));
+
+    reply("OSMSG_WHOIS_PRIVS", client_report_privs(target));
+
     intervalString(buffer, now - target->timestamp, user->handle_info);
     reply("OSMSG_WHOIS_NICK_AGE", buffer);
     if (target->channels.used <= MAX_CHANNELS_WHOIS)
@@ -2172,12 +2463,33 @@ opserv_new_user_check(struct userNode *user)
         }
     }
 
+    if (checkDefCon(DEFCON_NO_NEW_CLIENTS)) {
+        irc_kill(opserv, user, DefConGlineReason);
+        return 0;
+    }
+
+    if ( (checkDefCon(DEFCON_GLINE_NEW_CLIENTS) || checkDefCon(DEFCON_SHUN_NEW_CLIENTS)) && !IsOper(user)) {
+        char target[IRC_NTOP_MAX_SIZE + 3] = { '*', '@', '\0' };
+
+        strcpy(target + 2, user->hostname);
+        if (checkDefCon(DEFCON_GLINE_NEW_CLIENTS))
+            gline_add(opserv->nick, target, DefConGlineExpire, DefConGlineReason, now, 1, 0);
+        else if (checkDefCon(DEFCON_SHUN_NEW_CLIENTS))
+            shun_add(opserv->nick, target, DefConGlineExpire, DefConGlineReason, now, 1);
+          
+        return 0;
+    }
+
     /* Only warn or G-line if there's an untrusted max and their IP is sane. */
     if (opserv_conf.untrusted_max
         && irc_in_addr_is_valid(user->ip)
         && !irc_in_addr_is_loopback(user->ip)) {
         struct trusted_host *th = dict_find(opserv_trusted_hosts, addr, NULL);
         unsigned int limit = th ? th->limit : opserv_conf.untrusted_max;
+
+        if (checkDefCon(DEFCON_REDUCE_SESSION) && !th)
+            limit = DefConSessionLimit;
+
         if (!limit) {
             /* 0 means unlimited hosts */
         } else if (ohi->clients.used == limit) {
@@ -2269,9 +2581,7 @@ opserv_channel_check(struct chanNode *newchan)
     }
     /*
     if ((warning = dict_find(opserv_chan_warn, newchan->name, NULL))) {
-        char message[MAXLEN];
-        snprintf(message, sizeof(message), "Channel activity warning for channel %s: %s", newchan->name, warning);
-        global_message(MESSAGE_RECIPIENT_OPERS, message);
+        global_message_args(MESSAGE_RECIPIENT_OPERS, "OSMSG_CHANNEL_ACTIVITY_WARN", newchan->name, warning);
     }
     */
 
@@ -2755,6 +3065,10 @@ routing_connect_server(char *server, int port, struct server *to)
 
     wc->server = strdup(server);
     wc->target = strdup(to->name);
+    /* Just to make sure there isn't one left hanging
+     * if 2 connections are attempted at once.. 
+     * */
+    routing_delete_connect_timer(server);
     dict_insert(opserv_waiting_connections, strdup(server), wc);
     timeq_add(now + ROUTING_CONNECT_TIMEOUT, routing_connect_timeout, wc);
 
@@ -5989,6 +6303,48 @@ opserv_conf_read(void)
     policer_params_set(pp, "drain-rate", "3");
     if ((child = database_get_data(conf_node, KEY_NEW_USER_POLICER, RECDB_OBJECT)))
         dict_foreach(child, set_policer_param, pp);
+
+    /* Defcon configuration */
+    DefCon[0] = 0;
+    str = database_get_data(conf_node, KEY_DEFCON1, RECDB_QSTRING);
+    DefCon[1] = str ? atoi(str) : 415;
+    str = database_get_data(conf_node, KEY_DEFCON2, RECDB_QSTRING);
+    DefCon[2] = str ? atoi(str) : 159;
+    str = database_get_data(conf_node, KEY_DEFCON3, RECDB_QSTRING);
+    DefCon[3] = str ? atoi(str) : 31;
+    str = database_get_data(conf_node, KEY_DEFCON4, RECDB_QSTRING);
+    DefCon[4] = str? atoi(str) : 23;
+    DefCon[5] = 0;
+
+    str = database_get_data(conf_node, KEY_DEFCON_LEVEL, RECDB_QSTRING);
+    DefConLevel = str ? atoi(str) : 5;
+
+    str = database_get_data(conf_node, KEY_DEFCON_CHANMODES, RECDB_QSTRING);
+    DefConChanModes = str ? strdup(str) : "+r";
+
+    str = database_get_data(conf_node, KEY_DEFCON_SESSION_LIMIT, RECDB_QSTRING);
+    DefConSessionLimit = str ? atoi(str) : 2;
+
+    str = database_get_data(conf_node, KEY_DEFCON_TIMEOUT, RECDB_QSTRING);
+    DefConTimeOut = str ? ParseInterval(str) : 900;
+
+    str = database_get_data(conf_node, KEY_DEFCON_GLINE_DURATION, RECDB_QSTRING);
+    DefConGlineExpire = str ? ParseInterval(str) : 300;
+
+    str = database_get_data(conf_node, KEY_DEFCON_GLOBAL, RECDB_QSTRING);
+    GlobalOnDefcon = str ? atoi(str) : 0;
+
+    str = database_get_data(conf_node, KEY_DEFCON_GLOBAL_MORE, RECDB_QSTRING);
+    GlobalOnDefconMore = str ? atoi(str) : 0;
+
+    str = database_get_data(conf_node, KEY_DEFCON_MESSAGE, RECDB_QSTRING);
+    DefConMessage = str ? strdup(str) : "Put your message to send your users here. Dont forget to uncomment GlobalOnDefconMore";
+
+    str = database_get_data(conf_node, KEY_DEFCON_OFF_MESSAGE, RECDB_QSTRING);
+    DefConOffMessage = str? strdup(str) : "Services are now back to normal, sorry for any inconvenience";
+
+    str = database_get_data(conf_node, KEY_DEFCON_GLINE_REASON, RECDB_QSTRING);
+    DefConGlineReason = str ? strdup(str) : "This network is currently not accepting connections, please try again later";
 }
 
 /* lame way to export opserv_conf value to nickserv.c ... */
@@ -6097,6 +6453,7 @@ init_opserv(const char *nick)
     opserv_define_func("DELTRUST", cmd_deltrust, 800, 0, 2);
     opserv_define_func("DEOP", cmd_deop, 100, 2, 2);
     opserv_define_func("DEOPALL", cmd_deopall, 400, 2, 0);
+    opserv_define_func("DEFCON", cmd_defcon, 900, 0, 0);
     opserv_define_func("DEHOP", cmd_dehop, 100, 2, 2);
     opserv_define_func("DEHOPALL", cmd_dehopall, 400, 2, 0);
     opserv_define_func("DEVOICEALL", cmd_devoiceall, 300, 2, 0);
@@ -6131,6 +6488,7 @@ init_opserv(const char *nick)
     opserv_define_func("HOP", cmd_hop, 100, 2, 2);
     opserv_define_func("HOPALL", cmd_hopall, 400, 2, 0);
     opserv_define_func("MAP", cmd_stats_links, 0, 0, 0);
+    opserv_define_func("PRIVSET", cmd_privset, 900, 0, 3);
     opserv_define_func("PART", cmd_part, 601, 0, 2);
     opserv_define_func("QUERY", cmd_query, 0, 0, 0);
     opserv_define_func("RAW", cmd_raw, 999, 0, 2);