Separate out PPP processing
So we can later call it on frames obtained from kernel ppp interface. Better seen with diff -w
This commit is contained in:
parent
79a08faea9
commit
1db43fc51d
1 changed files with 167 additions and 159 deletions
326
l2tpns.c
326
l2tpns.c
|
|
@ -282,6 +282,7 @@ static void processcontrol(uint8_t *buf, int len, struct sockaddr_in *addr, int
|
||||||
static tunnelidt new_tunnel(void);
|
static tunnelidt new_tunnel(void);
|
||||||
static void unhide_value(uint8_t *value, size_t len, uint16_t type, uint8_t *vector, size_t vec_len);
|
static void unhide_value(uint8_t *value, size_t len, uint16_t type, uint8_t *vector, size_t vec_len);
|
||||||
static void bundleclear(bundleidt b);
|
static void bundleclear(bundleidt b);
|
||||||
|
static void processppp(sessionidt s, uint8_t *buf, int len, uint8_t *p, int l, struct sockaddr_in *addr, uint16_t indexudpfd);
|
||||||
|
|
||||||
// return internal time (10ths since process startup), set f if given
|
// return internal time (10ths since process startup), set f if given
|
||||||
// as a side-effect sets time_now, and time_changed
|
// as a side-effect sets time_now, and time_changed
|
||||||
|
|
@ -4179,180 +4180,187 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // data
|
// data
|
||||||
uint16_t proto;
|
processppp(s, buf, len, p, l, addr, indexudpfd);
|
||||||
|
}
|
||||||
|
|
||||||
LOG_HEX(5, "Receive Tunnel Data", p, l);
|
//
|
||||||
if (l > 2 && p[0] == 0xFF && p[1] == 0x03)
|
// process a ppp frame coming from tunnel
|
||||||
{ // HDLC address header, discard
|
static void processppp(sessionidt s, uint8_t *buf, int len, uint8_t *p, int l, struct sockaddr_in *addr, uint16_t indexudpfd)
|
||||||
p += 2;
|
{ // data
|
||||||
l -= 2;
|
int t = session[s].tunnel;
|
||||||
}
|
uint16_t proto;
|
||||||
if (l < 2)
|
|
||||||
{
|
|
||||||
LOG(1, s, t, "Short ppp length %d\n", l);
|
|
||||||
STAT(tunnel_rx_errors);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (*p & 1)
|
|
||||||
{
|
|
||||||
proto = *p++;
|
|
||||||
l--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
proto = ntohs(*(uint16_t *) p);
|
|
||||||
p += 2;
|
|
||||||
l -= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (session[s].forwardtosession)
|
LOG_HEX(5, "Receive Tunnel Data", p, l);
|
||||||
|
if (l > 2 && p[0] == 0xFF && p[1] == 0x03)
|
||||||
|
{ // HDLC address header, discard
|
||||||
|
p += 2;
|
||||||
|
l -= 2;
|
||||||
|
}
|
||||||
|
if (l < 2)
|
||||||
|
{
|
||||||
|
LOG(1, s, t, "Short ppp length %d\n", l);
|
||||||
|
STAT(tunnel_rx_errors);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (*p & 1)
|
||||||
|
{
|
||||||
|
proto = *p++;
|
||||||
|
l--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
proto = ntohs(*(uint16_t *) p);
|
||||||
|
p += 2;
|
||||||
|
l -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session[s].forwardtosession)
|
||||||
|
{
|
||||||
|
LOG(5, s, t, "Forwarding data session to session %u\n", session[s].forwardtosession);
|
||||||
|
// Forward to LAC/BAS or Remote LNS session
|
||||||
|
lac_session_forward(buf, len, s, proto, addr->sin_addr.s_addr, addr->sin_port, indexudpfd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (config->auth_tunnel_change_addr_src)
|
||||||
|
{
|
||||||
|
if (tunnel[t].ip != ntohl(addr->sin_addr.s_addr) &&
|
||||||
|
tunnel[t].port == ntohs(addr->sin_port))
|
||||||
{
|
{
|
||||||
LOG(5, s, t, "Forwarding data session to session %u\n", session[s].forwardtosession);
|
// The remotes BAS are a clustered l2tpns server and the source IP has changed
|
||||||
// Forward to LAC/BAS or Remote LNS session
|
LOG(5, s, t, "The tunnel IP source (%s) has changed by new IP (%s)\n",
|
||||||
lac_session_forward(buf, len, s, proto, addr->sin_addr.s_addr, addr->sin_port, indexudpfd);
|
fmtaddr(htonl(tunnel[t].ip), 0), fmtaddr(addr->sin_addr.s_addr, 0));
|
||||||
return;
|
|
||||||
|
tunnel[t].ip = ntohl(addr->sin_addr.s_addr);
|
||||||
}
|
}
|
||||||
else if (config->auth_tunnel_change_addr_src)
|
}
|
||||||
|
|
||||||
|
if (s && !session[s].opened) // Is something wrong??
|
||||||
|
{
|
||||||
|
if (!config->cluster_iam_master)
|
||||||
{
|
{
|
||||||
if (tunnel[t].ip != ntohl(addr->sin_addr.s_addr) &&
|
// Pass it off to the master to deal with..
|
||||||
tunnel[t].port == ntohs(addr->sin_port))
|
master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd);
|
||||||
{
|
|
||||||
// The remotes BAS are a clustered l2tpns server and the source IP has changed
|
|
||||||
LOG(5, s, t, "The tunnel IP source (%s) has changed by new IP (%s)\n",
|
|
||||||
fmtaddr(htonl(tunnel[t].ip), 0), fmtaddr(addr->sin_addr.s_addr, 0));
|
|
||||||
|
|
||||||
tunnel[t].ip = ntohl(addr->sin_addr.s_addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s && !session[s].opened) // Is something wrong??
|
|
||||||
{
|
|
||||||
if (!config->cluster_iam_master)
|
|
||||||
{
|
|
||||||
// Pass it off to the master to deal with..
|
|
||||||
master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(1, s, t, "UDP packet contains session which is not opened. Dropping packet.\n");
|
|
||||||
STAT(tunnel_rx_errors);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proto == PPPPAP)
|
LOG(1, s, t, "UDP packet contains session which is not opened. Dropping packet.\n");
|
||||||
{
|
STAT(tunnel_rx_errors);
|
||||||
session[s].last_packet = time_now;
|
return;
|
||||||
if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; }
|
}
|
||||||
processpap(s, t, p, l);
|
|
||||||
}
|
|
||||||
else if (proto == PPPCHAP)
|
|
||||||
{
|
|
||||||
session[s].last_packet = time_now;
|
|
||||||
if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; }
|
|
||||||
processchap(s, t, p, l);
|
|
||||||
}
|
|
||||||
else if (proto == PPPLCP)
|
|
||||||
{
|
|
||||||
session[s].last_packet = time_now;
|
|
||||||
if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; }
|
|
||||||
processlcp(s, t, p, l);
|
|
||||||
}
|
|
||||||
else if (proto == PPPIPCP)
|
|
||||||
{
|
|
||||||
session[s].last_packet = time_now;
|
|
||||||
if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; }
|
|
||||||
processipcp(s, t, p, l);
|
|
||||||
}
|
|
||||||
else if (proto == PPPIPV6CP && config->ipv6_prefix.s6_addr[0])
|
|
||||||
{
|
|
||||||
session[s].last_packet = time_now;
|
|
||||||
if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; }
|
|
||||||
processipv6cp(s, t, p, l);
|
|
||||||
}
|
|
||||||
else if (proto == PPPCCP)
|
|
||||||
{
|
|
||||||
session[s].last_packet = time_now;
|
|
||||||
if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; }
|
|
||||||
processccp(s, t, p, l);
|
|
||||||
}
|
|
||||||
else if (proto == PPPIP)
|
|
||||||
{
|
|
||||||
if (session[s].die)
|
|
||||||
{
|
|
||||||
LOG(4, s, t, "Session %u is closing. Don't process PPP packets\n", s);
|
|
||||||
return; // closing session, PPP not processed
|
|
||||||
}
|
|
||||||
|
|
||||||
session[s].last_packet = session[s].last_data = time_now;
|
if (proto == PPPPAP)
|
||||||
if (session[s].walled_garden && !config->cluster_iam_master)
|
{
|
||||||
|
session[s].last_packet = time_now;
|
||||||
|
if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; }
|
||||||
|
processpap(s, t, p, l);
|
||||||
|
}
|
||||||
|
else if (proto == PPPCHAP)
|
||||||
|
{
|
||||||
|
session[s].last_packet = time_now;
|
||||||
|
if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; }
|
||||||
|
processchap(s, t, p, l);
|
||||||
|
}
|
||||||
|
else if (proto == PPPLCP)
|
||||||
|
{
|
||||||
|
session[s].last_packet = time_now;
|
||||||
|
if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; }
|
||||||
|
processlcp(s, t, p, l);
|
||||||
|
}
|
||||||
|
else if (proto == PPPIPCP)
|
||||||
|
{
|
||||||
|
session[s].last_packet = time_now;
|
||||||
|
if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; }
|
||||||
|
processipcp(s, t, p, l);
|
||||||
|
}
|
||||||
|
else if (proto == PPPIPV6CP && config->ipv6_prefix.s6_addr[0])
|
||||||
|
{
|
||||||
|
session[s].last_packet = time_now;
|
||||||
|
if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; }
|
||||||
|
processipv6cp(s, t, p, l);
|
||||||
|
}
|
||||||
|
else if (proto == PPPCCP)
|
||||||
|
{
|
||||||
|
session[s].last_packet = time_now;
|
||||||
|
if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; }
|
||||||
|
processccp(s, t, p, l);
|
||||||
|
}
|
||||||
|
else if (proto == PPPIP)
|
||||||
|
{
|
||||||
|
if (session[s].die)
|
||||||
|
{
|
||||||
|
LOG(4, s, t, "Session %u is closing. Don't process PPP packets\n", s);
|
||||||
|
return; // closing session, PPP not processed
|
||||||
|
}
|
||||||
|
|
||||||
|
session[s].last_packet = session[s].last_data = time_now;
|
||||||
|
if (session[s].walled_garden && !config->cluster_iam_master)
|
||||||
|
{
|
||||||
|
master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
processipin(s, t, p, l);
|
||||||
|
}
|
||||||
|
else if (proto == PPPMP)
|
||||||
|
{
|
||||||
|
if (session[s].die)
|
||||||
|
{
|
||||||
|
LOG(4, s, t, "Session %u is closing. Don't process PPP packets\n", s);
|
||||||
|
return; // closing session, PPP not processed
|
||||||
|
}
|
||||||
|
|
||||||
|
session[s].last_packet = session[s].last_data = time_now;
|
||||||
|
if (!config->cluster_iam_master)
|
||||||
|
{
|
||||||
|
// The fragments reconstruction is managed by the Master.
|
||||||
|
master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
processmpin(s, t, p, l);
|
||||||
|
}
|
||||||
|
else if (proto == PPPIPV6 && config->ipv6_prefix.s6_addr[0])
|
||||||
|
{
|
||||||
|
if (session[s].die)
|
||||||
|
{
|
||||||
|
LOG(4, s, t, "Session %u is closing. Don't process PPP packets\n", s);
|
||||||
|
return; // closing session, PPP not processed
|
||||||
|
}
|
||||||
|
|
||||||
|
session[s].last_packet = session[s].last_data = time_now;
|
||||||
|
if (session[s].walled_garden && !config->cluster_iam_master)
|
||||||
|
{
|
||||||
|
master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config->cluster_iam_master)
|
||||||
|
{
|
||||||
|
// Check if DhcpV6, IP dst: FF02::1:2, Src Port 0x0222 (546), Dst Port 0x0223 (547)
|
||||||
|
if (*(p + 6) == 17 && *(p + 24) == 0xFF && *(p + 25) == 2 &&
|
||||||
|
*(uint32_t *)(p + 26) == 0 && *(uint32_t *)(p + 30) == 0 &&
|
||||||
|
*(uint16_t *)(p + 34) == 0 && *(p + 36) == 0 && *(p + 37) == 1 && *(p + 38) == 0 && *(p + 39) == 2 &&
|
||||||
|
*(p + 40) == 2 && *(p + 41) == 0x22 && *(p + 42) == 2 && *(p + 43) == 0x23)
|
||||||
{
|
{
|
||||||
|
// DHCPV6 must be managed by the Master.
|
||||||
master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd);
|
master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
processipin(s, t, p, l);
|
|
||||||
}
|
}
|
||||||
else if (proto == PPPMP)
|
|
||||||
{
|
|
||||||
if (session[s].die)
|
|
||||||
{
|
|
||||||
LOG(4, s, t, "Session %u is closing. Don't process PPP packets\n", s);
|
|
||||||
return; // closing session, PPP not processed
|
|
||||||
}
|
|
||||||
|
|
||||||
session[s].last_packet = session[s].last_data = time_now;
|
processipv6in(s, t, p, l);
|
||||||
if (!config->cluster_iam_master)
|
}
|
||||||
{
|
else if (session[s].ppp.lcp == Opened)
|
||||||
// The fragments reconstruction is managed by the Master.
|
{
|
||||||
master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd);
|
session[s].last_packet = time_now;
|
||||||
return;
|
if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; }
|
||||||
}
|
protoreject(s, t, p, l, proto);
|
||||||
|
}
|
||||||
processmpin(s, t, p, l);
|
else
|
||||||
}
|
{
|
||||||
else if (proto == PPPIPV6 && config->ipv6_prefix.s6_addr[0])
|
LOG(2, s, t, "Unknown PPP protocol 0x%04X received in LCP %s state\n",
|
||||||
{
|
proto, ppp_state(session[s].ppp.lcp));
|
||||||
if (session[s].die)
|
|
||||||
{
|
|
||||||
LOG(4, s, t, "Session %u is closing. Don't process PPP packets\n", s);
|
|
||||||
return; // closing session, PPP not processed
|
|
||||||
}
|
|
||||||
|
|
||||||
session[s].last_packet = session[s].last_data = time_now;
|
|
||||||
if (session[s].walled_garden && !config->cluster_iam_master)
|
|
||||||
{
|
|
||||||
master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!config->cluster_iam_master)
|
|
||||||
{
|
|
||||||
// Check if DhcpV6, IP dst: FF02::1:2, Src Port 0x0222 (546), Dst Port 0x0223 (547)
|
|
||||||
if (*(p + 6) == 17 && *(p + 24) == 0xFF && *(p + 25) == 2 &&
|
|
||||||
*(uint32_t *)(p + 26) == 0 && *(uint32_t *)(p + 30) == 0 &&
|
|
||||||
*(uint16_t *)(p + 34) == 0 && *(p + 36) == 0 && *(p + 37) == 1 && *(p + 38) == 0 && *(p + 39) == 2 &&
|
|
||||||
*(p + 40) == 2 && *(p + 41) == 0x22 && *(p + 42) == 2 && *(p + 43) == 0x23)
|
|
||||||
{
|
|
||||||
// DHCPV6 must be managed by the Master.
|
|
||||||
master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
processipv6in(s, t, p, l);
|
|
||||||
}
|
|
||||||
else if (session[s].ppp.lcp == Opened)
|
|
||||||
{
|
|
||||||
session[s].last_packet = time_now;
|
|
||||||
if (!config->cluster_iam_master) { master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port, indexudpfd); return; }
|
|
||||||
protoreject(s, t, p, l, proto);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG(2, s, t, "Unknown PPP protocol 0x%04X received in LCP %s state\n",
|
|
||||||
proto, ppp_state(session[s].ppp.lcp));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue