packet.c 13.7 KB
Newer Older
K
Kozlov Dmitry 已提交
1 2 3 4
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
D
Dmitry Kozlov 已提交
5 6
#include <stdio.h>
#include <unistd.h>
7
#include <fcntl.h>
D
Dmitry Kozlov 已提交
8 9

#include "log.h"
10
#include "mempool.h"
K
Kozlov Dmitry 已提交
11

12
#include "radius_p.h"
K
Kozlov Dmitry 已提交
13

D
Dmitry Kozlov 已提交
14 15
#include "memdebug.h"

16 17 18
static mempool_t packet_pool;
static mempool_t attr_pool;

19 20 21 22
struct rad_packet_t *rad_packet_alloc(int code)
{
	struct rad_packet_t *pack;

23
	pack = mempool_alloc(packet_pool);
24
	if (!pack) {
25
		log_emerg("radius:packet: out of memory\n");
26 27 28 29 30 31 32 33 34 35 36
		return NULL;
	}

	memset(pack, 0, sizeof(*pack));
	pack->code = code;
	pack->len = 20;
	pack->id = 1;
	INIT_LIST_HEAD(&pack->attrs);

	return pack;
}
K
Kozlov Dmitry 已提交
37

38 39 40 41 42 43 44 45 46
void print_buf(uint8_t *buf,int size)
{
	int i;
	for(i=0;i<size;i++)
		printf("%x ",buf[i]);
	printf("\n");
}

int rad_packet_build(struct rad_packet_t *pack, uint8_t *RA)
K
Kozlov Dmitry 已提交
47
{
48
	struct rad_attr_t *attr;
K
Kozlov Dmitry 已提交
49 50
	uint8_t *ptr;

51
	if (pack->buf)
D
Dmitry Kozlov 已提交
52
		ptr = _realloc(pack->buf, pack->len);
53
	else
D
Dmitry Kozlov 已提交
54
		ptr = _malloc(pack->len);
55

K
Kozlov Dmitry 已提交
56
	if (!ptr) {
57
		log_emerg("radius:packet: out of memory\n");
K
Kozlov Dmitry 已提交
58 59 60
		return -1;
	}
	
61
	pack->buf = ptr;
K
Kozlov Dmitry 已提交
62 63
	*ptr = pack->code; ptr++;
	*ptr = pack->id; ptr++;
64 65
	*(uint16_t*)ptr = htons(pack->len); ptr+= 2;
	memcpy(ptr, RA, 16);	ptr+=16;
K
Kozlov Dmitry 已提交
66 67

	list_for_each_entry(attr, &pack->attrs, entry) {
68 69 70 71 72
		if (attr->vendor) {
			*ptr = 26; ptr++;
			*ptr = attr->len + 2 + 6; ptr++;
			*(uint32_t *)ptr = htonl(attr->vendor->id); ptr+=4;
		} 
73 74
		*ptr = attr->attr->id; ptr++;
		*ptr = attr->len + 2; ptr++;
D
Dmitry Kozlov 已提交
75
		switch(attr->attr->type) {
K
Kozlov Dmitry 已提交
76
			case ATTR_TYPE_INTEGER:
77
				*(uint32_t*)ptr = htonl(attr->val.integer);
K
Kozlov Dmitry 已提交
78
				break;
79
			case ATTR_TYPE_OCTETS:
K
Kozlov Dmitry 已提交
80
			case ATTR_TYPE_STRING:
D
Dmitry Kozlov 已提交
81
				memcpy(ptr, attr->val.string, attr->len);
K
Kozlov Dmitry 已提交
82 83 84 85 86
				break;
			case ATTR_TYPE_IPADDR:
				*(in_addr_t*)ptr = attr->val.ipaddr;
				break;
			case ATTR_TYPE_DATE:
87
				*(uint32_t*)ptr = htonl(attr->val.date);
K
Kozlov Dmitry 已提交
88 89
				break;
			default:
90
				log_emerg("radius:packet:BUG: unknown attribute type\n");
K
Kozlov Dmitry 已提交
91 92 93 94 95
				abort();
		}
		ptr += attr->len;
	}

96
	//print_buf(pack->buf, pack->len);
97
	return 0;
K
Kozlov Dmitry 已提交
98 99
}

