GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/pppd/cbcp.c Lines: 0 147 0.0 %
Date: 2017-11-07 Branches: 0 72 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: cbcp.c,v 1.8 2010/05/01 08:14:26 mk Exp $	*/
2
3
/*
4
 * cbcp - Call Back Configuration Protocol.
5
 *
6
 * Copyright (c) 1995 Pedro Roque Marques.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 *
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 *
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in
17
 *    the documentation and/or other materials provided with the
18
 *    distribution.
19
 *
20
 * 3. The name(s) of the authors of this software must not be used to
21
 *    endorse or promote products derived from this software without
22
 *    prior written permission.
23
 *
24
 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
25
 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
26
 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
27
 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
28
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
29
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
30
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31
 */
32
33
#include <stdio.h>
34
#include <string.h>
35
#include <sys/types.h>
36
#include <sys/time.h>
37
#include <syslog.h>
38
39
#include "pppd.h"
40
#include "cbcp.h"
41
#include "fsm.h"
42
#include "lcp.h"
43
#include "ipcp.h"
44
45
/*
46
 * Protocol entry points.
47
 */
48
static void cbcp_init(int unit);
49
static void cbcp_open(int unit);
50
static void cbcp_lowerup(int unit);
51
static void cbcp_input(int unit, u_char *pkt, int len);
52
static void cbcp_protrej(int unit);
53
static int  cbcp_printpkt(u_char *pkt, int len,
54
    void (*printer)(void *, char *, ...), void *arg);
55
56
struct protent cbcp_protent = {
57
    PPP_CBCP,
58
    cbcp_init,
59
    cbcp_input,
60
    cbcp_protrej,
61
    cbcp_lowerup,
62
    NULL,
63
    cbcp_open,
64
    NULL,
65
    cbcp_printpkt,
66
    NULL,
67
    0,
68
    "CBCP",
69
    NULL,
70
    NULL,
71
    NULL
72
};
73
74
cbcp_state cbcp[NUM_PPP];
75
76
/* internal prototypes */
77
78
static void cbcp_recvreq(cbcp_state *us, char *pckt, int len);
79
static void cbcp_resp(cbcp_state *us);
80
static void cbcp_up(cbcp_state *us);
81
static void cbcp_recvack(cbcp_state *us, char *pckt, int len);
82
static void cbcp_send(cbcp_state *us, u_char code, u_char *buf, int len);
83
84
/* init state */
85
static void
86
cbcp_init(iface)
87
    int iface;
88
{
89
    cbcp_state *us;
90
91
    us = &cbcp[iface];
92
    memset(us, 0, sizeof(cbcp_state));
93
    us->us_unit = iface;
94
    us->us_type |= (1 << CB_CONF_NO);
95
}
96
97
/* lower layer is up */
98
static void
99
cbcp_lowerup(iface)
100
    int iface;
101
{
102
    cbcp_state *us = &cbcp[iface];
103
104
    syslog(LOG_DEBUG, "cbcp_lowerup");
105
    syslog(LOG_DEBUG, "want: %d", us->us_type);
106
107
    if (us->us_type == CB_CONF_USER)
108
        syslog(LOG_DEBUG, "phone no: %s", us->us_number);
109
}
110
111
static void
112
cbcp_open(unit)
113
    int unit;
114
{
115
    syslog(LOG_DEBUG, "cbcp_open");
116
}
117
118
/* process an incoming packet */
119
static void
120
cbcp_input(unit, inpacket, pktlen)
121
    int unit;
122
    u_char *inpacket;
123
    int pktlen;
