00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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();
00058
00059 buf += sprintf(buf, "%u.%u.%u.%u", addr[0], addr[1], addr[2], addr[3]);
00060
00061 if (!(flags & SOCKADDR_ATOP_NOPORT))
00062 sprintf(buf, ".%u", sa_ipaddrport(sa));
00063
00064 ev_return(0);
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();
00098
00099 for (i = 0; i < (SOCK_ADDRBUFV6_LEN >> 1); i++) {
00100
00101 cooked[i] = (addr[i << 1] << 8) | addr[(i << 1) + 1];
00102
00103
00104 if (!cooked[i]) {
00105
00106 if (cur.start < 0) {
00107 cur.start = i;
00108 cur.len = 1;
00109 } else
00110 cur.len++;
00111 } else {
00112 if (cur.start >= 0 && (best.start < 0 || best.len < cur.len))
00113 best = cur;
00114 cur.start = -1;
00115 }
00116 }
00117
00118
00119 if (cur.start >= 0 && (best.start < 0 || best.len < cur.len))
00120 best = cur;
00121
00122 if (best.start >= 0 && best.len < 2)
00123 best.start = -1;
00124
00125
00126 for (i = 0; i < (SOCK_ADDRBUFV6_LEN >> 1); ) {
00127 if (i >= best.start && i < (best.start + best.len)) {
00128 *buf++ = ':';
00129
00130 i = best.start + best.len;
00131
00132 if (i >= (SOCK_ADDRBUFV6_LEN >> 1)) {
00133 *buf++ = ':';
00134 break;
00135 }
00136
00137 continue;
00138 }
00139
00140 if (i)
00141 *buf++ = ':';
00142
00143
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
00150 buf += sprintf(buf, "%x", cooked[i]);
00151
00152 i++;
00153 }
00154
00155 if (!(flags & SOCKADDR_ATOP_NOPORT))
00156 sprintf(buf, ".%u", sa_ipaddrport(sa));
00157
00158 ev_return(0);
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];
00166
00167 ev_init();
00168
00169
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);
00177 break;
00178
00179 case AT_IPv4:
00180 src = addrbuf;
00181 atop_v4(sa, sa_ipaddrbuf(sa), addrbuf, flags);
00182 break;
00183
00184 case AT_LOCAL:
00185 src = sa_localaddr(sa);
00186 break;
00187
00188 case AT_NONE:
00189 src = "<NO ADDRESS>";
00190 break;
00191 }
00192
00193 strncpy(buf, src, size);
00194 buf[size - 1] = '\0';
00195
00196 ev_return(0);
00197 }