static int bridge_read_fdb(const char *bridge, struct fdb_entry *fdbs, unsigned long offset, int num) { FILE *f; int i, n; struct __fdb_entry fe[num]; char path[256]; snprintf(path, 256, "/sys/class/net/%s/brforward", bridge); f = fopen(path, "r"); if (f) { fseek(f, offset*sizeof(struct __fdb_entry), SEEK_SET); n = fread(fe, sizeof(struct __fdb_entry), num, f); fclose(f); } for (i = 0; i < n; i++) copy_fdb(fdbs+i, fe+i); return n; }
int br_fdb_get_entries(struct net_bridge *br, unsigned char *_buf, int maxnum, int offset) { int i; int num; struct __fdb_entry *walk; num = 0; walk = (struct __fdb_entry *)_buf; read_lock_bh(&br->hash_lock); for (i=0;i<BR_HASH_SIZE;i++) { struct net_bridge_fdb_entry *f; f = br->hash[i]; while (f != NULL && num < maxnum) { struct __fdb_entry ent; int err; struct net_bridge_fdb_entry *g; struct net_bridge_fdb_entry **pp; if (has_expired(br, f)) { f = f->next_hash; continue; } if (offset) { offset--; f = f->next_hash; continue; } copy_fdb(&ent, f); atomic_inc(&f->use_count); read_unlock_bh(&br->hash_lock); err = copy_to_user(walk, &ent, sizeof(struct __fdb_entry)); read_lock_bh(&br->hash_lock); g = f->next_hash; pp = f->pprev_hash; br_fdb_put(f); if (err) goto out_fault; if (g == NULL && pp == NULL) goto out_disappeared; num++; walk++; f = g; } } out: read_unlock_bh(&br->hash_lock); return num; out_disappeared: num = -EAGAIN; goto out; out_fault: num = -EFAULT; goto out; }