⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 config.c

📁 IPv6环境下的DHCP实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*	$KAME: config.c,v 1.20 2002/06/14 15:32:55 jinmei Exp $	*//* * Copyright (C) 2002 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include <sys/types.h>#include <sys/socket.h>#include <sys/queue.h>#include <net/if_dl.h>#include <netinet/in.h>#include <syslog.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <ifaddrs.h>#include <dhcp6.h>#include <config.h>#include <common.h>extern int errno;struct dhcp6_if *dhcp6_if;struct prefix_ifconf *prefix_ifconflist;struct dhcp6_list dnslist;static struct dhcp6_ifconf *dhcp6_ifconflist;static struct prefix_ifconf *prefix_ifconflist0;static struct host_conf *host_conflist0, *host_conflist;static struct dhcp6_list dnslist0; enum { DHCPOPTCODE_SEND, DHCPOPTCODE_REQUEST, DHCPOPTCODE_ALLOW };extern struct cf_list *cf_dns_list;extern char *configfilename;static int add_options __P((int, struct dhcp6_ifconf *, struct cf_list *));static int add_prefix __P((struct host_conf *, struct dhcp6_prefix *));static void clear_ifconf __P((struct dhcp6_ifconf *));static void clear_prefixifconf __P((struct prefix_ifconf *));static void clear_hostconf __P((struct host_conf *));static void clear_options __P((struct dhcp6_optconf *));static int configure_duid __P((char *, struct duid *));static int get_default_ifid __P((struct prefix_ifconf *));voidifinit(ifname)	char *ifname;{	struct dhcp6_if *ifp;	if ((ifp = find_ifconfbyname(ifname)) != NULL) {		dprintf(LOG_NOTICE, "%s" "duplicated interface: %s",			FNAME, ifname);		return;	}	if ((ifp = malloc(sizeof(*ifp))) == NULL) {		dprintf(LOG_ERR, "%s" "malloc failed", FNAME);		goto die;	}	memset(ifp, 0, sizeof(*ifp));	TAILQ_INIT(&ifp->event_list);	if ((ifp->ifname = strdup(ifname)) == NULL) {		dprintf(LOG_ERR, "%s" "failed to copy ifname", FNAME);		goto die;	}	if ((ifp->ifid = if_nametoindex(ifname)) == 0) {		dprintf(LOG_ERR, "%s" "invalid interface(%s): %s", FNAME,			ifname, strerror(errno));		goto die;	}#ifdef HAVE_SCOPELIB	if (inet_zoneid(AF_INET6, 2, ifname, &ifp->linkid)) {		dprintf(LOG_ERR, "%s" "failed to get link ID for %s",			FNAME, ifname);		goto die;	}#else	ifp->linkid = ifp->ifid; /* XXX */#endif	ifp->next = dhcp6_if;	dhcp6_if = ifp;	return;  die:	exit(1);}intconfigure_interface(iflist)	struct cf_namelist *iflist;{	struct cf_namelist *ifp;	struct dhcp6_ifconf *ifc;	for (ifp = iflist; ifp; ifp = ifp->next) {		struct cf_list *cfl;		if ((ifc = malloc(sizeof(*ifc))) == NULL) {			dprintf(LOG_ERR, "%s"				"memory allocation for %s failed", FNAME,				ifp->name);			goto bad;		}		memset(ifc, 0, sizeof(*ifc));		ifc->next = dhcp6_ifconflist;		dhcp6_ifconflist = ifc;		if ((ifc->ifname = strdup(ifp->name)) == NULL) {			dprintf(LOG_ERR, "%s" "failed to copy ifname", FNAME);			goto bad;		}		ifc->server_pref = DH6OPT_PREF_UNDEF;		TAILQ_INIT(&ifc->reqopt_list);		for (cfl = ifp->params; cfl; cfl = cfl->next) {			switch(cfl->type) {			case DECL_REQUEST:				if (dhcp6_mode != DHCP6_MODE_CLIENT) {					dprintf(LOG_INFO, "%s" "%s:%d "						"client-only configuration",						FNAME, configfilename,						cfl->line);					goto bad;				}				if (add_options(DHCPOPTCODE_REQUEST,						ifc, cfl->list)) {					goto bad;				}				break;			case DECL_SEND:				if (add_options(DHCPOPTCODE_SEND,						ifc, cfl->list)) {					goto bad;				}				break;			case DECL_ALLOW:				if (add_options(DHCPOPTCODE_ALLOW,						ifc, cfl->list)) {					goto bad;				}				break;			case DECL_INFO_ONLY:				if (dhcp6_mode != DHCP6_MODE_CLIENT) {					dprintf(LOG_INFO, "%s" "%s:%d "						"client-only configuration",						FNAME, configfilename,						cfl->line);					goto bad;				}				ifc->send_flags |= DHCIFF_INFO_ONLY;				break;			case DECL_PREFERENCE:				if (dhcp6_mode != DHCP6_MODE_SERVER) {					dprintf(LOG_INFO, "%s" "%s:%d "						"server-only configuration",						FNAME, configfilename,						cfl->line);					goto bad;				}				ifc->server_pref = (int)cfl->num;				if (ifc->server_pref < 0 ||				    ifc->server_pref > 255) {					dprintf(LOG_INFO, "%s" "%s:%d "						"bad value: %d", FNAME,						configfilename, cfl->line,						ifc->server_pref);					goto bad;				}				break;			default:				dprintf(LOG_ERR, "%s" "%s:%d "					"invalid interface configuration",					FNAME, configfilename, cfl->line);				goto bad;			}		}	}		return(0);  bad:	clear_ifconf(dhcp6_ifconflist);	dhcp6_ifconflist = NULL;	return(-1);}intconfigure_prefix_interface(iflist)	struct cf_namelist *iflist;{	struct cf_namelist *ifp;	struct prefix_ifconf *pif;	for (ifp = iflist; ifp; ifp = ifp->next) {		struct cf_list *cfl;		if ((pif = malloc(sizeof(*pif))) == NULL) {			dprintf(LOG_ERR, "%s"				"memory allocation for %s failed", FNAME,				ifp->name);			goto bad;		}		memset(pif, 0, sizeof(*pif));		pif->next = prefix_ifconflist0;		prefix_ifconflist0 = pif;		/* validate and copy ifname */		if (if_nametoindex(ifp->name) == 0) {			dprintf(LOG_ERR, "%s" "invalid interface (%s): %s",				FNAME, ifp->name, strerror(errno));			goto bad;		}		if ((pif->ifname = strdup(ifp->name)) == NULL) {			dprintf(LOG_ERR, "%s" "failed to copy ifname", FNAME);			goto bad;		}		pif->ifid_len = IFID_LEN_DEFAULT;		pif->sla_len = SLA_LEN_DEFAULT;		if (get_default_ifid(pif)) {			dprintf(LOG_NOTICE, "%s"				"failed to get default IF ID for %s",				FNAME, pif->ifname);			goto bad;		}		for (cfl = ifp->params; cfl; cfl = cfl->next) {			switch(cfl->type) {			case IFPARAM_SLA_ID:				pif->sla_id = (u_int32_t)cfl->num;				break;			case IFPARAM_SLA_LEN:				pif->sla_len = (int)cfl->num;				if (pif->sla_len < 0 || pif->sla_len > 128) {					dprintf(LOG_ERR, "%s"					    "invalid SLA length: %d", FNAME,					    pif->sla_len);					goto bad;				}				break;			default:				dprintf(LOG_ERR, "%s" "%s:%d "					"invalid configuration", FNAME,					configfilename, cfl->line);				goto bad;			}		}	}		return(0);  bad:	/* there is currently nothing special to recover the error */	return(-1);}intconfigure_host(hostlist)	struct cf_namelist *hostlist;{	struct cf_namelist *host;	struct host_conf *hconf;	for (host = hostlist; host; host = host->next) {		struct cf_list *cfl;		if ((hconf = malloc(sizeof(*hconf))) == NULL) {			dprintf(LOG_ERR, "%s" "memory allocation failed "				"for host %s", FNAME, host->name);			goto bad;		}		memset(hconf, 0, sizeof(*hconf));		TAILQ_INIT(&hconf->prefix_list);		TAILQ_INIT(&hconf->prefix_binding_list);		hconf->next = host_conflist0;		host_conflist0 = hconf;		if ((hconf->name = strdup(host->name)) == NULL) {			dprintf(LOG_ERR, "%s" "failed to copy host name: %s",				FNAME, host->name);			goto bad;		}		for (cfl = host->params; cfl; cfl = cfl->next) {			switch(cfl->type) {			case DECL_DUID:				if (hconf->duid.duid_id) {					dprintf(LOG_ERR, "%s" "%s:%d "						"duplicated DUID for %s",						FNAME, configfilename,						cfl->line, host->name);					goto bad;				}				if ((configure_duid((char *)cfl->ptr,						    &hconf->duid)) != 0) {					dprintf(LOG_ERR, "%s" "%s:%d "						"failed to configure "						"DUID for %s", FNAME,						configfilename, cfl->line,						host->name);					goto bad;				}				dprintf(LOG_DEBUG, "%s"					"configure DUID for %s: %s", FNAME,					host->name, duidstr(&hconf->duid));				break;			case DECL_PREFIX:				if (add_prefix(hconf, cfl->ptr)) {					dprintf(LOG_ERR, "%s" "failed "						"to configure prefix for %s",						FNAME, host->name);					goto bad;				}				break;			default:				dprintf(LOG_ERR, "%s" "%s:%d "					"invalid host configuration for %s"					FNAME, configfilename, cfl->line,					host->name);				goto bad;			}		}	}	return(0);  bad:	/* there is currently nothing special to recover the error */	return(-1);}intconfigure_global_option(){	struct cf_list *cl;	/* DNS servers */	if (cf_dns_list && dhcp6_mode != DHCP6_MODE_SERVER) {		dprintf(LOG_INFO, "%s" "%s:%d server-only configuration",		    FNAME, configfilename, cf_dns_list->line);		goto bad;	}	TAILQ_INIT(&dnslist0);	for (cl = cf_dns_list; cl; cl = cl->next) {		/* duplication check */		if (dhcp6_find_listval(&dnslist0, cl->ptr,		    DHCP6_LISTVAL_ADDR6)) {			dprintf(LOG_INFO, "%s"			    "%s:%d duplicated DNS server: %s", FNAME,			    configfilename, cl->line,			    in6addr2str((struct in6_addr *)cl->ptr, 0));			goto bad;		}		if (dhcp6_add_listval(&dnslist0, cl->ptr,		    DHCP6_LISTVAL_ADDR6) == NULL) {			dprintf(LOG_ERR, "%s" "failed to add a DNS server");			goto bad;		}	}	return 0;  bad:	return -1;}static intconfigure_duid(str, duid)	char *str;		/* this is a valid DUID string */	struct duid *duid;{	char *cp, *bp;	char *idbuf = NULL;	int duidlen, slen;	/* calculate DUID len */	slen = strlen(str);	if (slen < 2)		goto bad;	duidlen = 1;	slen -= 2;	if ((slen % 3) != 0)		goto bad;	duidlen += (slen / 3);	if (duidlen > 256) {		dprintf(LOG_ERR, "%s" "too long DUID (%d)", FNAME, duidlen);		return(-1);	}	if ((idbuf = malloc(sizeof(duidlen))) == NULL) {		dprintf(LOG_ERR, "%s" "memory allocation failed", FNAME);		return(-1);	}	for (cp = str, bp = idbuf; *cp;) {		if (*cp == ':') {			cp++;			continue;		}		if (sscanf(cp, "%02x", bp) != 1)			goto bad;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -