first version of the LAC functionality
[l2tpns.git] / l2tplac.c
1 /*
2 * Add functionality "LAC" to l2tpns.
3 * Used to forward a ppp session to another "LNS".
4 */
5 #include <errno.h>
6 #include <string.h>
7
8 #include "md5.h"
9 #include "l2tpns.h"
10 #include "util.h"
11
12 #include "l2tplac.h"
13
14 /* sequence diagram: Client <--> LAC <--> LNS1 <--> LNS2
15 *
16 * LCP Negotiation
17 * Client <-------------------> LAC
18 * Challenge (CHAP/PAP)
19 * Client <-------------------> LAC
20 * SCCRQ
21 * LAC --------------------> LNS1 (Tunnel Open)
22 * SCCRP
23 * LAC <-------------------- LNS1 (Tunnel Open)
24 * SCCCN
25 * LAC --------------------> LNS1 (Tunnel Open)
26 * ZLB
27 * LAC <-------------------- LNS1 (Tunnel Open)
28 * ICRQ
29 * LAC --------------------> LNS1 (Session Open)
30 * ICRP
31 * LAC <-------------------- LNS1 (Session Open)
32 * ICCN
33 * LAC --------------------> LNS1 (Session Open)
34 * ZLB
35 * LAC <-------------------- LNS1 (Session Open)
36 * LCP Negotiation
37 * Client <---------------------------------------------> LNS1
38 * Challenge (CHAP/PAP)
39 * Client <---------------------------------------------> LNS1
40 * SCCRQ
41 * LNS1 --------------------> LNS2 (Tunnel Open)
42 * SCCRP
43 * LNS1 <-------------------- LNS2 (Tunnel Open)
44 * SCCCN
45 * LNS1 --------------------> LNS2 (Tunnel Open)
46 * ZLB
47 * LNS1 <-------------------- LNS2 (Tunnel Open)
48 * ICRQ
49 * LNS1 --------------------> LNS2 (Session Open)
50 * ICRP
51 * LNS1 <-------------------- LNS2 (Session Open)
52 * ICCN
53 * LNS1 --------------------> LNS2 (Session Open)
54 * ZLB
55 * LNS1 <-------------------- LNS2 (Session Open)
56 * LCP Negotiation
57 * Client <------------------------------------------------------------------------> LNS2
58 * PAP/CHAP Authentification
59 * Client <------------------------------------------------------------------------> LNS2
60 * DATA (ppp)
61 * Client <------------------------------------------------------------------------> LNS2
62 * */
63
64 // Limits
65 #define MAXRLNSTUNNEL 101
66
67 typedef uint16_t confrlnsidt;
68
69 /*
70 * Possible configrlns states
71 * TUNNELFREE -> TUNNELOPEN -> TUNNELDIE -> TUNNELFREE
72 */
73 enum
74 {
75 CONFRLNSFREE = 0, // Not in use
76 CONFRLNSSET // Config Set
77 };
78
79 // struct remote lns
80 typedef struct
81 {
82 tunnelidt tid; // near end tunnel ID
83 int state; // conf state (tunnelstate enum)
84 in_addr_t ip; // Ip for far end
85 uint16_t port; // port for far end
86 hasht auth; // request authenticator
87 char strmaskuser[MAXUSER];
88 char l2tp_secret[64]; // L2TP shared secret
89 }
90 configrlns;
91
92 configrlns *pconfigrlns = NULL; // Array of tunnel structures.
93
94 // Init data structures
95 void initremotelnsdata()
96 {
97 confrlnsidt i;
98
99 if ( !(pconfigrlns = shared_malloc(sizeof(pconfigrlns[0]) * MAXRLNSTUNNEL)) )
100 {
101 LOG(0, 0, 0, "Error doing malloc for tunnels lac: %s\n", strerror(errno));
102 exit(1);
103 }
104
105 memset(pconfigrlns, 0, sizeof(pconfigrlns[0]) * MAXRLNSTUNNEL);
106
107 // Mark all the tunnels as undefined (waiting to be filled in by a download).
108 for (i = 1; i < MAXRLNSTUNNEL; i++)
109 pconfigrlns[i].state = CONFRLNSFREE; // mark it as not filled in.
110
111 config->highest_rlnsid = 0;
112 }
113
114 // Check if must be forwarded to another LNS
115 int forwardtolns(sessionidt s, char * puser)
116 {
117 tunnelidt t;
118 confrlnsidt i;
119
120 for (i = 1; i <= config->highest_rlnsid ; ++i)
121 {
122 if ( NULL != strstr(puser, pconfigrlns[i].strmaskuser))
123 {
124 t = pconfigrlns[i].tid;
125
126 if ((t != 0) && (tunnel[t].ip != pconfigrlns[i].ip))
127 {
128 pconfigrlns[i].tid = t = 0;
129 LOG(1, 0, t, "Tunnel ID inconsistency\n");
130 }
131
132 if (t == 0)
133 {
134 if (main_quit == QUIT_SHUTDOWN) return 0;
135
136 // Start Open Tunnel
137 if (!(t = lac_new_tunnel()))
138 {
139 LOG(1, 0, 0, "No more tunnels\n");
140 STAT(tunnel_overflow);
141 return 0;
142 }
143 lac_tunnelclear(t);
144 tunnel[t].ip = pconfigrlns[i].ip;
145 tunnel[t].port = pconfigrlns[i].port;
146 tunnel[t].window = 4; // default window
147 STAT(tunnel_created);
148 LOG(1, 0, t, "New (REMOTE LNS) tunnel to %s:%u ID %u\n", fmtaddr(htonl(tunnel[t].ip), 0), tunnel[t].port, t);
149
150 random_data(pconfigrlns[i].auth, sizeof(pconfigrlns[i].auth));
151
152 pconfigrlns[i].tid = t;
153
154 lac_send_SCCRQ(t, pconfigrlns[i].auth, sizeof(pconfigrlns[i].auth));
155 }
156 else if (tunnel[t].state == TUNNELOPEN)
157 {
158 if (main_quit != QUIT_SHUTDOWN)
159 {
160 /**********************/
161 /** Open New session **/
162 /**********************/
163 sessionidt new_sess = sessionfree;
164
165 sessionfree = session[new_sess].next;
166 memset(&session[new_sess], 0, sizeof(session[new_sess]));
167
168 if (new_sess > config->cluster_highest_sessionid)
169 config->cluster_highest_sessionid = new_sess;
170
171 session[new_sess].opened = time_now;
172 session[new_sess].tunnel = t;
173 session[new_sess].last_packet = session[s].last_data = time_now;
174
175 session[new_sess].ppp.phase = Establish;
176 session[new_sess].ppp.lcp = Starting;
177
178 // Sent ICRQ Incoming-call-request
179 lac_send_ICRQ(t, new_sess);
180
181 // Set session to forward to another LNS
182 session[s].forwardtosession = new_sess;
183 session[new_sess].forwardtosession = s;
184
185 STAT(session_created);
186 }
187 else
188 {
189 lac_tunnelshutdown(t, "Shutting down", 6, 0, 0);
190 pconfigrlns[i].tid = 0;
191 }
192 }
193 else
194 {
195 /** TODO **/
196 LOG(1, 0, t, "(REMOTE LNS) tunnel is not open\n");
197 }
198
199 return 1;
200 }
201 }
202
203 return 0;
204 }
205
206 static tunnelidt getidrlns(tunnelidt t)
207 {
208 confrlnsidt idrlns;
209
210 for (idrlns = 1; idrlns <= config->highest_rlnsid ; ++idrlns)
211 {
212 if (pconfigrlns[idrlns].tid == t) return idrlns;
213 }
214
215 return 0;
216 }
217
218 int istunneltolns(tunnelidt t)
219 {
220 confrlnsidt idrlns;
221
222 for (idrlns = 1; idrlns <= config->highest_rlnsid ; ++idrlns)
223 {
224 if (pconfigrlns[idrlns].tid == t) return 1;
225 }
226
227 return 0;
228 }
229
230 void calc_lac_auth(tunnelidt t, uint8_t id, uint8_t *out)
231 {
232 MD5_CTX ctx;
233 confrlnsidt idrlns;
234
235 idrlns = getidrlns(t);
236
237 MD5_Init(&ctx);
238 MD5_Update(&ctx, &id, 1);
239 MD5_Update(&ctx, pconfigrlns[idrlns].l2tp_secret, strlen(pconfigrlns[idrlns].l2tp_secret));
240 MD5_Update(&ctx, pconfigrlns[idrlns].auth, 16);
241 MD5_Final(out, &ctx);
242 }
243
244 // Forward session to external LNS
245 int session_forward_tolns(uint8_t *buf, int len, sessionidt sess, uint16_t proto)
246 {
247 uint16_t t = 0, s = 0;
248 uint8_t *p = buf + 2; // First word L2TP options
249
250 s = session[sess].forwardtosession;
251 if (session[s].forwardtosession != sess)
252 {
253 LOG(0, sess, session[sess].tunnel, "Link Session (%u) broken\n", s);
254 return 0;
255 }
256
257 t = session[s].tunnel;
258 if (t >= MAXTUNNEL)
259 {
260 LOG(1, s, t, "Session with invalid tunnel ID\n");
261 return 0;
262 }
263
264 if (*buf & 0x40)
265 { // length
266 p += 2;
267 }
268
269 *(uint16_t *) p = htons(tunnel[t].far); // tunnel
270 p += 2;
271 *(uint16_t *) p = htons(session[s].far); // session
272 p += 2;
273
274 if (*buf & 0x08)
275 { // ns/nr
276 *(uint16_t *) p = htons(tunnel[t].ns); // sequence
277 p += 2;
278 *(uint16_t *) p = htons(tunnel[t].nr); // sequence
279 p += 2;
280 }
281
282 if ((proto == PPPIP) || (proto == PPPMP) ||(proto == PPPIPV6 && config->ipv6_prefix.s6_addr[0]))
283 {
284 session[sess].last_packet = session[sess].last_data = time_now;
285 }
286 else
287 session[sess].last_packet = time_now;
288
289 tunnelsend(buf, len, t); // send it...
290
291 return 1;
292 }
293
294 int addremotelns(char *mask, char *IP_RemoteLNS, char *Port_RemoteLNS, char *SecretRemoteLNS)
295 {
296 confrlnsidt idrlns;
297
298 for (idrlns = 1; idrlns < MAXRLNSTUNNEL; ++idrlns)
299 {
300 if (pconfigrlns[idrlns].state == CONFRLNSFREE)
301 {
302 snprintf((char *) pconfigrlns[idrlns].strmaskuser, sizeof(pconfigrlns[idrlns].strmaskuser), "%s", mask);
303 pconfigrlns[idrlns].ip = ntohl(inet_addr(IP_RemoteLNS));
304 pconfigrlns[idrlns].port = atoi(Port_RemoteLNS);
305 snprintf((char *) pconfigrlns[idrlns].l2tp_secret, sizeof(pconfigrlns[idrlns].l2tp_secret), "%s", SecretRemoteLNS);
306
307 config->highest_rlnsid = idrlns;
308
309 pconfigrlns[idrlns].state = CONFRLNSSET;
310
311 LOG(1, 0, 0, "New Remote LNS conf (count %u) mask:%s IP:%s Port:%u l2tpsecret:*****\n", idrlns,
312 pconfigrlns[idrlns].strmaskuser, fmtaddr(htonl(pconfigrlns[idrlns].ip), 0),
313 pconfigrlns[idrlns].port);
314
315 return 1;
316 }
317 }
318
319 LOG(0, 0, 0, "No more Remote LNS Conf Free\n");
320
321 return 0;
322 }