1/*
2 * $Id: libbridge_devif.c,v 1.1.1.1 2008/10/15 03:28:31 james26_jang Exp $
3 *
4 * Copyright (C) 2000 Lennert Buytenhek
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <errno.h>
25#include <sys/fcntl.h>
26#include <sys/ioctl.h>
27#include <sys/time.h>
28#include "libbridge.h"
29#include "libbridge_private.h"
30
31int br_device_ioctl(struct bridge *br, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3)
32{
33	unsigned long args[4];
34	struct ifreq ifr;
35
36	args[0] = arg0;
37	args[1] = arg1;
38	args[2] = arg2;
39	args[3] = arg3;
40
41	memcpy(ifr.ifr_name, br->ifname, IFNAMSIZ);
42	((unsigned long *)(&ifr.ifr_data))[0] = (unsigned long)args;
43
44	return ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr);
45}
46
47int br_add_interface(struct bridge *br, int ifindex)
48{
49	if (br_device_ioctl(br, BRCTL_ADD_IF, ifindex, 0, 0) < 0)
50		return errno;
51
52	return 0;
53}
54
55int br_del_interface(struct bridge *br, int ifindex)
56{
57	if (br_device_ioctl(br, BRCTL_DEL_IF, ifindex, 0, 0) < 0)
58		return errno;
59
60	return 0;
61}
62
63int br_set_bridge_forward_delay(struct bridge *br, struct timeval *tv)
64{
65	unsigned long jif = __tv_to_jiffies(tv);
66
67	if (br_device_ioctl(br, BRCTL_SET_BRIDGE_FORWARD_DELAY,
68			    jif, 0, 0) < 0)
69		return errno;
70
71	return 0;
72}
73
74int br_set_bridge_hello_time(struct bridge *br, struct timeval *tv)
75{
76	unsigned long jif = __tv_to_jiffies(tv);
77
78	if (br_device_ioctl(br, BRCTL_SET_BRIDGE_HELLO_TIME, jif, 0, 0) < 0)
79		return errno;
80
81	return 0;
82}
83
84int br_set_bridge_max_age(struct bridge *br, struct timeval *tv)
85{
86	unsigned long jif = __tv_to_jiffies(tv);
87
88	if (br_device_ioctl(br, BRCTL_SET_BRIDGE_MAX_AGE, jif, 0, 0) < 0)
89		return errno;
90
91	return 0;
92}
93
94int br_set_ageing_time(struct bridge *br, struct timeval *tv)
95{
96	unsigned long jif = __tv_to_jiffies(tv);
97
98	if (br_device_ioctl(br, BRCTL_SET_AGEING_TIME, jif, 0, 0) < 0)
99		return errno;
100
101	return 0;
102}
103
104int br_set_gc_interval(struct bridge *br, struct timeval *tv)
105{
106	unsigned long jif = __tv_to_jiffies(tv);
107
108	if (br_device_ioctl(br, BRCTL_SET_GC_INTERVAL, jif, 0, 0) < 0)
109		return errno;
110
111	return 0;
112}
113
114int br_set_stp_state(struct bridge *br, int stp_state)
115{
116	if (br_device_ioctl(br, BRCTL_SET_BRIDGE_STP_STATE, stp_state,
117			    0, 0) < 0)
118		return errno;
119
120	return 0;
121}
122
123int br_set_bridge_priority(struct bridge *br, int bridge_priority)
124{
125	if (br_device_ioctl(br, BRCTL_SET_BRIDGE_PRIORITY, bridge_priority,
126			    0, 0) < 0)
127		return errno;
128
129	return 0;
130}
131
132int br_set_port_priority(struct port *p, int port_priority)
133{
134	if (br_device_ioctl(p->parent, BRCTL_SET_PORT_PRIORITY, p->index,
135			    port_priority, 0) < 0)
136		return errno;
137
138	return 0;
139}
140
141int br_set_path_cost(struct port *p, int path_cost)
142{
143	if (br_device_ioctl(p->parent, BRCTL_SET_PATH_COST, p->index,
144			    path_cost, 0) < 0)
145		return errno;
146
147	return 0;
148}
149
150void __copy_fdb(struct fdb_entry *ent, struct __fdb_entry *f)
151{
152	memcpy(ent->mac_addr, f->mac_addr, 6);
153	ent->port_no = f->port_no;
154	ent->is_local = f->is_local;
155	__jiffies_to_tv(&ent->ageing_timer_value, f->ageing_timer_value);
156}
157
158int br_read_fdb(struct bridge *br, struct fdb_entry *fdbs, int offset, int num)
159{
160	struct __fdb_entry f[num];
161	int i;
162	int numread;
163
164	if ((numread = br_device_ioctl(br, BRCTL_GET_FDB_ENTRIES,
165				       (unsigned long)f, num, offset)) < 0)
166		return errno;
167
168	for (i=0;i<numread;i++)
169		__copy_fdb(fdbs+i, f+i);
170
171	return numread;
172}
173