// Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced
// vim: sw=8 ts=8
-char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.60 2004/11/29 02:17:17 bodea Exp $";
+char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.63 2004/12/09 00:50:45 bodea Exp $";
#include <arpa/inet.h>
#include <assert.h>
// TBA - should we wait for sessions to stop?
{ // Send StopCCN
controlt *c = controlnew(4); // sending StopCCN
- control16(c, 1, 1, 1); // result code (admin reasons - TBA make error, general error, add message
+ control16(c, 1, 1, 1); // result code (admin reasons - TBA make error, general error, add message)
control16(c, 9, t, 1); // assigned tunnel (our end)
controladd(c, t, 0); // send the message
}
case 39: // seq required - we control it as an LNS anyway...
break;
case 36: // Random Vector
- LOG(4, s, t, " Random Vector received. Enabled AVP Hiding.\n");
+ LOG(4, s, t, " Random Vector received. Enabled AVP Hiding.\n");
memset(session[s].random_vector, 0, sizeof(session[s].random_vector));
memcpy(session[s].random_vector, b, n);
session[s].random_vector_length = n;
return;
}
- if (session[s].die)
- {
- LOG(3, s, t, "Session %d is closing. Don't process PPP packets\n", s);
-// I'm pretty sure this isn't right -- mo.
-// return; // closing session, PPP not processed
- }
if (prot == PPPPAP)
{
session[s].last_packet = time_now;
}
else if (prot == PPPIP)
{
+ if (session[s].die)
+ {
+ LOG(4, s, t, "Session %d is closing. Don't process PPP packets\n", s);
+ return; // closing session, PPP not processed
+ }
+
session[s].last_packet = time_now;
if (session[s].walled_garden && !config->cluster_iam_master)
{
master_forward_packet(buf, len, addr->sin_addr.s_addr, addr->sin_port);
return;
}
+
processipin(t, s, p, l);
}
else
// We stop waiting for radius after BUSY_WAIT_TIME 1/10th seconds
if (abs(TIME - start_busy_wait) > BUSY_WAIT_TIME)
{
- LOG(1, 0, 0, "Giving up waiting for RADIUS to be empty. Shutting down anyway.\n");
+ LOG(1, 0, 0, "Giving up waiting for RADIUS to be empty. Shutting down anyway.\n");
return 0;
}
clockt next_cluster_ping = 0; // send initial ping immediately
time_t next_clean = time_now + config->cleanup_interval;
- LOG(4, 0, 0, "Beginning of main loop. udpfd=%d, tunfd=%d, cluster_sockfd=%d, controlfd=%d\n",
+ LOG(4, 0, 0, "Beginning of main loop. udpfd=%d, tunfd=%d, cluster_sockfd=%d, controlfd=%d\n",
udpfd, tunfd, cluster_sockfd, controlfd);
FD_ZERO(&readset);
else if (n)
{
struct sockaddr_in addr;
- int alen = sizeof(addr);
- if (FD_ISSET(udpfd, &r))
- {
- int c, n;
- for (c = 0; c < config->multi_read_count; c++)
- {
- if ((n = recvfrom(udpfd, buf, sizeof(buf), 0, (void *) &addr, &alen)) > 0)
- processudp(buf, n, &addr);
- else
- break;
- }
- }
- if (FD_ISSET(tunfd, &r))
+ int alen, c, s;
+
+ // nsctl commands
+ if (FD_ISSET(controlfd, &r))
{
- int c, n;
- for (c = 0; c < config->multi_read_count; c++)
- {
- if ((n = read(tunfd, buf, sizeof(buf))) > 0)
- processtun(buf, n);
- else
- break;
- }
+ alen = sizeof(addr);
+ processcontrol(buf, recvfrom(controlfd, buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen), &addr, alen);
+ n--;
}
+ // RADIUS responses
if (config->cluster_iam_master)
+ {
for (i = 0; i < config->num_radfds; i++)
+ {
if (FD_ISSET(radfds[i], &r))
+ {
processrad(buf, recv(radfds[i], buf, sizeof(buf), 0), i);
+ n--;
+ }
+ }
+ }
- if (FD_ISSET(cluster_sockfd, &r))
+ // CLI connections
+ if (FD_ISSET(clifd, &r))
{
- int size;
- size = recvfrom(cluster_sockfd, buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen);
- processcluster(buf, size, addr.sin_addr.s_addr);
+ int cli;
+
+ alen = sizeof(addr);
+ if ((cli = accept(clifd, (struct sockaddr *)&addr, &len)) >= 0)
+ {
+ cli_do(cli);
+ close(cli);
+ }
+ else
+ LOG(0, 0, 0, "accept error: %s\n", strerror(errno));
+
+ n--;
}
- if (FD_ISSET(controlfd, &r))
- processcontrol(buf, recvfrom(controlfd, buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen), &addr, alen);
+#ifdef BGP
+ for (i = 0; i < BGP_NUM_PEERS; i++)
+ {
+ int isr = bgp_set[i] ? FD_ISSET(bgp_peers[i].sock, &r) : 0;
+ int isw = bgp_set[i] ? FD_ISSET(bgp_peers[i].sock, &w) : 0;
+ bgp_process(&bgp_peers[i], isr, isw);
+ if (isr) n--;
+ if (isw) n--;
+ }
+#endif /* BGP */
- if (FD_ISSET(clifd, &r))
+ for (c = 0; n && c < config->multi_read_count; c++)
{
- struct sockaddr_in addr;
- int sockfd;
- int len = sizeof(addr);
+ // L2TP
+ if (FD_ISSET(udpfd, &r))
+ {
+ alen = sizeof(addr);
+ if ((s = recvfrom(udpfd, buf, sizeof(buf), 0, (void *) &addr, &alen)) > 0)
+ {
+ processudp(buf, s, &addr);
+ }
+ else
+ {
+ FD_CLR(udpfd, &r);
+ n--;
+ }
+ }
- if ((sockfd = accept(clifd, (struct sockaddr *)&addr, &len)) <= 0)
+ // incoming IP
+ if (FD_ISSET(tunfd, &r))
{
- LOG(0, 0, 0, "accept error: %s\n", strerror(errno));
- continue;
+ if ((n = read(tunfd, buf, sizeof(buf))) > 0)
+ {
+ processtun(buf, n);
+ }
+ else
+ {
+ FD_CLR(tunfd, &r);
+ n--;
+ }
}
- else
+
+ // cluster
+ if (FD_ISSET(cluster_sockfd, &r))
{
- cli_do(sockfd);
- close(sockfd);
+ alen = sizeof(addr);
+ if ((s = recvfrom(cluster_sockfd, buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen)) > 0)
+ {
+ processcluster(buf, s, addr.sin_addr.s_addr);
+ }
+ else
+ {
+ FD_CLR(cluster_sockfd, &r);
+ n--;
+ }
}
}
}
next_clean = time_now + config->cleanup_interval; // Did. Move to next interval.
}
}
-
-#ifdef BGP
- for (i = 0; i < BGP_NUM_PEERS; i++)
- {
- bgp_process(&bgp_peers[i],
- bgp_set[i] ? FD_ISSET(bgp_peers[i].sock, &r) : 0,
- bgp_set[i] ? FD_ISSET(bgp_peers[i].sock, &w) : 0);
- }
-#endif /* BGP */
}
// Are we the master and shutting down??
{
if ((ret = sched_setscheduler(0, SCHED_FIFO, ¶ms)) == 0)
{
- LOG(1, 0, 0, "Using FIFO scheduler. Say goodbye to any other processes running\n");
+ LOG(1, 0, 0, "Using FIFO scheduler. Say goodbye to any other processes running\n");
}
else
{
assign_ip_address(s);
if (!session[s].ip)
{
- LOG(0, s, t, " No IP allocated. The IP address pool is FULL!\n");
+ LOG(0, s, t, " No IP allocated. The IP address pool is FULL!\n");
sessionshutdown(s, "No IP addresses available");
return 0;
}
- LOG(3, s, t, " No IP allocated. Assigned %s from pool\n",
+ LOG(3, s, t, " No IP allocated. Assigned %s from pool\n",
fmtaddr(htonl(session[s].ip), 0));
}
if (len < 20) // up to end of destination address
return 0;
- if (*buf >> 4) // IPv4
+ if ((*buf >> 4) != 4) // IPv4
return 0;
-
- frag_offset = ntohs(*(u16 *) (buf + 0)) & 0x1fff;
+ frag_offset = ntohs(*(u16 *) (buf + 6)) & 0x1fff;
proto = buf[9];
src_ip = *(u32 *) (buf + 12);
dst_ip = *(u32 *) (buf + 16);
if (frag_offset == 0 && (proto == IPPROTO_TCP || proto == IPPROTO_UDP))
{
- int l = buf[0] & 0xf;
+ int l = (buf[0] & 0xf) * 4; // length of IP header
if (len < l + 4) // ports
return 0;
dst_port = ntohs(*(u16 *) (buf + l + 2));
if (proto == IPPROTO_TCP)
{
- if (len < l + 15) // flags
+ if (len < l + 14) // flags
return 0;
- flags = buf[l + 14] & 0x3f;
+ flags = buf[l + 13] & 0x3f;
}
}
for (rule = ip_filters[filter].rules; rule->action; rule++)
{
- if (proto && proto != rule->proto)
+ if (rule->proto != IPPROTO_IP && proto != rule->proto)
continue;
if (rule->src_wild != INADDR_BROADCAST &&