source: rtems/cpukit/pppd/cbcp.c @ cf04e8ac

4.104.114.84.95
Last change on this file since cf04e8ac was aee474b, checked in by Joel Sherrill <joel.sherrill@…>, on 10/12/01 at 13:43:05

2001-10-12 Mike Siers <mikes@…>

  • Update to stable working state. Congratulations Mike! :)
  • modem_example: Directory removed.
  • modem_example/16550.h, modem_example/README, modem_example/modem.c, modem_example/modem.h, modem_example/ppp.c, modem_example/ppp.h, modem_example/pppcompress.c: Files removed.
  • pppd/example/pppd.options: New file.
  • pppd/README, pppd/STATUS, pppd/cbcp.c, pppd/cbcp.h, pppd/chat.c, pppd/pppd.h, pppd/rtemsmain.c: Updated.
  • Property mode set to 100644
File size: 8.7 KB
Line 
1/*
2 * cbcp - Call Back Configuration Protocol.
3 *
4 * Copyright (c) 1995 Pedro Roque Marques
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 Pedro Roque Marques.  The name of the author may not be used to
13 * endorse or promote products derived from this software without
14 * specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 */
20
21#define RCSID   "$Id$"
22
23#include <stdio.h>
24#include <string.h>
25#include <sys/types.h>
26#include <sys/time.h>
27
28#include "pppd.h"
29#include "cbcp.h"
30#include "fsm.h"
31#include "lcp.h"
32
33static const char rcsid[] = RCSID;
34
35/*
36 * Options.
37 */
38static int setcbcp __P((char **));
39
40static option_t cbcp_option_list[] = {
41    { "callback", o_special, setcbcp,
42      "Ask for callback" },
43    { NULL }
44};
45
46/*
47 * Protocol entry points.
48 */
49static void cbcp_init      __P((int unit));
50static void cbcp_open      __P((int unit));
51static void cbcp_lowerup   __P((int unit));
52static void cbcp_input     __P((int unit, u_char *pkt, int len));
53static void cbcp_protrej   __P((int unit));
54static int  cbcp_printpkt  __P((u_char *pkt, int len,
55                                void (*printer) __P((void *, char *, ...)),
56                                void *arg));
57
58struct protent cbcp_protent = {
59    PPP_CBCP,
60    cbcp_init,
61    cbcp_input,
62    cbcp_protrej,
63    cbcp_lowerup,
64    NULL,
65    cbcp_open,
66    NULL,
67    cbcp_printpkt,
68    NULL,
69    0,
70    "CBCP",
71    NULL,
72    cbcp_option_list,
73    NULL,
74    NULL,
75    NULL
76};
77
78cbcp_state cbcp[NUM_PPP];       
79
80/* internal prototypes */
81
82static void cbcp_recvreq __P((cbcp_state *us, char *pckt, int len));
83static void cbcp_resp __P((cbcp_state *us));
84static void cbcp_up __P((cbcp_state *us));
85static void cbcp_recvack __P((cbcp_state *us, char *pckt, int len));
86static void cbcp_send __P((cbcp_state *us, u_char code, u_char *buf, int len));
87
88/* option processing */
89static int
90setcbcp(argv)
91    char **argv;
92{
93    lcp_wantoptions[0].neg_cbcp = 1;
94    cbcp_protent.enabled_flag = 1;
95    cbcp[0].us_number = strdup(*argv);
96    if (cbcp[0].us_number == 0)
97        novm("callback number");
98    cbcp[0].us_type |= (1 << CB_CONF_USER);
99    cbcp[0].us_type |= (1 << CB_CONF_ADMIN);
100    return (1);
101}
102
103/* init state */
104static void
105cbcp_init(iface)
106    int iface;
107{
108    cbcp_state *us;
109
110    us = &cbcp[iface];
111    memset(us, 0, sizeof(cbcp_state));
112    us->us_unit = iface;
113    us->us_type |= (1 << CB_CONF_NO);
114}
115
116/* lower layer is up */
117static void
118cbcp_lowerup(iface)
119    int iface;
120{
121    cbcp_state *us = &cbcp[iface];
122
123    dbglog("cbcp_lowerup");
124    dbglog("want: %d", us->us_type);
125
126    if (us->us_type == CB_CONF_USER)
127        dbglog("phone no: %s", us->us_number);
128}
129
130static void
131cbcp_open(unit)
132    int unit;
133{
134    dbglog("cbcp_open");
135}
136
137/* process an incomming packet */
138static void
139cbcp_input(unit, inpacket, pktlen)
140    int unit;
141    u_char *inpacket;
142    int pktlen;
143{
144    u_char *inp;
145    u_char code, id;
146    u_short len;
147
148    cbcp_state *us = &cbcp[unit];
149
150    inp = inpacket;
151
152    if (pktlen < CBCP_MINLEN) {
153        error("CBCP packet is too small");
154        return;
155    }
156
157    GETCHAR(code, inp);
158    GETCHAR(id, inp);
159    GETSHORT(len, inp);
160
161#if 0
162    if (len > pktlen) {
163        error("CBCP packet: invalid length");
164        return;
165    }
166#endif
167
168    len -= CBCP_MINLEN;
169 
170    switch(code) {
171    case CBCP_REQ:
172        us->us_id = id;
173        cbcp_recvreq(us, inp, len);
174        break;
175
176    case CBCP_RESP:
177        dbglog("CBCP_RESP received");
178        break;
179
180    case CBCP_ACK:
181        if (id != us->us_id)
182            dbglog("id doesn't match: expected %d recv %d",
183                   us->us_id, id);
184
185        cbcp_recvack(us, inp, len);
186        break;
187
188    default:
189        break;
190    }
191}
192
193/* protocol was rejected by foe */
194void cbcp_protrej(int iface)
195{
196}
197
198char *cbcp_codenames[] = {
199    "Request", "Response", "Ack"
200};
201
202char *cbcp_optionnames[] = {
203    "NoCallback",
204    "UserDefined",
205    "AdminDefined",
206    "List"
207};
208
209/* pretty print a packet */
210static int
211cbcp_printpkt(p, plen, printer, arg)
212    u_char *p;
213    int plen;
214    void (*printer) __P((void *, char *, ...));
215    void *arg;
216{
217    int code, opt, id, len, olen, delay;
218    u_char *pstart;
219
220    if (plen < HEADERLEN)
221        return 0;
222    pstart = p;
223    GETCHAR(code, p);
224    GETCHAR(id, p);
225    GETSHORT(len, p);
226    if (len < HEADERLEN || len > plen)
227        return 0;
228
229    if (code >= 1 && code <= sizeof(cbcp_codenames) / sizeof(char *))
230        printer(arg, " %s", cbcp_codenames[code-1]);
231    else
232        printer(arg, " code=0x%x", code);
233
234    printer(arg, " id=0x%x", id);
235    len -= HEADERLEN;
236
237    switch (code) {
238    case CBCP_REQ:
239    case CBCP_RESP:
240    case CBCP_ACK:
241        while(len >= 2) {
242            GETCHAR(opt, p);
243            GETCHAR(olen, p);
244
245            if (olen < 2 || olen > len) {
246                break;
247            }
248
249            printer(arg, " <");
250            len -= olen;
251
252            if (opt >= 1 && opt <= sizeof(cbcp_optionnames) / sizeof(char *))
253                printer(arg, " %s", cbcp_optionnames[opt-1]);
254            else
255                printer(arg, " option=0x%x", opt);
256
257            if (olen > 2) {
258                GETCHAR(delay, p);
259                printer(arg, " delay = %d", delay);
260            }
261
262            if (olen > 3) {
263                int addrt;
264                char str[256];
265
266                GETCHAR(addrt, p);
267                memcpy(str, p, olen - 4);
268                str[olen - 4] = 0;
269                printer(arg, " number = %s", str);
270            }
271            printer(arg, ">");
272            break;
273        }
274
275    default:
276        break;
277    }
278
279    for (; len > 0; --len) {
280        GETCHAR(code, p);
281        printer(arg, " %.2x", code);
282    }
283
284    return p - pstart;
285}
286
287/* received CBCP request */
288static void
289cbcp_recvreq(us, pckt, pcktlen)
290    cbcp_state *us;
291    char *pckt;
292    int pcktlen;
293{
294    u_char type, opt_len, delay, addr_type;
295    char address[256];
296    int len = pcktlen;
297
298    address[0] = 0;
299
300    while (len) {
301        dbglog("length: %d", len);
302
303        GETCHAR(type, pckt);
304        GETCHAR(opt_len, pckt);
305
306        if (opt_len > 2)
307            GETCHAR(delay, pckt);
308
309        us->us_allowed |= (1 << type);
310
311        switch(type) {
312        case CB_CONF_NO:
313            dbglog("no callback allowed");
314            break;
315
316        case CB_CONF_USER:
317            dbglog("user callback allowed");
318            if (opt_len > 4) {
319                GETCHAR(addr_type, pckt);
320                memcpy(address, pckt, opt_len - 4);
321                address[opt_len - 4] = 0;
322                if (address[0])
323                    dbglog("address: %s", address);
324            }
325            break;
326
327        case CB_CONF_ADMIN:
328            dbglog("user admin defined allowed");
329            break;
330
331        case CB_CONF_LIST:
332            break;
333        }
334        len -= opt_len;
335    }
336
337    cbcp_resp(us);
338}
339
340static void
341cbcp_resp(us)
342    cbcp_state *us;
343{
344    u_char cb_type;
345    u_char buf[256];
346    u_char *bufp = buf;
347    int len = 0;
348
349    cb_type = us->us_allowed & us->us_type;
350    dbglog("cbcp_resp cb_type=%d", cb_type);
351
352#if 0
353    if (!cb_type)
354        lcp_down(us->us_unit);
355#endif
356
357    if (cb_type & ( 1 << CB_CONF_USER ) ) {
358        dbglog("cbcp_resp CONF_USER");
359        PUTCHAR(CB_CONF_USER, bufp);
360        len = 3 + 1 + strlen(us->us_number) + 1;
361        PUTCHAR(len , bufp);
362        PUTCHAR(5, bufp); /* delay */
363        PUTCHAR(1, bufp);
364        BCOPY(us->us_number, bufp, strlen(us->us_number) + 1);
365        cbcp_send(us, CBCP_RESP, buf, len);
366        return;
367    }
368
369    if (cb_type & ( 1 << CB_CONF_ADMIN ) ) {
370        dbglog("cbcp_resp CONF_ADMIN");
371        PUTCHAR(CB_CONF_ADMIN, bufp);
372        len = 3;
373        PUTCHAR(len, bufp);
374        PUTCHAR(5, bufp); /* delay */
375        cbcp_send(us, CBCP_RESP, buf, len);
376        return;
377    }
378
379    if (cb_type & ( 1 << CB_CONF_NO ) ) {
380        dbglog("cbcp_resp CONF_NO");
381        PUTCHAR(CB_CONF_NO, bufp);
382        len = 3;
383        PUTCHAR(len , bufp);
384        PUTCHAR(0, bufp);
385        cbcp_send(us, CBCP_RESP, buf, len);
386        start_networks();
387        return;
388    }
389}
390
391static void
392cbcp_send(us, code, buf, len)
393    cbcp_state *us;
394    u_char code;
395    u_char *buf;
396    int len;
397{
398    u_char *outp;
399    int outlen;
400
401    outp = outpacket_buf;
402
403    outlen = 4 + len;
404   
405    MAKEHEADER(outp, PPP_CBCP);
406
407    PUTCHAR(code, outp);
408    PUTCHAR(us->us_id, outp);
409    PUTSHORT(outlen, outp);
410   
411    if (len)
412        BCOPY(buf, outp, len);
413
414    output(us->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
415}
416
417static void
418cbcp_recvack(us, pckt, len)
419    cbcp_state *us;
420    char *pckt;
421    int len;
422{
423    u_char type, delay, addr_type;
424    int opt_len;
425    char address[256];
426
427    if (len) {
428        GETCHAR(type, pckt);
429        GETCHAR(opt_len, pckt);
430     
431        if (opt_len > 2)
432            GETCHAR(delay, pckt);
433
434        if (opt_len > 4) {
435            GETCHAR(addr_type, pckt);
436            memcpy(address, pckt, opt_len - 4);
437            address[opt_len - 4] = 0;
438            if (address[0])
439                dbglog("peer will call: %s", address);
440        }
441        if (type == CB_CONF_NO)
442            return;
443    }
444
445    cbcp_up(us);
446}
447
448/* ok peer will do callback */
449static void
450cbcp_up(us)
451    cbcp_state *us;
452{
453    persist = 0;
454    lcp_close(0, "Call me back, please");
455    status = EXIT_CALLBACK;
456}
Note: See TracBrowser for help on using the repository browser.