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