1/*	$Id: dad_token.l,v 1.1.1.1 2006/12/04 00:45:29 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