K
Kozlov Dmitry 已提交
100
int rad_packet_recv(int fd, struct rad_packet_t **p, struct sockaddr_in *addr)
K
Kozlov Dmitry 已提交
101 102
{
	struct rad_packet_t *pack;
103
	struct rad_attr_t *attr;
K
Kozlov Dmitry 已提交
104
	struct rad_dict_attr_t *da;
105
	struct rad_dict_vendor_t *vendor;
K
Kozlov Dmitry 已提交
106
	uint8_t *ptr;
107
	int n, id, len, vendor_id;
108
	socklen_t addr_len = sizeof(*addr);
K
Kozlov Dmitry 已提交
109

K
Kozlov Dmitry 已提交
110 111
	*p = NULL;

112 113
	pack = rad_packet_alloc(0);
	if (!pack)
K
Kozlov Dmitry 已提交
114
		return 0;
K
Kozlov Dmitry 已提交
115

D
Dmitry Kozlov 已提交
116
	pack->buf = _malloc(REQ_LENGTH_MAX);
K
Kozlov Dmitry 已提交
117
	if (!pack->buf) {
118
		log_emerg("radius:packet: out of memory\n");
119
		goto out_err;
K
Kozlov Dmitry 已提交
120 121 122
	}

	while (1) {
123 124 125 126
		if (addr)
			n = recvfrom(fd, pack->buf, REQ_LENGTH_MAX, 0, addr, &addr_len);
		else
			n = read(fd, pack->buf, REQ_LENGTH_MAX);
K
Kozlov Dmitry 已提交
127
		if (n < 0) {
128 129
			if (errno == EAGAIN) {
				rad_packet_free(pack);
K
Kozlov Dmitry 已提交
130
				return -1;
131 132 133
			}
			if (errno != ECONNREFUSED)
				log_ppp_error("radius:packet:read: %s\n", strerror(errno));
K
Kozlov Dmitry 已提交
134 135 136 137 138 139
			goto out_err;
		}
		break;
	}

	if (n < 20) {
140
		log_ppp_warn("radius:packet: short packed received (%i)\n", n);
K
Kozlov Dmitry 已提交
141 142 143 144 145 146 147
		goto out_err;
	}

	ptr = (uint8_t *)pack->buf;

	pack->code = *ptr; ptr++;
	pack->id = *ptr; ptr++;
148
	pack->len = ntohs(*(uint16_t*)ptr); ptr += 2;
K
Kozlov Dmitry 已提交
149 150

	if (pack->len > n) {
151
		log_ppp_warn("radius:packet: short packet received %i, expected %i\n", pack->len, n);
K
Kozlov Dmitry 已提交
152 153 154 155 156 157 158
		goto out_err;
	}

	ptr += 16;
	n -= 20;

	while (n>0) {
159 160 161
		id = *ptr; ptr++;
		len = *ptr - 2; ptr++;
		if (len < 0) {
162
			log_ppp_warn("radius:packet short attribute len received\n");
163 164
			goto out_err;
		}
K
Kozlov Dmitry 已提交
165
		if (2 + len > n) {
166
			log_ppp_warn("radius:packet: too long attribute received (%i, %i)\n", id, len);
K
Kozlov Dmitry 已提交
167 168
			goto out_err;
		}
169 170 171 172 173 174 175
		if (id == 26) {
			vendor_id = ntohl(*(uint32_t *)ptr);
			vendor = rad_dict_find_vendor_id(vendor_id);
			if (vendor) {
				ptr += 4;
				id = *ptr; ptr++;
				len = *ptr - 2; ptr++;
176
				n -= 2 + 4;
177
			} else
178
				log_ppp_warn("radius:packet: vendor %i not found\n", id);
179 180
		} else
			vendor = NULL;
181
		da = rad_dict_find_attr_id(vendor, id);
K
Kozlov Dmitry 已提交
182
		if (da) {
183
			attr = mempool_alloc(attr_pool);
K
Kozlov Dmitry 已提交
184
			if (!attr) {
185
				log_emerg("radius:packet: out of memory\n");
K
Kozlov Dmitry 已提交
186 187
				goto out_err;
			}
188 189
			memset(attr, 0, sizeof(*attr));
			attr->vendor = vendor;
K
Kozlov Dmitry 已提交
190 191
			attr->attr = da;
			attr->len = len;
192 193
			switch (da->type) {
				case ATTR_TYPE_STRING:
D
Dmitry Kozlov 已提交
194
					attr->val.string = _malloc(len+1);
195
					if (!attr->val.string) {
196
						log_emerg("radius:packet: out of memory\n");
D
Dmitry Kozlov 已提交
197
						_free(attr);
198 199 200 201 202
						goto out_err;
					}
					memcpy(attr->val.string, ptr, len);
					attr->val.string[len] = 0;
					break;
203
				case ATTR_TYPE_OCTETS:
D
Dmitry Kozlov 已提交
204
					attr->val.octets = _malloc(len);
205
					if (!attr->val.octets) {
206
						log_emerg("radius:packet: out of memory\n");
D
Dmitry Kozlov 已提交
207
						_free(attr);
208 209 210 211
						goto out_err;
					}
					memcpy(attr->val.octets, ptr, len);
					break;				
212 213 214 215 216 217 218 219
				case ATTR_TYPE_DATE:
				case ATTR_TYPE_INTEGER:
					attr->val.integer = ntohl(*(uint32_t*)ptr);
					break;
				case ATTR_TYPE_IPADDR:
					attr->val.integer = *(uint32_t*)ptr;
					break;
			}
K
Kozlov Dmitry 已提交
220 221
			list_add_tail(&attr->entry, &pack->attrs);
		} else
222
			log_ppp_warn("radius:packet: unknown attribute received (%i,%i)\n", vendor ? vendor->id : 0, id);
K
Kozlov Dmitry 已提交
223 224 225 226
		ptr += len;
		n -= 2 + len;
	}

K
Kozlov Dmitry 已提交
227 228 229
	*p = pack;

	return 0;
K
Kozlov Dmitry 已提交
230 231 232

out_err:
	rad_packet_free(pack);
K
Kozlov Dmitry 已提交
233
	return 0;
K
Kozlov Dmitry 已提交
234 235 236 237
}

