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