1/* 2 * $Id: libbridge_init.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 <errno.h> 24#include <sys/fcntl.h> 25#include <sys/ioctl.h> 26#include <sys/time.h> 27#include "libbridge.h" 28#include "libbridge_private.h" 29 30int br_socket_fd; 31struct bridge *bridge_list; 32 33static void __bridge_info_copy(struct bridge_info *info, struct __bridge_info *i) 34{ 35 memcpy(&info->designated_root, &i->designated_root, 8); 36 memcpy(&info->bridge_id, &i->bridge_id, 8); 37 info->root_path_cost = i->root_path_cost; 38 info->topology_change = i->topology_change; 39 info->topology_change_detected = i->topology_change_detected; 40 info->root_port = i->root_port; 41 info->stp_enabled = i->stp_enabled; 42 __jiffies_to_tv(&info->max_age, i->max_age); 43 __jiffies_to_tv(&info->hello_time, i->hello_time); 44 __jiffies_to_tv(&info->forward_delay, i->forward_delay); 45 __jiffies_to_tv(&info->bridge_max_age, i->bridge_max_age); 46 __jiffies_to_tv(&info->bridge_hello_time, i->bridge_hello_time); 47 __jiffies_to_tv(&info->bridge_forward_delay, i->bridge_forward_delay); 48 __jiffies_to_tv(&info->ageing_time, i->ageing_time); 49 __jiffies_to_tv(&info->gc_interval, i->gc_interval); 50 __jiffies_to_tv(&info->hello_timer_value, i->hello_timer_value); 51 __jiffies_to_tv(&info->tcn_timer_value, i->tcn_timer_value); 52 __jiffies_to_tv(&info->topology_change_timer_value, 53 i->topology_change_timer_value); 54 __jiffies_to_tv(&info->gc_timer_value, i->gc_timer_value); 55} 56 57static void __port_info_copy(struct port_info *info, struct __port_info *i) 58{ 59 memcpy(&info->designated_root, &i->designated_root, 8); 60 memcpy(&info->designated_bridge, &i->designated_bridge, 8); 61 info->port_id = i->port_id; 62 info->designated_port = i->designated_port; 63 info->path_cost = i->path_cost; 64 info->designated_cost = i->designated_cost; 65 info->state = i->state; 66 info->top_change_ack = i->top_change_ack; 67 info->config_pending = i->config_pending; 68 __jiffies_to_tv(&info->message_age_timer_value, 69 i->message_age_timer_value); 70 __jiffies_to_tv(&info->forward_delay_timer_value, 71 i->forward_delay_timer_value); 72 __jiffies_to_tv(&info->hold_timer_value, 73 i->hold_timer_value); 74} 75 76int br_read_info(struct bridge *br) 77{ 78 struct __bridge_info i; 79 80 if (if_indextoname(br->ifindex, br->ifname) == NULL) 81 return 1; 82 83 if (br_device_ioctl(br, BRCTL_GET_BRIDGE_INFO, 84 (unsigned long)&i, 0, 0) < 0) 85 return 1; 86 87 __bridge_info_copy(&br->info, &i); 88 return 0; 89} 90 91int br_read_port_info(struct port *p) 92{ 93 struct __port_info i; 94 95 if (br_device_ioctl(p->parent, BRCTL_GET_PORT_INFO, 96 (unsigned long)&i, p->index, 0) < 0) 97 return errno; 98 99 __port_info_copy(&p->info, &i); 100 return 0; 101} 102 103void br_nuke_bridge(struct bridge *b) 104{ 105 struct port *p; 106 107 p = b->firstport; 108 while (p != NULL) { 109 struct port *pnext; 110 111 pnext = p->next; 112 free(p); 113 p = pnext; 114 } 115 116 free(b); 117} 118 119int br_make_port_list(struct bridge *br) 120{ 121 int err; 122 int i; 123 int ifindices[256]; 124 125 if (br_device_ioctl(br, BRCTL_GET_PORT_LIST, (unsigned long)ifindices, 126 0, 0) < 0) 127 return errno; 128 129 for (i=255;i>=0;i--) { 130 struct port *p; 131 132 if (!ifindices[i]) 133 continue; 134 135 p = malloc(sizeof(struct port)); 136 p->index = i; 137 p->ifindex = ifindices[i]; 138 p->parent = br; 139 br->ports[i] = p; 140 p->next = br->firstport; 141 br->firstport = p; 142 if ((err = br_read_port_info(p)) != 0) 143 goto error_out; 144 } 145 146 return 0; 147 148 error_out: 149 while (++i < 256) 150 free(br->ports[i]); 151 152 return err; 153} 154 155int br_make_bridge_list() 156{ 157 int err; 158 int i; 159 int ifindices[32]; 160 int num; 161 162 num = br_ioctl(BRCTL_GET_BRIDGES, (unsigned long)ifindices, 32); 163 if (num < 0) 164 return errno; 165 166 bridge_list = NULL; 167 for (i=0;i<num;i++) { 168 struct bridge *br; 169 170 br = malloc(sizeof(struct bridge)); 171 memset(br, 0, sizeof(struct bridge)); 172 br->ifindex = ifindices[i]; 173 br->firstport = NULL; 174 br->next = bridge_list; 175 bridge_list = br; 176 if ((err = br_read_info(br)) != 0) 177 goto error_out; 178 if ((err = br_make_port_list(br)) != 0) 179 goto error_out; 180 } 181 182 return 0; 183 184 error_out: 185 while (bridge_list != NULL) { 186 struct bridge *nxt; 187 188 nxt = bridge_list->next; 189 br_nuke_bridge(bridge_list); 190 bridge_list = nxt; 191 } 192 193 return err; 194} 195 196int br_init() 197{ 198 int err; 199 200 if ((br_socket_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 201 return errno; 202 203 if (br_get_version() != BRCTL_VERSION) 204 return 12345; 205 206 if ((err = br_make_bridge_list()) != 0) 207 return err; 208 209 return 0; 210} 211 212int br_refresh() 213{ 214 struct bridge *b; 215 216 b = bridge_list; 217 while (b != NULL) { 218 struct bridge *bnext; 219 220 bnext = b->next; 221 br_nuke_bridge(b); 222 b = bnext; 223 } 224 225 return br_make_bridge_list(); 226} 227