124
{
125
    u_char *inp;
126
    u_char code, id;
127
    u_short len;
128
129
    cbcp_state *us = &cbcp[unit];
130
131
    inp = inpacket;
132
133
    if (pktlen < CBCP_MINLEN) {
134
        syslog(LOG_ERR, "CBCP packet is too small");
135
	return;
136
    }
137
138
    GETCHAR(code, inp);
139
    GETCHAR(id, inp);
140
    GETSHORT(len, inp);
141
142
    if (len < CBCP_MINLEN || len > pktlen) {
143
        syslog(LOG_ERR, "CBCP packet: invalid length");
144
        return;
145
    }
146
    len -= CBCP_MINLEN;
147
148
    switch(code) {
149
    case CBCP_REQ:
150
        us->us_id = id;
151
	cbcp_recvreq(us, inp, len);
152
	break;
153
154
    case CBCP_RESP:
155
	syslog(LOG_DEBUG, "CBCP_RESP received");
156
	break;
157
158
    case CBCP_ACK:
159
	if (id != us->us_id)
160
	    syslog(LOG_DEBUG, "id doesn't match: expected %d recv %d",
161
		   us->us_id, id);
162
163
	cbcp_recvack(us, inp, len);
164
	break;
165
166
    default:
167
	break;
168
    }
169
}
170
171
/* protocol was rejected by foe */
172
void cbcp_protrej(int iface)
173
{
174
}
175
176
char *cbcp_codenames[] = {
177
    "Request", "Response", "Ack"
178
};
179
180
char *cbcp_optionnames[] = {
181
    "NoCallback",
182
    "UserDefined",
183
    "AdminDefined",
184
    "List"
185
};
186
187
/* pretty print a packet */
188
static int
189
cbcp_printpkt(p, plen, printer, arg)
190
    u_char *p;
191
    int plen;
192
    void (*printer)(void *, char *, ...);
193
    void *arg;
194
{
195
    int code, opt, id, len, olen, delay;
196
    u_char *pstart;
197
198
    if (plen < HEADERLEN)
199
	return 0;
200
    pstart = p;
201
    GETCHAR(code, p);
202
    GETCHAR(id, p);
203
    GETSHORT(len, p);
204
    if (len < HEADERLEN || len > plen)
205
	return 0;
206
207
    if (code >= 1 && code <= sizeof(cbcp_codenames) / sizeof(char *))
208
	printer(arg, " %s", cbcp_codenames[code-1]);
209
    else
210
	printer(arg, " code=0x%x", code);
211
212
    printer(arg, " id=0x%x", id);
213
    len -= HEADERLEN;
214
215
    switch (code) {
216
    case CBCP_REQ:
217
    case CBCP_RESP:
218
    case CBCP_ACK:
219
        while(len >= 2) {
220
	    GETCHAR(opt, p);
221
	    GETCHAR(olen, p);
222
223
	    if (olen < 2 || olen > len) {
224
	        break;
225
	    }
226
227
	    printer(arg, " <");
228
	    len -= olen;
229
230
	    if (opt >= 1 && opt <= sizeof(cbcp_optionnames) / sizeof(char *))
231
	    	printer(arg, " %s", cbcp_optionnames[opt-1]);
232
	    else
233
	        printer(arg, " option=0x%x", opt);
234
235
	    if (olen > 2) {
236
	        GETCHAR(delay, p);
237
		printer(arg, " delay = %d", delay);
238
	    }
239
240
	    if (olen > 3) {
241
	        int addrt;
242
		char str[256];
243
244
		GETCHAR(addrt, p);
245
		memcpy(str, p, olen - 4);
246
		str[olen - 4] = 0;
247
		printer(arg, " number = %s", str);
248
	    }
249
	    printer(arg, ">");
250
	    break;
251
	}
252
253
    default:
254
	break;
255
    }
256
257
    for (; len > 0; --len) {
258
	GETCHAR(code, p);
259
	printer(arg, " %.2x", code);
260
    }
261
262
    return p - pstart;
263
}
264
265
/* received CBCP request */
266
static void
267
cbcp_recvreq(us, pckt, pcktlen)
268
    cbcp_state *us;
269
    char *pckt;
270
    int pcktlen;
271
{
272
    u_char type, opt_len, delay, addr_type;
273
    char address[256];
274
    int len = pcktlen;
275
276
    address[0] = 0;
277
278
    while (len > 1) {
279
        syslog(LOG_DEBUG, "length: %d", len);
280
281
	GETCHAR(type, pckt);
282
	GETCHAR(opt_len, pckt);
283
284
	if (len < opt_len)
285
	    break;
286
	len -= opt_len;
287
288
	if (opt_len > 2)
289
	    GETCHAR(delay, pckt);
290
291
	us->us_allowed |= (1 << type);
292
293
	switch(type) {
294
	case CB_CONF_NO:
295
	    syslog(LOG_DEBUG, "no callback allowed");
296
	    break;
297
298
	case CB_CONF_USER:
299
	    syslog(LOG_DEBUG, "user callback allowed");
300
	    if (opt_len > 4) {
301
	        GETCHAR(addr_type, pckt);
302
		memcpy(address, pckt, opt_len - 4);
303
		address[opt_len - 4] = 0;
304
		if (address[0])
305
		    syslog(LOG_DEBUG, "address: %s", address);
306
	    }
307
	    break;
308
309
	case CB_CONF_ADMIN:
310
	    syslog(LOG_DEBUG, "user admin defined allowed");
311
	    break;
312
313
	case CB_CONF_LIST:
314
	    break;
315
	}
316
    }
317
318
    cbcp_resp(us);
319
}
320
321
static void
322
cbcp_resp(us)
323
    cbcp_state *us;
