void ipv6ns_probeaddr(void *arg) { struct ipv6_addr *ap = arg; #ifdef IPV6_SEND_DAD struct nd_neighbor_solicit *ns; struct nd_opt_hdr *nd; struct sockaddr_in6 dst; struct cmsghdr *cm; struct in6_pktinfo pi; int hoplimit = HOPLIMIT; #else #ifdef LISTEN_DAD struct timeval tv, rtv; struct timeval mtv; int i; #endif #endif if (ap->dadcallback && ((ap->flags & IPV6_AF_NEW) == 0 || ap->nsprobes >= ap->iface->options->dadtransmits)) { #ifdef IPV6_SEND_DAD ap->dadcallback(ap); #else ipv6_addaddr(ap); #endif return; } if (ipv6ns_open() == -1) return; ap->flags &= ~IPV6_AF_DADCOMPLETED; #ifdef IPV6_SEND_DAD if (!ap->ns) { ap->nslen = sizeof(*ns) + ROUNDUP8(ap->iface->hwlen + 2); ap->ns = calloc(1, ap->nslen); if (ap->ns == NULL) { syslog(LOG_ERR, "%s: %m", __func__); return; } ns = (struct nd_neighbor_solicit *)(void *)ap->ns; ns->nd_ns_type = ND_NEIGHBOR_SOLICIT; //ns->nd_ns_cksum = 0; //ns->nd_ns_code = 0; //ns->nd_ns_reserved = 0; ns->nd_ns_target = ap->addr; nd = (struct nd_opt_hdr *)(ap->ns + sizeof(*ns)); nd->nd_opt_type = ND_OPT_SOURCE_LINKADDR; nd->nd_opt_len = (ROUNDUP8(ap->iface->hwlen + 2)) >> 3; memcpy(nd + 1, ap->iface->hwaddr, ap->iface->hwlen); }
int lladdropt_length(struct sockaddr_dl *sdl) { switch(sdl->sdl_type) { case IFT_ETHER: return(ROUNDUP8(ETHER_ADDR_LEN + 2)); default: return(0); } }
void lladdropt_fill(struct sockaddr_dl *sdl, struct nd_opt_hdr *ndopt) { char *addr; ndopt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; /* fixed */ switch (sdl->sdl_type) { case IFT_ETHER: ndopt->nd_opt_len = (ROUNDUP8(ETHER_ADDR_LEN + 2)) >> 3; addr = (char *)(ndopt + 1); memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN); break; default: warnmsg(LOG_ERR, __func__, "unsupported link type(%d)", sdl->sdl_type); exit(1); } }