?? config.c
字號:
/* $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 + -