Lines 1-8
Link Here
|
1 |
/* |
1 |
/* |
2 |
* cbcp - Call Back Configuration Protocol. |
2 |
* cbcp - Call Back Configuration Protocol. |
3 |
* |
3 |
* |
4 |
* Copyright (c) 1995 Pedro Roque Marques. All rights reserved. |
4 |
* Copyright (c) 1995 Pedro Roque Marques. |
|
|
5 |
* Copyright (c) 2001 Bolke de Bruin |
6 |
* Copyright (c) 2004 Valery Kartel |
5 |
* |
7 |
* |
|
|
8 |
* All rights reserved. |
9 |
* |
6 |
* Redistribution and use in source and binary forms, with or without |
10 |
* Redistribution and use in source and binary forms, with or without |
7 |
* modification, are permitted provided that the following conditions |
11 |
* modification, are permitted provided that the following conditions |
8 |
* are met: |
12 |
* are met: |
Lines 39-66
Link Here
|
39 |
#include <string.h> |
43 |
#include <string.h> |
40 |
#include <sys/types.h> |
44 |
#include <sys/types.h> |
41 |
#include <sys/time.h> |
45 |
#include <sys/time.h> |
|
|
46 |
#include <syslog.h> |
47 |
#include <sys/stat.h> |
42 |
|
48 |
|
43 |
#include "pppd.h" |
49 |
#include "pppd.h" |
44 |
#include "cbcp.h" |
50 |
#include "cbcp.h" |
45 |
#include "fsm.h" |
51 |
#include "fsm.h" |
46 |
#include "lcp.h" |
52 |
#include "lcp.h" |
|
|
53 |
#include "ipcp.h" |
54 |
#include "pathnames.h" |
47 |
|
55 |
|
48 |
static const char rcsid[] = RCSID; |
56 |
static const char rcsid[] = RCSID; |
49 |
|
57 |
|
50 |
/* |
58 |
/* |
51 |
* Options. |
|
|
52 |
*/ |
53 |
static int setcbcp __P((char **)); |
54 |
|
55 |
static option_t cbcp_option_list[] = { |
56 |
{ "callback", o_special, (void *)setcbcp, |
57 |
"Ask for callback", OPT_PRIO | OPT_A2STRVAL, &cbcp[0].us_number }, |
58 |
{ NULL } |
59 |
}; |
60 |
|
61 |
/* |
62 |
* Protocol entry points. |
59 |
* Protocol entry points. |
63 |
*/ |
60 |
*/ |
|
|
61 |
|
64 |
static void cbcp_init __P((int unit)); |
62 |
static void cbcp_init __P((int unit)); |
65 |
static void cbcp_open __P((int unit)); |
63 |
static void cbcp_open __P((int unit)); |
66 |
static void cbcp_lowerup __P((int unit)); |
64 |
static void cbcp_lowerup __P((int unit)); |
Lines 84-91
Link Here
|
84 |
0, |
82 |
0, |
85 |
"CBCP", |
83 |
"CBCP", |
86 |
NULL, |
84 |
NULL, |
87 |
cbcp_option_list, |
|
|
88 |
NULL, |
89 |
NULL, |
85 |
NULL, |
90 |
NULL |
86 |
NULL |
91 |
}; |
87 |
}; |
Lines 93-119
Link Here
|
93 |
cbcp_state cbcp[NUM_PPP]; |
89 |
cbcp_state cbcp[NUM_PPP]; |
94 |
|
90 |
|
95 |
/* internal prototypes */ |
91 |
/* internal prototypes */ |
96 |
|
92 |
static void cbcp_sendreq __P((void *arg)); |
97 |
static void cbcp_recvreq __P((cbcp_state *us, u_char *pckt, int len)); |
93 |
static void cbcp_recvreq __P((cbcp_state *us, u_char *pckt, int len)); |
98 |
static void cbcp_resp __P((cbcp_state *us)); |
94 |
static void cbcp_sendresp __P((cbcp_state *us)); |
99 |
static void cbcp_up __P((cbcp_state *us)); |
95 |
static void cbcp_recvresp __P((cbcp_state *us, char *pckt, int len)); |
|
|
96 |
static void cbcp_sendack __P((void *)); |
100 |
static void cbcp_recvack __P((cbcp_state *us, u_char *pckt, int len)); |
97 |
static void cbcp_recvack __P((cbcp_state *us, u_char *pckt, int len)); |
|
|
98 |
|
101 |
static void cbcp_send __P((cbcp_state *us, int code, u_char *buf, int len)); |
99 |
static void cbcp_send __P((cbcp_state *us, int code, u_char *buf, int len)); |
|
|
100 |
static void cbcp_make_options __P((int unit)); |
101 |
static int cbcp_check_user __P((char *user, char *mask)); |
102 |
static void cbcp_start_callback __P((cbcp_state *us)); |
103 |
static void cbcp_up __P((cbcp_state *us)); |
102 |
|
104 |
|
103 |
/* option processing */ |
105 |
|
104 |
static int |
106 |
cbcp_state *stop_iface = NULL; |
105 |
setcbcp(argv) |
107 |
|
106 |
char **argv; |
108 |
void (*cbcp_init_hook) __P((cbcp_state *)) = NULL; |
107 |
{ |
|
|
108 |
lcp_wantoptions[0].neg_cbcp = 1; |
109 |
cbcp_protent.enabled_flag = 1; |
110 |
cbcp[0].us_number = strdup(*argv); |
111 |
if (cbcp[0].us_number == 0) |
112 |
novm("callback number"); |
113 |
cbcp[0].us_type |= (1 << CB_CONF_USER); |
114 |
cbcp[0].us_type |= (1 << CB_CONF_ADMIN); |
115 |
return (1); |
116 |
} |
117 |
|
109 |
|
118 |
/* init state */ |
110 |
/* init state */ |
119 |
static void |
111 |
static void |
Lines 125-131
Link Here
|
125 |
us = &cbcp[iface]; |
117 |
us = &cbcp[iface]; |
126 |
memset(us, 0, sizeof(cbcp_state)); |
118 |
memset(us, 0, sizeof(cbcp_state)); |
127 |
us->us_unit = iface; |
119 |
us->us_unit = iface; |
128 |
us->us_type |= (1 << CB_CONF_NO); |
|
|
129 |
} |
120 |
} |
130 |
|
121 |
|
131 |
/* lower layer is up */ |
122 |
/* lower layer is up */ |
Lines 135-152
Link Here
|
135 |
{ |
126 |
{ |
136 |
cbcp_state *us = &cbcp[iface]; |
127 |
cbcp_state *us = &cbcp[iface]; |
137 |
|
128 |
|
138 |
dbglog("cbcp_lowerup"); |
129 |
CBCPDEBUG((LOG_DEBUG, "cbcp_lowerup")); |
139 |
dbglog("want: %d", us->us_type); |
130 |
CBCPDEBUG((LOG_DEBUG, "want: %d", us->us_type)); |
140 |
|
|
|
141 |
if (us->us_type == CB_CONF_USER) |
142 |
dbglog("phone no: %s", us->us_number); |
143 |
} |
131 |
} |
144 |
|
132 |
|
145 |
static void |
133 |
static void |
146 |
cbcp_open(unit) |
134 |
cbcp_open(unit) |
147 |
int unit; |
135 |
int unit; |
148 |
{ |
136 |
{ |
149 |
dbglog("cbcp_open"); |
137 |
CBCPDEBUG((LOG_DEBUG, "cbcp_open")); |
|
|
138 |
if (lcp_hisoptions[unit].neg_cbcp) |
139 |
cbcp_make_options(unit); |
150 |
} |
140 |
} |
151 |
|
141 |
|
152 |
/* process an incomming packet */ |
142 |
/* process an incomming packet */ |
Lines 161-171
Link Here
|
161 |
u_short len; |
151 |
u_short len; |
162 |
|
152 |
|
163 |
cbcp_state *us = &cbcp[unit]; |
153 |
cbcp_state *us = &cbcp[unit]; |
|
|
154 |
lcp_options *go = &lcp_gotoptions[unit]; |
155 |
lcp_options *his = &lcp_hisoptions[unit]; |
164 |
|
156 |
|
165 |
inp = inpacket; |
157 |
inp = inpacket; |
166 |
|
158 |
|
167 |
if (pktlen < CBCP_MINLEN) { |
159 |
if (pktlen < CBCP_MINLEN) { |
168 |
error("CBCP packet is too small"); |
160 |
syslog(LOG_ERR, "CBCP packet is too small"); |
169 |
return; |
161 |
return; |
170 |
} |
162 |
} |
171 |
|
163 |
|
Lines 175-181
Link Here
|
175 |
|
167 |
|
176 |
#if 0 |
168 |
#if 0 |
177 |
if (len > pktlen) { |
169 |
if (len > pktlen) { |
178 |
error("CBCP packet: invalid length"); |
170 |
syslog(LOG_ERR, "CBCP packet: invalid length"); |
179 |
return; |
171 |
return; |
180 |
} |
172 |
} |
181 |
#endif |
173 |
#endif |
Lines 184-200
Link Here
|
184 |
|
176 |
|
185 |
switch(code) { |
177 |
switch(code) { |
186 |
case CBCP_REQ: |
178 |
case CBCP_REQ: |
|
|
179 |
if ( !go->neg_cbcp ) |
180 |
{ |
181 |
syslog(LOG_ERR, "CBCP received CBCP_REQ, but CBCP running in server mode!"); |
182 |
return; |
183 |
} |
187 |
us->us_id = id; |
184 |
us->us_id = id; |
188 |
cbcp_recvreq(us, inp, len); |
185 |
cbcp_recvreq(us, inp, len); |
189 |
break; |
186 |
break; |
190 |
|
187 |
|
191 |
case CBCP_RESP: |
188 |
case CBCP_RESP: |
192 |
dbglog("CBCP_RESP received"); |
189 |
if ( !his->neg_cbcp ) |
|
|
190 |
{ |
191 |
syslog(LOG_ERR, "CBCP received CBCP_RESP, but CBCP running in client mode!"); |
192 |
return; |
193 |
} |
194 |
if (id != us->us_id) |
195 |
syslog(LOG_DEBUG, "id doesn't match: expected %d recv %d", |
196 |
us->us_id, id); |
197 |
|
198 |
cbcp_recvresp(us, inp, len); |
193 |
break; |
199 |
break; |
194 |
|
200 |
|
195 |
case CBCP_ACK: |
201 |
case CBCP_ACK: |
|
|
202 |
if ( !go->neg_cbcp ) |
203 |
{ |
204 |
syslog(LOG_ERR, "CBCP received CBCP_ACK, but CBCP running in server mode!"); |
205 |
return; |
206 |
} |
196 |
if (id != us->us_id) |
207 |
if (id != us->us_id) |
197 |
dbglog("id doesn't match: expected %d recv %d", |
208 |
syslog(LOG_DEBUG, "id doesn't match: expected %d recv %d", |
198 |
us->us_id, id); |
209 |
us->us_id, id); |
199 |
|
210 |
|
200 |
cbcp_recvack(us, inp, len); |
211 |
cbcp_recvack(us, inp, len); |
Lines 274-286
Link Here
|
274 |
printer(arg, " delay = %d", delay); |
285 |
printer(arg, " delay = %d", delay); |
275 |
} |
286 |
} |
276 |
|
287 |
|
277 |
if (olen > 3) { |
288 |
if (olen > 4) { |
278 |
int addrt; |
289 |
int addrt; |
279 |
char str[256]; |
290 |
char str[256]; |
280 |
|
291 |
|
281 |
GETCHAR(addrt, p); |
292 |
GETCHAR(addrt, p); |
282 |
memcpy(str, p, olen - 4); |
293 |
memcpy(str, p, olen - 4); |
283 |
str[olen - 4] = 0; |
294 |
str[olen - 4] = 0; |
|
|
295 |
p += olen - 4; |
284 |
printer(arg, " number = %s", str); |
296 |
printer(arg, " number = %s", str); |
285 |
} |
297 |
} |
286 |
printer(arg, ">"); |
298 |
printer(arg, ">"); |
Lines 306-346
Link Here
|
306 |
u_char *pckt; |
318 |
u_char *pckt; |
307 |
int pcktlen; |
319 |
int pcktlen; |
308 |
{ |
320 |
{ |
309 |
u_char type, opt_len, delay, addr_type; |
321 |
u_char type, opt_len, addr_type; |
310 |
char address[256]; |
322 |
char address[256]; |
311 |
int len = pcktlen; |
323 |
int len = pcktlen; |
312 |
|
324 |
|
313 |
address[0] = 0; |
325 |
address[0] = 0; |
314 |
|
326 |
|
315 |
while (len) { |
327 |
while (len) { |
316 |
dbglog("length: %d", len); |
|
|
317 |
|
318 |
GETCHAR(type, pckt); |
328 |
GETCHAR(type, pckt); |
319 |
GETCHAR(opt_len, pckt); |
329 |
GETCHAR(opt_len, pckt); |
320 |
|
330 |
|
|
|
331 |
us->us_delay = 0; |
321 |
if (opt_len > 2) |
332 |
if (opt_len > 2) |
322 |
GETCHAR(delay, pckt); |
333 |
GETCHAR(us->us_delay, pckt); |
323 |
|
334 |
|
324 |
us->us_allowed |= (1 << type); |
335 |
us->us_allowed |= (1 << type); |
325 |
|
336 |
|
326 |
switch(type) { |
337 |
switch(type) { |
327 |
case CB_CONF_NO: |
338 |
case CB_CONF_NO: |
328 |
dbglog("no callback allowed"); |
339 |
CBCPDEBUG((LOG_DEBUG, "no callback allowed")); |
329 |
break; |
340 |
break; |
330 |
|
341 |
|
331 |
case CB_CONF_USER: |
342 |
case CB_CONF_USER: |
332 |
dbglog("user callback allowed"); |
343 |
CBCPDEBUG((LOG_DEBUG, "user callback allowed")); |
333 |
if (opt_len > 4) { |
344 |
if (opt_len > 4) { |
334 |
GETCHAR(addr_type, pckt); |
345 |
GETCHAR(addr_type, pckt); |
335 |
memcpy(address, pckt, opt_len - 4); |
346 |
memcpy(address, pckt, opt_len - 4); |
336 |
address[opt_len - 4] = 0; |
347 |
address[opt_len - 4] = 0; |
337 |
if (address[0]) |
348 |
if (address[0]) |
338 |
dbglog("address: %s", address); |
349 |
CBCPDEBUG((LOG_DEBUG, "address: %s", address)); |
339 |
} |
350 |
} |
340 |
break; |
351 |
break; |
341 |
|
352 |
|
342 |
case CB_CONF_ADMIN: |
353 |
case CB_CONF_ADMIN: |
343 |
dbglog("user admin defined allowed"); |
354 |
CBCPDEBUG((LOG_DEBUG, "user admin defined allowed")); |
344 |
break; |
355 |
break; |
345 |
|
356 |
|
346 |
case CB_CONF_LIST: |
357 |
case CB_CONF_LIST: |
Lines 349-407
Link Here
|
349 |
len -= opt_len; |
360 |
len -= opt_len; |
350 |
} |
361 |
} |
351 |
|
362 |
|
352 |
cbcp_resp(us); |
363 |
cbcp_sendresp(us); |
353 |
} |
364 |
} |
354 |
|
365 |
|
355 |
static void |
366 |
static void |
356 |
cbcp_resp(us) |
367 |
cbcp_sendresp(us) |
357 |
cbcp_state *us; |
368 |
cbcp_state *us; |
358 |
{ |
369 |
{ |
359 |
u_char cb_type; |
370 |
u_char cb_allowed; |
360 |
u_char buf[256]; |
371 |
u_char buf[256]; |
361 |
u_char *bufp = buf; |
372 |
u_char *bufp = buf; |
362 |
int len = 0; |
373 |
int len = 0; |
363 |
|
374 |
|
364 |
cb_type = us->us_allowed & us->us_type; |
375 |
cb_allowed = us->us_allowed; |
365 |
dbglog("cbcp_resp cb_type=%d", cb_type); |
376 |
CBCPDEBUG((LOG_DEBUG, "cbcp_sendresp: available options: %d", cb_allowed)); |
366 |
|
377 |
|
367 |
#if 0 |
378 |
#if 0 |
368 |
if (!cb_type) |
379 |
if (!cb_allowed) |
369 |
lcp_down(us->us_unit); |
380 |
lcp_down(us->us_unit); |
370 |
#endif |
381 |
#endif |
371 |
|
382 |
|
372 |
if (cb_type & ( 1 << CB_CONF_USER ) ) { |
383 |
if (cb_allowed & ( 1 << CB_CONF_USER ) ) { |
373 |
dbglog("cbcp_resp CONF_USER"); |
384 |
us->us_type= ( 1 << CB_CONF_USER ); |
|
|
385 |
CBCPDEBUG((LOG_DEBUG, "cbcp_sendresp CONF_USER")); |
374 |
PUTCHAR(CB_CONF_USER, bufp); |
386 |
PUTCHAR(CB_CONF_USER, bufp); |
375 |
len = 3 + 1 + strlen(us->us_number) + 1; |
387 |
len = 3 + 1 + strlen(us->us_number) + 1; |
376 |
PUTCHAR(len , bufp); |
388 |
PUTCHAR(len , bufp); |
377 |
PUTCHAR(5, bufp); /* delay */ |
389 |
PUTCHAR(us->us_delay, bufp); |
378 |
PUTCHAR(1, bufp); |
390 |
PUTCHAR(1, bufp); |
379 |
BCOPY(us->us_number, bufp, strlen(us->us_number) + 1); |
391 |
BCOPY(us->us_number, bufp, strlen(us->us_number) + 1); |
380 |
cbcp_send(us, CBCP_RESP, buf, len); |
392 |
cbcp_send(us, CBCP_RESP, buf, len); |
381 |
return; |
393 |
return; |
382 |
} |
394 |
} |
383 |
|
395 |
|
384 |
if (cb_type & ( 1 << CB_CONF_ADMIN ) ) { |
396 |
if (cb_allowed & ( 1 << CB_CONF_ADMIN ) ) { |
385 |
dbglog("cbcp_resp CONF_ADMIN"); |
397 |
us->us_type= ( 1 << CB_CONF_ADMIN ); |
|
|
398 |
CBCPDEBUG((LOG_DEBUG, "cbcp_sendresp CONF_ADMIN")); |
386 |
PUTCHAR(CB_CONF_ADMIN, bufp); |
399 |
PUTCHAR(CB_CONF_ADMIN, bufp); |
387 |
len = 3; |
400 |
len = 3; |
388 |
PUTCHAR(len, bufp); |
401 |
PUTCHAR(len , bufp); |
389 |
PUTCHAR(5, bufp); /* delay */ |
402 |
PUTCHAR(us->us_delay, bufp); |
390 |
cbcp_send(us, CBCP_RESP, buf, len); |
403 |
cbcp_send(us, CBCP_RESP, buf, len); |
391 |
return; |
404 |
return; |
392 |
} |
405 |
} |
393 |
|
406 |
|
394 |
if (cb_type & ( 1 << CB_CONF_NO ) ) { |
407 |
if (cb_allowed & ( 1 << CB_CONF_NO ) ) { |
395 |
dbglog("cbcp_resp CONF_NO"); |
408 |
us->us_type= ( 1 << CB_CONF_NO ); |
|
|
409 |
CBCPDEBUG((LOG_DEBUG, "cbcp_sendresp CONF_NO")); |
396 |
PUTCHAR(CB_CONF_NO, bufp); |
410 |
PUTCHAR(CB_CONF_NO, bufp); |
397 |
len = 2; |
411 |
len = 3; |
398 |
PUTCHAR(len , bufp); |
412 |
PUTCHAR(len , bufp); |
|
|
413 |
PUTCHAR(0, bufp); |
399 |
cbcp_send(us, CBCP_RESP, buf, len); |
414 |
cbcp_send(us, CBCP_RESP, buf, len); |
400 |
start_networks(us->us_unit); |
|
|
401 |
return; |
415 |
return; |
402 |
} |
416 |
} |
|
|
417 |
syslog(LOG_WARNING, "cbcp_sendresp: no usable options available!"); |
403 |
} |
418 |
} |
404 |
|
419 |
|
|
|
420 |
/* Send the packet */ |
405 |
static void |
421 |
static void |
406 |
cbcp_send(us, code, buf, len) |
422 |
cbcp_send(us, code, buf, len) |
407 |
cbcp_state *us; |
423 |
cbcp_state *us; |
Lines 428-470
Link Here
|
428 |
output(us->us_unit, outpacket_buf, outlen + PPP_HDRLEN); |
444 |
output(us->us_unit, outpacket_buf, outlen + PPP_HDRLEN); |
429 |
} |
445 |
} |
430 |
|
446 |
|
|
|
447 |
/* Received Ack */ |
431 |
static void |
448 |
static void |
432 |
cbcp_recvack(us, pckt, len) |
449 |
cbcp_recvack(us, pckt, len) |
433 |
cbcp_state *us; |
450 |
cbcp_state *us; |
434 |
u_char *pckt; |
451 |
u_char *pckt; |
435 |
int len; |
452 |
int len; |
436 |
{ |
453 |
{ |
437 |
u_char type, delay, addr_type; |
454 |
u_char type, addr_type; |
438 |
int opt_len; |
455 |
int opt_len; |
439 |
char address[256]; |
456 |
char address[256]; |
440 |
|
457 |
|
|
|
458 |
stop_iface = us; |
459 |
|
441 |
if (len) { |
460 |
if (len) { |
442 |
GETCHAR(type, pckt); |
461 |
GETCHAR(type, pckt); |
443 |
GETCHAR(opt_len, pckt); |
462 |
GETCHAR(opt_len, pckt); |
444 |
|
463 |
|
445 |
if (opt_len > 2) |
464 |
if (opt_len > 2) |
446 |
GETCHAR(delay, pckt); |
465 |
GETCHAR(us->us_delay, pckt); |
447 |
|
466 |
|
448 |
if (opt_len > 4) { |
467 |
if (opt_len > 4) { |
449 |
GETCHAR(addr_type, pckt); |
468 |
GETCHAR(addr_type, pckt); |
450 |
memcpy(address, pckt, opt_len - 4); |
469 |
memcpy(address, pckt, opt_len - 4); |
451 |
address[opt_len - 4] = 0; |
470 |
address[opt_len - 4] = 0; |
452 |
if (address[0]) |
471 |
if (address[0]) |
453 |
dbglog("peer will call: %s", address); |
472 |
CBCPDEBUG((LOG_DEBUG, "peer will call: %s", address)); |
454 |
} |
473 |
} |
455 |
if (type == CB_CONF_NO) |
474 |
if (type != CB_CONF_NO) |
456 |
return; |
475 |
{ |
|
|
476 |
callback_in_progress = us->us_unit + 1; |
477 |
callback_in_progress |= CBCP_CLIENT; |
478 |
cbcp_up(us); |
479 |
} |
480 |
else |
481 |
network_phase(us->us_unit); |
457 |
} |
482 |
} |
|
|
483 |
else |
484 |
syslog(LOG_DEBUG, "cbcp: received bad ack - packet too small"); |
485 |
} |
486 |
|
487 |
/* Make options |
488 |
+ if auth req, options from callback-users file, else use CBCP_CONF_USER */ |
489 |
static void |
490 |
cbcp_make_options (unit) |
491 |
int unit; |
492 |
{ |
493 |
cbcp_state *us = &cbcp[unit]; |
494 |
FILE *userfile; |
495 |
struct stat sbuf; |
496 |
int best_fit, got_fit, newline; |
497 |
char uname[ 256 ], option[ 256 ]; |
498 |
|
499 |
us->us_id = 1; |
500 |
us->us_count = 0; |
501 |
us->us_delay = 5; /* Default delay 5 seconds */ |
502 |
if ( *peer_authname ) { /* Username available */ |
503 |
userfile = fopen( _PATH_CBCP_USERS, "r" ); |
504 |
if ( userfile == NULL ) { |
505 |
syslog( LOG_ERR, "Can't open callback user file: %s %m", |
506 |
_PATH_CBCP_USERS ); |
507 |
syslog( LOG_WARNING, "Allow user definied callback." ); |
508 |
us->us_allowed = ( 1 << CB_CONF_USER ); |
509 |
} |
510 |
else |
511 |
{ |
512 |
if ( fstat(fileno(userfile), &sbuf) < 0) { |
513 |
syslog( LOG_WARNING, "Cannot stat userfile file %s: %m", |
514 |
_PATH_CBCP_USERS ); |
515 |
} |
516 |
else |
517 |
if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) { |
518 |
syslog( LOG_WARNING, "Warning - user file %s has world and/or group access", |
519 |
_PATH_CBCP_USERS ); |
520 |
} |
521 |
|
522 |
us->us_allowed = ( 1 << CB_CONF_NO ); /* Assume, no callback allowed */ |
523 |
|
524 |
if ( getword(userfile, uname, &newline, _PATH_CBCP_USERS) ) { /* file not empty */ |
525 |
newline = 1; |
526 |
best_fit = 0; |
527 |
*option = 0; |
528 |
for (;;) { |
529 |
/* |
530 |
* Skip until we find a word at the start of a line. |
531 |
*/ |
532 |
while ( !newline && getword(userfile, uname, |
533 |
&newline, _PATH_CBCP_USERS)) |
534 |
; |
535 |
if ( !newline ) |
536 |
break; /* got to end of file */ |
537 |
|
538 |
/* |
539 |
* Got a user - check if it's a match or a wildcard. |
540 |
*/ |
541 |
got_fit = cbcp_check_user( peer_authname, uname ); |
542 |
if ( got_fit <= best_fit ) { |
543 |
newline = 0; |
544 |
continue; |
545 |
} |
546 |
|
547 |
/* Read the options */ |
548 |
best_fit = got_fit; |
549 |
if ( getword(userfile, option, &newline, _PATH_CBCP_USERS) ) |
550 |
break; |
551 |
|
552 |
if ( newline ) |
553 |
*option = 0; |
554 |
|
555 |
if ( best_fit == 100 ) |
556 |
break; |
557 |
} |
558 |
} |
559 |
|
560 |
switch ( *option ) { |
561 |
case '-': |
562 |
us->us_allowed = ( 1 << CB_CONF_NO ); |
563 |
break; |
564 |
case '*': |
565 |
case 0: |
566 |
us->us_allowed = ( 1 << CB_CONF_USER ); |
567 |
break; |
568 |
default: |
569 |
us->us_allowed = ( 1 << CB_CONF_ADMIN ); |
570 |
us->us_number = strdup( option ); |
571 |
break; |
572 |
} |
573 |
fclose( userfile ); |
574 |
} |
575 |
} |
576 |
else |
577 |
us->us_allowed = ( 1 << CB_CONF_USER ); |
578 |
|
579 |
if (cbcp_init_hook) |
580 |
cbcp_init_hook( us ); |
581 |
|
582 |
cbcp_sendreq( us ); |
583 |
} |
458 |
|
584 |
|
459 |
cbcp_up(us); |
585 |
/* make cbcp request packet & send it */ |
|
|
586 |
static void |
587 |
cbcp_sendreq (arg) |
588 |
void *arg; |
589 |
{ |
590 |
cbcp_state *us=(cbcp_state *)arg; |
591 |
u_char cb_allow = us->us_allowed; |
592 |
u_char buf[256]; |
593 |
u_char *bufp = buf; |
594 |
int len = 0; |
595 |
|
596 |
us->us_count++; |
597 |
if ( us->us_count<=CBCP_MAXRETRY ) |
598 |
TIMEOUT( cbcp_sendreq, arg, CBCP_DEFTIMEOUT ); |
599 |
else |
600 |
{ |
601 |
lcp_close(0, "Sorry, CBCP not responding."); |
602 |
return; |
603 |
} |
604 |
CBCPDEBUG((LOG_DEBUG, "cbcp_sendreq cb_allowed=%d", cb_allow)); |
605 |
|
606 |
if ( cb_allow & ( 1 << CB_CONF_USER ) ) { |
607 |
CBCPDEBUG((LOG_DEBUG, "cbcp_sendreq CONF_USER")); |
608 |
PUTCHAR(CB_CONF_USER, bufp); |
609 |
len+=3; |
610 |
PUTCHAR(3 , bufp); |
611 |
PUTCHAR(us->us_delay, bufp); |
612 |
} |
613 |
|
614 |
if ( cb_allow & ( 1 << CB_CONF_ADMIN ) ) { |
615 |
CBCPDEBUG((LOG_DEBUG, "cbcp_sendreq CONF_ADMIN")); |
616 |
PUTCHAR(CB_CONF_ADMIN, bufp); |
617 |
len += 3; |
618 |
PUTCHAR(3 , bufp); |
619 |
PUTCHAR(us->us_delay, bufp); |
620 |
} |
621 |
|
622 |
if ( cb_allow & ( 1 << CB_CONF_NO ) ) { |
623 |
CBCPDEBUG((LOG_DEBUG, "cbcp_sendreq CONF_NO")); |
624 |
PUTCHAR(CB_CONF_NO, bufp); |
625 |
len += 3; |
626 |
PUTCHAR(3 , bufp); |
627 |
PUTCHAR(us->us_delay, bufp); |
628 |
} |
629 |
|
630 |
if ( len ) |
631 |
cbcp_send(us, CBCP_REQ, buf, len); |
632 |
else |
633 |
{ |
634 |
syslog(LOG_WARNING, "cbcp: no available options to client!"); |
635 |
} |
636 |
} |
637 |
|
638 |
/* Received CBCP response, make ACK */ |
639 |
static void |
640 |
cbcp_recvresp (us, pckt, len) |
641 |
cbcp_state *us; |
642 |
char *pckt; |
643 |
int len; |
644 |
{ |
645 |
u_char type, addr_type; |
646 |
int opt_len; |
647 |
char address[256]; |
648 |
|
649 |
if ( len ) { |
650 |
GETCHAR(type, pckt); |
651 |
GETCHAR(opt_len, pckt); |
652 |
|
653 |
if ( !((1 << type) & us->us_allowed) ) { |
654 |
CBCPDEBUG((LOG_DEBUG, "CBCP received options not allowed on server!")); |
655 |
return; |
656 |
} |
657 |
|
658 |
if ( (type!= CB_CONF_NO ) && |
659 |
(type!= CB_CONF_USER ) && |
660 |
(type!= CB_CONF_ADMIN ) ) { |
661 |
syslog(LOG_DEBUG, "CBCP received BAD Response: too more or unknown options %d",type); |
662 |
return; |
663 |
} |
664 |
|
665 |
UNTIMEOUT( cbcp_sendreq, us ); |
666 |
us->us_count = 0; |
667 |
|
668 |
if ( opt_len > 2 ) |
669 |
GETCHAR(us->us_delay, pckt) |
670 |
if ( us->us_delay < 5 ) |
671 |
us->us_delay = 5; |
672 |
|
673 |
if ( opt_len > 4 ) { |
674 |
GETCHAR(addr_type, pckt); /* Address Type mezo elvesztve !!! */ |
675 |
memcpy(address, pckt, opt_len - 4); |
676 |
address[opt_len - 4] = 0; |
677 |
if ( address[0] ) |
678 |
syslog(LOG_DEBUG, "peer will callback the client on: %s", address); |
679 |
us->us_number=strdup( address ); |
680 |
} |
681 |
|
682 |
us->us_type = ( 1 << type ); |
683 |
cbcp_sendack( us ); |
684 |
} |
685 |
else |
686 |
{ |
687 |
syslog(LOG_DEBUG, "CBCP received BAD Response: size to small"); |
688 |
} |
689 |
} |
690 |
|
691 |
/* Send the CBCP_ACK packet */ |
692 |
static void |
693 |
cbcp_sendack (arg) |
694 |
void *arg; |
695 |
{ |
696 |
cbcp_state *us= (cbcp_state *)arg; |
697 |
u_char cb_type; |
698 |
u_char buf[256]; |
699 |
u_char *bufp = buf; |
700 |
int len = 0; |
701 |
|
702 |
stop_iface = (cbcp_state *)arg; |
703 |
cb_type = us->us_type; |
704 |
|
705 |
CBCPDEBUG((LOG_DEBUG, "cbcp_sendack cb_type=%d", cb_type)); |
706 |
|
707 |
us->us_count++; |
708 |
if ( us->us_count<=CBCP_MAXRETRY ) |
709 |
TIMEOUT( cbcp_sendack, arg, CBCP_DEFTIMEOUT ); |
710 |
else |
711 |
{ |
712 |
lcp_close(0, "Sorry, CBCP not responding."); |
713 |
return; |
714 |
} |
715 |
|
716 |
#if 0 |
717 |
if ( !cb_type ) |
718 |
lcp_down(us->us_unit); |
719 |
#endif |
720 |
|
721 |
if ( cb_type == (1 << CB_CONF_USER ) ) { |
722 |
CBCPDEBUG((LOG_DEBUG, "cbcp_sendack CONF_USER")); |
723 |
PUTCHAR(CB_CONF_USER, bufp); |
724 |
len = 3 + 1 + strlen(us->us_number) + 1; |
725 |
PUTCHAR(len , bufp); |
726 |
PUTCHAR(us->us_delay, bufp); /* delay */ |
727 |
PUTCHAR(1, bufp); /* Elvesztett byte... */ |
728 |
BCOPY(us->us_number, bufp, strlen(us->us_number) + 1); |
729 |
cbcp_send(us, CBCP_ACK, buf, len); |
730 |
/* lcp_close( 2, "Illegal, but required to server..." ); */ |
731 |
callback_in_progress = us->us_unit + 1; |
732 |
return; |
733 |
} |
734 |
|
735 |
if ( cb_type == (1 << CB_CONF_ADMIN ) ) { |
736 |
CBCPDEBUG((LOG_DEBUG, "cbcp_sendack CONF_ADMIN")); |
737 |
PUTCHAR(CB_CONF_ADMIN, bufp); |
738 |
len = 3; |
739 |
PUTCHAR(len , bufp); |
740 |
PUTCHAR(us->us_delay, bufp); /* delay */ |
741 |
PUTCHAR(0, bufp); |
742 |
cbcp_send(us, CBCP_ACK, buf, len); |
743 |
/* lcp_close( 2, "Illegal, but required to server..." ); */ |
744 |
callback_in_progress = us->us_unit + 1; |
745 |
return; |
746 |
} |
747 |
|
748 |
if ( cb_type == (1 << CB_CONF_NO ) ) { |
749 |
CBCPDEBUG((LOG_DEBUG, "cbcp_sendack CONF_NO")); |
750 |
PUTCHAR(CB_CONF_NO, bufp); |
751 |
len = 3; |
752 |
PUTCHAR(len , bufp); |
753 |
PUTCHAR(0, bufp); |
754 |
cbcp_send(us, CBCP_ACK, buf, len); |
755 |
if (us->us_count<=1) |
756 |
network_phase(us->us_unit); |
757 |
return; |
758 |
} |
759 |
|
760 |
syslog(LOG_DEBUG, "CBCP - Bad options in Ack routine."); |
761 |
|
762 |
} |
763 |
|
764 |
/* CBCP coming succesful up */ |
765 |
void cbcp_stop() |
766 |
{ |
767 |
if ( stop_iface && lcp_allowoptions[stop_iface->us_unit].neg_cbcp ) |
768 |
{ |
769 |
UNTIMEOUT( cbcp_sendack, stop_iface ); |
770 |
cbcp_start_callback( stop_iface ); |
771 |
} |
460 |
} |
772 |
} |
461 |
|
773 |
|
462 |
/* ok peer will do callback */ |
774 |
/* The server side coming up & client 'ack-ed' */ |
|
|
775 |
void cbcp_start_callback (us) |
776 |
cbcp_state *us; |
777 |
{ |
778 |
lcp_allowoptions[us->us_unit].neg_cbcp=0; |
779 |
|
780 |
CBCPDEBUG((LOG_DEBUG, "cbcp_start_callback running")); |
781 |
} |
782 |
|
783 |
/* The client side coming up: server allowed the callback */ |
463 |
static void |
784 |
static void |
464 |
cbcp_up(us) |
785 |
cbcp_up(us) |
465 |
cbcp_state *us; |
786 |
cbcp_state *us; |
466 |
{ |
787 |
{ |
467 |
persist = 0; |
788 |
lcp_wantoptions[us->us_unit].neg_cbcp=0; |
468 |
lcp_close(0, "Call me back, please"); |
789 |
CBCPDEBUG((LOG_DEBUG, "cbcp_up called")); |
469 |
status = EXIT_CALLBACK; |
790 |
lcp_close(us->us_unit, "Call me back, please"); |
|
|
791 |
} |
792 |
|
793 |
/* The main module gets the script with parameters to run */ |
794 |
char *cbcp_get_script() |
795 |
{ |
796 |
cbcp_state *us = &cbcp[(callback_in_progress & CBCP_NCLIENT)-1]; |
797 |
char script[ 256 ]; |
798 |
|
799 |
if ( callback_in_progress & CBCP_CLIENT ) |
800 |
sprintf( script, "%s %d", _PATH_CBCP_CLIENT, us->us_delay ); |
801 |
else |
802 |
sprintf( script, "%s %d %s", _PATH_CBCP_SERVER, |
803 |
us->us_delay, us->us_number ); |
804 |
|
805 |
return strdup( script ); |
806 |
} |
807 |
|
808 |
/* give me the hit rate. wild cars '*?' valids */ |
809 |
int cbcp_check_user ( user, mask ) |
810 |
char *user; |
811 |
char *mask; |
812 |
{ |
813 |
char *curr_user = user; |
814 |
char *curr_mask = mask; |
815 |
char *find, backp = 0; |
816 |
int count, len = 0; |
817 |
|
818 |
if ( !strcasecmp( user, mask ) ) |
819 |
return 100; |
820 |
|
821 |
if ( !strcmp( mask, "*" ) ) |
822 |
return 1; |
823 |
if ( !*user ) |
824 |
return 0; |
825 |
|
826 |
count = 0; |
827 |
|
828 |
while(( find = strpbrk( curr_mask, "*?" )) != 0 ) { |
829 |
if ( find != curr_mask ) { |
830 |
len = find - curr_mask; |
831 |
if ( strncmp( curr_user, curr_mask, len ) ) |
832 |
break; |
833 |
} |
834 |
|
835 |
curr_mask += len + 1; |
836 |
curr_user += len; |
837 |
count += len; |
838 |
if ( *curr_user == 0 ) |
839 |
break; |
840 |
|
841 |
if ( *find == '?' ) { |
842 |
curr_user++; |
843 |
if ( *curr_user == 0 ) |
844 |
break; |
845 |
} else { |
846 |
if ( *curr_mask == 0 ) |
847 |
break; |
848 |
|
849 |
if ( ( find = strpbrk( curr_mask, "*?" )) != 0 ) { |
850 |
backp = *find; |
851 |
*find = 0; |
852 |
} |
853 |
curr_user = strstr( curr_user, curr_mask ); |
854 |
if ( find ) |
855 |
*find = backp; |
856 |
if ( !curr_user ) |
857 |
break; |
858 |
|
859 |
find = strpbrk( curr_mask, "*?" ); |
860 |
if ( find ) |
861 |
len = find - curr_mask; |
862 |
else |
863 |
len = strlen( curr_mask ); |
864 |
|
865 |
curr_mask += len; |
866 |
curr_user += len; |
867 |
count += len; |
868 |
} |
869 |
} |
870 |
|
871 |
if ( *curr_user && *curr_mask && !strcmp( curr_user, curr_mask ) ) |
872 |
count += strlen( curr_user ); |
873 |
|
874 |
return ( count * 100 / strlen( user ) ); |
470 |
} |
875 |
} |