Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
54d36d7512
5 changed files with 548 additions and 187 deletions
588
ppp.c
588
ppp.c
|
|
@ -556,6 +556,437 @@ static void ppp_code_rej(sessionidt s, tunnelidt t, uint16_t proto,
|
|||
tunnelsend(buf, l + (q - buf), t);
|
||||
}
|
||||
|
||||
// Process received LCP options from o from packet p.
|
||||
// Set changed to 1 if we changed configuration that should be sent to cluster slaves, fill response on nak or rej
|
||||
static void processreceivedlcpconfreq(sessionidt s, tunnelidt t, uint8_t *p, uint8_t *o, uint16_t x, int *changed, uint8_t **response)
|
||||
{
|
||||
static uint8_t asyncmap[4] = { 0, 0, 0, 0 }; // all zero
|
||||
static uint8_t authproto[5];
|
||||
uint8_t b[MAXETHER];
|
||||
uint8_t *q = NULL;
|
||||
|
||||
while (x > 2)
|
||||
{
|
||||
int type = o[0];
|
||||
int length = o[1];
|
||||
|
||||
if (length == 0 || length == 1 || type == 0 || x < length) break;
|
||||
switch (type)
|
||||
{
|
||||
case 1: // Maximum-Receive-Unit
|
||||
{
|
||||
uint16_t mru = ntohs(*(uint16_t *)(o + 2));
|
||||
if (mru >= MINMTU)
|
||||
{
|
||||
session[s].mru = mru;
|
||||
(*changed)++;
|
||||
break;
|
||||
}
|
||||
|
||||
LOG(3, s, t, " Remote requesting MRU of %u. Rejecting.\n", mru);
|
||||
mru = htons(MRU);
|
||||
q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, response, q, p, o, (uint8_t *) &mru, sizeof(mru));
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // Async-Control-Character-Map
|
||||
if (!ntohl(*(uint32_t *)(o + 2))) // all bits zero is OK
|
||||
break;
|
||||
|
||||
LOG(3, s, t, " Remote requesting asyncmap. Rejecting.\n");
|
||||
q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, response, q, p, o, asyncmap, sizeof(asyncmap));
|
||||
break;
|
||||
|
||||
case 3: // Authentication-Protocol
|
||||
{
|
||||
int proto = ntohs(*(uint16_t *)(o + 2));
|
||||
char proto_name[] = "0x0000";
|
||||
int alen;
|
||||
|
||||
if (proto == PPPPAP)
|
||||
{
|
||||
if (config->radius_authtypes & AUTHPAP)
|
||||
{
|
||||
sess_local[s].lcp_authtype = AUTHPAP;
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy(proto_name, "PAP");
|
||||
}
|
||||
else if (proto == PPPCHAP)
|
||||
{
|
||||
if (config->radius_authtypes & AUTHCHAP
|
||||
&& *(o + 4) == 5) // MD5
|
||||
{
|
||||
sess_local[s].lcp_authtype = AUTHCHAP;
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy(proto_name, "CHAP");
|
||||
}
|
||||
else
|
||||
sprintf(proto_name, "%#4.4x", proto);
|
||||
|
||||
LOG(3, s, t, " Remote requesting %s authentication. Rejecting.\n", proto_name);
|
||||
|
||||
alen = add_lcp_auth(authproto, sizeof(authproto), config->radius_authprefer);
|
||||
if (alen < 2) break; // paranoia
|
||||
|
||||
q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, response, q, p, o, authproto + 2, alen - 2);
|
||||
if (q && **response == ConfigNak &&
|
||||
config->radius_authtypes != config->radius_authprefer)
|
||||
{
|
||||
// alternate type
|
||||
alen = add_lcp_auth(authproto, sizeof(authproto), config->radius_authtypes & ~config->radius_authprefer);
|
||||
if (alen < 2) break;
|
||||
q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, response, q, p, o, authproto + 2, alen - 2);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: // Quality-Protocol
|
||||
case 5: // Magic-Number
|
||||
case 7: // Protocol-Field-Compression
|
||||
case 8: // Address-And-Control-Field-Compression
|
||||
break;
|
||||
|
||||
case 17: // Multilink Max-Receive-Reconstructed-Unit
|
||||
{
|
||||
uint16_t mrru = ntohs(*(uint16_t *)(o + 2));
|
||||
session[s].mrru = mrru;
|
||||
(*changed)++;
|
||||
LOG(3, s, t, " Received PPP LCP option MRRU: %d\n",mrru);
|
||||
}
|
||||
break;
|
||||
|
||||
case 18: // Multilink Short Sequence Number Header Format
|
||||
{
|
||||
session[s].mssf = 1;
|
||||
(*changed)++;
|
||||
LOG(3, s, t, " Received PPP LCP option MSSN format\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case 19: // Multilink Endpoint Discriminator
|
||||
{
|
||||
uint8_t epdis_class = o[2];
|
||||
int addr;
|
||||
|
||||
session[s].epdis.addr_class = epdis_class;
|
||||
session[s].epdis.length = length - 3;
|
||||
if (session[s].epdis.length > 20)
|
||||
{
|
||||
LOG(1, s, t, "Error: received EndDis Address Length more than 20: %d\n", session[s].epdis.length);
|
||||
session[s].epdis.length = 20;
|
||||
}
|
||||
|
||||
for (addr = 0; addr < session[s].epdis.length; addr++)
|
||||
session[s].epdis.address[addr] = o[3+addr];
|
||||
|
||||
(*changed)++;
|
||||
|
||||
switch (epdis_class)
|
||||
{
|
||||
case LOCALADDR:
|
||||
LOG(3, s, t, " Received PPP LCP option Multilink EndDis Local Address Class: %d\n",epdis_class);
|
||||
break;
|
||||
case IPADDR:
|
||||
LOG(3, s, t, " Received PPP LCP option Multilink EndDis IP Address Class: %d\n",epdis_class);
|
||||
break;
|
||||
case IEEEMACADDR:
|
||||
LOG(3, s, t, " Received PPP LCP option Multilink EndDis IEEE MAC Address Class: %d\n",epdis_class);
|
||||
break;
|
||||
case PPPMAGIC:
|
||||
LOG(3, s, t, " Received PPP LCP option Multilink EndDis PPP Magic No Class: %d\n",epdis_class);
|
||||
break;
|
||||
case PSNDN:
|
||||
LOG(3, s, t, " Received PPP LCP option Multilink EndDis PSND No Class: %d\n",epdis_class);
|
||||
break;
|
||||
default:
|
||||
LOG(3, s, t, " Received PPP LCP option Multilink EndDis NULL Class %d\n",epdis_class);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: // Reject any unknown options
|
||||
LOG(3, s, t, " Rejecting unknown PPP LCP option %d\n", type);
|
||||
q = ppp_conf_rej(s, b, sizeof(b), PPPLCP, response, q, p, o);
|
||||
}
|
||||
x -= length;
|
||||
o += length;
|
||||
}
|
||||
}
|
||||
|
||||
// Process sent LCP options from o
|
||||
// Set changed to 1 if we changed configuration that should be sent to cluster slaves
|
||||
static int processsentlcpconfreq(sessionidt s, tunnelidt t, uint8_t *p, uint8_t *o, uint16_t x, int *changed)
|
||||
{
|
||||
int auth = 0;
|
||||
int ok = 1;
|
||||
|
||||
while (x > 2)
|
||||
{
|
||||
int type = o[0];
|
||||
int length = o[1];
|
||||
|
||||
if (length == 0 || length == 1 || type == 0 || x < length) break;
|
||||
switch (type)
|
||||
{
|
||||
case 1: // Maximum-Receive-Unit
|
||||
{
|
||||
uint16_t mru = ntohs(*(uint16_t *)(o + 2));
|
||||
if (mru >= MINMTU)
|
||||
{
|
||||
sess_local[s].ppp_mru = mru;
|
||||
break;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: // Async-Control-Character-Map
|
||||
if (ntohl(*(uint32_t *)(o + 2)))
|
||||
ok = 0;
|
||||
break;
|
||||
|
||||
case 3: // Authentication-Protocol
|
||||
{
|
||||
int proto = ntohs(*(uint16_t *)(o + 2));
|
||||
|
||||
if (proto == PPPPAP)
|
||||
{
|
||||
if (config->radius_authtypes & AUTHPAP)
|
||||
{
|
||||
auth = sess_local[s].lcp_authtype = AUTHPAP;
|
||||
break;
|
||||
}
|
||||
ok = 0;
|
||||
}
|
||||
else if (proto == PPPCHAP)
|
||||
{
|
||||
if (config->radius_authtypes & AUTHCHAP
|
||||
&& *(o + 4) == 5) // MD5
|
||||
{
|
||||
auth = sess_local[s].lcp_authtype = AUTHCHAP;
|
||||
break;
|
||||
}
|
||||
ok = 0;
|
||||
}
|
||||
else
|
||||
ok = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: // Quality-Protocol
|
||||
break;
|
||||
|
||||
case 5: // Magic-Number
|
||||
if (length < 6) break;
|
||||
session[s].magic = ntohl(*(uint32_t *)(o + 2));
|
||||
*changed = 1;
|
||||
break;
|
||||
|
||||
case 7: // Protocol-Field-Compression
|
||||
session[s].flags |= SESSION_PFC;
|
||||
*changed = 1;
|
||||
break;
|
||||
case 8: // Address-And-Control-Field-Compression
|
||||
session[s].flags |= SESSION_ACFC;
|
||||
*changed = 1;
|
||||
break;
|
||||
|
||||
case 17: // Multilink Max-Receive-Reconstructed-Unit
|
||||
sess_local[s].mp_mrru = ntohs(*(uint16_t *)(o + 2));
|
||||
break;
|
||||
|
||||
case 18: // Multilink Short Sequence Number Header Format
|
||||
sess_local[s].mp_mssf = 1;
|
||||
break;
|
||||
|
||||
case 19: // Multilink Endpoint Discriminator
|
||||
ok = 0;
|
||||
break;
|
||||
|
||||
default: // Reject any unknown options
|
||||
ok = 0;
|
||||
break;
|
||||
}
|
||||
x -= length;
|
||||
o += length;
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
// Return after taking note of magic and flags
|
||||
return 0;
|
||||
|
||||
if (sess_local[s].lcp_authtype && !auth)
|
||||
// We do want authentication, we have to check with client
|
||||
return 0;
|
||||
|
||||
if (sess_local[s].mp_epdis)
|
||||
// We do want Endpoint Discriminator
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Try to use LCP proxy to avoid renegotiating it (in case the LAC doesn't support passing LCP through)
|
||||
int processlcpproxy(sessionidt s, tunnelidt t, uint8_t *sent_lcp, uint16_t sent_lcp_n, uint8_t *received_lcp, uint16_t received_lcp_n)
|
||||
{
|
||||
uint8_t *response = 0;
|
||||
int changed = 0;
|
||||
|
||||
if (!strcmp(config->lcp_renegotiation, "always"))
|
||||
/* We always renegotiate */
|
||||
return 0;
|
||||
|
||||
LOG(3, s, t, "Trying to reuse the LAC sent and received LCP configuration:\n");
|
||||
if (config->debug >= 3)
|
||||
{
|
||||
dumplcp(sent_lcp, sent_lcp_n);
|
||||
dumplcp(received_lcp, received_lcp_n);
|
||||
}
|
||||
|
||||
/* Check what configuration the LAC sent */
|
||||
if (!processsentlcpconfreq(s, t, NULL, sent_lcp, sent_lcp_n, &changed))
|
||||
{
|
||||
LOG(3, s, t, "Sent LCP conf does not match\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check what configuration the LAC received */
|
||||
processreceivedlcpconfreq(s, t, NULL, received_lcp, received_lcp_n, &changed, &response);
|
||||
if (response)
|
||||
{
|
||||
LOG(3, s, t, "Received LCP conf does not match\n");
|
||||
/* Mismatch, renegotiate */
|
||||
return 0;
|
||||
}
|
||||
LOG(3, s, t, "LCP conf match\n");
|
||||
|
||||
if (changed)
|
||||
cluster_send_session(s);
|
||||
|
||||
// Ok!
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Try to use auth proxy to avoid renegotiating it (in case the LAC forces PAP)
|
||||
int processauthproxy(sessionidt s, tunnelidt t,
|
||||
uint16_t authtype, const char *authname,
|
||||
size_t authchalln, const char authchall[authchalln],
|
||||
size_t authrespn, const char authresp[authrespn])
|
||||
{
|
||||
uint16_t r;
|
||||
|
||||
if ((sess_local[s].lcp_authtype == 0 && authtype != 0)
|
||||
|| (sess_local[s].lcp_authtype == AUTHPAP && authtype != 3) // PAP
|
||||
|| (sess_local[s].lcp_authtype == AUTHCHAP && authtype != 2)) // CHAP
|
||||
{
|
||||
LOG(3, s, t, "Authentication proxy mismatch: got %u (%s) while expecting %u\n",
|
||||
authtype, ppp_auth_type(authtype), sess_local[s].lcp_authtype);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (session[s].ppp.phase != Authenticate)
|
||||
{
|
||||
LOG(3, s, t, "Already authenticated\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sess_local[s].lcp_authtype == 0)
|
||||
{
|
||||
LOG(4, s, t, "No auth needed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((!config->disable_lac_func) && lac_conf_forwardtoremotelns(s, authname))
|
||||
{
|
||||
// Creating a tunnel/session has been started
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(r = radiusnew(s)))
|
||||
{
|
||||
LOG(1, s, t, "No RADIUS session available to authenticate session...\n");
|
||||
sessionshutdown(s, "No free RADIUS sessions.", CDN_UNAVAILABLE, TERM_SERVICE_UNAVAILABLE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Run PRE_AUTH plugins
|
||||
struct param_pre_auth packet = { &tunnel[t], &session[s], strdup(authname), NULL, 0, 1 };
|
||||
|
||||
if (sess_local[s].lcp_authtype == AUTHPAP)
|
||||
{
|
||||
packet.password = strndup(authresp, authrespn);
|
||||
packet.protocol = PPPPAP;
|
||||
}
|
||||
else if (sess_local[s].lcp_authtype == AUTHCHAP)
|
||||
{
|
||||
if (authchalln != 16)
|
||||
{
|
||||
LOG(1, s, t, "CHAP challenge size different from 16: %zu\n", authchalln);
|
||||
return 0;
|
||||
}
|
||||
if (authrespn != 16)
|
||||
{
|
||||
LOG(1, s, t, "CHAP response size different from 16: %zu\n", authrespn);
|
||||
return 0;
|
||||
}
|
||||
packet.password = calloc(17, 1);
|
||||
memcpy(packet.password, authresp, 16);
|
||||
packet.protocol = PPPCHAP;
|
||||
}
|
||||
else
|
||||
// Not PAP or CHAP??
|
||||
return 0;
|
||||
|
||||
run_plugins(PLUGIN_PRE_AUTH, &packet);
|
||||
if (!packet.continue_auth)
|
||||
{
|
||||
LOG(3, s, t, "A plugin rejected PRE_AUTH\n");
|
||||
if (packet.username) free(packet.username);
|
||||
if (packet.password) free(packet.password);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Take all authentication information from proxy, and record for possibly proxying ourself
|
||||
strncpy(session[s].user, packet.username, sizeof(session[s].user) - 1);
|
||||
strncpy((char *) sess_local[s].auth_name, packet.username, sizeof(sess_local[s].auth_name) - 1);
|
||||
|
||||
if (sess_local[s].lcp_authtype == AUTHPAP)
|
||||
{
|
||||
strncpy(radius[r].pass, packet.password, sizeof(radius[r].pass) - 1);
|
||||
strncpy((char *) sess_local[s].auth_resp, packet.password, sizeof(sess_local[s].auth_resp) - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(radius[r].auth, authchall, 16);
|
||||
memcpy(sess_local[s].auth_chall, authchall, 16);
|
||||
|
||||
memcpy(radius[r].pass, packet.password, 16);
|
||||
memcpy(sess_local[s].auth_resp, packet.password, 16);
|
||||
|
||||
radius[r].chap = 1;
|
||||
}
|
||||
radius[r].id = sess_local[s].auth_id;
|
||||
|
||||
LOG(3, s, t, "Sending login for %s to RADIUS\n", packet.username);
|
||||
|
||||
free(packet.username);
|
||||
free(packet.password);
|
||||
|
||||
if ((session[s].mrru) && (!first_session_in_bundle(s)))
|
||||
radiussend(r, RADIUSJUSTAUTH);
|
||||
else
|
||||
radiussend(r, RADIUSAUTH);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Process LCP messages
|
||||
void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
||||
{
|
||||
|
|
@ -648,165 +1079,10 @@ void processlcp(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l)
|
|||
}
|
||||
else if (*p == ConfigReq)
|
||||
{
|
||||
int x = l - 4;
|
||||
uint8_t *o = (p + 4);
|
||||
uint8_t *response = 0;
|
||||
static uint8_t asyncmap[4] = { 0, 0, 0, 0 }; // all zero
|
||||
static uint8_t authproto[5];
|
||||
int changed = 0;
|
||||
|
||||
while (x > 2)
|
||||
{
|
||||
int type = o[0];
|
||||
int length = o[1];
|
||||
|
||||
if (length == 0 || length == 1 || type == 0 || x < length) break;
|
||||
switch (type)
|
||||
{
|
||||
case 1: // Maximum-Receive-Unit
|
||||
{
|
||||
uint16_t mru = ntohs(*(uint16_t *)(o + 2));
|
||||
if (mru >= MINMTU)
|
||||
{
|
||||
session[s].mru = mru;
|
||||
changed++;
|
||||
break;
|
||||
}
|
||||
|
||||
LOG(3, s, t, " Remote requesting MRU of %u. Rejecting.\n", mru);
|
||||
mru = htons(MRU);
|
||||
q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, &response, q, p, o, (uint8_t *) &mru, sizeof(mru));
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // Async-Control-Character-Map
|
||||
if (!ntohl(*(uint32_t *)(o + 2))) // all bits zero is OK
|
||||
break;
|
||||
|
||||
LOG(3, s, t, " Remote requesting asyncmap. Rejecting.\n");
|
||||
q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, &response, q, p, o, asyncmap, sizeof(asyncmap));
|
||||
break;
|
||||
|
||||
case 3: // Authentication-Protocol
|
||||
{
|
||||
int proto = ntohs(*(uint16_t *)(o + 2));
|
||||
char proto_name[] = "0x0000";
|
||||
int alen;
|
||||
|
||||
if (proto == PPPPAP)
|
||||
{
|
||||
if (config->radius_authtypes & AUTHPAP)
|
||||
{
|
||||
sess_local[s].lcp_authtype = AUTHPAP;
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy(proto_name, "PAP");
|
||||
}
|
||||
else if (proto == PPPCHAP)
|
||||
{
|
||||
if (config->radius_authtypes & AUTHCHAP
|
||||
&& *(o + 4) == 5) // MD5
|
||||
{
|
||||
sess_local[s].lcp_authtype = AUTHCHAP;
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy(proto_name, "CHAP");
|
||||
}
|
||||
else
|
||||
sprintf(proto_name, "%#4.4x", proto);
|
||||
|
||||
LOG(3, s, t, " Remote requesting %s authentication. Rejecting.\n", proto_name);
|
||||
|
||||
alen = add_lcp_auth(authproto, sizeof(authproto), config->radius_authprefer);
|
||||
if (alen < 2) break; // paranoia
|
||||
|
||||
q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, &response, q, p, o, authproto + 2, alen - 2);
|
||||
if (q && *response == ConfigNak &&
|
||||
config->radius_authtypes != config->radius_authprefer)
|
||||
{
|
||||
// alternate type
|
||||
alen = add_lcp_auth(authproto, sizeof(authproto), config->radius_authtypes & ~config->radius_authprefer);
|
||||
if (alen < 2) break;
|
||||
q = ppp_conf_nak(s, b, sizeof(b), PPPLCP, &response, q, p, o, authproto + 2, alen - 2);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: // Quality-Protocol
|
||||
case 5: // Magic-Number
|
||||
case 7: // Protocol-Field-Compression
|
||||
case 8: // Address-And-Control-Field-Compression
|
||||
break;
|
||||
|
||||
case 17: // Multilink Max-Receive-Reconstructed-Unit
|
||||
{
|
||||
uint16_t mrru = ntohs(*(uint16_t *)(o + 2));
|
||||
session[s].mrru = mrru;
|
||||
changed++;
|
||||
LOG(3, s, t, " Received PPP LCP option MRRU: %d\n",mrru);
|
||||
}
|
||||
break;
|
||||
|
||||
case 18: // Multilink Short Sequence Number Header Format
|
||||
{
|
||||
session[s].mssf = 1;
|
||||
changed++;
|
||||
LOG(3, s, t, " Received PPP LCP option MSSN format\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case 19: // Multilink Endpoint Discriminator
|
||||
{
|
||||
uint8_t epdis_class = o[2];
|
||||
int addr;
|
||||
|
||||
session[s].epdis.addr_class = epdis_class;
|
||||
session[s].epdis.length = length - 3;
|
||||
if (session[s].epdis.length > 20)
|
||||
{
|
||||
LOG(1, s, t, "Error: received EndDis Address Length more than 20: %d\n", session[s].epdis.length);
|
||||
session[s].epdis.length = 20;
|
||||
}
|
||||
|
||||
for (addr = 0; addr < session[s].epdis.length; addr++)
|
||||
session[s].epdis.address[addr] = o[3+addr];
|
||||
|
||||
changed++;
|
||||
|
||||
switch (epdis_class)
|
||||
{
|
||||
case LOCALADDR:
|
||||
LOG(3, s, t, " Received PPP LCP option Multilink EndDis Local Address Class: %d\n",epdis_class);
|
||||
break;
|
||||
case IPADDR:
|
||||
LOG(3, s, t, " Received PPP LCP option Multilink EndDis IP Address Class: %d\n",epdis_class);
|
||||
break;
|
||||
case IEEEMACADDR:
|
||||
LOG(3, s, t, " Received PPP LCP option Multilink EndDis IEEE MAC Address Class: %d\n",epdis_class);
|
||||
break;
|
||||
case PPPMAGIC:
|
||||
LOG(3, s, t, " Received PPP LCP option Multilink EndDis PPP Magic No Class: %d\n",epdis_class);
|
||||
break;
|
||||
case PSNDN:
|
||||
LOG(3, s, t, " Received PPP LCP option Multilink EndDis PSND No Class: %d\n",epdis_class);
|
||||
break;
|
||||
default:
|
||||
LOG(3, s, t, " Received PPP LCP option Multilink EndDis NULL Class %d\n",epdis_class);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: // Reject any unknown options
|
||||
LOG(3, s, t, " Rejecting unknown PPP LCP option %d\n", type);
|
||||
q = ppp_conf_rej(s, b, sizeof(b), PPPLCP, &response, q, p, o);
|
||||
}
|
||||
x -= length;
|
||||
o += length;
|
||||
}
|
||||
processreceivedlcpconfreq(s, t, p, p + 4, l - 4, &changed, &response);
|
||||
|
||||
if (changed)
|
||||
cluster_send_session(s);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue