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

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

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