Пример #1
0
static int
_intf_delete_addrs(intf_t *intf, struct intf_entry *entry)
{
#if defined(SIOCDIFADDR)
    struct dnet_ifaliasreq ifra;

    memset(&ifra, 0, sizeof(ifra));
    strlcpy(ifra.ifra_name, entry->intf_name, sizeof(ifra.ifra_name));
    if (entry->intf_addr.addr_type == ADDR_TYPE_IP) {
        addr_ntos(&entry->intf_addr, &ifra.ifra_addr);
        ioctl(intf->fd, SIOCDIFADDR, &ifra);
    }
    if (entry->intf_dst_addr.addr_type == ADDR_TYPE_IP) {
        addr_ntos(&entry->intf_dst_addr, &ifra.ifra_addr);
        ioctl(intf->fd, SIOCDIFADDR, &ifra);
    }
#elif defined(SIOCLIFREMOVEIF)
    struct ifreq ifr;

    memset(&ifr, 0, sizeof(ifr));
    strlcpy(ifr.ifr_name, entry->intf_name, sizeof(ifr.ifr_name));
    /* XXX - overloading Solaris lifreq with ifreq */
    ioctl(intf->fd, SIOCLIFREMOVEIF, &ifr);
#endif
    return (0);
}
Пример #2
0
static int
_intf_add_aliases(intf_t *intf, const struct intf_entry *entry)
{
    int i;
#ifdef SIOCAIFADDR
    struct dnet_ifaliasreq ifra;
    struct addr bcast;

    memset(&ifra, 0, sizeof(ifra));
    strlcpy(ifra.ifra_name, entry->intf_name, sizeof(ifra.ifra_name));

    for (i = 0; i < (int)entry->intf_alias_num; i++) {
        if (entry->intf_alias_addrs[i].addr_type != ADDR_TYPE_IP)
            continue;

        if (addr_ntos(&entry->intf_alias_addrs[i],
                      &ifra.ifra_addr) < 0)
            return (-1);
        addr_bcast(&entry->intf_alias_addrs[i], &bcast);
        addr_ntos(&bcast, &ifra.ifra_brdaddr);
        addr_btos(entry->intf_alias_addrs[i].addr_bits,
                  &ifra.ifra_mask);

        if (ioctl(intf->fd, SIOCAIFADDR, &ifra) < 0)
            return (-1);
    }
#else
    struct ifreq ifr;
    int n = 1;

    for (i = 0; i < entry->intf_alias_num; i++) {
        if (entry->intf_alias_addrs[i].addr_type != ADDR_TYPE_IP)
            continue;

        snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s:%d",
                 entry->intf_name, n++);
# ifdef SIOCLIFADDIF
        if (ioctl(intf->fd, SIOCLIFADDIF, &ifr) < 0)
            return (-1);
# endif
        if (addr_ntos(&entry->intf_alias_addrs[i], &ifr.ifr_addr) < 0)
            return (-1);
        if (ioctl(intf->fd, SIOCSIFADDR, &ifr) < 0)
            return (-1);
    }
    strlcpy(ifr.ifr_name, entry->intf_name, sizeof(ifr.ifr_name));
#endif
    return (0);
}
Пример #3
0
static int
_intf_delete_aliases(intf_t *intf, struct intf_entry *entry)
{
    int i;
#if defined(SIOCDIFADDR) && !defined(__linux__)	/* XXX - see Linux below */
    struct dnet_ifaliasreq ifra;

    memset(&ifra, 0, sizeof(ifra));
    strlcpy(ifra.ifra_name, entry->intf_name, sizeof(ifra.ifra_name));

    for (i = 0; i < (int)entry->intf_alias_num; i++) {
        addr_ntos(&entry->intf_alias_addrs[i], &ifra.ifra_addr);
        ioctl(intf->fd, SIOCDIFADDR, &ifra);
    }
#else
    struct ifreq ifr;

    for (i = 0; i < entry->intf_alias_num; i++) {
        snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s:%d",
                 entry->intf_name, i + 1);
# ifdef SIOCLIFREMOVEIF
        /* XXX - overloading Solaris lifreq with ifreq */
        ioctl(intf->fd, SIOCLIFREMOVEIF, &ifr);
# else
        /* XXX - only need to set interface down on Linux */
        ifr.ifr_flags = 0;
        ioctl(intf->fd, SIOCSIFFLAGS, &ifr);
# endif
    }
