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