/* * Copyright (C) 2000 Lennert Buytenhek * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/fcntl.h> #include <sys/ioctl.h> #include <sys/time.h> #include "libbridge.h" #include "libbridge_private.h" int br_device_ioctl32(struct bridge *br, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3) { unsigned long args[4]; struct ifreq ifr; args[0] = arg0; args[1] = arg1; args[2] = arg2; args[3] = arg3; memcpy(ifr.ifr_name, br->ifname, IFNAMSIZ); ((unsigned long *)(&ifr.ifr_data))[0] = (unsigned long)args; return ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr); } #ifdef __sparc__ int br_device_ioctl64(struct bridge *br, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3) { unsigned long long args[4]; struct ifreq ifr; args[0] = arg0; args[1] = arg1; args[2] = arg2; args[3] = arg3; memcpy(ifr.ifr_name, br->ifname, IFNAMSIZ); ((unsigned long long *)(&ifr.ifr_data))[0] = (unsigned long long)(unsigned long)args; return ioctl(br_socket_fd, SIOCDEVPRIVATE + 3, &ifr); } #endif int br_device_ioctl(struct bridge *br, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3) { #ifdef __sparc__ if (__kernel_is_64_bit()) return br_device_ioctl64(br, arg0, arg1, arg2, arg3); #endif return br_device_ioctl32(br, arg0, arg1, arg2, arg3); } int br_add_interface(struct bridge *br, int ifindex) { if (br_device_ioctl(br, BRCTL_ADD_IF, ifindex, 0, 0) < 0) return errno; return 0; } int br_del_interface(struct bridge *br, int ifindex) { if (br_device_ioctl(br, BRCTL_DEL_IF, ifindex, 0, 0) < 0) return errno; return 0; } int br_set_bridge_forward_delay(struct bridge *br, struct timeval *tv) { unsigned long jif = __tv_to_jiffies(tv); if (br_device_ioctl(br, BRCTL_SET_BRIDGE_FORWARD_DELAY, jif, 0, 0) < 0) return errno; return 0; } int br_set_bridge_hello_time(struct bridge *br, struct timeval *tv) { unsigned long jif = __tv_to_jiffies(tv); if (br_device_ioctl(br, BRCTL_SET_BRIDGE_HELLO_TIME, jif, 0, 0) < 0) return errno; return 0; } int br_set_bridge_max_age(struct bridge *br, struct timeval *tv) { unsigned long jif = __tv_to_jiffies(tv); if (br_device_ioctl(br, BRCTL_SET_BRIDGE_MAX_AGE, jif, 0, 0) < 0) return errno; return 0; } int br_set_ageing_time(struct bridge *br, struct timeval *tv) { unsigned long jif = __tv_to_jiffies(tv); if (br_device_ioctl(br, BRCTL_SET_AGEING_TIME, jif, 0, 0) < 0) return errno; return 0; } int br_set_gc_interval(struct bridge *br, struct timeval *tv) { unsigned long jif = __tv_to_jiffies(tv); if (br_device_ioctl(br, BRCTL_SET_GC_INTERVAL, jif, 0, 0) < 0) return errno; return 0; } int br_set_stp_state(struct bridge *br, int stp_state) { if (br_device_ioctl(br, BRCTL_SET_BRIDGE_STP_STATE, stp_state, 0, 0) < 0) return errno; return 0; } int br_set_bridge_priority(struct bridge *br, int bridge_priority) { if (br_device_ioctl(br, BRCTL_SET_BRIDGE_PRIORITY, bridge_priority, 0, 0) < 0) return errno; return 0; } int br_set_port_priority(struct port *p, int port_priority) { if (br_device_ioctl(p->parent, BRCTL_SET_PORT_PRIORITY, p->index, port_priority, 0) < 0) return errno; return 0; } int br_set_path_cost(struct port *p, int path_cost) { if (br_device_ioctl(p->parent, BRCTL_SET_PATH_COST, p->index, path_cost, 0) < 0) return errno; return 0; } void __copy_fdb(struct fdb_entry *ent, struct __fdb_entry *f) { memcpy(ent->mac_addr, f->mac_addr, 6); ent->port_no = f->port_no; ent->is_local = f->is_local; __jiffies_to_tv(&ent->ageing_timer_value, f->ageing_timer_value); } int br_read_fdb(struct bridge *br, struct fdb_entry *fdbs, int offset, int num) { struct __fdb_entry f[num]; int i; int numread; if ((numread = br_device_ioctl(br, BRCTL_GET_FDB_ENTRIES, (unsigned long)f, num, offset)) < 0) return errno; for (i=0;i<numread;i++) __copy_fdb(fdbs+i, f+i); return numread; } #ifdef MULTICAST_FILTER int br_set_clrfltr(struct bridge *br) { if (br_device_ioctl(br, 101, 0, 0, 0) < 0) return errno; return 0; } int br_set_fltrport(struct bridge *br, int port) { if (br_device_ioctl(br, 102, port, 0, 0) < 0) return errno; return 0; } #endif