Mercurial > illumos > illumos-gate
changeset 12915:2794a0c9cce1
6965774 bound the interface index in IP to [1,65535]
author | Darren Reed <Darren.Reed@Oracle.COM> |
---|---|
date | Fri, 23 Jul 2010 18:03:48 -0700 |
parents | 3bb859a7330c |
children | aab2c5dd2abc |
files | usr/src/uts/common/inet/ip/ip_if.c usr/src/uts/common/net/if.h |
diffstat | 2 files changed, 32 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/inet/ip/ip_if.c Fri Jul 23 17:34:02 2010 -0700 +++ b/usr/src/uts/common/inet/ip/ip_if.c Fri Jul 23 18:03:48 2010 -0700 @@ -3538,34 +3538,51 @@ &index, NULL) != NULL); } -/* Pick a unique ifindex */ +/* + * Pick a unique ifindex. + * When the index counter passes IF_INDEX_MAX for the first time, the wrap + * flag is set so that next time time ip_assign_ifindex() is called, it + * falls through and resets the index counter back to 1, the minimum value + * for the interface index. The logic below assumes that ips_ill_index + * can hold a value of IF_INDEX_MAX+1 without there being any loss + * (i.e. reset back to 0.) + */ boolean_t ip_assign_ifindex(uint_t *indexp, ip_stack_t *ipst) { - uint_t starting_index; + uint_t loops; if (!ipst->ips_ill_index_wrap) { *indexp = ipst->ips_ill_index++; - if (ipst->ips_ill_index == 0) { - /* Reached the uint_t limit Next time wrap */ + if (ipst->ips_ill_index > IF_INDEX_MAX) { + /* + * Reached the maximum ifindex value, set the wrap + * flag to indicate that it is no longer possible + * to assume that a given index is unallocated. + */ ipst->ips_ill_index_wrap = B_TRUE; } return (B_TRUE); } + if (ipst->ips_ill_index > IF_INDEX_MAX) + ipst->ips_ill_index = 1; + /* * Start reusing unused indexes. Note that we hold the ill_g_lock * at this point and don't want to call any function that attempts * to get the lock again. */ - starting_index = ipst->ips_ill_index++; - for (; ipst->ips_ill_index != starting_index; ipst->ips_ill_index++) { - if (ipst->ips_ill_index != 0 && - !phyint_exists(ipst->ips_ill_index, ipst)) { + for (loops = IF_INDEX_MAX; loops > 0; loops--) { + if (!phyint_exists(ipst->ips_ill_index, ipst)) { /* found unused index - use it */ *indexp = ipst->ips_ill_index; return (B_TRUE); } + + ipst->ips_ill_index++; + if (ipst->ips_ill_index > IF_INDEX_MAX) + ipst->ips_ill_index = 1; } /* @@ -15957,7 +15974,7 @@ */ ill = ipif->ipif_ill; phyi = ill->ill_phyint; - if (ipif->ipif_id != 0 || index == 0) { + if (ipif->ipif_id != 0 || index == 0 || index > IF_INDEX_MAX) { return (EINVAL); }
--- a/usr/src/uts/common/net/if.h Fri Jul 23 17:34:02 2010 -0700 +++ b/usr/src/uts/common/net/if.h Fri Jul 23 18:03:48 2010 -0700 @@ -720,6 +720,12 @@ extern void if_freenameindex(struct if_nameindex *); #define IF_NAMESIZE _LIFNAMSIZ +/* + * If changing IF_MAX_INDEX to a value greater than UINT16_MAX, check if + * struct sockaddr_dl needs to be modified as the interface index is placed + * in this structure by the kernel. + */ +#define IF_INDEX_MAX UINT16_MAX #ifdef __cplusplus }