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