void rad_packet_free(struct rad_packet_t *pack)
{
238
	struct rad_attr_t *attr;
K
Kozlov Dmitry 已提交
239 240
	
	if (pack->buf)
D
Dmitry Kozlov 已提交
241
		_free(pack->buf);
K
Kozlov Dmitry 已提交
242 243 244 245

	while(!list_empty(&pack->attrs)) {
		attr = list_entry(pack->attrs.next, typeof(*attr), entry);
		list_del(&attr->entry);
D
Dmitry Kozlov 已提交
246 247
		if (attr->attr->type == ATTR_TYPE_STRING || attr->attr->type == ATTR_TYPE_OCTETS)
			_free(attr->val.string);
248
		mempool_free(attr);
K
Kozlov Dmitry 已提交
249 250
	}

251
	mempool_free(pack);
K
Kozlov Dmitry 已提交
252
}
253 254 255

void rad_packet_print(struct rad_packet_t *pack, void (*print)(const char *fmt, ...))
{
256
	struct rad_attr_t *attr;
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
	struct rad_dict_value_t *val;
	
	print("[RADIUS ");
	switch(pack->code) {
		case CODE_ACCESS_REQUEST:
			print("Access-Request");
			break;
		case CODE_ACCESS_CHALLENGE:
			print("Access-Challenge");
			break;
		case CODE_ACCESS_ACCEPT:
			print("Access-Accept");
			break;
		case CODE_ACCESS_REJECT:
			print("Access-Reject");
			break;
273
		case CODE_ACCOUNTING_REQUEST:
274
			print("Accounting-Request");
275 276
			break;
		case CODE_ACCOUNTING_RESPONSE:
277
			print("Accounting-Response");
278
			break;
279
		case CODE_DISCONNECT_REQUEST:
280
			print("Disconnect-Request");
281 282
			break;
		case CODE_DISCONNECT_ACK:
283
			print("Disconnect-ACK");
284 285
			break;
		case CODE_DISCONNECT_NAK:
286
			print("Disconnect-NAK");
287 288
			break;
		case CODE_COA_REQUEST:
289
			print("CoA-Request");
290 291
			break;
		case CODE_COA_ACK:
292
			print("CoA-ACK");
293 294
			break;
		case CODE_COA_NAK:
295
			print("CoA-NAK");
296
			break;
297 298 299 300 301 302
		default:
			print("Unknown (%i)", pack->code);
	}
	print(" id=%x", pack->id);

	list_for_each_entry(attr, &pack->attrs, entry) {
303 304 305 306
		if (attr->vendor)
			print("<%s %s ", attr->vendor->name, attr->attr->name);
		else
			print(" <%s ", attr->attr->name);
307 308 309 310 311
		switch (attr->attr->type) {
			case ATTR_TYPE_INTEGER:
				val = rad_dict_find_val(attr->attr, attr->val);
				if (val)
					print("%s", val->name);
312
				else
313
					print("%u", attr->val.integer);
314 315 316 317 318 319 320
				break;
			case ATTR_TYPE_STRING:
				print("\"%s\"", attr->val.string);
				break;
			case ATTR_TYPE_IPADDR:
				print("%i.%i.%i.%i", attr->val.ipaddr & 0xff, (attr->val.ipaddr >> 8) & 0xff, (attr->val.ipaddr >> 16) & 0xff, (attr->val.ipaddr >> 24) & 0xff);
				break;
321 322 323 324 325 326
		}
		print(">");
	}
	print("]\n");
}

