l2tplac: Delay considering the tunnel to LNS open until SCCCN ack

We are not really supposed to send ICRQ until we got our SCCCN acked, so better
wait for it.
This commit is contained in:
Samuel Thibault 2025-03-09 17:48:28 +01:00
parent 6f04a5c390
commit b48dfb2697
2 changed files with 18 additions and 5 deletions

View file

@ -3483,14 +3483,15 @@ static void controlnull(tunnelidt t)
} }
// add a control message to a tunnel, and send if within window // add a control message to a tunnel, and send if within window
static void controladd(controlt *c, sessionidt far, tunnelidt t) static uint16_t controladd(controlt *c, sessionidt far, tunnelidt t)
{ {
uint16_t *pint16 = (uint16_t *) (c->buf + 2); uint16_t *pint16 = (uint16_t *) (c->buf + 2);
uint16_t ns;
pint16[0] = htons(c->length); // length pint16[0] = htons(c->length); // length
pint16[1] = htons(tunnel[t].far); // tunnel pint16[1] = htons(tunnel[t].far); // tunnel
pint16[2] = htons(far); // session pint16[2] = htons(far); // session
pint16[3] = htons(tunnel[t].ns); // sequence ns = tunnel[t].ns++; // advance sequence
tunnel[t].ns++; // advance sequence pint16[3] = htons(ns); // sequence
// link in message in to queue // link in message in to queue
if (tunnel[t].controlc) if (tunnel[t].controlc)
tunnel[t].controle->next = c; tunnel[t].controle->next = c;
@ -3506,6 +3507,7 @@ static void controladd(controlt *c, sessionidt far, tunnelidt t)
tunnel[t].try = 0; // first send tunnel[t].try = 0; // first send
tunnelsend(c->buf, c->length, t); tunnelsend(c->buf, c->length, t);
} }
return ns;
} }
// //
@ -3904,6 +3906,7 @@ static void tunnelclear(tunnelidt t)
tunn_local[t].l2tp_fd = -1; tunn_local[t].l2tp_fd = -1;
tunnel[t].state = TUNNELFREE; tunnel[t].state = TUNNELFREE;
tunn_local[t].scccn = -1;
} }
static void bundleclear(bundleidt b) static void bundleclear(bundleidt b)
@ -4279,6 +4282,15 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu
if (!tunnel[t].controlc) if (!tunnel[t].controlc)
tunnel[t].retry = 0; // caught up tunnel[t].retry = 0; // caught up
} }
{
// Handle ack (possibly just a ZLB)
if (tunn_local[t].scccn >= 0 && ((uint16_t) tunn_local[t].scccn) - nr >= 0x8000u)
{
LOG(3, s, t, "REMOTE LNS acked our SCCCN %d\n", tunn_local[t].scccn);
tunn_local[t].scccn = -1;
tunnel[t].state = TUNNELOPEN;
}
}
if (l) if (l)
{ // if not a null message { // if not a null message
int result = 0; int result = 0;
@ -4750,7 +4762,6 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu
} }
break; break;
case 2: // SCCRP case 2: // SCCRP
tunnel[t].state = TUNNELOPEN;
tunnel[t].lastrec = time_now; tunnel[t].lastrec = time_now;
LOG(3, s, t, "Received SCCRP\n"); LOG(3, s, t, "Received SCCRP\n");
if (main_quit != QUIT_SHUTDOWN) if (main_quit != QUIT_SHUTDOWN)
@ -4772,7 +4783,8 @@ void processudp(uint8_t *buf, int len, struct sockaddr_in *addr, uint16_t indexu
control32(c, 3, 3, 1); // framing Capabilities control32(c, 3, 3, 1); // framing Capabilities
if (sendchalresponse) controlb(c, 13, sendchalresponse, 16, 1); // Challenge response if (sendchalresponse) controlb(c, 13, sendchalresponse, 16, 1); // Challenge response
control16(c, 9, t, 1); // assigned tunnel control16(c, 9, t, 1); // assigned tunnel
controladd(c, 0, t); // send tunn_local[t].scccn = controladd(c, 0, t); // send
LOG(3, s, t, "sent SCCCN as %d\n", tunn_local[t].scccn);
} }
else else
{ {

View file

@ -517,6 +517,7 @@ tunnelt;
typedef struct typedef struct
{ {
int32_t scccn; // seq number of last sccn waiting for an ack (-1 if none)
controlt *controlr; // queue of OoO-received messages controlt *controlr; // queue of OoO-received messages
int l2tp_fd; // kernel acceleration UDP socket int l2tp_fd; // kernel acceleration UDP socket
} }