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

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. */
1.1.1.2 ! misho     300: static const char *
        !           301: sockunion_log (union sockunion *su, char *buf, size_t len)
1.1       misho     302: {
                    303:   switch (su->sa.sa_family) 
                    304:     {
                    305:     case AF_INET:
1.1.1.2 ! misho     306:       return inet_ntop(AF_INET, &su->sin.sin_addr, buf, len);
        !           307: 
1.1       misho     308: #ifdef HAVE_IPV6
                    309:     case AF_INET6:
1.1.1.2 ! misho     310:       return inet_ntop(AF_INET6, &(su->sin6.sin6_addr), buf, len);
1.1       misho     311:       break;
                    312: #endif /* HAVE_IPV6 */
1.1.1.2 ! misho     313: 
1.1       misho     314:     default:
1.1.1.2 ! misho     315:       snprintf (buf, len, "af_unknown %d ", su->sa.sa_family);
        !           316:       return buf;
1.1       misho     317:     }
                    318: }
                    319: 
                    320: /* sockunion_connect returns
                    321:    -1 : error occured
                    322:    0 : connect success
                    323:    1 : connect is in progress */
                    324: enum connect_result
                    325: sockunion_connect (int fd, union sockunion *peersu, unsigned short port,
                    326:                   unsigned int ifindex)
                    327: {
                    328:   int ret;
                    329:   int val;
                    330:   union sockunion su;
                    331: 
                    332:   memcpy (&su, peersu, sizeof (union sockunion));
                    333: 
                    334:   switch (su.sa.sa_family)
                    335:     {
                    336:     case AF_INET:
                    337:       su.sin.sin_port = port;
                    338:       break;
                    339: #ifdef HAVE_IPV6
                    340:     case AF_INET6:
                    341:       su.sin6.sin6_port  = port;
                    342: #ifdef KAME
                    343:       if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr) && ifindex)
                    344:        {
                    345: #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
                    346:          /* su.sin6.sin6_scope_id = ifindex; */
                    347: #ifdef MUSICA
                    348:          su.sin6.sin6_scope_id = ifindex; 
                    349: #endif
                    350: #endif /* HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID */
                    351: #ifndef MUSICA
                    352:          SET_IN6_LINKLOCAL_IFINDEX (su.sin6.sin6_addr, ifindex);
                    353: #endif
                    354:        }
                    355: #endif /* KAME */
                    356:       break;
                    357: #endif /* HAVE_IPV6 */
                    358:     }      
                    359: 
                    360:   /* Make socket non-block. */
                    361:   val = fcntl (fd, F_GETFL, 0);
                    362:   fcntl (fd, F_SETFL, val|O_NONBLOCK);
                    363: 
                    364:   /* Call connect function. */
                    365:   ret = connect (fd, (struct sockaddr *) &su, sockunion_sizeof (&su));
                    366: 
                    367:   /* Immediate success */
                    368:   if (ret == 0)
                    369:     {
                    370:       fcntl (fd, F_SETFL, val);
                    371:       return connect_success;
                    372:     }
                    373: 
                    374:   /* If connect is in progress then return 1 else it's real error. */
                    375:   if (ret < 0)
                    376:     {
                    377:       if (errno != EINPROGRESS)
                    378:        {
1.1.1.2 ! misho     379:          char str[SU_ADDRSTRLEN];
1.1       misho     380:          zlog_info ("can't connect to %s fd %d : %s",
1.1.1.2 ! misho     381:                     sockunion_log (&su, str, sizeof str),
        !           382:                     fd, safe_strerror (errno));
1.1       misho     383:          return connect_error;
                    384:        }
                    385:     }
                    386: 
                    387:   fcntl (fd, F_SETFL, val);
                    388: 
                    389:   return connect_in_progress;
                    390: }
                    391: 
                    392: /* Make socket from sockunion union. */
                    393: int
                    394: sockunion_stream_socket (union sockunion *su)
                    395: {
                    396:   int sock;
                    397: 
                    398:   if (su->sa.sa_family == 0)
                    399:     su->sa.sa_family = AF_INET_UNION;
                    400: 
                    401:   sock = socket (su->sa.sa_family, SOCK_STREAM, 0);
                    402: 
                    403:   if (sock < 0)
                    404:     zlog (NULL, LOG_WARNING, "can't make socket sockunion_stream_socket");
                    405: 
                    406:   return sock;
                    407: }
                    408: 
                    409: /* Bind socket to specified address. */
                    410: int
                    411: sockunion_bind (int sock, union sockunion *su, unsigned short port, 
                    412:                union sockunion *su_addr)
                    413: {
                    414:   int size = 0;
                    415:   int ret;
                    416: 
                    417:   if (su->sa.sa_family == AF_INET)
                    418:     {
                    419:       size = sizeof (struct sockaddr_in);
                    420:       su->sin.sin_port = htons (port);
                    421: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
                    422:       su->sin.sin_len = size;
                    423: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
                    424:       if (su_addr == NULL)
                    425:        su->sin.sin_addr.s_addr = htonl (INADDR_ANY);
                    426:     }
                    427: #ifdef HAVE_IPV6
                    428:   else if (su->sa.sa_family == AF_INET6)
                    429:     {
                    430:       size = sizeof (struct sockaddr_in6);
                    431:       su->sin6.sin6_port = htons (port);
                    432: #ifdef SIN6_LEN
                    433:       su->sin6.sin6_len = size;
                    434: #endif /* SIN6_LEN */
                    435:       if (su_addr == NULL)
                    436:        {
                    437: #if defined(LINUX_IPV6) || defined(NRL)
                    438:          memset (&su->sin6.sin6_addr, 0, sizeof (struct in6_addr));
                    439: #else
                    440:          su->sin6.sin6_addr = in6addr_any;
                    441: #endif /* LINUX_IPV6 */
                    442:        }
                    443:     }
                    444: #endif /* HAVE_IPV6 */
                    445:   
                    446: 
                    447:   ret = bind (sock, (struct sockaddr *)su, size);
                    448:   if (ret < 0)
                    449:     zlog (NULL, LOG_WARNING, "can't bind socket : %s", safe_strerror (errno));
                    450: 
                    451:   return ret;
                    452: }
                    453: 
                    454: int
                    455: sockopt_reuseaddr (int sock)
                    456: {
                    457:   int ret;
                    458:   int on = 1;
                    459: 
                    460:   ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, 
                    461:                    (void *) &on, sizeof (on));
                    462:   if (ret < 0)
                    463:     {
                    464:       zlog (NULL, LOG_WARNING, "can't set sockopt SO_REUSEADDR to socket %d", sock);
                    465:       return -1;
                    466:     }
                    467:   return 0;
                    468: }
                    469: 
                    470: #ifdef SO_REUSEPORT
                    471: int
                    472: sockopt_reuseport (int sock)
                    473: {
                    474:   int ret;
                    475:   int on = 1;
                    476: 
                    477:   ret = setsockopt (sock, SOL_SOCKET, SO_REUSEPORT, 
                    478:                    (void *) &on, sizeof (on));
                    479:   if (ret < 0)
                    480:     {
                    481:       zlog (NULL, LOG_WARNING, "can't set sockopt SO_REUSEPORT to socket %d", sock);
                    482:       return -1;
                    483:     }
                    484:   return 0;
                    485: }
                    486: #else
                    487: int
                    488: sockopt_reuseport (int sock)
                    489: {
                    490:   return 0;
                    491: }
                    492: #endif /* 0 */
                    493: 
                    494: int
                    495: sockopt_ttl (int family, int sock, int ttl)
                    496: {
                    497:   int ret;
                    498: 
                    499: #ifdef IP_TTL
                    500:   if (family == AF_INET)
                    501:     {
                    502:       ret = setsockopt (sock, IPPROTO_IP, IP_TTL, 
                    503:                        (void *) &ttl, sizeof (int));
                    504:       if (ret < 0)
                    505:        {
                    506:          zlog (NULL, LOG_WARNING, "can't set sockopt IP_TTL %d to socket %d", ttl, sock);
                    507:          return -1;
                    508:        }
                    509:       return 0;
                    510:     }
                    511: #endif /* IP_TTL */
                    512: #ifdef HAVE_IPV6
                    513:   if (family == AF_INET6)
                    514:     {
                    515:       ret = setsockopt (sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 
                    516:                        (void *) &ttl, sizeof (int));
                    517:       if (ret < 0)
                    518:        {
                    519:          zlog (NULL, LOG_WARNING, "can't set sockopt IPV6_UNICAST_HOPS %d to socket %d",
                    520:                    ttl, sock);
                    521:          return -1;
                    522:        }
                    523:       return 0;
                    524:     }
                    525: #endif /* HAVE_IPV6 */
                    526:   return 0;
                    527: }
                    528: 
                    529: int
                    530: sockopt_cork (int sock, int onoff)
                    531: {
                    532: #ifdef TCP_CORK
                    533:   return setsockopt (sock, IPPROTO_TCP, TCP_CORK, &onoff, sizeof(onoff));
                    534: #else
                    535:   return 0;
                    536: #endif
                    537: }
                    538: 
                    539: int
                    540: sockopt_minttl (int family, int sock, int minttl)
                    541: {
                    542: #ifdef IP_MINTTL
                    543:   if (family == AF_INET)
                    544:     {
                    545:       int ret = setsockopt (sock, IPPROTO_IP, IP_MINTTL, &minttl, sizeof(minttl));
                    546:       if (ret < 0)
                    547:          zlog (NULL, LOG_WARNING,
                    548:                "can't set sockopt IP_MINTTL to %d on socket %d: %s",
                    549:                minttl, sock, safe_strerror (errno));
                    550:       return ret;
                    551:     }
                    552: #endif /* IP_MINTTL */
                    553: #ifdef IPV6_MINHOPCNT
                    554:   if (family == AF_INET6)
                    555:     {
                    556:       int ret = setsockopt (sock, IPPROTO_IPV6, IPV6_MINHOPCNT, &minttl, sizeof(minttl));
                    557:       if (ret < 0)
                    558:          zlog (NULL, LOG_WARNING,
                    559:                "can't set sockopt IPV6_MINHOPCNT to %d on socket %d: %s",
                    560:                minttl, sock, safe_strerror (errno));
                    561:       return ret;
                    562:     }
                    563: #endif
                    564: 
                    565:   errno = EOPNOTSUPP;
                    566:   return -1;
                    567: }
                    568: 
