1/* $Id: dad_token.l,v 1.1.1.1 2006-12-04 00:45:29 pmoutarl Exp $ */ 2 3/* 4 * Copyright (C) International Business Machines Corp., 2003 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 */ 30 31%option noyywrap 32 33%{ 34#include <stdio.h> 35#include <string.h> 36#include <sys/types.h> 37#include <netinet/in.h> 38#include <arpa/inet.h> 39#include <net/if.h> 40 41#include <errno.h> 42#include <syslog.h> 43#include <string.h> 44 45#include "queue.h" 46#include "dhcp6.h" 47#include "config.h" 48#include "common.h" 49#include "lease.h" 50 51#define YYABORT(msg) dprintf(LOG_ERR, msg " %s lineno %d.", \ 52 ifyytext, num_lines) 53 54#define ABORT do { \ 55 YYABORT("/proc/net/if_inet6 file parse error"); \ 56 exit(1); \ 57} while (0) 58 59#define DAD_FLAGS 0xc0 60 61struct ifproc_info { 62 struct ifproc_info *next; 63 struct in6_addr addr; 64 char name[IFNAMSIZ]; 65 int index; 66 int plen; 67 int scope; 68 int flags; 69}; 70 71extern struct dhcp6_if *dhcp6_if; 72extern struct dhcp6_list request_list; 73const char *ifproc_file = "/proc/net/if_inet6"; 74struct ifproc_info *dadlist = NULL; 75 76static struct ifproc_info *ifinfo; 77static int num_lines = 0; 78 79%} 80 81hexdigit ([a-f]|[A-F]|[0-9]) 82hexpair ({hexdigit}{hexdigit}) 83hexaddr ({hexpair}{16}) 84whitespace ([ \t])+ 85ifname [a-zA-Z]+[0-9]+ 86nl \n 87 88 89%s S_CNF S_NAME S_INDEX S_PLEN S_SCOPE S_FLAGS 90 91%% 92 93%{ 94 BEGIN S_CNF; 95%} 96 97<S_CNF>{hexaddr} {struct in6_addr addr; 98 char buff[64]; 99 int i, len = 0; 100 for (i = 0; i < 32; i += 4) { 101 strncpy(buff+len, &ifyytext[i], 4); 102 len += 4; 103 if (i < 28) { 104 strcpy(buff+len, ":"); 105 len += 1; 106 } else 107 strcpy(buff+len, "\0"); 108 } 109 if (inet_pton(AF_INET6, buff, &addr) < 1) { 110 dprintf(LOG_ERR, "parse address failed"); 111 ABORT; 112 } else { 113 ifinfo = (struct ifproc_info *)malloc(sizeof(*ifinfo)); 114 if (ifinfo == NULL) 115 ABORT; 116 memcpy(&ifinfo->addr, &addr, sizeof(ifinfo->addr)); 117 BEGIN S_INDEX;} 118 } 119<S_INDEX>{hexpair} {ifinfo->index = strtol(ifyytext, NULL, 16); 120 BEGIN S_PLEN;} 121<S_PLEN>{hexpair} {ifinfo->plen = strtol(ifyytext, NULL, 16); 122 BEGIN S_SCOPE;} 123<S_SCOPE>{hexpair} {ifinfo->scope = strtol(ifyytext, NULL, 16); 124 BEGIN S_FLAGS;} 125<S_FLAGS>{hexpair} {ifinfo->flags = strtol(ifyytext, NULL, 16); 126 if (ifinfo->flags == DAD_FLAGS) { 127 dprintf(LOG_INFO, "duplicated ipv6 address %s detected", 128 in6addr2str(&ifinfo->addr, 0)); 129 BEGIN S_NAME; 130 } else { 131 free(ifinfo); 132 BEGIN S_CNF; 133 } 134 } 135<S_NAME>{ifname} { 136 if (strcmp(ifyytext, dhcp6_if->ifname)) { 137 free(ifinfo); 138 BEGIN S_CNF; 139 } else { 140 struct dhcp6_listval *lv; 141 struct dhcp6_lease *cl; 142 strncpy(ifinfo->name, ifyytext, IFNAMSIZ); 143 ifinfo->next = NULL; 144 if (dadlist == NULL) { 145 TAILQ_INIT(&request_list); 146 dadlist = ifinfo; 147 } else 148 dadlist->next = ifinfo; 149 150 /* check address on client6_iaidaddr list */ 151 if ((lv = (struct dhcp6_listval *)malloc(sizeof(*lv))) 152 == NULL) { 153 dprintf(LOG_ERR, "failed to allocate memory"); 154 return (-1); 155 } 156 157 for (cl = TAILQ_FIRST(&client6_iaidaddr.lease_list); cl; 158 cl = TAILQ_NEXT(cl, link)) { 159 if (cl->lease_addr.type != IAPD && 160 IN6_ARE_ADDR_EQUAL(&cl->lease_addr.addr, &ifinfo->addr)) 161 break; 162 else 163 BEGIN S_CNF; 164 } 165 /* deconfigure the interface's the address assgined by dhcpv6 */ 166 if (dhcp6_remove_lease(cl) != 0) { 167 dprintf(LOG_INFO, 168 "remove duplicated address failed: %s", 169 in6addr2str(&lv->val_dhcp6addr.addr, 0)); 170 return (-1); 171 } 172 memcpy(&lv->val_dhcp6addr.addr, &ifinfo->addr, 173 sizeof(lv->val_dhcp6addr.addr)); 174 lv->val_dhcp6addr.type = IANA; 175 lv->val_dhcp6addr.plen = ifinfo->plen; 176 lv->val_dhcp6addr.status_code = DH6OPT_STCODE_UNDEFINE; 177 lv->val_dhcp6addr.preferlifetime = 0; 178 lv->val_dhcp6addr.validlifetime = 0; 179 TAILQ_INSERT_TAIL(&request_list, lv, link); 180 BEGIN S_CNF; 181 } 182 } 183 184{nl} {num_lines++;} 185{whitespace} {;} 186%% 187 188int 189dad_parse(const char *file) 190{ 191 if ((ifyyin = fopen(file, "r")) == NULL) { 192 if (errno == ENOENT) 193 return (0); 194 dprintf(LOG_ERR, "dad_parse: fopen(%s): %s", 195 file, strerror(errno)); 196 return (-1); 197 } 198 yylex(); 199 return 0; 200} 201