Update changelog
[l2tpns.git] / l2tplac.c
1 /*
2 * Fernando ALVES 2013
3 * Add functionality "LAC" to l2tpns.
4 * Used to forward a ppp session to another "LNS".
5 * GPL licenced
6 */
7
8 #include <errno.h>
9 #include <string.h>
10 #include <linux/rtnetlink.h>
11 #include <netinet/ip6.h>
12
13 #include "md5.h"
14 #include "dhcp6.h"
15 #include "l2tpns.h"
16 #include "util.h"
17 #include "cluster.h"
18
19 #include "l2tplac.h"
20 #include "pppoe.h"
21
22 /* sequence diagram: Client <--> LAC <--> LNS1 <--> LNS2
23 *
24 * LCP Negotiation
25 * Client <-------------------> LAC
26 * Challenge (CHAP/PAP)
27 * Client <-------------------> LAC
28 * SCCRQ
29 * LAC --------------------> LNS1 (Tunnel Open)
30 * SCCRP
31 * LAC <-------------------- LNS1 (Tunnel Open)
32 * SCCCN
33 * LAC --------------------> LNS1 (Tunnel Open)
34 * ZLB
35 * LAC <-------------------- LNS1 (Tunnel Open)
36 * ICRQ
37 * LAC --------------------> LNS1 (Session Open)
38 * ICRP
39 * LAC <-------------------- LNS1 (Session Open)
40 * ICCN
41 * LAC --------------------> LNS1 (Session Open)
42 * ZLB
43 * LAC <-------------------- LNS1 (Session Open)
44 * LCP Negotiation
45 * Client <---------------------------------------------> LNS1
46 * Challenge (CHAP/PAP)
47 * Client <---------------------------------------------> LNS1
48 * SCCRQ
49 * LNS1 --------------------> LNS2 (Tunnel Open)
50 * SCCRP
51 * LNS1 <-------------------- LNS2 (Tunnel Open)
52 * SCCCN
53 * LNS1 --------------------> LNS2 (Tunnel Open)
54 * ZLB
55 * LNS1 <-------------------- LNS2 (Tunnel Open)
56 * ICRQ
57 * LNS1 --------------------> LNS2 (Session Open)
58 * ICRP
59 * LNS1 <-------------------- LNS2 (Session Open)
60 * ICCN
61 * LNS1 --------------------> LNS2 (Session Open)
62 * ZLB
63 * LNS1 <-------------------- LNS2 (Session Open)
64 * LCP Negotiation
65 * Client <------------------------------------------------------------------------> LNS2
66 * PAP/CHAP Authentification
67 * Client <------------------------------------------------------------------------> LNS2
68 * DATA (ppp)
69 * Client <------------------------------------------------------------------------> LNS2
70 * */
71
72 typedef struct
73 {
74 uint32_t tunnel_type;
75 uint32_t tunnel_medium_type;
76 in_addr_t tunnel_server_endpoint; /* IP remote LNS */
77 char tunnel_password[64]; /* l2tpsecret remote LNS */
78 char tunnel_assignment_id[256];
79 } tunnelrlnst;
80
81 // Max Radius Tunnels by remote LNS
82 #define MAXTAGTUNNEL 0x20
83 static tunnelrlnst ptunnelrlns[MAXTAGTUNNEL];
84
85 /*
86 * Possible configrlns states
87 * CONFRLNSFREE -> CONFRLNSSET -> CONFRLNSFREE
88 */
89 enum
90 {
91 CONFRLNSFREE = 0, // Not in use
92 CONFRLNSSET, // Config Set
93 CONFRLNSSETBYRADIUS // Config Set
94 };
95
96 // struct remote lns
97 typedef struct
98 {
99 int state; // conf state (tunnelstate enum)
100 in_addr_t ip; // Ip for far end
101 uint16_t port; // port for far end
102 hasht auth; // request authenticator
103 char strmaskuser[MAXUSER];
104 char l2tp_secret[64]; // L2TP shared secret
105 char tunnel_assignment_id[256];
106 }
107 configrlns;
108
109 configrlns *pconfigrlns = NULL;
110
111 // Init data structures
112 void lac_initremotelnsdata()
113 {
114 confrlnsidt i;
115
116 if ( !(pconfigrlns = shared_malloc(sizeof(pconfigrlns[0]) * MAXRLNSTUNNEL)) )
117 {
118 LOG(0, 0, 0, "Error doing malloc for tunnels lac: %s\n", strerror(errno));
119 exit(1);
120 }
121
122 memset(pconfigrlns, 0, sizeof(pconfigrlns[0]) * MAXRLNSTUNNEL);
123
124 // Mark all the conf as free.
125 for (i = 1; i < MAXRLNSTUNNEL; i++)
126 pconfigrlns[i].state = CONFRLNSFREE; // mark it as not filled in.
127
128 config->highest_rlnsid = 0;
129
130 lac_reset_rad_tag_tunnel_ctxt();
131 }
132
133 // Reset Radius TAG tunnel context
134 void lac_reset_rad_tag_tunnel_ctxt()
135 {
136 memset(ptunnelrlns, 0, sizeof(ptunnelrlns[0]) * MAXTAGTUNNEL);
137 }
138
139 // Add tunnel_type radius TAG tunnel to context
140 void lac_set_rad_tag_tunnel_type(uint8_t tag, uint32_t tunnel_type)
141 {
142 if (tag < MAXTAGTUNNEL)
143 ptunnelrlns[tag].tunnel_type = tunnel_type;
144 }
145
146 // Add tunnel_medium_type Radius TAG tunnel to context
147 void lac_set_rad_tag_tunnel_medium_type(uint8_t tag, uint32_t tunnel_medium_type)
148 {
149 if (tag < MAXTAGTUNNEL)
150 ptunnelrlns[tag].tunnel_medium_type = tunnel_medium_type;
151 }
152
153 // Add tunnel_server_endpoint Radius TAG tunnel to context
154 void lac_set_rad_tag_tunnel_serv_endpt(uint8_t tag, char *tunnel_server_endpoint)
155 {
156 if (tag < MAXTAGTUNNEL)
157 {
158 ptunnelrlns[tag].tunnel_server_endpoint = ntohl(inet_addr(tunnel_server_endpoint));
159 }
160 }
161
162 // Add tunnel_password Radius TAG tunnel to context
163 void lac_set_rad_tag_tunnel_password(uint8_t tag, char *tunnel_password)
164 {
165 if ((tag < MAXTAGTUNNEL) && (strlen(tunnel_password) < 64))
166 {
167 strcpy(ptunnelrlns[tag].tunnel_password, tunnel_password);
168 }
169 }
170
171 // Add tunnel_assignment_id Radius TAG tunnel to context
172 void lac_set_rad_tag_tunnel_assignment_id(uint8_t tag, char *tunnel_assignment_id)
173 {
174 if ((tag < MAXTAGTUNNEL) && (strlen(tunnel_assignment_id) < 256))
175 {
176 strcpy(ptunnelrlns[tag].tunnel_assignment_id, tunnel_assignment_id);
177 }
178 }
179
180 // Select a tunnel_assignment_id
181 int lac_rad_select_assignment_id(sessionidt s, char *assignment_id)
182 {
183 int idtag;
184 int nbtagfound = 0;
185 int bufidtag[MAXTAGTUNNEL];
186
187 for (idtag = 0; idtag < MAXTAGTUNNEL; ++idtag)
188 {
189 if (ptunnelrlns[idtag].tunnel_type == 0)
190 continue;
191 else if (ptunnelrlns[idtag].tunnel_type != 3) // 3 == L2TP tunnel type
192 LOG(1, s, session[s].tunnel, "Error, Only L2TP tunnel type supported\n");
193 else if (ptunnelrlns[idtag].tunnel_medium_type != 1)
194 LOG(1, s, session[s].tunnel, "Error, Only IP tunnel medium type supported\n");
195 else if (ptunnelrlns[idtag].tunnel_server_endpoint == 0)
196 LOG(1, s, session[s].tunnel, "Error, Bad IP tunnel server endpoint \n");
197 else if (strlen(ptunnelrlns[idtag].tunnel_assignment_id) > 0)
198 {
199 bufidtag[nbtagfound] = idtag;
200 nbtagfound++;
201 }
202 }
203
204 if (nbtagfound > 0)
205 {
206 // random between 0 and nbtagfound-1
207 idtag = (rand() % nbtagfound);
208
209 if (idtag >= nbtagfound)
210 idtag = 0; //Sanity checks.
211
212 strcpy(assignment_id, ptunnelrlns[bufidtag[idtag]].tunnel_assignment_id);
213 return 1;
214 }
215
216 // Error no tunnel_assignment_id found
217 return 0;
218 }
219
220 // Save the 'radius tag tunnels' context on global configuration
221 void lac_save_rad_tag_tunnels(sessionidt s)
222 {
223 confrlnsidt idrlns;
224 int idtag;
225
226 for (idtag = 0; idtag < MAXTAGTUNNEL; ++idtag)
227 {
228 if (ptunnelrlns[idtag].tunnel_type == 0)
229 continue;
230 else if (ptunnelrlns[idtag].tunnel_type != 3) // 3 == L2TP tunnel type
231 LOG(1, s, session[s].tunnel, "Error, Only L2TP tunnel type supported\n");
232 else if (ptunnelrlns[idtag].tunnel_medium_type != 1)
233 LOG(1, s, session[s].tunnel, "Error, Only IP tunnel medium type supported\n");
234 else if (ptunnelrlns[idtag].tunnel_server_endpoint == 0)
235 LOG(1, s, session[s].tunnel, "Error, Bad IP tunnel server endpoint \n");
236 else if (strlen(ptunnelrlns[idtag].tunnel_assignment_id) <= 0)
237 LOG(1, s, session[s].tunnel, "Error, No tunnel_assignment_id \n");
238 else if (ptunnelrlns[idtag].tunnel_server_endpoint == ntohl(config->bind_address))
239 LOG(0, s, session[s].tunnel, "Error, IP Remote LNS == IP local bind address (%s) !!!\n", fmtaddr(config->bind_address, 0));
240 else
241 {
242 for (idrlns = 1; idrlns < MAXRLNSTUNNEL; ++idrlns)
243 {
244 if (pconfigrlns[idrlns].state == CONFRLNSFREE)
245 {
246 pconfigrlns[idrlns].ip = ptunnelrlns[idtag].tunnel_server_endpoint;
247 pconfigrlns[idrlns].port = L2TPPORT; //Default L2TP port
248 strcpy(pconfigrlns[idrlns].l2tp_secret, ptunnelrlns[idtag].tunnel_password);
249 strcpy(pconfigrlns[idrlns].tunnel_assignment_id, ptunnelrlns[idtag].tunnel_assignment_id);
250
251 config->highest_rlnsid = idrlns;
252
253 pconfigrlns[idrlns].state = CONFRLNSSETBYRADIUS;
254
255 break;
256 }
257 else if (pconfigrlns[idrlns].state == CONFRLNSSETBYRADIUS)
258 {
259 if ( (pconfigrlns[idrlns].ip == ptunnelrlns[idtag].tunnel_server_endpoint) &&
260 (strcmp(pconfigrlns[idrlns].tunnel_assignment_id, ptunnelrlns[idtag].tunnel_assignment_id) == 0) )
261 {
262 // l2tp_secret may be changed
263 strcpy(pconfigrlns[idrlns].l2tp_secret, ptunnelrlns[idtag].tunnel_password);
264 pconfigrlns[idrlns].port = L2TPPORT; //Default L2TP poart
265
266 if (config->highest_rlnsid < idrlns) config->highest_rlnsid = idrlns;
267
268 break;
269 }
270 }
271 }
272
273 if (idrlns >= MAXRLNSTUNNEL)
274 {
275 LOG(0, s, session[s].tunnel, "No more Remote LNS Conf Free\n");
276 return;
277 }
278 }
279 }
280 }
281
282 // Create Remote LNS a Tunnel or Session
283 static int lac_create_tunnelsession(tunnelidt t, sessionidt s, confrlnsidt i_conf, char * puser)
284 {
285 if (t == 0)
286 {
287 if (main_quit == QUIT_SHUTDOWN) return 0;
288
289 // Start Open Tunnel
290 if (!(t = lac_new_tunnel()))
291 {
292 LOG(1, 0, 0, "No more tunnels\n");
293 STAT(tunnel_overflow);
294 return 0;
295 }
296 lac_tunnelclear(t);
297 tunnel[t].ip = pconfigrlns[i_conf].ip;
298 tunnel[t].port = pconfigrlns[i_conf].port;
299 tunnel[t].window = 4; // default window
300 tunnel[t].isremotelns = i_conf;
301 tunnel[t].indexudp = config->indexlacudpfd;
302 STAT(tunnel_created);
303
304 random_data(pconfigrlns[i_conf].auth, sizeof(pconfigrlns[i_conf].auth));
305
306 LOG(2, 0, t, "Create New tunnel to REMOTE LNS %s for user %s\n", fmtaddr(htonl(tunnel[t].ip), 0), puser);
307 lac_send_SCCRQ(t, pconfigrlns[i_conf].auth, sizeof(pconfigrlns[i_conf].auth));
308 }
309 else if (tunnel[t].state == TUNNELOPEN)
310 {
311 if (main_quit != QUIT_SHUTDOWN)
312 {
313
314 /**********************/
315 /** Open New session **/
316 /**********************/
317 sessionidt new_sess = sessionfree;
318
319 sessionfree = session[new_sess].next;
320 memset(&session[new_sess], 0, sizeof(session[new_sess]));
321
322 if (new_sess > config->cluster_highest_sessionid)
323 config->cluster_highest_sessionid = new_sess;
324
325 session[new_sess].opened = time_now;
326 session[new_sess].tunnel = t;
327 session[new_sess].last_packet = session[s].last_data = time_now;
328
329 session[new_sess].ppp.phase = Establish;
330 session[new_sess].ppp.lcp = Starting;
331 session[s].ppp.phase = Establish;
332
333 LOG(2, 0, t, "Open New session to REMOTE LNS %s for user: %s\n", fmtaddr(htonl(tunnel[t].ip), 0), puser);
334 // Sent ICRQ Incoming-call-request
335 lac_send_ICRQ(t, new_sess);
336
337 // Set session to forward to another LNS
338 session[s].forwardtosession = new_sess;
339 session[new_sess].forwardtosession = s;
340 strncpy(session[s].user, puser, sizeof(session[s].user) - 1);
341 strncpy(session[new_sess].user, puser, sizeof(session[new_sess].user) - 1);
342
343 STAT(session_created);
344 }
345 else
346 {
347 lac_tunnelshutdown(t, "Shutting down", 6, 0, 0);
348 }
349 }
350 else
351 {
352 /** TODO **/
353 LOG(1, 0, t, "(REMOTE LNS) tunnel is not open\n");
354 }
355
356 return 1;
357 }
358 // Check if session must be forwarded to another LNS
359 // return 1 if the session must be forwarded (and Creating a tunnel/session has been started)
360 // else 0.
361 // Note: check from the configuration read on the startup-config (see setforward)
362 int lac_conf_forwardtoremotelns(sessionidt s, char * puser)
363 {
364 tunnelidt t, j;
365 confrlnsidt i;
366
367 for (i = 1; i <= config->highest_rlnsid ; ++i)
368 {
369 if ( (pconfigrlns[i].state == CONFRLNSSET) && (NULL != strstr(puser, pconfigrlns[i].strmaskuser)) )
370 {
371 t = 0;
372 for (j = 0; j <= config->cluster_highest_tunnelid ; ++j)
373 {
374 if ((tunnel[j].isremotelns) &&
375 (tunnel[j].ip == pconfigrlns[i].ip) &&
376 (tunnel[j].port == pconfigrlns[i].port) &&
377 (tunnel[j].state != TUNNELDIE))
378 {
379 t = j;
380 if (tunnel[t].isremotelns != i)
381 {
382 if ( (tunnel[t].state == TUNNELOPEN) || (tunnel[t].state == TUNNELOPENING) )
383 {
384 LOG(1, 0, t, "Tunnel Remote LNS ID inconsistency (IP RLNS:%s)\n",
385 fmtaddr(htonl(pconfigrlns[i].ip), 0));
386
387 tunnel[t].isremotelns = i;
388 }
389 else t = 0;
390 }
391 break;
392 }
393 }
394
395 return lac_create_tunnelsession(t, s, i, puser);
396 }
397 }
398
399 return 0;
400 }
401
402 // return 1 if the session must be forwarded (and Creating a tunnel/session has been started)
403 // else 0.
404 // Note: Started from a radius response
405 int lac_rad_forwardtoremotelns(sessionidt s, char *assignment_id, char * puser)
406 {
407 tunnelidt t, j;
408 confrlnsidt i;
409
410 for (i = 1; i <= config->highest_rlnsid ; ++i)
411 {
412 if ((pconfigrlns[i].state == CONFRLNSSETBYRADIUS) &&
413 (strcmp(pconfigrlns[i].tunnel_assignment_id, assignment_id) == 0))
414 {
415 t = 0;
416 for (j = 1; j <= config->cluster_highest_tunnelid ; ++j)
417 {
418 if ((tunnel[j].isremotelns == i) &&
419 (tunnel[j].ip == pconfigrlns[i].ip) &&
420 (tunnel[j].port == pconfigrlns[i].port) &&
421 (tunnel[j].state != TUNNELDIE))
422 {
423 if ( (tunnel[j].state == TUNNELOPEN) ||
424 (tunnel[j].state == TUNNELOPENING) )
425 {
426 t = j;
427 LOG(3, 0, t, "Tunnel Remote LNS already open(ing) (RLNS IP:%s)\n", fmtaddr(htonl(pconfigrlns[i].ip), 0));
428 break;
429 }
430 }
431 }
432
433 return lac_create_tunnelsession(t, s, i, puser);
434 }
435 }
436
437 return 0;
438 }
439
440 // Calcul the remote LNS auth
441 void lac_calc_rlns_auth(tunnelidt t, uint8_t id, uint8_t *out)
442 {
443 MD5_CTX ctx;
444 confrlnsidt idrlns;
445
446 idrlns = tunnel[t].isremotelns;
447
448 MD5_Init(&ctx);
449 MD5_Update(&ctx, &id, 1);
450 MD5_Update(&ctx, pconfigrlns[idrlns].l2tp_secret, strlen(pconfigrlns[idrlns].l2tp_secret));
451 MD5_Update(&ctx, pconfigrlns[idrlns].auth, 16);
452 MD5_Final(out, &ctx);
453 }
454
455 // Forward session to LAC or Remote LNS
456 int lac_session_forward(uint8_t *buf, int len, sessionidt sess, uint16_t proto, in_addr_t s_addr, int sin_port, uint16_t indexudpfd)
457 {
458 uint16_t t = 0, s = 0;
459 uint8_t *p = buf + 2; // First word L2TP options
460
461 s = session[sess].forwardtosession;
462 if (session[s].forwardtosession != sess)
463 {
464 LOG(0, sess, session[sess].tunnel, "Link Session (%u) broken\n", s);
465 return 0;
466 }
467
468 t = session[s].tunnel;
469 if (t >= MAXTUNNEL)
470 {
471 LOG(1, s, t, "Session with invalid tunnel ID\n");
472 return 0;
473 }
474
475 if ((!tunnel[t].isremotelns) && (!tunnel[session[sess].tunnel].isremotelns))
476 {
477 LOG(0, sess, session[sess].tunnel, "Link Tunnel Session (%u/%u) broken\n", s, t);
478 return 0;
479 }
480
481 if (!config->cluster_iam_master)
482 {
483 if ( (proto == PPPIPCP) || (proto == PPPLCP) ||
484 (proto == PPPPAP) || (proto == PPPCHAP) ||
485 (proto == PPPIPV6CP && config->ipv6_prefix.s6_addr[0]) ||
486 (proto == PPPCCP) )
487 {
488 session[sess].last_packet = time_now;
489 master_forward_packet(buf, len, s_addr, sin_port, indexudpfd);
490 return 1;
491 }
492 }
493
494 if (t == TUNNEL_ID_PPPOE)
495 {
496 pppoe_forwardto_session_pppoe(buf, len, sess, proto);
497 return 1;
498 }
499
500 if (*buf & 0x40)
501 { // length
502 p += 2;
503 }
504
505 *(uint16_t *) p = htons(tunnel[t].far); // tunnel
506 p += 2;
507 *(uint16_t *) p = htons(session[s].far); // session
508 p += 2;
509
510 if (*buf & 0x08)
511 { // ns/nr
512 *(uint16_t *) p = htons(tunnel[t].ns); // sequence
513 p += 2;
514 *(uint16_t *) p = htons(tunnel[t].nr); // sequence
515 p += 2;
516 }
517
518 if ((proto == PPPIP) || (proto == PPPMP) ||(proto == PPPIPV6 && config->ipv6_prefix.s6_addr[0]))
519 {
520 session[sess].last_packet = session[sess].last_data = time_now;
521 // Update STAT IN
522 increment_counter(&session[sess].cin, &session[sess].cin_wrap, len);
523 session[sess].cin_delta += len;
524 session[sess].pin++;
525 sess_local[sess].cin += len;
526 sess_local[sess].pin++;
527
528 session[s].last_data = time_now;
529 // Update STAT OUT
530 increment_counter(&session[s].cout, &session[s].cout_wrap, len); // byte count
531 session[s].cout_delta += len;
532 session[s].pout++;
533 sess_local[s].cout += len;
534 sess_local[s].pout++;
535 }
536 else
537 session[sess].last_packet = time_now;
538
539 tunnelsend(buf, len, t); // send it...
540
541 return 1;
542 }
543
544 // Add new Remote LNS from CLI
545 // return:
546 // 0 = Error
547 // 1 = New Remote LNS conf ADD
548 // 2 = Remote LNS Conf Updated
549 int lac_addremotelns(char *mask, char *IP_RemoteLNS, char *Port_RemoteLNS, char *SecretRemoteLNS)
550 {
551 confrlnsidt idrlns;
552
553 for (idrlns = 1; idrlns < MAXRLNSTUNNEL; ++idrlns)
554 {
555 if (pconfigrlns[idrlns].state == CONFRLNSFREE)
556 {
557 snprintf((char *) pconfigrlns[idrlns].strmaskuser, sizeof(pconfigrlns[idrlns].strmaskuser), "%s", mask);
558 pconfigrlns[idrlns].ip = ntohl(inet_addr(IP_RemoteLNS));
559 pconfigrlns[idrlns].port = atoi(Port_RemoteLNS);
560 snprintf((char *) pconfigrlns[idrlns].l2tp_secret, sizeof(pconfigrlns[idrlns].l2tp_secret), "%s", SecretRemoteLNS);
561
562 config->highest_rlnsid = idrlns;
563
564 pconfigrlns[idrlns].state = CONFRLNSSET;
565
566 return 1;
567 }
568 else if ((pconfigrlns[idrlns].state == CONFRLNSSET) && (strcmp(pconfigrlns[idrlns].strmaskuser, mask) == 0))
569 {
570 if ( (pconfigrlns[idrlns].ip != ntohl(inet_addr(IP_RemoteLNS))) ||
571 (pconfigrlns[idrlns].port != atoi(Port_RemoteLNS)) ||
572 (strcmp(pconfigrlns[idrlns].l2tp_secret, SecretRemoteLNS) != 0) )
573 {
574 memset(&pconfigrlns[idrlns], 0, sizeof(pconfigrlns[idrlns]));
575 snprintf((char *) pconfigrlns[idrlns].strmaskuser, sizeof(pconfigrlns[idrlns].strmaskuser), "%s", mask);
576 pconfigrlns[idrlns].ip = ntohl(inet_addr(IP_RemoteLNS));
577 pconfigrlns[idrlns].port = atoi(Port_RemoteLNS);
578 snprintf((char *) pconfigrlns[idrlns].l2tp_secret, sizeof(pconfigrlns[idrlns].l2tp_secret), "%s", SecretRemoteLNS);
579
580 if (config->highest_rlnsid < idrlns) config->highest_rlnsid = idrlns;
581
582 pconfigrlns[idrlns].state = CONFRLNSSET;
583 // Conf Updated, the tunnel must be dropped
584 return 2;
585 }
586
587 return 1;
588 }
589 }
590
591 LOG(0, 0, 0, "No more Remote LNS Conf Free\n");
592
593 return 0;
594 }
595
596 // Cli Show remote LNS defined
597 int lac_cli_show_remotelns(confrlnsidt idrlns, char *strout)
598 {
599 if (idrlns > config->highest_rlnsid)
600 return 0;
601
602 if (idrlns == 0)
603 // Show Summary
604 sprintf(strout, "%15s %3s %-32s %-32s %11s %7s %10s",
605 "IP Remote LNS",
606 "TID",
607 "l2tp secret",
608 "assignment Id",
609 "File/Radius",
610 "State",
611 "Count Sess");
612 else
613 {
614 tunnelidt t, tfound = 0;
615 sessionidt s;
616 int countsess = 0;
617 char state[20];
618
619 strcpy(state, "Close");
620 for (t = 0; t <= config->cluster_highest_tunnelid ; ++t)
621 {
622 if ((tunnel[t].isremotelns == idrlns) &&
623 (tunnel[t].ip == pconfigrlns[idrlns].ip) &&
624 (tunnel[t].port == pconfigrlns[idrlns].port) &&
625 (tunnel[t].state != TUNNELDIE))
626 {
627 if (tunnel[t].state == TUNNELOPENING)
628 strcpy(state, "Opening");
629 else if (tunnel[t].state == TUNNELOPEN)
630 strcpy(state, "Open");
631
632 for (s = 1; s <= config->cluster_highest_sessionid ; ++s)
633 if (session[s].tunnel == t)
634 countsess++;
635 tfound = t;
636 break;
637 }
638 }
639
640 sprintf(strout, "%15s %3u %-32s %-32s %11s %7s %10u",
641 fmtaddr(htonl(pconfigrlns[idrlns].ip), 0),
642 tfound,
643 pconfigrlns[idrlns].l2tp_secret,
644 pconfigrlns[idrlns].tunnel_assignment_id,
645 (pconfigrlns[idrlns].state == CONFRLNSSET?"File":(pconfigrlns[idrlns].state == CONFRLNSSETBYRADIUS?"Radius":"Free")),
646 state,
647 countsess);
648 }
649
650 return 1;
651 }