source: rtems/cpukit/pppd/demand.c @ 6ac6a5c8

5
Last change on this file since 6ac6a5c8 was 33a1a4db, checked in by Peng Fan <van.freenix@…>, on 04/05/16 at 12:45:55

cpukit: pppd: fix compile warning

rcsid is defined, but not used. So discard it.

Signed-off-by: Peng Fan <van.freenix@…>

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