Annotation of embedaddon/quagga/lib/sockunion.c, revision 1.1.1.4

1.1       misho       1: /* Socket union related function.
                      2:  * Copyright (c) 1997, 98 Kunihiro Ishiguro
                      3:  *
                      4:  * This file is part of GNU Zebra.
                      5:  *
                      6:  * GNU Zebra is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2, or (at your option) any
                      9:  * later version.
                     10:  *
                     11:  * GNU Zebra is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     14:  * General Public License for more details.
                     15:  *
                     16:  * You should have received a copy of the GNU General Public License
                     17:  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
                     18:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
                     19:  * 02111-1307, USA.  
                     20:  */
                     21: 
                     22: #include <zebra.h>
                     23: 
                     24: #include "prefix.h"
                     25: #include "vty.h"
                     26: #include "sockunion.h"
                     27: #include "memory.h"
                     28: #include "str.h"
                     29: #include "log.h"
1.1.1.4 ! misho      30: #include "jhash.h"
1.1       misho      31: 
                     32: #ifndef HAVE_INET_ATON
                     33: int
                     34: inet_aton (const char *cp, struct in_addr *inaddr)
                     35: {
                     36:   int dots = 0;
                     37:   register u_long addr = 0;
                     38:   register u_long val = 0, base = 10;
                     39: 
                     40:   do
                     41:     {
                     42:       register char c = *cp;
                     43: 
                     44:       switch (c)
                     45:        {
                     46:        case '0': case '1': case '2': case '3': case '4': case '5':
                     47:        case '6': case '7': case '8': case '9':
                     48:          val = (val * base) + (c - '0');
                     49:          break;
                     50:        case '.':
                     51:          if (++dots > 3)
                     52:            return 0;
                     53:        case '\0':
                     54:          if (val > 255)
                     55:            return 0;
                     56:          addr = addr << 8 | val;
                     57:          val = 0;
                     58:          break;
                     59:        default:
                     60:          return 0;
                     61:        }
                     62:     } while (*cp++) ;
                     63: 
                     64:   if (dots < 3)
                     65:     addr <<= 8 * (3 - dots);
                     66:   if (inaddr)
                     67:     inaddr->s_addr = htonl (addr);
                     68:   return 1;
                     69: }
                     70: #endif /* ! HAVE_INET_ATON */
                     71: 
                     72: 
                     73: #ifndef HAVE_INET_PTON
                     74: int
                     75: inet_pton (int family, const char *strptr, void *addrptr)
                     76: {
                     77:   if (family == AF_INET)
                     78:     {
                     79:       struct in_addr in_val;
                     80: 
                     81:       if (inet_aton (strptr, &in_val))
                     82:        {
                     83:          memcpy (addrptr, &in_val, sizeof (struct in_addr));
                     84:          return 1;
                     85:        }
                     86:       return 0;
                     87:     }
                     88:   errno = EAFNOSUPPORT;
                     89:   return -1;
                     90: }
                     91: #endif /* ! HAVE_INET_PTON */
                     92: 
                     93: #ifndef HAVE_INET_NTOP
                     94: const char *
                     95: inet_ntop (int family, const void *addrptr, char *strptr, size_t len)
                     96: {
                     97:   unsigned char *p = (unsigned char *) addrptr;
                     98: 
                     99:   if (family == AF_INET) 
                    100:     {
                    101:       char temp[INET_ADDRSTRLEN];
                    102: 
                    103:       snprintf(temp, sizeof(temp), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
                    104: 
                    105:       if (strlen(temp) >= len) 
                    106:        {
                    107:          errno = ENOSPC;
                    108:          return NULL;
                    109:        }
                    110:       strcpy(strptr, temp);
                    111:       return strptr;
                    112:     }
                    113: 
                    114:   errno = EAFNOSUPPORT;
                    115:   return NULL;
                    116: }
                    117: #endif /* ! HAVE_INET_NTOP */
                    118: 
                    119: const char *
1.1.1.4 ! misho     120: inet_sutop (const union sockunion *su, char *str)
1.1       misho     121: {
                    122:   switch (su->sa.sa_family)
                    123:     {
                    124:     case AF_INET:
                    125:       inet_ntop (AF_INET, &su->sin.sin_addr, str, INET_ADDRSTRLEN);
                    126:       break;
                    127: #ifdef HAVE_IPV6
                    128:     case AF_INET6:
                    129:       inet_ntop (AF_INET6, &su->sin6.sin6_addr, str, INET6_ADDRSTRLEN);
                    130:       break;
                    131: #endif /* HAVE_IPV6 */
                    132:     }
                    133:   return str;
                    134: }
                    135: 
                    136: int
                    137: str2sockunion (const char *str, union sockunion *su)
                    138: {
                    139:   int ret;
                    140: 
                    141:   memset (su, 0, sizeof (union sockunion));
                    142: 
                    143:   ret = inet_pton (AF_INET, str, &su->sin.sin_addr);
                    144:   if (ret > 0)                 /* Valid IPv4 address format. */
                    145:     {
                    146:       su->sin.sin_family = AF_INET;
                    147: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
                    148:       su->sin.sin_len = sizeof(struct sockaddr_in);
                    149: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
                    150:       return 0;
                    151:     }
                    152: #ifdef HAVE_IPV6
                    153:   ret = inet_pton (AF_INET6, str, &su->sin6.sin6_addr);
                    154:   if (ret > 0)                 /* Valid IPv6 address format. */
                    155:     {
                    156:       su->sin6.sin6_family = AF_INET6;
                    157: #ifdef SIN6_LEN
                    158:       su->sin6.sin6_len = sizeof(struct sockaddr_in6);
                    159: #endif /* SIN6_LEN */
                    160:       return 0;
                    161:     }
                    162: #endif /* HAVE_IPV6 */
                    163:   return -1;
                    164: }
                    165: 
                    166: const char *
1.1.1.4 ! misho     167: sockunion2str (const union sockunion *su, char *buf, size_t len)
1.1       misho     168: {
1.1.1.4 ! misho     169:   switch (sockunion_family(su))
        !           170:     {
        !           171:     case AF_UNSPEC:
        !           172:       snprintf (buf, len, "(unspec)");
        !           173:       return buf;
        !           174:     case AF_INET:
        !           175:       return inet_ntop (AF_INET, &su->sin.sin_addr, buf, len);
1.1       misho     176: #ifdef HAVE_IPV6
1.1.1.4 ! misho     177:     case AF_INET6:
        !           178:       return inet_ntop (AF_INET6, &su->sin6.sin6_addr, buf, len);
1.1       misho     179: #endif /* HAVE_IPV6 */
1.1.1.4 ! misho     180:     }
        !           181:   snprintf (buf, len, "(af %d)", sockunion_family(su));
        !           182:   return buf;
1.1       misho     183: }
                    184: 
                    185: union sockunion *
                    186: sockunion_str2su (const char *str)
                    187: {
1.1.1.3   misho     188:   union sockunion *su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
                    189:   
                    190:   if (!str2sockunion (str, su))
                    191:     return su;
                    192:   
1.1       misho     193:   XFREE (MTYPE_SOCKUNION, su);
                    194:   return NULL;
                    195: }
                    196: 
                    197: /* Convert IPv4 compatible IPv6 address to IPv4 address. */
                    198: static void
                    199: sockunion_normalise_mapped (union sockunion *su)
                    200: {
                    201:   struct sockaddr_in sin;
                    202:   
                    203: #ifdef HAVE_IPV6
                    204:   if (su->sa.sa_family == AF_INET6 
                    205:       && IN6_IS_ADDR_V4MAPPED (&su->sin6.sin6_addr))
                    206:     {
                    207:       memset (&sin, 0, sizeof (struct sockaddr_in));
                    208:       sin.sin_family = AF_INET;
                    209:       sin.sin_port = su->sin6.sin6_port;
                    210:       memcpy (&sin.sin_addr, ((char *)&su->sin6.sin6_addr) + 12, 4);
                    211:       memcpy (su, &sin, sizeof (struct sockaddr_in));
                    212:     }
                    213: #endif /* HAVE_IPV6 */
                    214: }
                    215: 
                    216: /* Return socket of sockunion. */
                    217: int
1.1.1.4 ! misho     218: sockunion_socket (const union sockunion *su)
1.1       misho     219: {
                    220:   int sock;
                    221: 
                    222:   sock = socket (su->sa.sa_family, SOCK_STREAM, 0);
                    223:   if (sock < 0)
                    224:     {
                    225:       zlog (NULL, LOG_WARNING, "Can't make socket : %s", safe_strerror (errno));
                    226:       return -1;
                    227:     }
                    228: 
                    229:   return sock;
                    230: }
                    231: 
                    232: /* Return accepted new socket file descriptor. */
                    233: int
                    234: sockunion_accept (int sock, union sockunion *su)
                    235: {
                    236:   socklen_t len;
                    237:   int client_sock;
                    238: 
                    239:   len = sizeof (union sockunion);
                    240:   client_sock = accept (sock, (struct sockaddr *) su, &len);
                    241:   
                    242:   sockunion_normalise_mapped (su);
                    243:   return client_sock;
                    244: }
                    245: 
                    246: /* Return sizeof union sockunion.  */
                    247: static int
1.1.1.4 ! misho     248: sockunion_sizeof (const union sockunion *su)
1.1       misho     249: {
                    250:   int ret;
                    251: 
                    252:   ret = 0;
                    253:   switch (su->sa.sa_family)
                    254:     {
                    255:     case AF_INET:
                    256:       ret = sizeof (struct sockaddr_in);
                    257:       break;
                    258: #ifdef HAVE_IPV6
                    259:     case AF_INET6:
                    260:       ret = sizeof (struct sockaddr_in6);
                    261:       break;
                    262: #endif /* AF_INET6 */
                    263:     }
                    264:   return ret;
                    265: }
                    266: 
                    267: /* return sockunion structure : this function should be revised. */
1.1.1.2   misho     268: static const char *
1.1.1.4 ! misho     269: sockunion_log (const union sockunion *su, char *buf, size_t len)
1.1       misho     270: {
                    271:   switch (su->sa.sa_family) 
                    272:     {
                    273:     case AF_INET:
1.1.1.2   misho     274:       return inet_ntop(AF_INET, &su->sin.sin_addr, buf, len);
                    275: 
1.1       misho     276: #ifdef HAVE_IPV6
                    277:     case AF_INET6:
1.1.1.2   misho     278:       return inet_ntop(AF_INET6, &(su->sin6.sin6_addr), buf, len);
1.1       misho     279:       break;
                    280: #endif /* HAVE_IPV6 */
1.1.1.2   misho     281: 
1.1       misho     282:     default:
1.1.1.2   misho     283:       snprintf (buf, len, "af_unknown %d ", su->sa.sa_family);
                    284:       return buf;
1.1       misho     285:     }
                    286: }
                    287: 
                    288: /* sockunion_connect returns
                    289:    -1 : error occured
                    290:    0 : connect success
                    291:    1 : connect is in progress */
                    292: enum connect_result
1.1.1.4 ! misho     293: sockunion_connect (int fd, const union sockunion *peersu, unsigned short port,
        !           294:                   ifindex_t ifindex)
1.1       misho     295: {
                    296:   int ret;
                    297:   int val;
                    298:   union sockunion su;
                    299: 
                    300:   memcpy (&su, peersu, sizeof (union sockunion));
                    301: 
                    302:   switch (su.sa.sa_family)
                    303:     {
                    304:     case AF_INET:
                    305:       su.sin.sin_port = port;
                    306:       break;
                    307: #ifdef HAVE_IPV6
                    308:     case AF_INET6:
                    309:       su.sin6.sin6_port  = port;
                    310: #ifdef KAME
                    311:       if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr) && ifindex)
                    312:        {
                    313: #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
                    314:          /* su.sin6.sin6_scope_id = ifindex; */
                    315: #endif /* HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID */
                    316:          SET_IN6_LINKLOCAL_IFINDEX (su.sin6.sin6_addr, ifindex);
                    317:        }
                    318: #endif /* KAME */
                    319:       break;
                    320: #endif /* HAVE_IPV6 */
                    321:     }      
                    322: 
                    323:   /* Make socket non-block. */
                    324:   val = fcntl (fd, F_GETFL, 0);
                    325:   fcntl (fd, F_SETFL, val|O_NONBLOCK);
                    326: 
                    327:   /* Call connect function. */
                    328:   ret = connect (fd, (struct sockaddr *) &su, sockunion_sizeof (&su));
                    329: 
                    330:   /* Immediate success */
                    331:   if (ret == 0)
                    332:     {
                    333:       fcntl (fd, F_SETFL, val);
                    334:       return connect_success;
                    335:     }
                    336: 
                    337:   /* If connect is in progress then return 1 else it's real error. */
                    338:   if (ret < 0)
                    339:     {
                    340:       if (errno != EINPROGRESS)
                    341:        {
1.1.1.2   misho     342:          char str[SU_ADDRSTRLEN];
1.1       misho     343:          zlog_info ("can't connect to %s fd %d : %s",
1.1.1.2   misho     344:                     sockunion_log (&su, str, sizeof str),
                    345:                     fd, safe_strerror (errno));
1.1       misho     346:          return connect_error;
                    347:        }
                    348:     }
                    349: 
                    350:   fcntl (fd, F_SETFL, val);
                    351: 
                    352:   return connect_in_progress;
                    353: }
                    354: 
                    355: /* Make socket from sockunion union. */
                    356: int
                    357: sockunion_stream_socket (union sockunion *su)
                    358: {
                    359:   int sock;
                    360: 
                    361:   if (su->sa.sa_family == 0)
                    362:     su->sa.sa_family = AF_INET_UNION;
                    363: 
                    364:   sock = socket (su->sa.sa_family, SOCK_STREAM, 0);
                    365: 
                    366:   if (sock < 0)
                    367:     zlog (NULL, LOG_WARNING, "can't make socket sockunion_stream_socket");
                    368: 
                    369:   return sock;
                    370: }
                    371: 
                    372: /* Bind socket to specified address. */
                    373: int
                    374: sockunion_bind (int sock, union sockunion *su, unsigned short port, 
                    375:                union sockunion *su_addr)
                    376: {
                    377:   int size = 0;
                    378:   int ret;
                    379: 
                    380:   if (su->sa.sa_family == AF_INET)
                    381:     {
                    382:       size = sizeof (struct sockaddr_in);
                    383:       su->sin.sin_port = htons (port);
                    384: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
                    385:       su->sin.sin_len = size;
                    386: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
                    387:       if (su_addr == NULL)
1.1.1.3   misho     388:        sockunion2ip (su) = htonl (INADDR_ANY);
1.1       misho     389:     }
                    390: #ifdef HAVE_IPV6
                    391:   else if (su->sa.sa_family == AF_INET6)
                    392:     {
                    393:       size = sizeof (struct sockaddr_in6);
                    394:       su->sin6.sin6_port = htons (port);
                    395: #ifdef SIN6_LEN
                    396:       su->sin6.sin6_len = size;
                    397: #endif /* SIN6_LEN */
                    398:       if (su_addr == NULL)
                    399:        {
1.1.1.4 ! misho     400: #ifdef LINUX_IPV6
1.1       misho     401:          memset (&su->sin6.sin6_addr, 0, sizeof (struct in6_addr));
                    402: #else
                    403:          su->sin6.sin6_addr = in6addr_any;
                    404: #endif /* LINUX_IPV6 */
                    405:        }
                    406:     }
                    407: #endif /* HAVE_IPV6 */
                    408:   
                    409: 
                    410:   ret = bind (sock, (struct sockaddr *)su, size);
                    411:   if (ret < 0)
                    412:     zlog (NULL, LOG_WARNING, "can't bind socket : %s", safe_strerror (errno));
                    413: 
                    414:   return ret;
                    415: }
                    416: 
                    417: int
                    418: sockopt_reuseaddr (int sock)
                    419: {
                    420:   int ret;
                    421:   int on = 1;
                    422: 
                    423:   ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, 
                    424:                    (void *) &on, sizeof (on));
                    425:   if (ret < 0)
                    426:     {
                    427:       zlog (NULL, LOG_WARNING, "can't set sockopt SO_REUSEADDR to socket %d", sock);
                    428:       return -1;
                    429:     }
                    430:   return 0;
                    431: }
                    432: 
                    433: #ifdef SO_REUSEPORT
                    434: int
                    435: sockopt_reuseport (int sock)
                    436: {
                    437:   int ret;
                    438:   int on = 1;
                    439: 
                    440:   ret = setsockopt (sock, SOL_SOCKET, SO_REUSEPORT, 
                    441:                    (void *) &on, sizeof (on));
                    442:   if (ret < 0)
                    443:     {
                    444:       zlog (NULL, LOG_WARNING, "can't set sockopt SO_REUSEPORT to socket %d", sock);
                    445:       return -1;
                    446:     }
                    447:   return 0;
                    448: }
                    449: #else
                    450: int
                    451: sockopt_reuseport (int sock)
                    452: {
                    453:   return 0;
                    454: }
                    455: #endif /* 0 */
                    456: 
                    457: int
                    458: sockopt_ttl (int family, int sock, int ttl)
                    459: {
                    460:   int ret;
                    461: 
                    462: #ifdef IP_TTL
                    463:   if (family == AF_INET)
                    464:     {
                    465:       ret = setsockopt (sock, IPPROTO_IP, IP_TTL, 
                    466:                        (void *) &ttl, sizeof (int));
                    467:       if (ret < 0)
                    468:        {
                    469:          zlog (NULL, LOG_WARNING, "can't set sockopt IP_TTL %d to socket %d", ttl, sock);
                    470:          return -1;
                    471:        }
                    472:       return 0;
                    473:     }
                    474: #endif /* IP_TTL */
                    475: #ifdef HAVE_IPV6
                    476:   if (family == AF_INET6)
                    477:     {
                    478:       ret = setsockopt (sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 
                    479:                        (void *) &ttl, sizeof (int));
                    480:       if (ret < 0)
                    481:        {
                    482:          zlog (NULL, LOG_WARNING, "can't set sockopt IPV6_UNICAST_HOPS %d to socket %d",
                    483:                    ttl, sock);
                    484:          return -1;
                    485:        }
                    486:       return 0;
                    487:     }
                    488: #endif /* HAVE_IPV6 */
                    489:   return 0;
                    490: }
                    491: 
                    492: int
                    493: sockopt_cork (int sock, int onoff)
                    494: {
                    495: #ifdef TCP_CORK
                    496:   return setsockopt (sock, IPPROTO_TCP, TCP_CORK, &onoff, sizeof(onoff));
                    497: #else
                    498:   return 0;
                    499: #endif
                    500: }
                    501: 
                    502: int
                    503: sockopt_minttl (int family, int sock, int minttl)
                    504: {
                    505: #ifdef IP_MINTTL
                    506:   if (family == AF_INET)
                    507:     {
                    508:       int ret = setsockopt (sock, IPPROTO_IP, IP_MINTTL, &minttl, sizeof(minttl));
                    509:       if (ret < 0)
                    510:          zlog (NULL, LOG_WARNING,
                    511:                "can't set sockopt IP_MINTTL to %d on socket %d: %s",
                    512:                minttl, sock, safe_strerror (errno));
                    513:       return ret;
                    514:     }
                    515: #endif /* IP_MINTTL */
                    516: #ifdef IPV6_MINHOPCNT
                    517:   if (family == AF_INET6)
                    518:     {
                    519:       int ret = setsockopt (sock, IPPROTO_IPV6, IPV6_MINHOPCNT, &minttl, sizeof(minttl));
                    520:       if (ret < 0)
                    521:          zlog (NULL, LOG_WARNING,
                    522:                "can't set sockopt IPV6_MINHOPCNT to %d on socket %d: %s",
                    523:                minttl, sock, safe_strerror (errno));
                    524:       return ret;
                    525:     }
                    526: #endif
                    527: 
                    528:   errno = EOPNOTSUPP;
                    529:   return -1;
                    530: }
                    531: 
