ISC DHCP  4.3.1
A reference DHCPv4 and DHCPv6 implementation
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
inet.c
Go to the documentation of this file.
1 /* inet.c
2 
3  Subroutines to manipulate internet addresses and ports in a safely portable
4  way... */
5 
6 /*
7  * Copyright (c) 2011,2013,2014 by Internet Systems Consortium, Inc. ("ISC")
8  * Copyright (c) 2007-2009 by Internet Systems Consortium, Inc. ("ISC")
9  * Copyright (c) 2004,2005 by Internet Systems Consortium, Inc. ("ISC")
10  * Copyright (c) 1995-2003 by Internet Software Consortium
11  *
12  * Permission to use, copy, modify, and distribute this software for any
13  * purpose with or without fee is hereby granted, provided that the above
14  * copyright notice and this permission notice appear in all copies.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
17  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
19  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
21  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
22  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23  *
24  * Internet Systems Consortium, Inc.
25  * 950 Charter Street
26  * Redwood City, CA 94063
27  * <info@isc.org>
28  * https://www.isc.org/
29  *
30  */
31 
32 #include "dhcpd.h"
33 
34 /* Return just the network number of an internet address... */
35 
36 struct iaddr subnet_number (addr, mask)
37  struct iaddr addr;
38  struct iaddr mask;
39 {
40  int i;
41  struct iaddr rv;
42 
43  if (addr.len > sizeof(addr.iabuf))
44  log_fatal("subnet_number():%s:%d: Invalid addr length.", MDL);
45  if (addr.len != mask.len)
46  log_fatal("subnet_number():%s:%d: Addr/mask length mismatch.",
47  MDL);
48 
49  rv.len = 0;
50 
51  /* Both addresses must have the same length... */
52  if (addr.len != mask.len)
53  return rv;
54 
55  rv.len = addr.len;
56  for (i = 0; i < rv.len; i++)
57  rv.iabuf [i] = addr.iabuf [i] & mask.iabuf [i];
58  return rv;
59 }
60 
61 /* Combine a network number and a integer to produce an internet address.
62  This won't work for subnets with more than 32 bits of host address, but
63  maybe this isn't a problem. */
64 
65 struct iaddr ip_addr (subnet, mask, host_address)
66  struct iaddr subnet;
67  struct iaddr mask;
68  u_int32_t host_address;
69 {
70  int i, j, k;
71  u_int32_t swaddr;
72  struct iaddr rv;
73  unsigned char habuf [sizeof swaddr];
74 
75  if (subnet.len > sizeof(subnet.iabuf))
76  log_fatal("ip_addr():%s:%d: Invalid addr length.", MDL);
77  if (subnet.len != mask.len)
78  log_fatal("ip_addr():%s:%d: Addr/mask length mismatch.",
79  MDL);
80 
81  swaddr = htonl (host_address);
82  memcpy (habuf, &swaddr, sizeof swaddr);
83 
84  /* Combine the subnet address and the host address. If
85  the host address is bigger than can fit in the subnet,
86  return a zero-length iaddr structure. */
87  rv = subnet;
88  j = rv.len - sizeof habuf;
89  for (i = sizeof habuf - 1; i >= 0; i--) {
90  if (mask.iabuf [i + j]) {
91  if (habuf [i] > (mask.iabuf [i + j] ^ 0xFF)) {
92  rv.len = 0;
93  return rv;
94  }
95  for (k = i - 1; k >= 0; k--) {
96  if (habuf [k]) {
97  rv.len = 0;
98  return rv;
99  }
100  }
101  rv.iabuf [i + j] |= habuf [i];
102  break;
103  } else
104  rv.iabuf [i + j] = habuf [i];
105  }
106 
107  return rv;
108 }
109 
110 /* Given a subnet number and netmask, return the address on that subnet
111  for which the host portion of the address is all ones (the standard
112  broadcast address). */
113 
115  struct iaddr subnet;
116  struct iaddr mask;
117 {
118  int i;
119  struct iaddr rv;
120 
121  if (subnet.len > sizeof(subnet.iabuf))
122  log_fatal("broadcast_addr():%s:%d: Invalid addr length.", MDL);
123  if (subnet.len != mask.len)
124  log_fatal("broadcast_addr():%s:%d: Addr/mask length mismatch.",
125  MDL);
126 
127  if (subnet.len != mask.len) {
128  rv.len = 0;
129  return rv;
130  }
131 
132  for (i = 0; i < subnet.len; i++) {
133  rv.iabuf [i] = subnet.iabuf [i] | (~mask.iabuf [i] & 255);
134  }
135  rv.len = subnet.len;
136 
137  return rv;
138 }
139 
140 u_int32_t host_addr (addr, mask)
141  struct iaddr addr;
142  struct iaddr mask;
143 {
144  int i;
145  u_int32_t swaddr;
146  struct iaddr rv;
147 
148  if (addr.len > sizeof(addr.iabuf))
149  log_fatal("host_addr():%s:%d: Invalid addr length.", MDL);
150  if (addr.len != mask.len)
151  log_fatal("host_addr():%s:%d: Addr/mask length mismatch.",
152  MDL);
153 
154  rv.len = 0;
155 
156  /* Mask out the network bits... */
157  rv.len = addr.len;
158  for (i = 0; i < rv.len; i++)
159  rv.iabuf [i] = addr.iabuf [i] & ~mask.iabuf [i];
160 
161  /* Copy out up to 32 bits... */
162  memcpy (&swaddr, &rv.iabuf [rv.len - sizeof swaddr], sizeof swaddr);
163 
164  /* Swap it and return it. */
165  return ntohl (swaddr);
166 }
167 
168 int addr_eq (addr1, addr2)
169  struct iaddr addr1, addr2;
170 {
171  if (addr1.len > sizeof(addr1.iabuf))
172  log_fatal("addr_eq():%s:%d: Invalid addr length.", MDL);
173 
174  if (addr1.len != addr2.len)
175  return 0;
176  return memcmp (addr1.iabuf, addr2.iabuf, addr1.len) == 0;
177 }
178 
179 /* addr_match
180  *
181  * compares an IP address against a network/mask combination
182  * by ANDing the IP with the mask and seeing whether the result
183  * matches the masked network value.
184  */
185 int
186 addr_match(addr, match)
187  struct iaddr *addr;
188  struct iaddrmatch *match;
189 {
190  int i;
191 
192  if (addr->len != match->addr.len)
193  return 0;
194 
195  for (i = 0 ; i < addr->len ; i++) {
196  if ((addr->iabuf[i] & match->mask.iabuf[i]) !=
197  match->addr.iabuf[i])
198  return 0;
199  }
200  return 1;
201 }
202 
203 /*
204  * Compares the addresses a1 and a2.
205  *
206  * If a1 < a2, returns -1.
207  * If a1 == a2, returns 0.
208  * If a1 > a2, returns 1.
209  *
210  * WARNING: if a1 and a2 differ in length, returns 0.
211  */
212 int
213 addr_cmp(const struct iaddr *a1, const struct iaddr *a2) {
214  int i;
215 
216  if (a1->len != a2->len) {
217  return 0;
218  }
219 
220  for (i=0; i<a1->len; i++) {
221  if (a1->iabuf[i] < a2->iabuf[i]) {
222  return -1;
223  }
224  if (a1->iabuf[i] > a2->iabuf[i]) {
225  return 1;
226  }
227  }
228 
229  return 0;
230 }
231 
232 /*
233  * Performs a bitwise-OR of two addresses.
234  *
235  * Returns 1 if the result is non-zero, or 0 otherwise.
236  *
237  * WARNING: if a1 and a2 differ in length, returns 0.
238  */
239 int
240 addr_or(struct iaddr *result, const struct iaddr *a1, const struct iaddr *a2) {
241  int i;
242  int all_zero;
243 
244  if (a1->len != a2->len) {
245  return 0;
246  }
247 
248  all_zero = 1;
249 
250  result->len = a1->len;
251  for (i=0; i<a1->len; i++) {
252  result->iabuf[i] = a1->iabuf[i] | a2->iabuf[i];
253  if (result->iabuf[i] != 0) {
254  all_zero = 0;
255  }
256  }
257 
258  return !all_zero;
259 }
260 
261 /*
262  * Performs a bitwise-AND of two addresses.
263  *
264  * Returns 1 if the result is non-zero, or 0 otherwise.
265  *
266  * WARNING: if a1 and a2 differ in length, returns 0.
267  */
268 int
269 addr_and(struct iaddr *result, const struct iaddr *a1, const struct iaddr *a2) {
270  int i;
271  int all_zero;
272 
273  if (a1->len != a2->len) {
274  return 0;
275  }
276 
277  all_zero = 1;
278 
279  result->len = a1->len;
280  for (i=0; i<a1->len; i++) {
281  result->iabuf[i] = a1->iabuf[i] & a2->iabuf[i];
282  if (result->iabuf[i] != 0) {
283  all_zero = 0;
284  }
285  }
286 
287  return !all_zero;
288 }
289 
290 /*
291  * Check if a bitmask of the given length is valid for the address.
292  * This is not the case if any bits longer than the bitmask are 1.
293  *
294  * So, this is valid:
295  *
296  * 127.0.0.0/8
297  *
298  * But this is not:
299  *
300  * 127.0.0.1/8
301  *
302  * Because the final ".1" would get masked out by the /8.
303  */
304 isc_boolean_t
305 is_cidr_mask_valid(const struct iaddr *addr, int bits) {
306  int zero_bits;
307  int zero_bytes;
308  int i;
309  char byte;
310  int shift_bits;
311 
312  /*
313  * Check our bit boundaries.
314  */
315  if (bits < 0) {
316  return ISC_FALSE;
317  }
318  if (bits > (addr->len * 8)) {
319  return ISC_FALSE;
320  }
321 
322  /*
323  * Figure out how many low-order bits need to be zero.
324  */
325  zero_bits = (addr->len * 8) - bits;
326  zero_bytes = zero_bits / 8;
327 
328  /*
329  * Check to make sure the low-order bytes are zero.
330  */
331  for (i=1; i<=zero_bytes; i++) {
332  if (addr->iabuf[addr->len-i] != 0) {
333  return ISC_FALSE;
334  }
335  }
336 
337  /*
338  * Look to see if any bits not in right-hand bytes are
339  * non-zero, by making a byte that has these bits set to zero
340  * comparing to the original byte. If these two values are
341  * equal, then the right-hand bits are zero, and we are
342  * happy.
343  */
344  shift_bits = zero_bits % 8;
345  if (shift_bits == 0) return ISC_TRUE;
346  byte = addr->iabuf[addr->len-zero_bytes-1];
347  return (((byte >> shift_bits) << shift_bits) == byte);
348 }
349 
350 /*
351  * range2cidr
352  *
353  * Converts a range of IP addresses to a set of CIDR networks.
354  *
355  * Examples:
356  * 192.168.0.0 - 192.168.0.255 = 192.168.0.0/24
357  * 10.0.0.0 - 10.0.1.127 = 10.0.0.0/24, 10.0.1.0/25
358  * 255.255.255.32 - 255.255.255.255 = 255.255.255.32/27, 255.255.255.64/26,
359  * 255.255.255.128/25
360  */
361 isc_result_t
362 range2cidr(struct iaddrcidrnetlist **result,
363  const struct iaddr *lo, const struct iaddr *hi) {
364  struct iaddr addr;
365  struct iaddr mask;
366  int bit;
367  struct iaddr end_addr;
368  struct iaddr dummy;
369  int ofs, val;
370  struct iaddrcidrnetlist *net;
371  int tmp;
372 
373  if (result == NULL) {
374  return DHCP_R_INVALIDARG;
375  }
376  if (*result != NULL) {
377  return DHCP_R_INVALIDARG;
378  }
379  if ((lo == NULL) || (hi == NULL) || (lo->len != hi->len)) {
380  return DHCP_R_INVALIDARG;
381  }
382 
383  /*
384  * Put our start and end in the right order, if reversed.
385  */
386  if (addr_cmp(lo, hi) > 0) {
387  const struct iaddr *tmp;
388  tmp = lo;
389  lo = hi;
390  hi = tmp;
391  }
392 
393  /*
394  * Theory of operation:
395  *
396  * -------------------
397  * Start at the low end, and keep trying larger networks
398  * until we get one that is too big (explained below).
399  *
400  * We keep a "mask", which is the ones-complement of a
401  * normal netmask. So, a /23 has a netmask of 255.255.254.0,
402  * and a mask of 0.0.1.255.
403  *
404  * We know when a network is too big when we bitwise-AND the
405  * mask with the starting address and we get a non-zero
406  * result, like this:
407  *
408  * addr: 192.168.1.0, mask: 0.0.1.255
409  * bitwise-AND: 0.0.1.0
410  *
411  * A network is also too big if the bitwise-OR of the mask
412  * with the starting address is larger than the end address,
413  * like this:
414  *
415  * start: 192.168.1.0, mask: 0.0.1.255, end: 192.168.0.255
416  * bitwise-OR: 192.168.1.255
417  *
418  * -------------------
419  * Once we have found a network that is too big, we add the
420  * appropriate CIDR network to our list of found networks.
421  *
422  * We then use the next IP address as our low address, and
423  * begin the process of searching for a network that is
424  * too big again, starting with an empty mask.
425  */
426  addr = *lo;
427  bit = 0;
428  memset(&mask, 0, sizeof(mask));
429  mask.len = addr.len;
430  while (addr_cmp(&addr, hi) <= 0) {
431  /*
432  * Bitwise-OR mask with (1 << bit)
433  */
434  ofs = addr.len - (bit / 8) - 1;
435  val = 1 << (bit % 8);
436  if (ofs >= 0) {
437  mask.iabuf[ofs] |= val;
438  }
439 
440  /*
441  * See if we're too big, and save this network if so.
442  */
443  addr_or(&end_addr, &addr, &mask);
444  if ((ofs < 0) ||
445  (addr_cmp(&end_addr, hi) > 0) ||
446  addr_and(&dummy, &addr, &mask)) {
447  /*
448  * Add a new prefix to our list.
449  */
450  net = dmalloc(sizeof(*net), MDL);
451  if (net == NULL) {
452  while (*result != NULL) {
453  net = (*result)->next;
454  dfree(*result, MDL);
455  *result = net;
456  }
457  return ISC_R_NOMEMORY;
458  }
459  net->cidrnet.lo_addr = addr;
460  net->cidrnet.bits = (addr.len * 8) - bit;
461  net->next = *result;
462  *result = net;
463 
464  /*
465  * Figure out our new starting address,
466  * by adding (1 << bit) to our previous
467  * starting address.
468  */
469  tmp = addr.iabuf[ofs] + val;
470  while ((ofs >= 0) && (tmp > 255)) {
471  addr.iabuf[ofs] = tmp - 256;
472  ofs--;
473  tmp = addr.iabuf[ofs] + 1;
474  }
475  if (ofs < 0) {
476  /* Gone past last address, we're done. */
477  break;
478  }
479  addr.iabuf[ofs] = tmp;
480 
481  /*
482  * Reset our bit and mask.
483  */
484  bit = 0;
485  memset(mask.iabuf, 0, sizeof(mask.iabuf));
486  memset(end_addr.iabuf, 0, sizeof(end_addr.iabuf));
487  } else {
488  /*
489  * If we're not too big, increase our network size.
490  */
491  bit++;
492  }
493  }
494 
495  /*
496  * We're done.
497  */
498  return ISC_R_SUCCESS;
499 }
500 
501 /*
502  * Free a list of CIDR networks, such as returned from range2cidr().
503  */
504 isc_result_t
506  struct iaddrcidrnetlist *p;
507 
508  if (result == NULL) {
509  return DHCP_R_INVALIDARG;
510  }
511  if (*result == NULL) {
512  return DHCP_R_INVALIDARG;
513  }
514 
515  while (*result != NULL) {
516  p = *result;
517  *result = p->next;
518  dfree(p, MDL);
519  }
520 
521  return ISC_R_SUCCESS;
522 }
523 
524 static const char *
525 inet_ntopdd(const unsigned char *src, unsigned srclen, char *dst, size_t size)
526 {
527  char tmp[sizeof("32.255.255.255.255")];
528  int len;
529 
530  switch (srclen) {
531  case 2:
532  len = sprintf (tmp, "%u.%u", src[0], src[1]);
533  break;
534  case 3:
535  len = sprintf (tmp, "%u.%u.%u", src[0], src[1], src[2]);
536  break;
537  case 4:
538  len = sprintf (tmp, "%u.%u.%u.%u", src[0], src[1], src[2], src[3]);
539  break;
540  case 5:
541  len = sprintf (tmp, "%u.%u.%u.%u.%u", src[0], src[1], src[2], src[3], src[4]);
542  break;
543  default:
544  return NULL;
545  }
546  if (len < 0)
547  return NULL;
548 
549  if (len > size) {
550  errno = ENOSPC;
551  return NULL;
552  }
553 
554  return strcpy (dst, tmp);
555 }
556 
557 /* pdestdesc() turns an iaddr structure into a printable dest. descriptor */
558 const char *
559 pdestdesc(const struct iaddr addr) {
560  static char pbuf[sizeof("255.255.255.255.255")];
561 
562  if (addr.len == 0) {
563  return "<null destination descriptor>";
564  }
565  if (addr.len == 1) {
566  return "0";
567  }
568  if ((addr.len >= 2) && (addr.len <= 5)) {
569  return inet_ntopdd(addr.iabuf, addr.len, pbuf, sizeof(pbuf));
570  }
571 
572  log_fatal("pdestdesc():%s:%d: Invalid destination descriptor length %d.",
573  MDL, addr.len);
574  /* quell compiler warnings */
575  return NULL;
576 }
577 
578 /* piaddr() turns an iaddr structure into a printable address. */
579 /* XXX: should use a const pointer rather than passing the structure */
580 const char *
581 piaddr(const struct iaddr addr) {
582  static char
583  pbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
584  /* "255.255.255.255" */
585 
586  /* INSIST((addr.len == 0) || (addr.len == 4) || (addr.len == 16)); */
587 
588  if (addr.len == 0) {
589  return "<null address>";
590  }
591  if (addr.len == 4) {
592  return inet_ntop(AF_INET, addr.iabuf, pbuf, sizeof(pbuf));
593  }
594  if (addr.len == 16) {
595  return inet_ntop(AF_INET6, addr.iabuf, pbuf, sizeof(pbuf));
596  }
597 
598  log_fatal("piaddr():%s:%d: Invalid address length %d.", MDL,
599  addr.len);
600  /* quell compiler warnings */
601  return NULL;
602 }
603 
604 /* piaddrmask takes an iaddr structure mask, determines the bitlength of
605  * the mask, and then returns the printable CIDR notation of the two.
606  */
607 char *
608 piaddrmask(struct iaddr *addr, struct iaddr *mask) {
609  int mw;
610  unsigned int oct, bit;
611 
612  if ((addr->len != 4) && (addr->len != 16))
613  log_fatal("piaddrmask():%s:%d: Address length %d invalid",
614  MDL, addr->len);
615  if (addr->len != mask->len)
616  log_fatal("piaddrmask():%s:%d: Address and mask size mismatch",
617  MDL);
618 
619  /* Determine netmask width in bits. */
620  for (mw = (mask->len * 8) ; mw > 0 ; ) {
621  oct = (mw - 1) / 8;
622  bit = 0x80 >> ((mw - 1) % 8);
623  if (!mask->iabuf[oct])
624  mw -= 8;
625  else if (mask->iabuf[oct] & bit)
626  break;
627  else
628  mw--;
629  }
630 
631  if (mw < 0)
632  log_fatal("Impossible condition at %s:%d.", MDL);
633 
634  return piaddrcidr(addr, mw);
635 }
636 
637 /* Format an address and mask-length into printable CIDR notation. */
638 char *
639 piaddrcidr(const struct iaddr *addr, unsigned int bits) {
640  static char
641  ret[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128")];
642  /* "255.255.255.255/32" */
643 
644  /* INSIST(addr != NULL); */
645  /* INSIST((addr->len == 4) || (addr->len == 16)); */
646  /* INSIST(bits <= (addr->len * 8)); */
647 
648  if (bits > (addr->len * 8))
649  return NULL;
650 
651  sprintf(ret, "%s/%d", piaddr(*addr), bits);
652 
653  return ret;
654 }
655 
656 /* Validate that the string represents a valid port number and
657  * return it in network byte order
658  */
659 
660 u_int16_t
661 validate_port(char *port) {
662  long local_port = 0;
663  long lower = 1;
664  long upper = 65535;
665  char *endptr;
666 
667  errno = 0;
668  local_port = strtol(port, &endptr, 10);
669 
670  if ((*endptr != '\0') || (errno == ERANGE) || (errno == EINVAL))
671  log_fatal ("Invalid port number specification: %s", port);
672 
673  if (local_port < lower || local_port > upper)
674  log_fatal("Port number specified is out of range (%ld-%ld).",
675  lower, upper);
676 
677  return htons((u_int16_t)local_port);
678 }
struct iaddrcidrnet cidrnet
Definition: inet.h:77
int addr_or(struct iaddr *result, const struct iaddr *a1, const struct iaddr *a2)
Definition: inet.c:240
int bits
Definition: inet.h:72
const char * piaddr(const struct iaddr addr)
Definition: inet.c:581
void * dmalloc(unsigned, const char *, int)
Definition: alloc.c:56
char * piaddrmask(struct iaddr *addr, struct iaddr *mask)
Definition: inet.c:608
Definition: dhcpd.h:952
int addr_cmp(const struct iaddr *a1, const struct iaddr *a2)
Definition: inet.c:213
struct iaddr ip_addr(struct iaddr subnet, struct iaddr mask, u_int32_t host_address)
Definition: inet.c:65
#define MDL
Definition: omapip.h:568
unsigned char iabuf[16]
Definition: inet.h:33
#define DHCP_R_INVALIDARG
Definition: result.h:48
unsigned len
Definition: inet.h:32
const char * pdestdesc(const struct iaddr addr)
Definition: inet.c:559
void log_fatal(const char *,...) __attribute__((__format__(__printf__
struct iaddr subnet_number(struct iaddr addr, struct iaddr mask)
Definition: inet.c:36
u_int16_t validate_port(char *port)
Definition: inet.c:661
u_int16_t local_port
Definition: dhclient.c:88
struct iaddrcidrnetlist * next
Definition: inet.h:76
isc_result_t free_iaddrcidrnetlist(struct iaddrcidrnetlist **result)
Definition: inet.c:505
void dfree(void *, const char *, int)
Definition: alloc.c:131
int addr_eq(struct iaddr addr1, struct iaddr addr2)
Definition: inet.c:168
struct iaddr broadcast_addr(struct iaddr subnet, struct iaddr mask)
Definition: inet.c:114
Definition: inet.h:31
u_int32_t host_addr(struct iaddr addr, struct iaddr mask)
Definition: inet.c:140
isc_boolean_t is_cidr_mask_valid(const struct iaddr *addr, int bits)
Definition: inet.c:305
int addr_match(struct iaddr *addr, struct iaddrmatch *match)
Definition: inet.c:186
struct iaddr addr
Definition: inet.h:54
struct iaddr lo_addr
Definition: inet.h:71
struct iaddr mask
Definition: inet.h:55
char * piaddrcidr(const struct iaddr *addr, unsigned int bits)
Definition: inet.c:639
isc_result_t range2cidr(struct iaddrcidrnetlist **result, const struct iaddr *lo, const struct iaddr *hi)
Definition: inet.c:362
int addr_and(struct iaddr *result, const struct iaddr *a1, const struct iaddr *a2)
Definition: inet.c:269