324
{
325
    u_char cb_type;
326
    u_char buf[256];
327
    u_char *bufp = buf;
328
    int len = 0;
329
330
    cb_type = us->us_allowed & us->us_type;
331
    syslog(LOG_DEBUG, "cbcp_resp cb_type=%d", cb_type);
332
333
#if 0
334
    if (!cb_type)
335
        lcp_down(us->us_unit);
336
#endif
337
338
    if (cb_type & ( 1 << CB_CONF_USER ) ) {
339
	syslog(LOG_DEBUG, "cbcp_resp CONF_USER");
340
	PUTCHAR(CB_CONF_USER, bufp);
341
	len = 3 + 1 + strlen(us->us_number) + 1;
342
	PUTCHAR(len , bufp);
343
	PUTCHAR(5, bufp); /* delay */
344
	PUTCHAR(1, bufp);
345
	BCOPY(us->us_number, bufp, strlen(us->us_number) + 1);
346
	cbcp_send(us, CBCP_RESP, buf, len);
347
	return;
348
    }
349
350
    if (cb_type & ( 1 << CB_CONF_ADMIN ) ) {
351
	syslog(LOG_DEBUG, "cbcp_resp CONF_ADMIN");
352
        PUTCHAR(CB_CONF_ADMIN, bufp);
353
	len = 3 + 1;
354
	PUTCHAR(len , bufp);
355
	PUTCHAR(5, bufp); /* delay */
356
	PUTCHAR(0, bufp);
357
	cbcp_send(us, CBCP_RESP, buf, len);
358
	return;
359
    }
360
361
    if (cb_type & ( 1 << CB_CONF_NO ) ) {
362
        syslog(LOG_DEBUG, "cbcp_resp CONF_NO");
363
	PUTCHAR(CB_CONF_NO, bufp);
364
	len = 3;
365
	PUTCHAR(len , bufp);
366
	PUTCHAR(0, bufp);
367
	cbcp_send(us, CBCP_RESP, buf, len);
368
	(*ipcp_protent.open)(us->us_unit);
369
	return;
370
    }
371
}
372
373
static void
374
cbcp_send(us, code, buf, len)
375
    cbcp_state *us;
376
    u_char code;
377
    u_char *buf;
378
    int len;
379
{
380
    u_char *outp;
381
    int outlen;
382
383
    outp = outpacket_buf;
384
385
    outlen = 4 + len;
386
387
    MAKEHEADER(outp, PPP_CBCP);
388
389
    PUTCHAR(code, outp);
390
    PUTCHAR(us->us_id, outp);
391
    PUTSHORT(outlen, outp);
392
393
    if (len)
394
        BCOPY(buf, outp, len);
395
396
    output(us->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
397
}
398
399
static void
400
cbcp_recvack(us, pckt, len)
401
    cbcp_state *us;
402
    char *pckt;
403
    int len;
404
{
405
    u_char type, delay, addr_type;
406
    int opt_len;
407
    char address[256];
408
409
    if (len > 1) {
410
        GETCHAR(type, pckt);
411
	GETCHAR(opt_len, pckt);
412
413
	if (opt_len > len)
414
	    return;
415
416
	if (opt_len > 2)
417
	    GETCHAR(delay, pckt);
418
419
	if (opt_len > 4) {
420
	    GETCHAR(addr_type, pckt);
421
	    memcpy(address, pckt, opt_len - 4);
422
	    address[opt_len - 4] = 0;
423
	    if (address[0])
424
	        syslog(LOG_DEBUG, "peer will call: %s", address);
425
	}
426
    }
427
428
    cbcp_up(us);
429
}
430
431
extern int persist;
432
433
/* ok peer will do callback */
434
static void
435
cbcp_up(us)
436
    cbcp_state *us;
437
{
438
    persist = 0;
439
    lcp_close(0, "Call me back, please");
440
}