1.1.1.2   misho     532: int
                    533: sockopt_v6only (int family, int sock)
                    534: {
                    535:   int ret, on = 1;
                    536: 
                    537: #ifdef HAVE_IPV6
                    538: #ifdef IPV6_V6ONLY
                    539:   if (family == AF_INET6)
                    540:     {
                    541:       ret = setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY,
                    542:                        (void *) &on, sizeof (int));
                    543:       if (ret < 0)
                    544:        {
                    545:          zlog (NULL, LOG_WARNING, "can't set sockopt IPV6_V6ONLY "
                    546:                    "to socket %d", sock);
                    547:          return -1;
                    548:        }
                    549:       return 0;
                    550:     }
                    551: #endif /* IPV6_V6ONLY */
                    552: #endif /* HAVE_IPV6 */
                    553:   return 0;
                    554: }
                    555: 
1.1       misho     556: /* If same family and same prefix return 1. */
                    557: int
1.1.1.4 ! misho     558: sockunion_same (const union sockunion *su1, const union sockunion *su2)
1.1       misho     559: {
                    560:   int ret = 0;
                    561: 
                    562:   if (su1->sa.sa_family != su2->sa.sa_family)
                    563:     return 0;
                    564: 
                    565:   switch (su1->sa.sa_family)
                    566:     {
                    567:     case AF_INET:
                    568:       ret = memcmp (&su1->sin.sin_addr, &su2->sin.sin_addr,
                    569:                    sizeof (struct in_addr));
                    570:       break;
                    571: #ifdef HAVE_IPV6
                    572:     case AF_INET6:
                    573:       ret = memcmp (&su1->sin6.sin6_addr, &su2->sin6.sin6_addr,
                    574:                    sizeof (struct in6_addr));
                    575:       break;
                    576: #endif /* HAVE_IPV6 */
                    577:     }
                    578:   if (ret == 0)
                    579:     return 1;
                    580:   else
                    581:     return 0;
                    582: }
                    583: 
