struct addrinfo * camel_getaddrinfo(const char *name, const char *service, const struct addrinfo *hints, CamelException *ex) { struct _addrinfo_msg *msg; struct addrinfo *res = NULL; #ifndef ENABLE_IPv6 struct addrinfo myhints; #endif g_return_val_if_fail(name != NULL, NULL); if (camel_operation_cancel_check(NULL)) { camel_exception_set(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Canceled")); return NULL; } camel_operation_start_transient(NULL, _("Resolving: %s"), name); /* force ipv4 addresses only */ #ifndef ENABLE_IPv6 if (hints == NULL) memset(&myhints, 0, sizeof(myhints)); else memcpy (&myhints, hints, sizeof (myhints)); myhints.ai_family = AF_INET; hints = &myhints; #endif msg = g_malloc0(sizeof(*msg)); msg->name = name; msg->service = service; msg->hints = hints; msg->res = &res; #ifdef NEED_ADDRINFO msg->hostbuflen = 1024; msg->hostbufmem = g_malloc(msg->hostbuflen); #endif if (cs_waitinfo(cs_getaddrinfo, msg, _("Host lookup failed"), ex) == 0) { if (msg->result != 0) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Host lookup failed: %s: %s"), name, gai_strerror (msg->result)); } cs_freeinfo(msg); } else res = NULL; camel_operation_end(NULL); return res; }
static void * cs_getnameinfo(void *data) { struct _addrinfo_msg *msg = data; /* there doens't appear to be a return code which says host or serv buffers are too short, lengthen them */ msg->result = getnameinfo(msg->addr, msg->addrlen, msg->host, msg->hostlen, msg->serv, msg->servlen, msg->flags); if (msg->cancelled) cs_freeinfo(msg); else e_msgport_reply((EMsg *)msg); return NULL; }
static void * cs_getaddrinfo(void *data) { struct _addrinfo_msg *info = data; info->result = getaddrinfo(info->name, info->service, info->hints, info->res); if (info->cancelled) { cs_freeinfo(info); } else { e_msgport_reply((EMsg *)info); } return NULL; }
static void * cs_getnameinfo(void *data) { struct _addrinfo_msg *msg = data; int herr; struct hostent h; struct sockaddr_in *sin = (struct sockaddr_in *)msg->addr; /* FIXME: error code */ if (msg->addr->sa_family != AF_INET) { msg->result = -1; return NULL; } /* FIXME: honour getnameinfo flags: do we care, not really */ while ((msg->result = camel_gethostbyaddr_r((const char *)&sin->sin_addr, sizeof(sin->sin_addr), AF_INET, &h, msg->hostbufmem, msg->hostbuflen, &herr)) == ERANGE) { pthread_testcancel (); msg->hostbuflen *= 2; msg->hostbufmem = g_realloc(msg->hostbufmem, msg->hostbuflen); } if (msg->cancelled) goto cancel; if (msg->host) { g_free(msg->host); if (msg->result == 0 && h.h_name && h.h_name[0]) { msg->host = g_strdup(h.h_name); } else { unsigned char *in = (unsigned char *)&sin->sin_addr; /* sin_addr is always network order which is big-endian */ msg->host = g_strdup_printf("%u.%u.%u.%u", in[0], in[1], in[2], in[3]); } } /* we never actually use this anyway */ if (msg->serv) sprintf(msg->serv, "%d", sin->sin_port); e_msgport_reply((EMsg *)msg); return NULL; cancel: cs_freeinfo(msg); return NULL; }
static void * cs_getaddrinfo(void *data) { struct _addrinfo_msg *info = data; if (!info->name) g_warning ("Memory problem in cs_getaddrinfo\n"); info->result = getaddrinfo(info->name, info->service, info->hints, info->res); if (info->cancelled) { /* g_free(info); */ cs_freeinfo(info); } else { e_msgport_reply((EMsg *)info); } return NULL; }
static void * cs_getaddrinfo(void *data) { struct _addrinfo_msg *msg = data; int herr; struct hostent h; struct addrinfo *res, *last = NULL; struct sockaddr_in *sin; in_port_t port = 0; int i; /* This is a pretty simplistic emulation of getaddrinfo */ while ((msg->result = camel_gethostbyname_r(msg->name, &h, msg->hostbufmem, msg->hostbuflen, &herr)) == ERANGE) { pthread_testcancel(); msg->hostbuflen *= 2; msg->hostbufmem = g_realloc(msg->hostbufmem, msg->hostbuflen); } /* If we got cancelled, dont reply, just free it */ if (msg->cancelled) goto cancel; /* FIXME: map error numbers across */ if (msg->result != 0) goto reply; /* check hints matched */ if (msg->hints && msg->hints->ai_family && msg->hints->ai_family != h.h_addrtype) { msg->result = EAI_FAMILY; goto reply; } /* we only support ipv4 for this interface, even if it could supply ipv6 */ if (h.h_addrtype != AF_INET) { msg->result = EAI_FAMILY; goto reply; } /* check service mapping */ if (msg->service) { const char *p = msg->service; while (*p) { if (*p < '0' || *p > '9') break; p++; } if (*p) { const char *socktype = NULL; struct servent *serv; if (msg->hints && msg->hints->ai_socktype) { if (msg->hints->ai_socktype == SOCK_STREAM) socktype = "tcp"; else if (msg->hints->ai_socktype == SOCK_DGRAM) socktype = "udp"; } serv = getservbyname(msg->service, socktype); if (serv == NULL) { msg->result = EAI_NONAME; goto reply; } port = serv->s_port; } else { port = htons(strtoul(msg->service, NULL, 10)); } } for (i=0;h.h_addr_list[i];i++) { res = g_malloc0(sizeof(*res)); if (msg->hints) { res->ai_flags = msg->hints->ai_flags; if (msg->hints->ai_flags & AI_CANONNAME) res->ai_canonname = g_strdup(h.h_name); res->ai_socktype = msg->hints->ai_socktype; res->ai_protocol = msg->hints->ai_protocol; } else { res->ai_flags = 0; res->ai_socktype = SOCK_STREAM; /* fudge */ res->ai_protocol = 0; /* fudge */ } res->ai_family = AF_INET; res->ai_addrlen = sizeof(*sin); res->ai_addr = g_malloc(sizeof(*sin)); sin = (struct sockaddr_in *)res->ai_addr; sin->sin_family = AF_INET; sin->sin_port = port; memcpy(&sin->sin_addr, h.h_addr_list[i], sizeof(sin->sin_addr)); if (last == NULL) { *msg->res = last = res; } else { last->ai_next = res; last = res; } } reply: e_msgport_reply((EMsg *)msg); return NULL; cancel: cs_freeinfo(msg); return NULL; }