blob: ae55aac23cda6f41d547dad80b2e0f0af91d418b [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/*
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#define RCSID "$Id: demand.c,v 1.1 2008-08-04 06:11:51 winfred Exp $"
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <errno.h>
26#include <fcntl.h>
27#include <netdb.h>
28#include <sys/param.h>
29#include <sys/types.h>
30#include <sys/wait.h>
31#include <sys/time.h>
32#include <sys/resource.h>
33#include <sys/stat.h>
34#include <sys/socket.h>
35#ifdef PPP_FILTER
36#include <net/if.h>
37#include <net/bpf.h>
38#include <pcap.h>
39#endif
40
41#include <pppd.h>
42#include "fsm.h"
43#include "ipcp.h"
44#include "lcp.h"
45
46static const char rcsid[] = RCSID;
47
48char *frame;
49int framelen;
50int framemax;
51int escape_flag;
52int flush_flag;
53int fcs;
54
55struct packet {
56 int length;
57 struct packet *next;
58 unsigned char data[1];
59};
60
61struct packet *pend_q;
62struct packet *pend_qtail;
63
64static int active_packet __P((unsigned char *, int));
65
66/*
67 * demand_conf - configure the interface for doing dial-on-demand.
68 */
69void
70demand_conf()
71{
72 int i;
73 struct protent *protp;
74
75/* framemax = lcp_allowoptions[0].mru;
76 if (framemax < PPP_MRU) */
77 framemax = PPP_MRU;
78 framemax += PPP_HDRLEN + PPP_FCSLEN;
79 frame = malloc(framemax);
80 if (frame == NULL)
81 novm("demand frame");
82 framelen = 0;
83 pend_q = NULL;
84 escape_flag = 0;
85 flush_flag = 0;
86 fcs = PPP_INITFCS;
87
88 netif_set_mtu(0, MIN(lcp_allowoptions[0].mru, PPP_MRU));
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 */
109void
110demand_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 */
125void
126demand_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 */
152void
153demand_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 */
166static 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 */
206int
207loop_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((unsigned char *)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 */
258int
259loop_frame(frame, len)
260 unsigned char *frame;
261 int len;
262{
263 struct packet *pkt;
264
265 /* dbglog("from loop: %P", frame, len); */
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 */
291void
292demand_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 */
322static int
323active_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 (pass_filter.bf_len != 0
335 && bpf_filter(pass_filter.bf_insns, p, len, len) == 0)
336 return 0;
337 if (active_filter.bf_len != 0
338 && bpf_filter(active_filter.bf_insns, p, len, len) == 0)
339 return 0;
340#endif
341 for (i = 0; (protp = protocols[i]) != NULL; ++i) {
342 if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
343 if (!protp->enabled_flag)
344 return 0;
345 if (protp->active_pkt == NULL)
346 return 1;
347 return (*protp->active_pkt)(p, len);
348 }
349 }
350 return 0; /* not a supported protocol !!?? */
351}