linux.c (identify): Don't leak the file handle.
[yaid] / addr.c
1 /* -*-c-*-
2 *
3 * Address-type specific functionality
4 *
5 * (c) 2012 Straylight/Edgeware
6 */
7
8 /*----- Licensing notice --------------------------------------------------*
9 *
10 * This file is part of Yet Another Ident Daemon (YAID).
11 *
12 * YAID is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * YAID is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with YAID; if not, write to the Free Software Foundation,
24 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 */
26
27 /*----- Header files ------------------------------------------------------*/
28
29 #include "yaid.h"
30
31 /*----- IPv4 addresses ----------------------------------------------------*/
32
33 static int addreq_ipv4(const union addr *a, const union addr *b)
34 { return a->ipv4.s_addr == b->ipv4.s_addr; }
35
36 static int match_addrpat_ipv4(const struct addrpat *ap, const union addr *a)
37 {
38 unsigned m;
39
40 if (!ap->len) return (1);
41 m = htonl((MASK32 << (32 - ap->len)) & MASK32);
42 return (((ap->addr.ipv4.s_addr ^ a->ipv4.s_addr) & m) == 0);
43 }
44
45 static void socket_to_sockaddr_ipv4(const struct socket *s,
46 void *sa, size_t *ssz)
47 {
48 struct sockaddr_in *sin = sa;
49
50 sin->sin_family = AF_INET;
51 sin->sin_addr = s->addr.ipv4;
52 sin->sin_port = htons(s->port);
53 *ssz = sizeof(*sin);
54 }
55
56 static void sockaddr_to_addr_ipv4(const void *sa, union addr *a)
57 { const struct sockaddr_in *sin = sa; a->ipv4 = sin->sin_addr; }
58
59 static int init_listen_socket_ipv4(int fd) { return (0); }
60
61 static const union addr any_ipv4 = { .ipv4.s_addr = INADDR_ANY };
62
63 /*----- IPv6 addresses ----------------------------------------------------*/
64
65 static int addreq_ipv6(const union addr *a, const union addr *b)
66 { return !memcmp(a->ipv6.s6_addr, b->ipv6.s6_addr, 16); }
67
68 static int match_addrpat_ipv6(const struct addrpat *ap, const union addr *a)
69 {
70 unsigned i = 0, m, n = ap->len;
71
72 if (!n) return (1);
73 for (i = 0; n >= 8; i++, n -= 8)
74 if (ap->addr.ipv6.s6_addr[i] != a->ipv6.s6_addr[i]) return (0);
75 if (!n) return (1);
76 m = (MASK8 << (8 - n)) & MASK8;
77 return (((ap->addr.ipv6.s6_addr[i] ^ a->ipv6.s6_addr[i]) & m) == 0);
78 }
79
80 static void socket_to_sockaddr_ipv6(const struct socket *s,
81 void *sa, size_t *ssz)
82 {
83 struct sockaddr_in6 *sin6 = sa;
84
85 sin6->sin6_family = AF_INET6;
86 sin6->sin6_addr = s->addr.ipv6;
87 sin6->sin6_port = htons(s->port);
88 sin6->sin6_flowinfo = 0;
89 sin6->sin6_scope_id = 0;
90 *ssz = sizeof(*sin6);
91 }
92
93 static void sockaddr_to_addr_ipv6(const void *sa, union addr *a)
94 { const struct sockaddr_in6 *sin6 = sa; a->ipv6 = sin6->sin6_addr; }
95
96 static int init_listen_socket_ipv6(int fd)
97 {
98 int yes = 1;
99
100 if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes)))
101 return (-1);
102 return (0);
103 }
104
105 static const union addr any_ipv6 = { .ipv6 = IN6ADDR_ANY_INIT };
106
107 /*----- General utilities -------------------------------------------------*/
108
109 int sockeq(const struct addrops *ao,
110 const struct socket *sa, const struct socket *sb)
111 { return (ao->addreq(&sa->addr, &sb->addr) && sa->port == sb->port); }
112
113 void dputsock(dstr *d, const struct addrops *ao, const struct socket *s)
114 {
115 char buf[ADDRLEN];
116
117 inet_ntop(ao->af, &s->addr, buf, sizeof(buf));
118 if (!s->port || ao->af != AF_INET6) dstr_puts(d, buf);
119 else { dstr_putc(d, '['); dstr_puts(d, buf); dstr_putc(d, ']'); }
120 if (s->port) dstr_putf(d, ":%d", s->port);
121 }
122
123 /*----- The operations table ----------------------------------------------*/
124
125 const struct addrops addroptab[] = {
126 #define DEFOPS(ty, TY, af, name, len) \
127 { AF_##af, name, len, &any_##ty, &addrops_sys_##ty, \
128 addreq_##ty, match_addrpat_##ty, \
129 socket_to_sockaddr_##ty, sockaddr_to_addr_##ty, \
130 init_listen_socket_##ty },
131 ADDRTYPES(DEFOPS)
132 { 0 }
133 #undef DEFOPS
134 };
135
136 /*----- That's all, folks -------------------------------------------------*/