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