00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "dhcpd.h"
00033
00034
00035
00036 struct iaddr subnet_number (addr, mask)
00037 struct iaddr addr;
00038 struct iaddr mask;
00039 {
00040 int i;
00041 struct iaddr rv;
00042
00043 if (addr.len > sizeof(addr.iabuf))
00044 log_fatal("subnet_number():%s:%d: Invalid addr length.", MDL);
00045 if (addr.len != mask.len)
00046 log_fatal("subnet_number():%s:%d: Addr/mask length mismatch.",
00047 MDL);
00048
00049 rv.len = 0;
00050
00051
00052 if (addr.len != mask.len)
00053 return rv;
00054
00055 rv.len = addr.len;
00056 for (i = 0; i < rv.len; i++)
00057 rv.iabuf [i] = addr.iabuf [i] & mask.iabuf [i];
00058 return rv;
00059 }
00060
00061
00062
00063
00064
00065 struct iaddr ip_addr (subnet, mask, host_address)
00066 struct iaddr subnet;
00067 struct iaddr mask;
00068 u_int32_t host_address;
00069 {
00070 int i, j, k;
00071 u_int32_t swaddr;
00072 struct iaddr rv;
00073 unsigned char habuf [sizeof swaddr];
00074
00075 if (subnet.len > sizeof(subnet.iabuf))
00076 log_fatal("ip_addr():%s:%d: Invalid addr length.", MDL);
00077 if (subnet.len != mask.len)
00078 log_fatal("ip_addr():%s:%d: Addr/mask length mismatch.",
00079 MDL);
00080
00081 swaddr = htonl (host_address);
00082 memcpy (habuf, &swaddr, sizeof swaddr);
00083
00084
00085
00086
00087 rv = subnet;
00088 j = rv.len - sizeof habuf;
00089 for (i = sizeof habuf - 1; i >= 0; i--) {
00090 if (mask.iabuf [i + j]) {
00091 if (habuf [i] > (mask.iabuf [i + j] ^ 0xFF)) {
00092 rv.len = 0;
00093 return rv;
00094 }
00095 for (k = i - 1; k >= 0; k--) {
00096 if (habuf [k]) {
00097 rv.len = 0;
00098 return rv;
00099 }
00100 }
00101 rv.iabuf [i + j] |= habuf [i];
00102 break;
00103 } else
00104 rv.iabuf [i + j] = habuf [i];
00105 }
00106
00107 return rv;
00108 }
00109
00110
00111
00112
00113
00114 struct iaddr broadcast_addr (subnet, mask)
00115 struct iaddr subnet;
00116 struct iaddr mask;
00117 {
00118 int i;
00119 struct iaddr rv;
00120
00121 if (subnet.len > sizeof(subnet.iabuf))
00122 log_fatal("broadcast_addr():%s:%d: Invalid addr length.", MDL);
00123 if (subnet.len != mask.len)
00124 log_fatal("broadcast_addr():%s:%d: Addr/mask length mismatch.",
00125 MDL);
00126
00127 if (subnet.len != mask.len) {
00128 rv.len = 0;
00129 return rv;
00130 }
00131
00132 for (i = 0; i < subnet.len; i++) {
00133 rv.iabuf [i] = subnet.iabuf [i] | (~mask.iabuf [i] & 255);
00134 }
00135 rv.len = subnet.len;
00136
00137 return rv;
00138 }
00139
00140 u_int32_t host_addr (addr, mask)
00141 struct iaddr addr;
00142 struct iaddr mask;
00143 {
00144 int i;
00145 u_int32_t swaddr;
00146 struct iaddr rv;
00147
00148 if (addr.len > sizeof(addr.iabuf))
00149 log_fatal("host_addr():%s:%d: Invalid addr length.", MDL);
00150 if (addr.len != mask.len)
00151 log_fatal("host_addr():%s:%d: Addr/mask length mismatch.",
00152 MDL);
00153
00154 rv.len = 0;
00155
00156
00157 rv.len = addr.len;
00158 for (i = 0; i < rv.len; i++)
00159 rv.iabuf [i] = addr.iabuf [i] & ~mask.iabuf [i];
00160
00161
00162 memcpy (&swaddr, &rv.iabuf [rv.len - sizeof swaddr], sizeof swaddr);
00163
00164
00165 return ntohl (swaddr);
00166 }
00167
00168 int addr_eq (addr1, addr2)
00169 struct iaddr addr1, addr2;
00170 {
00171 if (addr1.len > sizeof(addr1.iabuf))
00172 log_fatal("addr_eq():%s:%d: Invalid addr length.", MDL);
00173
00174 if (addr1.len != addr2.len)
00175 return 0;
00176 return memcmp (addr1.iabuf, addr2.iabuf, addr1.len) == 0;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185 int
00186 addr_match(addr, match)
00187 struct iaddr *addr;
00188 struct iaddrmatch *match;
00189 {
00190 int i;
00191
00192 if (addr->len != match->addr.len)
00193 return 0;
00194
00195 for (i = 0 ; i < addr->len ; i++) {
00196 if ((addr->iabuf[i] & match->mask.iabuf[i]) !=
00197 match->addr.iabuf[i])
00198 return 0;
00199 }
00200 return 1;
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 int
00213 addr_cmp(const struct iaddr *a1, const struct iaddr *a2) {
00214 int i;
00215
00216 if (a1->len != a2->len) {
00217 return 0;
00218 }
00219
00220 for (i=0; i<a1->len; i++) {
00221 if (a1->iabuf[i] < a2->iabuf[i]) {
00222 return -1;
00223 }
00224 if (a1->iabuf[i] > a2->iabuf[i]) {
00225 return 1;
00226 }
00227 }
00228
00229 return 0;
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239 int
00240 addr_or(struct iaddr *result, const struct iaddr *a1, const struct iaddr *a2) {
00241 int i;
00242 int all_zero;
00243
00244 if (a1->len != a2->len) {
00245 return 0;
00246 }
00247
00248 all_zero = 1;
00249
00250 result->len = a1->len;
00251 for (i=0; i<a1->len; i++) {
00252 result->iabuf[i] = a1->iabuf[i] | a2->iabuf[i];
00253 if (result->iabuf[i] != 0) {
00254 all_zero = 0;
00255 }
00256 }
00257
00258 return !all_zero;
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268 int
00269 addr_and(struct iaddr *result, const struct iaddr *a1, const struct iaddr *a2) {
00270 int i;
00271 int all_zero;
00272
00273 if (a1->len != a2->len) {
00274 return 0;
00275 }
00276
00277 all_zero = 1;
00278
00279 result->len = a1->len;
00280 for (i=0; i<a1->len; i++) {
00281 result->iabuf[i] = a1->iabuf[i] & a2->iabuf[i];
00282 if (result->iabuf[i] != 0) {
00283 all_zero = 0;
00284 }
00285 }
00286
00287 return !all_zero;
00288 }
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 isc_boolean_t
00305 is_cidr_mask_valid(const struct iaddr *addr, int bits) {
00306 int zero_bits;
00307 int zero_bytes;
00308 int i;
00309 char byte;
00310 int shift_bits;
00311
00312
00313
00314
00315 if (bits < 0) {
00316 return ISC_FALSE;
00317 }
00318 if (bits > (addr->len * 8)) {
00319 return ISC_FALSE;
00320 }
00321
00322
00323
00324
00325 zero_bits = (addr->len * 8) - bits;
00326 zero_bytes = zero_bits / 8;
00327
00328
00329
00330
00331 for (i=1; i<=zero_bytes; i++) {
00332 if (addr->iabuf[addr->len-i] != 0) {
00333 return ISC_FALSE;
00334 }
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344 shift_bits = zero_bits % 8;
00345 if (shift_bits == 0) return ISC_TRUE;
00346 byte = addr->iabuf[addr->len-zero_bytes-1];
00347 return (((byte >> shift_bits) << shift_bits) == byte);
00348 }
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 isc_result_t
00362 range2cidr(struct iaddrcidrnetlist **result,
00363 const struct iaddr *lo, const struct iaddr *hi) {
00364 struct iaddr addr;
00365 struct iaddr mask;
00366 int bit;
00367 struct iaddr end_addr;
00368 struct iaddr dummy;
00369 int ofs, val;
00370 struct iaddrcidrnetlist *net;
00371 int tmp;
00372
00373 if (result == NULL) {
00374 return DHCP_R_INVALIDARG;
00375 }
00376 if (*result != NULL) {
00377 return DHCP_R_INVALIDARG;
00378 }
00379 if ((lo == NULL) || (hi == NULL) || (lo->len != hi->len)) {
00380 return DHCP_R_INVALIDARG;
00381 }
00382
00383
00384
00385
00386 if (addr_cmp(lo, hi) > 0) {
00387 const struct iaddr *tmp;
00388 tmp = lo;
00389 lo = hi;
00390 hi = tmp;
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426 addr = *lo;
00427 bit = 0;
00428 memset(&mask, 0, sizeof(mask));
00429 mask.len = addr.len;
00430 while (addr_cmp(&addr, hi) <= 0) {
00431
00432
00433
00434 ofs = addr.len - (bit / 8) - 1;
00435 val = 1 << (bit % 8);
00436 if (ofs >= 0) {
00437 mask.iabuf[ofs] |= val;
00438 }
00439
00440
00441
00442
00443 addr_or(&end_addr, &addr, &mask);
00444 if ((ofs < 0) ||
00445 (addr_cmp(&end_addr, hi) > 0) ||
00446 addr_and(&dummy, &addr, &mask)) {
00447
00448
00449
00450 net = dmalloc(sizeof(*net), MDL);
00451 if (net == NULL) {
00452 while (*result != NULL) {
00453 net = (*result)->next;
00454 dfree(*result, MDL);
00455 *result = net;
00456 }
00457 return ISC_R_NOMEMORY;
00458 }
00459 net->cidrnet.lo_addr = addr;
00460 net->cidrnet.bits = (addr.len * 8) - bit;
00461 net->next = *result;
00462 *result = net;
00463
00464
00465
00466
00467
00468
00469 tmp = addr.iabuf[ofs] + val;
00470 while ((ofs >= 0) && (tmp > 255)) {
00471 addr.iabuf[ofs] = tmp - 256;
00472 ofs--;
00473 tmp = addr.iabuf[ofs] + 1;
00474 }
00475 if (ofs < 0) {
00476
00477 break;
00478 }
00479 addr.iabuf[ofs] = tmp;
00480
00481
00482
00483
00484 bit = 0;
00485 memset(mask.iabuf, 0, sizeof(mask.iabuf));
00486 memset(end_addr.iabuf, 0, sizeof(end_addr.iabuf));
00487 } else {
00488
00489
00490
00491 bit++;
00492 }
00493 }
00494
00495
00496
00497
00498 return ISC_R_SUCCESS;
00499 }
00500
00501
00502
00503
00504 isc_result_t
00505 free_iaddrcidrnetlist(struct iaddrcidrnetlist **result) {
00506 struct iaddrcidrnetlist *p;
00507
00508 if (result == NULL) {
00509 return DHCP_R_INVALIDARG;
00510 }
00511 if (*result == NULL) {
00512 return DHCP_R_INVALIDARG;
00513 }
00514
00515 while (*result != NULL) {
00516 p = *result;
00517 *result = p->next;
00518 dfree(p, MDL);
00519 }
00520
00521 return ISC_R_SUCCESS;
00522 }
00523
00524 static const char *
00525 inet_ntopdd(const unsigned char *src, unsigned srclen, char *dst, size_t size)
00526 {
00527 char tmp[sizeof("32.255.255.255.255")];
00528 int len;
00529
00530 switch (srclen) {
00531 case 2:
00532 len = sprintf (tmp, "%u.%u", src[0], src[1]);
00533 break;
00534 case 3:
00535 len = sprintf (tmp, "%u.%u.%u", src[0], src[1], src[2]);
00536 break;
00537 case 4:
00538 len = sprintf (tmp, "%u.%u.%u.%u", src[0], src[1], src[2], src[3]);
00539 break;
00540 case 5:
00541 len = sprintf (tmp, "%u.%u.%u.%u.%u", src[0], src[1], src[2], src[3], src[4]);
00542 break;
00543 default:
00544 return NULL;
00545 }
00546 if (len < 0)
00547 return NULL;
00548
00549 if (len > size) {
00550 errno = ENOSPC;
00551 return NULL;
00552 }
00553
00554 return strcpy (dst, tmp);
00555 }
00556
00557
00558 const char *
00559 pdestdesc(const struct iaddr addr) {
00560 static char pbuf[sizeof("255.255.255.255.255")];
00561
00562 if (addr.len == 0) {
00563 return "<null destination descriptor>";
00564 }
00565 if (addr.len == 1) {
00566 return "0";
00567 }
00568 if ((addr.len >= 2) && (addr.len <= 5)) {
00569 return inet_ntopdd(addr.iabuf, addr.len, pbuf, sizeof(pbuf));
00570 }
00571
00572 log_fatal("pdestdesc():%s:%d: Invalid destination descriptor length %d.",
00573 MDL, addr.len);
00574
00575 return NULL;
00576 }
00577
00578
00579
00580 const char *
00581 piaddr(const struct iaddr addr) {
00582 static char
00583 pbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
00584
00585
00586
00587
00588 if (addr.len == 0) {
00589 return "<null address>";
00590 }
00591 if (addr.len == 4) {
00592 return inet_ntop(AF_INET, addr.iabuf, pbuf, sizeof(pbuf));
00593 }
00594 if (addr.len == 16) {
00595 return inet_ntop(AF_INET6, addr.iabuf, pbuf, sizeof(pbuf));
00596 }
00597
00598 log_fatal("piaddr():%s:%d: Invalid address length %d.", MDL,
00599 addr.len);
00600
00601 return NULL;
00602 }
00603
00604
00605
00606
00607 char *
00608 piaddrmask(struct iaddr *addr, struct iaddr *mask) {
00609 int mw;
00610 unsigned int oct, bit;
00611
00612 if ((addr->len != 4) && (addr->len != 16))
00613 log_fatal("piaddrmask():%s:%d: Address length %d invalid",
00614 MDL, addr->len);
00615 if (addr->len != mask->len)
00616 log_fatal("piaddrmask():%s:%d: Address and mask size mismatch",
00617 MDL);
00618
00619
00620 for (mw = (mask->len * 8) ; mw > 0 ; ) {
00621 oct = (mw - 1) / 8;
00622 bit = 0x80 >> ((mw - 1) % 8);
00623 if (!mask->iabuf[oct])
00624 mw -= 8;
00625 else if (mask->iabuf[oct] & bit)
00626 break;
00627 else
00628 mw--;
00629 }
00630
00631 if (mw < 0)
00632 log_fatal("Impossible condition at %s:%d.", MDL);
00633
00634 return piaddrcidr(addr, mw);
00635 }
00636
00637
00638 char *
00639 piaddrcidr(const struct iaddr *addr, unsigned int bits) {
00640 static char
00641 ret[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128")];
00642
00643
00644
00645
00646
00647
00648 if (bits > (addr->len * 8))
00649 return NULL;
00650
00651 sprintf(ret, "%s/%d", piaddr(*addr), bits);
00652
00653 return ret;
00654 }
00655
00656
00657
00658
00659
00660 u_int16_t
00661 validate_port(char *port) {
00662 long local_port = 0;
00663 long lower = 1;
00664 long upper = 65535;
00665 char *endptr;
00666
00667 errno = 0;
00668 local_port = strtol(port, &endptr, 10);
00669
00670 if ((*endptr != '\0') || (errno == ERANGE) || (errno == EINVAL))
00671 log_fatal ("Invalid port number specification: %s", port);
00672
00673 if (local_port < lower || local_port > upper)
00674 log_fatal("Port number specified is out of range (%ld-%ld).",
00675 lower, upper);
00676
00677 return htons((u_int16_t)local_port);
00678 }