📄 radvd_token.l
字号:
/* $Id: radvd_token.l,v 1.7 2003/07/07 18:01:05 shirleyma 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 *//* Author: Shirley Ma, xma@us.ibm.com */%option noyywrap%{#include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/file.h>#include <sys/stat.h>#include <unistd.h>#include <signal.h>#include <netinet/in.h>#include <arpa/inet.h>#include <errno.h>#include <syslog.h>#include <string.h>#include "queue.h"#include "dhcp6.h"#include "config.h"#include "common.h"#include "lease.h"#ifndef PATH_RADVD_PID#define PATH_RADVD_PID "/var/run/radvd/radvd.pid"#endif#define YYABORT(msg) dprintf(LOG_ERR, msg " %s lineno %d.", \ yytext, num_lines)#define ABORT do { \ YYABORT("radvd.conf parse error"); \ remove(RADVD_CONF_DHCPV6_FILE); \ exit(1); \} while (0)#undef yywrap#define DHCP6_MARK "# update prefix from DHCPv6 server\n"extern struct dhcp6_if *dhcp6_if;int radvd_parse __P((struct dhcp6_iaidaddr *, int));static struct dhcp6_list ori_prefix_list;static struct dhcp6_iaidaddr *client6iaid;static struct dhcp6_list previous_prefix_list;static FILE *dhcp6_radvd_file;static int update_flag;static int oldfd, newfd;static int num_lines = 0;static int brace = 0;static int update = 0;static int yywrap __P((void));static int update_radvd __P((void));%}whitespace ([ \t])+digit [0-9]string [a-zA-Z0-9:\.\/][a-zA-Z0-9:\.\/]*nl \nlbrace "{"rbrace "}"mark DHCP6_MARK comment \#.*%s S_INTERFACE S_IFNAME S_ORIPREFIX S_NEWPREFIX S_DHCP6%%{nl} {fprintf(dhcp6_radvd_file, yytext); num_lines++;}{whitespace} {fprintf(dhcp6_radvd_file, yytext);}"interface" {fprintf(dhcp6_radvd_file, yytext); BEGIN S_INTERFACE;}<S_INTERFACE>{string} { fprintf(dhcp6_radvd_file, yytext); if (!strcmp(yytext, dhcp6_if->ifname)) BEGIN INITIAL; else { TAILQ_INIT(&ori_prefix_list); TAILQ_INIT(&previous_prefix_list); BEGIN S_IFNAME;} }<S_IFNAME>{comment} { if (strstr(yytext, DHCP6_MARK) != NULL) { BEGIN S_DHCP6; } else fprintf(dhcp6_radvd_file, yytext);} <S_IFNAME>"prefix" {fprintf(dhcp6_radvd_file, yytext); BEGIN S_ORIPREFIX;}<S_IFNAME>{lbrace} {fprintf(dhcp6_radvd_file, yytext); brace++; BEGIN S_IFNAME;} <S_IFNAME>{rbrace} {struct dhcp6_lease *lv; brace--; if (brace == 0 && update_flag == ADDR_UPDATE) { /* add prefix which is not on the original prefix list * check the lifetime value, AdvValidLifetime, * AdvPreferredLifetime: infinity or XXX seconds */ for (lv = TAILQ_FIRST(&client6iaid->lease_list); lv; lv = TAILQ_NEXT(lv, link)) { if (!addr_on_addrlist(&ori_prefix_list, &lv->lease_addr) && !addr_on_addrlist(&previous_prefix_list, &lv->lease_addr)){ fprintf(dhcp6_radvd_file, DHCP6_MARK); fprintf(dhcp6_radvd_file, "\tprefix %s/%d {};\n", in6addr2str(&(lv->lease_addr.addr), 0), lv->lease_addr.plen); update = 1; } dprintf(LOG_INFO, "update radvd.conf with DHCPv6 prefixes"); } fprintf(dhcp6_radvd_file, yytext); BEGIN INITIAL; } else { fprintf(dhcp6_radvd_file, yytext); BEGIN S_IFNAME;} }<S_DHCP6>"prefix" {BEGIN S_NEWPREFIX;}<S_NEWPREFIX>{string} { /* update the prefix from DHCPv6 server * if the new list doesn't include this prefix remove it */ struct dhcp6_listval *lv; /* create orignal prefix list */ if ((lv = (struct dhcp6_listval *)malloc(sizeof(*lv))) == NULL) { ABORT; } memset(lv, 0, sizeof(*lv)); if (strstr(yytext, "/") == NULL) ABORT; if (inet_pton(AF_INET6, strtok(yytext, "/"), &lv->val_dhcp6addr.addr) < 1) { ABORT; } lv->val_dhcp6addr.type = IAPD; lv->val_dhcp6addr.plen = atoi(strtok(NULL, "/")); lv->val_dhcp6addr.status_code = DH6OPT_STCODE_UNDEFINE; /* remove the prefix list for release */ if (update_flag == ADDR_REMOVE && !addr_on_addrlist((struct dhcp6_list *)&client6iaid->lease_list, &lv->val_dhcp6addr)) { dprintf(LOG_DEBUG, "remove DHCPv6 assgined prefix in radvd.conf"); update = 1; } else { TAILQ_INSERT_TAIL(&previous_prefix_list, lv, link); fprintf(dhcp6_radvd_file, DHCP6_MARK); fprintf(dhcp6_radvd_file, "\tprefix %s/%d {};\n", in6addr2str(&(lv->val_dhcp6addr.addr), 0), lv->val_dhcp6addr.plen); } BEGIN S_NEWPREFIX;}<S_NEWPREFIX>{rbrace}";" {BEGIN S_IFNAME;}<S_NEWPREFIX>. {;}<S_ORIPREFIX>{string} { struct dhcp6_listval *lv; fprintf(dhcp6_radvd_file, yytext); /* create orignal prefix list */ if ((lv = (struct dhcp6_listval *)malloc(sizeof(*lv))) == NULL) { ABORT; } memset(lv, 0, sizeof(*lv)); if (inet_pton(AF_INET6, strtok(yytext, "/"), &lv->val_dhcp6addr.addr) < 1) { ABORT; } lv->val_dhcp6addr.type = IAPD; lv->val_dhcp6addr.plen = atoi(strtok(NULL, "/")); lv->val_dhcp6addr.status_code = DH6OPT_STCODE_UNDEFINE; TAILQ_INSERT_TAIL(&ori_prefix_list, lv, link); BEGIN S_IFNAME; }{comment} {fprintf(dhcp6_radvd_file, yytext);}. {fprintf(dhcp6_radvd_file, yytext);}%%/* parse radvd.conf * create a new radvd.conf.dhcpv6 * mv /etc/radvd.conf to /etc/radvd.conf.V6BAK * link radvd.conf to radvd.conf.dhcpv6 */intradvd_parse(struct dhcp6_iaidaddr *client6_iaid, int flag){ struct stat buf; char pidstr[128]; sprintf(pidstr, "%d", getpid()); strcpy(radvd_dhcpv6_file, RADVD_CONF_DHCPV6_FILE); strcat(radvd_dhcpv6_file, pidstr); while ((oldfd = open(RADVD_CONF_FILE, O_EXCL)) < 0) { switch (errno) { case ENOENT: /* exclusive open of new radvd.conf.dhcpv6 file */ if ((newfd = open(radvd_dhcpv6_file, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC, 0644)) < 0) { dprintf(LOG_ERR, "%s" " failed to open radvd.conf.dhcpv6 file", FNAME); return (-1); } if ((dhcp6_radvd_file = fdopen(newfd, "w")) == NULL) { dprintf(LOG_ERR, "%s" " failed to fdopen radvd.conf.dhcpv6 file", FNAME); return (-1); } return(update_radvd()); case EACCES: sleep(1); continue; default: dprintf(LOG_ERR, "radvd_parse: fopen(%s): %s", RADVD_CONF_FILE, strerror(errno)); return (-1); } } if (lstat(RADVD_CONF_FILE, &buf)) { dprintf(LOG_ERR, "lstat radvd.conf file failed"); return (-1); } if ((yyin = fdopen(oldfd, "r")) == NULL) { dprintf(LOG_ERR, "radvd_parse: fdopen(%s): %s", RADVD_CONF_FILE, strerror(errno)); return (-1); } /* exclusive open of new radvd.conf.dhcpv6$pid file */ if ((newfd = open(radvd_dhcpv6_file, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC, buf.st_mode)) < 0) { dprintf(LOG_ERR, "%s" " failed to open radvd.conf.dhcpv6 file", FNAME); return (-1); } if ((dhcp6_radvd_file = fdopen(newfd, "w")) == NULL) { dprintf(LOG_ERR, "%s" " failed to fdopen radvd.conf.dhcpv6$pid file", FNAME); return (-1); } client6iaid = client6_iaid; update_flag = flag; yylex();}static intupdate_radvd(void){ struct dhcp6_listval *d, *d_next; struct stat buf; if (fflush(dhcp6_radvd_file) == EOF) { dprintf(LOG_ERR, "%s" "write radvd.conf.dhcpv6 file fflush failed %s", FNAME, strerror(errno)); return (-1); } if (fsync(newfd) < 0) { dprintf(LOG_ERR, "%s" "write radvd.conf.dhcpv6 file failed %s", FNAME, strerror(errno)); return (-1); } fclose(dhcp6_radvd_file); close(newfd); if (!lstat(RADVD_CONF_FILE, &buf)) { if (lstat(RADVD_CONF_BAK_FILE, &buf) < 0 && errno == ENOENT) { /* save the orignal file as a bak file */ if (link(RADVD_CONF_FILE, RADVD_CONF_BAK_FILE)) { dprintf(LOG_ERR, "%s" " backup failed for radvd.conf file", FNAME); return (-1); } } } /* rename the new conf file as the radvd.conf file */ if (rename(radvd_dhcpv6_file, RADVD_CONF_FILE)) { dprintf(LOG_ERR, "%s" " rename failed for radvd.conf file", FNAME); return(-1); } return (0);}static int yywrap(void){ int fd; char buff[8]; pid_t radvd_pid; (void)update_radvd(); if (update) { if ((fd = open(PATH_RADVD_PID, O_RDONLY)) > 0) { if (read(fd, buff, sizeof(buff)) > 0) { radvd_pid = strtol(buff, NULL, 10); if (radvd_pid == 0) dprintf(LOG_INFO, "invalid radvd pid"); else if (kill(radvd_pid, SIGHUP) != 0) dprintf(LOG_INFO, "failed to reload radvd"); } else dprintf(LOG_INFO, "failed to read radvd pid file"); close(fd); } else dprintf(LOG_INFO, "failed to open radvd pid file"); } fclose(yyin); close(oldfd);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -