3 * Add functionality "LAC" to l2tpns.
4 * Used to forward a ppp session to another "LNS".
10 #include <sys/socket.h>
11 #include <linux/rtnetlink.h>
21 /* sequence diagram: Client <--> LAC <--> LNS1 <--> LNS2
24 * Client <-------------------> LAC
25 * Challenge (CHAP/PAP)
26 * Client <-------------------> LAC
28 * LAC --------------------> LNS1 (Tunnel Open)
30 * LAC <-------------------- LNS1 (Tunnel Open)
32 * LAC --------------------> LNS1 (Tunnel Open)
34 * LAC <-------------------- LNS1 (Tunnel Open)
36 * LAC --------------------> LNS1 (Session Open)
38 * LAC <-------------------- LNS1 (Session Open)
40 * LAC --------------------> LNS1 (Session Open)
42 * LAC <-------------------- LNS1 (Session Open)
44 * Client <---------------------------------------------> LNS1
45 * Challenge (CHAP/PAP)
46 * Client <---------------------------------------------> LNS1
48 * LNS1 --------------------> LNS2 (Tunnel Open)
50 * LNS1 <-------------------- LNS2 (Tunnel Open)
52 * LNS1 --------------------> LNS2 (Tunnel Open)
54 * LNS1 <-------------------- LNS2 (Tunnel Open)
56 * LNS1 --------------------> LNS2 (Session Open)
58 * LNS1 <-------------------- LNS2 (Session Open)
60 * LNS1 --------------------> LNS2 (Session Open)
62 * LNS1 <-------------------- LNS2 (Session Open)
64 * Client <------------------------------------------------------------------------> LNS2
65 * PAP/CHAP Authentification
66 * Client <------------------------------------------------------------------------> LNS2
68 * Client <------------------------------------------------------------------------> LNS2
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];
80 // Max Radius Tunnels by remote LNS
81 #define MAXTAGTUNNEL 0x20
82 static tunnelrlnst ptunnelrlns
[MAXTAGTUNNEL
];
85 * Possible configrlns states
86 * CONFRLNSFREE -> CONFRLNSSET -> CONFRLNSFREE
90 CONFRLNSFREE
= 0, // Not in use
91 CONFRLNSSET
, // Config Set
92 CONFRLNSSETBYRADIUS
// Config Set
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];
108 configrlns
*pconfigrlns
= NULL
;
110 // Init data structures
111 void lac_initremotelnsdata()
115 if ( !(pconfigrlns
= shared_malloc(sizeof(pconfigrlns
[0]) * MAXRLNSTUNNEL
)) )
117 LOG(0, 0, 0, "Error doing malloc for tunnels lac: %s\n", strerror(errno
));
121 memset(pconfigrlns
, 0, sizeof(pconfigrlns
[0]) * MAXRLNSTUNNEL
);
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.
127 config
->highest_rlnsid
= 0;
129 lac_reset_rad_tag_tunnel_ctxt();
132 // Reset Radius TAG tunnel context
133 void lac_reset_rad_tag_tunnel_ctxt()
135 memset(ptunnelrlns
, 0, sizeof(ptunnelrlns
[0]) * MAXTAGTUNNEL
);
138 // Add tunnel_type radius TAG tunnel to context
139 void lac_set_rad_tag_tunnel_type(uint8_t tag
, uint32_t tunnel_type
)
141 if (tag
< MAXTAGTUNNEL
)
142 ptunnelrlns
[tag
].tunnel_type
= tunnel_type
;
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
)
148 if (tag
< MAXTAGTUNNEL
)
149 ptunnelrlns
[tag
].tunnel_medium_type
= tunnel_medium_type
;
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
)
155 if (tag
< MAXTAGTUNNEL
)
157 ptunnelrlns
[tag
].tunnel_server_endpoint
= ntohl(inet_addr(tunnel_server_endpoint
));
161 // Add tunnel_password Radius TAG tunnel to context
162 void lac_set_rad_tag_tunnel_password(uint8_t tag
, char *tunnel_password
)
164 if ((tag
< MAXTAGTUNNEL
) && (strlen(tunnel_password
) < 64))
166 strcpy(ptunnelrlns
[tag
].tunnel_password
, tunnel_password
);
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
)
173 if ((tag
< MAXTAGTUNNEL
) && (strlen(tunnel_assignment_id
) < 256))
175 strcpy(ptunnelrlns
[tag
].tunnel_assignment_id
, tunnel_assignment_id
);
179 // Select a tunnel_assignment_id
180 int lac_rad_select_assignment_id(sessionidt s
, char *assignment_id
)
184 int bufidtag
[MAXTAGTUNNEL
];
186 for (idtag
= 0; idtag
< MAXTAGTUNNEL
; ++idtag
)
188 if (ptunnelrlns
[idtag
].tunnel_type
== 0)
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)
198 bufidtag
[nbtagfound
] = idtag
;
205 // random between 0 and nbtagfound-1
206 idtag
= (rand() % nbtagfound
);
208 if (idtag
>= nbtagfound
)
209 idtag
= 0; //Sanity checks.
211 strcpy(assignment_id
, ptunnelrlns
[bufidtag
[idtag
]].tunnel_assignment_id
);
215 // Error no tunnel_assignment_id found
219 // Save the 'radius tag tunnels' context on global configuration
220 void lac_save_rad_tag_tunnels(sessionidt s
)
225 for (idtag
= 0; idtag
< MAXTAGTUNNEL
; ++idtag
)
227 if (ptunnelrlns
[idtag
].tunnel_type
== 0)
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));
241 for (idrlns
= 1; idrlns
< MAXRLNSTUNNEL
; ++idrlns
)
243 if (pconfigrlns
[idrlns
].state
== CONFRLNSFREE
)
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
);
250 config
->highest_rlnsid
= idrlns
;
252 pconfigrlns
[idrlns
].state
= CONFRLNSSETBYRADIUS
;
256 else if (pconfigrlns
[idrlns
].state
== CONFRLNSSETBYRADIUS
)
258 if ( (pconfigrlns
[idrlns
].ip
== ptunnelrlns
[idtag
].tunnel_server_endpoint
) &&
259 (strcmp(pconfigrlns
[idrlns
].tunnel_assignment_id
, ptunnelrlns
[idtag
].tunnel_assignment_id
) == 0) )
261 // l2tp_secret may be changed
262 strcpy(pconfigrlns
[idrlns
].l2tp_secret
, ptunnelrlns
[idtag
].tunnel_password
);
263 pconfigrlns
[idrlns
].port
= L2TPPORT
; //Default L2TP poart
265 if (config
->highest_rlnsid
< idrlns
) config
->highest_rlnsid
= idrlns
;
272 if (idrlns
>= MAXRLNSTUNNEL
)
274 LOG(0, s
, session
[s
].tunnel
, "No more Remote LNS Conf Free\n");
281 // Create Remote LNS a Tunnel or Session
282 static int lac_create_tunnelsession(tunnelidt t
, sessionidt s
, confrlnsidt i_conf
, char * puser
)
286 if (main_quit
== QUIT_SHUTDOWN
) return 0;
289 if (!(t
= lac_new_tunnel()))
291 LOG(1, 0, 0, "No more tunnels\n");
292 STAT(tunnel_overflow
);
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
);
303 random_data(pconfigrlns
[i_conf
].auth
, sizeof(pconfigrlns
[i_conf
].auth
));
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
));
308 else if (tunnel
[t
].state
== TUNNELOPEN
)
310 if (main_quit
!= QUIT_SHUTDOWN
)
313 /**********************/
314 /** Open New session **/
315 /**********************/
316 sessionidt new_sess
= sessionfree
;
318 sessionfree
= session
[new_sess
].next
;
319 memset(&session
[new_sess
], 0, sizeof(session
[new_sess
]));
321 if (new_sess
> config
->cluster_highest_sessionid
)
322 config
->cluster_highest_sessionid
= new_sess
;
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
;
328 session
[new_sess
].ppp
.phase
= Establish
;
329 session
[new_sess
].ppp
.lcp
= Starting
;
330 session
[s
].ppp
.phase
= Establish
;
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
);
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);
342 STAT(session_created
);
346 lac_tunnelshutdown(t
, "Shutting down", 6, 0, 0);
352 LOG(1, 0, t
, "(REMOTE LNS) tunnel is not open\n");
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)
360 // Note: check from the configuration read on the startup-config (see setforward)
361 int lac_conf_forwardtoremotelns(sessionidt s
, char * puser
)
366 for (i
= 1; i
<= config
->highest_rlnsid
; ++i
)
368 if ( (pconfigrlns
[i
].state
== CONFRLNSSET
) && (NULL
!= strstr(puser
, pconfigrlns
[i
].strmaskuser
)) )
371 for (j
= 0; j
<= config
->cluster_highest_tunnelid
; ++j
)
373 if ((tunnel
[j
].isremotelns
) &&
374 (tunnel
[j
].ip
== pconfigrlns
[i
].ip
) &&
375 (tunnel
[j
].port
== pconfigrlns
[i
].port
) &&
376 (tunnel
[j
].state
!= TUNNELDIE
))
379 if (tunnel
[t
].isremotelns
!= i
)
381 if ( (tunnel
[t
].state
== TUNNELOPEN
) || (tunnel
[t
].state
== TUNNELOPENING
) )
383 LOG(1, 0, t
, "Tunnel Remote LNS ID inconsistency (IP RLNS:%s)\n",
384 fmtaddr(htonl(pconfigrlns
[i
].ip
), 0));
386 tunnel
[t
].isremotelns
= i
;
394 return lac_create_tunnelsession(t
, s
, i
, puser
);
401 // return 1 if the session must be forwarded (and Creating a tunnel/session has been started)
403 // Note: Started from a radius response
404 int lac_rad_forwardtoremotelns(sessionidt s
, char *assignment_id
, char * puser
)
409 for (i
= 1; i
<= config
->highest_rlnsid
; ++i
)
411 if ((pconfigrlns
[i
].state
== CONFRLNSSETBYRADIUS
) &&
412 (strcmp(pconfigrlns
[i
].tunnel_assignment_id
, assignment_id
) == 0))
415 for (j
= 1; j
<= config
->cluster_highest_tunnelid
; ++j
)
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
))
422 if ( (tunnel
[j
].state
== TUNNELOPEN
) ||
423 (tunnel
[j
].state
== TUNNELOPENING
) )
426 LOG(3, 0, t
, "Tunnel Remote LNS already open(ing) (RLNS IP:%s)\n", fmtaddr(htonl(pconfigrlns
[i
].ip
), 0));
432 return lac_create_tunnelsession(t
, s
, i
, puser
);
439 // Calcul the remote LNS auth
440 void lac_calc_rlns_auth(tunnelidt t
, uint8_t id
, uint8_t *out
)
445 idrlns
= tunnel
[t
].isremotelns
;
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
);
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
)
457 uint16_t t
= 0, s
= 0;
458 uint8_t *p
= buf
+ 2; // First word L2TP options
460 s
= session
[sess
].forwardtosession
;
461 if (session
[s
].forwardtosession
!= sess
)
463 LOG(0, sess
, session
[sess
].tunnel
, "Link Session (%u) broken\n", s
);
467 t
= session
[s
].tunnel
;
470 LOG(1, s
, t
, "Session with invalid tunnel ID\n");
474 if ((!tunnel
[t
].isremotelns
) && (!tunnel
[session
[sess
].tunnel
].isremotelns
))
476 LOG(0, sess
, session
[sess
].tunnel
, "Link Tunnel Session (%u/%u) broken\n", s
, t
);
480 if (!config
->cluster_iam_master
)
482 if ( (proto
== PPPIPCP
) || (proto
== PPPLCP
) ||
483 (proto
== PPPPAP
) || (proto
== PPPCHAP
) ||
484 (proto
== PPPIPV6CP
&& config
->ipv6_prefix
.s6_addr
[0]) ||
487 session
[sess
].last_packet
= time_now
;
488 master_forward_packet(buf
, len
, s_addr
, sin_port
, indexudpfd
);
493 if (t
== TUNNEL_ID_PPPOE
)
495 pppoe_forwardto_session_pppoe(buf
, len
, sess
, proto
);
504 *(uint16_t *) p
= htons(tunnel
[t
].far
); // tunnel
506 *(uint16_t *) p
= htons(session
[s
].far
); // session
511 *(uint16_t *) p
= htons(tunnel
[t
].ns
); // sequence
513 *(uint16_t *) p
= htons(tunnel
[t
].nr
); // sequence
517 if ((proto
== PPPIP
) || (proto
== PPPMP
) ||(proto
== PPPIPV6
&& config
->ipv6_prefix
.s6_addr
[0]))
519 session
[sess
].last_packet
= session
[sess
].last_data
= time_now
;
521 increment_counter(&session
[sess
].cin
, &session
[sess
].cin_wrap
, len
);
522 session
[sess
].cin_delta
+= len
;
524 sess_local
[sess
].cin
+= len
;
525 sess_local
[sess
].pin
++;
527 session
[s
].last_data
= time_now
;
529 increment_counter(&session
[s
].cout
, &session
[s
].cout_wrap
, len
); // byte count
530 session
[s
].cout_delta
+= len
;
531 session
[s
].coutgrp_delta
+= len
;
533 sess_local
[s
].cout
+= len
;
534 sess_local
[s
].pout
++;
537 session
[sess
].last_packet
= time_now
;
539 tunnelsend(buf
, len
, t
); // send it...
544 // Add new Remote LNS from CLI
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
)
553 for (idrlns
= 1; idrlns
< MAXRLNSTUNNEL
; ++idrlns
)
555 if (pconfigrlns
[idrlns
].state
== CONFRLNSFREE
)
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
);
562 config
->highest_rlnsid
= idrlns
;
564 pconfigrlns
[idrlns
].state
= CONFRLNSSET
;
568 else if ((pconfigrlns
[idrlns
].state
== CONFRLNSSET
) && (strcmp(pconfigrlns
[idrlns
].strmaskuser
, mask
) == 0))
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) )
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
);
580 if (config
->highest_rlnsid
< idrlns
) config
->highest_rlnsid
= idrlns
;
582 pconfigrlns
[idrlns
].state
= CONFRLNSSET
;
583 // Conf Updated, the tunnel must be dropped
591 LOG(0, 0, 0, "No more Remote LNS Conf Free\n");
596 // Cli Show remote LNS defined
597 int lac_cli_show_remotelns(confrlnsidt idrlns
, char *strout
)
599 if (idrlns
> config
->highest_rlnsid
)
604 sprintf(strout
, "%15s %3s %-32s %-32s %11s %7s %10s",
614 tunnelidt t
, tfound
= 0;
619 strcpy(state
, "Close");
620 for (t
= 0; t
<= config
->cluster_highest_tunnelid
; ++t
)
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
))
627 if (tunnel
[t
].state
== TUNNELOPENING
)
628 strcpy(state
, "Opening");
629 else if (tunnel
[t
].state
== TUNNELOPEN
)
630 strcpy(state
, "Open");
632 for (s
= 1; s
<= config
->cluster_highest_sessionid
; ++s
)
633 if (session
[s
].tunnel
== t
)
640 sprintf(strout
, "%15s %3u %-32s %-32s %11s %7s %10u",
641 fmtaddr(htonl(pconfigrlns
[idrlns
].ip
), 0),
643 pconfigrlns
[idrlns
].l2tp_secret
,
644 pconfigrlns
[idrlns
].tunnel_assignment_id
,
645 (pconfigrlns
[idrlns
].state
== CONFRLNSSET
?"File":(pconfigrlns
[idrlns
].state
== CONFRLNSSETBYRADIUS
?"Radius":"Free")),