diff options
Diffstat (limited to 'fs/afs/addr_list.c')
-rw-r--r-- | fs/afs/addr_list.c | 54 |
1 files changed, 48 insertions, 6 deletions
diff --git a/fs/afs/addr_list.c b/fs/afs/addr_list.c index b91e59a77f0e..a537368ba0db 100644 --- a/fs/afs/addr_list.c +++ b/fs/afs/addr_list.c @@ -17,9 +17,10 @@ #include "internal.h" #include "afs_fs.h" -#define AFS_MAX_ADDRESSES \ - ((unsigned int)((PAGE_SIZE - sizeof(struct afs_addr_list)) / \ - sizeof(struct sockaddr_rxrpc))) +//#define AFS_MAX_ADDRESSES +// ((unsigned int)((PAGE_SIZE - sizeof(struct afs_addr_list)) / +// sizeof(struct sockaddr_rxrpc))) +#define AFS_MAX_ADDRESSES ((unsigned int)(sizeof(unsigned long) * 8)) /* * Release an address list. @@ -230,15 +231,20 @@ struct afs_addr_list *afs_dns_query(struct afs_cell *cell, time64_t *_expiry) /* * Merge an IPv4 entry into a fileserver address list. */ -void afs_merge_fs_addr4(struct afs_addr_list *alist, __be32 xdr) +void afs_merge_fs_addr4(struct afs_addr_list *alist, __be32 xdr, u16 port) { struct sockaddr_in6 *a; + __be16 xport = htons(port); int i; for (i = 0; i < alist->nr_ipv4; i++) { a = &alist->addrs[i].transport.sin6; - if (xdr == a->sin6_addr.s6_addr32[3]) + if (xdr == a->sin6_addr.s6_addr32[3] && + xport == a->sin6_port) return; + if (xdr == a->sin6_addr.s6_addr32[3] && + xport < a->sin6_port) + break; if (xdr < a->sin6_addr.s6_addr32[3]) break; } @@ -249,7 +255,7 @@ void afs_merge_fs_addr4(struct afs_addr_list *alist, __be32 xdr) sizeof(alist->addrs[0]) * (alist->nr_addrs - i)); a = &alist->addrs[i].transport.sin6; - a->sin6_port = htons(AFS_FS_PORT); + a->sin6_port = xport; a->sin6_addr.s6_addr32[0] = 0; a->sin6_addr.s6_addr32[1] = 0; a->sin6_addr.s6_addr32[2] = htonl(0xffff); @@ -259,6 +265,42 @@ void afs_merge_fs_addr4(struct afs_addr_list *alist, __be32 xdr) } /* + * Merge an IPv6 entry into a fileserver address list. + */ +void afs_merge_fs_addr6(struct afs_addr_list *alist, __be32 *xdr, u16 port) +{ + struct sockaddr_in6 *a; + __be16 xport = htons(port); + int i, diff; + + for (i = alist->nr_ipv4; i < alist->nr_addrs; i++) { + a = &alist->addrs[i].transport.sin6; + diff = memcmp(xdr, &a->sin6_addr, 16); + if (diff == 0 && + xport == a->sin6_port) + return; + if (diff == 0 && + xport < a->sin6_port) + break; + if (diff < 0) + break; + } + + if (i < alist->nr_addrs) + memmove(alist->addrs + i + 1, + alist->addrs + i, + sizeof(alist->addrs[0]) * (alist->nr_addrs - i)); + + a = &alist->addrs[i].transport.sin6; + a->sin6_port = xport; + a->sin6_addr.s6_addr32[0] = xdr[0]; + a->sin6_addr.s6_addr32[1] = xdr[1]; + a->sin6_addr.s6_addr32[2] = xdr[2]; + a->sin6_addr.s6_addr32[3] = xdr[3]; + alist->nr_addrs++; +} + +/* * Get an address to try. */ bool afs_iterate_addresses(struct afs_addr_cursor *ac) |