File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / lib / sockunion.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jul 21 23:54:39 2013 UTC (11 years, 1 month ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, HEAD
0.99.22

    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:   union sockunion *su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
  181:   
  182:   if (!str2sockunion (str, su))
  183:     return su;
  184:   
  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. */
  260: static const char *
  261: sockunion_log (union sockunion *su, char *buf, size_t len)
  262: {
  263:   switch (su->sa.sa_family) 
  264:     {
  265:     case AF_INET:
  266:       return inet_ntop(AF_INET, &su->sin.sin_addr, buf, len);
  267: 
  268: #ifdef HAVE_IPV6
  269:     case AF_INET6:
  270:       return inet_ntop(AF_INET6, &(su->sin6.sin6_addr), buf, len);
  271:       break;
  272: #endif /* HAVE_IPV6 */
  273: 
  274:     default:
  275:       snprintf (buf, len, "af_unknown %d ", su->sa.sa_family);
  276:       return buf;
  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: 	{
  339: 	  char str[SU_ADDRSTRLEN];
  340: 	  zlog_info ("can't connect to %s fd %d : %s",
  341: 		     sockunion_log (&su, str, sizeof str),
  342: 		     fd, safe_strerror (errno));
  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)
  385: 	sockunion2ip (su) = htonl (INADDR_ANY);
  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: 
  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: 
  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:     {
  742:       if (ntohl (sockunion2ip (su1)) == ntohl (sockunion2ip (su2)))
  743: 	return 0;
  744:       if (ntohl (sockunion2ip (su1)) > ntohl (sockunion2ip (su2)))
  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>