📄 server6_parse.y
字号:
/* $Id: server6_parse.y,v 1.9 2004/02/05 00:10:31 shemminger Exp $ *//* * Copyright (C) International Business Machines Corp., 2003 * 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. *//* Author: Shirley Ma, xma@us.ibm.com */%{#include <stdio.h>#include <string.h>#include <syslog.h>#include <errno.h>#include <sys/socket.h>#include <net/if.h>#include <linux/ipv6.h>#include "queue.h"#include "dhcp6.h"#include "config.h"#include "common.h"#include "server6_conf.h"#include "hash.h"#include "lease.h"extern int num_lines;extern char *sfyytext;extern int sock;static struct interface *ifnetworklist = NULL;static struct link_decl *linklist = NULL;static struct host_decl *hostlist = NULL;static struct pool_decl *poollist = NULL;static struct interface *ifnetwork = NULL;static struct link_decl *link = NULL;static struct host_decl *host = NULL;static struct pool_decl *pool = NULL;static struct scopelist *currentscope = NULL;static struct scopelist *currentgroup = NULL;static int allow = 0;static void cleanup(void);void sfyyerror(char *msg);#define ABORT do { cleanup(); YYABORT; } while (0)extern int sfyylex __P((void));%}%token <str> INTERFACE IFNAME%token <str> PREFIX%token <str> LINK %token <str> RELAY%token <str> STRING%token <num> NUMBER%token <snum> SIGNEDNUMBER%token <dec> DECIMAL%token <bool> BOOLEAN%token <addr> IPV6ADDR%token <str> INFINITY%token <str> HOST%token <str> POOL%token <str> RANGE%token <str> GROUP%token <str> LINKLOCAL%token <str> OPTION ALLOW SEND%token <str> PREFERENCE%token <str> RENEWTIME%token <str> REBINDTIME%token <str> RAPIDCOMMIT%token <str> ADDRESS%token <str> VALIDLIFETIME%token <str> PREFERLIFETIME%token <str> UNICAST%token <str> TEMPIPV6ADDR%token <str> DNS_SERVERS%token <str> DUID DUID_ID%token <str> IAID IAIDINFO%token <str> INFO_ONLY%token <str> TO%token <str> BAD_TOKEN%type <str> name%type <num> number_or_infinity%type <dhcp6addr> hostaddr6 hostprefix6 addr6para v6address%union { unsigned int num; int snum; char *str; int dec; int bool; struct in6_addr addr; struct dhcp6_addr *dhcp6addr;}%%statements : | statements networkdef ;networkdef : ifdef | groupdef | confdecl | linkdef ;ifdef : ifhead '{' ifbody '}' ';' { if (linklist) { ifnetwork->linklist = linklist; linklist = NULL; } if (hostlist) { ifnetwork->hostlist = hostlist; hostlist = NULL; } if (currentgroup) ifnetwork->group = currentgroup->scope; dprintf(LOG_DEBUG, "interface definition for %s is ok", ifnetwork->name); ifnetwork->next = ifnetworklist; ifnetworklist = ifnetwork; ifnetwork = NULL; globalgroup->iflist = ifnetworklist; /* leave interface scope we know the current scope is not point to NULL*/ currentscope = pop_double_list(currentscope); } ;ifhead : INTERFACE IFNAME { struct interface *temp_if = ifnetworklist; while (temp_if) { if (!strcmp(temp_if->name, $2)) { dprintf(LOG_ERR, "duplicate interface definition for %s", temp_if->name); ABORT; } temp_if = temp_if->next; } ifnetwork = (struct interface *)malloc(sizeof(*ifnetwork)); if (ifnetwork == NULL) { dprintf(LOG_ERR, "failed to allocate memory"); ABORT; } memset(ifnetwork, 0, sizeof(*ifnetwork)); TAILQ_INIT(&ifnetwork->ifscope.dnslist.addrlist); strncpy(ifnetwork->name, $2, strlen($2)); if (get_linklocal(ifnetwork->name, &ifnetwork->linklocal) < 0) { dprintf(LOG_ERR, "get device %s linklocal failed", ifnetwork->name); } /* check device, if the device is not available, * it is OK, it might be added later * so keep this in the configuration file. */ if (if_nametoindex(ifnetwork->name) == 0) { dprintf(LOG_ERR, "this device %s doesn't exist.", $2); } /* set up hw_addr, link local, primary ipv6addr */ /* enter interface scope */ currentscope = push_double_list(currentscope, &ifnetwork->ifscope); if (currentscope == NULL) ABORT; } ;ifbody : | ifbody ifparams ;ifparams : linkdef | hostdef | groupdef | confdecl ; linkdef : linkhead '{' linkbody '}' ';' { if (poollist) { link->poollist = poollist; poollist = NULL; } if (currentgroup) link->group = currentgroup->scope; link->next = linklist; linklist = link; link = NULL; /* leave iink scope we know the current scope is not point to NULL*/ currentscope = pop_double_list(currentscope); } ;linkhead : LINK name { struct link_decl *temp_sub = linklist; /* memory allocation for link */ link = (struct link_decl *)malloc(sizeof(*link)); if (link == NULL) { dprintf(LOG_ERR, "failed to allocate memory"); ABORT; } memset(link, 0, sizeof(*link)); TAILQ_INIT(&link->linkscope.dnslist.addrlist); while (temp_sub) { if (!strcmp(temp_sub->name, $2)) { dprintf(LOG_ERR, "duplicate link definition for %s", $2); ABORT; } temp_sub = temp_sub->next; } /* link set */ strncpy(link->name, $2, strlen($2)); if (ifnetwork) link->network = ifnetwork; else { /* create a ifnetwork for this interface */ } link->relaylist = NULL; link->seglist = NULL; /* enter link scope */ currentscope = push_double_list(currentscope, &link->linkscope); if (currentscope == NULL) ABORT; } ; linkbody : | linkbody linkparams | relaylist ;linkparams : pooldef | rangedef | prefixdef | hostdef | groupdef | confdecl ;relaylist : relaylist relaypara | relaypara ;relaypara : RELAY IPV6ADDR '/' NUMBER ';' { struct v6addrlist *temprelay; if (!link) { dprintf(LOG_ERR, "relay must be defined under link"); ABORT; } temprelay = (struct v6addrlist *)malloc(sizeof(*temprelay)); if (temprelay == NULL) { dprintf(LOG_ERR, "failed to allocate memory"); ABORT; } memset(temprelay, 0, sizeof(*temprelay)); memcpy(&temprelay->v6addr.addr, &$2, sizeof(temprelay->v6addr.addr)); temprelay->v6addr.plen = $4; temprelay->next = link->relaylist; link->relaylist = temprelay; temprelay = NULL; } ;pooldef : poolhead '{' poolbody '}' ';' { if (currentgroup) pool->group = currentgroup->scope; pool->next = poollist; poollist = pool; pool = NULL; /* leave pool scope we know the current scope is not point to NULL*/ currentscope = pop_double_list(currentscope); } ;poolhead : POOL { if (!link) { dprintf(LOG_ERR, "pooldef must be defined under link"); ABORT; } pool = (struct pool_decl *)malloc(sizeof(*pool)); if (pool == NULL) { dprintf(LOG_ERR, "fail to allocate memory"); ABORT; } memset(pool, 0, sizeof(*pool)); TAILQ_INIT(&pool->poolscope.dnslist.addrlist); if (link) pool->link = link; /* enter pool scope */ currentscope = push_double_list(currentscope, &pool->poolscope); if (currentscope == NULL) ABORT; } ;poolbody : | poolbody poolparas ;poolparas : hostdef | groupdef | rangedef | prefixdef | confdecl ;prefixdef : PREFIX IPV6ADDR '/' NUMBER ';' { struct v6prefix *v6prefix, *v6prefix0; struct v6addr *prefix; if (!link) { dprintf(LOG_ERR, "prefix must be defined under link"); ABORT; } v6prefix = (struct v6prefix *)malloc(sizeof(*v6prefix)); if (v6prefix == NULL) { dprintf(LOG_ERR, "failed to allocate memory"); ABORT; } memset(v6prefix, 0, sizeof(*v6prefix)); v6prefix->link = link; if (pool) v6prefix->pool = pool; /* make sure the range ipv6 address within the prefixaddr */ if ($4 > 128 || $4 < 0) { dprintf(LOG_ERR, "invalid prefix length in line %d", num_lines); ABORT; } prefix = getprefix(&$2, $4); for (v6prefix0 = link->prefixlist; v6prefix0; v6prefix0 = v6prefix0->next) { if (IN6_ARE_ADDR_EQUAL(prefix, &v6prefix0->prefix.addr) && $4 == v6prefix0->prefix.plen) { dprintf(LOG_ERR, "duplicated prefix defined within same link"); ABORT; } } /* check the assigned prefix is not reserved pv6 addresses */ if (IN6_IS_ADDR_RESERVED(prefix)) { dprintf(LOG_ERR, "config reserved prefix"); ABORT; } memcpy(&v6prefix->prefix, prefix, sizeof(v6prefix->prefix)); v6prefix->next = link->prefixlist; link->prefixlist = v6prefix; free(prefix); } ;rangedef : RANGE IPV6ADDR TO IPV6ADDR '/' NUMBER ';' { struct v6addrseg *seg, *temp_seg; struct v6addr *prefix1, *prefix2; if (!link) { dprintf(LOG_ERR, "range must be defined under link"); ABORT; } seg = (struct v6addrseg *)malloc(sizeof(*seg)); if (seg == NULL) { dprintf(LOG_ERR, "failed to allocate memory"); ABORT; } memset(seg, 0, sizeof(*seg)); temp_seg = link->seglist; seg->link = link; if (pool) seg->pool = pool; /* make sure the range ipv6 address within the prefixaddr */ if ($6 > 128 || $6 < 0) { dprintf(LOG_ERR, "invalid prefix length in line %d", num_lines); ABORT; } prefix1 = getprefix(&$2, $6); prefix2 = getprefix(&$4, $6); if (!prefix1 || !prefix2) { dprintf(LOG_ERR, "address range defined error"); ABORT; } if (ipv6addrcmp(&prefix1->addr, &prefix2->addr)) { dprintf(LOG_ERR, "address range defined doesn't in the same prefix range"); ABORT; } if (ipv6addrcmp(&$2, &$4) < 0) { memcpy(&seg->min, &$2, sizeof(seg->min)); memcpy(&seg->max, &$4, sizeof(seg->max)); } else { memcpy(&seg->max, &$2, sizeof(seg->max)); memcpy(&seg->min, &$4, sizeof(seg->min)); } /* check the assigned addresses are not reserved ipv6 addresses */ if (IN6_IS_ADDR_RESERVED(&seg->max) || IN6_IS_ADDR_RESERVED(&seg->max)) { dprintf(LOG_ERR, "config reserved ipv6address"); ABORT; } memcpy(&seg->prefix, prefix1, sizeof(seg->prefix)); memcpy(&seg->free, &seg->min, sizeof(seg->free)); if (pool) seg->pool = pool; /* make sure there is no overlap in the rangelist */ /* the segaddr is sorted by prefix len, thus most specific ipv6 address is going to be assigned. */ if (!temp_seg) { seg->next = NULL; seg->prev = NULL; link->seglist = seg; } else { for (; temp_seg; temp_seg = temp_seg->next) { if ( prefix1->plen < temp_seg->prefix.plen) { if (temp_seg->next == NULL) { temp_seg->next = seg; seg->prev = temp_seg; seg->next = NULL; break; } continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -