1313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* $USAGI: ninfod_name.c,v 1.15 2003-01-11 14:33:28 yoshfuji Exp $ */
2313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/*
3313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Copyright (C) 2002 USAGI/WIDE Project.
4313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * All rights reserved.
5313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *
6313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Redistribution and use in source and binary forms, with or without
7313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * modification, are permitted provided that the following conditions
8313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * are met:
9313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 1. Redistributions of source code must retain the above copyright
10313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *    notice, this list of conditions and the following disclaimer.
11313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 2. Redistributions in binary form must reproduce the above copyright
12313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *    notice, this list of conditions and the following disclaimer in the
13313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *    documentation and/or other materials provided with the distribution.
14313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 3. Neither the name of the project nor the names of its contributors
15313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *    may be used to endorse or promote products derived from this software
16313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *    without specific prior written permission.
17313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti *
18313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
19313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
22313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * SUCH DAMAGE.
29313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */
30313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/*
31313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * Author:
32313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti * 	YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
33313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti */
34313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
35313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_CONFIG_H
36313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include "config.h"
37313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
38313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
39313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_SYS_TYPES_H
40313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <sys/types.h>
41313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
42313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if STDC_HEADERS
43313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <stdio.h>
44313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <stdlib.h>
45313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <stddef.h>
46313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <ctype.h>
47313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else
48313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# if HAVE_STDLIB_H
49313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#  include <stdlib.h>
50313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# endif
51313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
52313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_STRING_H
53313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# if !STDC_HEADERS && HAVE_MEMORY_H
54313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#  include <memory.h>
55313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# endif
56313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <string.h>
57313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
58313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_STRINGS_H
59313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <strings.h>
60313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
61313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_INTTYPES_H
62313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <inttypes.h>
63313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else
64313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# if HAVE_STDINT_H
65313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#  include <stdint.h>
66313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# endif
67313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
68313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_UNISTD_H
69313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <unistd.h>
70313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
71313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
72313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if TIME_WITH_SYS_TIME
73313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <sys/time.h>
74313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <time.h>
75313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else
76313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# if HAVE_SYS_TIME_H
77313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#  include <sys/time.h>
78313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# else
79313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#  include <time.h>
80313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# endif
81313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
82313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
83313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_SYS_UIO_H
84313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/uio.h>
85313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
86313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
87313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <sys/socket.h>
88313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
89313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_NETINET_IN_H
90313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <netinet/in.h>
91313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
92313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
93313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_NETINET_ICMP6_H
94313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <netinet/icmp6.h>
95313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
96313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef HAVE_STRUCT_ICMP6_NODEINFO
97313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include "icmp6_nodeinfo.h"
98313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
99313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
100313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <arpa/inet.h>
101313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
102313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if defined(HAVE_GNUTLS_OPENSSL_H)
103313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <gnutls/openssl.h>
104313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#elif defined(HAVE_OPENSSL_MD5_H)
105313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <openssl/md5.h>
106313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
107313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
108313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_SYS_UTSNAME_H
109313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <sys/utsname.h>
110313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
111313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_NETDB_H
112313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <netdb.h>
113313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
114313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include <errno.h>
115313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
116313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if HAVE_SYSLOG_H
117313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# include <syslog.h>
118313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
119313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
120313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#include "ninfod.h"
121313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
122313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef offsetof
123313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# define offsetof(aggregate,member)	((size_t)&((aggregate *)0)->member)
124313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
125313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
126313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Hmm,,, */
127313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifndef IPV6_JOIN_GROUP
128313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# define IPV6_JOIN_GROUP	IPV6_ADD_MEMBERSHIP
129313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti# define IPV6_LEAVE_GROUP	IPV6_DROP_MEMBERSHIP
130313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
131313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
132313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------- */
133313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ID */
134313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic char *RCSID __attribute__ ((unused)) = "$USAGI: ninfod_name.c,v 1.15 2003-01-11 14:33:28 yoshfuji Exp $";
135313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
136313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Variables */
137313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic struct utsname utsname;
138313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic char *uts_nodename = utsname.nodename;
139313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
140313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittichar nodename[MAX_DNSNAME_SIZE];
141313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic size_t nodenamelen;
142313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
143313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic struct ipv6_mreq nigroup;
144313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
145313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------- */
146313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* Functions */
147313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint check_nigroup(const struct in6_addr *addr)
148313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
149313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return IN6_IS_ADDR_MULTICAST(&nigroup.ipv6mr_multiaddr) &&
150313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	       IN6_ARE_ADDR_EQUAL(&nigroup.ipv6mr_multiaddr, addr);
151313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
152313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
153313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int encode_dnsname(const char *name,
154313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			  char *buf, size_t buflen,
155313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			  int fqdn)
156313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
157313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	size_t namelen;
158313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int i;
159313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
160313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (buflen < 0)
161313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;
162313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
163313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	namelen = strlen(name);
164313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (namelen == 0)
165313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return 0;
166313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (namelen > 255 || buflen < namelen+1)
167313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;
168313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
169313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	i = 0;
170313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	while(i <= namelen) {
171313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		const char *e;
172313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		int llen, ii;
173313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
174313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		e = strchr(&name[i], '.');
175313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (e == NULL)
176313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			e = name + namelen;
177313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		llen = e - &name[i];
178313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (llen == 0) {
179313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (*e)
180313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				return -1;
181313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (fqdn < 0)
182313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				return -1;
183313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			fqdn = 1;
184313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			break;
185313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
186313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (llen >= 0x40)
187313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			return -1;
188313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		buf[i] = llen;
189313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		for (ii = 0; ii < llen; ii++) {
190313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (!isascii(name[i+ii]))
191313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				return -1;
192313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (ii == 0 || ii == llen-1) {
193313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (!isalpha(name[i+ii]) && !isdigit(name[i+ii]))
194313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					return -1;
195313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			} else if (!isalnum(name[i+ii]) && name[i+ii] != '-')
196313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				return -1;
197313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			buf[i+ii+1] = isupper(name[i+ii]) ? tolower(name[i+ii]) : name[i+ii];
198313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
199313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		i += llen + 1;
200313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
201313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (buflen < i + 1 + !(fqdn > 0))
202313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;
203313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	buf[i++] = 0;
204313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!(fqdn > 0))
205313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		buf[i++] = 0;
206313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return i;
207313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
208313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
209313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int compare_dnsname(const char *s, size_t slen,
210313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			   const char *n, size_t nlen)
211313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
212313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	const char *s0 = s, *n0 = n;
213313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int done = 0, retcode = 0;
214313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (slen < 1 || nlen < 1)
215313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;	/* invalid length */
216313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* simple case */
217313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (slen == nlen && memcmp(s, n, slen) == 0)
218313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return 0;
219313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (*(s0 + slen - 1) || *(n0 + nlen - 1))
220313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;	/* invalid termination */
221313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	while (s < s0 + slen && n < n0 + nlen) {
222313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (*s >= 0x40 || *n >= 0x40)
223313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			return -1;	/* DNS compression is not allowed here */
224313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (s + *s + 1 > s0 + slen || n + *n + 1 > n0 + nlen)
225313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			return -1;	/* overrun */
226313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (*s == '\0') {
227313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (s == s0 + slen - 1)
228313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				break;	/* FQDN */
229313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			else if (s + 1 == s0 + slen - 1)
230313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				return retcode;	/* truncated */
231313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			else
232313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				return -1;	/* more than one subject */
233313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
234313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (!done) {
235313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (*n == '\0') {
236313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (n == n0 + nlen - 1) {
237313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					done = 1;	/* FQDN */
238313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				} else if (n + 1 == n0 + nlen - 1) {
239313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					retcode = 1;	// trunc
240313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					done = 1;
241313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				} else
242313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					return -1;
243313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			} else {
244313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (*s != *n) {
245313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					done = 1;
246313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					retcode = 1;
247313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				} else {
248313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					if (memcmp(s+1, n+1, *s)) {
249313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti						done = 1;
250313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti						retcode = 1;
251313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					}
252313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				}
253313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
254313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
255313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		s += *s + 1;
256313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		n += done ? 0 : (*n + 1);
257313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
258313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return retcode;
259313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
260313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
261313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittistatic int nodeinfo_group(const char *dnsname, int namelen,
262313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			  struct in6_addr *nigroup)
263313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
264313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	MD5_CTX ctxt;
265313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	unsigned char digest[16];
266313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
267313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!dnsname || !nigroup)
268313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return -1;
269313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
270313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	MD5_Init(&ctxt);
271313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	MD5_Update(&ctxt, dnsname, *dnsname);
272313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	MD5_Final(digest, &ctxt);
273313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
274313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#ifdef s6_addr32
275313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	nigroup->s6_addr32[0] = htonl(0xff020000);
276313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	nigroup->s6_addr32[1] = 0;
277313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	nigroup->s6_addr32[2] = htonl(0x00000002);
278313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#else
279313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memset(nigroup, 0, sizeof(*nigroup));
280313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	nigroup->s6_addr[ 0] = 0xff;
281313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	nigroup->s6_addr[ 1] = 0x02;
282313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	nigroup->s6_addr[11] = 0x02;
283313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
284313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memcpy(&nigroup->s6_addr[12], digest, 4);
285313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
286313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return 0;
287313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
288313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
289313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------- */
290313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittivoid init_nodeinfo_nodename(int forced)
291313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
292313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	struct utsname newname;
293313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int len;
294313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	int changed = 0;
295313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
296313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	DEBUG(LOG_DEBUG, "%s()\n", __func__);
297313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
298313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	uname(&newname);
299313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	changed = strcmp(newname.nodename, utsname.nodename);
300313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
301313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (!changed && !forced)
302313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		return;
303313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
304313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	memcpy(&utsname, &newname, sizeof(newname));
305313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
306313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* leave old group */
307313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if ((changed || forced) && !IN6_IS_ADDR_UNSPECIFIED(&nigroup.ipv6mr_multiaddr)) {
308313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (setsockopt(sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &nigroup, sizeof(nigroup)) < 0) {
309313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if ENABLE_DEBUG
310313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			char niaddrbuf[INET6_ADDRSTRLEN];
311313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (inet_ntop(AF_INET6, &nigroup, niaddrbuf, sizeof(niaddrbuf)) == NULL)
312313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				strcpy(niaddrbuf, "???");
313313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
314313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			DEBUG(LOG_WARNING,
315313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      "%s(): failed to leave group %s.\n",
316313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			      __func__, niaddrbuf);
317313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			memset(&nigroup, 0, sizeof(nigroup));
318313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
319313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
320313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
321313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	len = encode_dnsname(uts_nodename,
322313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			     nodename,
323313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			     sizeof(nodename),
324313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			     0);
325313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
326313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* setup ni reply */
327313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	nodenamelen = len > 0 ? len : 0;
328313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
329313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	/* setup ni group */
330313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (changed || forced) {
331313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (nodenamelen) {
332313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			memset(&nigroup, 0, sizeof(nigroup));
333313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			nodeinfo_group(nodename, len, &nigroup.ipv6mr_multiaddr);
334313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			nigroup.ipv6mr_interface = 0;
335313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &nigroup, sizeof(nigroup)) < 0) {
336313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#if ENABLE_DEBUG
337313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				char niaddrbuf[INET6_ADDRSTRLEN];
338313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				if (inet_ntop(AF_INET6, &nigroup, niaddrbuf, sizeof(niaddrbuf)) == NULL)
339313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti					strcpy(niaddrbuf, "???");
340313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti#endif
341313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				DEBUG(LOG_WARNING,
342313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				      "%s(): failed to join group %s.\n",
343313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				      __func__, niaddrbuf);
344313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				memset(&nigroup, 0, sizeof(nigroup));
345313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			}
346313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		} else {
347313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			memset(&nigroup, 0, sizeof(nigroup));
348313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
349313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
350313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
351313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return;
352313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
353313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
354313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* ---------- */
355313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti/* nodename */
356313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colittiint pr_nodeinfo_nodename(CHECKANDFILL_ARGS)
357313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti{
358313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	DEBUG(LOG_DEBUG, "%s()\n", __func__);
359313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
360313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (subject) {
361313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (!nodenamelen ||
362313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		    compare_dnsname(subject, subjlen,
363313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				    nodename,
364313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti				    nodenamelen))
365313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			return 1;
366313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (subj_if)
367313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			*subj_if = p->pktinfo.ipi6_ifindex;
368313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
369313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
370313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	if (reply) {
371313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		uint32_t ttl = 0;
372313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
373313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->reply.ni_type = ICMP6_NI_REPLY;
374313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->reply.ni_code = ICMP6_NI_SUCCESS;
375313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->reply.ni_cksum = 0;
376313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->reply.ni_qtype = htons(NI_QTYPE_DNSNAME);
377313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->reply.ni_flags = 0;
378313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
379313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->replydatalen = nodenamelen ? sizeof(ttl)+nodenamelen : 0;
380313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		p->replydata = nodenamelen ? ni_malloc(p->replydatalen) : NULL;
381313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		if (p->replydata) {
382313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			memcpy(p->replydata, &ttl, sizeof(ttl));
383313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti			memcpy(p->replydata + sizeof(ttl), &nodename, nodenamelen);
384313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti		}
385313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	}
386313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
387313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti	return 0;
388313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti}
389313379eb6b9da55f7371adef39a92153a0707d4aLorenzo Colitti
390