• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

  • tdecore
netsupp.cpp
1/*
2 * This file is part of the KDE libraries
3 * Copyright (C) 2000,2001 Thiago Macieira <thiago.macieira@kdemail.net>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 **/
20
21#include <sys/types.h>
22#include <sys/socket.h>
23#include <sys/un.h>
24#include <netinet/in.h>
25#include <stdlib.h>
26#include <stdio.h>
27#include <errno.h>
28#include <unistd.h>
29#include <arpa/inet.h>
30
31#include <tqglobal.h>
32
33// This is so that, if addrinfo is defined, it doesn't clobber our definition
34// It might be defined in the few cases in which we are replacing the system's
35// broken getaddrinfo
36#include <netdb.h>
37
38#include "config.h"
39#include "kdebug.h"
40#include "tdelocale.h"
41
42#ifndef IN6_IS_ADDR_V4MAPPED
43#define NEED_IN6_TESTS
44#endif
45#undef CLOBBER_IN6
46#include "netsupp.h"
47
48#if defined(__hpux) || defined(_HPUX_SOURCE)
49extern int h_errno;
50#endif
51
52#include <tdemacros.h>
53
54#if !defined(kde_sockaddr_in6)
55/*
56 * kde_sockaddr_in6 might have got defined even though we #undef'ed
57 * CLOBBER_IN6. This happens when we are compiling under --enable-final.
58 * However, in that case, if it was defined, that's because ksockaddr.cpp
59 * had it defined because sockaddr_in6 didn't exist, and so sockaddr_in6
60 * exists and is our kde_sockaddr_in6
61 */
62# define sockaddr_in6 kde_sockaddr_in6
63# define in6_addr kde_in6_addr
64#endif
65
66#ifdef offsetof
67#undef offsetof
68#endif
69#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
70
71/*
72 * These constants tell the flags in KDE::resolverFlags
73 * The user could (but shouldn't) test the variable to know what kind of
74 * resolution is supported
75 */
76#define KRF_KNOWS_AF_INET6 0x01 /* if present, the code knows about AF_INET6 */
77#define KRF_USING_OWN_GETADDRINFO 0x02 /* if present, we are using our own getaddrinfo */
78#define KRF_USING_OWN_INET_NTOP 0x04 /* if present, we are using our own inet_ntop */
79#define KRF_USING_OWN_INET_PTON 0x08 /* if present, we are using our own inet_pton */
80#define KRF_CAN_RESOLVE_UNIX 0x100 /* if present, the resolver can resolve Unix sockets */
81#define KRF_CAN_RESOLVE_IPV4 0x200 /* if present, the resolver can resolve to IPv4 */
82#define KRF_CAN_RESOLVE_IPV6 0x400 /* if present, the resolver can resolve to IPv6 */
83
84
85static void dofreeaddrinfo(struct addrinfo *ai)
86{
87 while (ai)
88 {
89 struct addrinfo *ai2 = ai;
90 if (ai->ai_canonname != NULL)
91 free(ai->ai_canonname);
92
93 if (ai->ai_addr != NULL)
94 free(ai->ai_addr);
95
96 ai = ai->ai_next;
97 free(ai2);
98 }
99}
100
101void kde_freeaddrinfo(struct kde_addrinfo *ai)
102{
103 if (ai->origin == KAI_LOCALUNIX)
104 {
105 struct addrinfo *p, *last = NULL;
106 /* We've added one AF_UNIX socket in here, to the
107 * tail of the linked list. We have to find it */
108 for (p = ai->data; p; p = p->ai_next)
109 {
110 if (p->ai_family == AF_UNIX)
111 {
112 if (last)
113 {
114 last->ai_next = NULL;
115 freeaddrinfo(ai->data);
116 }
117 dofreeaddrinfo(p);
118 break;
119 }
120 last = p;
121 }
122 }
123 else
124 freeaddrinfo(ai->data);
125
126 free(ai);
127}
128
129static struct addrinfo*
130make_unix(const char *name, const char *serv)
131{
132 const char *buf;
133 struct addrinfo *p;
134 struct sockaddr_un *_sun;
135 int len;
136
137 p = (addrinfo*)malloc(sizeof(*p));
138 if (p == NULL)
139 return NULL;
140 memset(p, 0, sizeof(*p));
141
142 if (name != NULL)
143 buf = name;
144 else
145 buf = serv;
146
147 // Calculate length of the binary representation
148 len = strlen(buf) + offsetof(struct sockaddr_un, sun_path) + 1;
149 if (*buf != '/')
150 len += 5; // strlen("/tmp/");
151
152 _sun = (sockaddr_un*)malloc(len);
153 if (_sun == NULL)
154 {
155 // Oops
156 free(p);
157 return NULL;
158 }
159
160 _sun->sun_family = AF_UNIX;
161# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
162 _sun->sun_len = len;
163# endif
164 if (*buf == '/')
165 *_sun->sun_path = '\0'; // empty it
166 else
167 strcpy(_sun->sun_path, "/tmp/");
168 strcat(_sun->sun_path, buf);
169
170 // Set the addrinfo
171 p->ai_family = AF_UNIX;
172 p->ai_addrlen = len;
173 p->ai_addr = (sockaddr*)_sun;
174 p->ai_canonname = strdup(buf);
175
176 return p;
177}
178
179// Ugh. I hate #ifdefs
180// Anyways, here's what this does:
181// KDE_IPV6_LOOKUP_MODE != 1, this function doesn't exist
182// AF_INET6 not defined, we say there is no IPv6 stack
183// otherwise, we try to create a socket.
184// returns: 1 for IPv6 stack available, 2 for not available
185#if defined(KDE_IPV6_LOOKUP_MODE) && KDE_IPV6_LOOKUP_MODE == 1
186static int check_ipv6_stack()
187{
188# ifndef AF_INET6
189 return 2; // how can we check?
190# else
191 if (getenv("TDE_NO_IPV6"))
192 return 2;
193 int fd = ::socket(AF_INET6, SOCK_STREAM, 0);
194 if (fd == -1)
195 return 2;
196
197 ::close(fd);
198 return 1;
199# endif
200}
201#endif
202
203
204/*
205 * Reason for using this function: kde_getaddrinfo
206 *
207 * I decided to add this wrapper function for getaddrinfo
208 * and have this be called by KExtendedSocket instead of
209 * the real getaddrinfo so that we can make sure that the
210 * behavior is the desired one.
211 *
212 * Currently, the only "undesired" behavior is getaddrinfo
213 * not returning PF_UNIX sockets in some implementations.
214 *
215 * getaddrinfo and family are defined in POSIX 1003.1g
216 * (Protocol Independent Interfaces) and in RFC 2553
217 * (Basic Socket Interface for IPv6). Whereas the RFC is ambiguosly
218 * vague whether this family of functions should return Internet
219 * sockets only or not, the name of the POSIX draft says
220 * otherwise: it should be independent of protocol.
221 *
222 * So, my interpretation is that they should return every
223 * kind of socket available and known and that's how I
224 * designed KExtendedSocket on top of it.
225 *
226 * That's why there's this wrapper, to make sure PF_UNIX
227 * sockets are returned when expected.
228 */
229
230int kde_getaddrinfo(const char *name, const char *service,
231 const struct addrinfo* hint,
232 struct kde_addrinfo** result)
233{
234 struct kde_addrinfo* res;
235 struct addrinfo* p;
236 int err = EAI_SERVICE;
237#if defined(KDE_IPV6_LOOKUP_MODE) && KDE_IPV6_LOOKUP_MODE == 1
238 // mode 1: do a check on whether we have an IPv6 stack
239 static int ipv6_stack = 0; // 0: unknown, 1: yes, 2: no
240#endif
241
242 // allocate memory for results
243 res = (kde_addrinfo*)malloc(sizeof(*res));
244 if (res == NULL)
245 return EAI_MEMORY;
246 res->data = NULL;
247 res->origin = KAI_SYSTEM; // at first, it'll be only system data
248
249 struct addrinfo* last = NULL;
250
251 // Skip the getaddrinfo call and the ipv6 check for a UNIX socket.
252 if (hint && (hint->ai_family == PF_UNIX))
253 {
254 if (service == NULL || *service == '\0')
255 goto out; // can't be Unix if no service was requested
256
257 // Unix sockets must be localhost
258 // That is, either name is NULL or, if it's not, it must be empty,
259 // "*" or "localhost"
260 if (name != NULL && !(name[0] == '\0' || (name[0] == '*' && name[1] == '\0') ||
261 strcmp("localhost", name) == 0))
262 goto out; // isn't localhost
263
264 goto do_unix;
265 }
266
267#if defined(KDE_IPV6_LOOKUP_MODE) && KDE_IPV6_LOOKUP_MODE != 0
268# if KDE_IPV6_LOOKUP_MODE == 1
269 // mode 1: do a check on whether we have an IPv6 stack
270 if (ipv6_stack == 0)
271 ipv6_stack = check_ipv6_stack();
272
273 if (ipv6_stack == 2)
274 {
275# endif
276 // here we have modes 1 and 2 (no lookups)
277 // this is shared code
278 struct addrinfo our_hint;
279 if (hint != NULL)
280 {
281 memcpy(&our_hint, hint, sizeof(our_hint));
282 if (our_hint.ai_family == AF_UNSPEC)
283 our_hint.ai_family = AF_INET;
284 }
285 else
286 {
287 memset(&our_hint, 0, sizeof(our_hint));
288 our_hint.ai_family = AF_INET;
289 }
290
291 // do the actual resolution
292 err = getaddrinfo(name, service, &our_hint, &res->data);
293# if KDE_IPV6_LOOKUP_MODE == 1
294 }
295 else
296# endif
297#endif
298#if defined(KDE_IPV6_LOOKUP_MODE) && KDE_IPV6_LOOKUP_MODE != 2
299 // do the IPV6 resolution
300 err = getaddrinfo(name, service, hint, &res->data);
301#endif
302
303 // Now we have to check whether the user could want a Unix socket
304
305 if (service == NULL || *service == '\0')
306 goto out; // can't be Unix if no service was requested
307
308 // Unix sockets must be localhost
309 // That is, either name is NULL or, if it's not, it must be empty,
310 // "*" or "localhost"
311 if (name != NULL && !(name[0] == '\0' || (name[0] == '*' && name[1] == '\0') ||
312 strcmp("localhost", name) == 0))
313 goto out; // isn't localhost
314
315 // Unix sockets can only be returned if the user asked for a PF_UNSPEC
316 // or PF_UNIX socket type or gave us a NULL hint
317 if (hint != NULL && (hint->ai_family != PF_UNSPEC && hint->ai_family != PF_UNIX))
318 goto out; // user doesn't want Unix
319
320 // If we got here, then it means that the user might be expecting Unix
321 // sockets. The user wants a local socket, with a non-null service and
322 // has told us that they accept PF_UNIX sockets
323 // Check whether the system implementation returned Unix
324 if (err == 0)
325 for (p = res->data; p; p = p->ai_next)
326 {
327 last = p; // we have to find out which one is last anyways
328 if (p->ai_family == AF_UNIX)
329 // there is an Unix node
330 goto out;
331 }
332
333 do_unix:
334 // So, give the user a PF_UNIX socket
335 p = make_unix(NULL, service);
336 if (p == NULL)
337 {
338 err = EAI_MEMORY;
339 goto out;
340 }
341 if (hint != NULL)
342 p->ai_socktype = hint->ai_socktype;
343 if (p->ai_socktype == 0)
344 p->ai_socktype = SOCK_STREAM; // default
345
346 if (last)
347 last->ai_next = p;
348 else
349 res->data = p;
350 res->origin = KAI_LOCALUNIX;
351 *result = res;
352 return 0;
353
354 out:
355 if (res->data != NULL)
356 freeaddrinfo(res->data);
357 free(res);
358 return err;
359}
360
361#if defined(HAVE_GETADDRINFO) && !defined(HAVE_BROKEN_GETADDRINFO)
362
363#define KRF_getaddrinfo 0
364#define KRF_resolver 0
365
366#else // !defined(HAVE_GETADDRINFO) || defined(HAVE_BROKEN_GETADDRINFO)
367
368#define KRF_getaddrinfo KRF_USING_OWN_GETADDRINFO
369#define KRF_resolver KRF_CAN_RESOLVE_UNIX | KRF_CAN_RESOLVE_IPV4
370
371/*
372 * No getaddrinfo() in this system.
373 * We shall provide our own
374 */
375
379static int inet_lookup(const char *name, int portnum, int protonum,
380 struct addrinfo *p, const struct addrinfo *hint,
381 struct addrinfo** result)
382{
383 struct addrinfo *q;
384 struct hostent *h;
385 struct sockaddr **psa = NULL;
386 int len;
387
388 // TODO
389 // Currently, this never resolves IPv6 (need gethostbyname2, etc.)
390# ifdef AF_INET6
391 if (hint->ai_family == AF_INET6)
392 {
393 if (p != NULL)
394 {
395 *result = p;
396 return 0;
397 }
398 return EAI_FAIL;
399 }
400# endif
401
402 q = (addrinfo*)malloc(sizeof(*q));
403 if (q == NULL)
404 {
405 freeaddrinfo(p);
406 return EAI_MEMORY;
407 }
408
409 h = gethostbyname(name);
410 if (h == NULL)
411 {
412 if (p != NULL)
413 {
414 // There already is a suitable result
415 *result = p;
416 return 0;
417 }
418
419 switch (h_errno)
420 {
421 case HOST_NOT_FOUND:
422 return EAI_NONAME;
423 case TRY_AGAIN:
424 return EAI_AGAIN;
425 case NO_RECOVERY:
426 return EAI_FAIL;
427 case NO_ADDRESS:
428 return EAI_NODATA;
429 default:
430 // EH!?
431 return EAI_FAIL;
432 }
433 }
434
435 // convert the hostent to addrinfo
436 if (h->h_addrtype == AF_INET && (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC))
437 len = sizeof(struct sockaddr_in);
438# ifdef AF_INET6
439 else if (h->h_addrtype == AF_INET6 && (hint->ai_family == AF_INET6 ||
440 hint->ai_family == AF_UNSPEC))
441 len = sizeof(struct sockaddr_in6);
442# endif
443 else
444 {
445 // We don't know what to do with these addresses
446 // Or gethostbyname returned information we don't want
447 if (p != NULL)
448 {
449 *result = p;
450 return 0;
451 }
452 return EAI_NODATA;
453 }
454
455 q->ai_flags = 0;
456 q->ai_family = h->h_addrtype;
457 q->ai_socktype = hint->ai_socktype;
458 q->ai_protocol = protonum;
459 q->ai_addrlen = len;
460
461 q->ai_addr = (sockaddr*)malloc(len);
462 if (q->ai_addr == NULL)
463 {
464 free(q);
465 freeaddrinfo(p);
466 return EAI_MEMORY;
467 }
468 if (h->h_addrtype == AF_INET)
469 {
470 struct sockaddr_in *sin = (sockaddr_in*)q->ai_addr;
471 sin->sin_family = AF_INET;
472# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
473 sin->sin_len = sizeof(*sin);
474# endif
475 sin->sin_port = portnum;
476 memcpy(&sin->sin_addr, h->h_addr, h->h_length);
477 }
478# ifdef AF_INET6
479 else if (h->h_addrtype == AF_INET6)
480 {
481 struct sockaddr_in6 *sin6 = (sockaddr_in6*)q->ai_addr;
482 sin6->sin6_family = AF_INET6;
483# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
484 sin6->sin6_len = sizeof(*sin6);
485# endif
486 sin6->sin6_port = portnum;
487 sin6->sin6_flowinfo = 0;
488 memcpy(&sin6->sin6_addr, h->h_addr, h->h_length);
489 sin6->sin6_scope_id = 0;
490 }
491# endif
492
493 if (hint->ai_flags & AI_CANONNAME)
494 q->ai_canonname = strdup(h->h_name);
495 else
496 q->ai_canonname = NULL;
497
498 q->ai_next = p;
499 p = q;
500
501 // cycle through the rest of the hosts;
502 for (psa = (sockaddr**)h->h_addr_list + 1; *psa; psa++)
503 {
504 q = (addrinfo*)malloc(sizeof(*q));
505 if (q == NULL)
506 {
507 freeaddrinfo(p);
508 return EAI_MEMORY;
509 }
510 memcpy(q, p, sizeof(*q));
511
512 q->ai_addr = (sockaddr*)malloc(h->h_length);
513 if (q->ai_addr == NULL)
514 {
515 freeaddrinfo(p);
516 free(q);
517 return EAI_MEMORY;
518 }
519 if (h->h_addrtype == AF_INET)
520 {
521 struct sockaddr_in *sin = (sockaddr_in*)q->ai_addr;
522 sin->sin_family = AF_INET;
523# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
524 sin->sin_len = sizeof(*sin);
525# endif
526 sin->sin_port = portnum;
527 memcpy(&sin->sin_addr, *psa, h->h_length);
528 }
529# ifdef AF_INET6
530 else if (h->h_addrtype == AF_INET6)
531 {
532 struct sockaddr_in6 *sin6 = (sockaddr_in6*)q->ai_addr;
533 sin6->sin6_family = AF_INET6;
534# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
535 sin6->sin6_len = sizeof(*sin6);
536# endif
537 sin6->sin6_port = portnum;
538 sin6->sin6_flowinfo = 0;
539 memcpy(&sin6->sin6_addr, *psa, h->h_length);
540 sin6->sin6_scope_id = 0;
541 }
542# endif
543
544 if (q->ai_canonname != NULL)
545 q->ai_canonname = strdup(q->ai_canonname);
546
547 q->ai_next = p;
548 p = q;
549 }
550
551 *result = p;
552 return 0; // Whew! Success!
553}
554
555static int make_inet(const char *name, int portnum, int protonum, struct addrinfo *p,
556 const struct addrinfo *hint, struct addrinfo** result)
557{
558 struct addrinfo *q;
559
560 do
561 {
562 // This 'do' is here just so that we can 'break' out of it
563
564 if (name != NULL)
565 {
566 // first, try to use inet_pton before resolving
567 // it will catch IP addresses given without having to go to lookup
568 struct sockaddr_in *sin;
569 struct in_addr in;
570# ifdef AF_INET6
571 struct sockaddr_in6 *sin6;
572 struct in6_addr in6;
573
574 if (hint->ai_family == AF_INET6 || (hint->ai_family == AF_UNSPEC &&
575 strchr(name, ':') != NULL))
576 {
577 // yes, this is IPv6
578 if (inet_pton(AF_INET6, name, &in6) != 1)
579 {
580 if (hint->ai_flags & AI_NUMERICHOST)
581 {
582 freeaddrinfo(p);
583 return EAI_FAIL;
584 }
585 break; // not a numeric host
586 }
587
588 sin6 = (sockaddr_in6*)malloc(sizeof(*sin6));
589 if (sin6 == NULL)
590 {
591 freeaddrinfo(p);
592 return EAI_MEMORY;
593 }
594 memcpy(&sin6->sin6_addr, &in6, sizeof(in6));
595
596 if (strchr(name, '%') != NULL)
597 {
598 errno = 0;
599 sin6->sin6_scope_id = strtoul(strchr(name, '%') + 1, NULL, 10);
600 if (errno != 0)
601 sin6->sin6_scope_id = 0; // no interface
602 }
603
604 q = (addrinfo*)malloc(sizeof(*q));
605 if (q == NULL)
606 {
607 freeaddrinfo(p);
608 free(sin6);
609 return EAI_MEMORY;
610 }
611
612 sin6->sin6_family = AF_INET6;
613# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
614 sin6->sin6_len = sizeof(*sin6);
615# endif
616 sin6->sin6_port = portnum;
617 sin6->sin6_flowinfo = 0;
618
619 q->ai_flags = 0;
620 q->ai_family = AF_INET6;
621 q->ai_socktype = hint->ai_socktype;
622 q->ai_protocol = protonum;
623 q->ai_addrlen = sizeof(*sin6);
624 q->ai_canonname = NULL;
625 q->ai_addr = (sockaddr*)sin6;
626 q->ai_next = p;
627
628 *result = q;
629 return 0; // success!
630 }
631# endif // AF_INET6
632
633 if (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC)
634 {
635 // This has to be IPv4
636 if (inet_pton(AF_INET, name, &in) != 1)
637 {
638 if (hint->ai_flags & AI_NUMERICHOST)
639 {
640 freeaddrinfo(p);
641 return EAI_FAIL; // invalid, I guess
642 }
643 break; // not a numeric host, do lookup
644 }
645
646 sin = (sockaddr_in*)malloc(sizeof(*sin));
647 if (sin == NULL)
648 {
649 freeaddrinfo(p);
650 return EAI_MEMORY;
651 }
652
653 q = (addrinfo*)malloc(sizeof(*q));
654 if (q == NULL)
655 {
656 freeaddrinfo(p);
657 free(sin);
658 return EAI_MEMORY;
659 }
660
661 sin->sin_family = AF_INET;
662# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
663 sin->sin_len = sizeof(*sin);
664# endif
665 sin->sin_port = portnum;
666 sin->sin_addr = in;
667
668 q->ai_flags = 0;
669 q->ai_family = AF_INET;
670 q->ai_socktype = hint->ai_socktype;
671 q->ai_protocol = protonum;
672 q->ai_addrlen = sizeof(*sin);
673 q->ai_canonname = NULL;
674 q->ai_addr = (sockaddr*)sin;
675 q->ai_next = p;
676 *result = q;
677 return 0;
678 }
679
680 // Eh, what!?
681 // One of the two above has to have matched
682 kdError() << "I wasn't supposed to get here!";
683 }
684 } while (false);
685
686 // This means localhost
687 if (name == NULL)
688 {
689 struct sockaddr_in *sin = (sockaddr_in*)malloc(sizeof(*sin));
690# ifdef AF_INET6
691 struct sockaddr_in6 *sin6;
692# endif
693
694 if (hint->ai_family == AF_INET || hint->ai_family == AF_UNSPEC)
695 {
696 if (sin == NULL)
697 {
698 free(sin);
699 freeaddrinfo(p);
700 return EAI_MEMORY;
701 }
702
703 // Do IPv4 first
704 q = (addrinfo*)malloc(sizeof(*q));
705 if (q == NULL)
706 {
707 free(sin);
708 freeaddrinfo(p);
709 return EAI_MEMORY;
710 }
711
712 sin->sin_family = AF_INET;
713# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
714 sin->sin_len = sizeof(*sin);
715# endif
716 sin->sin_port = portnum;
717 if (hint->ai_flags & AI_PASSIVE)
718 *(TQ_UINT32*)&sin->sin_addr = INADDR_ANY;
719 else
720 *(TQ_UINT32*)&sin->sin_addr = htonl(INADDR_LOOPBACK);
721 q->ai_flags = 0;
722 q->ai_family = AF_INET;
723 q->ai_socktype = hint->ai_socktype;
724 q->ai_protocol = protonum;
725 q->ai_addrlen = sizeof(*sin);
726 q->ai_canonname = NULL;
727 q->ai_addr = (sockaddr*)sin;
728 q->ai_next = p;
729 p = q;
730 }
731
732# ifdef AF_INET6
733 // Try now IPv6
734
735 if (hint->ai_family == AF_INET6 || hint->ai_family == AF_UNSPEC)
736 {
737 sin6 = (sockaddr_in6*)malloc(sizeof(*sin6));
738 q = (addrinfo*)malloc(sizeof(*q));
739 if (q == NULL || sin6 == NULL)
740 {
741 free(sin6);
742 free(q);
743 freeaddrinfo(p);
744 return EAI_MEMORY;
745 }
746
747 sin6->sin6_family = AF_INET6;
748# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
749 sin6->sin6_len = sizeof(*sin6);
750# endif
751 sin6->sin6_port = portnum;
752 sin6->sin6_flowinfo = 0;
753 sin6->sin6_scope_id = 0;
754
755 // We don't want to use in6addr_loopback and in6addr_any
756 memset(&sin6->sin6_addr, 0, sizeof(sin6->sin6_addr));
757 if ((hint->ai_flags & AI_PASSIVE) == 0)
758 ((char*)&sin6->sin6_addr)[15] = 1;
759
760 q->ai_flags = 0;
761 q->ai_family = AF_INET6;
762 q->ai_socktype = hint->ai_socktype;
763 q->ai_protocol = protonum;
764 q->ai_addrlen = sizeof(*sin6);
765 q->ai_canonname = NULL;
766 q->ai_addr = (sockaddr*)sin6;
767 q->ai_next = p;
768 p = q;
769 }
770
771# endif // AF_INET6
772
773 *result = p;
774 return 0; // success!
775 }
776
777 return inet_lookup(name, portnum, protonum, p, hint, result);
778}
779
780
781int getaddrinfo(const char *name, const char *serv,
782 const struct addrinfo* hint,
783 struct addrinfo** result)
784{
785 unsigned short portnum; // remember to store in network byte order
786 int protonum = IPPROTO_TCP;
787 const char *proto = "tcp";
788 struct addrinfo *p = NULL;
789
790 // Sanity checks:
791 if (hint == NULL || result == NULL)
792 return EAI_BADFLAGS;
793 if (hint->ai_family != AF_UNSPEC && hint->ai_family != AF_UNIX &&
794 hint->ai_family != AF_INET
795# ifdef AF_INET6
796 && hint->ai_family != AF_INET6
797# endif
798 )
799 return EAI_FAMILY;
800 if (hint->ai_socktype != 0 && hint->ai_socktype != SOCK_STREAM &&
801 hint->ai_socktype != SOCK_DGRAM)
802 return EAI_SOCKTYPE;
803
804 // Treat hostname of "*" as NULL, which means localhost
805 if (name != NULL && ((*name == '*' && name[1] == '\0') || *name == '\0'))
806 name = NULL;
807 // Treat service of "*" as NULL, which I guess means no port (0)
808 if (serv != NULL && ((*serv == '*' && serv[1] == '\0') || *serv == '\0'))
809 serv = NULL;
810
811 if (name == NULL && serv == NULL) // what the hell do you want?
812 return EAI_NONAME;
813
814 // This is just to make it easier
815 if (name != NULL && strcmp(name, "localhost") == 0)
816 name = NULL;
817
818 // First, check for a Unix socket
819 // family must be either AF_UNIX or AF_UNSPEC
820 // either of name or serv must be set, the other must be NULL or empty
821 if (hint->ai_family == AF_UNIX || hint->ai_family == AF_UNSPEC)
822 {
823 if (name != NULL && serv != NULL)
824 {
825 // This is not allowed
826 if (hint->ai_family == AF_UNIX)
827 return EAI_BADFLAGS;
828 }
829 else
830 {
831 p = make_unix(name, serv);
832 if (p == NULL)
833 return EAI_MEMORY;
834
835 p->ai_socktype = hint->ai_socktype;
836 // If the name/service started with a slash, then this *IS*
837 // only a Unix socket. Return.
838 if (hint->ai_family == AF_UNIX || ((name != NULL && *name == '/') ||
839 (serv != NULL && *serv == '/')))
840 {
841 *result = p;
842 return 0; // successful lookup
843 }
844 }
845 }
846
847 // Lookup the service name, if required
848 if (serv != NULL)
849 {
850 char *tail;
851 struct servent *sent;
852
853 portnum = htons((unsigned)strtoul(serv, &tail, 10));
854 if (*tail != '\0')
855 {
856 // not a number. We have to do the lookup
857 if (hint->ai_socktype == SOCK_DGRAM)
858 {
859 proto = "udp";
860 protonum = IPPROTO_UDP;
861 }
862
863 sent = getservbyname(serv, proto);
864 if (sent == NULL) // no service?
865 {
866 if (p == NULL)
867 return EAI_NONAME;
868 else
869 return 0; // a Unix socket available
870 }
871
872 portnum = sent->s_port;
873 }
874 }
875 else
876 portnum = 0; // no port number
877
878 return make_inet(name, portnum, protonum, p, hint, result);
879}
880
881void freeaddrinfo(struct addrinfo *p)
882{
883 dofreeaddrinfo(p);
884}
885
886char *gai_strerror(int errorcode)
887{
888 static const char * const messages[] =
889 {
890 I18N_NOOP("no error"), // 0
891 I18N_NOOP("address family for nodename not supported"), // EAI_ADDRFAMILY
892 I18N_NOOP("temporary failure in name resolution"), // EAI_AGAIN
893 I18N_NOOP("invalid value for 'ai_flags'"), // EAI_BADFLAGS
894 I18N_NOOP("non-recoverable failure in name resolution"), // EAI_FAIL
895 I18N_NOOP("'ai_family' not supported"), // EAI_FAMILY
896 I18N_NOOP("memory allocation failure"), // EAI_MEMORY
897 I18N_NOOP("no address associated with nodename"), // EAI_NODATA
898 I18N_NOOP("name or service not known"), // EAI_NONAME
899 I18N_NOOP("servname not supported for ai_socktype"), // EAI_SERVICE
900 I18N_NOOP("'ai_socktype' not supported"), // EAI_SOCKTYPE
901 I18N_NOOP("system error") // EAI_SYSTEM
902 };
903
904 if (errorcode > EAI_SYSTEM || errorcode < 0)
905 return NULL;
906
907 static char buffer[200];
908 strcpy(buffer, i18n(messages[errorcode]).local8Bit());
909 return buffer;
910}
911
912static void findport(unsigned short port, char *serv, size_t servlen, int flags)
913{
914 if (serv == NULL)
915 return;
916
917 if ((flags & NI_NUMERICSERV) == 0)
918 {
919 struct servent *sent;
920 sent = getservbyport(ntohs(port), flags & NI_DGRAM ? "udp" : "tcp");
921 if (sent != NULL && servlen > strlen(sent->s_name))
922 {
923 strcpy(serv, sent->s_name);
924 return;
925 }
926 }
927
928 snprintf(serv, servlen, "%u", ntohs(port));
929}
930
931int getnameinfo(const struct sockaddr *sa, ksocklen_t salen,
932 char *host, size_t hostlen, char *serv, size_t servlen,
933 int flags)
934{
935 union
936 {
937 const sockaddr *sa;
938 const sockaddr_un *_sun;
939 const sockaddr_in *sin;
940 const sockaddr_in6 *sin6;
941 } s;
942
943 if ((host == NULL || hostlen == 0) && (serv == NULL || servlen == 0))
944 return 1;
945
946 s.sa = sa;
947 if (s.sa->sa_family == AF_UNIX)
948 {
949 if (salen < offsetof(struct sockaddr_un, sun_path) + strlen(s._sun->sun_path) + 1)
950 return 1; // invalid socket
951
952 if (servlen && serv != NULL)
953 *serv = '\0';
954 if (host != NULL && hostlen > strlen(s._sun->sun_path))
955 strcpy(host, s._sun->sun_path);
956
957 return 0;
958 }
959 else if (s.sa->sa_family == AF_INET)
960 {
961 if (salen < offsetof(struct sockaddr_in, sin_addr) + sizeof(s.sin->sin_addr))
962 return 1; // invalid socket
963
964 if (flags & NI_NUMERICHOST)
965 inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen);
966 else
967 {
968 // have to do lookup
969 struct hostent *h = gethostbyaddr((const char*)&s.sin->sin_addr, sizeof(s.sin->sin_addr),
970 AF_INET);
971 if (h == NULL && flags & NI_NAMEREQD)
972 return 1;
973 else if (h == NULL)
974 inet_ntop(AF_INET, &s.sin->sin_addr, host, hostlen);
975 else if (host != NULL && hostlen > strlen(h->h_name))
976 strcpy(host, h->h_name);
977 else
978 return 1; // error
979 }
980
981 findport(s.sin->sin_port, serv, servlen, flags);
982 }
983# ifdef AF_INET6
984 else if (s.sa->sa_family == AF_INET6)
985 {
986 if (salen < offsetof(struct sockaddr_in6, sin6_addr) + sizeof(s.sin6->sin6_addr))
987 return 1; // invalid socket
988
989 if (flags & NI_NUMERICHOST)
990 inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen);
991 else
992 {
993 // have to do lookup
994 struct hostent *h = gethostbyaddr((const char*)&s.sin->sin_addr, sizeof(s.sin->sin_addr),
995 AF_INET6);
996 if (h == NULL && flags & NI_NAMEREQD)
997 return 1;
998 else if (h == NULL)
999 inet_ntop(AF_INET6, &s.sin6->sin6_addr, host, hostlen);
1000 else if (host != NULL && hostlen > strlen(h->h_name))
1001 strcpy(host, h->h_name);
1002 else
1003 return 1; // error
1004 }
1005
1006 findport(s.sin6->sin6_port, serv, servlen, flags);
1007 }
1008# endif // AF_INET6
1009
1010 return 1; // invalid family
1011}
1012
1013#endif // HAVE_GETADDRINFO
1014
1015#ifndef HAVE_INET_NTOP
1016
1017#define KRF_inet_ntop KRF_USING_OWN_INET_NTOP
1018
1019static void add_dwords(char *buf, TQ_UINT16 *dw, int count)
1020{
1021 int i = 1;
1022 sprintf(buf + strlen(buf), "%x", ntohs(dw[0]));
1023 while (--count)
1024 sprintf(buf + strlen(buf), ":%x", ntohs(dw[i++]));
1025}
1026
1027const char* inet_ntop(int af, const void *cp, char *buf, size_t len)
1028{
1029 char buf2[sizeof "1234:5678:9abc:def0:1234:5678:255.255.255.255" + 1];
1030 TQ_UINT8 *data = (TQ_UINT8*)cp;
1031
1032 if (af == AF_INET)
1033 {
1034 sprintf(buf2, "%u.%u.%u.%u", data[0], data[1], data[2], data[3]);
1035
1036 if (len > strlen(buf2))
1037 {
1038 strcpy(buf, buf2);
1039 return buf;
1040 }
1041
1042 errno = ENOSPC;
1043 return NULL; // failed
1044 }
1045
1046# ifdef AF_INET6
1047 if (af == AF_INET6)
1048 {
1049 TQ_UINT16 *p = (TQ_UINT16*)data;
1050 TQ_UINT16 *longest = NULL, *cur = NULL;
1051 int longest_length = 0, cur_length;
1052 int i;
1053
1054 if (KDE_IN6_IS_ADDR_V4MAPPED(p) || KDE_IN6_IS_ADDR_V4COMPAT(p))
1055 sprintf(buf2, "::%s%u.%u.%u.%u",
1056 KDE_IN6_IS_ADDR_V4MAPPED(p) ? "ffff:" : "",
1057 buf[12], buf[13], buf[14], buf[15]);
1058 else
1059 {
1060 // find the longest sequence of zeroes
1061 for (i = 0; i < 8; i++)
1062 if (cur == NULL && p[i] == 0)
1063 {
1064 // a zero, start the sequence
1065 cur = p + i;
1066 cur_length = 1;
1067 }
1068 else if (cur != NULL && p[i] == 0)
1069 // part of the sequence
1070 cur_length++;
1071 else if (cur != NULL && p[i] != 0)
1072 {
1073 // end of the sequence
1074 if (cur_length > longest_length)
1075 {
1076 longest_length = cur_length;
1077 longest = cur;
1078 }
1079 cur = NULL; // restart sequence
1080 }
1081 if (cur != NULL && cur_length > longest_length)
1082 {
1083 longest_length = cur_length;
1084 longest = cur;
1085 }
1086
1087 if (longest_length > 1)
1088 {
1089 // We have a candidate
1090 buf2[0] = '\0';
1091 if (longest != p)
1092 add_dwords(buf2, p, longest - p);
1093 strcat(buf2, "::");
1094 if (longest + longest_length < p + 8)
1095 add_dwords(buf2, longest + longest_length, 8 - (longest - p) - longest_length);
1096 }
1097 else
1098 {
1099 // Nope, no candidate
1100 buf2[0] = '\0';
1101 add_dwords(buf2, p, 8);
1102 }
1103 }
1104
1105 if (strlen(buf2) < len)
1106 {
1107 strcpy(buf, buf2);
1108 return buf;
1109 }
1110
1111 errno = ENOSPC;
1112 return NULL;
1113 }
1114# endif
1115
1116 errno = EAFNOSUPPORT;
1117 return NULL; // a family we don't know about
1118}
1119
1120#else // HAVE_INET_NTOP
1121
1122#define KRF_inet_ntop 0
1123
1124#endif // HAVE_INET_NTOP
1125
1126#ifndef HAVE_INET_PTON
1127
1128#define KRF_inet_pton KRF_USING_OWN_INET_PTON
1129int inet_pton(int af, const char *cp, void *buf)
1130{
1131 if (af == AF_INET)
1132 {
1133 // Piece of cake
1134 unsigned p[4];
1135 unsigned char *q = (unsigned char*)buf;
1136 if (sscanf(cp, "%u.%u.%u.%u", p, p + 1, p + 2, p + 3) != 4)
1137 return 0;
1138
1139 if (p[0] > 0xff || p[1] > 0xff || p[2] > 0xff || p[3] > 0xff)
1140 return 0;
1141
1142 q[0] = p[0];
1143 q[1] = p[1];
1144 q[2] = p[2];
1145 q[3] = p[3];
1146
1147 return 1;
1148 }
1149
1150# ifdef AF_INET6
1151 else if (af == AF_INET6)
1152 {
1153 TQ_UINT16 addr[8];
1154 const char *p = cp;
1155 int n = 0, start = 8;
1156 bool has_v4 = strchr(p, '.') != NULL;
1157
1158 memset(addr, 0, sizeof(addr));
1159
1160 if (*p == '\0' || p[1] == '\0')
1161 return 0; // less than 2 chars is not valid
1162
1163 if (*p == ':' && p[1] == ':')
1164 {
1165 start = 0;
1166 p += 2;
1167 }
1168 while (*p)
1169 {
1170 if (has_v4 && inet_pton(AF_INET, p, addr + n) != 0)
1171 {
1172 // successful v4 convertion
1173 addr[n] = ntohs(addr[n]);
1174 n++;
1175 addr[n] = ntohs(addr[n]);
1176 n++;
1177 break;
1178 }
1179 if (sscanf(p, "%hx", addr + n++) != 1)
1180 return 0;
1181
1182 while (*p && *p != ':')
1183 p++;
1184 if (!*p)
1185 break;
1186 p++;
1187
1188 if (*p == ':') // another ':'?
1189 {
1190 if (start != 8)
1191 return 0; // two :: were found
1192 start = n;
1193 p++;
1194 }
1195 }
1196
1197 // if start is not 8, then a "::" was found at word 'start'
1198 // n is the number of converted words
1199 // n == 8 means everything was converted and no moving is necessary
1200 // n < 8 means that we have to move n - start words 8 - n words to the right
1201 if (start == 8 && n != 8)
1202 return 0; // bad conversion
1203 memmove(addr + start + (8 - n), addr + start, (n - start) * sizeof(TQ_UINT16));
1204 memset(addr + start, 0, (8 - n) * sizeof(TQ_UINT16));
1205
1206 // check the byte order
1207 // The compiler should optimise this out in big endian machines
1208 if (htons(0x1234) != 0x1234)
1209 for (n = 0; n < 8; n++)
1210 addr[n] = htons(addr[n]);
1211
1212 memcpy(buf, addr, sizeof(addr));
1213 return 1;
1214 }
1215# endif
1216
1217 errno = EAFNOSUPPORT;
1218 return -1; // unknown family
1219}
1220
1221#else // HAVE_INET_PTON
1222
1223#define KRF_inet_pton 0
1224
1225#endif // HAVE_INET_PTON
1226
1227#ifdef AF_INET6
1228# define KRF_afinet6 KRF_KNOWS_AF_INET6
1229#else
1230# define KRF_afinet6 0
1231#endif
1232
1233namespace KDE
1234{
1236 extern const int TDE_EXPORT resolverFlags = KRF_getaddrinfo | KRF_resolver | KRF_afinet6 | KRF_inet_ntop | KRF_inet_pton;
1237}
TDELocale::i18n
TQString i18n(const char *text)
i18n is the function that does everything you need to translate a string.
Definition: tdelocale.cpp:1976
TDELocale::I18N_NOOP
#define I18N_NOOP(x)
I18N_NOOP marks a string to be translated without translating it.
Definition: tdelocale.h:51
TDEGlobal::kdError
kdbgstream kdError(int area=0)
Returns an error stream.
Definition: kdebug.cpp:374
KDE
Namespace for general KDE functions.
Definition: ktypelist.h:350
KStdAction::name
const char * name(StdAction id)
tdelocale.h

tdecore

Skip menu "tdecore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.9.4
This website is maintained by Timothy Pearson.