1.1.1.4 ! misho     584: unsigned int
        !           585: sockunion_hash (const union sockunion *su)
        !           586: {
        !           587:   switch (sockunion_family(su))
        !           588:     {
        !           589:     case AF_INET:
        !           590:       return jhash_1word(su->sin.sin_addr.s_addr, 0);
        !           591: #ifdef HAVE_IPV6
        !           592:     case AF_INET6:
        !           593:       return jhash2(su->sin6.sin6_addr.s6_addr32, ZEBRA_NUM_OF(su->sin6.sin6_addr.s6_addr32), 0);
        !           594: #endif /* HAVE_IPV6 */
        !           595:     }
        !           596:   return 0;
        !           597: }
        !           598: 
        !           599: size_t
        !           600: family2addrsize(int family)
        !           601: {
        !           602:   switch (family)
        !           603:     {
        !           604:     case AF_INET:
        !           605:       return sizeof(struct in_addr);
        !           606: #ifdef HAVE_IPV6
        !           607:     case AF_INET6:
        !           608:       return sizeof(struct in6_addr);
        !           609: #endif /* HAVE_IPV6 */
        !           610:     }
        !           611:   return 0;
        !           612: }
        !           613: 
        !           614: size_t
        !           615: sockunion_get_addrlen(const union sockunion *su)
        !           616: {
        !           617:   return family2addrsize(sockunion_family(su));
        !           618: }
        !           619: 
        !           620: const u_char *
        !           621: sockunion_get_addr(const union sockunion *su)
        !           622: {
        !           623:   switch (sockunion_family(su))
        !           624:     {
        !           625:     case AF_INET:
        !           626:       return (const u_char *) &su->sin.sin_addr.s_addr;
        !           627: #ifdef HAVE_IPV6
        !           628:     case AF_INET6:
        !           629:       return (const u_char *) &su->sin6.sin6_addr;
        !           630: #endif /* HAVE_IPV6 */
        !           631:     }
        !           632:   return NULL;
        !           633: }
        !           634: 
        !           635: void
        !           636: sockunion_set(union sockunion *su, int family, const u_char *addr, size_t bytes)
        !           637: {
        !           638:   if (family2addrsize(family) != bytes)
        !           639:     return;
        !           640: 
        !           641:   sockunion_family(su) = family;
        !           642:   switch (family)
        !           643:     {
        !           644:     case AF_INET:
        !           645:       memcpy(&su->sin.sin_addr.s_addr, addr, bytes);
        !           646:       break;
        !           647: #ifdef HAVE_IPV6
        !           648:     case AF_INET6:
        !           649:       memcpy(&su->sin6.sin6_addr, addr, bytes);
        !           650:       break;
        !           651: #endif /* HAVE_IPV6 */
        !           652:     }
        !           653: }
        !           654: 
