summaryrefslogtreecommitdiff
path: root/functions.h
blob: c22d7acb221b3e11b5d218a19543579305e8ff34 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/*
 * This file is part of blabouncer (https://www.blatech.co.uk/l_bratch/blabouncer).
 * Copyright (C) 2019 Luke Bratch <luke@bratch.co.uk>.
 *
 * Blabouncer is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3.
 *
 * Blabouncer is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with blabouncer. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef FUNCTIONS_H_INCLUDED
#define FUNCTIONS_H_INCLUDED

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <stdarg.h>
#include <limits.h>

#include "sockets.h"
#include "structures.h"
#include "replay.h"
#include "config.h"

// getstdin() return codes
#define OK       0
#define NO_INPUT 1
#define TOO_LONG 2

#define DEBUG_CRIT 0
#define DEBUG_SOME 1
#define DEBUG_FULL 2

#define EXCEPT_NONE 0

#define MAXDATASIZE 513 // Maximum number of bytes we can get at once (RFC2812 says 512, plus one for null terminator)
#define MAXCLIENTS 32 // Maximum number of clients that can connect to the bouncer at a time
#define MAXCHANNELS 1024 // Let's assume 1024 is reasonable for now (it's configured per IRCd)
#define MAXRFCNICKLEN 9 // From RFC 1459

#define MAXTOKENS 100 // For strsep string splitting

#define VERSION "0.2-git" // Blabouncer version

// Write debug string to file.
// Debug level is provided by level, set to one of DEBUG_CRIT, DEBUG_SOME or DEBUG_FULL.
// Debug is only written if the global int "debug" is greater than or equal to the level.
void debugprint(int level, char *format, ...);

// Get stdin line with buffer overrun protection
int getstdin(char *prompt, char *buff, size_t sz);

// Append CR-LF to the end of a string (after cleaning up any existing trailing CR or LF)
void appendcrlf(char *string);

// Remove leading colon ':' which is the starting character of a prefix in an IRC message
// If no leading colon present, string is left unchanged.
// "debug" is used to determine whether stripprefix() should produce all debug output,
// used as debug output with stripprefix() can be particularly noisy.
void stripprefix(char *string, int debug);

// Extract final parameter from IRC message, removing the leading colon ':'
void extractfinalparameter(char *string);

// Extract the IRC nick from a prefix
// e.g. given this string:
// ":foo!bar@baz"
// We want to end up with:
// "foo"
// "debug" is used to determine whether extractnickfromprefix() should produce all debug output,
// used as debug output with extractnickfromprefix() can be particularly noisy.
void extractnickfromprefix(char *string, int debug);

// Update an existing nickuserhost string with a new nick
void updatenickuserhost(char *nickuserhost, char *nick);

// Update an existing 001 greeting with a new nickuserhost
void updategreetings(char *greeting001, char *greeting002, char *greeting003, char *greeting004, char *greeting005a, char *greeting005b, char *greeting005c, char *newnickuserhost, char *oldnickuserhost, char *newnick, char *oldnick);

// Return index of requested client FD within the clients array.
// Returns 0 or more on success, or -1 on failure.
// TODO - Use this wherever we are calculating the position (various places) instead of
// duplicating code.
int arrindex(struct client *clients, int clientfd);

// Send whatever string to a specific client by providing the FD
// If "bypass" == 1 then permit sending to client even if unauthenticated (for instance for a CAP LS response)
int sendtoclient(int fd, char *strsrc, struct client *clients, struct settings *settings, int bypass);

// Relay/send message to all clients (optionally except one)
// "except" is used to send to all clients _except_ the fd provided (except = 0 (EXCEPT_NONE) avoids this, i.e. sends to all)
// "except" is really the "sourcefd" and is also used as part of the authentication check - this is messy and they should perhaps be two separate arguments.
int sendtoallclients(struct client *clients, char *strsrc, int except, struct settings *settings);

// Send whatever string to the real IRC server
// Client FD and arrays needed to make sure anything relayed from a client is from an authenticated client.
// clientfd of "0" means trusted, used when we are sending things ourselves that weren't relayed
// from a real client.
int sendtoserver(SSL *server_ssl, char *strsrc, int str_len, int clientfd, struct client *clients, struct settings *settings);

// Disconnect the client fd "fd" by close()ing it and remove
// it from the array of clients.
// Also set its authentication and registration statuses to 0.
// Also set the pending statuses to 0
int disconnectclient(int fd, struct client *clients, struct ircdstate *ircdstate, struct settings *settings, struct clientcodes *clientcodes);

int createchannel(struct channel *channels, struct ircdstate *ircdstate, char *name, char *topic, char *topicwho, char *topicwhen);

int setchanneltopicwhotime(struct channel *channels, int maxchannelcount, char *channelname, char *who, char *when);

int setchanneltopic(struct channel *channels, int maxchannelcount, char *channelname, char *topic);

int getchannelcount(struct channel *channels, int maxchannelcount);

int removechannel(struct channel *channels, int maxchannelcount, char *name);

// Check if we have the NAMES for the channel 'name' already.
// Return the 1 if we do, 0 if we don't, or -1 if there's an error.
int channelgotnames(struct channel *channels, int maxchannelcount, char *name);

// Check if we are in a channel named "name" or not.
// Return 1 if we are, or 0 if not.
int inchannel(struct channel *channels, int maxchannelcount, char *name);

// Returns the array index in the 'channels' array of the channel
// named 'channel'.
// Returns -1 if there was an error.
int channelindex(struct channel *channels, int maxchannelcount, char *name);

// Send the requested number of lines of replay log to the requested client.
// 'sourcefd' is the client to send to, and replayseconds is the number of
// seconds of replay log to replay.
// Returns 1 for success or 0 for failure.
int doreplay(int sourcefd, int replayseconds, struct client *clients, struct settings *settings, struct ircdstate *ircdstate, struct channel *channels);

// Send the auto replay to the requested client, where 'sourcefd' is the client
// to send to.  The type of replay will depend on the user's settings.
// Returns 1 for success or 0 for failure.
int doautoreplay(int sourcefd, struct client *clients, struct settings *settings, struct ircdstate *ircdstate, struct channel *channels);

// Return a count of the number of connected clients
int numclients(struct client *clients);

// Join any channels that were configured to be automatically
// joined in the configuration file.
// Returns 1 on success or 0 on failure.
int joinautochannels(SSL *server_ssl, struct client *clients, struct settings *settings);

// Try to make a new nick if no configured are available or liked by the server
// Do this by sticking a number on the end of the current nick and trying numbers
// 1 through to 9.
void tryautonick(struct ircdstate *ircdstate);

// Exit the program cleanly - tell clients, tell the server, then exit(0)
// Optional quit message string "quitmsg"
// "sourcefd" of 0 means the request didn't come from a client
void cleanexit(SSL *server_ssl, struct client *clients, int sourcefd, struct ircdstate *ircdstate, struct settings *settings, char *quitmsg);

// Re-read the configuration file, setting 'failuremsg' to a failure message on failure.
// Returns 1 on success or 0 on failure.
int rehash(struct settings *settings, char *failuremsg);

// Check the password provided in the string 'str' against what is in
// the settings structure 'settings'.
// Return 0 for password mismatch, or 1 for password match.
int checkpassword(char *password, struct settings *settings);

// Adds a client code to the clientcode structure if it doesn't already exist.
// On success, copy it to the client's clientcode field.
// Returns 1 on adding a new code, 0 if the code already existed, or -1 on error.
int addclientcode(int sourcefd, char *code, struct clientcodes *clientcodes, struct client *clients);

// Sets a given client code as last disconnecting at the current time.
// Returns 1 on success or 0 on failure.
int setclientcodetime(char *code, struct clientcodes *clientcodes);

// Return the timestamp that a given client last disconnected, or 0 on failure.
int getclientcodetime(char *code, struct clientcodes *clientcodes);

// Replace any instances of "find" with "replace" in the string "str"
void replacechar(char *str, char find, char replace);

// Add nick (passed as a :nick!user@host) to channel 'channel'
// Returns 1 on success or 0 on failure
int addnicktochannel(char *nickuserhost, char *channel, struct channel *channels, int maxchannelcount);

// Remove nick(passed as a :nick!user@host) from channel 'channel'
// Returns 1 on success or 0 on failure
int removenickfromchannel(char *nickuserhost, char *channel, struct channel *channels, int maxchannelcount);

// Remove nick (passed as a :nick!user@host) from all channels
// Returns 1 on success or 0 on failure
int removenickfromallchannels(char *nickuserhost, struct channel *channels, int maxchannelcount);

// Update old nick (passed as a :nick!user@host) to 'newnick' in all channels
// Returns 1 on success or 0 on failure
int updatenickinallchannels(char *nickuserhost, char *newnick, struct channel *channels, int maxchannelcount);

// Populate our channels struct with all nicks in a RPL_NAMREPLY
// Returns 1 on success or 0 on failure
int addnamereplytochannel(char *namereply, struct channel *channels, int maxchannelcount);

// Strips all leading prefixes (colons, user modes) from a nick
void stripprefixesfromnick(char *nick);

// Convert the given 'string' into lowercase
void strlower(char *string);
#endif