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