Main Page | Modules | Class List | Directories | File List | Class Members | File Members | Related Pages

addr.c

Go to the documentation of this file.
00001 /*
00002  * addr.c
00003  *
00004  * Network address operations.
00005  *
00006  * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
00007  *
00008  * $Id: addr.c,v 1.34 2005/06/26 18:23:26 dugsong Exp $
00009  */
00010 
00011 #include "config.h"
00012 
00013 #include <sys/types.h>
00014 #ifdef HAVE_NET_IF_H
00015 # include <sys/socket.h>
00016 # include <net/if.h>
00017 #endif
00018 #ifdef HAVE_NET_IF_DL_H
00019 # include <net/if_dl.h>
00020 #endif
00021 #ifdef HAVE_NET_RAW_H
00022 # include <net/raw.h>
00023 #endif
00024 
00025 #include <ctype.h>
00026 #include <errno.h>
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 
00031 #include "dnet.h"
00032 
00033 #ifndef MAXHOSTNAMELEN
00034 # define MAXHOSTNAMELEN 256
00035 #endif
00036 
00037 union sockunion {
00038 #ifdef HAVE_NET_IF_DL_H
00039         struct sockaddr_dl      sdl;
00040 #endif
00041         struct sockaddr_in      sin;
00042 #ifdef HAVE_SOCKADDR_IN6
00043         struct sockaddr_in6     sin6;
00044 #endif
00045         struct sockaddr         sa;
00046 #ifdef AF_RAW
00047         struct sockaddr_raw     sr;
00048 #endif
00049 };
00050 
00051 int
00052 addr_cmp(const struct addr *a, const struct addr *b)
00053 {
00054         int i, j, k;
00055 
00056         /* XXX */
00057         if ((i = a->addr_type - b->addr_type) != 0)
00058                 return (i);
00059         
00060         /* XXX - 10.0.0.1 is "smaller" than 10.0.0.0/8? */
00061         if ((i = a->addr_bits - b->addr_bits) != 0)
00062                 return (i);
00063         
00064         j = b->addr_bits / 8;
00065 
00066         for (i = 0; i < j; i++) {
00067                 if ((k = a->addr_data8[i] - b->addr_data8[i]) != 0)
00068                         return (k);
00069         }
00070         if ((k = b->addr_bits % 8) == 0)
00071                 return (0);
00072 
00073         k = ~0 << (8 - k);
00074         i = b->addr_data8[j] & k;
00075         j = a->addr_data8[j] & k;
00076         
00077         return (j - i);
00078 }
00079 
00080 int
00081 addr_net(const struct addr *a, struct addr *b)
00082 {
00083         uint32_t mask;
00084         int i, j;
00085 
00086         if (a->addr_type == ADDR_TYPE_IP) {
00087                 addr_btom(a->addr_bits, &mask, IP_ADDR_LEN);
00088                 b->addr_type = ADDR_TYPE_IP;
00089                 b->addr_bits = IP_ADDR_BITS;
00090                 b->addr_ip = a->addr_ip & mask;
00091         } else if (a->addr_type == ADDR_TYPE_ETH) {
00092                 memcpy(b, a, sizeof(*b));
00093                 if (a->addr_data8[0] & 0x1)
00094                         memset(b->addr_data8 + 3, 0, 3);
00095                 b->addr_bits = ETH_ADDR_BITS;
00096         } else if (a->addr_type == ADDR_TYPE_IP6) {
00097                 b->addr_type = ADDR_TYPE_IP6;
00098                 b->addr_bits = IP6_ADDR_BITS;
00099                 memset(&b->addr_ip6, 0, IP6_ADDR_LEN);
00100                 
00101                 switch ((i = a->addr_bits / 32)) {
00102                 case 4: b->addr_data32[3] = a->addr_data32[3];
00103                 case 3: b->addr_data32[2] = a->addr_data32[2];
00104                 case 2: b->addr_data32[1] = a->addr_data32[1];
00105                 case 1: b->addr_data32[0] = a->addr_data32[0];
00106                 }
00107                 if ((j = a->addr_bits % 32) > 0) {
00108                         addr_btom(j, &mask, sizeof(mask));
00109                         b->addr_data32[i] = a->addr_data32[i] & mask;
00110                 }
00111         } else
00112                 return (-1);
00113         
00114         return (0);
00115 }
00116 
00117 int
00118 addr_bcast(const struct addr *a, struct addr *b)
00119 {
00120         struct addr mask;
00121         
00122         if (a->addr_type == ADDR_TYPE_IP) {
00123                 addr_btom(a->addr_bits, &mask.addr_ip, IP_ADDR_LEN);
00124                 b->addr_type = ADDR_TYPE_IP;
00125                 b->addr_bits = IP_ADDR_BITS;
00126                 b->addr_ip = (a->addr_ip & mask.addr_ip) |
00127                     (~0L & ~mask.addr_ip);
00128         } else if (a->addr_type == ADDR_TYPE_ETH) {
00129                 b->addr_type = ADDR_TYPE_ETH;
00130                 b->addr_bits = ETH_ADDR_BITS;
00131                 memcpy(&b->addr_eth, ETH_ADDR_BROADCAST, ETH_ADDR_LEN);
00132         } else {
00133                 /* XXX - no broadcast addresses in IPv6 */
00134                 errno = EINVAL;
00135                 return (-1);
00136         }
00137         return (0);
00138 }
00139 
00140 char *
00141 addr_ntop(const struct addr *src, char *dst, size_t size)
00142 {
00143         if (src->addr_type == ADDR_TYPE_IP && size >= 20) {
00144                 if (ip_ntop(&src->addr_ip, dst, size) != NULL) {
00145                         if (src->addr_bits != IP_ADDR_BITS)
00146                                 sprintf(dst + strlen(dst), "/%d",
00147                                     src->addr_bits);
00148                         return (dst);
00149                 }
00150         } else if (src->addr_type == ADDR_TYPE_IP6 && size >= 42) {
00151                 if (ip6_ntop(&src->addr_ip6, dst, size) != NULL) {
00152                         if (src->addr_bits != IP6_ADDR_BITS)
00153                                 sprintf(dst + strlen(dst), "/%d",
00154                                     src->addr_bits);
00155                         return (dst);
00156                 }
00157         } else if (src->addr_type == ADDR_TYPE_ETH && size >= 18) {
00158                 if (src->addr_bits == ETH_ADDR_BITS)
00159                         return (eth_ntop(&src->addr_eth, dst, size));
00160         }
00161         errno = EINVAL;
00162         return (NULL);
00163 }
00164 
00165 int
00166 addr_pton(const char *src, struct addr *dst)
00167 {
00168         struct hostent *hp;
00169         char *ep, tmp[300];
00170         long bits = -1;
00171         int i;
00172         
00173         for (i = 0; i < (int)sizeof(tmp) - 1; i++) {
00174                 if (src[i] == '/') {
00175                         tmp[i] = '\0';
00176                         if (strchr(&src[i + 1], '.')) {
00177                                 uint32_t m;
00178                                 uint16_t b;
00179                                 /* XXX - mask is specified like /255.0.0.0 */
00180                                 if (ip_pton(&src[i + 1], &m) != 0) {
00181                                         errno = EINVAL;
00182                                         return (-1);
00183                                 }
00184                                 addr_mtob(&m, sizeof(m), &b);
00185                                 bits = b;
00186                         } else {
00187                                 bits = strtol(&src[i + 1], &ep, 10);
00188                                 if (ep == src || *ep != '\0' || bits < 0) {
00189                                         errno = EINVAL;
00190                                         return (-1);
00191                                 }
00192                         }
00193                         break;
00194                 } else if ((tmp[i] = src[i]) == '\0')
00195                         break;
00196         }
00197         if (ip_pton(tmp, &dst->addr_ip) == 0) {
00198                 dst->addr_type = ADDR_TYPE_IP;
00199                 dst->addr_bits = IP_ADDR_BITS;
00200         } else if (eth_pton(tmp, &dst->addr_eth) == 0) {
00201                 dst->addr_type = ADDR_TYPE_ETH;
00202                 dst->addr_bits = ETH_ADDR_BITS;
00203         } else if (ip6_pton(tmp, &dst->addr_ip6) == 0) {
00204                 dst->addr_type = ADDR_TYPE_IP6;
00205                 dst->addr_bits = IP6_ADDR_BITS;
00206         } else if ((hp = gethostbyname(tmp)) != NULL) {
00207                 memcpy(&dst->addr_ip, hp->h_addr, IP_ADDR_LEN);
00208                 dst->addr_type = ADDR_TYPE_IP;
00209                 dst->addr_bits = IP_ADDR_BITS;
00210         } else {
00211                 errno = EINVAL;
00212                 return (-1);
00213         }
00214         if (bits >= 0) {
00215                 if (bits > dst->addr_bits) {
00216                         errno = EINVAL;
00217                         return (-1);
00218                 }
00219                 dst->addr_bits = (uint16_t)bits;
00220         }
00221         return (0);
00222 }
00223 
00224 char *
00225 addr_ntoa(const struct addr *a)
00226 {
00227         static char *p, buf[BUFSIZ];
00228         char *q = NULL;
00229         
00230         if (p == NULL || p > buf + sizeof(buf) - 64 /* XXX */)
00231                 p = buf;
00232         
00233         if (addr_ntop(a, p, (buf + sizeof(buf)) - p) != NULL) {
00234                 q = p;
00235                 p += strlen(p) + 1;
00236         }
00237         return (q);
00238 }
00239 
00240 int
00241 addr_ntos(const struct addr *a, struct sockaddr *sa)
00242 {
00243         union sockunion *so = (union sockunion *)sa;
00244         
00245         switch (a->addr_type) {
00246         case ADDR_TYPE_ETH:
00247 #ifdef HAVE_NET_IF_DL_H
00248                 memset(&so->sdl, 0, sizeof(so->sdl));
00249 # ifdef HAVE_SOCKADDR_SA_LEN
00250                 so->sdl.sdl_len = sizeof(so->sdl);
00251 # endif
00252                 so->sdl.sdl_family = AF_LINK;
00253                 so->sdl.sdl_alen = ETH_ADDR_LEN;
00254                 memcpy(LLADDR(&so->sdl), &a->addr_eth, ETH_ADDR_LEN);
00255 #else
00256                 memset(sa, 0, sizeof(*sa));
00257 # ifdef AF_LINK
00258                 sa->sa_family = AF_LINK;
00259 # else
00260                 sa->sa_family = AF_UNSPEC;
00261 # endif
00262                 memcpy(sa->sa_data, &a->addr_eth, ETH_ADDR_LEN);
00263 #endif
00264                 break;
00265 #ifdef HAVE_SOCKADDR_IN6
00266         case ADDR_TYPE_IP6:
00267                 memset(&so->sin6, 0, sizeof(so->sin6));
00268 #ifdef HAVE_SOCKADDR_SA_LEN
00269                 so->sin6.sin6_len = sizeof(so->sin6);
00270 #endif
00271                 so->sin6.sin6_family = AF_INET6;
00272                 memcpy(&so->sin6.sin6_addr, &a->addr_ip6, IP6_ADDR_LEN);
00273                 break;
00274 #endif
00275         case ADDR_TYPE_IP:
00276                 memset(&so->sin, 0, sizeof(so->sin));
00277 #ifdef HAVE_SOCKADDR_SA_LEN
00278                 so->sin.sin_len = sizeof(so->sin);
00279 #endif
00280                 so->sin.sin_family = AF_INET;
00281                 so->sin.sin_addr.s_addr = a->addr_ip;
00282                 break;
00283         default:
00284                 errno = EINVAL;
00285                 return (-1);
00286         }
00287         return (0);
00288 }
00289 
00290 int
00291 addr_ston(const struct sockaddr *sa, struct addr *a)
00292 {
00293         union sockunion *so = (union sockunion *)sa;
00294         
00295         memset(a, 0, sizeof(*a));
00296         
00297         switch (sa->sa_family) {
00298 #ifdef HAVE_NET_IF_DL_H
00299         case AF_LINK:
00300                 if (so->sdl.sdl_alen != ETH_ADDR_LEN) {
00301                         errno = EINVAL;
00302                         return (-1);
00303                 }
00304                 a->addr_type = ADDR_TYPE_ETH;
00305                 a->addr_bits = ETH_ADDR_BITS;
00306                 memcpy(&a->addr_eth, LLADDR(&so->sdl), ETH_ADDR_LEN);
00307                 break;
00308 #endif
00309         case AF_UNSPEC:
00310         case ARP_HRD_ETH:       /* XXX- Linux arp(7) */
00311                 a->addr_type = ADDR_TYPE_ETH;
00312                 a->addr_bits = ETH_ADDR_BITS;
00313                 memcpy(&a->addr_eth, sa->sa_data, ETH_ADDR_LEN);
00314                 break;
00315                 
00316 #ifdef AF_RAW
00317         case AF_RAW:            /* XXX - IRIX raw(7f) */
00318                 a->addr_type = ADDR_TYPE_ETH;
00319                 a->addr_bits = ETH_ADDR_BITS;
00320                 memcpy(&a->addr_eth, so->sr.sr_addr, ETH_ADDR_LEN);
00321                 break;
00322 #endif
00323 #ifdef HAVE_SOCKADDR_IN6
00324         case AF_INET6:
00325                 a->addr_type = ADDR_TYPE_IP6;
00326                 a->addr_bits = IP6_ADDR_BITS;
00327                 memcpy(&a->addr_ip6, &so->sin6.sin6_addr, IP6_ADDR_LEN);
00328                 break;
00329 #endif
00330         case AF_INET:
00331                 a->addr_type = ADDR_TYPE_IP;
00332                 a->addr_bits = IP_ADDR_BITS;
00333                 a->addr_ip = so->sin.sin_addr.s_addr;
00334                 break;
00335         default:
00336                 errno = EINVAL;
00337                 return (-1);
00338         }
00339         return (0);
00340 }
00341 
00342 int
00343 addr_btos(uint16_t bits, struct sockaddr *sa)
00344 {
00345         union sockunion *so = (union sockunion *)sa;
00346 
00347 #ifdef HAVE_SOCKADDR_IN6
00348         if (bits > IP_ADDR_BITS && bits <= IP6_ADDR_BITS) {
00349                 memset(&so->sin6, 0, sizeof(so->sin6));
00350 #ifdef HAVE_SOCKADDR_SA_LEN
00351                 so->sin6.sin6_len = IP6_ADDR_LEN + (bits / 8) + (bits % 8);
00352 #endif
00353                 so->sin6.sin6_family = AF_INET6;
00354                 return (addr_btom(bits, &so->sin6.sin6_addr, IP6_ADDR_LEN));
00355         } else
00356 #endif
00357         if (bits <= IP_ADDR_BITS) {
00358                 memset(&so->sin, 0, sizeof(so->sin));
00359 #ifdef HAVE_SOCKADDR_SA_LEN
00360                 so->sin.sin_len = IP_ADDR_LEN + (bits / 8) + (bits % 8);
00361 #endif
00362                 so->sin.sin_family = AF_INET;
00363                 return (addr_btom(bits, &so->sin.sin_addr, IP_ADDR_LEN));
00364         }
00365         errno = EINVAL;
00366         return (-1);
00367 }
00368 
00369 int
00370 addr_stob(const struct sockaddr *sa, uint16_t *bits)
00371 {
00372         union sockunion *so = (union sockunion *)sa;
00373         int i, j, len;
00374         uint16_t n;
00375         u_char *p;
00376 
00377 #ifdef HAVE_SOCKADDR_IN6
00378         if (sa->sa_family == AF_INET6) {
00379                 len = IP6_ADDR_LEN;
00380                 p = (u_char *)&so->sin6.sin6_addr;
00381         } else
00382 #endif
00383         {
00384 #ifdef HAVE_SOCKADDR_SA_LEN
00385                 if ((len = sa->sa_len - IP_ADDR_LEN) > IP_ADDR_LEN)
00386 #endif
00387                 len = IP_ADDR_LEN;
00388                 p = (u_char *)&so->sin.sin_addr.s_addr;
00389         }
00390         for (n = i = 0; i < len; i++, n += 8) {
00391                 if (p[i] != 0xff)
00392                         break;
00393         }
00394         if (i != len && p[i]) {
00395                 for (j = 7; j > 0; j--, n++) {
00396                         if ((p[i] & (1 << j)) == 0)
00397                                 break;
00398                 }
00399         }
00400         *bits = n;
00401         
00402         return (0);
00403 }
00404         
00405 int
00406 addr_btom(uint16_t bits, void *mask, size_t size)
00407 {
00408         int net, host;
00409         u_char *p;
00410 
00411         if (size == IP_ADDR_LEN) {
00412                 if (bits > IP_ADDR_BITS) {
00413                         errno = EINVAL;
00414                         return (-1);
00415                 }
00416                 *(uint32_t *)mask = bits ?
00417                     htonl(~0 << (IP_ADDR_BITS - bits)) : 0;
00418         } else {
00419                 if (size * 8 < bits) {
00420                         errno = EINVAL;
00421                         return (-1);
00422                 }
00423                 p = (u_char *)mask;
00424                 
00425                 if ((net = bits / 8) > 0)
00426                         memset(p, 0xff, net);
00427                 
00428                 if ((host = bits % 8) > 0) {
00429                         p[net] = 0xff << (8 - host);
00430                         memset(&p[net + 1], 0, size - net - 1);
00431                 } else
00432                         memset(&p[net], 0, size - net);
00433         }
00434         return (0);
00435 }
00436 
00437 int
00438 addr_mtob(const void *mask, size_t size, uint16_t *bits)
00439 {
00440         uint16_t n;
00441         u_char *p;
00442         int i, j;
00443 
00444         p = (u_char *)mask;
00445         
00446         for (n = i = 0; i < (int)size; i++, n += 8) {
00447                 if (p[i] != 0xff)
00448                         break;
00449         }
00450         if (i != (int)size && p[i]) {
00451                 for (j = 7; j > 0; j--, n++) {
00452                         if ((p[i] & (1 << j)) == 0)
00453                                 break;
00454                 }
00455         }
00456         *bits = n;
00457 
00458         return (0);
00459 }

Generated on Sun May 14 14:51:11 2006 by  doxygen 1.4.2