in_ifinit() fix for SIOCSIFADDR
Matthew Dillon
dillon at apollo.backplane.com
Sat May 24 10:43:30 PDT 2008
:Hi all,
:
:Following scenario will cause inaddr hash table contains dangling
:reference to 'ia':
:- ifaceX has an AF_INET ia
:- SIOCSIFADDR is used to change address, and new address' hash value
:is different from ia's
:- in in_ifinit()
: o ia is currently in hash bucket B1
:...
Oooh, nice. I think you found the corruption that has been bugging
me for a long time.
The patch looks good except for that XXX assumption. I can't quite
follow that code sequence.
:Old code will also leave ia in the wrong hash bucket, if the rtinit()
:in in_ifinit() fails, is this an intended behavior?
:
It looks like in_ifinit() assumes that the (ia) is in some hash list
somewhere no matter what, but it should probably not be in the wrong
hash table. I think it would be appropriate to move it to the correct
hash table for that failure case.
That whole code section around line 749 of in.c, in the original file,
is very confusing:
if (ifp->if_ioctl &&
(error = ifp->if_ioctl(ifp, SIOCSIFADDR, (caddr_t)ia, NULL))) {
lwkt_serialize_exit(ifp->if_serializer);
/* LIST_REMOVE(ia, ia_hash) is done in in_control */
ia->ia_addr = oldaddr;
if (ia->ia_addr.sin_family == AF_INET)
LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr
),
ia, ia_hash);
return (error);
}
I'm not sure what is going on with (ia) there.
-Matt
Matthew Dillon
<dillon at backplane.com>
More information about the Submit
mailing list