2 * Copyright (C) 2005-2008 Andre Noll <maan@systemlinux.org>
4 * Licensed under the GPL v2. For licencing details see COPYING.
7 /** \file acl.c Access control lists for paraslash senders. */
16 * Describes one entry in the blacklist/whitelist of a paraslash sender.
19 /** The address to be black/whitelisted. */
21 /** The netmask for this entry. */
23 /** The position of this entry in the acl. */
24 struct list_head node
;
29 * Return true if addr_1 matches addr_2 in the first `netmask' bits.
31 static int v4_addr_match(uint32_t addr_1
, uint32_t addr_2
, uint8_t netmask
)
36 mask
<<= (32 - netmask
);
37 return (htonl(addr_1
) & mask
) == (htonl(addr_2
) & mask
);
40 int acl_lookup(int fd
, struct list_head
*acl
)
42 struct access_info
*ai
, *tmp
;
43 struct sockaddr_storage ss
;
44 socklen_t sslen
= sizeof(ss
);
45 struct in_addr v4_addr
;
47 if (getpeername(fd
, (struct sockaddr
*)&ss
, &sslen
) < 0) {
48 PARA_ERROR_LOG("Can not determine peer address: %s\n", strerror(errno
));
51 v4_addr
= extract_v4_addr(&ss
);
55 list_for_each_entry_safe(ai
, tmp
, acl
, node
)
56 if (v4_addr_match(v4_addr
.s_addr
, ai
->addr
.s_addr
, ai
->netmask
))
62 void acl_add_entry(struct list_head
*acl
, struct in_addr addr
,
65 struct access_info
*ai
= para_malloc(sizeof(struct access_info
));
67 ai
->netmask
= netmask
;
68 PARA_INFO_LOG("adding %s/%i to access list\n", inet_ntoa(ai
->addr
),
70 para_list_add(&ai
->node
, acl
);
74 void acl_del_entry(struct list_head
*acl
, struct in_addr addr
,
77 struct access_info
*ai
, *tmp
;
79 list_for_each_entry_safe(ai
, tmp
, acl
, node
) {
80 char *nad
= para_strdup(inet_ntoa(ai
->addr
));
81 if (!strcmp(nad
, inet_ntoa(addr
)) &&
82 ai
->netmask
== netmask
) {
83 PARA_NOTICE_LOG("removing %s/%i from access list\n",
92 char *acl_get_contents(struct list_head
*acl
)
94 struct access_info
*ai
, *tmp_ai
;
97 list_for_each_entry_safe(ai
, tmp_ai
, acl
, node
) {
98 char *tmp
= make_message("%s%s/%d ", ret
? ret
: "",
99 inet_ntoa(ai
->addr
), ai
->netmask
);
106 void acl_init(struct list_head
*acl
, char * const *acl_info
, int num
)
111 for (i
= 0; i
< num
; i
++) {
112 char *arg
= para_strdup(acl_info
[i
]);
113 char *p
= strchr(arg
, '/');
120 if (!inet_pton(AF_INET
, arg
, &addr
))
123 if (netmask
< 0 || netmask
> 32)
125 acl_add_entry(acl
, addr
, netmask
);
128 PARA_CRIT_LOG("syntax error: %s\n", acl_info
[i
]);