Subject: bug?
To: None <tech-net@netbsd.org>
From: Pramod Srinivasan <pramodsri@yahoo.com>
List: tech-net
Date: 02/23/2004 15:39:46
There may be a bug in if_detach code. I have a test
program which does the following

o create an interface (say a vlan intf), 
o assigns an ip address to the interface
o open a udp socket
o does a setsockopt to add an IP group membership
(IP_ADD_MEMBERSHIP)
o deletes the ip address of the interface
o delete the interface
o close the socket.

The kernel will dump core as a result of the close,
looked through the code, the problem seems to be that
in if_detach, we go through the addresses associated
with the interface and based on the family of the
address, we call the callbacks for the the protocols
to clean up the pcbs. In my test case, the interface
address was deleted prior to deleting the interface,
hence the cleanup (in_pcbpurgeif0 for the udp) was
never called from if_detach, the close of the socket
which cleans up the pcb called ip_freemoptions which
had reference to the the deleted ifp. (the bug was
caught because DIAGNOSTIC was turned on). 

I think we should go through the in_mk list which
keeps track of interfaces having multicast addresses
when interface address is deleted and use this to
clean up pcbs. we could call the below function from
if_detach.

 void
in_cleanmcast(ifp)
        struct ifnet *ifp;
{
        struct in_ifaddr *oia;
        struct in_ifaddr *noia;
        int family;
        struct domain *dp;
        struct protosw *pr;
        struct socket so;

        noia = TAILQ_FIRST(&in_mk);

        while (noia) {
                if (noia->ia_ifp != ifp) {
                        noia = TAILQ_NEXT(noia,
ia_list);
                        continue;
                }
                oia = noia;
                noia = TAILQ_NEXT(noia, ia_list);

                family =
oia->ia_ifa.ifa_addr->sa_family;
                dp = pffinddomain(family);
                for (pr = dp->dom_protosw;
                        pr < dp->dom_protoswNPROTOSW;
pr++) {
                        so.so_proto = pr;
                        if (pr->pr_usrreq != NULL) {
                                (void)
(*pr->pr_usrreq)(&so,
                                           
PRU_PURGEIF, NULL, NULL,
                                            (struct
mbuf *) ifp, curproc);
                        }
                }
        }
}

Thanks,
pramod


__________________________________
Do you Yahoo!?
Yahoo! Mail SpamGuard - Read only the mail you want.
http://antispam.yahoo.com/tools