ct ifaddr **q = (struct ifaddr **)
malloc(n, M_IFADDR, M_WAITOK);
if (ifnet_addrs) {
bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
free((caddr_t)ifnet_addrs, M_IFADDR);
}
ifnet_addrs = q;
}
/*
* create a Link Level name for this device
*/
这个函数也很有意思,很有意思
把ifp->if_unit转换成字符串,相当于itoa()....
unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf));
namelen = strlen(ifp->if_name);
unitlen = strlen(unitname);
#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) +
unitlen + namelen;
比较抽象,看看书上那个图就明白内存布局了。
从前往后是name,unit,mask,分别由namelen,unitlen,masklen标识内存的长度
socksize = masklen + ifp->if_addrlen;
#define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
socksize = ROUNDUP(socksize);
if (socksize < sizeof(*sdl))
socksize = sizeof(*sdl);
ifasize = sizeof(*ifa) + 2 * socksize;
这代码我是看的很晕,没细看,看71页的图就理解了
if (ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK)) {
bzero((caddr_t)ifa, ifasize);
第一个sockaddr_dl 表示name和uinit信息,如eth0
物理地址是在后面的ether_attach中附给第一个sdl的
sdl = (struct sockaddr_dl *)(ifa + 1);
sdl->sdl_len = socksize;
sdl->sdl_family = AF_LINK;
bcopy(ifp->if_name, sdl->sdl_data, namelen);
bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen);
sdl->sdl_nlen = (namelen += unitlen);
sdl->sdl_index = ifp->if_index;
sdl->sdl_type = ifp->if_type;
ifnet_addrs[if_index - 1] = ifa;
ifa->ifa_ifp = ifp;
ifa->ifa_next = ifp->if_addrlist;
ifa->ifa_rtrequest = link_rtrequest;
ifp->if_addrlist = ifa;
ifa->ifa_addr = (struct sockaddr *)sdl;
第2个sdl,表示netmask信息
sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
ifa->ifa_netmask = (struct sockaddr *)sdl;
sdl->sdl_len = masklen;
while (namelen != 0)
sdl->sdl_data[--namelen] = 0xff;
}
/* XXX -- Temporary fix before changing 10 ethernet drivers */
if (ifp->if_output == ether_output)
ether_ifattach(ifp);
}
至此,over