New config file format
[l2tpns.git] / cluster_slave.c
1 // L2TPNS Cluster Master
2 // $Id: cluster_slave.c,v 1.2 2004-03-05 00:09:03 fred_nerk Exp $
3
4 #include <stdio.h>
5 #include <netinet/in.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <string.h>
9 #include <time.h>
10 #include <errno.h>
11 #include <malloc.h>
12 #include <sys/socket.h>
13 #include <sys/file.h>
14 #include <sys/stat.h>
15 #include <sys/types.h>
16 #include <arpa/inet.h>
17 #include "l2tpns.h"
18 #include "cluster.h"
19 #include "ll.h"
20 #include "util.h"
21
22 // vim: sw=4 ts=8
23
24 extern int cluster_sockfd;
25 extern char hostname[1000];
26 extern ippoolt *ip_address_pool;
27 extern uint32_t vip_address;
28 extern struct configt *config;
29
30 int handle_tunnel(char *buf, int l);
31 int handle_session(char *buf, int l);
32 int handle_hello_response(char *buf, int l);
33
34 int processcluster(char *buf, int l)
35 {
36 char mtype;
37 uint32_t addr;
38
39 log_hex(4, "Cluster receive", buf, l);
40 if (!buf || l <= sizeof(uint32_t)) return 0;
41
42 addr = ntohl(*(uint32_t*)buf);
43 buf += sizeof(uint32_t);
44 l -= sizeof(uint32_t);
45
46 if (addr != vip_address)
47 {
48 log(0, 0, 0, 0, "Received cluster message for VIP %s, which isn't ours\n", inet_toa(addr));
49 }
50
51 mtype = *buf; buf++; l--;
52
53 switch (mtype)
54 {
55 case C_HELLO:
56 break;
57 case C_HELLO_RESPONSE:
58 handle_hello_response(buf, l);
59 break;
60 case C_PING:
61 break;
62 case C_TUNNEL:
63 handle_tunnel(buf, l);
64 break;
65 case C_SESSION:
66 handle_session(buf, l);
67 break;
68 }
69 return mtype;
70
71 return 0;
72 }
73
74 int handle_tunnel(char *buf, int l)
75 {
76 int t;
77
78 // Ignore tunnel message if NOSTATEFILE exists
79 if (config->ignore_cluster_updates)
80 {
81 log(1, 0, 0, 0, "Discarding tunnel message from cluster master.\n", l, sizeof(tunnelt));
82 return 0;
83 }
84
85 t = *(int *)buf;
86 log(1, 0, 0, t, "Receiving tunnel %d from cluster master (%d bytes)\n", t, l);
87 buf += sizeof(int); l -= sizeof(int);
88
89 if (t > MAXTUNNEL)
90 {
91 log(0, 0, 0, t, "Cluster master tried to send tunnel %d, which is bigger than MAXTUNNEL (%d)\n", t, MAXTUNNEL);
92 return 0;
93 }
94
95 if (l != sizeof(tunnelt))
96 {
97 log(1, 0, 0, t, "Discarding bogus tunnel message (%d bytes instead of %d).\n", l, sizeof(tunnelt));
98 return 0;
99 }
100
101 memcpy(&tunnel[t], buf, l);
102 log(3, 0, 0, t, "Cluster master sent tunnel for %s\n", tunnel[t].hostname);
103
104 tunnel[t].controlc = 0;
105 tunnel[t].controls = NULL;
106 tunnel[t].controle = NULL;
107 return 0;
108 }
109
110 int handle_session(char *buf, int l)
111 {
112 int s;
113
114 // Ignore tunnel message if NOSTATEFILE exists
115 if (config->ignore_cluster_updates)
116 {
117 log(1, 0, 0, 0, "Discarding session message from cluster master.\n", l, sizeof(tunnelt));
118 return 0;
119 }
120
121 s = *(int *)buf;
122 log(1, 0, s, 0, "Receiving session %d from cluster master (%d bytes)\n", s, l);
123 buf += sizeof(int); l -= sizeof(int);
124
125 if (s > MAXSESSION)
126 {
127 log(0, 0, s, 0, "Cluster master tried to send session %d, which is bigger than MAXSESSION (%d)\n", s, MAXSESSION);
128 return 0;
129 }
130
131 if (l != sizeof(sessiont))
132 {
133 log(1, 0, s, 0, "Discarding short session message (%d bytes instead of %d).\n", l, sizeof(sessiont));
134 return 0;
135 }
136
137 if (s > 1)
138 {
139 session[s-1].next = session[s].next;
140 }
141
142 if (sessionfree == s)
143 {
144 sessionfree = session[s].next;
145 }
146
147 memcpy(&session[s], buf, l);
148 session[s].tbf = 0;
149 session[s].throttle = 0;
150 if (session[s].opened)
151 {
152 log(2, 0, s, session[s].tunnel, "Cluster master sent active session for user %s\n", session[s].user);
153 sessionsetup(session[s].tunnel, s, 0);
154 if (session[s].ip && session[s].ip != 0xFFFFFFFE)
155 {
156 int x;
157 for (x = 0; x < MAXIPPOOL && ip_address_pool[x].address; x++)
158 {
159 if (ip_address_pool[x].address == session[s].ip)
160 {
161 ip_address_pool[x].assigned = 1;
162 break;
163 }
164 }
165 }
166 }
167 /*
168 if (session[s].servicenet)
169 servicenet_session(s, 1);
170 */
171 return 0;
172 }
173
174 int handle_hello_response(char *buf, int l)
175 {
176 int numtunnels, numsessions;
177
178 /* The cluster master has downed the address, so send another garp */
179 send_garp(vip_address);
180
181 if (!l) return 0;
182
183 if (l < (4 * IL))
184 {
185 log(1, 0, 0, 0, "Cluster master sent invalid hello response: %d bytes instead of %d\n", l, (4 * IL));
186 return 0;
187 }
188 numtunnels = *(int *)(buf + IL * 0);
189 numsessions = *(int *)(buf + IL * 1);
190 if (numtunnels == 0 && numsessions == 0)
191 {
192 log(2, 0, 0, 0, "Cluster master has no state information for us.\n");
193 return 0;
194 }
195 log(2, 0, 0, 0, "The cluster master will send %d tunnels and %d sessions.\n", numtunnels, numsessions);
196 return 0;
197 }
198
199 int cluster_send_session(int s)
200 {
201 char *packet;
202 int len = 0;
203
204 if (!cluster_sockfd) return 1;
205
206 packet = malloc(4096);
207
208 // Hostname
209 len = strlen(hostname);
210 *(char *)packet = len;
211 memcpy((char *)(packet + 1), hostname, len);
212 len++;
213
214 // Session ID
215 *(int *)(packet + len) = s;
216 len += sizeof(int);
217
218 // Session data
219 memcpy((char *)(packet + len), &session[s], sizeof(sessiont));
220 len += sizeof(sessiont);
221
222 cluster_send_message(config->cluster_address, vip_address, C_SESSION, packet, len);
223 free(packet);
224
225 return 1;
226 }
227
228 int cluster_send_tunnel(int t)
229 {
230 char *packet;
231 int len = 0;
232
233 packet = malloc(4096);
234
235 // Hostname
236 len = strlen(hostname);
237 *(char *)packet = len;
238 memcpy((char *)(packet + 1), hostname, len);
239 len++;
240
241 // Tunnel ID
242 *(int *)(packet + len) = t;
243 len += sizeof(int);
244
245 // Tunnel data
246 memcpy((char *)(packet + len), &tunnel[t], sizeof(tunnelt));
247 len += sizeof(tunnelt);
248
249 cluster_send_message(config->cluster_address, vip_address, C_TUNNEL, packet, len);
250 free(packet);
251
252 return 1;
253 }
254
255 int cluster_send_goodbye()
256 {
257 char *packet;
258 int len = 0;
259
260 packet = malloc(4096);
261
262 log(2, 0, 0, 0, "Sending goodbye to cluster master\n");
263 // Hostname
264 len = strlen(hostname);
265 *(char *)packet = len;
266 memcpy((char *)(packet + 1), hostname, len);
267 len++;
268
269 cluster_send_message(config->cluster_address, vip_address, C_GOODBYE, packet, len);
270 free(packet);
271
272 return 1;
273 }
274