K
Kozlov Dmitry 已提交
327
int __export rad_packet_add_int(struct rad_packet_t *pack, const char *vendor_name, const char *name, int val)
328 329 330
{
	struct rad_attr_t *ra;
	struct rad_dict_attr_t *attr;
K
Kozlov Dmitry 已提交
331
	struct rad_dict_vendor_t *vendor;
332

K
Kozlov Dmitry 已提交
333
	if (pack->len + (vendor_name ? 8 : 2) + 4 >= REQ_LENGTH_MAX)
334 335
		return -1;

K
Kozlov Dmitry 已提交
336 337 338 339 340 341 342 343 344 345
	if (vendor_name) {
		vendor = rad_dict_find_vendor_name(vendor_name);
		if (!vendor)
			return -1;
		attr = rad_dict_find_vendor_attr(vendor, name);
	} else {
		vendor = NULL;
		attr = rad_dict_find_attr(name);
	}

346 347 348
	if (!attr)
		return -1;
	
349
	ra = mempool_alloc(attr_pool);
350 351 352
	if (!ra)
		return -1;

353
	memset(ra, 0, sizeof(*ra));
K
Kozlov Dmitry 已提交
354
	ra->vendor = vendor;
355 356 357 358
	ra->attr = attr;
	ra->len = 4;
	ra->val.integer = val;
	list_add_tail(&ra->entry, &pack->attrs);
K
Kozlov Dmitry 已提交
359
	pack->len += (vendor_name ? 8 : 2) + 4;
360 361 362 363

	return 0;
}

K
Kozlov Dmitry 已提交
364
int __export rad_packet_change_int(struct rad_packet_t *pack, const char *vendor_name, const char *name, int val)
365 366 367
{
	struct rad_attr_t *ra;
	
K
Kozlov Dmitry 已提交
368
	ra = rad_packet_find_attr(pack, vendor_name, name);
369 370 371 372 373 374 375 376
	if (!ra)
		return -1;

	ra->val.integer = val;

	return 0;
}

K
Kozlov Dmitry 已提交
377
int __export rad_packet_add_octets(struct rad_packet_t *pack, const char *vendor_name, const char *name, const uint8_t *val, int len)
378 379 380
{
	struct rad_attr_t *ra;
	struct rad_dict_attr_t *attr;
K
Kozlov Dmitry 已提交
381
	struct rad_dict_vendor_t *vendor;
382

K
Kozlov Dmitry 已提交
383
	if (pack->len + (vendor_name ? 8 : 2) + len >= REQ_LENGTH_MAX)
384 385
		return -1;

K
Kozlov Dmitry 已提交
386 387 388 389 390 391 392 393 394 395
	if (vendor_name) {
		vendor = rad_dict_find_vendor_name(vendor_name);
		if (!vendor)
			return -1;
		attr = rad_dict_find_vendor_attr(vendor, name);
	} else {
		vendor = NULL;
		attr = rad_dict_find_attr(name);
	}
	
396 397 398
	if (!attr)
		return -1;
	
399
	ra = mempool_alloc(attr_pool);
400
	if (!ra) {
401
		log_emerg("radius: out of memory\n");
402 403 404
		return -1;
	}

405
	memset(ra, 0, sizeof(*ra));
K
Kozlov Dmitry 已提交
406
	ra->vendor = vendor;
407 408
	ra->attr = attr;
	ra->len = len;
D
Dmitry Kozlov 已提交
409
	ra->val.octets = _malloc(len);
410
	if (!ra->val.octets) {
411
		log_emerg("radius: out of memory\n");
D
Dmitry Kozlov 已提交
412
		_free(ra);
413 414 415 416
		return -1;
	}
	memcpy(ra->val.octets, val, len);
	list_add_tail(&ra->entry, &pack->attrs);
K
Kozlov Dmitry 已提交
417
	pack->len += (vendor_name ? 8 : 2) + len;
418 419 420

	return 0;
}
421

