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

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: {
1.1.1.3 ! misho     180:   union sockunion *su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
        !           181:   
        !           182:   if (!str2sockunion (str, su))
        !           183:     return su;
        !           184:   
1.1       misho     185:   XFREE (MTYPE_SOCKUNION, su);
                    186:   return NULL;
                    187: }
                    188: 
                    189: /* Convert IPv4 compatible IPv6 address to IPv4 address. */
                    190: static void
                    191: sockunion_normalise_mapped (union sockunion *su)
                    192: {
                    193:   struct sockaddr_in sin;
                    194:   
                    195: #ifdef HAVE_IPV6
                    196:   if (su->sa.sa_family == AF_INET6 
                    197:       && IN6_IS_ADDR_V4MAPPED (&su->sin6.sin6_addr))
                    198:     {
                    199:       memset (&sin, 0, sizeof (struct sockaddr_in));
                    200:       sin.sin_family = AF_INET;
                    201:       sin.sin_port = su->sin6.sin6_port;
                    202:       memcpy (&sin.sin_addr, ((char *)&su->sin6.sin6_addr) + 12, 4);
                    203:       memcpy (su, &sin, sizeof (struct sockaddr_in));
                    204:     }
                    205: #endif /* HAVE_IPV6 */
                    206: }
                    207: 
                    208: /* Return socket of sockunion. */
                    209: int
                    210: sockunion_socket (union sockunion *su)
                    211: {
                    212:   int sock;
                    213: 
                    214:   sock = socket (su->sa.sa_family, SOCK_STREAM, 0);
                    215:   if (sock < 0)
                    216:     {
                    217:       zlog (NULL, LOG_WARNING, "Can't make socket : %s", safe_strerror (errno));
                    218:       return -1;
                    219:     }
                    220: 
                    221:   return sock;
                    222: }
                    223: 
                    224: /* Return accepted new socket file descriptor. */
                    225: int
                    226: sockunion_accept (int sock, union sockunion *su)
                    227: {
                    228:   socklen_t len;
                    229:   int client_sock;
                    230: 
                    231:   len = sizeof (union sockunion);
                    232:   client_sock = accept (sock, (struct sockaddr *) su, &len);
                    233:   
                    234:   sockunion_normalise_mapped (su);
                    235:   return client_sock;
                    236: }
                    237: 
                    238: /* Return sizeof union sockunion.  */
                    239: static int
                    240: sockunion_sizeof (union sockunion *su)
                    241: {
                    242:   int ret;
                    243: 
                    244:   ret = 0;
                    245:   switch (su->sa.sa_family)
                    246:     {
                    247:     case AF_INET:
                    248:       ret = sizeof (struct sockaddr_in);
                    249:       break;
                    250: #ifdef HAVE_IPV6
                    251:     case AF_INET6:
                    252:       ret = sizeof (struct sockaddr_in6);
                    253:       break;
                    254: #endif /* AF_INET6 */
                    255:     }
                    256:   return ret;
                    257: }
                    258: 
                    259: /* return sockunion structure : this function should be revised. */
1.1.1.2   misho     260: static const char *
                    261: sockunion_log (union sockunion *su, char *buf, size_t len)
