moved protos here from ipcp.h; print reason on terminate-request;
[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.4 1996/07/01 01:12:52 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     if (len < PPP_HDRLEN)
258         return 0;
259     if ((PPP_PROTOCOL(frame) & 0x8000) != 0)
260         return 0;               /* shouldn't get any of these anyway */
261     if (!active_packet(frame, len))
262         return 0;
263
264     pkt = (struct packet *) malloc(sizeof(struct packet) + len);
265     if (pkt != NULL) {
266         pkt->length = len;
267         pkt->next = NULL;
268         memcpy(pkt->data, frame, len);
269         if (pend_q == NULL)
270             pend_q = pkt;
271         else
272             pend_qtail->next = pkt;
273         pend_qtail = pkt;
274     }
275     return 1;
276 }
277
278 /*
279  * demand_rexmit - Resend all those frames which we got via the
280  * loopback, now that the real serial link is up.
281  */
282 void
283 demand_rexmit(proto)
284     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
314 active_packet(p, len)
315     unsigned char *p;
316     int len;
317 {
318     int proto, i;
319     struct protent *protp;
320
321     if (len < PPP_HDRLEN)
322         return 0;
323     proto = PPP_PROTOCOL(p);
324     for (i = 0; (protp = protocols[i]) != NULL; ++i) {
325         if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
326             if (!protp->enabled_flag)
327                 return 0;
328             if (protp->active_pkt == NULL)
329                 return 1;
330             return (*protp->active_pkt)(p, len);
331         }
332     }
333     return 0;                   /* not a supported protocol !!?? */
334 }