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