source: rtems/cpukit/pppd/demand.c @ 4bf1801

4.104.114.84.9
Last change on this file since 4bf1801 was d0950ad, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 30, 1999 at 10:12:50 PM

Added port of ppp-2.3.5 from Tomasz Domin <dot@…> of ComArch? SA.
Tomasz only tested this on the mpc823.

The official site for the original source for this PPP implementation is:

ftp://cs.anu.edu.au/pub/software/ppp

NOTE: As of 11/30/1999, the current version of this source is 2.3.10.

  • 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#ifndef lint
21/* static char rcsid[] = "$Id$"; */
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
49char *frame;
50int framelen;
51int framemax;
52int escape_flag;
53int flush_flag;
54int fcs;
55
56struct packet {
57    int length;
58    struct packet *next;
59    unsigned char data[1];
60};
61
62struct packet *pend_q;
63struct packet *pend_qtail;
64
65static int active_packet __P((unsigned char *, int));
66
67/*
68 * demand_conf - configure the interface for doing dial-on-demand.
69 */
70void
71demand_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 */
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(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    /* 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 */
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 (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}
Note: See TracBrowser for help on using the repository browser.