Annotation of embedaddon/quagga/lib/sockunion.c, revision 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>