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