Merge from master
[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 STAT(tunnel_created);
301
302 random_data(pconfigrlns[i_conf].auth, sizeof(pconfigrlns[i_conf].auth));
303
304 LOG(2, 0, t, "Create New tunnel to REMOTE LNS %s for user %s\n", fmtaddr(htonl(tunnel[t].ip), 0), puser);
305 lac_send_SCCRQ(t, pconfigrlns[i_conf].auth, sizeof(pconfigrlns[i_conf].auth));
306 }
307 else if (tunnel[t].state == TUNNELOPEN)
308 {
309 if (main_quit != QUIT_SHUTDOWN)
310 {
311
312 /**********************/
313 /** Open New session **/
314 /**********************/
315 sessionidt new_sess = sessionfree;
316
317 sessionfree = session[new_sess].next;
318 memset(&session[new_sess], 0, sizeof(session[new_sess]));
319
320 if (new_sess > config->cluster_highest_sessionid)
321 config->cluster_highest_sessionid = new_sess;
322
323 session[new_sess].opened = time_now;
324 session[new_sess].tunnel = t;
325 session[new_sess].last_packet = session[s].last_data = time_now;
326
327 session[new_sess].ppp.phase = Establish;
328 session[new_sess].ppp.lcp = Starting;
329 session[s].ppp.phase = Establish;
330
331 LOG(2, 0, t, "Open New session to REMOTE LNS %s for user: %s\n", fmtaddr(htonl(tunnel[t].ip), 0), puser);
332 // Sent ICRQ Incoming-call-request
333 lac_send_ICRQ(t, new_sess);
334
335 // Set session to forward to another LNS
336 session[s].forwardtosession = new_sess;
337 session[new_sess].forwardtosession = s;
338 strncpy(session[s].user, puser, sizeof(session[s].user) - 1);
339 strncpy(session[new_sess].user, puser, sizeof(session[new_sess].user) - 1);
340
341 STAT(session_created);
342 }
343 else
344 {
345 lac_tunnelshutdown(t, "Shutting down", 6, 0, 0);
346 }
347 }
348 else
349 {
350 /** TODO **/
351 LOG(1, 0, t, "(REMOTE LNS) tunnel is not open\n");
352 }
353
354 return 1;
355 }
356 // Check if session must be forwarded to another LNS
357 // return 1 if the session must be forwarded (and Creating a tunnel/session has been started)
358 // else 0.
359 // Note: check from the configuration read on the startup-config (see setforward)
360 int lac_conf_forwardtoremotelns(sessionidt s, char * puser)
361 {
362 tunnelidt t, j;
363 confrlnsidt i;
364
365 for (i = 1; i <= config->highest_rlnsid ; ++i)
366 {
367 if ( (pconfigrlns[i].state == CONFRLNSSET) && (NULL != strstr(puser, pconfigrlns[i].strmaskuser)) )
368 {
369 t = 0;
370 for (j = 0; j <= config->cluster_highest_tunnelid ; ++j)
371 {
372 if ((tunnel[j].isremotelns) &&
373 (tunnel[j].ip == pconfigrlns[i].ip) &&
374 (tunnel[j].port == pconfigrlns[i].port) &&
375 (tunnel[j].state != TUNNELDIE))
376 {
377 t = j;
378 if (tunnel[t].isremotelns != i)
379 {
380 if ( (tunnel[t].state == TUNNELOPEN) || (tunnel[t].state == TUNNELOPENING) )
381 {
382 LOG(1, 0, t, "Tunnel Remote LNS ID inconsistency (IP RLNS:%s)\n",
383 fmtaddr(htonl(pconfigrlns[i].ip), 0));
384
385 tunnel[t].isremotelns = i;
386 }
387 else t = 0;
388 }
389 break;
390 }
391 }
392
393 return lac_create_tunnelsession(t, s, i, puser);
394 }
395 }
396
397 return 0;
398 }
399
400 // return 1 if the session must be forwarded (and Creating a tunnel/session has been started)
401 // else 0.
402 // Note: Started from a radius response
403 int lac_rad_forwardtoremotelns(sessionidt s, char *assignment_id, char * puser)
404 {
405 tunnelidt t, j;
406 confrlnsidt i;
407
408 for (i = 1; i <= config->highest_rlnsid ; ++i)
409 {
410 if ((pconfigrlns[i].state == CONFRLNSSETBYRADIUS) &&
411 (strcmp(pconfigrlns[i].tunnel_assignment_id, assignment_id) == 0))
412 {
413 t = 0;
414 for (j = 1; j <= config->cluster_highest_tunnelid ; ++j)
415 {
416 if ((tunnel[j].isremotelns == i) &&
417 (tunnel[j].ip == pconfigrlns[i].ip) &&
418 (tunnel[j].port == pconfigrlns[i].port) &&
419 (tunnel[j].state != TUNNELDIE))
420 {
421 if ( (tunnel[j].state == TUNNELOPEN) ||
422 (tunnel[j].state == TUNNELOPENING) )
423 {
424 t = j;
425 LOG(3, 0, t, "Tunnel Remote LNS already open(ing) (RLNS IP:%s)\n", fmtaddr(htonl(pconfigrlns[i].ip), 0));
426 break;
427 }
428 }
429 }
430
431 return lac_create_tunnelsession(t, s, i, puser);
432 }
433 }
434
435 return 0;
436 }
437
438 // Calcul the remote LNS auth
439 void lac_calc_rlns_auth(tunnelidt t, uint8_t id, uint8_t *out)
440 {
441 MD5_CTX ctx;
442 confrlnsidt idrlns;
443
444 idrlns = tunnel[t].isremotelns;
445
446 MD5_Init(&ctx);
447 MD5_Update(&ctx, &id, 1);
448 MD5_Update(&ctx, pconfigrlns[idrlns].l2tp_secret, strlen(pconfigrlns[idrlns].l2tp_secret));
449 MD5_Update(&ctx, pconfigrlns[idrlns].auth, 16);
450 MD5_Final(out, &ctx);
451 }
452
453 // Forward session to LAC or Remote LNS
454 int lac_session_forward(uint8_t *buf, int len, sessionidt sess, uint16_t proto, in_addr_t s_addr, int sin_port)
455 {
456 uint16_t t = 0, s = 0;
457 uint8_t *p = buf + 2; // First word L2TP options
458
459 s = session[sess].forwardtosession;
460 if (session[s].forwardtosession != sess)
461 {
462 LOG(0, sess, session[sess].tunnel, "Link Session (%u) broken\n", s);
463 return 0;
464 }
465
466 t = session[s].tunnel;
467 if (t >= MAXTUNNEL)
468 {
469 LOG(1, s, t, "Session with invalid tunnel ID\n");
470 return 0;
471 }
472
473 if ((!tunnel[t].isremotelns) && (!tunnel[session[sess].tunnel].isremotelns))
474 {
475 LOG(0, sess, session[sess].tunnel, "Link Tunnel Session (%u/%u) broken\n", s, t);
476 return 0;
477 }
478
479 if (!config->cluster_iam_master)
480 {
481 if ( (proto == PPPIPCP) || (proto == PPPLCP) ||
482 (proto == PPPPAP) || (proto == PPPCHAP) ||
483 (proto == PPPIPV6CP && config->ipv6_prefix.s6_addr[0]) ||
484 (proto == PPPCCP) )
485 {
486 session[sess].last_packet = time_now;
487 master_forward_packet(buf, len, s_addr, sin_port);
488 return 1;
489 }
490 }
491
492 if (t == TUNNEL_ID_PPPOE)
493 {
494 pppoe_forwardto_session_pppoe(buf, len, sess, proto);
495 return 1;
496 }
497
498 if (*buf & 0x40)
499 { // length
500 p += 2;
501 }
502
503 *(uint16_t *) p = htons(tunnel[t].far); // tunnel
504 p += 2;
505 *(uint16_t *) p = htons(session[s].far); // session
506 p += 2;
507
508 if (*buf & 0x08)
509 { // ns/nr
510 *(uint16_t *) p = htons(tunnel[t].ns); // sequence
511 p += 2;
512 *(uint16_t *) p = htons(tunnel[t].nr); // sequence
513 p += 2;
514 }
515
516 if ((proto == PPPIP) || (proto == PPPMP) ||(proto == PPPIPV6 && config->ipv6_prefix.s6_addr[0]))
517 {
518 session[sess].last_packet = session[sess].last_data = time_now;
519 // Update STAT IN
520 increment_counter(&session[sess].cin, &session[sess].cin_wrap, len);
521 session[sess].cin_delta += len;
522 session[sess].pin++;
523 sess_local[sess].cin += len;
524 sess_local[sess].pin++;
525
526 session[s].last_data = time_now;
527 // Update STAT OUT
528 increment_counter(&session[s].cout, &session[s].cout_wrap, len); // byte count
529 session[s].cout_delta += len;
530 session[s].coutgrp_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 }