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