#endif
    return (0);
}
Пример #4
0
in_addr_t anubis_default_route(void) {
    route_t *handle = route_open();
    struct route_entry route_entry = {0};
    in_addr_t addr = 0;
    
    if(!handle) {
        anubis_perror("route_open()");
        return addr;
    }//end if
    
    int ret = route_loop(handle, route_default_route_callback, (void *)&route_entry);
    
    if(ret == 1) {
        struct sockaddr_in sa = {0};
        addr_ntos(&route_entry.route_gw, (struct sockaddr *)&sa);
        addr = sa.sin_addr.s_addr;
        anubis_verbose("Default route: %s\n", anubis_ip_ntoa(addr));
    }//end if
    else {
        anubis_err("anubis_default_route(): Default gateway is not found\n");
    }//end else
    
    route_close(handle);
    return addr;
}//end anubis_default_route
Пример #5
0
/* XXX - aliases on IRIX don't show up in SIOCGIFCONF */
static int
_intf_get_aliases(intf_t *intf, struct intf_entry *entry)
{
    struct dnet_ifaliasreq ifra;
    struct addr *ap, *lap;

    strlcpy(ifra.ifra_name, entry->intf_name, sizeof(ifra.ifra_name));
    addr_ntos(&entry->intf_addr, &ifra.ifra_addr);
    addr_btos(entry->intf_addr.addr_bits, &ifra.ifra_mask);
    memset(&ifra.ifra_brdaddr, 0, sizeof(ifra.ifra_brdaddr));
    ifra.ifra_cookie = 1;

    ap = entry->intf_alias_addrs;
    lap = (struct addr *)((u_char *)entry + entry->intf_len);

    while (ioctl(intf->fd, SIOCLIFADDR, &ifra) == 0 &&
            ifra.ifra_cookie > 0 && (ap + 1) < lap) {
        if (addr_ston(&ifra.ifra_addr, ap) < 0)
            break;
        ap++, entry->intf_alias_num++;
    }
    entry->intf_len = (u_char *)ap - (u_char *)entry;

    return (0);
}
Пример #6
0
int
intf_get_dst(intf_t *intf, struct intf_entry *entry, struct addr *dst)
{
    struct sockaddr_in sin;
    int n;

    if (dst->addr_type != ADDR_TYPE_IP) {
        errno = EINVAL;
        return (-1);
    }
    addr_ntos(dst, (struct sockaddr *)&sin);
    sin.sin_port = htons(666);

    if (connect(intf->fd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
        return (-1);

    n = sizeof(sin);
    if (getsockname(intf->fd, (struct sockaddr *)&sin, &n) < 0)
        return (-1);

    addr_ston((struct sockaddr *)&sin, &entry->intf_addr);

    if (intf_loop(intf, _match_intf_src, entry) != 1)
        return (-1);

    return (0);
}
Пример #7
0
int
arp_get(arp_t *a, struct arp_entry *entry)
{
	struct arpreq ar;

	memset(&ar, 0, sizeof(ar));
	
	if (addr_ntos(&entry->arp_pa, &ar.arp_pa) < 0)
		return (-1);
	
#ifdef HAVE_ARPREQ_ARP_DEV
	if (intf_loop(a->intf, _arp_set_dev, &ar) != 1) {
		errno = ESRCH;
		return (-1);
	}
#endif
	if (ioctl(a->fd, SIOCGARP, &ar) < 0)
		return (-1);

	if ((ar.arp_flags & ATF_COM) == 0) {
		errno = ESRCH;
		return (-1);
	}
	return (addr_ston(&ar.arp_ha, &entry->arp_ha));
}
static void
RecordNetworkAddress(GuestNicV3 *nic,           // IN: operand NIC
                     const struct addr *addr)   // IN: dnet(3) address to process
{
   struct sockaddr_storage ss;
   struct sockaddr *sa = (struct sockaddr *)&ss;

   memset(&ss, 0, sizeof ss);
   addr_ntos(addr, sa);
   GuestInfoAddIpAddress(nic, sa, addr->addr_bits, NULL, NULL);
}
Пример #9
0
static int route_default_route_callback(const struct route_entry *entry, void *arg) {
    struct route_entry *route = (struct route_entry *)arg;
    struct sockaddr_in sock = {0};
    
    addr_ntos(&entry->route_dst, (struct sockaddr *)&sock);
    
    if(sock.sin_addr.s_addr == 0) {
        memmove(&route->route_gw, &entry->route_gw, sizeof(route->route_gw));
        return 1;
    }//end if
    
    return 0;
}//end route_default_route_callback
Пример #10
0
int
route_add(route_t *r, const struct route_entry *entry)
{
	struct rtentry rt;
	struct addr dst;

	memset(&rt, 0, sizeof(rt));
	rt.rt_flags = RTF_UP | RTF_GATEWAY;

	if (ADDR_ISHOST(&entry->route_dst)) {
		rt.rt_flags |= RTF_HOST;
		memcpy(&dst, &entry->route_dst, sizeof(dst));
	} else
		addr_net(&entry->route_dst, &dst);
	
	if (addr_ntos(&dst, &rt.rt_dst) < 0 ||
	    addr_ntos(&entry->route_gw, &rt.rt_gateway) < 0 ||
	    addr_btos(entry->route_dst.addr_bits, &rt.rt_genmask) < 0)
		return (-1);
	
	return (ioctl(r->fd, SIOCADDRT, &rt));
}
Пример #11
0
int
eth_set(eth_t *e, const eth_addr_t *ea)
{
	struct addr ha;

	ha.addr_type = ADDR_TYPE_ETH;
	ha.addr_bits = ETH_ADDR_BITS;
	memcpy(&ha.addr_eth, ea, ETH_ADDR_LEN);

	addr_ntos(&ha, &e->ifr.ifr_hwaddr);

	return (ioctl(e->fd, SIOCSIFHWADDR, &e->ifr));
}
Пример #12
0
int
arp_delete(arp_t *a, const struct arp_entry *entry)
{
	struct arpreq ar;

	memset(&ar, 0, sizeof(ar));
	
	if (addr_ntos(&entry->arp_pa, &ar.arp_pa) < 0)
		return (-1);
	
	if (ioctl(a->fd, SIOCDARP, &ar) < 0)
		return (-1);

	return (0);
}
Пример #13
0
int
eth_set(eth_t *e, const eth_addr_t *ea)
{
	struct ifreq ifr;
	struct addr ha;

	ha.addr_type = ADDR_TYPE_ETH;
	ha.addr_bits = ETH_ADDR_BITS;
	memcpy(&ha.addr_eth, ea, ETH_ADDR_LEN);

	memset(&ifr, 0, sizeof(ifr));
	strlcpy(ifr.ifr_name, e->device, sizeof(ifr.ifr_name));
	addr_ntos(&ha, &ifr.ifr_addr);

	return (ioctl(e->fd, SIOCSIFLLADDR, &ifr));
}
Пример #14
0
int
arp_delete(arp_t *arp, const struct arp_entry *entry)
{
	struct arpmsg msg;
	struct sockaddr_in *sin;
	struct sockaddr *sa;

	if (entry->arp_pa.addr_type != ADDR_TYPE_IP) {
		errno = EAFNOSUPPORT;
		return (-1);
	}
	sin = (struct sockaddr_in *)msg.addrs;
	sa = (struct sockaddr *)(sin + 1);

	if (addr_ntos(&entry->arp_pa, (struct sockaddr *)sin) < 0)
		return (-1);

	memset(&msg.rtm, 0, sizeof(msg.rtm));
	msg.rtm.rtm_type = RTM_GET;
	msg.rtm.rtm_addrs = RTA_DST;
	msg.rtm.rtm_msglen = sizeof(msg.rtm) + sizeof(*sin);

	if (arp_msg(arp, &msg) < 0)
		return (-1);

	if (msg.rtm.rtm_msglen < (int)sizeof(msg.rtm) +
	    sizeof(*sin) + sizeof(*sa)) {
		errno = ESRCH;
		return (-1);
	}
	if (sin->sin_addr.s_addr == entry->arp_pa.addr_ip) {
		if ((msg.rtm.rtm_flags & RTF_LLINFO) == 0 ||
		    (msg.rtm.rtm_flags & RTF_GATEWAY) != 0) {
			errno = EADDRINUSE;
			return (-1);
		}
	}
	if (sa->sa_family != AF_LINK) {
		errno = ESRCH;
		return (-1);
	}
	msg.rtm.rtm_type = RTM_DELETE;

	return (arp_msg(arp, &msg));
}
Пример #15
0
int
arp_get(arp_t *arp, struct arp_entry *entry)
{
	struct arpmsg msg;
	struct sockaddr_in *sin;
	struct sockaddr *sa;

	if (entry->arp_pa.addr_type != ADDR_TYPE_IP) {
		errno = EAFNOSUPPORT;
		return (-1);
	}
	sin = (struct sockaddr_in *)msg.addrs;
	sa = (struct sockaddr *)(sin + 1);

	if (addr_ntos(&entry->arp_pa, (struct sockaddr *)sin) < 0)
		return (-1);

	memset(&msg.rtm, 0, sizeof(msg.rtm));
	msg.rtm.rtm_type = RTM_GET;
	msg.rtm.rtm_addrs = RTA_DST;
	msg.rtm.rtm_flags = RTF_LLINFO;
	msg.rtm.rtm_msglen = sizeof(msg.rtm) + sizeof(*sin);

	if (arp_msg(arp, &msg) < 0)
		return (-1);

	if (msg.rtm.rtm_msglen < (int)sizeof(msg.rtm) +
	    sizeof(*sin) + sizeof(*sa) ||
	    sin->sin_addr.s_addr != entry->arp_pa.addr_ip ||
	    sa->sa_family != AF_LINK) {
		errno = ESRCH;
		return (-1);
	}
	if (addr_ston(sa, &entry->arp_ha) < 0)
		return (-1);

	return (0);
}
Пример #16
0
/* Converts a dnet interface name (ifname) to its pcap equivalent, which is stored in
pcapdev (up to a length of pcapdevlen).  Returns 0 and fills in pcapdev if successful. */
int intf_get_pcap_devname(const char *ifname, char *pcapdev, int pcapdevlen) {
	int i;
	intf_t *intf;
	struct intf_entry ie;
	pcap_if_t *pcapdevs;
	pcap_if_t *pdev;
	char pname[128];
	struct sockaddr_in devip;
	pcap_addr_t *pa;

	if ((intf = intf_open()) == NULL)
		return -1;
	
	pname[0] = '\0';
	memset(&ie, 0, sizeof(ie));
	strlcpy(ie.intf_name, ifname, sizeof(ie.intf_name));
	if (intf_get(intf, &ie) != 0) {
		intf_close(intf);
		return -1;
	}
	intf_close(intf);
	
	/* Find the first IPv4 address for ie */
	if (ie.intf_addr.addr_type == ADDR_TYPE_IP) {
		addr_ntos(&ie.intf_addr, (struct sockaddr *) &devip);
	} else {
		for(i=0; i < (int) ie.intf_alias_num; i++) {
			if (ie.intf_alias_addrs[i].addr_type == ADDR_TYPE_IP) {
				addr_ntos(&ie.intf_alias_addrs[i], (struct sockaddr *) &devip);
				break;
			}
		}
		if (i == ie.intf_alias_num)
			return -1; // Failed to find IPv4 address, which is currently a requirement
	}

	/* Next we must find the pcap device name corresponding to the device.
	   The device description used to be compared with those from PacketGetAdapterNames(), but
	   that was unrelaible because dnet and pcap sometimes give different descriptions.  For example, 
	   dnet gave me "AMD PCNET Family PCI Ethernet Adapter - Packet Scheduler Miniport" for one of my 
	   adapters (in vmware), while pcap described it as "VMware Accelerated AMD PCNet Adapter (Microsoft's
	   Packet Scheduler)". Plus,  Packet* functions aren't really supported for external use by the 
	   WinPcap folks.  So I have rewritten this to compare interface addresses (which has its own 
	   problems -- what if you want to listen an an interface with no IP address set?) --Fyodor */
	if (pcap_findalldevs(&pcapdevs, NULL) == -1)
		return -1;

	for(pdev=pcapdevs; pdev && !pname[0]; pdev = pdev->next) {
		for (pa=pdev->addresses; pa && !pname[0]; pa = pa->next) {
			if (pa->addr->sa_family != AF_INET)
				continue;
			if (((struct sockaddr_in *)pa->addr)->sin_addr.s_addr == devip.sin_addr.s_addr) {
				strlcpy(pname, pdev->name, sizeof(pname)); /* Found it -- Yay! */
			break;
	}
		}
	}

	pcap_freealldevs(pcapdevs);
	if (pname[0]) {
		strlcpy(pcapdev, pname, pcapdevlen);
		return 0;
	}
	return -1;
}
Пример #17
0
int
intf_set(intf_t *intf, const struct intf_entry *entry)
{
    struct ifreq ifr;
    struct intf_entry *orig;
    struct addr bcast;
    u_char buf[BUFSIZ];

    orig = (struct intf_entry *)buf;
    orig->intf_len = sizeof(buf);
    strcpy(orig->intf_name, entry->intf_name);

    if (intf_get(intf, orig) < 0)
        return (-1);

    /* Delete any existing aliases. */
    if (_intf_delete_aliases(intf, orig) < 0)
        return (-1);

    /* Delete any existing addrs. */
    if (_intf_delete_addrs(intf, orig) < 0)
        return (-1);

    memset(&ifr, 0, sizeof(ifr));
    strlcpy(ifr.ifr_name, entry->intf_name, sizeof(ifr.ifr_name));

    /* Set interface MTU. */
    if (entry->intf_mtu != 0) {
        ifr.ifr_mtu = entry->intf_mtu;
#ifdef SIOCSIFMTU
        if (ioctl(intf->fd, SIOCSIFMTU, &ifr) < 0)
#endif
            return (-1);
    }
    /* Set interface address. */
    if (entry->intf_addr.addr_type == ADDR_TYPE_IP) {
#ifdef BSD
        /* XXX - why must this happen before SIOCSIFADDR? */
        if (addr_btos(entry->intf_addr.addr_bits,
                      &ifr.ifr_addr) == 0) {
            if (ioctl(intf->fd, SIOCSIFNETMASK, &ifr) < 0)
                return (-1);
        }
#endif
        if (addr_ntos(&entry->intf_addr, &ifr.ifr_addr) < 0)
            return (-1);
        if (ioctl(intf->fd, SIOCSIFADDR, &ifr) < 0 && errno != EEXIST)
            return (-1);

        if (addr_btos(entry->intf_addr.addr_bits, &ifr.ifr_addr) == 0
#ifdef __linux__
                && entry->intf_addr.addr_ip != 0
#endif
           ) {
            if (ioctl(intf->fd, SIOCSIFNETMASK, &ifr) < 0)
                return (-1);
        }
        if (addr_bcast(&entry->intf_addr, &bcast) == 0) {
            if (addr_ntos(&bcast, &ifr.ifr_broadaddr) == 0) {
                /* XXX - ignore error from non-broadcast ifs */
                ioctl(intf->fd, SIOCSIFBRDADDR, &ifr);
            }
        }
    }
    /* Set link-level address. */
    if (entry->intf_link_addr.addr_type == ADDR_TYPE_ETH &&
            addr_cmp(&entry->intf_link_addr, &orig->intf_link_addr) != 0) {
#if defined(SIOCSIFHWADDR)
        if (addr_ntos(&entry->intf_link_addr, &ifr.ifr_hwaddr) < 0)
            return (-1);
        if (ioctl(intf->fd, SIOCSIFHWADDR, &ifr) < 0)
            return (-1);
#elif defined (SIOCSIFLLADDR)
        memcpy(ifr.ifr_addr.sa_data, &entry->intf_link_addr.addr_eth,
               ETH_ADDR_LEN);
        ifr.ifr_addr.sa_len = ETH_ADDR_LEN;
        if (ioctl(intf->fd, SIOCSIFLLADDR, &ifr) < 0)
            return (-1);
#else
        eth_t *eth;

        if ((eth = eth_open(entry->intf_name)) == NULL)
            return (-1);
        if (eth_set(eth, &entry->intf_link_addr.addr_eth) < 0) {
            eth_close(eth);
            return (-1);
        }
        eth_close(eth);
#endif
    }
    /* Set point-to-point destination. */
    if (entry->intf_dst_addr.addr_type == ADDR_TYPE_IP) {
        if (addr_ntos(&entry->intf_dst_addr, &ifr.ifr_dstaddr) < 0)
            return (-1);
        if (ioctl(intf->fd, SIOCSIFDSTADDR, &ifr) < 0 &&
                errno != EEXIST)
            return (-1);
    }
    /* Add aliases. */
    if (_intf_add_aliases(intf, entry) < 0)
        return (-1);

    /* Set interface flags. */
    if (ioctl(intf->fd, SIOCGIFFLAGS, &ifr) < 0)
        return (-1);

    ifr.ifr_flags = intf_flags_to_iff(entry->intf_flags, ifr.ifr_flags);

    if (ioctl(intf->fd, SIOCSIFFLAGS, &ifr) < 0)
        return (-1);

    return (0);
}
Пример #18
0
static int
route_msg(route_t *r, int type, struct addr *dst, struct addr *gw)
{
	struct addr net;
	struct rt_msghdr *rtm;
	struct sockaddr *sa;
	u_char buf[BUFSIZ];
	pid_t pid;
	int len;

	memset(buf, 0, sizeof(buf));

	rtm = (struct rt_msghdr *)buf;
	rtm->rtm_version = RTM_VERSION;
	if ((rtm->rtm_type = type) != RTM_DELETE)
		rtm->rtm_flags = RTF_UP;
	rtm->rtm_addrs = RTA_DST;
	rtm->rtm_seq = ++r->seq;

	/* Destination */
	sa = (struct sockaddr *)(rtm + 1);
	if (addr_net(dst, &net) < 0 || addr_ntos(&net, sa) < 0)
		return (-1);
	sa = NEXTSA(sa);

	/* Gateway */
	if (gw != NULL && type != RTM_GET) {
		rtm->rtm_flags |= RTF_GATEWAY;
		rtm->rtm_addrs |= RTA_GATEWAY;
		if (addr_ntos(gw, sa) < 0)
			return (-1);
		sa = NEXTSA(sa);
	}
	/* Netmask */
	if (dst->addr_ip == IP_ADDR_ANY || dst->addr_bits < IP_ADDR_BITS) {
		rtm->rtm_addrs |= RTA_NETMASK;
		if (addr_btos(dst->addr_bits, sa) < 0)
			return (-1);
		sa = NEXTSA(sa);
	} else
		rtm->rtm_flags |= RTF_HOST;
	
	rtm->rtm_msglen = (u_char *)sa - buf;
#ifdef DEBUG
	route_msg_print(rtm);
#endif
#ifdef HAVE_STREAMS_ROUTE
	if (ioctl(r->fd, RTSTR_SEND, rtm) < 0)
		return (-1);
#else
	if (write(r->fd, buf, rtm->rtm_msglen) < 0)
		return (-1);

	pid = getpid();
	
	while (type == RTM_GET && (len = read(r->fd, buf, sizeof(buf))) > 0) {
		if (len < (int)sizeof(*rtm)) {
			return (-1);
		}
		if (rtm->rtm_type == type && rtm->rtm_pid == pid &&
		    rtm->rtm_seq == r->seq) {
			if (rtm->rtm_errno) {
				errno = rtm->rtm_errno;
				return (-1);
			}
			break;
		}
	}
#endif
	if (type == RTM_GET && (rtm->rtm_addrs & (RTA_DST|RTA_GATEWAY)) ==
	    (RTA_DST|RTA_GATEWAY)) {
		sa = (struct sockaddr *)(rtm + 1);
		sa = NEXTSA(sa);
		
		if (addr_ston(sa, gw) < 0 || gw->addr_type != ADDR_TYPE_IP) {
			errno = ESRCH;
			return (-1);
		}
	}
	return (0);
}
Пример #19
0
int
arp_add(arp_t *arp, const struct arp_entry *entry)
{
	struct arpmsg msg;
	struct sockaddr_in *sin;
	struct sockaddr *sa;
	int index, type;

	if (entry->arp_pa.addr_type != ADDR_TYPE_IP ||
	    entry->arp_ha.addr_type != ADDR_TYPE_ETH) {
		errno = EAFNOSUPPORT;
		return (-1);
	}
	sin = (struct sockaddr_in *)msg.addrs;
	sa = (struct sockaddr *)(sin + 1);

	if (addr_ntos(&entry->arp_pa, (struct sockaddr *)sin) < 0)
		return (-1);

	memset(&msg.rtm, 0, sizeof(msg.rtm));
	msg.rtm.rtm_type = RTM_GET;
	msg.rtm.rtm_addrs = RTA_DST;
	msg.rtm.rtm_msglen = sizeof(msg.rtm) + sizeof(*sin);

	if (arp_msg(arp, &msg) < 0)
		return (-1);

	if (msg.rtm.rtm_msglen < (int)sizeof(msg.rtm) +
	    sizeof(*sin) + sizeof(*sa)) {
		errno = EADDRNOTAVAIL;
		return (-1);
	}
	if (sin->sin_addr.s_addr == entry->arp_pa.addr_ip) {
		if ((msg.rtm.rtm_flags & RTF_LLINFO) == 0 ||
		    (msg.rtm.rtm_flags & RTF_GATEWAY) != 0) {
			errno = EADDRINUSE;
			return (-1);
		}
	}
	if (sa->sa_family != AF_LINK) {
		errno = EADDRNOTAVAIL;
		return (-1);
	} else {
		index = ((struct sockaddr_dl *)sa)->sdl_index;
		type = ((struct sockaddr_dl *)sa)->sdl_type;
	}
	if (addr_ntos(&entry->arp_pa, (struct sockaddr *)sin) < 0 ||
	    addr_ntos(&entry->arp_ha, sa) < 0)
		return (-1);

	((struct sockaddr_dl *)sa)->sdl_index = index;
	((struct sockaddr_dl *)sa)->sdl_type = type;

	memset(&msg.rtm, 0, sizeof(msg.rtm));
	msg.rtm.rtm_type = RTM_ADD;
	msg.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY;
	msg.rtm.rtm_inits = RTV_EXPIRE;
	msg.rtm.rtm_flags = RTF_HOST | RTF_STATIC;
#ifdef HAVE_SOCKADDR_SA_LEN
	msg.rtm.rtm_msglen = sizeof(msg.rtm) + sin->sin_len + sa->sa_len;
#else
	msg.rtm.rtm_msglen = sizeof(msg.rtm) + sizeof(*sin) + sizeof(*sa);
#endif
	return (arp_msg(arp, &msg));
}
Пример #20
0
int
arp_add(arp_t *a, const struct arp_entry *entry)
{
	struct arpreq ar;

	memset(&ar, 0, sizeof(ar));

	if (addr_ntos(&entry->arp_pa, &ar.arp_pa) < 0)
		return (-1);

	/* XXX - see arp(7) for details... */
#ifdef __linux__
	if (addr_ntos(&entry->arp_ha, &ar.arp_ha) < 0)
		return (-1);
	ar.arp_ha.sa_family = ARP_HRD_ETH;
#else
	/* XXX - Solaris, HP-UX, IRIX, other Mentat stacks? */
	ar.arp_ha.sa_family = AF_UNSPEC;
	memcpy(ar.arp_ha.sa_data, &entry->arp_ha.addr_eth, ETH_ADDR_LEN);
#endif

#ifdef HAVE_ARPREQ_ARP_DEV
	if (intf_loop(a->intf, _arp_set_dev, &ar) != 1) {
		errno = ESRCH;
		return (-1);
	}
#endif
	ar.arp_flags = ATF_PERM | ATF_COM;
#ifdef hpux
	/* XXX - screwy extended arpreq struct */
	{
		struct sockaddr_in *sin;

		ar.arp_hw_addr_len = ETH_ADDR_LEN;
		sin = (struct sockaddr_in *)&ar.arp_pa_mask;
		sin->sin_family = AF_INET;
		sin->sin_addr.s_addr = IP_ADDR_BROADCAST;
	}
#endif
	if (ioctl(a->fd, SIOCSARP, &ar) < 0)
		return (-1);

#ifdef HAVE_STREAMS_MIB2
	/* XXX - force entry into ipNetToMediaTable. */
	{
		struct sockaddr_in sin;
		int fd;
		
		addr_ntos(&entry->arp_pa, (struct sockaddr *)&sin);
		sin.sin_port = htons(666);
		
		if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
			return (-1);
		
		if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
			close(fd);
			return (-1);
		}
		write(fd, NULL, 0);
		close(fd);
	}
#endif
	return (0);
}