2 * misc.c Various miscellaneous functions.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2000 The FreeRADIUS server project
23 static const char rcsid[] =
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
42 #include "libradius.h"
50 * Return a printable host name (or IP address in dot notation)
51 * for the supplied IP address.
53 char * ip_hostname(char *buf, size_t buflen, uint32_t ipaddr)
56 #ifdef GETHOSTBYADDRRSTYLE
57 #if (GETHOSTBYADDRRSTYLE == SYSVSTYLE) || (GETHOSTBYADDRRSTYLE == GNUSTYLE)
59 struct hostent result;
65 * No DNS: don't look up host names
67 if (librad_dodns == 0) {
72 #ifdef GETHOSTBYADDRRSTYLE
73 #if GETHOSTBYADDRRSTYLE == SYSVSTYLE
74 hp = gethostbyaddr_r((char *)&ipaddr, sizeof(struct in_addr), AF_INET, &result, buffer, sizeof(buffer), &error);
75 #elif GETHOSTBYADDRRSTYLE == GNUSTYLE
76 if (gethostbyaddr_r((char *)&ipaddr, sizeof(struct in_addr),
77 AF_INET, &result, buffer, sizeof(buffer),
82 hp = gethostbyaddr((char *)&ipaddr, sizeof(struct in_addr), AF_INET);
85 hp = gethostbyaddr((char *)&ipaddr, sizeof(struct in_addr), AF_INET);
88 (strlen((char *)hp->h_name) >= buflen)) {
93 strNcpy(buf, (char *)hp->h_name, buflen);
99 * Return an IP address from a host
100 * name or address in dot notation.
102 uint32_t ip_getaddr(const char *host)
106 #ifdef GETHOSTBYNAMERSTYLE
107 #if (GETHOSTBYNAMERSTYLE == SYSVSTYLE) || (GETHOSTBYNAMERSTYLE == GNUSTYLE)
108 struct hostent result;
114 if ((a = ip_addr(host)) != htonl(INADDR_NONE))
117 #ifdef GETHOSTBYNAMERSTYLE
118 #if GETHOSTBYNAMERSTYLE == SYSVSTYLE
119 hp = gethostbyname_r(host, &result, buffer, sizeof(buffer), &error);
120 #elif GETHOSTBYNAMERSTYLE == GNUSTYLE
121 if (gethostbyname_r(host, &result, buffer, sizeof(buffer),
123 return htonl(INADDR_NONE);
126 hp = gethostbyname(host);
129 hp = gethostbyname(host);
132 return htonl(INADDR_NONE);
136 * Paranoia from a Bind vulnerability. An attacker
137 * can manipulate DNS entries to change the length of the
138 * address. If the length isn't 4, something's wrong.
140 if (hp->h_length != 4) {
141 return htonl(INADDR_NONE);
144 memcpy(&a, hp->h_addr, sizeof(uint32_t));
150 * Return an IP address in standard dot notation
152 char *ip_ntoa(char *buffer, uint32_t ipaddr)
154 ipaddr = ntohl(ipaddr);
156 sprintf(buffer, "%d.%d.%d.%d",
157 (ipaddr >> 24) & 0xff,
158 (ipaddr >> 16) & 0xff,
159 (ipaddr >> 8) & 0xff,
166 * Return an IP address from
167 * one supplied in standard dot notation.
169 uint32_t ip_addr(const char *ip_str)
173 if (inet_aton(ip_str, &in) == 0)
174 return htonl(INADDR_NONE);
180 * Like strncpy, but always adds \0
182 char *strNcpy(char *dest, const char *src, int n)
186 while ((n > 1) && (*src)) {
199 void rad_lowercase(char *str) {
203 if (isupper((int) *s)) *s = tolower((int) *s);
207 * Remove spaces from a string
209 void rad_rmspace(char *str) {
213 while(ptr && *ptr!='\0') {
214 while(isspace((int) *ptr))
224 * Internal wrapper for locking, to minimize the number of ifdef's
226 * Lock an fd, prefer lockf() over flock()
228 int rad_lockfd(int fd, int lock_len)
230 #if defined(F_LOCK) && !defined(BSD)
231 return lockf(fd, F_LOCK, lock_len);
232 #elif defined(LOCK_EX)
233 return flock(fd, LOCK_EX);
240 fl.l_whence = SEEK_CUR;
241 return fcntl(fd, F_SETLKW, (void *)&fl);
246 * Internal wrapper for locking, to minimize the number of ifdef's
248 * Lock an fd, prefer lockf() over flock()
249 * Nonblocking version.
251 int rad_lockfd_nonblock(int fd, int lock_len)
253 #if defined(F_LOCK) && !defined(BSD)
254 return lockf(fd, F_TLOCK, lock_len);
255 #elif defined(LOCK_EX)
256 return flock(fd, LOCK_EX | LOCK_NB);
263 fl.l_whence = SEEK_CUR;
264 return fcntl(fd, F_SETLK, (void *)&fl);
269 * Internal wrapper for unlocking, to minimize the number of ifdef's
272 * Unlock an fd, prefer lockf() over flock()
274 int rad_unlockfd(int fd, int lock_len)
276 #if defined(F_LOCK) && !defined(BSD)
277 return lockf(fd, F_ULOCK, lock_len);
278 #elif defined(LOCK_EX)
279 return flock(fd, LOCK_UN);
286 fl.l_whence = SEEK_CUR;
287 return fcntl(fd, F_UNLCK, (void *)&fl);
292 * Return an interface-id in standard colon notation
294 char *ifid_ntoa(char *buffer, size_t size, uint8_t *ifid)
296 snprintf(buffer, size, "%x:%x:%x:%x",
297 (ifid[0] << 8) + ifid[1], (ifid[2] << 8) + ifid[3],
298 (ifid[4] << 8) + ifid[5], (ifid[6] << 8) + ifid[7]);
304 * Return an interface-id from
305 * one supplied in standard colon notation.
307 uint8_t *ifid_aton(const char *ifid_str, uint8_t *ifid)
309 static const char xdigits[] = "0123456789abcdef";
311 int num_id = 0, val = 0, idx = 0;
313 for (p = ifid_str; ; ++p) {
314 if (*p == ':' || *p == '\0') {
319 * Drop 'val' into the array.
321 ifid[idx] = (val >> 8) & 0xff;
322 ifid[idx + 1] = val & 0xff;
325 * Must have all entries before
336 } else if ((pch = strchr(xdigits, tolower(*p))) != NULL) {
340 * Dumb version of 'scanf'
343 val |= (pch - xdigits);
350 * Return an IPv6 address in standard colon notation
352 const char *ipv6_ntoa(char *buffer, size_t size, void *ip6addr)
354 #if defined(HAVE_INET_NTOP) && defined(AF_INET6)
355 return inet_ntop(AF_INET6, (struct in6_addr *) ip6addr, buffer, size);
358 * Do it really stupidly.
360 snprintf(buffer, size, "%x:%x:%x:%x:%x:%x:%x:%x",
361 (((uint8_t *) ip6addr)[0] << 8) | ((uint8_t *) ip6addr)[1],
362 (((uint8_t *) ip6addr)[2] << 8) | ((uint8_t *) ip6addr)[3],
363 (((uint8_t *) ip6addr)[4] << 8) | ((uint8_t *) ip6addr)[5],
364 (((uint8_t *) ip6addr)[6] << 8) | ((uint8_t *) ip6addr)[7],
365 (((uint8_t *) ip6addr)[8] << 8) | ((uint8_t *) ip6addr)[9],
366 (((uint8_t *) ip6addr)[10] << 8) | ((uint8_t *) ip6addr)[11],
367 (((uint8_t *) ip6addr)[12] << 8) | ((uint8_t *) ip6addr)[13],
368 (((uint8_t *) ip6addr)[14] << 8) | ((uint8_t *) ip6addr)[15]);
375 * Return an IPv6 address from
376 * one supplied in standard colon notation.
378 int ipv6_addr(const char *ip6_str, void *ip6addr)
380 #if defined(HAVE_INET_PTON) && defined(AF_INET6)
381 if (inet_pton(AF_INET6, ip6_str, (struct in6_addr *) ip6addr) != 1)
385 * Copied from the 'ifid' code above, with minor edits.
387 static const char xdigits[] = "0123456789abcdef";
389 int num_id = 0, val = 0, idx = 0;
390 uint8_t *addr = ip6addr;
392 for (p = ip6_str; ; ++p) {
393 if (*p == ':' || *p == '\0') {
398 * Drop 'val' into the array.
400 addr[idx] = (val >> 8) & 0xff;
401 addr[idx + 1] = val & 0xff;
404 * Must have all entries before
415 } else if ((pch = strchr(xdigits, tolower(*p))) != NULL) {
416 if (++num_id > 8) /* no more than 8 16-bit numbers */
419 * Dumb version of 'scanf'
422 val |= (pch - xdigits);
430 static const char *hextab = "0123456789abcdef";
435 * We allow: hex == bin
437 int lrad_hex2bin(const char *hex, uint8_t *bin, int len)
442 for (i = 0; i < len; i++) {
443 if(!(c1 = memchr(hextab, tolower((int) hex[i << 1]), 16)) ||
444 !(c2 = memchr(hextab, tolower((int) hex[(i << 1) + 1]), 16)))
446 bin[i] = ((c1-hextab)<<4) + (c2-hextab);
456 * If the output buffer isn't long enough, we have a buffer overflow.
458 void lrad_bin2hex(const uint8_t *bin, char *hex, int len)
462 for (i = 0; i < len; i++) {
463 hex[0] = hextab[((*bin) >> 4) & 0x0f];
464 hex[1] = hextab[*bin & 0x0f];
473 * So we don't have ifdef's in the rest of the code
475 #ifndef HAVE_CLOSEFROM
476 int closefrom(int fd)
482 maxfd = sysconf(_SC_OPEN_MAX);
488 if (fd > maxfd) return 0;
491 * FIXME: return EINTR?
495 for (i = fd; i < maxfd; i++) {