1 /*        $NetBSD: demand.c,v 1.6 2025/01/08 19:59:39 christos Exp $  */
2 
3 /*
4  * demand.c - Support routines for demand-dialling.
5  *
6  * Copyright (c) 1996-2024 Paul Mackerras. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
21  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
22  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
23  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
24  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
25  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
26  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27  */
28 
29 #include <sys/cdefs.h>
30 __RCSID("$NetBSD: demand.c,v 1.6 2025/01/08 19:59:39 christos Exp $");
31 
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <netdb.h>
42 #include <sys/param.h>
43 #include <sys/types.h>
44 #include <sys/wait.h>
45 #include <sys/time.h>
46 #include <sys/resource.h>
47 #include <sys/stat.h>
48 #include <sys/socket.h>
49 #ifdef PPP_WITH_FILTER
50 #ifdef __NetBSD__
51 #include <pcap.h>
52 #else
53 #include <pcap-bpf.h>
54 #endif
55 #endif
56 
57 #include "pppd-private.h"
58 #include "fsm.h"
59 #include "ipcp.h"
60 #include "lcp.h"
61 
62 
63 char *frame;
64 int framelen;
65 int framemax;
66 int escape_flag;
67 int flush_flag;
68 int fcs;
69 
70 struct packet {
71     int length;
72     struct packet *next;
73     unsigned char data[1];
74 };
75 
76 struct packet *pend_q;
77 struct packet *pend_qtail;
78 
79 static int active_packet(unsigned char *, int);
80 
81 /*
82  * demand_conf - configure the interface for doing dial-on-demand.
83  */
84 void
demand_conf(void)85 demand_conf(void)
86 {
87     int i;
88     struct protent *protp;
89 
90 /*    framemax = lcp_allowoptions[0].mru;
91     if (framemax < PPP_MRU) */
92           framemax = PPP_MRU;
93     framemax += PPP_HDRLEN + PPP_FCSLEN;
94     frame = malloc(framemax);
95     if (frame == NULL)
96           novm("demand frame");
97     framelen = 0;
98     pend_q = NULL;
99     escape_flag = 0;
100     flush_flag = 0;
101     fcs = PPP_INITFCS;
102 
103     ppp_set_mtu(0, MIN(lcp_allowoptions[0].mru, PPP_MRU));
104     if (ppp_send_config(0, PPP_MRU, (u_int32_t) 0, 0, 0) < 0
105           || ppp_recv_config(0, PPP_MRU, (u_int32_t) 0, 0, 0) < 0)
106               fatal("Couldn't set up demand-dialled PPP interface: %m");
107 
108 #ifdef PPP_WITH_FILTER
109     set_filters(&pass_filter_in, &pass_filter_out,
110                     &active_filter_in, &active_filter_out);
111 #endif
112 
113     /*
114      * Call the demand_conf procedure for each protocol that's got one.
115      */
116     for (i = 0; (protp = protocols[i]) != NULL; ++i)
117           if (protp->enabled_flag && protp->demand_conf != NULL)
118               if (!((*protp->demand_conf)(0)))
119                     die(1);
120 }
121 
122 
123 /*
124  * demand_block - set each network protocol to block further packets.
125  */
126 void
demand_block(void)127 demand_block(void)
128 {
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_QUEUE);
135     get_loop_output();
136 }
137 
138 /*
139  * demand_discard - set each network protocol to discard packets
140  * with an error.
141  */
142 void
demand_discard(void)143 demand_discard(void)
144 {
145     struct packet *pkt, *nextpkt;
146     int i;
147     struct protent *protp;
148 
149     for (i = 0; (protp = protocols[i]) != NULL; ++i)
150           if (protp->enabled_flag && protp->demand_conf != NULL)
151               sifnpmode(0, protp->protocol & ~0x8000, NPMODE_ERROR);
152     get_loop_output();
153 
154     /* discard all saved packets */
155     for (pkt = pend_q; pkt != NULL; pkt = nextpkt) {
156           nextpkt = pkt->next;
157           free(pkt);
158     }
159     pend_q = NULL;
160     framelen = 0;
161     flush_flag = 0;
162     escape_flag = 0;
163     fcs = PPP_INITFCS;
164 }
165 
166 /*
167  * demand_unblock - set each enabled network protocol to pass packets.
168  */
169 void
demand_unblock(void)170 demand_unblock(void)
171 {
172     int i;
173     struct protent *protp;
174 
175     for (i = 0; (protp = protocols[i]) != NULL; ++i)
176           if (protp->enabled_flag && protp->demand_conf != NULL)
177               sifnpmode(0, protp->protocol & ~0x8000, NPMODE_PASS);
178 }
179 
180 /*
181  * FCS lookup table as calculated by genfcstab.
182  */
183 static u_short fcstab[256] = {
184           0x0000,   0x1189,   0x2312,   0x329b,   0x4624,   0x57ad,   0x6536,   0x74bf,
185           0x8c48,   0x9dc1,   0xaf5a,   0xbed3,   0xca6c,   0xdbe5,   0xe97e,   0xf8f7,
186           0x1081,   0x0108,   0x3393,   0x221a,   0x56a5,   0x472c,   0x75b7,   0x643e,
187           0x9cc9,   0x8d40,   0xbfdb,   0xae52,   0xdaed,   0xcb64,   0xf9ff,   0xe876,
188           0x2102,   0x308b,   0x0210,   0x1399,   0x6726,   0x76af,   0x4434,   0x55bd,
189           0xad4a,   0xbcc3,   0x8e58,   0x9fd1,   0xeb6e,   0xfae7,   0xc87c,   0xd9f5,
190           0x3183,   0x200a,   0x1291,   0x0318,   0x77a7,   0x662e,   0x54b5,   0x453c,
191           0xbdcb,   0xac42,   0x9ed9,   0x8f50,   0xfbef,   0xea66,   0xd8fd,   0xc974,
192           0x4204,   0x538d,   0x6116,   0x709f,   0x0420,   0x15a9,   0x2732,   0x36bb,
193           0xce4c,   0xdfc5,   0xed5e,   0xfcd7,   0x8868,   0x99e1,   0xab7a,   0xbaf3,
194           0x5285,   0x430c,   0x7197,   0x601e,   0x14a1,   0x0528,   0x37b3,   0x263a,
195           0xdecd,   0xcf44,   0xfddf,   0xec56,   0x98e9,   0x8960,   0xbbfb,   0xaa72,
196           0x6306,   0x728f,   0x4014,   0x519d,   0x2522,   0x34ab,   0x0630,   0x17b9,
197           0xef4e,   0xfec7,   0xcc5c,   0xddd5,   0xa96a,   0xb8e3,   0x8a78,   0x9bf1,
198           0x7387,   0x620e,   0x5095,   0x411c,   0x35a3,   0x242a,   0x16b1,   0x0738,
199           0xffcf,   0xee46,   0xdcdd,   0xcd54,   0xb9eb,   0xa862,   0x9af9,   0x8b70,
200           0x8408,   0x9581,   0xa71a,   0xb693,   0xc22c,   0xd3a5,   0xe13e,   0xf0b7,
201           0x0840,   0x19c9,   0x2b52,   0x3adb,   0x4e64,   0x5fed,   0x6d76,   0x7cff,
202           0x9489,   0x8500,   0xb79b,   0xa612,   0xd2ad,   0xc324,   0xf1bf,   0xe036,
203           0x18c1,   0x0948,   0x3bd3,   0x2a5a,   0x5ee5,   0x4f6c,   0x7df7,   0x6c7e,
204           0xa50a,   0xb483,   0x8618,   0x9791,   0xe32e,   0xf2a7,   0xc03c,   0xd1b5,
205           0x2942,   0x38cb,   0x0a50,   0x1bd9,   0x6f66,   0x7eef,   0x4c74,   0x5dfd,
206           0xb58b,   0xa402,   0x9699,   0x8710,   0xf3af,   0xe226,   0xd0bd,   0xc134,
207           0x39c3,   0x284a,   0x1ad1,   0x0b58,   0x7fe7,   0x6e6e,   0x5cf5,   0x4d7c,
208           0xc60c,   0xd785,   0xe51e,   0xf497,   0x8028,   0x91a1,   0xa33a,   0xb2b3,
209           0x4a44,   0x5bcd,   0x6956,   0x78df,   0x0c60,   0x1de9,   0x2f72,   0x3efb,
210           0xd68d,   0xc704,   0xf59f,   0xe416,   0x90a9,   0x8120,   0xb3bb,   0xa232,
211           0x5ac5,   0x4b4c,   0x79d7,   0x685e,   0x1ce1,   0x0d68,   0x3ff3,   0x2e7a,
212           0xe70e,   0xf687,   0xc41c,   0xd595,   0xa12a,   0xb0a3,   0x8238,   0x93b1,
213           0x6b46,   0x7acf,   0x4854,   0x59dd,   0x2d62,   0x3ceb,   0x0e70,   0x1ff9,
214           0xf78f,   0xe606,   0xd49d,   0xc514,   0xb1ab,   0xa022,   0x92b9,   0x8330,
215           0x7bc7,   0x6a4e,   0x58d5,   0x495c,   0x3de3,   0x2c6a,   0x1ef1,   0x0f78
216 };
217 #define PPP_FCS(fcs, c)       (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
218 
219 /*
220  * loop_chars - process characters received from the loopback.
221  * Calls loop_frame when a complete frame has been accumulated.
222  * Return value is 1 if we need to bring up the link, 0 otherwise.
223  */
224 int
loop_chars(unsigned char * p,int n)225 loop_chars(unsigned char *p, int n)
226 {
227     int c, rv;
228 
229     rv = 0;
230     for (; n > 0; --n) {
231           c = *p++;
232           if (c == PPP_FLAG) {
233               if (!escape_flag && !flush_flag
234                     && framelen > 2 && fcs == PPP_GOODFCS) {
235                     framelen -= 2;
236                     if (loop_frame((unsigned char *)frame, framelen))
237                         rv = 1;
238               }
239               framelen = 0;
240               flush_flag = 0;
241               escape_flag = 0;
242               fcs = PPP_INITFCS;
243               continue;
244           }
245           if (flush_flag)
246               continue;
247           if (escape_flag) {
248               c ^= PPP_TRANS;
249               escape_flag = 0;
250           } else if (c == PPP_ESCAPE) {
251               escape_flag = 1;
252               continue;
253           }
254           if (framelen >= framemax) {
255               flush_flag = 1;
256               continue;
257           }
258           frame[framelen++] = c;
259           fcs = PPP_FCS(fcs, c);
260     }
261     return rv;
262 }
263 
264 /*
265  * loop_frame - given a frame obtained from the loopback,
266  * decide whether to bring up the link or not, and, if we want
267  * to transmit this frame later, put it on the pending queue.
268  * Return value is 1 if we need to bring up the link, 0 otherwise.
269  * We assume that the kernel driver has already applied the
270  * pass_filter, so we won't get packets it rejected.
271  * We apply the active_filter to see if we want this packet to
272  * bring up the link.
273  */
274 int
loop_frame(unsigned char * frame,int len)275 loop_frame(unsigned char *frame, int len)
276 {
277     struct packet *pkt;
278 
279     /* dbglog("from loop: %P", frame, len); */
280     if (len < PPP_HDRLEN)
281           return 0;
282     if ((PPP_PROTOCOL(frame) & 0x8000) != 0)
283           return 0;           /* shouldn't get any of these anyway */
284     if (!active_packet(frame, len))
285           return 0;
286 
287     pkt = (struct packet *) malloc(sizeof(struct packet) + len);
288     if (pkt != NULL) {
289           pkt->length = len;
290           pkt->next = NULL;
291           memcpy(pkt->data, frame, len);
292           if (pend_q == NULL)
293               pend_q = pkt;
294           else
295               pend_qtail->next = pkt;
296           pend_qtail = pkt;
297     }
298     return 1;
299 }
300 
301 /*
302  * demand_rexmit - Resend all those frames which we got via the
303  * loopback, now that the real serial link is up.
304  */
305 void
demand_rexmit(int proto)306 demand_rexmit(int proto)
307 {
308     struct packet *pkt, *prev, *nextpkt;
309 
310     prev = NULL;
311     pkt = pend_q;
312     pend_q = NULL;
313     for (; pkt != NULL; pkt = nextpkt) {
314           nextpkt = pkt->next;
315           if (PPP_PROTOCOL(pkt->data) == proto) {
316               output(0, pkt->data, pkt->length);
317               free(pkt);
318           } else {
319               if (prev == NULL)
320                     pend_q = pkt;
321               else
322                     prev->next = pkt;
323               prev = pkt;
324           }
325     }
326     pend_qtail = prev;
327     if (prev != NULL)
328           prev->next = NULL;
329 }
330 
331 /*
332  * Scan a packet to decide whether it is an "active" packet,
333  * that is, whether it is worth bringing up the link for.
334  */
335 static int
active_packet(unsigned char * p,int len)336 active_packet(unsigned char *p, int len)
337 {
338     int proto, i;
339     struct protent *protp;
340 
341     if (len < PPP_HDRLEN)
342           return 0;
343     proto = PPP_PROTOCOL(p);
344 #ifdef PPP_WITH_FILTER
345     p[0] = 1;                 /* outbound packet indicator */
346     if ((pass_filter_out.bf_len != 0
347            && bpf_filter(pass_filter_out.bf_insns, p, len, len) == 0)
348           || (active_filter_out.bf_len != 0
349               && bpf_filter(active_filter_out.bf_insns, p, len, len) == 0)) {
350           p[0] = 0xff;
351           return 0;
352     }
353     p[0] = 0xff;
354 #endif
355     for (i = 0; (protp = protocols[i]) != NULL; ++i) {
356           if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
357               if (!protp->enabled_flag)
358                     return 0;
359               if (protp->active_pkt == NULL)
360                     return 1;
361               return (*protp->active_pkt)(p, len);
362           }
363     }
364     return 0;                           /* not a supported protocol !!?? */
365 }
366