]> git.ozlabs.org Git - ppp.git/blob - pppd/demand.c
use option_error, fix ip_active_pkt
[ppp.git] / pppd / demand.c
1 /*
2  * demand.c - Support routines for demand-dialling.
3  *
4  * Copyright (c) 1993 The Australian National University.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms are permitted
8  * provided that the above copyright notice and this paragraph are
9  * duplicated in all such forms and that any documentation,
10  * advertising materials, and other materials related to such
11  * distribution and use acknowledge that the software was developed
12  * by the Australian National University.  The name of the University
13  * may not be used to endorse or promote products derived from this
14  * software without specific prior written permission.
15  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18  */
19
20 #ifndef lint
21 static char rcsid[] = "$Id: demand.c,v 1.5 1996/08/28 06:40:03 paulus Exp $";
22 #endif
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <syslog.h>
30 #include <netdb.h>
31 #include <sys/param.h>
32 #include <sys/types.h>
33 #include <sys/wait.h>
34 #include <sys/time.h>
35 #include <sys/resource.h>
36 #include <sys/stat.h>
37 #include <sys/socket.h>
38 #include <net/if.h>
39
40 #include "pppd.h"
41 #include "fsm.h"
42 #include "ipcp.h"
43 #include "lcp.h"
44
45 char *frame;
46 int framelen;
47 int framemax;
48 int escape_flag;
49 int flush_flag;
50 int fcs;
51
52 struct packet {
53     int length;
54     struct packet *next;
55     unsigned char data[1];
56 };
57
58 struct packet *pend_q;
59 struct packet *pend_qtail;
60
61 static int active_packet __P((unsigned char *, int));
62
63 /*
64  * demand_conf - configure the interface for doing dial-on-demand.
65  */
66 void
67 demand_conf()
68 {
69     int i;
70     struct protent *protp;
71
72 /*    framemax = lcp_allowoptions[0].mru;
73     if (framemax < PPP_MRU) */
74         framemax = PPP_MRU;
75     framemax += PPP_HDRLEN + PPP_FCSLEN;
76     frame = malloc(framemax);
77     if (frame == NULL)
78         novm("demand frame");
79     framelen = 0;
80     pend_q = NULL;
81     escape_flag = 0;
82     flush_flag = 0;
83     fcs = PPP_INITFCS;
84
85     ppp_send_config(0, PPP_MRU, (u_int32_t) 0, 0, 0);
86     ppp_recv_config(0, PPP_MRU, (u_int32_t) 0, 0, 0);
87
88 #if 0
89     set_filters(&pass_filter, &active_filter);
90 #endif
91
92     /*
93      * Call the demand_conf procedure for each protocol that's got one.
94      */
95     for (i = 0; (protp = protocols[i]) != NULL; ++i)
96         if (protp->enabled_flag && protp->demand_conf != NULL)
97             if (!((*protp->demand_conf)(0)))
98                 die(1);
99 }
100
101
102 /*
103  * demand_block - set each network protocol to block further packets.
104  */
105 void
106 demand_block()
107 {
108     int i;
109     struct protent *protp;
110
111     for (i = 0; (protp = protocols[i]) != NULL; ++i)
112         if (protp->enabled_flag && protp->demand_conf != NULL)
113             sifnpmode(0, protp->protocol & ~0x8000, NPMODE_QUEUE);
114     get_loop_output();
115 }
116
117 /*
118  * demand_discard - set each network protocol to discard packets
119  * with an error.
120  */
121 void
122 demand_discard()
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_ERROR);
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  */
250 int
251 loop_frame(frame, len)
252     unsigned char *frame;
253     int len;
254 {
255     struct packet *pkt;
256
257     /* log_packet(frame, len, "from loop: "); */
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
284 demand_rexmit(proto)
285     int proto;
286 {
287     struct packet *pkt, *prev, *nextpkt;
288
289     prev = NULL;
290     pkt = pend_q;
291     pend_q = NULL;
292     for (; pkt != NULL; pkt = nextpkt) {
293         nextpkt = pkt->next;
294         if (PPP_PROTOCOL(pkt->data) == proto) {
295             output(0, pkt->data, pkt->length);
296             free(pkt);
297         } else {
298             if (prev == NULL)
299                 pend_q = pkt;
300             else
301                 prev->next = pkt;
302             prev = pkt;
303         }
304     }
305     pend_qtail = prev;
306     if (prev != NULL)
307         prev->next = NULL;
308 }
309
310 /*
311  * Scan a packet to decide whether it is an "active" packet,
312  * that is, whether it is worth bringing up the link for.
313  */
314 static int
315 active_packet(p, len)
316     unsigned char *p;
317     int len;
318 {
319     int proto, i;
320     struct protent *protp;
321
322     if (len < PPP_HDRLEN)
323         return 0;
324     proto = PPP_PROTOCOL(p);
325     for (i = 0; (protp = protocols[i]) != NULL; ++i) {
326         if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
327             if (!protp->enabled_flag)
328                 return 0;
329             if (protp->active_pkt == NULL)
330                 return 1;
331             return (*protp->active_pkt)(p, len);
332         }
333     }
334     return 0;                   /* not a supported protocol !!?? */
335 }