]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/net/ppp/v2_0/src/cbcp.c
Initial revision
[karo-tx-redboot.git] / packages / net / ppp / v2_0 / src / cbcp.c
1 //==========================================================================
2 //
3 //      src/cbcp.c
4 //
5 //==========================================================================
6 //####ECOSGPLCOPYRIGHTBEGIN####
7 // -------------------------------------------
8 // This file is part of eCos, the Embedded Configurable Operating System.
9 // Portions created by Nick Garnett are
10 // Copyright (C) 2003 eCosCentric Ltd.
11 //
12 // eCos is free software; you can redistribute it and/or modify it under
13 // the terms of the GNU General Public License as published by the Free
14 // Software Foundation; either version 2 or (at your option) any later version.
15 //
16 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
17 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19 // for more details.
20 //
21 // You should have received a copy of the GNU General Public License along
22 // with eCos; if not, write to the Free Software Foundation, Inc.,
23 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
24 //
25 // As a special exception, if other files instantiate templates or use macros
26 // or inline functions from this file, or you compile this file and link it
27 // with other works to produce a work based on this file, this file does not
28 // by itself cause the resulting work to be covered by the GNU General Public
29 // License. However the source code for this file must still be made available
30 // in accordance with section (3) of the GNU General Public License.
31 //
32 // This exception does not invalidate any other reasons why a work based on
33 // this file might be covered by the GNU General Public License.
34 //
35 // -------------------------------------------
36 //####ECOSGPLCOPYRIGHTEND####
37 //####BSDCOPYRIGHTBEGIN####
38 //
39 // -------------------------------------------
40 //
41 // Portions of this software may have been derived from OpenBSD, 
42 // FreeBSD or other sources, and are covered by the appropriate
43 // copyright disclaimers included herein.
44 //
45 // -------------------------------------------
46 //
47 //####BSDCOPYRIGHTEND####
48 //==========================================================================
49
50 /*
51  * cbcp - Call Back Configuration Protocol.
52  *
53  * Copyright (c) 1995 Pedro Roque Marques
54  * All rights reserved.
55  *
56  * Redistribution and use in source and binary forms are permitted
57  * provided that the above copyright notice and this paragraph are
58  * duplicated in all such forms and that any documentation,
59  * advertising materials, and other materials related to such
60  * distribution and use acknowledge that the software was developed
61  * by Pedro Roque Marques.  The name of the author may not be used to
62  * endorse or promote products derived from this software without
63  * specific prior written permission.
64  *
65  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
66  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
67  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
68  */
69
70 #ifndef lint
71 //static char rcsid[] = "$FreeBSD: src/usr.sbin/pppd/cbcp.c,v 1.4 1999/08/28 01:19:00 peter Exp $";
72 #endif
73
74 #include <stdio.h>
75 #include <string.h>
76 #include <sys/types.h>
77 #include <sys/time.h>
78 #include <cyg/ppp/syslog.h>
79 #include "cyg/ppp/pppd.h"
80 #include "cyg/ppp/cbcp.h"
81 #include "cyg/ppp/fsm.h"
82 #include "cyg/ppp/lcp.h"
83 #include "cyg/ppp/ipcp.h"
84
85 /*
86  * Protocol entry points.
87  */
88 static void cbcp_init      __P((int unit));
89 static void cbcp_open      __P((int unit));
90 static void cbcp_lowerup   __P((int unit));
91 static void cbcp_input     __P((int unit, u_char *pkt, int len));
92 static void cbcp_protrej   __P((int unit));
93 static int  cbcp_printpkt  __P((u_char *pkt, int len,
94                                 void (*printer) __P((void *, char *, ...)),
95                                 void *arg));
96
97 struct protent cbcp_protent = {
98     PPP_CBCP,
99     cbcp_init,
100     cbcp_input,
101     cbcp_protrej,
102     cbcp_lowerup,
103     NULL,
104     cbcp_open,
105     NULL,
106     cbcp_printpkt,
107     NULL,
108     0,
109     "CBCP",
110     NULL,
111     NULL,
112     NULL
113 };
114
115 cbcp_state cbcp[NUM_PPP];       
116
117 /* internal prototypes */
118
119 static void cbcp_recvreq __P((cbcp_state *us, u_char *pckt, int len));
120 static void cbcp_resp __P((cbcp_state *us));
121 static void cbcp_up __P((cbcp_state *us));
122 static void cbcp_recvack __P((cbcp_state *us, u_char *pckt, int len));
123 static void cbcp_send __P((cbcp_state *us, u_char code, u_char *buf, int len));
124
125 /* init state */
126 static void
127 cbcp_init(iface)
128     int iface;
129 {
130     cbcp_state *us;
131
132     us = &cbcp[iface];
133     memset(us, 0, sizeof(cbcp_state));
134     us->us_unit = iface;
135     us->us_type |= (1 << CB_CONF_NO);
136 }
137
138 /* lower layer is up */
139 static void
140 cbcp_lowerup(iface)
141     int iface;
142 {
143     cbcp_state *us = &cbcp[iface];
144
145     syslog(LOG_DEBUG, "cbcp_lowerup");
146     syslog(LOG_DEBUG, "want: %d", us->us_type);
147
148     if (us->us_type == CB_CONF_USER)
149         syslog(LOG_DEBUG, "phone no: %s", us->us_number);
150 }
151
152 static void
153 cbcp_open(unit)
154     int unit;
155 {
156     syslog(LOG_DEBUG, "cbcp_open");
157 }
158
159 /* process an incomming packet */
160 static void
161 cbcp_input(unit, inpacket, pktlen)
162     int unit;
163     u_char *inpacket;
164     int pktlen;
165 {
166     u_char *inp;
167     u_char code, id;
168     u_short len;
169
170     cbcp_state *us = &cbcp[unit];
171
172     inp = inpacket;
173
174     if (pktlen < CBCP_MINLEN) {
175         syslog(LOG_ERR, "CBCP packet is too small");
176         return;
177     }
178
179     GETCHAR(code, inp);
180     GETCHAR(id, inp);
181     GETSHORT(len, inp);
182
183 #if 0
184     if (len > pktlen) {
185         syslog(LOG_ERR, "CBCP packet: invalid length");
186         return;
187     }
188 #endif
189
190     len -= CBCP_MINLEN;
191  
192     switch(code) {
193     case CBCP_REQ:
194         us->us_id = id;
195         cbcp_recvreq(us, inp, len);
196         break;
197
198     case CBCP_RESP:
199         syslog(LOG_DEBUG, "CBCP_RESP received");
200         break;
201
202     case CBCP_ACK:
203         if (id != us->us_id)
204             syslog(LOG_DEBUG, "id doesn't match: expected %d recv %d",
205                    us->us_id, id);
206
207         cbcp_recvack(us, inp, len);
208         break;
209
210     default:
211         break;
212     }
213 }
214
215 /* protocol was rejected by foe */
216 void cbcp_protrej(int iface)
217 {
218 }
219
220 char *cbcp_codenames[] = {
221     "Request", "Response", "Ack"
222 };
223
224 char *cbcp_optionnames[] = {
225     "NoCallback",
226     "UserDefined",
227     "AdminDefined",
228     "List"
229 };
230
231 /* pretty print a packet */
232 static int
233 cbcp_printpkt(p, plen, printer, arg)
234     u_char *p;
235     int plen;
236     void (*printer) __P((void *, char *, ...));
237     void *arg;
238 {
239     int code, opt, id, len, olen, delay;
240     u_char *pstart;
241
242     if (plen < HEADERLEN)
243         return 0;
244     pstart = p;
245     GETCHAR(code, p);
246     GETCHAR(id, p);
247     GETSHORT(len, p);
248     if (len < HEADERLEN || len > plen)
249         return 0;
250
251     if (code >= 1 && code <= sizeof(cbcp_codenames) / sizeof(char *))
252         printer(arg, " %s", cbcp_codenames[code-1]);
253     else
254         printer(arg, " code=0x%x", code); 
255
256     printer(arg, " id=0x%x", id);
257     len -= HEADERLEN;
258
259     switch (code) {
260     case CBCP_REQ:
261     case CBCP_RESP:
262     case CBCP_ACK:
263         while(len >= 2) {
264             GETCHAR(opt, p);
265             GETCHAR(olen, p);
266
267             if (olen < 2 || olen > len) {
268                 break;
269             }
270
271             printer(arg, " <");
272             len -= olen;
273
274             if (opt >= 1 && opt <= sizeof(cbcp_optionnames) / sizeof(char *))
275                 printer(arg, " %s", cbcp_optionnames[opt-1]);
276             else
277                 printer(arg, " option=0x%x", opt); 
278
279             if (olen > 2) {
280                 GETCHAR(delay, p);
281                 printer(arg, " delay = %d", delay);
282             }
283
284             if (olen > 3) {
285                 int addrt;
286                 char str[256];
287
288                 GETCHAR(addrt, p);
289                 memcpy(str, p, olen - 4);
290                 str[olen - 4] = 0;
291                 printer(arg, " number = %s", str);
292             }
293             printer(arg, ">");
294             break;
295         }
296
297     default:
298         break;
299     }
300
301     for (; len > 0; --len) {
302         GETCHAR(code, p);
303         printer(arg, " %.2x", code);
304     }
305
306     return p - pstart;
307 }
308
309 /* received CBCP request */
310 static void
311 cbcp_recvreq(us, pckt, pcktlen)
312     cbcp_state *us;
313     u_char *pckt;
314     int pcktlen;
315 {
316     u_char type, opt_len, delay, addr_type;
317     char address[256];
318     int len = pcktlen;
319
320     address[0] = 0;
321
322     while (len) {
323         syslog(LOG_DEBUG, "length: %d", len);
324
325         GETCHAR(type, pckt);
326         GETCHAR(opt_len, pckt);
327
328         if (opt_len > 2)
329             GETCHAR(delay, pckt);
330
331         us->us_allowed |= (1 << type);
332
333         switch(type) {
334         case CB_CONF_NO:
335             syslog(LOG_DEBUG, "no callback allowed");
336             break;
337
338         case CB_CONF_USER:
339             syslog(LOG_DEBUG, "user callback allowed");
340             if (opt_len > 4) {
341                 GETCHAR(addr_type, pckt);
342                 memcpy(address, pckt, opt_len - 4);
343                 address[opt_len - 4] = 0;
344                 if (address[0])
345                     syslog(LOG_DEBUG, "address: %s", address);
346             }
347             break;
348
349         case CB_CONF_ADMIN:
350             syslog(LOG_DEBUG, "user admin defined allowed");
351             break;
352
353         case CB_CONF_LIST:
354             break;
355         }
356         len -= opt_len;
357     }
358
359     cbcp_resp(us);
360 }
361
362 static void
363 cbcp_resp(us)
364     cbcp_state *us;
365 {
366     u_char cb_type;
367     u_char buf[256];
368     u_char *bufp = buf;
369     int len = 0;
370
371     cb_type = us->us_allowed & us->us_type;
372     syslog(LOG_DEBUG, "cbcp_resp cb_type=%d", cb_type);
373
374 #if 0
375     if (!cb_type)
376         lcp_down(us->us_unit);
377 #endif
378
379     if (cb_type & ( 1 << CB_CONF_USER ) ) {
380         syslog(LOG_DEBUG, "cbcp_resp CONF_USER");
381         PUTCHAR(CB_CONF_USER, bufp);
382         len = 3 + 1 + strlen(us->us_number) + 1;
383         PUTCHAR(len , bufp);
384         PUTCHAR(5, bufp); /* delay */
385         PUTCHAR(1, bufp);
386         BCOPY(us->us_number, bufp, strlen(us->us_number) + 1);
387         cbcp_send(us, CBCP_RESP, buf, len);
388         return;
389     }
390
391     if (cb_type & ( 1 << CB_CONF_ADMIN ) ) {
392         syslog(LOG_DEBUG, "cbcp_resp CONF_ADMIN");
393         PUTCHAR(CB_CONF_ADMIN, bufp);
394         len = 3 + 1;
395         PUTCHAR(len , bufp);
396         PUTCHAR(5, bufp); /* delay */
397         PUTCHAR(0, bufp);
398         cbcp_send(us, CBCP_RESP, buf, len);
399         return;
400     }
401
402     if (cb_type & ( 1 << CB_CONF_NO ) ) {
403         syslog(LOG_DEBUG, "cbcp_resp CONF_NO");
404         PUTCHAR(CB_CONF_NO, bufp);
405         len = 3;
406         PUTCHAR(len , bufp);
407         PUTCHAR(0, bufp);
408         cbcp_send(us, CBCP_RESP, buf, len);
409         (*ipcp_protent.open)(us->us_unit);
410         return;
411     }
412 }
413
414 static void
415 cbcp_send(us, code, buf, len)
416     cbcp_state *us;
417     u_char code;
418     u_char *buf;
419     int len;
420 {
421     u_char *outp;
422     int outlen;
423
424     outp = outpacket_buf;
425
426     outlen = 4 + len;
427     
428     MAKEHEADER(outp, PPP_CBCP);
429
430     PUTCHAR(code, outp);
431     PUTCHAR(us->us_id, outp);
432     PUTSHORT(outlen, outp);
433     
434     if (len)
435         BCOPY(buf, outp, len);
436
437     output(us->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
438 }
439
440 static void
441 cbcp_recvack(us, pckt, len)
442     cbcp_state *us;
443     u_char *pckt;
444     int len;
445 {
446     u_char type, delay, addr_type;
447     int opt_len;
448     char address[256];
449
450     if (len) {
451         GETCHAR(type, pckt);
452         GETCHAR(opt_len, pckt);
453      
454         if (opt_len > 2)
455             GETCHAR(delay, pckt);
456
457         if (opt_len > 4) {
458             GETCHAR(addr_type, pckt);
459             memcpy(address, pckt, opt_len - 4);
460             address[opt_len - 4] = 0;
461             if (address[0])
462                 syslog(LOG_DEBUG, "peer will call: %s", address);
463         }
464     }
465
466     cbcp_up(us);
467 }
468
469 extern int persist;
470
471 /* ok peer will do callback */
472 static void
473 cbcp_up(us)
474     cbcp_state *us;
475 {
476     persist = 0;
477     lcp_close(0, "Call me back, please");
478 }