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

Line Branch Exec Source
1
/*	$OpenBSD: demand.c,v 1.11 2015/01/16 06:40:19 deraadt Exp $	*/
2
3
/*
4
 * demand.c - Support routines for demand-dialling.
5
 *
6
 * Copyright (c) 1989-2002 Paul Mackerras. 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
 * 4. Redistributions of any form whatsoever must retain the following
25
 *    acknowledgment:
26
 *    "This product includes software developed by Paul Mackerras
27
 *     <paulus@samba.org>".
28
 *
29
 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
30
 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
31
 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
32
 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
33
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
34
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
35
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
36
 */
37
38
#include <sys/types.h>
39
#include <sys/wait.h>
40
#include <sys/time.h>
41
#include <sys/resource.h>
42
#include <sys/stat.h>
43
#include <sys/socket.h>
44
#ifdef PPP_FILTER
45
#include <net/if.h>
46
#include <net/bpf.h>
47
#include <pcap.h>
48
#endif
49
#include <stdio.h>
50
#include <stdlib.h>
51
#include <string.h>
52
#include <errno.h>
53
#include <fcntl.h>
54
#include <syslog.h>
55
56
#include "pppd.h"
57
#include "fsm.h"
58
#include "ipcp.h"
59
#include "lcp.h"
60
61
char *frame;
62
int framelen;
63
int framemax;
64
int escape_flag;
65
int flush_flag;
66
int fcs;
67
68
struct packet {
69
    int length;
70
    struct packet *next;
71
    unsigned char data[1];
72
};
73
74
struct packet *pend_q;
75
struct packet *pend_qtail;
76
77
static int active_packet(unsigned char *, int);
78
79
/*
80
 * demand_conf - configure the interface for doing dial-on-demand.
81
 */
82
void
83
demand_conf()
84
{
85
    int i;
86
    struct protent *protp;
87
88
/*    framemax = lcp_allowoptions[0].mru;
89
    if (framemax < PPP_MRU) */
90
	framemax = PPP_MRU;
91
    framemax += PPP_HDRLEN + PPP_FCSLEN;
92
    frame = malloc(framemax);
93
    if (frame == NULL)
94
	novm("demand frame");
95
    framelen = 0;
96
    pend_q = NULL;
97
    escape_flag = 0;
98
    flush_flag = 0;
99
    fcs = PPP_INITFCS;
100
101
    ppp_send_config(0, PPP_MRU, (u_int32_t) 0, 0, 0);
102
    ppp_recv_config(0, PPP_MRU, (u_int32_t) 0, 0, 0);
103
104
#ifdef PPP_FILTER
105
    set_filters(&pass_filter, &active_filter);
106
#endif
107
108
    /*
109
     * Call the demand_conf procedure for each protocol that's got one.
110
     */
111
    for (i = 0; (protp = protocols[i]) != NULL; ++i)
112
	if (protp->enabled_flag && protp->demand_conf != NULL)
113
	    if (!((*protp->demand_conf)(0)))
114
		die(1);
115
}
116
117
/*
118
 * demand_drop - set each network protocol to discard packets
119
 * without an error.
120
 */
121
void
122
demand_drop()
123
{
124
    struct packet *pkt, *nextpkt;
125
    int i;
126
    struct protent *protp;
127
128
    for (i = 0; (protp = protocols[i]) != NULL; ++i)
129
        if (protp->enabled_flag && protp->demand_conf != NULL)
130
            sifnpmode(0, protp->protocol & ~0x8000, NPMODE_DROP);
131
    get_loop_output();
132
133
    /* discard all saved packets */
134
    for (pkt = pend_q; pkt != NULL; pkt = nextpkt) {
135
        nextpkt = pkt->next;
136
        free(pkt);
137
    }
138
    pend_q = NULL;
139
    framelen = 0;
140
    flush_flag = 0;
141
    escape_flag = 0;
142
    fcs = PPP_INITFCS;
143
}
144
145
/*
146
 * demand_unblock - set each enabled network protocol to pass packets.
147
 */
148
void
149
demand_unblock()
150
{
151
    int i;
152
    struct protent *protp;
153
154
    for (i = 0; (protp = protocols[i]) != NULL; ++i)
155
	if (protp->enabled_flag && protp->demand_conf != NULL)
156
	    sifnpmode(0, protp->protocol & ~0x8000, NPMODE_PASS);
157
}
158
159
/*
160
 * FCS lookup table as calculated by genfcstab.
161
 */
