460b9539 |
1 | /* |
2 | * This file is part of DisOrder. |
3 | * Copyright (C) 2004 Richard Kettlewell |
4 | * |
5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. |
9 | * |
10 | * This program is distributed in the hope that it will be useful, but |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | * General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program; if not, write to the Free Software |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
18 | * USA |
19 | */ |
20 | |
21 | #include <config.h> |
22 | #include "types.h" |
23 | |
24 | #include <stdio.h> |
25 | #include <string.h> |
26 | #include <sys/types.h> |
27 | #include <sys/socket.h> |
28 | #include <netinet/in.h> |
29 | #include <netdb.h> |
30 | |
31 | #include "log.h" |
32 | #include "printf.h" |
33 | #include "configuration.h" |
34 | #include "addr.h" |
35 | |
36 | struct addrinfo *get_address(const struct stringlist *a, |
37 | const struct addrinfo *pref, |
38 | char **namep) { |
39 | struct addrinfo *res; |
40 | char *name; |
41 | int rc; |
42 | |
43 | if(a->n == 1) { |
44 | byte_xasprintf(&name, "host * service %s", a->s[0]); |
45 | if((rc = getaddrinfo(0, a->s[0], pref, &res))) { |
46 | error(0, "getaddrinfo %s: %s", a->s[0], gai_strerror(rc)); |
47 | return 0; |
48 | } |
49 | } else { |
50 | byte_xasprintf(&name, "host %s service %s", a->s[0], a->s[1]); |
51 | if((rc = getaddrinfo(a->s[0], a->s[1], pref, &res))) { |
52 | error(0, "getaddrinfo %s %s: %s", a->s[0], a->s[1], gai_strerror(rc)); |
53 | return 0; |
54 | } |
55 | } |
56 | if(!res || res->ai_socktype != SOCK_STREAM) { |
57 | error(0, "getaddrinfo didn't give us a stream socket"); |
58 | if(res) |
59 | freeaddrinfo(res); |
60 | return 0; |
61 | } |
62 | if(namep) |
63 | *namep = name; |
64 | return res; |
65 | } |
66 | |
67 | int addrinfocmp(const struct addrinfo *a, |
68 | const struct addrinfo *b) { |
69 | const struct sockaddr_in *ina, *inb; |
70 | const struct sockaddr_in6 *in6a, *in6b; |
71 | |
72 | if(a->ai_family != b->ai_family) return a->ai_family - b->ai_family; |
73 | if(a->ai_socktype != b->ai_socktype) return a->ai_socktype - b->ai_socktype; |
74 | if(a->ai_protocol != b->ai_protocol) return a->ai_protocol - b->ai_protocol; |
75 | switch(a->ai_protocol) { |
76 | case PF_INET: |
77 | ina = (const struct sockaddr_in *)a->ai_addr; |
78 | inb = (const struct sockaddr_in *)b->ai_addr; |
79 | if(ina->sin_port != inb->sin_port) return ina->sin_port - inb->sin_port; |
80 | return ina->sin_addr.s_addr - inb->sin_addr.s_addr; |
81 | break; |
82 | case PF_INET6: |
83 | in6a = (const struct sockaddr_in6 *)a->ai_addr; |
84 | in6b = (const struct sockaddr_in6 *)b->ai_addr; |
85 | if(in6a->sin6_port != in6b->sin6_port) |
86 | return in6a->sin6_port - in6b->sin6_port; |
87 | return memcmp(&in6a->sin6_addr, &in6b->sin6_addr, |
88 | sizeof (struct in6_addr)); |
89 | default: |
90 | error(0, "unsupported protocol family %d", a->ai_protocol); |
91 | return memcmp(a->ai_addr, b->ai_addr, a->ai_addrlen); /* kludge */ |
92 | } |
93 | } |
94 | |
95 | /* |
96 | Local Variables: |
97 | c-basic-offset:2 |
98 | comment-column:40 |
99 | End: |
100 | */ |