1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD: stable/12/usr.sbin/ppp/cbcp.c 326276 2017-11-27 15:37:16Z pfg $
29 */
30
31 #include <sys/param.h>
32
33 #ifdef __FreeBSD__
34 #include <netinet/in.h>
35 #endif
36 #include <sys/un.h>
37
38 #include <string.h>
39 #include <termios.h>
40
41 #include "layer.h"
42 #include "defs.h"
43 #include "log.h"
44 #include "timer.h"
45 #include "descriptor.h"
46 #include "lqr.h"
47 #include "mbuf.h"
48 #include "fsm.h"
49 #include "throughput.h"
50 #include "hdlc.h"
51 #include "lcp.h"
52 #include "ccp.h"
53 #include "link.h"
54 #include "async.h"
55 #include "physical.h"
56 #include "proto.h"
57 #include "cbcp.h"
58 #include "mp.h"
59 #include "chat.h"
60 #include "auth.h"
61 #include "chap.h"
62 #include "datalink.h"
63
64 void
cbcp_Init(struct cbcp * cbcp,struct physical * p)65 cbcp_Init(struct cbcp *cbcp, struct physical *p)
66 {
67 cbcp->required = 0;
68 cbcp->fsm.state = CBCP_CLOSED;
69 cbcp->fsm.id = 0;
70 cbcp->fsm.delay = 0;
71 *cbcp->fsm.phone = '\0';
72 memset(&cbcp->fsm.timer, '\0', sizeof cbcp->fsm.timer);
73 cbcp->p = p;
74 }
75
76 static void cbcp_SendReq(struct cbcp *);
77 static void cbcp_SendResponse(struct cbcp *);
78 static void cbcp_SendAck(struct cbcp *);
79
80 static void
cbcp_Timeout(void * v)81 cbcp_Timeout(void *v)
82 {
83 struct cbcp *cbcp = (struct cbcp *)v;
84
85 timer_Stop(&cbcp->fsm.timer);
86 if (cbcp->fsm.restart) {
87 switch (cbcp->fsm.state) {
88 case CBCP_CLOSED:
89 case CBCP_STOPPED:
90 log_Printf(LogCBCP, "%s: Urk - unexpected CBCP timeout !\n",
91 cbcp->p->dl->name);
92 break;
93
94 case CBCP_REQSENT:
95 cbcp_SendReq(cbcp);
96 break;
97 case CBCP_RESPSENT:
98 cbcp_SendResponse(cbcp);
99 break;
100 case CBCP_ACKSENT:
101 cbcp_SendAck(cbcp);
102 break;
103 }
104 } else {
105 const char *missed;
106
107 switch (cbcp->fsm.state) {
108 case CBCP_STOPPED:
109 missed = "REQ";
110 break;
111 case CBCP_REQSENT:
112 missed = "RESPONSE";
113 break;
114 case CBCP_RESPSENT:
115 missed = "ACK";
116 break;
117 case CBCP_ACKSENT:
118 missed = "Terminate REQ";
119 break;
120 default:
121 log_Printf(LogCBCP, "%s: Urk - unexpected CBCP timeout !\n",
122 cbcp->p->dl->name);
123 missed = NULL;
124 break;
125 }
126 if (missed)
127 log_Printf(LogCBCP, "%s: Timeout waiting for peer %s\n",
128 cbcp->p->dl->name, missed);
129 datalink_CBCPFailed(cbcp->p->dl);
130 }
131 }
132
133 static void
cbcp_StartTimer(struct cbcp * cbcp,int timeout)134 cbcp_StartTimer(struct cbcp *cbcp, int timeout)
135 {
136 timer_Stop(&cbcp->fsm.timer);
137 cbcp->fsm.timer.func = cbcp_Timeout;
138 cbcp->fsm.timer.name = "cbcp";
139 cbcp->fsm.timer.load = timeout * SECTICKS;
140 cbcp->fsm.timer.arg = cbcp;
141 timer_Start(&cbcp->fsm.timer);
142 }
143
144 #define CBCP_CLOSED (0) /* Not in use */
145 #define CBCP_STOPPED (1) /* Waiting for a REQ */
146 #define CBCP_REQSENT (2) /* Waiting for a RESP */
147 #define CBCP_RESPSENT (3) /* Waiting for an ACK */
148 #define CBCP_ACKSENT (4) /* Waiting for an LCP Term REQ */
149
150 static const char * const cbcpname[] = {
151 "closed", "stopped", "req-sent", "resp-sent", "ack-sent"
152 };
153
154 static const char *
cbcpstate(unsigned s)155 cbcpstate(unsigned s)
156 {
157 if (s < sizeof cbcpname / sizeof cbcpname[0])
158 return cbcpname[s];
159 return HexStr(s, NULL, 0);
160 }
161
162 static void
cbcp_NewPhase(struct cbcp * cbcp,int new)163 cbcp_NewPhase(struct cbcp *cbcp, int new)
164 {
165 if (cbcp->fsm.state != new) {
166 log_Printf(LogCBCP, "%s: State change %s --> %s\n", cbcp->p->dl->name,
167 cbcpstate(cbcp->fsm.state), cbcpstate(new));
168 cbcp->fsm.state = new;
169 }
170 }
171
172 struct cbcp_header {
173 u_char code;
174 u_char id;
175 u_int16_t length; /* Network byte order */
176 };
177
178
179 /* cbcp_header::code values */
180 #define CBCP_REQ (1)
181 #define CBCP_RESPONSE (2)
182 #define CBCP_ACK (3)
183
184 struct cbcp_data {
185 u_char type;
186 u_char length;
187 u_char delay;
188 char addr_start[253]; /* max cbcp_data length 255 + 1 for NULL */
189 };
190
191 /* cbcp_data::type values */
192 #define CBCP_NONUM (1)
193 #define CBCP_CLIENTNUM (2)
194 #define CBCP_SERVERNUM (3)
195 #define CBCP_LISTNUM (4)
196
197 static void
cbcp_Output(struct cbcp * cbcp,u_char code,struct cbcp_data * data)198 cbcp_Output(struct cbcp *cbcp, u_char code, struct cbcp_data *data)
199 {
200 struct cbcp_header *head;
201 struct mbuf *bp;
202
203 bp = m_get(sizeof *head + data->length, MB_CBCPOUT);
204 head = (struct cbcp_header *)MBUF_CTOP(bp);
205 head->code = code;
206 head->id = cbcp->fsm.id;
207 head->length = htons(sizeof *head + data->length);
208 memcpy(MBUF_CTOP(bp) + sizeof *head, data, data->length);
209 log_DumpBp(LogDEBUG, "cbcp_Output", bp);
210 link_PushPacket(&cbcp->p->link, bp, cbcp->p->dl->bundle,
211 LINK_QUEUES(&cbcp->p->link) - 1, PROTO_CBCP);
212 }
213
214 static const char *
cbcp_data_Type(unsigned type)215 cbcp_data_Type(unsigned type)
216 {
217 static const char * const types[] = {
218 "No callback", "User-spec", "Server-spec", "list"
219 };
220
221 if (type < 1 || type > sizeof types / sizeof types[0])
222 return HexStr(type, NULL, 0);
223 return types[type-1];
224 }
225
226 struct cbcp_addr {
227 u_char type;
228 char addr[sizeof ((struct cbcp_data *)0)->addr_start - 1]; /* ASCIIZ */
229 };
230
231 /* cbcp_data::type values */
232 #define CBCP_ADDR_PSTN (1)
233
234 static void
cbcp_data_Show(struct cbcp_data * data)235 cbcp_data_Show(struct cbcp_data *data)
236 {
237 struct cbcp_addr *addr;
238 char *end;
239
240 addr = (struct cbcp_addr *)data->addr_start;
241 end = (char *)data + data->length;
242 *end = '\0';
243
244 log_Printf(LogCBCP, " TYPE %s\n", cbcp_data_Type(data->type));
245 if ((char *)&data->delay < end) {
246 log_Printf(LogCBCP, " DELAY %d\n", data->delay);
247 while (addr->addr < end) {
248 if (addr->type == CBCP_ADDR_PSTN)
249 log_Printf(LogCBCP, " ADDR %s\n", addr->addr);
250 else
251 log_Printf(LogCBCP, " ADDR type %d ??\n", (int)addr->type);
252 addr = (struct cbcp_addr *)(addr->addr + strlen(addr->addr) + 1);
253 }
254 }
255 }
256
257 static void
cbcp_SendReq(struct cbcp * cbcp)258 cbcp_SendReq(struct cbcp *cbcp)
259 {
260 struct cbcp_data data;
261 struct cbcp_addr *addr;
262 char list[sizeof cbcp->fsm.phone], *next;
263 int len, max;
264
265 /* Only callees send REQs */
266
267 log_Printf(LogCBCP, "%s: SendReq(%d) state = %s\n", cbcp->p->dl->name,
268 cbcp->fsm.id, cbcpstate(cbcp->fsm.state));
269 data.type = cbcp->fsm.type;
270 data.delay = 0;
271 strncpy(list, cbcp->fsm.phone, sizeof list - 1);
272 list[sizeof list - 1] = '\0';
273
274 switch (data.type) {
275 case CBCP_CLIENTNUM:
276 addr = (struct cbcp_addr *)data.addr_start;
277 addr->type = CBCP_ADDR_PSTN;
278 *addr->addr = '\0';
279 data.length = addr->addr - (char *)&data;
280 break;
281
282 case CBCP_LISTNUM:
283 addr = (struct cbcp_addr *)data.addr_start;
284 for (next = strtok(list, ","); next; next = strtok(NULL, ",")) {
285 len = strlen(next);
286 max = data.addr_start + sizeof data.addr_start - addr->addr - 1;
287 if (len <= max) {
288 addr->type = CBCP_ADDR_PSTN;
289 strncpy(addr->addr, next, sizeof addr->addr - 1);
290 addr->addr[sizeof addr->addr - 1] = '\0';
291 addr = (struct cbcp_addr *)((char *)addr + len + 2);
292 } else
293 log_Printf(LogWARN, "CBCP ADDR \"%s\" skipped - packet too large\n",
294 next);
295 }
296 data.length = (char *)addr - (char *)&data;
297 break;
298
299 case CBCP_SERVERNUM:
300 data.length = data.addr_start - (char *)&data;
301 break;
302
303 default:
304 data.length = (char *)&data.delay - (char *)&data;
305 break;
306 }
307
308 cbcp_data_Show(&data);
309 cbcp_Output(cbcp, CBCP_REQ, &data);
310 cbcp->fsm.restart--;
311 cbcp_StartTimer(cbcp, cbcp->fsm.delay);
312 cbcp_NewPhase(cbcp, CBCP_REQSENT); /* Wait for a RESPONSE */
313 }
314
315 void
cbcp_Up(struct cbcp * cbcp)316 cbcp_Up(struct cbcp *cbcp)
317 {
318 struct lcp *lcp = &cbcp->p->link.lcp;
319
320 cbcp->fsm.delay = cbcp->p->dl->cfg.cbcp.delay;
321 if (*cbcp->p->dl->peer.authname == '\0' ||
322 !auth_SetPhoneList(cbcp->p->dl->peer.authname, cbcp->fsm.phone,
323 sizeof cbcp->fsm.phone)) {
324 strncpy(cbcp->fsm.phone, cbcp->p->dl->cfg.cbcp.phone,
325 sizeof cbcp->fsm.phone - 1);
326 cbcp->fsm.phone[sizeof cbcp->fsm.phone - 1] = '\0';
327 }
328
329 if (lcp->want_callback.opmask) {
330 if (*cbcp->fsm.phone == '\0')
331 cbcp->fsm.type = CBCP_NONUM;
332 else if (!strcmp(cbcp->fsm.phone, "*")) {
333 cbcp->fsm.type = CBCP_SERVERNUM;
334 *cbcp->fsm.phone = '\0';
335 } else
336 cbcp->fsm.type = CBCP_CLIENTNUM;
337 cbcp_NewPhase(cbcp, CBCP_STOPPED); /* Wait for a REQ */
338 cbcp_StartTimer(cbcp, cbcp->fsm.delay * DEF_FSMTRIES);
339 } else {
340 if (*cbcp->fsm.phone == '\0')
341 cbcp->fsm.type = CBCP_NONUM;
342 else if (!strcmp(cbcp->fsm.phone, "*")) {
343 cbcp->fsm.type = CBCP_CLIENTNUM;
344 *cbcp->fsm.phone = '\0';
345 } else if (strchr(cbcp->fsm.phone, ','))
346 cbcp->fsm.type = CBCP_LISTNUM;
347 else
348 cbcp->fsm.type = CBCP_SERVERNUM;
349 cbcp->fsm.restart = DEF_FSMTRIES;
350 cbcp_SendReq(cbcp);
351 }
352 }
353
354 static int
cbcp_AdjustResponse(struct cbcp * cbcp,struct cbcp_data * data)355 cbcp_AdjustResponse(struct cbcp *cbcp, struct cbcp_data *data)
356 {
357 /*
358 * We've received a REQ (data). Adjust our response (cbcp->fsm.*)
359 * so that we (hopefully) agree with the peer
360 */
361 struct cbcp_addr *addr;
362
363 switch (data->type) {
364 case CBCP_NONUM:
365 if (cbcp->p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_NONE))
366 /*
367 * if ``none'' is a configured callback possibility
368 * (ie, ``set callback cbcp none''), go along with the callees
369 * request
370 */
371 cbcp->fsm.type = CBCP_NONUM;
372
373 /*
374 * Otherwise, we send our desired response anyway. This seems to be
375 * what Win95 does - although I can't find this behaviour documented
376 * in the CBCP spec....
377 */
378
379 return 1;
380
381 case CBCP_CLIENTNUM:
382 if (cbcp->fsm.type == CBCP_CLIENTNUM) {
383 char *ptr;
384
385 if (data->length > data->addr_start - (char *)data) {
386 /*
387 * The peer has given us an address type spec - make sure we
388 * understand !
389 */
390 addr = (struct cbcp_addr *)data->addr_start;
391 if (addr->type != CBCP_ADDR_PSTN) {
392 log_Printf(LogPHASE, "CBCP: Unrecognised address type %d !\n",
393 (int)addr->type);
394 return 0;
395 }
396 }
397 /* we accept the REQ even if the peer didn't specify an addr->type */
398 ptr = strchr(cbcp->fsm.phone, ',');
399 if (ptr)
400 *ptr = '\0'; /* Just use the first number in our list */
401 return 1;
402 }
403 log_Printf(LogPHASE, "CBCP: no number to pass to the peer !\n");
404 return 0;
405
406 case CBCP_SERVERNUM:
407 if (cbcp->fsm.type == CBCP_SERVERNUM) {
408 *cbcp->fsm.phone = '\0';
409 return 1;
410 }
411 if (data->length > data->addr_start - (char *)data) {
412 /*
413 * This violates the spec, but if the peer has told us the
414 * number it wants to call back, take advantage of this fact
415 * and allow things to proceed if we've specified the same
416 * number
417 */
418 addr = (struct cbcp_addr *)data->addr_start;
419 if (addr->type != CBCP_ADDR_PSTN) {
420 log_Printf(LogPHASE, "CBCP: Unrecognised address type %d !\n",
421 (int)addr->type);
422 return 0;
423 } else if (cbcp->fsm.type == CBCP_CLIENTNUM) {
424 /*
425 * If the peer's insisting on deciding the number, make sure
426 * it's one of the ones in our list. If it is, let the peer
427 * think it's in control :-)
428 */
429 char list[sizeof cbcp->fsm.phone], *next;
430
431 strncpy(list, cbcp->fsm.phone, sizeof list - 1);
432 list[sizeof list - 1] = '\0';
433 for (next = strtok(list, ","); next; next = strtok(NULL, ","))
434 if (!strcmp(next, addr->addr)) {
435 cbcp->fsm.type = CBCP_SERVERNUM;
436 strcpy(cbcp->fsm.phone, next);
437 return 1;
438 }
439 }
440 }
441 log_Printf(LogPHASE, "CBCP: Peer won't allow local decision !\n");
442 return 0;
443
444 case CBCP_LISTNUM:
445 if (cbcp->fsm.type == CBCP_CLIENTNUM || cbcp->fsm.type == CBCP_LISTNUM) {
446 /*
447 * Search through ``data''s addresses and see if cbcp->fsm.phone
448 * contains any of them
449 */
450 char list[sizeof cbcp->fsm.phone], *next, *end;
451
452 addr = (struct cbcp_addr *)data->addr_start;
453 end = (char *)data + data->length;
454
455 while (addr->addr < end) {
456 if (addr->type == CBCP_ADDR_PSTN) {
457 strncpy(list, cbcp->fsm.phone, sizeof list - 1);
458 list[sizeof list - 1] = '\0';
459 for (next = strtok(list, ","); next; next = strtok(NULL, ","))
460 if (!strcmp(next, addr->addr)) {
461 cbcp->fsm.type = CBCP_LISTNUM;
462 strcpy(cbcp->fsm.phone, next);
463 return 1;
464 }
465 } else
466 log_Printf(LogCBCP, "Warning: Unrecognised address type %d !\n",
467 (int)addr->type);
468 addr = (struct cbcp_addr *)(addr->addr + strlen(addr->addr) + 1);
469 }
470 }
471 log_Printf(LogPHASE, "CBCP: no good number to pass to the peer !\n");
472 return 0;
473 }
474
475 log_Printf(LogCBCP, "Unrecognised REQ type %d !\n", (int)data->type);
476 return 0;
477 }
478
479 static void
cbcp_SendResponse(struct cbcp * cbcp)480 cbcp_SendResponse(struct cbcp *cbcp)
481 {
482 struct cbcp_data data;
483 struct cbcp_addr *addr;
484
485 /* Only callers send RESPONSEs */
486
487 log_Printf(LogCBCP, "%s: SendResponse(%d) state = %s\n", cbcp->p->dl->name,
488 cbcp->fsm.id, cbcpstate(cbcp->fsm.state));
489
490 data.type = cbcp->fsm.type;
491 data.delay = cbcp->fsm.delay;
492 addr = (struct cbcp_addr *)data.addr_start;
493 if (data.type == CBCP_NONUM)
494 data.length = (char *)&data.delay - (char *)&data;
495 else if (*cbcp->fsm.phone) {
496 addr->type = CBCP_ADDR_PSTN;
497 strncpy(addr->addr, cbcp->fsm.phone, sizeof addr->addr - 1);
498 addr->addr[sizeof addr->addr - 1] = '\0';
499 data.length = (addr->addr + strlen(addr->addr) + 1) - (char *)&data;
500 } else
501 data.length = data.addr_start - (char *)&data;
502
503 cbcp_data_Show(&data);
504 cbcp_Output(cbcp, CBCP_RESPONSE, &data);
505 cbcp->fsm.restart--;
506 cbcp_StartTimer(cbcp, cbcp->fsm.delay);
507 cbcp_NewPhase(cbcp, CBCP_RESPSENT); /* Wait for an ACK */
508 }
509
510 /* What to do after checking an incoming response */
511 #define CBCP_ACTION_DOWN (0)
512 #define CBCP_ACTION_REQ (1)
513 #define CBCP_ACTION_ACK (2)
514
515 static int
cbcp_CheckResponse(struct cbcp * cbcp,struct cbcp_data * data)516 cbcp_CheckResponse(struct cbcp *cbcp, struct cbcp_data *data)
517 {
518 /*
519 * We've received a RESPONSE (data). Check if it agrees with
520 * our REQ (cbcp->fsm)
521 */
522 struct cbcp_addr *addr;
523
524 addr = (struct cbcp_addr *)data->addr_start;
525
526 if (data->type == cbcp->fsm.type) {
527 switch (cbcp->fsm.type) {
528 case CBCP_NONUM:
529 return CBCP_ACTION_ACK;
530
531 case CBCP_CLIENTNUM:
532 if ((char *)data + data->length <= addr->addr)
533 log_Printf(LogPHASE, "CBCP: peer didn't respond with a number !\n");
534 else if (addr->type != CBCP_ADDR_PSTN)
535 log_Printf(LogPHASE, "CBCP: Unrecognised address type %d !\n",
536 addr->type);
537 else {
538 strncpy(cbcp->fsm.phone, addr->addr, sizeof cbcp->fsm.phone - 1);
539 cbcp->fsm.phone[sizeof cbcp->fsm.phone - 1] = '\0';
540 cbcp->fsm.delay = data->delay;
541 return CBCP_ACTION_ACK;
542 }
543 return CBCP_ACTION_DOWN;
544
545 case CBCP_SERVERNUM:
546 cbcp->fsm.delay = data->delay;
547 return CBCP_ACTION_ACK;
548
549 case CBCP_LISTNUM:
550 if ((char *)data + data->length <= addr->addr)
551 log_Printf(LogPHASE, "CBCP: peer didn't respond with a number !\n");
552 else if (addr->type != CBCP_ADDR_PSTN)
553 log_Printf(LogPHASE, "CBCP: Unrecognised address type %d !\n",
554 addr->type);
555 else {
556 char list[sizeof cbcp->fsm.phone], *next;
557
558 strncpy(list, cbcp->fsm.phone, sizeof list - 1);
559 list[sizeof list - 1] = '\0';
560 for (next = strtok(list, ","); next; next = strtok(NULL, ","))
561 if (!strcmp(addr->addr, next)) {
562 strcpy(cbcp->fsm.phone, next);
563 cbcp->fsm.delay = data->delay;
564 return CBCP_ACTION_ACK;
565 }
566 log_Printf(LogPHASE, "CBCP: peer didn't respond with a "
567 "valid number !\n");
568 }
569 return CBCP_ACTION_DOWN;
570 }
571 log_Printf(LogPHASE, "Internal CBCP error - agreed on %d !\n",
572 (int)cbcp->fsm.type);
573 return CBCP_ACTION_DOWN;
574 } else if (data->type == CBCP_NONUM && cbcp->fsm.type == CBCP_CLIENTNUM) {
575 /*
576 * Client doesn't want CBCP after all....
577 * We only allow this when ``set cbcp *'' has been specified.
578 */
579 cbcp->fsm.type = CBCP_NONUM;
580 return CBCP_ACTION_ACK;
581 }
582 log_Printf(LogCBCP, "Invalid peer RESPONSE\n");
583 return CBCP_ACTION_REQ;
584 }
585
586 static void
cbcp_SendAck(struct cbcp * cbcp)587 cbcp_SendAck(struct cbcp *cbcp)
588 {
589 struct cbcp_data data;
590 struct cbcp_addr *addr;
591
592 /* Only callees send ACKs */
593
594 log_Printf(LogCBCP, "%s: SendAck(%d) state = %s\n", cbcp->p->dl->name,
595 cbcp->fsm.id, cbcpstate(cbcp->fsm.state));
596
597 data.type = cbcp->fsm.type;
598 switch (data.type) {
599 case CBCP_NONUM:
600 data.length = (char *)&data.delay - (char *)&data;
601 break;
602 case CBCP_CLIENTNUM:
603 addr = (struct cbcp_addr *)data.addr_start;
604 addr->type = CBCP_ADDR_PSTN;
605 strncpy(addr->addr, cbcp->fsm.phone, sizeof addr->addr - 1);
606 addr->addr[sizeof addr->addr - 1] = '\0';
607 data.delay = cbcp->fsm.delay;
608 data.length = addr->addr + strlen(addr->addr) + 1 - (char *)&data;
609 break;
610 default:
611 data.delay = cbcp->fsm.delay;
612 data.length = data.addr_start - (char *)&data;
613 break;
614 }
615
616 cbcp_data_Show(&data);
617 cbcp_Output(cbcp, CBCP_ACK, &data);
618 cbcp->fsm.restart--;
619 cbcp_StartTimer(cbcp, cbcp->fsm.delay);
620 cbcp_NewPhase(cbcp, CBCP_ACKSENT); /* Wait for an ACK */
621 }
622
623 extern struct mbuf *
cbcp_Input(struct bundle * bundle __unused,struct link * l,struct mbuf * bp)624 cbcp_Input(struct bundle *bundle __unused, struct link *l, struct mbuf *bp)
625 {
626 struct physical *p = link2physical(l);
627 struct cbcp_header *head;
628 struct cbcp_data *data;
629 struct cbcp *cbcp = &p->dl->cbcp;
630 size_t len;
631
632 if (p == NULL) {
633 log_Printf(LogERROR, "cbcp_Input: Not a physical link - dropped\n");
634 m_freem(bp);
635 return NULL;
636 }
637
638 bp = m_pullup(bp);
639 len = m_length(bp);
640 if (len < sizeof(struct cbcp_header)) {
641 m_freem(bp);
642 return NULL;
643 }
644 head = (struct cbcp_header *)MBUF_CTOP(bp);
645 if (ntohs(head->length) != len) {
646 log_Printf(LogWARN, "Corrupt CBCP packet (code %d, length %u not %zu)"
647 " - ignored\n", head->code, ntohs(head->length), len);
648 m_freem(bp);
649 return NULL;
650 }
651 m_settype(bp, MB_CBCPIN);
652
653 /* XXX check the id */
654
655 bp->m_offset += sizeof(struct cbcp_header);
656 bp->m_len -= sizeof(struct cbcp_header);
657 data = (struct cbcp_data *)MBUF_CTOP(bp);
658
659 switch (head->code) {
660 case CBCP_REQ:
661 log_Printf(LogCBCP, "%s: RecvReq(%d) state = %s\n",
662 p->dl->name, head->id, cbcpstate(cbcp->fsm.state));
663 cbcp_data_Show(data);
664 if (cbcp->fsm.state == CBCP_STOPPED || cbcp->fsm.state == CBCP_RESPSENT) {
665 timer_Stop(&cbcp->fsm.timer);
666 if (cbcp_AdjustResponse(cbcp, data)) {
667 cbcp->fsm.restart = DEF_FSMTRIES;
668 cbcp->fsm.id = head->id;
669 cbcp_SendResponse(cbcp);
670 } else
671 datalink_CBCPFailed(cbcp->p->dl);
672 } else
673 log_Printf(LogCBCP, "%s: unexpected REQ dropped\n", p->dl->name);
674 break;
675
676 case CBCP_RESPONSE:
677 log_Printf(LogCBCP, "%s: RecvResponse(%d) state = %s\n",
678 p->dl->name, head->id, cbcpstate(cbcp->fsm.state));
679 cbcp_data_Show(data);
680 if (cbcp->fsm.id != head->id) {
681 log_Printf(LogCBCP, "Warning: Expected id was %d, not %d\n",
682 cbcp->fsm.id, head->id);
683 cbcp->fsm.id = head->id;
684 }
685 if (cbcp->fsm.state == CBCP_REQSENT || cbcp->fsm.state == CBCP_ACKSENT) {
686 timer_Stop(&cbcp->fsm.timer);
687 switch (cbcp_CheckResponse(cbcp, data)) {
688 case CBCP_ACTION_REQ:
689 cbcp_SendReq(cbcp);
690 break;
691
692 case CBCP_ACTION_ACK:
693 cbcp->fsm.restart = DEF_FSMTRIES;
694 cbcp_SendAck(cbcp);
695 if (cbcp->fsm.type == CBCP_NONUM) {
696 /*
697 * Don't change state in case the peer doesn't get our ACK,
698 * just bring the layer up.
699 */
700 timer_Stop(&cbcp->fsm.timer);
701 datalink_NCPUp(cbcp->p->dl);
702 }
703 break;
704
705 default:
706 datalink_CBCPFailed(cbcp->p->dl);
707 break;
708 }
709 } else
710 log_Printf(LogCBCP, "%s: unexpected RESPONSE dropped\n", p->dl->name);
711 break;
712
713 case CBCP_ACK:
714 log_Printf(LogCBCP, "%s: RecvAck(%d) state = %s\n",
715 p->dl->name, head->id, cbcpstate(cbcp->fsm.state));
716 cbcp_data_Show(data);
717 if (cbcp->fsm.id != head->id) {
718 log_Printf(LogCBCP, "Warning: Expected id was %d, not %d\n",
719 cbcp->fsm.id, head->id);
720 cbcp->fsm.id = head->id;
721 }
722 if (cbcp->fsm.type == CBCP_NONUM) {
723 /*
724 * Don't change state in case the peer doesn't get our ACK,
725 * just bring the layer up.
726 */
727 timer_Stop(&cbcp->fsm.timer);
728 datalink_NCPUp(cbcp->p->dl);
729 } else if (cbcp->fsm.state == CBCP_RESPSENT) {
730 timer_Stop(&cbcp->fsm.timer);
731 datalink_CBCPComplete(cbcp->p->dl);
732 log_Printf(LogPHASE, "%s: CBCP: Peer will dial back\n", p->dl->name);
733 } else
734 log_Printf(LogCBCP, "%s: unexpected ACK dropped\n", p->dl->name);
735 break;
736
737 default:
738 log_Printf(LogWARN, "Unrecognised CBCP packet (code %d, length %zd)\n",
739 head->code, len);
740 break;
741 }
742
743 m_freem(bp);
744 return NULL;
745 }
746
747 void
cbcp_Down(struct cbcp * cbcp)748 cbcp_Down(struct cbcp *cbcp)
749 {
750 timer_Stop(&cbcp->fsm.timer);
751 cbcp_NewPhase(cbcp, CBCP_CLOSED);
752 cbcp->required = 0;
753 }
754
755 void
cbcp_ReceiveTerminateReq(struct physical * p)756 cbcp_ReceiveTerminateReq(struct physical *p)
757 {
758 if (p->dl->cbcp.fsm.state == CBCP_ACKSENT) {
759 /* Don't change our state in case the peer doesn't get the ACK */
760 p->dl->cbcp.required = 1;
761 log_Printf(LogPHASE, "%s: CBCP: Will dial back on %s\n", p->dl->name,
762 p->dl->cbcp.fsm.phone);
763 } else
764 cbcp_NewPhase(&p->dl->cbcp, CBCP_CLOSED);
765 }
766