1.1       misho     262: {
                    263:   switch (su->sa.sa_family) 
                    264:     {
                    265:     case AF_INET:
1.1.1.2   misho     266:       return inet_ntop(AF_INET, &su->sin.sin_addr, buf, len);
                    267: 
1.1       misho     268: #ifdef HAVE_IPV6
                    269:     case AF_INET6:
1.1.1.2   misho     270:       return inet_ntop(AF_INET6, &(su->sin6.sin6_addr), buf, len);
1.1       misho     271:       break;
                    272: #endif /* HAVE_IPV6 */
1.1.1.2   misho     273: 
1.1       misho     274:     default:
1.1.1.2   misho     275:       snprintf (buf, len, "af_unknown %d ", su->sa.sa_family);
                    276:       return buf;
1.1       misho     277:     }
                    278: }
                    279: 
                    280: /* sockunion_connect returns
                    281:    -1 : error occured
                    282:    0 : connect success
                    283:    1 : connect is in progress */
                    284: enum connect_result
                    285: sockunion_connect (int fd, union sockunion *peersu, unsigned short port,
                    286:                   unsigned int ifindex)
                    287: {
                    288:   int ret;
                    289:   int val;
                    290:   union sockunion su;
                    291: 
                    292:   memcpy (&su, peersu, sizeof (union sockunion));
                    293: 
                    294:   switch (su.sa.sa_family)
                    295:     {
                    296:     case AF_INET:
                    297:       su.sin.sin_port = port;
                    298:       break;
                    299: #ifdef HAVE_IPV6
                    300:     case AF_INET6:
                    301:       su.sin6.sin6_port  = port;
                    302: #ifdef KAME
                    303:       if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr) && ifindex)
                    304:        {
                    305: #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
                    306:          /* su.sin6.sin6_scope_id = ifindex; */
                    307: #ifdef MUSICA
                    308:          su.sin6.sin6_scope_id = ifindex; 
                    309: #endif
                    310: #endif /* HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID */
                    311: #ifndef MUSICA
                    312:          SET_IN6_LINKLOCAL_IFINDEX (su.sin6.sin6_addr, ifindex);
                    313: #endif
                    314:        }
                    315: #endif /* KAME */
                    316:       break;
                    317: #endif /* HAVE_IPV6 */
                    318:     }      
                    319: 
                    320:   /* Make socket non-block. */
                    321:   val = fcntl (fd, F_GETFL, 0);
                    322:   fcntl (fd, F_SETFL, val|O_NONBLOCK);
                    323: 
                    324:   /* Call connect function. */
                    325:   ret = connect (fd, (struct sockaddr *) &su, sockunion_sizeof (&su));
                    326: 
                    327:   /* Immediate success */
                    328:   if (ret == 0)
                    329:     {
                    330:       fcntl (fd, F_SETFL, val);
                    331:       return connect_success;
                    332:     }
                    333: 
                    334:   /* If connect is in progress then return 1 else it's real error. */
                    335:   if (ret < 0)
                    336:     {
                    337:       if (errno != EINPROGRESS)
                    338:        {
1.1.1.2   misho     339:          char str[SU_ADDRSTRLEN];
1.1       misho     340:          zlog_info ("can't connect to %s fd %d : %s",
1.1.1.2   misho     341:                     sockunion_log (&su, str, sizeof str),
                    342:                     fd, safe_strerror (errno));
1.1       misho     343:          return connect_error;
                    344:        }
                    345:     }
                    346: 
                    347:   fcntl (fd, F_SETFL, val);
                    348: 
                    349:   return connect_in_progress;
                    350: }
                    351: 
                    352: /* Make socket from sockunion union. */
                    353: int
                    354: sockunion_stream_socket (union sockunion *su)
                    355: {
                    356:   int sock;
                    357: 
                    358:   if (su->sa.sa_family == 0)
                    359:     su->sa.sa_family = AF_INET_UNION;
                    360: 
                    361:   sock = socket (su->sa.sa_family, SOCK_STREAM, 0);
                    362: 
                    363:   if (sock < 0)
                    364:     zlog (NULL, LOG_WARNING, "can't make socket sockunion_stream_socket");
                    365: 
                    366:   return sock;
                    367: }
                    368: 
                    369: /* Bind socket to specified address. */
                    370: int
                    371: sockunion_bind (int sock, union sockunion *su, unsigned short port, 
                    372:                union sockunion *su_addr)
                    373: {
                    374:   int size = 0;
                    375:   int ret;
                    376: 
                    377:   if (su->sa.sa_family == AF_INET)
                    378:     {
                    379:       size = sizeof (struct sockaddr_in);
                    380:       su->sin.sin_port = htons (port);
                    381: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
                    382:       su->sin.sin_len = size;
                    383: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
                    384:       if (su_addr == NULL)
1.1.1.3 ! misho     385:        sockunion2ip (su) = htonl (INADDR_ANY);
1.1       misho     386:     }
                    387: #ifdef HAVE_IPV6
                    388:   else if (su->sa.sa_family == AF_INET6)
                    389:     {
                    390:       size = sizeof (struct sockaddr_in6);
                    391:       su->sin6.sin6_port = htons (port);
                    392: #ifdef SIN6_LEN
                    393:       su->sin6.sin6_len = size;
                    394: #endif /* SIN6_LEN */
                    395:       if (su_addr == NULL)
                    396:        {
                    397: #if defined(LINUX_IPV6) || defined(NRL)
                    398:          memset (&su->sin6.sin6_addr, 0, sizeof (struct in6_addr));
                    399: #else
                    400:          su->sin6.sin6_addr = in6addr_any;
                    401: #endif /* LINUX_IPV6 */
                    402:        }
                    403:     }
                    404: #endif /* HAVE_IPV6 */
                    405:   
                    406: 
                    407:   ret = bind (sock, (struct sockaddr *)su, size);
                    408:   if (ret < 0)
                    409:     zlog (NULL, LOG_WARNING, "can't bind socket : %s", safe_strerror (errno));
                    410: 
                    411:   return ret;
                    412: }
                    413: 
                    414: int
                    415: sockopt_reuseaddr (int sock)
                    416: {
                    417:   int ret;
                    418:   int on = 1;
                    419: 
                    420:   ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, 
                    421:                    (void *) &on, sizeof (on));
                    422:   if (ret < 0)
                    423:     {
                    424:       zlog (NULL, LOG_WARNING, "can't set sockopt SO_REUSEADDR to socket %d", sock);
                    425:       return -1;
                    426:     }
                    427:   return 0;
                    428: }
                    429: 
                    430: #ifdef SO_REUSEPORT
                    431: int
                    432: sockopt_reuseport (int sock)
                    433: {
                    434:   int ret;
                    435:   int on = 1;
                    436: 
                    437:   ret = setsockopt (sock, SOL_SOCKET, SO_REUSEPORT, 
                    438:                    (void *) &on, sizeof (on));
                    439:   if (ret < 0)
                    440:     {
                    441:       zlog (NULL, LOG_WARNING, "can't set sockopt SO_REUSEPORT to socket %d", sock);
                    442:       return -1;
                    443:     }
                    444:   return 0;
                    445: }
                    446: #else
                    447: int
                    448: sockopt_reuseport (int sock)
                    449: {
                    450:   return 0;
                    451: }
                    452: #endif /* 0 */
                    453: 
                    454: int
                    455: sockopt_ttl (int family, int sock, int ttl)
                    456: {
                    457:   int ret;
                    458: 
                    459: #ifdef IP_TTL
                    460:   if (family == AF_INET)
                    461:     {
                    462:       ret = setsockopt (sock, IPPROTO_IP, IP_TTL, 
                    463:                        (void *) &ttl, sizeof (int));
                    464:       if (ret < 0)
                    465:        {
                    466:          zlog (NULL, LOG_WARNING, "can't set sockopt IP_TTL %d to socket %d", ttl, sock);
                    467:          return -1;
                    468:        }
                    469:       return 0;
                    470:     }
                    471: #endif /* IP_TTL */
                    472: #ifdef HAVE_IPV6
                    473:   if (family == AF_INET6)
                    474:     {
                    475:       ret = setsockopt (sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 
                    476:                        (void *) &ttl, sizeof (int));
                    477:       if (ret < 0)
                    478:        {
                    479:          zlog (NULL, LOG_WARNING, "can't set sockopt IPV6_UNICAST_HOPS %d to socket %d",
                    480:                    ttl, sock);
                    481:          return -1;
                    482:        }
                    483:       return 0;
                    484:     }
                    485: #endif /* HAVE_IPV6 */
                    486:   return 0;
                    487: }
                    488: 
                    489: int
                    490: sockopt_cork (int sock, int onoff)
                    491: {
                    492: #ifdef TCP_CORK
                    493:   return setsockopt (sock, IPPROTO_TCP, TCP_CORK, &onoff, sizeof(onoff));
                    494: #else
                    495:   return 0;
                    496: #endif
                    497: }
                    498: 
                    499: int
                    500: sockopt_minttl (int family, int sock, int minttl)
                    501: {
                    502: #ifdef IP_MINTTL
                    503:   if (family == AF_INET)
                    504:     {
                    505:       int ret = setsockopt (sock, IPPROTO_IP, IP_MINTTL, &minttl, sizeof(minttl));
                    506:       if (ret < 0)
                    507:          zlog (NULL, LOG_WARNING,
                    508:                "can't set sockopt IP_MINTTL to %d on socket %d: %s",
                    509:                minttl, sock, safe_strerror (errno));
                    510:       return ret;
                    511:     }
                    512: #endif /* IP_MINTTL */
                    513: #ifdef IPV6_MINHOPCNT
                    514:   if (family == AF_INET6)
                    515:     {
                    516:       int ret = setsockopt (sock, IPPROTO_IPV6, IPV6_MINHOPCNT, &minttl, sizeof(minttl));
                    517:       if (ret < 0)
                    518:          zlog (NULL, LOG_WARNING,
                    519:                "can't set sockopt IPV6_MINHOPCNT to %d on socket %d: %s",
                    520:                minttl, sock, safe_strerror (errno));
                    521:       return ret;
                    522:     }
                    523: #endif
                    524: 
                    525:   errno = EOPNOTSUPP;
                    526:   return -1;
                    527: }
                    528: 
