- 论坛徽章:
- 0
|
in_control函数中有两处调用in_ifinit函数,一处是SIOCAIFADDR(添加多个地址)另一处是SIOCSIFADDR(设置一个接口地址)可是为什么在4.4BSD和FreeBSD6.2的网络代码中的in_ifinit函数中看不到处理SIOCAIFADDR命令的代码呢?在in_ifinit函数中一上来就先把接口的旧地址保存到一个变量中,然后就用传进来的新地址替换了老地址,然后是如果接口结构定义了if_ioctl函数就调用他的链路层处理,可是调用的时候仅仅是执行SIOCSIFADDR一个命令,( error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia); )再后就是一些路由和组播相关的代码.请高手指点小弟谢谢了.
int in_control(xxx){
.....
switch(cmd)
case
........
case SIOCAIFADDR:
maskIsNew = 0;
hostIsNew = 1;
error = 0;
if (ia->ia_addr.sin_family == AF_INET) {
if (ifra->ifra_addr.sin_len == 0) { //新地址没有长度,认为不是一个新地址
ifra->ifra_addr = ia->ia_addr;
hostIsNew = 0;
} else if (ifra->ifra_addr.sin_addr.s_addr ==
ia->ia_addr.sin_addr.s_addr) //新旧地址相等不算新地址
hostIsNew = 0;
}
if (ifra->ifra_mask.sin_len) { //新地址有掩码
in_ifscrub(ifp, ia); //删除接口存在的路由
ia->ia_sockmask = ifra->ifra_mask; //设置掩码
ia->ia_sockmask.sin_family = AF_INET;
ia->ia_subnetmask =
ntohl(ia->ia_sockmask.sin_addr.s_addr); //设置子码
maskIsNew = 1;
}
if ((ifp->if_flags & IFF_POINTOPOINT) &&
(ifra->ifra_dstaddr.sin_family == AF_INET)) {
in_ifscrub(ifp, ia); //删除接口存在的路由
ia->ia_dstaddr = ifra->ifra_dstaddr; //更新目的地址
maskIsNew = 1; /* We lie; but the effect's the same */
}
if (ifra->ifra_addr.sin_family == AF_INET &&
(hostIsNew || maskIsNew)) //有新地址或新掩码
error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0); //调用in_ifinit执行操作 最后一个参数为0表示不必刷新所有路由
if (error != 0 && iaIsNew)
break;
if ((ifp->if_flags & IFF_BROADCAST) && //如果接口支持广播
(ifra->ifra_broadaddr.sin_family == AF_INET))
ia->ia_broadaddr = ifra->ifra_broadaddr; //设置广播地址
if (error == 0)
EVENTHANDLER_INVOKE(ifaddr_event, ifp);
return (error);
........
}
static int
in_ifinit(ifp, ia, sin, scrub)
register struct ifnet *ifp; //物理接口
register struct in_ifaddr *ia; //物理接口的原地址结构
struct sockaddr_in *sin; //要加入或者删除的地址
int scrub; //接口改变后是否更新路由
{
register u_long i = ntohl(sin->sin_addr.s_addr);
struct sockaddr_in oldaddr;
int s = splimp(), flags = RTF_UP, error = 0;
oldaddr = ia->ia_addr; //保存老地址
if (oldaddr.sin_family == AF_INET)
LIST_REMOVE(ia, ia_hash); //从hash表中删除老地址
ia->ia_addr = *sin;
if (ia->ia_addr.sin_family == AF_INET)
LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
ia, ia_hash); //加入新地址到hash接口的表中
/*
* Give the interface a chance to initialize
* if this is its first address,
* and to validate the address if necessary.
*/
if (ifp->if_ioctl) { //如果定义了ioctl函数
IFF_LOCKGIANT(ifp);
error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia); //可能是leioctl,loioctl等链路层地址
IFF_UNLOCKGIANT(ifp);
if (error) {
splx(s);
/* 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);
}
}
splx(s);
if (scrub) {
ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
in_ifscrub(ifp, ia); //删除接口路由
ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
}
if (IN_CLASSA(i)) //尝试网络掩码
ia->ia_netmask = IN_CLASSA_NET;
else if (IN_CLASSB(i))
ia->ia_netmask = IN_CLASSB_NET;
else
ia->ia_netmask = IN_CLASSC_NET;
/*
* The subnet mask usually includes at least the standard network part,
* but may may be smaller in the case of supernetting.
* If it is set, we believe it.
*/
if (ia->ia_subnetmask == 0) { //如果没有子网掩码就用尝试性的掩码
ia->ia_subnetmask = ia->ia_netmask;
ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
} else //使用子网掩码
ia->ia_netmask &= ia->ia_subnetmask;
ia->ia_net = i & ia->ia_netmask;
ia->ia_subnet = i & ia->ia_subnetmask;
in_socktrim(&ia->ia_sockmask);
#ifdef DEV_CARP
/*
* XXX: carp(4) does not have interface route
*/
if (ifp->if_type == IFT_CARP)
return (0);
#endif
/*
* Add route for the network.
*/
ia->ia_ifa.ifa_metric = ifp->if_metric;
if (ifp->if_flags & IFF_BROADCAST) {
ia->ia_broadaddr.sin_addr.s_addr =
htonl(ia->ia_subnet | ~ia->ia_subnetmask);
ia->ia_netbroadcast.s_addr =
htonl(ia->ia_net | ~ ia->ia_netmask);
} else if (ifp->if_flags & IFF_LOOPBACK) {
ia->ia_dstaddr = ia->ia_addr;
flags |= RTF_HOST;
} else if (ifp->if_flags & IFF_POINTOPOINT) {
if (ia->ia_dstaddr.sin_family != AF_INET)
return (0);
flags |= RTF_HOST;
}
if ((error = in_addprefix(ia, flags)) != 0)
return (error);
/*
* If the interface supports multicast, join the "all hosts"
* multicast group on that interface.
*/
if (ifp->if_flags & IFF_MULTICAST) {
struct in_addr addr;
addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
in_addmulti(&addr, ifp); //加入所有主机组
}
return (error);
} |
|