1.1       misho     655: /* After TCP connection is established.  Get local address and port. */
                    656: union sockunion *
                    657: sockunion_getsockname (int fd)
                    658: {
                    659:   int ret;
                    660:   socklen_t len;
                    661:   union
                    662:   {
                    663:     struct sockaddr sa;
                    664:     struct sockaddr_in sin;
                    665: #ifdef HAVE_IPV6
                    666:     struct sockaddr_in6 sin6;
                    667: #endif /* HAVE_IPV6 */
                    668:     char tmp_buffer[128];
                    669:   } name;
                    670:   union sockunion *su;
                    671: 
                    672:   memset (&name, 0, sizeof name);
                    673:   len = sizeof name;
                    674: 
                    675:   ret = getsockname (fd, (struct sockaddr *)&name, &len);
                    676:   if (ret < 0)
                    677:     {
                    678:       zlog_warn ("Can't get local address and port by getsockname: %s",
                    679:                 safe_strerror (errno));
                    680:       return NULL;
                    681:     }
                    682: 
                    683:   if (name.sa.sa_family == AF_INET)
                    684:     {
                    685:       su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
                    686:       memcpy (su, &name, sizeof (struct sockaddr_in));
                    687:       return su;
                    688:     }
                    689: #ifdef HAVE_IPV6
                    690:   if (name.sa.sa_family == AF_INET6)
                    691:     {
                    692:       su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
                    693:       memcpy (su, &name, sizeof (struct sockaddr_in6));
                    694:       sockunion_normalise_mapped (su);
                    695:       return su;
                    696:     }
                    697: #endif /* HAVE_IPV6 */
                    698:   return NULL;
                    699: }
                    700: 
                    701: /* After TCP connection is established.  Get remote address and port. */
                    702: union sockunion *
                    703: sockunion_getpeername (int fd)
                    704: {
                    705:   int ret;
                    706:   socklen_t len;
                    707:   union
                    708:   {
                    709:     struct sockaddr sa;
                    710:     struct sockaddr_in sin;
                    711: #ifdef HAVE_IPV6
                    712:     struct sockaddr_in6 sin6;
                    713: #endif /* HAVE_IPV6 */
                    714:     char tmp_buffer[128];
                    715:   } name;
                    716:   union sockunion *su;
                    717: 
                    718:   memset (&name, 0, sizeof name);
                    719:   len = sizeof name;
                    720:   ret = getpeername (fd, (struct sockaddr *)&name, &len);
                    721:   if (ret < 0)
                    722:     {
                    723:       zlog (NULL, LOG_WARNING, "Can't get remote address and port: %s",
                    724:            safe_strerror (errno));
                    725:       return NULL;
                    726:     }
                    727: 
                    728:   if (name.sa.sa_family == AF_INET)
                    729:     {
                    730:       su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
                    731:       memcpy (su, &name, sizeof (struct sockaddr_in));
                    732:       return su;
                    733:     }
                    734: #ifdef HAVE_IPV6
                    735:   if (name.sa.sa_family == AF_INET6)
                    736:     {
                    737:       su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
                    738:       memcpy (su, &name, sizeof (struct sockaddr_in6));
                    739:       sockunion_normalise_mapped (su);
                    740:       return su;
                    741:     }
                    742: #endif /* HAVE_IPV6 */
                    743:   return NULL;
                    744: }
                    745: 
                    746: /* Print sockunion structure */
                    747: static void __attribute__ ((unused))