K
Kozlov Dmitry 已提交
422
int __export rad_packet_change_octets(struct rad_packet_t *pack, const char *vendor_name, const char *name, const uint8_t *val, int len)
423 424 425
{
	struct rad_attr_t *ra;
	
K
Kozlov Dmitry 已提交
426
	ra = rad_packet_find_attr(pack, vendor_name, name);
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449
	if (!ra)
		return -1;

	if (ra->len != len) {
		if (pack->len - ra->len + len >= REQ_LENGTH_MAX)
			return -1;

		ra->val.octets = _realloc(ra->val.octets, len);
		if (!ra->val.octets) {
			log_emerg("radius: out of memory\n");
			return -1;
		}
	
		pack->len += len - ra->len;
		ra->len = len;
	}

	memcpy(ra->val.octets, val, len);

	return 0;
}


K
Kozlov Dmitry 已提交
450
int __export rad_packet_add_str(struct rad_packet_t *pack, const char *vendor_name, const char *name, const char *val)
451 452 453
{
	struct rad_attr_t *ra;
	struct rad_dict_attr_t *attr;
K
Kozlov Dmitry 已提交
454 455
	struct rad_dict_vendor_t *vendor;
	int len = strlen(val);
456

K
Kozlov Dmitry 已提交
457
	if (pack->len + (vendor_name ? 8 : 2) + len >= REQ_LENGTH_MAX)
458 459
		return -1;

K
Kozlov Dmitry 已提交
460 461 462 463 464 465 466 467 468 469
	if (vendor_name) {
		vendor = rad_dict_find_vendor_name(vendor_name);
		if (!vendor)
			return -1;
		attr = rad_dict_find_vendor_attr(vendor, name);
	} else {
		vendor = NULL;
		attr = rad_dict_find_attr(name);
	}

470 471 472
	if (!attr)
		return -1;
	
473
	ra = mempool_alloc(attr_pool);
474
	if (!ra) {
475
		log_emerg("radius: out of memory\n");
476 477 478
		return -1;
	}

479
	memset(ra, 0, sizeof(*ra));
K
Kozlov Dmitry 已提交
480
	ra->vendor = vendor;
481 482
	ra->attr = attr;
	ra->len = len;
K
Kozlov Dmitry 已提交
483
	ra->val.string = _malloc(len + 1);
484
	if (!ra->val.string) {
485
		log_emerg("radius: out of memory\n");
D
Dmitry Kozlov 已提交
486
		_free(ra);
487 488 489 490 491
		return -1;
	}
	memcpy(ra->val.string, val, len);
	ra->val.string[len] = 0;
	list_add_tail(&ra->entry, &pack->attrs);
K
Kozlov Dmitry 已提交
492
	pack->len += (vendor_name ? 8 : 2) + len;
493 494 495 496

	return 0;
}

K
Kozlov Dmitry 已提交
497
int __export rad_packet_change_str(struct rad_packet_t *pack, const char *vendor_name, const char *name, const char *val, int len)
498 499 500
{
	struct rad_attr_t *ra;
	
K
Kozlov Dmitry 已提交
501
	ra = rad_packet_find_attr(pack, vendor_name, name);
502 503 504 505 506 507 508
	if (!ra)
		return -1;

	if (ra->len != len) {
		if (pack->len - ra->len + len >= REQ_LENGTH_MAX)
			return -1;

D
Dmitry Kozlov 已提交
509
		ra->val.string = _realloc(ra->val.string, len + 1);
510
		if (!ra->val.string) {
511
			log_emerg("radius: out of memory\n");
512 513 514 515 516 517 518 519 520 521 522 523 524
			return -1;
		}
	
		pack->len += len - ra->len;
		ra->len = len;
	}

	memcpy(ra->val.string, val, len);
	ra->val.string[len] = 0;

	return 0;
}

