Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

sockaddr_atop.c

Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 2005 by Kevin L. Mitchell <klmitch@mit.edu>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 ** GNU General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 **
00018 ** @(#)$Id: sockaddr_atop.c,v 1.6 2005/12/29 04:33:58 klmitch Exp $
00019 */
00027 #include "event_int.h"
00028 
00029 #include <stdio.h>
00030 #include <string.h>
00031 
00032 RCSTAG("@(#)$Id: sockaddr_atop.c,v 1.6 2005/12/29 04:33:58 klmitch Exp $");
00033 
00053 static ev_err_t
00054 atop_v4(const ev_sockaddr_t *sa, const unsigned char *addr, char *buf,
00055         ev_flags_t flags)
00056 {
00057   ev_trace(); /* trace entry to function */
00058 
00059   buf += sprintf(buf, "%u.%u.%u.%u", addr[0], addr[1], addr[2], addr[3]);
00060 
00061   if (!(flags & SOCKADDR_ATOP_NOPORT)) /* format the port... */
00062     sprintf(buf, ".%u", sa_ipaddrport(sa));
00063 
00064   ev_return(0); /* trace exit from function */
00065 }
00066 
00086 static ev_err_t
00087 atop_v6(const ev_sockaddr_t *sa, const unsigned char *addr, char *buf,
00088         ev_flags_t flags)
00089 {
00090   uint16_t cooked[SOCK_ADDRBUFV6_LEN >> 1];
00091   struct {
00092     int start;
00093     int len;
00094   } best = { -1, -1 }, cur = { -1, -1 };
00095   int i;
00096 
00097   ev_trace(); /* trace entry to function */
00098 
00099   for (i = 0; i < (SOCK_ADDRBUFV6_LEN >> 1); i++) {
00100     /* Assemble 2 bytes into a single uint16_t */
00101     cooked[i] = (addr[i << 1] << 8) | addr[(i << 1) + 1];
00102 
00103     /* Now test if it's zero... */
00104     if (!cooked[i]) {
00105       /* Is it the start of a run? */
00106       if (cur.start < 0) {
00107         cur.start = i; /* remember the beginning point */
00108         cur.len = 1; /* and the length so far */
00109       } else
00110         cur.len++; /* increment the length */
00111     } else {
00112       if (cur.start >= 0 && (best.start < 0 || best.len < cur.len))
00113         best = cur; /* Found a better (read: longer) run */
00114       cur.start = -1; /* reset current run */
00115     }
00116   }
00117 
00118   /* Did we end on a run of 0s? */
00119   if (cur.start >= 0 && (best.start < 0 || best.len < cur.len))
00120     best = cur; /* Found a better 0 run */
00121 
00122   if (best.start >= 0 && best.len < 2) /* need at least 2 consecutive 0s */
00123     best.start = -1;
00124 
00125   /* OK, now do the formatting */
00126   for (i = 0; i < (SOCK_ADDRBUFV6_LEN >> 1); ) {
00127     if (i >= best.start && i < (best.start + best.len)) { /* in best run? */
00128       *buf++ = ':'; /* Add colon... */
00129 
00130       i = best.start + best.len; /* jump to next non-zero entry */
00131 
00132       if (i >= (SOCK_ADDRBUFV6_LEN >> 1)) {
00133         *buf++ = ':'; /* Add one more colon... */
00134         break; /* and bail out */
00135       }
00136 
00137       continue;
00138     }
00139 
00140     if (i)
00141       *buf++ = ':'; /* Add colon... */
00142 
00143     /* Is this an encapsulated v4 address? */
00144     if (i == 6 && best.start == 0 &&
00145         (best.len == 6 || (best.len == 5 && cooked[5] == 0xffff)))
00146       ev_return(atop_v4(sa, addr + (SOCK_ADDRBUFV6_LEN - SOCK_ADDRBUFV4_LEN),
00147                         buf, flags));
00148 
00149     /* OK, now fill in the address component */
00150     buf += sprintf(buf, "%x", cooked[i]);
00151 
00152     i++; /* move on... */
00153   }
00154 
00155   if (!(flags & SOCKADDR_ATOP_NOPORT)) /* format the port... */
00156     sprintf(buf, ".%u", sa_ipaddrport(sa));
00157 
00158   ev_return(0); /* trace exit from function */
00159 }
00160 
00161 ev_err_t
00162 sockaddr_atop(const ev_sockaddr_t *sa, char *buf, int size, ev_flags_t flags)
00163 {
00164   const char *src = 0;
00165   char addrbuf[SOCK_ADDRSTRV6_LEN + 6]; /* v6 address + ".65535" */
00166 
00167   ev_init(); /* make sure library is initialized... */
00168 
00169   /* sanity-check arguments */
00170   if (!sa || !buf || !size)
00171     ev_return(EINVAL);
00172 
00173   switch (sa->sa_type) {
00174   case AT_IPv6:
00175     src = addrbuf;
00176     atop_v6(sa, sa_ipaddrbuf(sa), addrbuf, flags); /* format v6 address */
00177     break;
00178 
00179   case AT_IPv4:
00180     src = addrbuf;
00181     atop_v4(sa, sa_ipaddrbuf(sa), addrbuf, flags); /* format v4 address */
00182     break;
00183 
00184   case AT_LOCAL: /* Local address; just the file name */
00185     src = sa_localaddr(sa);
00186     break;
00187 
00188   case AT_NONE: /* No address type... */
00189     src = "<NO ADDRESS>";
00190     break;
00191   }
00192 
00193   strncpy(buf, src, size); /* Copy the address into the user's buffer */
00194   buf[size - 1] = '\0'; /* make sure buffer gets terminated */
00195 
00196   ev_return(0);
00197 }

Generated on Wed Dec 28 23:36:56 2005 for event by  doxygen 1.4.4