1.1.1.4 ! misho     748: sockunion_print (const union sockunion *su)
1.1       misho     749: {
                    750:   if (su == NULL)
                    751:     return;
                    752: 
                    753:   switch (su->sa.sa_family) 
                    754:     {
                    755:     case AF_INET:
                    756:       printf ("%s\n", inet_ntoa (su->sin.sin_addr));
                    757:       break;
                    758: #ifdef HAVE_IPV6
                    759:     case AF_INET6:
                    760:       {
                    761:        char buf [SU_ADDRSTRLEN];
                    762: 
                    763:        printf ("%s\n", inet_ntop (AF_INET6, &(su->sin6.sin6_addr),
                    764:                                 buf, sizeof (buf)));
                    765:       }
                    766:       break;
                    767: #endif /* HAVE_IPV6 */
                    768: 
                    769: #ifdef AF_LINK
                    770:     case AF_LINK:
                    771:       {
                    772:        struct sockaddr_dl *sdl;
                    773: 
                    774:        sdl = (struct sockaddr_dl *)&(su->sa);
                    775:        printf ("link#%d\n", sdl->sdl_index);
                    776:       }
                    777:       break;
                    778: #endif /* AF_LINK */
                    779:     default:
                    780:       printf ("af_unknown %d\n", su->sa.sa_family);
                    781:       break;
                    782:     }
                    783: }
                    784: 
                    785: #ifdef HAVE_IPV6
                    786: static int