162
static u_short fcstab[256] = {
163
	0x0000,	0x1189,	0x2312,	0x329b,	0x4624,	0x57ad,	0x6536,	0x74bf,
164
	0x8c48,	0x9dc1,	0xaf5a,	0xbed3,	0xca6c,	0xdbe5,	0xe97e,	0xf8f7,
165
	0x1081,	0x0108,	0x3393,	0x221a,	0x56a5,	0x472c,	0x75b7,	0x643e,
166
	0x9cc9,	0x8d40,	0xbfdb,	0xae52,	0xdaed,	0xcb64,	0xf9ff,	0xe876,
167
	0x2102,	0x308b,	0x0210,	0x1399,	0x6726,	0x76af,	0x4434,	0x55bd,
168
	0xad4a,	0xbcc3,	0x8e58,	0x9fd1,	0xeb6e,	0xfae7,	0xc87c,	0xd9f5,
169
	0x3183,	0x200a,	0x1291,	0x0318,	0x77a7,	0x662e,	0x54b5,	0x453c,
170
	0xbdcb,	0xac42,	0x9ed9,	0x8f50,	0xfbef,	0xea66,	0xd8fd,	0xc974,
171
	0x4204,	0x538d,	0x6116,	0x709f,	0x0420,	0x15a9,	0x2732,	0x36bb,
172
	0xce4c,	0xdfc5,	0xed5e,	0xfcd7,	0x8868,	0x99e1,	0xab7a,	0xbaf3,
173
	0x5285,	0x430c,	0x7197,	0x601e,	0x14a1,	0x0528,	0x37b3,	0x263a,
174
	0xdecd,	0xcf44,	0xfddf,	0xec56,	0x98e9,	0x8960,	0xbbfb,	0xaa72,
175
	0x6306,	0x728f,	0x4014,	0x519d,	0x2522,	0x34ab,	0x0630,	0x17b9,
176
	0xef4e,	0xfec7,	0xcc5c,	0xddd5,	0xa96a,	0xb8e3,	0x8a78,	0x9bf1,
177
	0x7387,	0x620e,	0x5095,	0x411c,	0x35a3,	0x242a,	0x16b1,	0x0738,
178
	0xffcf,	0xee46,	0xdcdd,	0xcd54,	0xb9eb,	0xa862,	0x9af9,	0x8b70,
179
	0x8408,	0x9581,	0xa71a,	0xb693,	0xc22c,	0xd3a5,	0xe13e,	0xf0b7,
180
	0x0840,	0x19c9,	0x2b52,	0x3adb,	0x4e64,	0x5fed,	0x6d76,	0x7cff,
181
	0x9489,	0x8500,	0xb79b,	0xa612,	0xd2ad,	0xc324,	0xf1bf,	0xe036,
182
	0x18c1,	0x0948,	0x3bd3,	0x2a5a,	0x5ee5,	0x4f6c,	0x7df7,	0x6c7e,
183
	0xa50a,	0xb483,	0x8618,	0x9791,	0xe32e,	0xf2a7,	0xc03c,	0xd1b5,
184
	0x2942,	0x38cb,	0x0a50,	0x1bd9,	0x6f66,	0x7eef,	0x4c74,	0x5dfd,
185
	0xb58b,	0xa402,	0x9699,	0x8710,	0xf3af,	0xe226,	0xd0bd,	0xc134,
186
	0x39c3,	0x284a,	0x1ad1,	0x0b58,	0x7fe7,	0x6e6e,	0x5cf5,	0x4d7c,
187
	0xc60c,	0xd785,	0xe51e,	0xf497,	0x8028,	0x91a1,	0xa33a,	0xb2b3,
188
	0x4a44,	0x5bcd,	0x6956,	0x78df,	0x0c60,	0x1de9,	0x2f72,	0x3efb,
189
	0xd68d,	0xc704,	0xf59f,	0xe416,	0x90a9,	0x8120,	0xb3bb,	0xa232,
190
	0x5ac5,	0x4b4c,	0x79d7,	0x685e,	0x1ce1,	0x0d68,	0x3ff3,	0x2e7a,
191
	0xe70e,	0xf687,	0xc41c,	0xd595,	0xa12a,	0xb0a3,	0x8238,	0x93b1,
192
	0x6b46,	0x7acf,	0x4854,	0x59dd,	0x2d62,	0x3ceb,	0x0e70,	0x1ff9,
193
	0xf78f,	0xe606,	0xd49d,	0xc514,	0xb1ab,	0xa022,	0x92b9,	0x8330,
194
	0x7bc7,	0x6a4e,	0x58d5,	0x495c,	0x3de3,	0x2c6a,	0x1ef1,	0x0f78
195
};
196
197
/*
198
 * loop_chars - process characters received from the loopback.
199
 * Calls loop_frame when a complete frame has been accumulated.
200
 * Return value is 1 if we need to bring up the link, 0 otherwise.
201
 */
