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