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