202
int
203
loop_chars(p, n)
204
    unsigned char *p;
205
    int n;
206
{
207
    int c, rv;
208
209
    rv = 0;
210
    for (; n > 0; --n) {
211
	c = *p++;
212
	if (c == PPP_FLAG) {
213
	    if (!escape_flag && !flush_flag
214
		&& framelen > 2 && fcs == PPP_GOODFCS) {
215
		framelen -= 2;
216
		if (loop_frame(frame, framelen))
217
		    rv = 1;
218
	    }
219
	    framelen = 0;
220
	    flush_flag = 0;
221
	    escape_flag = 0;
222
	    fcs = PPP_INITFCS;
223
	    continue;
224
	}
225
	if (flush_flag)
226
	    continue;
227
	if (escape_flag) {
228
	    c ^= PPP_TRANS;
229
	    escape_flag = 0;
230
	} else if (c == PPP_ESCAPE) {
231
	    escape_flag = 1;
232
	    continue;
233
	}
234
	if (framelen >= framemax) {
235
	    flush_flag = 1;
236
	    continue;
237
	}
238
	frame[framelen++] = c;
239
	fcs = PPP_FCS(fcs, c);
240
    }
241
    return rv;
242
}
243
244
/*
245
 * loop_frame - given a frame obtained from the loopback,
246
 * decide whether to bring up the link or not, and, if we want
247
 * to transmit this frame later, put it on the pending queue.
248
 * Return value is 1 if we need to bring up the link, 0 otherwise.
249
 * We assume that the kernel driver has already applied the
250
 * pass_filter, so we won't get packets it rejected.
251
 * We apply the active_filter to see if we want this packet to
252
 * bring up the link.
253
 */
254
int
255
loop_frame(frame, len)
256
    unsigned char *frame;
257
    int len;
258
{
259
    struct packet *pkt;
260
261
    /* log_packet(frame, len, "from loop: ", LOG_DEBUG); */
262
    if (len < PPP_HDRLEN)
263
	return 0;
264
    if ((PPP_PROTOCOL(frame) & 0x8000) != 0)
265
	return 0;		/* shouldn't get any of these anyway */
266
    if (!active_packet(frame, len))
267
	return 0;
268
269
    pkt = (struct packet *) malloc(sizeof(struct packet) + len);
270
    if (pkt != NULL) {
271
	pkt->length = len;
272
	pkt->next = NULL;
273
	memcpy(pkt->data, frame, len);
274
	if (pend_q == NULL)
275
	    pend_q = pkt;
276
	else
277
	    pend_qtail->next = pkt;
278
	pend_qtail = pkt;
279
    }
280
    return 1;
281
}
282
283
/*
284
 * demand_rexmit - Resend all those frames which we got via the
285
 * loopback, now that the real serial link is up.
286
 */
287
void
288
demand_rexmit(proto)
289
    int proto;
290
{
291
    struct packet *pkt, *prev, *nextpkt;
292
293
    prev = NULL;
294
    pkt = pend_q;
295
    pend_q = NULL;
296
    for (; pkt != NULL; pkt = nextpkt) {
297
	nextpkt = pkt->next;
298
	if (PPP_PROTOCOL(pkt->data) == proto) {
299
	    output(0, pkt->data, pkt->length);
300
	    free(pkt);
301
	} else {
302
	    if (prev == NULL)
303
		pend_q = pkt;
304
	    else
305
		prev->next = pkt;
306
	    prev = pkt;
307
	}
308
    }
309
    pend_qtail = prev;
310
    if (prev != NULL)
311
	prev->next = NULL;
312
}
313
314
/*
315
 * Scan a packet to decide whether it is an "active" packet,
316
 * that is, whether it is worth bringing up the link for.
317
 */
318
static int
319
active_packet(p, len)
320
    unsigned char *p;
321
    int len;
322
{
323
    int proto, i;
324
    struct protent *protp;
325
326
    if (len < PPP_HDRLEN)
327
	return 0;
328
    proto = PPP_PROTOCOL(p);
329
#ifdef PPP_FILTER
330
    if (active_filter.bf_len != 0
331
	&& bpf_filter(active_filter.bf_insns, frame, len, len) == 0)
332
	return 0;
333
#endif
334
    for (i = 0; (protp = protocols[i]) != NULL; ++i) {
335
	if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
336
	    if (!protp->enabled_flag)
337
		return 0;
338
	    if (protp->active_pkt == NULL)
339
		return 1;
340
	    return (*protp->active_pkt)(p, len);
341
	}
342
    }
343
    return 0;			/* not a supported protocol !!?? */
344
}