1.1.1.2   misho     529: int
                    530: sockopt_v6only (int family, int sock)
                    531: {
                    532:   int ret, on = 1;
                    533: 
                    534: #ifdef HAVE_IPV6
                    535: #ifdef IPV6_V6ONLY
                    536:   if (family == AF_INET6)
                    537:     {
                    538:       ret = setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY,
                    539:                        (void *) &on, sizeof (int));
                    540:       if (ret < 0)
                    541:        {
                    542:          zlog (NULL, LOG_WARNING, "can't set sockopt IPV6_V6ONLY "
                    543:                    "to socket %d", sock);
                    544:          return -1;
                    545:        }
                    546:       return 0;
                    547:     }
                    548: #endif /* IPV6_V6ONLY */
                    549: #endif /* HAVE_IPV6 */
                    550:   return 0;
                    551: }
                    552: 
1.1       misho     553: /* If same family and same prefix return 1. */
                    554: int
                    555: sockunion_same (union sockunion *su1, union sockunion *su2)
                    556: {
                    557:   int ret = 0;
                    558: 
                    559:   if (su1->sa.sa_family != su2->sa.sa_family)
                    560:     return 0;
                    561: 
                    562:   switch (su1->sa.sa_family)
                    563:     {
                    564:     case AF_INET:
                    565:       ret = memcmp (&su1->sin.sin_addr, &su2->sin.sin_addr,
                    566:                    sizeof (struct in_addr));
                    567:       break;
                    568: #ifdef HAVE_IPV6
                    569:     case AF_INET6:
                    570:       ret = memcmp (&su1->sin6.sin6_addr, &su2->sin6.sin6_addr,
                    571:                    sizeof (struct in6_addr));
                    572:       break;
                    573: #endif /* HAVE_IPV6 */
                    574:     }
                    575:   if (ret == 0)
                    576:     return 1;
                    577:   else
                    578:     return 0;
                    579: }
                    580: 
                    581: /* After TCP connection is established.  Get local address and port. */
                    582: union sockunion *
                    583: sockunion_getsockname (int fd)
                    584: {
                    585:   int ret;
                    586:   socklen_t len;
                    587:   union
                    588:   {
                    589:     struct sockaddr sa;
                    590:     struct sockaddr_in sin;
                    591: #ifdef HAVE_IPV6
                    592:     struct sockaddr_in6 sin6;
                    593: #endif /* HAVE_IPV6 */
                    594:     char tmp_buffer[128];
                    595:   } name;
                    596:   union sockunion *su;
                    597: 
                    598:   memset (&name, 0, sizeof name);
                    599:   len = sizeof name;
                    600: 
                    601:   ret = getsockname (fd, (struct sockaddr *)&name, &len);
                    602:   if (ret < 0)
                    603:     {
                    604:       zlog_warn ("Can't get local address and port by getsockname: %s",
                    605:                 safe_strerror (errno));
                    606:       return NULL;
                    607:     }
                    608: 
                    609:   if (name.sa.sa_family == AF_INET)
                    610:     {
                    611:       su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
                    612:       memcpy (su, &name, sizeof (struct sockaddr_in));
                    613:       return su;
                    614:     }
                    615: #ifdef HAVE_IPV6
                    616:   if (name.sa.sa_family == AF_INET6)
                    617:     {
                    618:       su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
                    619:       memcpy (su, &name, sizeof (struct sockaddr_in6));
                    620:       sockunion_normalise_mapped (su);
                    621:       return su;
                    622:     }
                    623: #endif /* HAVE_IPV6 */
                    624:   return NULL;
                    625: }
                    626: 
                    627: /* After TCP connection is established.  Get remote address and port. */
                    628: union sockunion *
                    629: sockunion_getpeername (int fd)
                    630: {
                    631:   int ret;
                    632:   socklen_t len;
                    633:   union
                    634:   {
                    635:     struct sockaddr sa;
                    636:     struct sockaddr_in sin;
                    637: #ifdef HAVE_IPV6
                    638:     struct sockaddr_in6 sin6;
                    639: #endif /* HAVE_IPV6 */
                    640:     char tmp_buffer[128];
                    641:   } name;
                    642:   union sockunion *su;
                    643: 
                    644:   memset (&name, 0, sizeof name);
                    645:   len = sizeof name;
                    646:   ret = getpeername (fd, (struct sockaddr *)&name, &len);
                    647:   if (ret < 0)
                    648:     {
                    649:       zlog (NULL, LOG_WARNING, "Can't get remote address and port: %s",
                    650:            safe_strerror (errno));
                    651:       return NULL;
                    652:     }
                    653: 
                    654:   if (name.sa.sa_family == AF_INET)
                    655:     {
                    656:       su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
                    657:       memcpy (su, &name, sizeof (struct sockaddr_in));
                    658:       return su;
                    659:     }
                    660: #ifdef HAVE_IPV6
                    661:   if (name.sa.sa_family == AF_INET6)
                    662:     {
                    663:       su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
                    664:       memcpy (su, &name, sizeof (struct sockaddr_in6));
                    665:       sockunion_normalise_mapped (su);
                    666:       return su;
                    667:     }
                    668: #endif /* HAVE_IPV6 */
                    669:   return NULL;
                    670: }
                    671: 
                    672: /* Print sockunion structure */
                    673: static void __attribute__ ((unused))
                    674: sockunion_print (union sockunion *su)
                    675: {
                    676:   if (su == NULL)
                    677:     return;
                    678: 
                    679:   switch (su->sa.sa_family) 
                    680:     {
                    681:     case AF_INET:
                    682:       printf ("%s\n", inet_ntoa (su->sin.sin_addr));
                    683:       break;
                    684: #ifdef HAVE_IPV6
                    685:     case AF_INET6:
                    686:       {
                    687:        char buf [SU_ADDRSTRLEN];
                    688: 
                    689:        printf ("%s\n", inet_ntop (AF_INET6, &(su->sin6.sin6_addr),
                    690:                                 buf, sizeof (buf)));
                    691:       }
                    692:       break;
                    693: #endif /* HAVE_IPV6 */
                    694: 
                    695: #ifdef AF_LINK
                    696:     case AF_LINK:
                    697:       {
                    698:        struct sockaddr_dl *sdl;
                    699: 
                    700:        sdl = (struct sockaddr_dl *)&(su->sa);
                    701:        printf ("link#%d\n", sdl->sdl_index);
                    702:       }
                    703:       break;
                    704: #endif /* AF_LINK */
                    705:     default:
                    706:       printf ("af_unknown %d\n", su->sa.sa_family);
                    707:       break;
                    708:     }
                    709: }
                    710: 
                    711: #ifdef HAVE_IPV6
                    712: static int
                    713: in6addr_cmp (struct in6_addr *addr1, struct in6_addr *addr2)
                    714: {
                    715:   unsigned int i;
                    716:   u_char *p1, *p2;
                    717: 
                    718:   p1 = (u_char *)addr1;
                    719:   p2 = (u_char *)addr2;
                    720: 
                    721:   for (i = 0; i < sizeof (struct in6_addr); i++)
                    722:     {
                    723:       if (p1[i] > p2[i])
                    724:        return 1;
                    725:       else if (p1[i] < p2[i])
                    726:        return -1;
                    727:     }
                    728:   return 0;
                    729: }
                    730: #endif /* HAVE_IPV6 */
                    731: 
                    732: int
                    733: sockunion_cmp (union sockunion *su1, union sockunion *su2)
                    734: {
                    735:   if (su1->sa.sa_family > su2->sa.sa_family)
                    736:     return 1;
                    737:   if (su1->sa.sa_family < su2->sa.sa_family)
                    738:     return -1;
                    739: 
                    740:   if (su1->sa.sa_family == AF_INET)
                    741:     {
1.1.1.3 ! misho     742:       if (ntohl (sockunion2ip (su1)) == ntohl (sockunion2ip (su2)))
1.1       misho     743:        return 0;
1.1.1.3 ! misho     744:       if (ntohl (sockunion2ip (su1)) > ntohl (sockunion2ip (su2)))
1.1       misho     745:        return 1;
                    746:       else
                    747:        return -1;
                    748:     }
                    749: #ifdef HAVE_IPV6
                    750:   if (su1->sa.sa_family == AF_INET6)
                    751:     return in6addr_cmp (&su1->sin6.sin6_addr, &su2->sin6.sin6_addr);
                    752: #endif /* HAVE_IPV6 */
                    753:   return 0;
                    754: }
                    755: 
                    756: /* Duplicate sockunion. */
                    757: union sockunion *
                    758: sockunion_dup (union sockunion *su)
                    759: {
                    760:   union sockunion *dup = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
                    761:   memcpy (dup, su, sizeof (union sockunion));
                    762:   return dup;
                    763: }
                    764: 
                    765: void
                    766: sockunion_free (union sockunion *su)
                    767: {
                    768:   XFREE (MTYPE_SOCKUNION, su);
                    769: }

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