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