CPU: Wrong CPU Load %.
[tomato.git] / release / src / router / ppp / pppd / cbcp.c
blob77724322553c4fde439b3bd29af7b877f7e58e18
1 /*
2 * cbcp - Call Back Configuration Protocol.
4 * Copyright (c) 1995 Pedro Roque Marques
5 * All rights reserved.
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.
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.
21 #define RCSID "$Id: cbcp.c,v 1.1.1.4 2003/10/14 08:09:53 sparq Exp $"
23 #include <stdio.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <sys/time.h>
28 #include "pppd.h"
29 #include "cbcp.h"
30 #include "fsm.h"
31 #include "lcp.h"
33 static const char rcsid[] = RCSID;
36 * Options.
38 static int setcbcp __P((char **));
40 static option_t cbcp_option_list[] = {
41 { "callback", o_special, setcbcp,
42 "Ask for callback", OPT_PRIO | OPT_A2STRVAL, &cbcp[0].us_number },
43 { NULL }
47 * Protocol entry points.
49 static void cbcp_init __P((int unit));
50 static void cbcp_open __P((int unit));
51 static void cbcp_lowerup __P((int unit));
52 static void cbcp_input __P((int unit, u_char *pkt, int len));
53 static void cbcp_protrej __P((int unit));
54 static int cbcp_printpkt __P((u_char *pkt, int len,
55 void (*printer) __P((void *, char *, ...)),
56 void *arg));
58 struct 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,
70 "CBCP",
71 NULL,
72 cbcp_option_list,
73 NULL,
74 NULL,
75 NULL
78 cbcp_state cbcp[NUM_PPP];
80 /* internal prototypes */
82 static void cbcp_recvreq __P((cbcp_state *us, char *pckt, int len));
83 static void cbcp_resp __P((cbcp_state *us));
84 static void cbcp_up __P((cbcp_state *us));
85 static void cbcp_recvack __P((cbcp_state *us, char *pckt, int len));
86 static void cbcp_send __P((cbcp_state *us, u_char code, u_char *buf, int len));
88 /* option processing */
89 static int
90 setcbcp(argv)
91 char **argv;
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);
103 /* init state */
104 static void
105 cbcp_init(iface)
106 int iface;
108 cbcp_state *us;
110 us = &cbcp[iface];
111 memset(us, 0, sizeof(cbcp_state));
112 us->us_unit = iface;
113 us->us_type |= (1 << CB_CONF_NO);
116 /* lower layer is up */
117 static void
118 cbcp_lowerup(iface)
119 int iface;
121 cbcp_state *us = &cbcp[iface];
123 dbglog("cbcp_lowerup");
124 dbglog("want: %d", us->us_type);
126 if (us->us_type == CB_CONF_USER)
127 dbglog("phone no: %s", us->us_number);
130 static void
131 cbcp_open(unit)
132 int unit;
134 dbglog("cbcp_open");
137 /* process an incomming packet */
138 static void
139 cbcp_input(unit, inpacket, pktlen)
140 int unit;
141 u_char *inpacket;
142 int pktlen;
144 u_char *inp;
145 u_char code, id;
146 u_short len;
148 cbcp_state *us = &cbcp[unit];
150 inp = inpacket;
152 if (pktlen < CBCP_MINLEN) {
153 error("CBCP packet is too small");
154 return;
157 GETCHAR(code, inp);
158 GETCHAR(id, inp);
159 GETSHORT(len, inp);
162 len -= CBCP_MINLEN;
164 switch(code) {
165 case CBCP_REQ:
166 us->us_id = id;
167 cbcp_recvreq(us, inp, len);
168 break;
170 case CBCP_RESP:
171 dbglog("CBCP_RESP received");
172 break;
174 case CBCP_ACK:
175 if (id != us->us_id)
176 dbglog("id doesn't match: expected %d recv %d",
177 us->us_id, id);
179 cbcp_recvack(us, inp, len);
180 break;
182 default:
183 break;
187 /* protocol was rejected by foe */
188 void cbcp_protrej(int iface)
192 char *cbcp_codenames[] = {
193 "Request", "Response", "Ack"
196 char *cbcp_optionnames[] = {
197 "NoCallback",
198 "UserDefined",
199 "AdminDefined",
200 "List"
203 /* pretty print a packet */
204 static int
205 cbcp_printpkt(p, plen, printer, arg)
206 u_char *p;
207 int plen;
208 void (*printer) __P((void *, char *, ...));
209 void *arg;
211 int code, opt, id, len, olen, delay;
212 u_char *pstart;
214 if (plen < HEADERLEN)
215 return 0;
216 pstart = p;
217 GETCHAR(code, p);
218 GETCHAR(id, p);
219 GETSHORT(len, p);
220 if (len < HEADERLEN || len > plen)
221 return 0;
223 if (code >= 1 && code <= sizeof(cbcp_codenames) / sizeof(char *))
224 printer(arg, " %s", cbcp_codenames[code-1]);
225 else
226 printer(arg, " code=0x%x", code);
228 printer(arg, " id=0x%x", id);
229 len -= HEADERLEN;
231 switch (code) {
232 case CBCP_REQ:
233 case CBCP_RESP:
234 case CBCP_ACK:
235 while(len >= 2) {
236 GETCHAR(opt, p);
237 GETCHAR(olen, p);
239 if (olen < 2 || olen > len) {
240 break;
243 printer(arg, " <");
244 len -= olen;
246 if (opt >= 1 && opt <= sizeof(cbcp_optionnames) / sizeof(char *))
247 printer(arg, " %s", cbcp_optionnames[opt-1]);
248 else
249 printer(arg, " option=0x%x", opt);
251 if (olen > 2) {
252 GETCHAR(delay, p);
253 printer(arg, " delay = %d", delay);
256 if (olen > 3) {
257 int addrt;
258 char str[256];
260 GETCHAR(addrt, p);
261 memcpy(str, p, olen - 4);
262 str[olen - 4] = 0;
263 printer(arg, " number = %s", str);
265 printer(arg, ">");
266 break;
269 default:
270 break;
273 for (; len > 0; --len) {
274 GETCHAR(code, p);
275 printer(arg, " %.2x", code);
278 return p - pstart;
281 /* received CBCP request */
282 static void
283 cbcp_recvreq(us, pckt, pcktlen)
284 cbcp_state *us;
285 char *pckt;
286 int pcktlen;
288 u_char type, opt_len, delay, addr_type;
289 char address[256];
290 int len = pcktlen;
292 address[0] = 0;
294 while (len) {
295 dbglog("length: %d", len);
297 GETCHAR(type, pckt);
298 GETCHAR(opt_len, pckt);
300 if (opt_len > 2)
301 GETCHAR(delay, pckt);
303 us->us_allowed |= (1 << type);
305 switch(type) {
306 case CB_CONF_NO:
307 dbglog("no callback allowed");
308 break;
310 case CB_CONF_USER:
311 dbglog("user callback allowed");
312 if (opt_len > 4) {
313 GETCHAR(addr_type, pckt);
314 memcpy(address, pckt, opt_len - 4);
315 address[opt_len - 4] = 0;
316 if (address[0])
317 dbglog("address: %s", address);
319 break;
321 case CB_CONF_ADMIN:
322 dbglog("user admin defined allowed");
323 break;
325 case CB_CONF_LIST:
326 break;
328 len -= opt_len;
331 cbcp_resp(us);
334 static void
335 cbcp_resp(us)
336 cbcp_state *us;
338 u_char cb_type;
339 u_char buf[256];
340 u_char *bufp = buf;
341 int len = 0;
343 cb_type = us->us_allowed & us->us_type;
344 dbglog("cbcp_resp cb_type=%d", cb_type);
347 if (cb_type & ( 1 << CB_CONF_USER ) ) {
348 dbglog("cbcp_resp CONF_USER");
349 PUTCHAR(CB_CONF_USER, bufp);
350 len = 3 + 1 + strlen(us->us_number) + 1;
351 PUTCHAR(len , bufp);
352 PUTCHAR(5, bufp); /* delay */
353 PUTCHAR(1, bufp);
354 BCOPY(us->us_number, bufp, strlen(us->us_number) + 1);
355 cbcp_send(us, CBCP_RESP, buf, len);
356 return;
359 if (cb_type & ( 1 << CB_CONF_ADMIN ) ) {
360 dbglog("cbcp_resp CONF_ADMIN");
361 PUTCHAR(CB_CONF_ADMIN, bufp);
362 len = 3;
363 PUTCHAR(len, bufp);
364 PUTCHAR(5, bufp); /* delay */
365 cbcp_send(us, CBCP_RESP, buf, len);
366 return;
369 if (cb_type & ( 1 << CB_CONF_NO ) ) {
370 dbglog("cbcp_resp CONF_NO");
371 PUTCHAR(CB_CONF_NO, bufp);
372 len = 3;
373 PUTCHAR(len , bufp);
374 PUTCHAR(0, bufp);
375 cbcp_send(us, CBCP_RESP, buf, len);
376 start_networks();
377 return;
381 static void
382 cbcp_send(us, code, buf, len)
383 cbcp_state *us;
384 u_char code;
385 u_char *buf;
386 int len;
388 u_char *outp;
389 int outlen;
391 outp = outpacket_buf;
393 outlen = 4 + len;
395 MAKEHEADER(outp, PPP_CBCP);
397 PUTCHAR(code, outp);
398 PUTCHAR(us->us_id, outp);
399 PUTSHORT(outlen, outp);
401 if (len)
402 BCOPY(buf, outp, len);
404 output(us->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
407 static void
408 cbcp_recvack(us, pckt, len)
409 cbcp_state *us;
410 char *pckt;
411 int len;
413 u_char type, delay, addr_type;
414 int opt_len;
415 char address[256];
417 if (len) {
418 GETCHAR(type, pckt);
419 GETCHAR(opt_len, pckt);
421 if (opt_len > 2)
422 GETCHAR(delay, pckt);
424 if (opt_len > 4) {
425 GETCHAR(addr_type, pckt);
426 memcpy(address, pckt, opt_len - 4);
427 address[opt_len - 4] = 0;
428 if (address[0])
429 dbglog("peer will call: %s", address);
431 if (type == CB_CONF_NO)
432 return;
435 cbcp_up(us);
438 /* ok peer will do callback */
439 static void
440 cbcp_up(us)
441 cbcp_state *us;
443 persist = 0;
444 lcp_close(0, "Call me back, please");
445 status = EXIT_CALLBACK;