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