source: rtems/cpukit/pppd/demand.c @ 7452b855

4.104.114.84.95
Last change on this file since 7452b855 was 48cdb95a, checked in by Joel Sherrill <joel.sherrill@…>, on 04/10/03 at 16:20:38

2003-04-10 Joel Sherrill <joel@…>

PR 371/pppd

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