1/*    $Id: server6_conf.c,v 1.1.1.1 2006-12-04 00:45:34 Exp $   */
2
3/*
4 * Copyright (C) International Business Machines  Corp., 2003
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/* Author: Shirley Ma, xma@us.ibm.com */
33
34#include <stdio.h>
35#include <string.h>
36#include <syslog.h>
37#include <stdlib.h>
38#include <errno.h>
39#include <arpa/inet.h>
40#include <sys/socket.h>
41#include <net/if.h>
42//#include <openssl/md5.h>
43
44#include "queue.h"
45#include "dhcp6.h"
46#include "config.h"
47#include "common.h"
48#include "server6_conf.h"
49
50#define NMASK(n) htonl((1<<(n))-1)
51
52static void download_scope __P((struct scope *, struct scope *));
53
54int
55ipv6addrcmp(addr1, addr2)
56	struct in6_addr *addr1;
57	struct in6_addr *addr2;
58{
59	int i;
60	for (i = 0; i < 16; i++) {
61		if (addr1->s6_addr[i] < addr2->s6_addr[i]) return (-1);
62		else if (addr1->s6_addr[i] > addr2->s6_addr[i]) return 1;
63	}
64	return 0;
65}
66
67
68struct in6_addr
69*inc_ipv6addr(current)
70	struct in6_addr *current;
71{
72	int i;
73	for (i = 15; i >= 0; i--) {
74		current->s6_addr[i]++;
75		if (current->s6_addr[i] != 0x00) break;
76	}
77	return current;
78}
79
80struct v6addr
81*getprefix(addr, len)
82	struct in6_addr *addr;
83	int len;
84{
85	int i, num_bytes;
86	struct v6addr *prefix;
87	prefix = (struct v6addr *)malloc(sizeof(*prefix));
88	if (prefix == NULL) {
89		dprintf(LOG_ERR, "%s" "fail to malloc memory", FNAME);
90		return NULL;
91	}
92	memset(prefix, 0, sizeof(*prefix));
93	prefix->plen = len;
94	num_bytes = len / 8;
95	for (i = 0; i < num_bytes; i++) {
96		prefix->addr.s6_addr[i] = 0xFF;
97	}
98	prefix->addr.s6_addr[num_bytes] = (0xFF << 8) - len % 8 ;
99	for (i = 0; i <= num_bytes; i++) {
100		prefix->addr.s6_addr[i] &= addr->s6_addr[i];
101	}
102	for (i = num_bytes + 1; i < 16; i++) {
103		prefix->addr.s6_addr[i] = 0x00;
104	}
105	return prefix;
106}
107
108
109int
110get_numleases(currentpool, poolfile)
111	struct pool_decl *currentpool;
112       	char *poolfile;
113{
114	return 0;
115}
116
117
118struct scopelist
119*push_double_list(current, scope)
120	struct scopelist *current;
121	struct scope *scope;
122{
123	struct scopelist *item;
124	item = (struct scopelist *)malloc(sizeof(*item));
125	if (item == NULL) {
126		dprintf(LOG_ERR, "%s" "fail to allocate memory", FNAME);
127		return NULL;
128	}
129	memset(item, 0, sizeof(*item));
130	item->scope = scope;
131	if (current) {
132		if (current->next)
133			current->next->prev = item;
134		item->next = current->next;
135		current->next = item;
136	} else
137		item->next = NULL;
138	item->prev = current;
139	current = item;
140	return current;
141}
142
143struct scopelist
144*pop_double_list(current)
145       struct scopelist *current;
146{
147	struct scopelist *temp;
148	temp = current;
149	/* current must not be NULL */
150	if (current->next)
151		current->next->prev = current->prev;
152	if (current->prev)
153		current->prev->next = current->next;
154	current = current->prev;
155	temp->prev = NULL;
156	temp->next = NULL;
157	temp->scope = NULL;
158	free(temp);
159	return current;
160}
161
162void
163post_config(root)
164	struct rootgroup *root;
165{
166	struct interface *ifnetwork;
167	struct link_decl *link;
168	struct host_decl *host;
169	struct v6addrseg *seg;
170	struct v6prefix *prefix6;
171	struct scope *current;
172	struct scope *up;
173
174	if (root->group)
175		download_scope(root->group, &root->scope);
176	up = &root->scope;
177	for (ifnetwork = root->iflist; ifnetwork; ifnetwork = ifnetwork->next) {
178		if (ifnetwork->group)
179			download_scope(ifnetwork->group, &ifnetwork->ifscope);
180		current = &ifnetwork->ifscope;
181		download_scope(up, current);
182		up = &ifnetwork->ifscope;
183		for (host = ifnetwork->hostlist; host; host = host->next) {
184			if (host->group)
185				download_scope(host->group, &host->hostscope);
186			current = &host->hostscope;
187			download_scope(up, current);
188		}
189
190	}
191	for (ifnetwork = root->iflist; ifnetwork; ifnetwork = ifnetwork->next) {
192		if (ifnetwork->group)
193			download_scope(ifnetwork->group, &ifnetwork->ifscope);
194		current = &ifnetwork->ifscope;
195		download_scope(up, current);
196		up = &ifnetwork->ifscope;
197		for (link = ifnetwork->linklist; link; link = link->next) {
198				if (link->group)
199					download_scope(link->group, &link->linkscope);
200				current = &link->linkscope;
201				download_scope(up, current);
202				up = &link->linkscope;
203				for (seg = link->seglist; seg; seg = seg->next) {
204					if (seg->pool) {
205						if (seg->pool->group)
206							download_scope(seg->pool->group,
207									&seg->pool->poolscope);
208						current = &seg->pool->poolscope;
209						download_scope(up, current);
210						if (current->prefer_life_time != 0 &&
211						    current->valid_life_time != 0 &&
212						    current->prefer_life_time >
213						    current->valid_life_time) {
214							dprintf(LOG_ERR, "%s"
215					"preferlife time is greater than validlife time",
216							    FNAME);
217							exit (1);
218						}
219						memcpy(&seg->parainfo, current,
220								sizeof(seg->parainfo));
221					} else {
222						memcpy(&seg->parainfo, up,
223								sizeof(seg->parainfo));
224					}
225				}
226				for (prefix6 = link->prefixlist; prefix6;
227						prefix6 = prefix6->next) {
228					if (prefix6->pool) {
229						if (prefix6->pool->group)
230							download_scope(prefix6->pool->group,
231								&prefix6->pool->poolscope);
232						current = &prefix6->pool->poolscope;
233						download_scope(up, current);
234						if (current->prefer_life_time != 0 &&
235						    current->valid_life_time != 0 &&
236						    current->prefer_life_time >
237						    current->valid_life_time) {
238							dprintf(LOG_ERR, "%s"
239					"preferlife time is greater than validlife time",
240							    FNAME);
241							exit (1);
242						}
243						memcpy(&prefix6->parainfo, current,
244								sizeof(prefix6->parainfo));
245					} else {
246						memcpy(&prefix6->parainfo, up,
247								sizeof(prefix6->parainfo));
248					}
249				}
250			}
251	}
252	return;
253}
254
255static void
256download_scope(up, current)
257	struct scope *up;
258	struct scope *current;
259{
260	if (current->prefer_life_time == 0 && up->prefer_life_time != 0)
261		current->prefer_life_time = up->prefer_life_time;
262	if (current->valid_life_time == 0 && up->valid_life_time != 0)
263		current->valid_life_time = up->valid_life_time;
264	if (current->renew_time == 0 && up->renew_time != 0)
265		current->renew_time = up->renew_time;
266	if (current->rebind_time == 0 && up->rebind_time != 0)
267		current->rebind_time = up->rebind_time;
268	if (current->renew_time > current->rebind_time) {
269		dprintf(LOG_ERR, "dhcpv6 server defines T1 > T2");
270		exit(1);
271	}
272	if (current->server_pref == 0 || current->server_pref == DH6OPT_PREF_UNDEF) {
273		if (up->server_pref != 0)
274			current->server_pref = up->server_pref;
275		else
276			current->server_pref = DH6OPT_PREF_UNDEF;
277	}
278	current->allow_flags |= up->allow_flags;
279	current->send_flags |= up->send_flags;
280	if (TAILQ_EMPTY(&current->dnslist.addrlist))
281		dhcp6_copy_list(&current->dnslist.addrlist, &up->dnslist.addrlist);
282	if (TAILQ_EMPTY(&current->siplist))
283		dhcp6_copy_list(&current->siplist, &up->siplist);
284	if (TAILQ_EMPTY(&current->ntplist))
285		dhcp6_copy_list(&current->ntplist, &up->ntplist);
286	if (current->dnslist.domainlist == NULL)
287		current->dnslist.domainlist = up->dnslist.domainlist;
288	return;
289}
290
291int
292is_anycast(struct in6_addr *in, int plen)
293{
294	int wc;
295
296	if (plen == 64) { /* assume EUI64 */
297		/* doesn't cover none EUI64 */
298		return in->s6_addr32[2] == htonl(0xFDFFFFFF) &&
299			(in->s6_addr32[3] | htonl(0x7f)) ==
300				(u_int32_t) ~0;
301	}
302	/* not EUI64 */
303	if (plen > 121)
304		return 0;
305	wc = plen / 32;
306	if (plen) {
307		if (in->s6_addr32[wc] != NMASK(32 - (plen%32)))
308			return 0;
309		wc++;
310
311	}
312	for (/*empty*/; wc < 2; wc++)
313		if (in->s6_addr32[wc] != (u_int32_t) ~0)
314			return 0;
315	return (in->s6_addr32[3] | htonl(0x7f)) == (u_int32_t)~0;
316}
317