1.1.1.4 ! misho     787: in6addr_cmp (const struct in6_addr *addr1, const struct in6_addr *addr2)
1.1       misho     788: {
                    789:   unsigned int i;
                    790:   u_char *p1, *p2;
                    791: 
                    792:   p1 = (u_char *)addr1;
                    793:   p2 = (u_char *)addr2;
                    794: 
                    795:   for (i = 0; i < sizeof (struct in6_addr); i++)
                    796:     {
                    797:       if (p1[i] > p2[i])
                    798:        return 1;
                    799:       else if (p1[i] < p2[i])
                    800:        return -1;
                    801:     }
                    802:   return 0;
                    803: }
                    804: #endif /* HAVE_IPV6 */
                    805: 
                    806: int
1.1.1.4 ! misho     807: sockunion_cmp (const union sockunion *su1, const union sockunion *su2)
1.1       misho     808: {
                    809:   if (su1->sa.sa_family > su2->sa.sa_family)
                    810:     return 1;
                    811:   if (su1->sa.sa_family < su2->sa.sa_family)
                    812:     return -1;
                    813: 
                    814:   if (su1->sa.sa_family == AF_INET)
                    815:     {
1.1.1.3   misho     816:       if (ntohl (sockunion2ip (su1)) == ntohl (sockunion2ip (su2)))
1.1       misho     817:        return 0;
1.1.1.3   misho     818:       if (ntohl (sockunion2ip (su1)) > ntohl (sockunion2ip (su2)))
1.1       misho     819:        return 1;
                    820:       else
                    821:        return -1;
                    822:     }
                    823: #ifdef HAVE_IPV6
                    824:   if (su1->sa.sa_family == AF_INET6)
                    825:     return in6addr_cmp (&su1->sin6.sin6_addr, &su2->sin6.sin6_addr);
                    826: #endif /* HAVE_IPV6 */
                    827:   return 0;
                    828: }
                    829: 
                    830: /* Duplicate sockunion. */
                    831: union sockunion *
1.1.1.4 ! misho     832: sockunion_dup (const union sockunion *su)
1.1       misho     833: {
                    834:   union sockunion *dup = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
                    835:   memcpy (dup, su, sizeof (union sockunion));
                    836:   return dup;
                    837: }
                    838: 
                    839: void
                    840: sockunion_free (union sockunion *su)
                    841: {
                    842:   XFREE (MTYPE_SOCKUNION, su);
                    843: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>