xref: /openbsd/usr.sbin/pppd/demand.c (revision 7a7a726b)
1 /*	$OpenBSD: demand.c,v 1.13 2024/08/10 05:32:28 jsg 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
demand_conf(void)83 demand_conf(void)
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
demand_drop(void)122 demand_drop(void)
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
demand_unblock(void)149 demand_unblock(void)
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
loop_chars(unsigned char * p,int n)203 loop_chars(unsigned char *p, int n)
204 {
205     int c, rv;
206 
207     rv = 0;
208     for (; n > 0; --n) {
209 	c = *p++;
210 	if (c == PPP_FLAG) {
211 	    if (!escape_flag && !flush_flag
212 		&& framelen > 2 && fcs == PPP_GOODFCS) {
213 		framelen -= 2;
214 		if (loop_frame(frame, framelen))
215 		    rv = 1;
216 	    }
217 	    framelen = 0;
218 	    flush_flag = 0;
219 	    escape_flag = 0;
220 	    fcs = PPP_INITFCS;
221 	    continue;
222 	}
223 	if (flush_flag)
224 	    continue;
225 	if (escape_flag) {
226 	    c ^= PPP_TRANS;
227 	    escape_flag = 0;
228 	} else if (c == PPP_ESCAPE) {
229 	    escape_flag = 1;
230 	    continue;
231 	}
232 	if (framelen >= framemax) {
233 	    flush_flag = 1;
234 	    continue;
235 	}
236 	frame[framelen++] = c;
237 	fcs = PPP_FCS(fcs, c);
238     }
239     return rv;
240 }
241 
242 /*
243  * loop_frame - given a frame obtained from the loopback,
244  * decide whether to bring up the link or not, and, if we want
245  * to transmit this frame later, put it on the pending queue.
246  * Return value is 1 if we need to bring up the link, 0 otherwise.
247  * We assume that the kernel driver has already applied the
248  * pass_filter, so we won't get packets it rejected.
249  * We apply the active_filter to see if we want this packet to
250  * bring up the link.
251  */
252 int
loop_frame(unsigned char * frame,int len)253 loop_frame(unsigned char *frame, int len)
254 {
255     struct packet *pkt;
256 
257     /* log_packet(frame, len, "from loop: ", LOG_DEBUG); */
258     if (len < PPP_HDRLEN)
259 	return 0;
260     if ((PPP_PROTOCOL(frame) & 0x8000) != 0)
261 	return 0;		/* shouldn't get any of these anyway */
262     if (!active_packet(frame, len))
263 	return 0;
264 
265     pkt = (struct packet *) malloc(sizeof(struct packet) + len);
266     if (pkt != NULL) {
267 	pkt->length = len;
268 	pkt->next = NULL;
269 	memcpy(pkt->data, frame, len);
270 	if (pend_q == NULL)
271 	    pend_q = pkt;
272 	else
273 	    pend_qtail->next = pkt;
274 	pend_qtail = pkt;
275     }
276     return 1;
277 }
278 
279 /*
280  * demand_rexmit - Resend all those frames which we got via the
281  * loopback, now that the real serial link is up.
282  */
283 void
demand_rexmit(int proto)284 demand_rexmit(int proto)
285 {
286     struct packet *pkt, *prev, *nextpkt;
287 
288     prev = NULL;
289     pkt = pend_q;
290     pend_q = NULL;
291     for (; pkt != NULL; pkt = nextpkt) {
292 	nextpkt = pkt->next;
293 	if (PPP_PROTOCOL(pkt->data) == proto) {
294 	    output(0, pkt->data, pkt->length);
295 	    free(pkt);
296 	} else {
297 	    if (prev == NULL)
298 		pend_q = pkt;
299 	    else
300 		prev->next = pkt;
301 	    prev = pkt;
302 	}
303     }
304     pend_qtail = prev;
305     if (prev != NULL)
306 	prev->next = NULL;
307 }
308 
309 /*
310  * Scan a packet to decide whether it is an "active" packet,
311  * that is, whether it is worth bringing up the link for.
312  */
313 static int
active_packet(unsigned char * p,int len)314 active_packet(unsigned char *p, int len)
315 {
316     int proto, i;
317     struct protent *protp;
318 
319     if (len < PPP_HDRLEN)
320 	return 0;
321     proto = PPP_PROTOCOL(p);
322 #ifdef PPP_FILTER
323     if (active_filter.bf_len != 0
324 	&& bpf_filter(active_filter.bf_insns, frame, len, len) == 0)
325 	return 0;
326 #endif
327     for (i = 0; (protp = protocols[i]) != NULL; ++i) {
328 	if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
329 	    if (!protp->enabled_flag)
330 		return 0;
331 	    if (protp->active_pkt == NULL)
332 		return 1;
333 	    return (*protp->active_pkt)(p, len);
334 	}
335     }
336     return 0;			/* not a supported protocol !!?? */
337 }
338