1.1.1.2 ! misho     569: int
        !           570: sockopt_v6only (int family, int sock)
        !           571: {
        !           572:   int ret, on = 1;
        !           573: 
        !           574: #ifdef HAVE_IPV6
        !           575: #ifdef IPV6_V6ONLY
        !           576:   if (family == AF_INET6)
        !           577:     {
        !           578:       ret = setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY,
        !           579:                        (void *) &on, sizeof (int));
        !           580:       if (ret < 0)
        !           581:        {
        !           582:          zlog (NULL, LOG_WARNING, "can't set sockopt IPV6_V6ONLY "
        !           583:                    "to socket %d", sock);
        !           584:          return -1;
        !           585:        }
        !           586:       return 0;
        !           587:     }
        !           588: #endif /* IPV6_V6ONLY */
        !           589: #endif /* HAVE_IPV6 */
        !           590:   return 0;
        !           591: }
        !           592: 
1.1       misho     593: /* If same family and same prefix return 1. */
                    594: int
                    595: sockunion_same (union sockunion *su1, union sockunion *su2)
                    596: {
                    597:   int ret = 0;
                    598: 
                    599:   if (su1->sa.sa_family != su2->sa.sa_family)
                    600:     return 0;
                    601: 
                    602:   switch (su1->sa.sa_family)
                    603:     {
                    604:     case AF_INET:
                    605:       ret = memcmp (&su1->sin.sin_addr, &su2->sin.sin_addr,
                    606:                    sizeof (struct in_addr));
                    607:       break;
                    608: #ifdef HAVE_IPV6
                    609:     case AF_INET6:
                    610:       ret = memcmp (&su1->sin6.sin6_addr, &su2->sin6.sin6_addr,
                    611:                    sizeof (struct in6_addr));
                    612:       break;
                    613: #endif /* HAVE_IPV6 */
                    614:     }
                    615:   if (ret == 0)
                    616:     return 1;
                    617:   else
                    618:     return 0;
                    619: }
                    620: 
                    621: /* After TCP connection is established.  Get local address and port. */
                    622: union sockunion *
                    623: sockunion_getsockname (int fd)
                    624: {
                    625:   int ret;
                    626:   socklen_t len;
                    627:   union
                    628:   {
                    629:     struct sockaddr sa;
                    630:     struct sockaddr_in sin;
                    631: #ifdef HAVE_IPV6
                    632:     struct sockaddr_in6 sin6;
                    633: #endif /* HAVE_IPV6 */
                    634:     char tmp_buffer[128];
                    635:   } name;
                    636:   union sockunion *su;
                    637: 
                    638:   memset (&name, 0, sizeof name);
                    639:   len = sizeof name;
                    640: 
                    641:   ret = getsockname (fd, (struct sockaddr *)&name, &len);
                    642:   if (ret < 0)
                    643:     {
                    644:       zlog_warn ("Can't get local address and port by getsockname: %s",
                    645:                 safe_strerror (errno));
                    646:       return NULL;
                    647:     }
                    648: 
                    649:   if (name.sa.sa_family == AF_INET)
                    650:     {
                    651:       su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
                    652:       memcpy (su, &name, sizeof (struct sockaddr_in));
                    653:       return su;
                    654:     }
                    655: #ifdef HAVE_IPV6
                    656:   if (name.sa.sa_family == AF_INET6)
                    657:     {
                    658:       su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
                    659:       memcpy (su, &name, sizeof (struct sockaddr_in6));
                    660:       sockunion_normalise_mapped (su);
                    661:       return su;
                    662:     }
                    663: #endif /* HAVE_IPV6 */
                    664:   return NULL;
                    665: }
                    666: 
                    667: /* After TCP connection is established.  Get remote address and port. */
                    668: union sockunion *
                    669: sockunion_getpeername (int fd)
                    670: {
                    671:   int ret;
                    672:   socklen_t len;
                    673:   union
                    674:   {
                    675:     struct sockaddr sa;
                    676:     struct sockaddr_in sin;
                    677: #ifdef HAVE_IPV6
                    678:     struct sockaddr_in6 sin6;
                    679: #endif /* HAVE_IPV6 */
                    680:     char tmp_buffer[128];
                    681:   } name;
                    682:   union sockunion *su;
                    683: 
                    684:   memset (&name, 0, sizeof name);
                    685:   len = sizeof name;
                    686:   ret = getpeername (fd, (struct sockaddr *)&name, &len);
                    687:   if (ret < 0)
                    688:     {
                    689:       zlog (NULL, LOG_WARNING, "Can't get remote address and port: %s",
                    690:            safe_strerror (errno));
                    691:       return NULL;
                    692:     }
                    693: 
                    694:   if (name.sa.sa_family == AF_INET)
                    695:     {
                    696:       su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
                    697:       memcpy (su, &name, sizeof (struct sockaddr_in));
                    698:       return su;
                    699:     }
                    700: #ifdef HAVE_IPV6
                    701:   if (name.sa.sa_family == AF_INET6)
                    702:     {
                    703:       su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
                    704:       memcpy (su, &name, sizeof (struct sockaddr_in6));
                    705:       sockunion_normalise_mapped (su);
                    706:       return su;
                    707:     }
                    708: #endif /* HAVE_IPV6 */
                    709:   return NULL;
                    710: }
                    711: 
                    712: /* Print sockunion structure */
                    713: static void __attribute__ ((unused))
                    714: sockunion_print (union sockunion *su)
                    715: {
                    716:   if (su == NULL)
                    717:     return;
                    718: 
                    719:   switch (su->sa.sa_family) 
                    720:     {
                    721:     case AF_INET:
                    722:       printf ("%s\n", inet_ntoa (su->sin.sin_addr));
                    723:       break;
                    724: #ifdef HAVE_IPV6
                    725:     case AF_INET6:
                    726:       {
                    727:        char buf [SU_ADDRSTRLEN];
                    728: 
                    729:        printf ("%s\n", inet_ntop (AF_INET6, &(su->sin6.sin6_addr),
                    730:                                 buf, sizeof (buf)));
                    731:       }
                    732:       break;
                    733: #endif /* HAVE_IPV6 */
                    734: 
                    735: #ifdef AF_LINK
                    736:     case AF_LINK:
                    737:       {
                    738:        struct sockaddr_dl *sdl;
                    739: 
                    740:        sdl = (struct sockaddr_dl *)&(su->sa);
                    741:        printf ("link#%d\n", sdl->sdl_index);
                    742:       }
                    743:       break;
                    744: #endif /* AF_LINK */
                    745:     default:
                    746:       printf ("af_unknown %d\n", su->sa.sa_family);
                    747:       break;
                    748:     }
                    749: }
                    750: 
                    751: #ifdef HAVE_IPV6
                    752: static int
                    753: in6addr_cmp (struct in6_addr *addr1, struct in6_addr *addr2)
                    754: {
                    755:   unsigned int i;
                    756:   u_char *p1, *p2;
                    757: 
                    758:   p1 = (u_char *)addr1;
                    759:   p2 = (u_char *)addr2;
                    760: 
                    761:   for (i = 0; i < sizeof (struct in6_addr); i++)
                    762:     {
                    763:       if (p1[i] > p2[i])
                    764:        return 1;
                    765:       else if (p1[i] < p2[i])
                    766:        return -1;
                    767:     }
                    768:   return 0;
                    769: }
                    770: #endif /* HAVE_IPV6 */
                    771: 
                    772: int
                    773: sockunion_cmp (union sockunion *su1, union sockunion *su2)
                    774: {
                    775:   if (su1->sa.sa_family > su2->sa.sa_family)
                    776:     return 1;
                    777:   if (su1->sa.sa_family < su2->sa.sa_family)
                    778:     return -1;
                    779: 
                    780:   if (su1->sa.sa_family == AF_INET)
                    781:     {
                    782:       if (ntohl (su1->sin.sin_addr.s_addr) == ntohl (su2->sin.sin_addr.s_addr))
                    783:        return 0;
                    784:       if (ntohl (su1->sin.sin_addr.s_addr) > ntohl (su2->sin.sin_addr.s_addr))
                    785:        return 1;
                    786:       else
                    787:        return -1;
                    788:     }
                    789: #ifdef HAVE_IPV6
                    790:   if (su1->sa.sa_family == AF_INET6)
                    791:     return in6addr_cmp (&su1->sin6.sin6_addr, &su2->sin6.sin6_addr);
                    792: #endif /* HAVE_IPV6 */
                    793:   return 0;
                    794: }
                    795: 
                    796: /* Duplicate sockunion. */
                    797: union sockunion *
                    798: sockunion_dup (union sockunion *su)
                    799: {
                    800:   union sockunion *dup = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
                    801:   memcpy (dup, su, sizeof (union sockunion));
                    802:   return dup;
                    803: }
                    804: 
                    805: void
                    806: sockunion_free (union sockunion *su)
                    807: {
                    808:   XFREE (MTYPE_SOCKUNION, su);
                    809: }

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