K
Kozlov Dmitry 已提交
525
int __export rad_packet_add_val(struct rad_packet_t *pack, const char *vendor_name, const char *name, const char *val)
526 527 528 529
{
	struct rad_attr_t *ra;
	struct rad_dict_attr_t *attr;
	struct rad_dict_value_t *v;
K
Kozlov Dmitry 已提交
530
	struct rad_dict_vendor_t *vendor;
531

K
Kozlov Dmitry 已提交
532
	if (pack->len + (vendor_name ? 8 : 2) + 4 >= REQ_LENGTH_MAX)
533 534
		return -1;

K
Kozlov Dmitry 已提交
535 536 537 538 539 540 541 542 543 544
	if (vendor_name) {
		vendor = rad_dict_find_vendor_name(vendor_name);
		if (!vendor)
			return -1;
		attr = rad_dict_find_vendor_attr(vendor, name);
	} else {
		vendor = NULL;
		attr = rad_dict_find_attr(name);
	}
	
545 546
	if (!attr)
		return -1;
K
Kozlov Dmitry 已提交
547

548 549 550 551
	v = rad_dict_find_val_name(attr, val);
	if (!v)
		return -1;
	
552
	ra = mempool_alloc(attr_pool);
553 554 555
	if (!ra)
		return -1;

556
	memset(ra, 0, sizeof(*ra));
K
Kozlov Dmitry 已提交
557
	ra->vendor = vendor;
558 559 560 561
	ra->attr = attr;
	ra->len = 4;
	ra->val = v->val;
	list_add_tail(&ra->entry, &pack->attrs);
K
Kozlov Dmitry 已提交
562
	pack->len += (vendor_name ? 8 : 2) + 4;
563 564 565 566

	return 0;
}

K
Kozlov Dmitry 已提交
567
int __export rad_packet_change_val(struct rad_packet_t *pack, const char *vendor_name, const char *name, const char *val)
568 569 570 571
{
	struct rad_attr_t *ra;
	struct rad_dict_value_t *v;
	
K
Kozlov Dmitry 已提交
572
	ra = rad_packet_find_attr(pack, vendor_name, name);
573 574 575 576 577 578 579 580 581 582 583 584
	if (!ra)
		return -1;

	v = rad_dict_find_val_name(ra->attr, val);
	if (!v)
		return -1;

	ra->val = v->val;
	
	return 0;
}

K
Kozlov Dmitry 已提交
585
int __export rad_packet_add_ipaddr(struct rad_packet_t *pack, const char *vendor_name, const char *name, in_addr_t ipaddr)
586
{
K
Kozlov Dmitry 已提交
587
	return rad_packet_add_int(pack, vendor_name, name, ipaddr);
588 589 590
}


K
Kozlov Dmitry 已提交
591
struct rad_attr_t __export *rad_packet_find_attr(struct rad_packet_t *pack, const char *vendor_name, const char *name)
592 593
{
	struct rad_attr_t *ra;
K
Kozlov Dmitry 已提交
594
	struct rad_dict_vendor_t *vendor;
595

K
Kozlov Dmitry 已提交
596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611
	if (vendor_name) {
		vendor = rad_dict_find_vendor_name(vendor_name);
		if (!vendor)
			return NULL;
	} else
		vendor = NULL;
	
	list_for_each_entry(ra, &pack->attrs, entry) {
		if (vendor && vendor != ra->vendor)
			continue;

		if (strcmp(ra->attr->name, name))
			continue;
		
		return ra;
	}
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627

	return NULL;
}

int rad_packet_send(struct rad_packet_t *pack, int fd, struct sockaddr_in *addr)
{
	int n;

	while (1) {
		if (addr)
			n = sendto(fd, pack->buf, pack->len, 0, addr, sizeof(*addr));
		else
			n = write(fd, pack->buf, pack->len);
		if (n < 0) {
			if (errno == EINTR)
				continue;
628
			log_ppp_error("radius:write: %s\n", strerror(errno));
629 630
			return -1;
		} else if (n != pack->len) {
631
			log_ppp_error("radius:write: short write %i, excpected %i\n", n, pack->len);
632 633 634 635 636 637 638 639
			return -1;
		}
		break;
	}

	return 0;
}

640 641 642 643 644
static void __init init(void)
{
	attr_pool = mempool_create(sizeof(struct rad_attr_t));
	packet_pool = mempool_create(sizeof(struct rad_packet_t));
}