xref: /openbsd/usr.sbin/pppd/cbcp.c (revision 259a39c7)
1 /*	$OpenBSD: cbcp.c,v 1.9 2018/07/28 22:57:27 deraadt Exp $	*/
2 
3 /*
4  * cbcp - Call Back Configuration Protocol.
5  *
6  * Copyright (c) 1995 Pedro Roque Marques.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. The name(s) of the authors of this software must not be used to
21  *    endorse or promote products derived from this software without
22  *    prior written permission.
23  *
24  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
25  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
26  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
27  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
28  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
29  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
30  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31  */
32 
33 #include <stdio.h>
34 #include <string.h>
35 #include <sys/types.h>
36 #include <sys/time.h>
37 #include <syslog.h>
38 
39 #include "pppd.h"
40 #include "cbcp.h"
41 #include "fsm.h"
42 #include "lcp.h"
43 #include "ipcp.h"
44 
45 /*
46  * Protocol entry points.
47  */
48 static void cbcp_init(int unit);
49 static void cbcp_open(int unit);
50 static void cbcp_lowerup(int unit);
51 static void cbcp_input(int unit, u_char *pkt, int len);
52 static void cbcp_protrej(int unit);
53 static int  cbcp_printpkt(u_char *pkt, int len,
54     void (*printer)(void *, char *, ...), void *arg);
55 
56 struct protent cbcp_protent = {
57     PPP_CBCP,
58     cbcp_init,
59     cbcp_input,
60     cbcp_protrej,
61     cbcp_lowerup,
62     NULL,
63     cbcp_open,
64     NULL,
65     cbcp_printpkt,
66     NULL,
67     0,
68     "CBCP",
69     NULL,
70     NULL,
71     NULL
72 };
73 
74 cbcp_state cbcp[NUM_PPP];
75 
76 /* internal prototypes */
77 
78 static void cbcp_recvreq(cbcp_state *us, char *pckt, int len);
79 static void cbcp_resp(cbcp_state *us);
80 static void cbcp_up(cbcp_state *us);
81 static void cbcp_recvack(cbcp_state *us, char *pckt, int len);
82 static void cbcp_send(cbcp_state *us, u_char code, u_char *buf, int len);
83 
84 /* init state */
85 static void
cbcp_init(int iface)86 cbcp_init(int iface)
87 {
88     cbcp_state *us;
89 
90     us = &cbcp[iface];
91     memset(us, 0, sizeof(cbcp_state));
92     us->us_unit = iface;
93     us->us_type |= (1 << CB_CONF_NO);
94 }
95 
96 /* lower layer is up */
97 static void
cbcp_lowerup(int iface)98 cbcp_lowerup(int iface)
99 {
100     cbcp_state *us = &cbcp[iface];
101 
102     syslog(LOG_DEBUG, "cbcp_lowerup");
103     syslog(LOG_DEBUG, "want: %d", us->us_type);
104 
105     if (us->us_type == CB_CONF_USER)
106         syslog(LOG_DEBUG, "phone no: %s", us->us_number);
107 }
108 
109 static void
cbcp_open(int unit)110 cbcp_open(int unit)
111 {
112     syslog(LOG_DEBUG, "cbcp_open");
113 }
114 
115 /* process an incoming packet */
116 static void
cbcp_input(int unit,u_char * inpacket,int pktlen)117 cbcp_input(int unit, u_char *inpacket, int pktlen)
118 {
119     u_char *inp;
120     u_char code, id;
121     u_short len;
122 
123     cbcp_state *us = &cbcp[unit];
124 
125     inp = inpacket;
126 
127     if (pktlen < CBCP_MINLEN) {
128         syslog(LOG_ERR, "CBCP packet is too small");
129 	return;
130     }
131 
132     GETCHAR(code, inp);
133     GETCHAR(id, inp);
134     GETSHORT(len, inp);
135 
136     if (len < CBCP_MINLEN || len > pktlen) {
137         syslog(LOG_ERR, "CBCP packet: invalid length");
138         return;
139     }
140     len -= CBCP_MINLEN;
141 
142     switch(code) {
143     case CBCP_REQ:
144         us->us_id = id;
145 	cbcp_recvreq(us, inp, len);
146 	break;
147 
148     case CBCP_RESP:
149 	syslog(LOG_DEBUG, "CBCP_RESP received");
150 	break;
151 
152     case CBCP_ACK:
153 	if (id != us->us_id)
154 	    syslog(LOG_DEBUG, "id doesn't match: expected %d recv %d",
155 		   us->us_id, id);
156 
157 	cbcp_recvack(us, inp, len);
158 	break;
159 
160     default:
161 	break;
162     }
163 }
164 
165 /* protocol was rejected by foe */
cbcp_protrej(int iface)166 void cbcp_protrej(int iface)
167 {
168 }
169 
170 char *cbcp_codenames[] = {
171     "Request", "Response", "Ack"
172 };
173 
174 char *cbcp_optionnames[] = {
175     "NoCallback",
176     "UserDefined",
177     "AdminDefined",
178     "List"
179 };
180 
181 /* pretty print a packet */
182 static int
cbcp_printpkt(u_char * p,int plen,void (* printer)(void *,char *,...),void * arg)183 cbcp_printpkt(u_char *p, int plen, void (*printer)(void *, char *, ...),
184     void *arg)
185 {
186     int code, opt, id, len, olen, delay;
187     u_char *pstart;
188 
189     if (plen < HEADERLEN)
190 	return 0;
191     pstart = p;
192     GETCHAR(code, p);
193     GETCHAR(id, p);
194     GETSHORT(len, p);
195     if (len < HEADERLEN || len > plen)
196 	return 0;
197 
198     if (code >= 1 && code <= sizeof(cbcp_codenames) / sizeof(char *))
199 	printer(arg, " %s", cbcp_codenames[code-1]);
200     else
201 	printer(arg, " code=0x%x", code);
202 
203     printer(arg, " id=0x%x", id);
204     len -= HEADERLEN;
205 
206     switch (code) {
207     case CBCP_REQ:
208     case CBCP_RESP:
209     case CBCP_ACK:
210         while(len >= 2) {
211 	    GETCHAR(opt, p);
212 	    GETCHAR(olen, p);
213 
214 	    if (olen < 2 || olen > len) {
215 	        break;
216 	    }
217 
218 	    printer(arg, " <");
219 	    len -= olen;
220 
221 	    if (opt >= 1 && opt <= sizeof(cbcp_optionnames) / sizeof(char *))
222 	    	printer(arg, " %s", cbcp_optionnames[opt-1]);
223 	    else
224 	        printer(arg, " option=0x%x", opt);
225 
226 	    if (olen > 2) {
227 	        GETCHAR(delay, p);
228 		printer(arg, " delay = %d", delay);
229 	    }
230 
231 	    if (olen > 3) {
232 	        int addrt;
233 		char str[256];
234 
235 		GETCHAR(addrt, p);
236 		memcpy(str, p, olen - 4);
237 		str[olen - 4] = 0;
238 		printer(arg, " number = %s", str);
239 	    }
240 	    printer(arg, ">");
241 	    break;
242 	}
243 
244     default:
245 	break;
246     }
247 
248     for (; len > 0; --len) {
249 	GETCHAR(code, p);
250 	printer(arg, " %.2x", code);
251     }
252 
253     return p - pstart;
254 }
255 
256 /* received CBCP request */
257 static void
cbcp_recvreq(cbcp_state * us,char * pckt,int pcktlen)258 cbcp_recvreq(cbcp_state *us, char *pckt, int pcktlen)
259 {
260     u_char type, opt_len, delay, addr_type;
261     char address[256];
262     int len = pcktlen;
263 
264     address[0] = 0;
265 
266     while (len > 1) {
267         syslog(LOG_DEBUG, "length: %d", len);
268 
269 	GETCHAR(type, pckt);
270 	GETCHAR(opt_len, pckt);
271 
272 	if (len < opt_len)
273 	    break;
274 	len -= opt_len;
275 
276 	if (opt_len > 2)
277 	    GETCHAR(delay, pckt);
278 
279 	us->us_allowed |= (1 << type);
280 
281 	switch(type) {
282 	case CB_CONF_NO:
283 	    syslog(LOG_DEBUG, "no callback allowed");
284 	    break;
285 
286 	case CB_CONF_USER:
287 	    syslog(LOG_DEBUG, "user callback allowed");
288 	    if (opt_len > 4) {
289 	        GETCHAR(addr_type, pckt);
290 		memcpy(address, pckt, opt_len - 4);
291 		address[opt_len - 4] = 0;
292 		if (address[0])
293 		    syslog(LOG_DEBUG, "address: %s", address);
294 	    }
295 	    break;
296 
297 	case CB_CONF_ADMIN:
298 	    syslog(LOG_DEBUG, "user admin defined allowed");
299 	    break;
300 
301 	case CB_CONF_LIST:
302 	    break;
303 	}
304     }
305 
306     cbcp_resp(us);
307 }
308 
309 static void
cbcp_resp(cbcp_state * us)310 cbcp_resp(cbcp_state *us)
311 {
312     u_char cb_type;
313     u_char buf[256];
314     u_char *bufp = buf;
315     int len = 0;
316 
317     cb_type = us->us_allowed & us->us_type;
318     syslog(LOG_DEBUG, "cbcp_resp cb_type=%d", cb_type);
319 
320 #if 0
321     if (!cb_type)
322         lcp_down(us->us_unit);
323 #endif
324 
325     if (cb_type & ( 1 << CB_CONF_USER ) ) {
326 	syslog(LOG_DEBUG, "cbcp_resp CONF_USER");
327 	PUTCHAR(CB_CONF_USER, bufp);
328 	len = 3 + 1 + strlen(us->us_number) + 1;
329 	PUTCHAR(len , bufp);
330 	PUTCHAR(5, bufp); /* delay */
331 	PUTCHAR(1, bufp);
332 	BCOPY(us->us_number, bufp, strlen(us->us_number) + 1);
333 	cbcp_send(us, CBCP_RESP, buf, len);
334 	return;
335     }
336 
337     if (cb_type & ( 1 << CB_CONF_ADMIN ) ) {
338 	syslog(LOG_DEBUG, "cbcp_resp CONF_ADMIN");
339         PUTCHAR(CB_CONF_ADMIN, bufp);
340 	len = 3 + 1;
341 	PUTCHAR(len , bufp);
342 	PUTCHAR(5, bufp); /* delay */
343 	PUTCHAR(0, bufp);
344 	cbcp_send(us, CBCP_RESP, buf, len);
345 	return;
346     }
347 
348     if (cb_type & ( 1 << CB_CONF_NO ) ) {
349         syslog(LOG_DEBUG, "cbcp_resp CONF_NO");
350 	PUTCHAR(CB_CONF_NO, bufp);
351 	len = 3;
352 	PUTCHAR(len , bufp);
353 	PUTCHAR(0, bufp);
354 	cbcp_send(us, CBCP_RESP, buf, len);
355 	(*ipcp_protent.open)(us->us_unit);
356 	return;
357     }
358 }
359 
360 static void
cbcp_send(cbcp_state * us,u_char code,u_char * buf,int len)361 cbcp_send(cbcp_state *us, u_char code, u_char *buf, int len)
362 {
363     u_char *outp;
364     int outlen;
365 
366     outp = outpacket_buf;
367 
368     outlen = 4 + len;
369 
370     MAKEHEADER(outp, PPP_CBCP);
371 
372     PUTCHAR(code, outp);
373     PUTCHAR(us->us_id, outp);
374     PUTSHORT(outlen, outp);
375 
376     if (len)
377         BCOPY(buf, outp, len);
378 
379     output(us->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
380 }
381 
382 static void
cbcp_recvack(cbcp_state * us,char * pckt,int len)383 cbcp_recvack(cbcp_state *us, char *pckt, int len)
384 {
385     u_char type, delay, addr_type;
386     int opt_len;
387     char address[256];
388 
389     if (len > 1) {
390         GETCHAR(type, pckt);
391 	GETCHAR(opt_len, pckt);
392 
393 	if (opt_len > len)
394 	    return;
395 
396 	if (opt_len > 2)
397 	    GETCHAR(delay, pckt);
398 
399 	if (opt_len > 4) {
400 	    GETCHAR(addr_type, pckt);
401 	    memcpy(address, pckt, opt_len - 4);
402 	    address[opt_len - 4] = 0;
403 	    if (address[0])
404 	        syslog(LOG_DEBUG, "peer will call: %s", address);
405 	}
406     }
407 
408     cbcp_up(us);
409 }
410 
411 extern int persist;
412 
413 /* ok peer will do callback */
414 static void
cbcp_up(cbcp_state * us)415 cbcp_up(cbcp_state *us)
416 {
417     persist = 0;
418     lcp_close(0, "Call me back, please");
419 }
420