示例#1
0
文件: lldp.c 项目: houzhenggang/ladvd
size_t lldp_packet(uint8_t proto, void *packet, struct netif *netif,
		struct nhead *netifs, struct my_sysinfo *sysinfo) {

    struct ether_hdr ether;

    char *tlv;
    char *pos = packet;
    size_t length = ETHER_MAX_LEN;

    uint16_t cap = 0, cap_active = 0;
    struct netif *parent, *mgmt, *vlanif = NULL;
    uint8_t *hwaddr;
    struct hinv *hinv;
    char *description;

    const uint8_t lldp_dst[] = LLDP_MULTICAST_ADDR;

    // fixup parent netif
    if (netif->parent != NULL)
	parent = netif->parent;
    else
	parent = netif;

    // configure managment interface
    mgmt = sysinfo->mnetif;
    if (!mgmt)
	mgmt = parent;

    // ethernet header
    memcpy(ether.dst, lldp_dst, ETHER_ADDR_LEN);
    memcpy(ether.src, netif->hwaddr, ETHER_ADDR_LEN);
    ether.type = htons(ETHERTYPE_LLDP);
    memcpy(pos, &ether, sizeof(struct ether_hdr));
    pos += sizeof(struct ether_hdr);

    // update tlv counters
    length -= VOIDP_DIFF(pos, packet);

    // chassis id and hinv
    hwaddr = (options & OPT_CHASSIS_IF) ? netif->hwaddr : sysinfo->hwaddr;
    hinv = &(sysinfo->hinv);

    if (!(
	START_LLDP_TLV(LLDP_TYPE_CHASSIS_ID) &&
	PUSH_UINT8(LLDP_CHASSIS_MAC_ADDR_SUBTYPE) &&
	PUSH_BYTES(hwaddr, ETHER_ADDR_LEN)
    ))
	return 0;
    END_LLDP_TLV;


    // port id
    if (!(
	START_LLDP_TLV(LLDP_TYPE_PORT_ID) &&
	PUSH_UINT8(LLDP_PORT_INTF_NAME_SUBTYPE) &&
	PUSH_BYTES(netif->name, strlen(netif->name))
    ))
	return 0;
    END_LLDP_TLV;


    // ttl
    if (!(
	START_LLDP_TLV(LLDP_TYPE_TTL) &&
	PUSH_UINT16(LADVD_TTL)
    ))
	return 0;
    END_LLDP_TLV;


    // port description
    if (options & OPT_IFDESCR)
	description = netif->device_name;
    else if (strlen(netif->description))
	description = netif->description;
    else if (strlen(parent->description))
	description = parent->description;
    else
	description = netif->device_name;

    if (strlen(description) > 0) {
	if (!(
	    START_LLDP_TLV(LLDP_TYPE_PORT_DESCR) &&
	    PUSH_BYTES(description, strlen(description))
	))
	    return 0;
	END_LLDP_TLV;
    }


    // system name
    if (!(
	START_LLDP_TLV(LLDP_TYPE_SYSTEM_NAME) &&
	PUSH_BYTES(sysinfo->hostname, strlen(sysinfo->hostname))
    ))
	return 0;
    END_LLDP_TLV;


    // system description
    if (!(
	START_LLDP_TLV(LLDP_TYPE_SYSTEM_DESCR) &&
	PUSH_BYTES(sysinfo->uts_str, strlen(sysinfo->uts_str))
    ))
	return 0;
    END_LLDP_TLV;


    // capabilities
    if (sysinfo->cap == CAP_HOST) {
	cap = cap_active = LLDP_CAP_STATION_ONLY;
    } else {
	cap |= (sysinfo->cap & CAP_BRIDGE) ? LLDP_CAP_BRIDGE : 0;
	cap_active |= (sysinfo->cap_active & CAP_BRIDGE) ? LLDP_CAP_BRIDGE : 0;

	cap |= (sysinfo->cap & CAP_ROUTER) ? LLDP_CAP_ROUTER : 0;
	cap_active |= (sysinfo->cap_active & CAP_ROUTER) ? LLDP_CAP_ROUTER : 0;

	cap |= (sysinfo->cap & CAP_SWITCH) ? LLDP_CAP_BRIDGE : 0;
	cap_active |= (sysinfo->cap_active & CAP_SWITCH) ? LLDP_CAP_BRIDGE : 0;

	cap |= (sysinfo->cap & CAP_WLAN) ? LLDP_CAP_WLAN_AP : 0;
	cap_active |= (sysinfo->cap_active & CAP_WLAN) ? LLDP_CAP_WLAN_AP : 0;
    }

    if (!(
	START_LLDP_TLV(LLDP_TYPE_SYSTEM_CAP) &&
	PUSH_UINT16(cap) && PUSH_UINT16(cap_active)
    ))
	return 0;
    END_LLDP_TLV;


    // ipv4 management addr
    if (mgmt->ipaddr4 != 0) {
	if (!(
	    START_LLDP_TLV(LLDP_TYPE_MGMT_ADDR) &&
	    PUSH_UINT8(1 + sizeof(mgmt->ipaddr4)) &&
	    PUSH_UINT8(LLDP_AFNUM_INET) &&
	    PUSH_BYTES(&mgmt->ipaddr4, sizeof(mgmt->ipaddr4)) &&
	    PUSH_UINT8(LLDP_INTF_NUMB_IFX_SUBTYPE) &&
	    PUSH_UINT32(mgmt->index) &&
	    PUSH_UINT8(0)
	))
	    return 0;
	END_LLDP_TLV;
    }


    // ipv6 management addr
    if (!IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)mgmt->ipaddr6)) {
	if (!(
	    START_LLDP_TLV(LLDP_TYPE_MGMT_ADDR) &&
	    PUSH_UINT8(1 + sizeof(mgmt->ipaddr6)) &&
	    PUSH_UINT8(LLDP_AFNUM_INET6) &&
	    PUSH_BYTES(mgmt->ipaddr6, sizeof(mgmt->ipaddr6)) &&
	    PUSH_UINT8(LLDP_INTF_NUMB_IFX_SUBTYPE) &&
	    PUSH_UINT32(mgmt->index) &&
	    PUSH_UINT8(0)
	))
	    return 0;
	END_LLDP_TLV;
    }


    // hw management addr
    if (!(
	START_LLDP_TLV(LLDP_TYPE_MGMT_ADDR) &&
	PUSH_UINT8(1 + sizeof(mgmt->hwaddr)) &&
	PUSH_UINT8(LLDP_AFNUM_802) &&
	PUSH_BYTES(mgmt->hwaddr, sizeof(mgmt->hwaddr)) &&
	PUSH_UINT8(LLDP_INTF_NUMB_IFX_SUBTYPE) &&
	PUSH_UINT32(mgmt->index) &&
	PUSH_UINT8(0)
    ))
	return 0;
    END_LLDP_TLV;


    // IEEE 802.1 Organizationally Specific TLV set

    // vlan names
    while ((vlanif = netif_iter(vlanif, netifs)) != NULL) {    
	    if (vlanif->type != NETIF_VLAN)
		continue;

	    // skip unless attached to this interface or the parent
	    if ((vlanif->vlan_parent != netif->index) &&
		(vlanif->vlan_parent != parent->index))
		continue;

	    if (!(
		START_LLDP_TLV(LLDP_TYPE_PRIVATE) &&
		PUSH_BYTES(OUI_IEEE_8021_PRIVATE, OUI_LEN) &&
		PUSH_UINT8(LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME) &&
		PUSH_UINT16(vlanif->vlan_id) &&
		PUSH_UINT8(strlen(vlanif->name)) &&
		PUSH_BYTES(vlanif->name, strlen(vlanif->name))
	    ))
		return 0;
	    END_LLDP_TLV;
    }


    // IEEE 802.3 Organizationally Specific TLV set

    // autoneg
    if (netif->autoneg_supported != -1) {
	if (!(
	    START_LLDP_TLV(LLDP_TYPE_PRIVATE) &&
	    PUSH_BYTES(OUI_IEEE_8023_PRIVATE, OUI_LEN) &&
	    PUSH_UINT8(LLDP_PRIVATE_8023_SUBTYPE_MACPHY) &&
	    PUSH_UINT8(netif->autoneg_supported +
		       (netif->autoneg_enabled << 1)) &&
	    PUSH_UINT16(netif->autoneg_pmd) &&
	    PUSH_UINT16(netif->mau)
	))
	    return 0;
	END_LLDP_TLV;
    }


    // lacp
    if (parent->bonding_mode == NETIF_BONDING_LACP) {
	if (!(
	    START_LLDP_TLV(LLDP_TYPE_PRIVATE) &&
	    PUSH_BYTES(OUI_IEEE_8023_PRIVATE, OUI_LEN) &&
	    PUSH_UINT8(LLDP_PRIVATE_8023_SUBTYPE_LINKAGGR) &&
	    PUSH_UINT8(LLDP_AGGREGATION_CAPABILTIY|LLDP_AGGREGATION_STATUS) &&
	    PUSH_UINT32(netif->lacp_index)
	))
	    return 0;
	END_LLDP_TLV;
    }


    // mtu
    if (netif->mtu != 0) {
	if (!(
	    START_LLDP_TLV(LLDP_TYPE_PRIVATE) &&
	    PUSH_BYTES(OUI_IEEE_8023_PRIVATE, OUI_LEN) &&
	    PUSH_UINT8(LLDP_PRIVATE_8023_SUBTYPE_MTU) &&
	    PUSH_UINT16(netif->mtu + 22)
	))
	    return 0;
	END_LLDP_TLV;
    }


    // TIA LLDP-MED Capabilities TLV
    if (!(
	START_LLDP_TLV(LLDP_TYPE_PRIVATE) &&
	PUSH_BYTES(OUI_TIA, OUI_LEN) &&
	PUSH_UINT8(LLDP_PRIVATE_TIA_SUBTYPE_CAPABILITIES) &&
	PUSH_UINT16(sysinfo->cap_lldpmed) &&
	PUSH_UINT8(sysinfo->lldpmed_devtype)
    ))
	return 0;
    END_LLDP_TLV;

    // TIA Location Identification TLv

    // LOC ("location", CAtype 22): unstructured additional information
    if ((strlen(sysinfo->country) == 2) && (strlen(sysinfo->location) != 0)) {
	if (!(
	    START_LLDP_TLV(LLDP_TYPE_PRIVATE) &&
	    PUSH_BYTES(OUI_TIA, OUI_LEN) &&
	    PUSH_UINT8(LLDP_PRIVATE_TIA_SUBTYPE_LOCAL_ID) &&
	    PUSH_UINT8(LLDP_TIA_LOCATION_DATA_FORMAT_CIVIC_ADDRESS) &&
	    PUSH_UINT8(5 + strlen(sysinfo->location)) &&
	    PUSH_UINT8(LLDP_TIA_LOCATION_LCI_WHAT_CLIENT) &&
	    PUSH_BYTES(sysinfo->country, 2) &&
	    PUSH_UINT8(LLDP_TIA_LOCATION_LCI_CATYPE_LOC) &&
	    PUSH_UINT8(strlen(sysinfo->location)) &&
	    PUSH_BYTES(sysinfo->location, strlen(sysinfo->location))
	))
	    return 0;
	END_LLDP_TLV;
    }



    // TIA Inventory Management TLV Set

    // hardware revision
    if (strlen(hinv->hw_revision) > 0) {
	if (!(
	    START_LLDP_TLV(LLDP_TYPE_PRIVATE) &&
	    PUSH_BYTES(OUI_TIA, OUI_LEN) &&
	    PUSH_UINT8(LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV) &&
	    PUSH_BYTES(hinv->hw_revision, strlen(hinv->hw_revision))
	))
	    return 0;
	END_LLDP_TLV;
    }


    // firmware revision
    if (strlen(hinv->fw_revision) > 0) {
	if (!(
	    START_LLDP_TLV(LLDP_TYPE_PRIVATE) &&
	    PUSH_BYTES(OUI_TIA, OUI_LEN) &&
	    PUSH_UINT8(LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV) &&
	    PUSH_BYTES(hinv->fw_revision, strlen(hinv->fw_revision))
	))
	    return 0;
	END_LLDP_TLV;
    }


    // software revision
    if (strlen(hinv->sw_revision) > 0) {
	if (!(
	    START_LLDP_TLV(LLDP_TYPE_PRIVATE) &&
	    PUSH_BYTES(OUI_TIA, OUI_LEN) &&
	    PUSH_UINT8(LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV) &&
	    PUSH_BYTES(hinv->sw_revision, strlen(hinv->sw_revision))
	))
	    return 0;
	END_LLDP_TLV;
    }


    // serial number
    if (strlen(hinv->serial_number) > 0) {
	if (!(
	    START_LLDP_TLV(LLDP_TYPE_PRIVATE) &&
	    PUSH_BYTES(OUI_TIA, OUI_LEN) &&
	    PUSH_UINT8(LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER) &&
	    PUSH_BYTES(hinv->serial_number, strlen(hinv->serial_number))
	))
	    return 0;
	END_LLDP_TLV;
    }


    // manufacturer
    if (strlen(hinv->manufacturer) > 0) {
	if (!(
	    START_LLDP_TLV(LLDP_TYPE_PRIVATE) &&
	    PUSH_BYTES(OUI_TIA, OUI_LEN) &&
	    PUSH_UINT8(LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME) &&
	    PUSH_BYTES(hinv->manufacturer, strlen(hinv->manufacturer))
	))
	    return 0;
	END_LLDP_TLV;
    }


    // model name
    if (strlen(hinv->model_name) > 0) {
	if (!(
	    START_LLDP_TLV(LLDP_TYPE_PRIVATE) &&
	    PUSH_BYTES(OUI_TIA, OUI_LEN) &&
	    PUSH_UINT8(LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME) &&
	    PUSH_BYTES(hinv->model_name, strlen(hinv->model_name))
	))
	    return 0;
	END_LLDP_TLV;
    }


    // asset id
    if (strlen(hinv->asset_id) > 0) {
	if (!(
	    START_LLDP_TLV(LLDP_TYPE_PRIVATE) &&
	    PUSH_BYTES(OUI_TIA, OUI_LEN) &&
	    PUSH_UINT8(LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID) &&
	    PUSH_BYTES(hinv->asset_id, strlen(hinv->asset_id))
	))
	    return 0;
	END_LLDP_TLV;
    }



    // the end
    if (!(
	START_LLDP_TLV(LLDP_TYPE_END)
    ))
	return 0;
    END_LLDP_TLV;


    // return the packet length
    return(VOIDP_DIFF(pos, packet));
}
示例#2
0
int fr_packet_list_socket_add(fr_packet_list_t *pl, int sockfd)
{
	int i, start;
	struct sockaddr_storage	src;
	socklen_t	        sizeof_src = sizeof(src);
	fr_packet_socket_t	*ps;

	if (!pl) return 0;

	ps = NULL;
	i = start = SOCK2OFFSET(sockfd);

	do {
		if (pl->sockets[i].sockfd == -1) {
			ps =  &pl->sockets[i];
			start = i;
			break;
		}

		i = (i + 1) & SOCKOFFSET_MASK;
	} while (i != start);

	if (!ps) {
		return 0;
	}

	memset(ps, 0, sizeof(*ps));
	ps->sockfd = sockfd;
	ps->offset = start;

	/*
	 *	Get address family, etc. first, so we know if we
	 *	need to do udpfromto.
	 *
	 *	FIXME: udpfromto also does this, but it's not
	 *	a critical problem.
	 */
	memset(&src, 0, sizeof_src);
	if (getsockname(sockfd, (struct sockaddr *) &src,
			&sizeof_src) < 0) {
		return 0;
	}

	if (!fr_sockaddr2ipaddr(&src, sizeof_src, &ps->ipaddr, &ps->port)) {
		return 0;
	}

	/*
	 *	Grab IP addresses & ports from the sockaddr.
	 */
	if (src.ss_family == AF_INET) {
		if (ps->ipaddr.ipaddr.ip4addr.s_addr == INADDR_ANY) {
			ps->inaddr_any = 1;
		}

#ifdef HAVE_STRUCT_SOCKADDR_IN6
	} else if (src.ss_family == AF_INET6) {
		if (IN6_IS_ADDR_UNSPECIFIED(&ps->ipaddr.ipaddr.ip6addr)) {
			ps->inaddr_any = 1;
		}
#endif
	} else {
		return 0;
	}

	pl->mask |= (1 << ps->offset);
	return 1;
}
示例#3
0
/*
 * Input a Neighbor Solicitation Message.
 *
 * Based on RFC 2461
 * Based on RFC 2462 (duplicate address detection)
 */
void
nd6_ns_input(struct mbuf *m, int off, int icmp6len)
{
	struct ifnet *ifp = m->m_pkthdr.rcvif;
	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
	struct nd_neighbor_solicit *nd_ns;
	struct in6_addr saddr6 = ip6->ip6_src;
	struct in6_addr daddr6 = ip6->ip6_dst;
	struct in6_addr taddr6;
	struct in6_addr myaddr6;
	char *lladdr = NULL;
	struct ifaddr *ifa = NULL;
	int lladdrlen = 0;
	int anycast = 0, proxy = 0, tentative = 0;
	int tlladdr;
	int rflag;
	union nd_opts ndopts;
	struct sockaddr_dl proxydl;
	char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];

	rflag = (V_ip6_forwarding) ? ND_NA_FLAG_ROUTER : 0;
	if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV && V_ip6_norbit_raif)
		rflag = 0;
#ifndef PULLDOWN_TEST
	IP6_EXTHDR_CHECK(m, off, icmp6len,);
	nd_ns = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off);
#else
	IP6_EXTHDR_GET(nd_ns, struct nd_neighbor_solicit *, m, off, icmp6len);
	if (nd_ns == NULL) {
		ICMP6STAT_INC(icp6s_tooshort);
		return;
	}
#endif
	ip6 = mtod(m, struct ip6_hdr *); /* adjust pointer for safety */
	taddr6 = nd_ns->nd_ns_target;
	if (in6_setscope(&taddr6, ifp, NULL) != 0)
		goto bad;

	if (ip6->ip6_hlim != 255) {
		nd6log((LOG_ERR,
		    "nd6_ns_input: invalid hlim (%d) from %s to %s on %s\n",
		    ip6->ip6_hlim, ip6_sprintf(ip6bufs, &ip6->ip6_src),
		    ip6_sprintf(ip6bufd, &ip6->ip6_dst), if_name(ifp)));
		goto bad;
	}

	if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) {
		/* dst has to be a solicited node multicast address. */
		if (daddr6.s6_addr16[0] == IPV6_ADDR_INT16_MLL &&
		    /* don't check ifindex portion */
		    daddr6.s6_addr32[1] == 0 &&
		    daddr6.s6_addr32[2] == IPV6_ADDR_INT32_ONE &&
		    daddr6.s6_addr8[12] == 0xff) {
			; /* good */
		} else {
			nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet "
			    "(wrong ip6 dst)\n"));
			goto bad;
		}
	} else if (!V_nd6_onlink_ns_rfc4861) {
		struct sockaddr_in6 src_sa6;

		/*
		 * According to recent IETF discussions, it is not a good idea
		 * to accept a NS from an address which would not be deemed
		 * to be a neighbor otherwise.  This point is expected to be
		 * clarified in future revisions of the specification.
		 */
		bzero(&src_sa6, sizeof(src_sa6));
		src_sa6.sin6_family = AF_INET6;
		src_sa6.sin6_len = sizeof(src_sa6);
		src_sa6.sin6_addr = saddr6;
		if (nd6_is_addr_neighbor(&src_sa6, ifp) == 0) {
			nd6log((LOG_INFO, "nd6_ns_input: "
				"NS packet from non-neighbor\n"));
			goto bad;
		}
	}

	if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
		nd6log((LOG_INFO, "nd6_ns_input: bad NS target (multicast)\n"));
		goto bad;
	}

	icmp6len -= sizeof(*nd_ns);
	nd6_option_init(nd_ns + 1, icmp6len, &ndopts);
	if (nd6_options(&ndopts) < 0) {
		nd6log((LOG_INFO,
		    "nd6_ns_input: invalid ND option, ignored\n"));
		/* nd6_options have incremented stats */
		goto freeit;
	}

	if (ndopts.nd_opts_src_lladdr) {
		lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
		lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
	}

	if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) && lladdr) {
		nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet "
		    "(link-layer address option)\n"));
		goto bad;
	}

	/*
	 * Attaching target link-layer address to the NA?
	 * (RFC 2461 7.2.4)
	 *
	 * NS IP dst is unicast/anycast			MUST NOT add
	 * NS IP dst is solicited-node multicast	MUST add
	 *
	 * In implementation, we add target link-layer address by default.
	 * We do not add one in MUST NOT cases.
	 */
	if (!IN6_IS_ADDR_MULTICAST(&daddr6))
		tlladdr = 0;
	else
		tlladdr = 1;

	/*
	 * Target address (taddr6) must be either:
	 * (1) Valid unicast/anycast address for my receiving interface,
	 * (2) Unicast address for which I'm offering proxy service, or
	 * (3) "tentative" address on which DAD is being performed.
	 */
	/* (1) and (3) check. */
	if (ifp->if_carp)
		ifa = (*carp_iamatch6_p)(ifp, &taddr6);
	if (ifa == NULL)
		ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);

	/* (2) check. */
	if (ifa == NULL) {
		struct route_in6 ro;
		int need_proxy;

		bzero(&ro, sizeof(ro));
		ro.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
		ro.ro_dst.sin6_family = AF_INET6;
		ro.ro_dst.sin6_addr = taddr6;

		/* Always use the default FIB. */
#ifdef RADIX_MPATH
		rtalloc_mpath_fib((struct route *)&ro, RTF_ANNOUNCE,
		    RT_DEFAULT_FIB);
#else
		in6_rtalloc(&ro, RT_DEFAULT_FIB);
#endif
		need_proxy = (ro.ro_rt &&
		    (ro.ro_rt->rt_flags & RTF_ANNOUNCE) != 0 &&
		    ro.ro_rt->rt_gateway->sa_family == AF_LINK);
		if (ro.ro_rt != NULL) {
			if (need_proxy)
				proxydl = *SDL(ro.ro_rt->rt_gateway);
			RTFREE(ro.ro_rt);
		}
		if (need_proxy) {
			/*
			 * proxy NDP for single entry
			 */
			ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp,
				IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
			if (ifa)
				proxy = 1;
		}
	}
	if (ifa == NULL) {
		/*
		 * We've got an NS packet, and we don't have that adddress
		 * assigned for us.  We MUST silently ignore it.
		 * See RFC2461 7.2.3.
		 */
		goto freeit;
	}
	myaddr6 = *IFA_IN6(ifa);
	anycast = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST;
	tentative = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE;
	if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DUPLICATED)
		goto freeit;

	if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
		nd6log((LOG_INFO, "nd6_ns_input: lladdrlen mismatch for %s "
		    "(if %d, NS packet %d)\n",
		    ip6_sprintf(ip6bufs, &taddr6),
		    ifp->if_addrlen, lladdrlen - 2));
		goto bad;
	}

	if (IN6_ARE_ADDR_EQUAL(&myaddr6, &saddr6)) {
		nd6log((LOG_INFO, "nd6_ns_input: duplicate IP6 address %s\n",
		    ip6_sprintf(ip6bufs, &saddr6)));
		goto freeit;
	}

	/*
	 * We have neighbor solicitation packet, with target address equals to
	 * one of my tentative address.
	 *
	 * src addr	how to process?
	 * ---		---
	 * multicast	of course, invalid (rejected in ip6_input)
	 * unicast	somebody is doing address resolution -> ignore
	 * unspec	dup address detection
	 *
	 * The processing is defined in RFC 2462.
	 */
	if (tentative) {
		/*
		 * If source address is unspecified address, it is for
		 * duplicate address detection.
		 *
		 * If not, the packet is for addess resolution;
		 * silently ignore it.
		 */
		if (IN6_IS_ADDR_UNSPECIFIED(&saddr6))
			nd6_dad_ns_input(ifa);

		goto freeit;
	}

	/*
	 * If the source address is unspecified address, entries must not
	 * be created or updated.
	 * It looks that sender is performing DAD.  Output NA toward
	 * all-node multicast address, to tell the sender that I'm using
	 * the address.
	 * S bit ("solicited") must be zero.
	 */
	if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) {
		struct in6_addr in6_all;

		in6_all = in6addr_linklocal_allnodes;
		if (in6_setscope(&in6_all, ifp, NULL) != 0)
			goto bad;
		nd6_na_output_fib(ifp, &in6_all, &taddr6,
		    ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
		    rflag, tlladdr, proxy ? (struct sockaddr *)&proxydl : NULL,
		    M_GETFIB(m));
		goto freeit;
	}

	nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen,
	    ND_NEIGHBOR_SOLICIT, 0);

	nd6_na_output_fib(ifp, &saddr6, &taddr6,
	    ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
	    rflag | ND_NA_FLAG_SOLICITED, tlladdr,
	    proxy ? (struct sockaddr *)&proxydl : NULL, M_GETFIB(m));
 freeit:
	if (ifa != NULL)
		ifa_free(ifa);
	m_freem(m);
	return;

 bad:
	nd6log((LOG_ERR, "nd6_ns_input: src=%s\n",
		ip6_sprintf(ip6bufs, &saddr6)));
	nd6log((LOG_ERR, "nd6_ns_input: dst=%s\n",
		ip6_sprintf(ip6bufs, &daddr6)));
	nd6log((LOG_ERR, "nd6_ns_input: tgt=%s\n",
		ip6_sprintf(ip6bufs, &taddr6)));
	ICMP6STAT_INC(icp6s_badns);
	if (ifa != NULL)
		ifa_free(ifa);
	m_freem(m);
}
示例#4
0
/*
 * Type0 routing header processing
 *
 * RFC2292 backward compatibility warning: no support for strict/loose bitmap,
 * as it was dropped between RFC1883 and RFC2460.
 */
static int
ip6_rthdr0(struct mbuf *m, struct ip6_hdr *ip6, 
	struct ip6_rthdr0 *rh0)
{
	int addrs, index;
	struct in6_addr *nextaddr, tmpaddr;
	const struct ip6aux *ip6a;

	if (rh0->ip6r0_segleft == 0)
		return (0);

	if (rh0->ip6r0_len % 2
#ifdef COMPAT_RFC1883
	    || rh0->ip6r0_len > 46
#endif
		) {
		/*
		 * Type 0 routing header can't contain more than 23 addresses.
		 * RFC 2462: this limitation was removed since strict/loose
		 * bitmap field was deleted.
		 */
		IP6_STATINC(IP6_STAT_BADOPTIONS);
		icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
			    (char *)&rh0->ip6r0_len - (char *)ip6);
		return (-1);
	}

	if ((addrs = rh0->ip6r0_len / 2) < rh0->ip6r0_segleft) {
		IP6_STATINC(IP6_STAT_BADOPTIONS);
		icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
			    (char *)&rh0->ip6r0_segleft - (char *)ip6);
		return (-1);
	}

	index = addrs - rh0->ip6r0_segleft;
	rh0->ip6r0_segleft--;
	nextaddr = ((struct in6_addr *)(rh0 + 1)) + index;

	/*
	 * reject invalid addresses.  be proactive about malicious use of
	 * IPv4 mapped/compat address.
	 * XXX need more checks?
	 */
	if (IN6_IS_ADDR_MULTICAST(nextaddr) ||
	    IN6_IS_ADDR_UNSPECIFIED(nextaddr) ||
	    IN6_IS_ADDR_V4MAPPED(nextaddr) ||
	    IN6_IS_ADDR_V4COMPAT(nextaddr)) {
		p6stat[IP6_STAT_BADOPTIONS]++;
		goto bad;
	}
	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
	    IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst) ||
	    IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst) ||
	    IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) {
		IP6_STATINC(IP6_STAT_BADOPTIONS);
		goto bad;
	}

	/*
	 * Determine the scope zone of the next hop, based on the interface
	 * of the current hop. [RFC4007, Section 9]
	 * Then disambiguate the scope zone for the next hop (if necessary). 
	 */
	if ((ip6a = ip6_getdstifaddr(m)) == NULL)
		goto bad;
	if (in6_setzoneid(nextaddr, ip6a->ip6a_scope_id) != 0) {
		IP6_STATINC(IP6_STAT_BADSCOPE);
		goto bad;
	}

	/*
	 * Swap the IPv6 destination address and nextaddr. Forward the packet.
	 */
	tmpaddr = *nextaddr;
	*nextaddr = ip6->ip6_dst;
	in6_clearscope(nextaddr); /* XXX */
	ip6->ip6_dst = tmpaddr;

#ifdef COMPAT_RFC1883
	if (rh0->ip6r0_slmap[index / 8] & (1 << (7 - (index % 8))))
		ip6_forward(m, IPV6_SRCRT_NEIGHBOR);
	else
		ip6_forward(m, IPV6_SRCRT_NOTNEIGHBOR);
#else
	ip6_forward(m, 1);
#endif

	return (-1);			/* m would be freed in ip6_forward() */

  bad:
	m_freem(m);
	return (-1);
}
示例#5
0
void
ospf6_asbr_external_lsa_update (struct ospf6_route_req *request)
{
  char buffer [MAXLSASIZE];
  u_int16_t size;
  struct ospf6_lsa_as_external *external;
  char *p;
  struct ospf6_route_req route;
  char pbuf[BUFSIZ];

  /* assert this is best path; if not, return */
  ospf6_route_lookup (&route, &request->route.prefix, request->table);
  if (memcmp (&route.path, &request->path, sizeof (route.path)))
    return;

  if (IS_OSPF6_DUMP_LSA)
    zlog_info ("Update AS-External: ID: %lu",
               (u_long) ntohl (request->path.origin.id));

  /* prepare buffer */
  memset (buffer, 0, sizeof (buffer));
  size = sizeof (struct ospf6_lsa_as_external);
  external = (struct ospf6_lsa_as_external *) buffer;
  p = (char *) (external + 1);

  if (route.path.metric_type == 2)
    SET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E);   /* type2 */
  else
    UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E); /* type1 */

  /* forwarding address */
  if (! IN6_IS_ADDR_UNSPECIFIED (&route.nexthop.address))
    SET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F);
  else
    UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F);

  /* external route tag */
  UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T);

  /* set metric. note: related to E bit */
  OSPF6_ASBR_METRIC_SET (external, route.path.cost);

  /* prefixlen */
  external->prefix.prefix_length = route.route.prefix.prefixlen;

  /* PrefixOptions */
  external->prefix.prefix_options = route.path.prefix_options;

  /* don't use refer LS-type */
  external->prefix.prefix_refer_lstype = htons (0);

  if (IS_OSPF6_DUMP_LSA)
    {
      prefix2str (&route.route.prefix, pbuf, sizeof (pbuf));
      zlog_info ("  Prefix: %s", pbuf);
    }

  /* set Prefix */
  memcpy (p, &route.route.prefix.u.prefix6,
          OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen));
  ospf6_prefix_apply_mask (&external->prefix);
  size += OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen);
  p += OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen);

  /* Forwarding address */
  if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
    {
      memcpy (p, &route.nexthop.address, sizeof (struct in6_addr));
      size += sizeof (struct in6_addr);
      p += sizeof (struct in6_addr);
    }

  /* External Route Tag */
  if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T))
    {
      /* xxx */
    }

  ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_AS_EXTERNAL),
                       route.path.origin.id, ospf6->router_id,
                       (char *) external, size, ospf6);
  return;
}
示例#6
0
static bool inetAddressToSockaddr(JNIEnv* env, jobject inetAddress, int port, sockaddr_storage* ss, bool map) {
    memset(ss, 0, sizeof(*ss));

    if (inetAddress == NULL) {
        jniThrowNullPointerException(env, NULL);
        return false;
    }

    // Get the address family.
    static jfieldID familyFid = env->GetFieldID(JniConstants::inetAddressClass, "family", "I");
    ss->ss_family = env->GetIntField(inetAddress, familyFid);
    if (ss->ss_family == AF_UNSPEC) {
        return true; // Job done!
    }

    // Check this is an address family we support.
    if (ss->ss_family != AF_INET && ss->ss_family != AF_INET6) {
        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
                "inetAddressToSockaddr bad family: %i", ss->ss_family);
        return false;
    }

    // Get the byte array that stores the IP address bytes in the InetAddress.
    static jfieldID bytesFid = env->GetFieldID(JniConstants::inetAddressClass, "ipaddress", "[B");
    ScopedLocalRef<jbyteArray> addressBytes(env, reinterpret_cast<jbyteArray>(env->GetObjectField(inetAddress, bytesFid)));
    if (addressBytes.get() == NULL) {
        jniThrowNullPointerException(env, NULL);
        return false;
    }

    // We use AF_INET6 sockets, so we want an IPv6 address (which may be a IPv4-mapped address).
    sockaddr_in6* sin6 = reinterpret_cast<sockaddr_in6*>(ss);
    sin6->sin6_port = htons(port);
    if (ss->ss_family == AF_INET6) {
        // IPv6 address. Copy the bytes...
        jbyte* dst = reinterpret_cast<jbyte*>(&sin6->sin6_addr.s6_addr);
        env->GetByteArrayRegion(addressBytes.get(), 0, 16, dst);
        // ...and set the scope id...
        static jfieldID scopeFid = env->GetFieldID(JniConstants::inet6AddressClass, "scope_id", "I");
        sin6->sin6_scope_id = env->GetIntField(inetAddress, scopeFid);
        return true;
    }

    // Deal with Inet4Address instances.
    if (map) {
        // We should represent this Inet4Address as an IPv4-mapped IPv6 sockaddr_in6.
        // Change the family...
        sin6->sin6_family = AF_INET6;
        // Copy the bytes...
        jbyte* dst = reinterpret_cast<jbyte*>(&sin6->sin6_addr.s6_addr[12]);
        env->GetByteArrayRegion(addressBytes.get(), 0, 4, dst);
        // INADDR_ANY and in6addr_any are both all-zeros...
        if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
            // ...but all other IPv4-mapped addresses are ::ffff:a.b.c.d, so insert the ffff...
            memset(&(sin6->sin6_addr.s6_addr[10]), 0xff, 2);
        }
    } else {
        // We should represent this Inet4Address as an IPv4 sockaddr_in.
        sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(ss);
        sin->sin_port = htons(port);
        jbyte* dst = reinterpret_cast<jbyte*>(&sin->sin_addr.s_addr);
        env->GetByteArrayRegion(addressBytes.get(), 0, 4, dst);
    }
    return true;
}
static GPtrArray *
read_ip6_addresses (GKeyFile *file,
                    const char *setting_name,
                    const char *key)
{
	GPtrArray *addresses;
	struct in6_addr addr, gw;
	guint32 prefix;
	int i = 0;

	addresses = g_ptr_array_sized_new (3);

	/* Look for individual addresses */
	while (i++ < 1000) {
		char *tmp, *key_name, *str_prefix, *str_gw;
		int ret;
		GValueArray *values;
		GByteArray *address;
		GByteArray *gateway;
		GValue value = { 0 };

		key_name = g_strdup_printf ("%s%d", key, i);
		tmp = g_key_file_get_string (file, setting_name, key_name, NULL);
		g_free (key_name);

		if (!tmp)
			break; /* all done */

		/* convert the string array into IPv6 addresses */
		values = g_value_array_new (2); /* NMIP6Address has 2 items */

		/* Split the address and prefix */
		str_prefix = split_prefix (tmp);

		/* address */
		ret = inet_pton (AF_INET6, tmp, &addr);
		if (ret <= 0) {
			g_warning ("%s: ignoring invalid IPv6 %s element '%s'", __func__, key_name, tmp);
			g_value_array_free (values);
			goto next;
		}

		address = g_byte_array_new ();
		g_byte_array_append (address, (guint8 *) addr.s6_addr, 16);
		g_value_init (&value, DBUS_TYPE_G_UCHAR_ARRAY);
		g_value_take_boxed (&value, address);
		g_value_array_append (values, &value);
		g_value_unset (&value);

		/* prefix */
		prefix = 0;
		if (str_prefix) {
			if (!get_one_int (str_prefix, 128, key_name, &prefix)) {
				g_value_array_free (values);
				goto next;
			}
		} else {
			/* Missing prefix defaults to /64 */
			prefix = 64;
		}

		g_value_init (&value, G_TYPE_UINT);
		g_value_set_uint (&value, prefix);
		g_value_array_append (values, &value);
		g_value_unset (&value);

		/* Gateway (optional) */
		str_gw = split_gw (str_prefix);
		if (str_gw) {
			ret = inet_pton (AF_INET6, str_gw, &gw);
			if (ret <= 0) {
				g_warning ("%s: ignoring invalid IPv6 %s gateway '%s'", __func__, key_name, tmp);
				g_value_array_free (values);
				goto next;
			}

			if (!IN6_IS_ADDR_UNSPECIFIED (&gw)) {
				gateway = g_byte_array_new ();
				g_byte_array_append (gateway, (guint8 *) gw.s6_addr, 16);
				g_value_init (&value, DBUS_TYPE_G_UCHAR_ARRAY);
				g_value_take_boxed (&value, gateway);
				g_value_array_append (values, &value);
				g_value_unset (&value);
			}
		}

		g_ptr_array_add (addresses, values);

next:
		g_free (tmp);
	}

	if (addresses->len < 1) {
		g_ptr_array_free (addresses, TRUE);
		addresses = NULL;
	}

	return addresses;
}
示例#8
0
int
udp6_input(struct mbuf **mp, int *offp, int proto)
{
	struct mbuf *m = *mp;
	struct ifnet *ifp;
	struct ip6_hdr *ip6;
	struct udphdr *uh;
	struct inpcb *inp;
	struct inpcbinfo *pcbinfo;
	struct udpcb *up;
	int off = *offp;
	int cscov_partial;
	int plen, ulen;
	struct sockaddr_in6 fromsa;
	struct m_tag *fwd_tag;
	uint16_t uh_sum;
	uint8_t nxt;

	ifp = m->m_pkthdr.rcvif;
	ip6 = mtod(m, struct ip6_hdr *);

#ifndef PULLDOWN_TEST
	IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE);
	ip6 = mtod(m, struct ip6_hdr *);
	uh = (struct udphdr *)((caddr_t)ip6 + off);
#else
	IP6_EXTHDR_GET(uh, struct udphdr *, m, off, sizeof(*uh));
	if (!uh)
		return (IPPROTO_DONE);
#endif

	UDPSTAT_INC(udps_ipackets);

	/*
	 * Destination port of 0 is illegal, based on RFC768.
	 */
	if (uh->uh_dport == 0)
		goto badunlocked;

	plen = ntohs(ip6->ip6_plen) - off + sizeof(*ip6);
	ulen = ntohs((u_short)uh->uh_ulen);

	nxt = ip6->ip6_nxt;
	cscov_partial = (nxt == IPPROTO_UDPLITE) ? 1 : 0;
	if (nxt == IPPROTO_UDPLITE) {
		/* Zero means checksum over the complete packet. */
		if (ulen == 0)
			ulen = plen;
		if (ulen == plen)
			cscov_partial = 0;
		if ((ulen < sizeof(struct udphdr)) || (ulen > plen)) {
			/* XXX: What is the right UDPLite MIB counter? */
			goto badunlocked;
		}
		if (uh->uh_sum == 0) {
			/* XXX: What is the right UDPLite MIB counter? */
			goto badunlocked;
		}
	} else {
		if ((ulen < sizeof(struct udphdr)) || (plen != ulen)) {
			UDPSTAT_INC(udps_badlen);
			goto badunlocked;
		}
		if (uh->uh_sum == 0) {
			UDPSTAT_INC(udps_nosum);
			goto badunlocked;
		}
	}

	if ((m->m_pkthdr.csum_flags & CSUM_DATA_VALID_IPV6) &&
	    !cscov_partial) {
		if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
			uh_sum = m->m_pkthdr.csum_data;
		else
			uh_sum = in6_cksum_pseudo(ip6, ulen, nxt,
			    m->m_pkthdr.csum_data);
		uh_sum ^= 0xffff;
	} else
		uh_sum = in6_cksum_partial(m, nxt, off, plen, ulen);

	if (uh_sum != 0) {
		UDPSTAT_INC(udps_badsum);
		goto badunlocked;
	}

	/*
	 * Construct sockaddr format source address.
	 */
	init_sin6(&fromsa, m);
	fromsa.sin6_port = uh->uh_sport;

	pcbinfo = udp_get_inpcbinfo(nxt);
	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
		struct inpcb *last;
		struct inpcbhead *pcblist;
		struct ip6_moptions *imo;

		INP_INFO_RLOCK(pcbinfo);
		/*
		 * In the event that laddr should be set to the link-local
		 * address (this happens in RIPng), the multicast address
		 * specified in the received packet will not match laddr.  To
		 * handle this situation, matching is relaxed if the
		 * receiving interface is the same as one specified in the
		 * socket and if the destination multicast address matches
		 * one of the multicast groups specified in the socket.
		 */

		/*
		 * KAME note: traditionally we dropped udpiphdr from mbuf
		 * here.  We need udphdr for IPsec processing so we do that
		 * later.
		 */
		pcblist = udp_get_pcblist(nxt);
		last = NULL;
		LIST_FOREACH(inp, pcblist, inp_list) {
			if ((inp->inp_vflag & INP_IPV6) == 0)
				continue;
			if (inp->inp_lport != uh->uh_dport)
				continue;
			if (inp->inp_fport != 0 &&
			    inp->inp_fport != uh->uh_sport)
				continue;
			if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) {
				if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr,
							&ip6->ip6_dst))
					continue;
			}
			if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
				if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr,
							&ip6->ip6_src) ||
				    inp->inp_fport != uh->uh_sport)
					continue;
			}

			/*
			 * XXXRW: Because we weren't holding either the inpcb
			 * or the hash lock when we checked for a match 
			 * before, we should probably recheck now that the 
			 * inpcb lock is (supposed to be) held.
			 */

			/*
			 * Handle socket delivery policy for any-source
			 * and source-specific multicast. [RFC3678]
			 */
			imo = inp->in6p_moptions;
			if (imo && IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
				struct sockaddr_in6	 mcaddr;
				int			 blocked;

				INP_RLOCK(inp);

				bzero(&mcaddr, sizeof(struct sockaddr_in6));
				mcaddr.sin6_len = sizeof(struct sockaddr_in6);
				mcaddr.sin6_family = AF_INET6;
				mcaddr.sin6_addr = ip6->ip6_dst;

				blocked = im6o_mc_filter(imo, ifp,
					(struct sockaddr *)&mcaddr,
					(struct sockaddr *)&fromsa);
				if (blocked != MCAST_PASS) {
					if (blocked == MCAST_NOTGMEMBER)
						IP6STAT_INC(ip6s_notmember);
					if (blocked == MCAST_NOTSMEMBER ||
					    blocked == MCAST_MUTED)
						UDPSTAT_INC(udps_filtermcast);
					INP_RUNLOCK(inp); /* XXX */
					continue;
				}

				INP_RUNLOCK(inp);
			}
			if (last != NULL) {
				struct mbuf *n;

				if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
					INP_RLOCK(last);
					UDP_PROBE(receive, NULL, last, ip6,
					    last, uh);
					if (udp6_append(last, n, off, &fromsa))
						goto inp_lost;
					INP_RUNLOCK(last);
				}
			}
			last = inp;
			/*
			 * Don't look for additional matches if this one does
			 * not have either the SO_REUSEPORT or SO_REUSEADDR
			 * socket options set.  This heuristic avoids
			 * searching through all pcbs in the common case of a
			 * non-shared port.  It assumes that an application
			 * will never clear these options after setting them.
			 */
			if ((last->inp_socket->so_options &
			     (SO_REUSEPORT|SO_REUSEADDR)) == 0)
				break;
		}

		if (last == NULL) {
			/*
			 * No matching pcb found; discard datagram.  (No need
			 * to send an ICMP Port Unreachable for a broadcast
			 * or multicast datgram.)
			 */
			UDPSTAT_INC(udps_noport);
			UDPSTAT_INC(udps_noportmcast);
			goto badheadlocked;
		}
		INP_RLOCK(last);
		INP_INFO_RUNLOCK(pcbinfo);
		UDP_PROBE(receive, NULL, last, ip6, last, uh);
		if (udp6_append(last, m, off, &fromsa) == 0) 
			INP_RUNLOCK(last);
	inp_lost:
		return (IPPROTO_DONE);
	}
	/*
	 * Locate pcb for datagram.
	 */

	/*
	 * Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain.
	 */
	if ((m->m_flags & M_IP6_NEXTHOP) &&
	    (fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL) {
		struct sockaddr_in6 *next_hop6;

		next_hop6 = (struct sockaddr_in6 *)(fwd_tag + 1);

		/*
		 * Transparently forwarded. Pretend to be the destination.
		 * Already got one like this?
		 */
		inp = in6_pcblookup_mbuf(pcbinfo, &ip6->ip6_src,
		    uh->uh_sport, &ip6->ip6_dst, uh->uh_dport,
		    INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif, m);
		if (!inp) {
			/*
			 * It's new.  Try to find the ambushing socket.
			 * Because we've rewritten the destination address,
			 * any hardware-generated hash is ignored.
			 */
			inp = in6_pcblookup(pcbinfo, &ip6->ip6_src,
			    uh->uh_sport, &next_hop6->sin6_addr,
			    next_hop6->sin6_port ? htons(next_hop6->sin6_port) :
			    uh->uh_dport, INPLOOKUP_WILDCARD |
			    INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif);
		}
		/* Remove the tag from the packet. We don't need it anymore. */
		m_tag_delete(m, fwd_tag);
		m->m_flags &= ~M_IP6_NEXTHOP;
	} else
		inp = in6_pcblookup_mbuf(pcbinfo, &ip6->ip6_src,
		    uh->uh_sport, &ip6->ip6_dst, uh->uh_dport,
		    INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB,
		    m->m_pkthdr.rcvif, m);
	if (inp == NULL) {
		if (udp_log_in_vain) {
			char ip6bufs[INET6_ADDRSTRLEN];
			char ip6bufd[INET6_ADDRSTRLEN];

			log(LOG_INFO,
			    "Connection attempt to UDP [%s]:%d from [%s]:%d\n",
			    ip6_sprintf(ip6bufd, &ip6->ip6_dst),
			    ntohs(uh->uh_dport),
			    ip6_sprintf(ip6bufs, &ip6->ip6_src),
			    ntohs(uh->uh_sport));
		}
		UDPSTAT_INC(udps_noport);
		if (m->m_flags & M_MCAST) {
			printf("UDP6: M_MCAST is set in a unicast packet.\n");
			UDPSTAT_INC(udps_noportmcast);
			goto badunlocked;
		}
		if (V_udp_blackhole)
			goto badunlocked;
		if (badport_bandlim(BANDLIM_ICMP6_UNREACH) < 0)
			goto badunlocked;
		icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
		return (IPPROTO_DONE);
	}
	INP_RLOCK_ASSERT(inp);
	up = intoudpcb(inp);
	if (cscov_partial) {
		if (up->u_rxcslen == 0 || up->u_rxcslen > ulen) {
			INP_RUNLOCK(inp);
			m_freem(m);
			return (IPPROTO_DONE);
		}
	}
	UDP_PROBE(receive, NULL, inp, ip6, inp, uh);
	if (udp6_append(inp, m, off, &fromsa) == 0)
		INP_RUNLOCK(inp);
	return (IPPROTO_DONE);

badheadlocked:
	INP_INFO_RUNLOCK(pcbinfo);
badunlocked:
	if (m)
		m_freem(m);
	return (IPPROTO_DONE);
}
示例#9
0
static int
udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
    struct mbuf *control, struct thread *td)
{
	u_int32_t ulen = m->m_pkthdr.len;
	u_int32_t plen = sizeof(struct udphdr) + ulen;
	struct ip6_hdr *ip6;
	struct udphdr *udp6;
	struct in6_addr *laddr, *faddr, in6a;
	struct sockaddr_in6 *sin6 = NULL;
	struct ifnet *oifp = NULL;
	int cscov_partial = 0;
	int scope_ambiguous = 0;
	u_short fport;
	int error = 0;
	uint8_t nxt;
	uint16_t cscov = 0;
	struct ip6_pktopts *optp, opt;
	int af = AF_INET6, hlen = sizeof(struct ip6_hdr);
	int flags;
	struct sockaddr_in6 tmp;

	INP_WLOCK_ASSERT(inp);
	INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo);

	if (addr6) {
		/* addr6 has been validated in udp6_send(). */
		sin6 = (struct sockaddr_in6 *)addr6;

		/* protect *sin6 from overwrites */
		tmp = *sin6;
		sin6 = &tmp;

		/*
		 * Application should provide a proper zone ID or the use of
		 * default zone IDs should be enabled.  Unfortunately, some
		 * applications do not behave as it should, so we need a
		 * workaround.  Even if an appropriate ID is not determined,
		 * we'll see if we can determine the outgoing interface.  If we
		 * can, determine the zone ID based on the interface below.
		 */
		if (sin6->sin6_scope_id == 0 && !V_ip6_use_defzone)
			scope_ambiguous = 1;
		if ((error = sa6_embedscope(sin6, V_ip6_use_defzone)) != 0)
			return (error);
	}

	if (control) {
		if ((error = ip6_setpktopts(control, &opt,
		    inp->in6p_outputopts, td->td_ucred, IPPROTO_UDP)) != 0)
			goto release;
		optp = &opt;
	} else
		optp = inp->in6p_outputopts;

	if (sin6) {
		faddr = &sin6->sin6_addr;

		/*
		 * Since we saw no essential reason for calling in_pcbconnect,
		 * we get rid of such kind of logic, and call in6_selectsrc
		 * and in6_pcbsetport in order to fill in the local address
		 * and the local port.
		 */
		if (sin6->sin6_port == 0) {
			error = EADDRNOTAVAIL;
			goto release;
		}

		if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
			/* how about ::ffff:0.0.0.0 case? */
			error = EISCONN;
			goto release;
		}

		fport = sin6->sin6_port; /* allow 0 port */

		if (IN6_IS_ADDR_V4MAPPED(faddr)) {
			if ((inp->inp_flags & IN6P_IPV6_V6ONLY)) {
				/*
				 * I believe we should explicitly discard the
				 * packet when mapped addresses are disabled,
				 * rather than send the packet as an IPv6 one.
				 * If we chose the latter approach, the packet
				 * might be sent out on the wire based on the
				 * default route, the situation which we'd
				 * probably want to avoid.
				 * (20010421 [email protected])
				 */
				error = EINVAL;
				goto release;
			}
			if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) &&
			    !IN6_IS_ADDR_V4MAPPED(&inp->in6p_laddr)) {
				/*
				 * when remote addr is an IPv4-mapped address,
				 * local addr should not be an IPv6 address,
				 * since you cannot determine how to map IPv6
				 * source address to IPv4.
				 */
				error = EINVAL;
				goto release;
			}

			af = AF_INET;
		}

		if (!IN6_IS_ADDR_V4MAPPED(faddr)) {
			error = in6_selectsrc(sin6, optp, inp, NULL,
			    td->td_ucred, &oifp, &in6a);
			if (error)
				goto release;
			if (oifp && scope_ambiguous &&
			    (error = in6_setscope(&sin6->sin6_addr,
			    oifp, NULL))) {
				goto release;
			}
			laddr = &in6a;
		} else
			laddr = &inp->in6p_laddr;	/* XXX */
		if (laddr == NULL) {
			if (error == 0)
				error = EADDRNOTAVAIL;
			goto release;
		}
		if (inp->inp_lport == 0 &&
		    (error = in6_pcbsetport(laddr, inp, td->td_ucred)) != 0) {
			/* Undo an address bind that may have occurred. */
			inp->in6p_laddr = in6addr_any;
			goto release;
		}
	} else {
		if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
			error = ENOTCONN;
			goto release;
		}
		if (IN6_IS_ADDR_V4MAPPED(&inp->in6p_faddr)) {
			if ((inp->inp_flags & IN6P_IPV6_V6ONLY)) {
				/*
				 * XXX: this case would happen when the
				 * application sets the V6ONLY flag after
				 * connecting the foreign address.
				 * Such applications should be fixed,
				 * so we bark here.
				 */
				log(LOG_INFO, "udp6_output: IPV6_V6ONLY "
				    "option was set for a connected socket\n");
				error = EINVAL;
				goto release;
			} else
				af = AF_INET;
		}
		laddr = &inp->in6p_laddr;
		faddr = &inp->in6p_faddr;
		fport = inp->inp_fport;
	}

	if (af == AF_INET)
		hlen = sizeof(struct ip);

	/*
	 * Calculate data length and get a mbuf
	 * for UDP and IP6 headers.
	 */
	M_PREPEND(m, hlen + sizeof(struct udphdr), M_NOWAIT);
	if (m == 0) {
		error = ENOBUFS;
		goto release;
	}

	/*
	 * Stuff checksum and output datagram.
	 */
	nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ?
	    IPPROTO_UDP : IPPROTO_UDPLITE;
	udp6 = (struct udphdr *)(mtod(m, caddr_t) + hlen);
	udp6->uh_sport = inp->inp_lport; /* lport is always set in the PCB */
	udp6->uh_dport = fport;
	if (nxt == IPPROTO_UDPLITE) {
		struct udpcb *up;

		up = intoudpcb(inp);
		cscov = up->u_txcslen;
		if (cscov >= plen)
			cscov = 0;
		udp6->uh_ulen = htons(cscov);
		/*
		 * For UDP-Lite, checksum coverage length of zero means
		 * the entire UDPLite packet is covered by the checksum.
		 */
		cscov_partial = (cscov == 0) ? 0 : 1;
	} else if (plen <= 0xffff)
		udp6->uh_ulen = htons((u_short)plen);
	else
		udp6->uh_ulen = 0;
	udp6->uh_sum = 0;

	switch (af) {
	case AF_INET6:
		ip6 = mtod(m, struct ip6_hdr *);
		ip6->ip6_flow	= inp->inp_flow & IPV6_FLOWINFO_MASK;
		ip6->ip6_vfc	&= ~IPV6_VERSION_MASK;
		ip6->ip6_vfc	|= IPV6_VERSION;
		ip6->ip6_plen	= htons((u_short)plen);
		ip6->ip6_nxt	= nxt;
		ip6->ip6_hlim	= in6_selecthlim(inp, NULL);
		ip6->ip6_src	= *laddr;
		ip6->ip6_dst	= *faddr;

		if (cscov_partial) {
			if ((udp6->uh_sum = in6_cksum_partial(m, nxt,
			    sizeof(struct ip6_hdr), plen, cscov)) == 0)
				udp6->uh_sum = 0xffff;
		} else {
			udp6->uh_sum = in6_cksum_pseudo(ip6, plen, nxt, 0);
			m->m_pkthdr.csum_flags = CSUM_UDP_IPV6;
			m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
		}

#ifdef	RSS
		{
			uint32_t hash_val, hash_type;
			uint8_t pr;

			pr = inp->inp_socket->so_proto->pr_protocol;
			/*
			 * Calculate an appropriate RSS hash for UDP and
			 * UDP Lite.
			 *
			 * The called function will take care of figuring out
			 * whether a 2-tuple or 4-tuple hash is required based
			 * on the currently configured scheme.
			 *
			 * Later later on connected socket values should be
			 * cached in the inpcb and reused, rather than constantly
			 * re-calculating it.
			 *
			 * UDP Lite is a different protocol number and will
			 * likely end up being hashed as a 2-tuple until
			 * RSS / NICs grow UDP Lite protocol awareness.
			 */
			if (rss_proto_software_hash_v6(faddr, laddr, fport,
			    inp->inp_lport, pr, &hash_val, &hash_type) == 0) {
				m->m_pkthdr.flowid = hash_val;
				M_HASHTYPE_SET(m, hash_type);
			}
		}
#endif
		flags = 0;
#ifdef	RSS
		/*
		 * Don't override with the inp cached flowid.
		 *
		 * Until the whole UDP path is vetted, it may actually
		 * be incorrect.
		 */
		flags |= IP_NODEFAULTFLOWID;
#endif

		UDP_PROBE(send, NULL, inp, ip6, inp, udp6);
		UDPSTAT_INC(udps_opackets);
		error = ip6_output(m, optp, NULL, flags, inp->in6p_moptions,
		    NULL, inp);
		break;
	case AF_INET:
		error = EAFNOSUPPORT;
		goto release;
	}
	goto releaseopt;

release:
	m_freem(m);

releaseopt:
	if (control) {
		ip6_clearpktopts(&opt, -1);
		m_freem(control);
	}
	return (error);
}
示例#10
0
文件: radius.c 项目: JabirTech/Source
/*
 * rad_continue_send_request() has given us `got' (non-zero).  Deal with it.
 */
static void
radius_Process(struct radius *r, int got)
{
  char *argv[MAXARGS], *nuke;
  struct bundle *bundle;
  int argc, addrs, res, width;
  size_t len;
  struct ncprange dest;
  struct ncpaddr gw;
  const void *data;
  const char *stype;
  u_int32_t ipaddr, vendor;
  struct in_addr ip;
#ifndef NOINET6
  uint8_t ipv6addr[INET6_ADDRSTRLEN];
  struct in6_addr ip6;
#endif

  r->cx.fd = -1;		/* Stop select()ing */
  stype = r->cx.auth ? "auth" : "acct";

  switch (got) {
    case RAD_ACCESS_ACCEPT:
      log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		 "Radius(%s): ACCEPT received\n", stype);
      if (!r->cx.auth) {
        rad_close(r->cx.rad);
        return;
      }
      break;

    case RAD_ACCESS_REJECT:
      log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		 "Radius(%s): REJECT received\n", stype);
      if (!r->cx.auth) {
        rad_close(r->cx.rad);
        return;
      }
      break;

    case RAD_ACCESS_CHALLENGE:
      /* we can't deal with this (for now) ! */
      log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		 "Radius: CHALLENGE received (can't handle yet)\n");
      if (r->cx.auth)
        auth_Failure(r->cx.auth);
      rad_close(r->cx.rad);
      return;

    case RAD_ACCOUNTING_RESPONSE:
      /*
       * It's probably not ideal to log this at PHASE level as we'll see
       * too much stuff going to the log when ``set rad_alive'' is used.
       * So we differ from older behaviour (ppp version 3.1 and before)
       * and just log accounting responses to LogRADIUS.
       */
      log_Printf(LogRADIUS, "Radius(%s): Accounting response received\n",
		 stype);
      if (r->cx.auth)
        auth_Failure(r->cx.auth);		/* unexpected !!! */

      /* No further processing for accounting requests, please */
      rad_close(r->cx.rad);
      return;

    case -1:
      log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		 "radius(%s): %s\n", stype, rad_strerror(r->cx.rad));
      if (r->cx.auth)
        auth_Failure(r->cx.auth);
      rad_close(r->cx.rad);
      return;

    default:
      log_Printf(LogERROR, "rad_send_request(%s): Failed %d: %s\n", stype,
                 got, rad_strerror(r->cx.rad));
      if (r->cx.auth)
        auth_Failure(r->cx.auth);
      rad_close(r->cx.rad);
      return;
  }

  /* Let's see what we've got in our reply */
  r->ip.s_addr = r->mask.s_addr = INADDR_NONE;
  r->mtu = 0;
  r->vj = 0;
  while ((res = rad_get_attr(r->cx.rad, &data, &len)) > 0) {
    switch (res) {
      case RAD_FRAMED_IP_ADDRESS:
        r->ip = rad_cvt_addr(data);
	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " IP %s\n", inet_ntoa(r->ip));
        break;

      case RAD_FILTER_ID:
        free(r->filterid);
        if ((r->filterid = rad_cvt_string(data, len)) == NULL) {
          log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
          auth_Failure(r->cx.auth);
          rad_close(r->cx.rad);
          return;
        }
	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " Filter \"%s\"\n", r->filterid);
        break;

      case RAD_SESSION_TIMEOUT:
        r->sessiontime = rad_cvt_int(data);
	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " Session-Timeout %lu\n", r->sessiontime);
        break;

      case RAD_FRAMED_IP_NETMASK:
        r->mask = rad_cvt_addr(data);
	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " Netmask %s\n", inet_ntoa(r->mask));
        break;

      case RAD_FRAMED_MTU:
        r->mtu = rad_cvt_int(data);
	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " MTU %lu\n", r->mtu);
        break;

      case RAD_FRAMED_ROUTING:
        /* Disabled for now - should we automatically set up some filters ? */
        /* rad_cvt_int(data); */
        /* bit 1 = Send routing packets */
        /* bit 2 = Receive routing packets */
        break;

      case RAD_FRAMED_COMPRESSION:
        r->vj = rad_cvt_int(data) == 1 ? 1 : 0;
	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " VJ %sabled\n", r->vj ? "en" : "dis");
        break;

      case RAD_FRAMED_ROUTE:
        /*
         * We expect a string of the format ``dest[/bits] gw [metrics]''
         * Any specified metrics are ignored.  MYADDR and HISADDR are
         * understood for ``dest'' and ``gw'' and ``0.0.0.0'' is the same
         * as ``HISADDR''.
         */

        if ((nuke = rad_cvt_string(data, len)) == NULL) {
          log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
          auth_Failure(r->cx.auth);
          rad_close(r->cx.rad);
          return;
        }

	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " Route: %s\n", nuke);
        bundle = r->cx.auth->physical->dl->bundle;
        ip.s_addr = INADDR_ANY;
        ncpaddr_setip4(&gw, ip);
        ncprange_setip4host(&dest, ip);
        argc = command_Interpret(nuke, strlen(nuke), argv);
        if (argc < 0)
          log_Printf(LogWARN, "radius: %s: Syntax error\n",
                     argc == 1 ? argv[0] : "\"\"");
        else if (argc < 2)
          log_Printf(LogWARN, "radius: %s: Invalid route\n",
                     argc == 1 ? argv[0] : "\"\"");
        else if ((strcasecmp(argv[0], "default") != 0 &&
                  !ncprange_aton(&dest, &bundle->ncp, argv[0])) ||
                 !ncpaddr_aton(&gw, &bundle->ncp, argv[1]))
          log_Printf(LogWARN, "radius: %s %s: Invalid route\n",
                     argv[0], argv[1]);
        else {
          ncprange_getwidth(&dest, &width);
          if (width == 32 && strchr(argv[0], '/') == NULL) {
            /* No mask specified - use the natural mask */
            ncprange_getip4addr(&dest, &ip);
            ncprange_setip4mask(&dest, addr2mask(ip));
          }
          addrs = 0;

          if (!strncasecmp(argv[0], "HISADDR", 7))
            addrs = ROUTE_DSTHISADDR;
          else if (!strncasecmp(argv[0], "MYADDR", 6))
            addrs = ROUTE_DSTMYADDR;

          if (ncpaddr_getip4addr(&gw, &ipaddr) && ipaddr == INADDR_ANY) {
            addrs |= ROUTE_GWHISADDR;
            ncpaddr_setip4(&gw, bundle->ncp.ipcp.peer_ip);
          } else if (strcasecmp(argv[1], "HISADDR") == 0)
            addrs |= ROUTE_GWHISADDR;

          route_Add(&r->routes, addrs, &dest, &gw);
        }
        free(nuke);
        break;

      case RAD_REPLY_MESSAGE:
        free(r->repstr);
        if ((r->repstr = rad_cvt_string(data, len)) == NULL) {
          log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
          auth_Failure(r->cx.auth);
          rad_close(r->cx.rad);
          return;
        }
	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " Reply-Message \"%s\"\n", r->repstr);
        break;

#ifndef NOINET6
      case RAD_FRAMED_IPV6_PREFIX:
	free(r->ipv6prefix);
	if ((r->ipv6prefix = rad_cvt_ipv6prefix(data, len)) == NULL) {
	  log_Printf(LogERROR, "rad_cvt_ipv6prefix: %s\n",
		     "Malformed attribute in response");
	  auth_Failure(r->cx.auth);
	  rad_close(r->cx.rad);
	  return;
	}
	inet_ntop(AF_INET6, &r->ipv6prefix[2], ipv6addr, sizeof(ipv6addr));
	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " IPv6 %s/%d\n", ipv6addr, r->ipv6prefix[1]);
        break;

      case RAD_FRAMED_IPV6_ROUTE:
        /*
         * We expect a string of the format ``dest[/bits] gw [metrics]''
         * Any specified metrics are ignored.  MYADDR6 and HISADDR6 are
         * understood for ``dest'' and ``gw'' and ``::'' is the same
         * as ``HISADDR6''.
         */

        if ((nuke = rad_cvt_string(data, len)) == NULL) {
          log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
          auth_Failure(r->cx.auth);
          rad_close(r->cx.rad);
          return;
        }

	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " IPv6 Route: %s\n", nuke);
        bundle = r->cx.auth->physical->dl->bundle;
	ncpaddr_setip6(&gw, &in6addr_any);
	ncprange_set(&dest, &gw, 0);
        argc = command_Interpret(nuke, strlen(nuke), argv);
        if (argc < 0)
          log_Printf(LogWARN, "radius: %s: Syntax error\n",
                     argc == 1 ? argv[0] : "\"\"");
        else if (argc < 2)
          log_Printf(LogWARN, "radius: %s: Invalid route\n",
                     argc == 1 ? argv[0] : "\"\"");
        else if ((strcasecmp(argv[0], "default") != 0 &&
                  !ncprange_aton(&dest, &bundle->ncp, argv[0])) ||
                 !ncpaddr_aton(&gw, &bundle->ncp, argv[1]))
          log_Printf(LogWARN, "radius: %s %s: Invalid route\n",
                     argv[0], argv[1]);
        else {
          addrs = 0;

          if (!strncasecmp(argv[0], "HISADDR6", 8))
            addrs = ROUTE_DSTHISADDR6;
          else if (!strncasecmp(argv[0], "MYADDR6", 7))
            addrs = ROUTE_DSTMYADDR6;

          if (ncpaddr_getip6(&gw, &ip6) && IN6_IS_ADDR_UNSPECIFIED(&ip6)) {
            addrs |= ROUTE_GWHISADDR6;
            ncpaddr_copy(&gw, &bundle->ncp.ipv6cp.hisaddr);
          } else if (strcasecmp(argv[1], "HISADDR6") == 0)
            addrs |= ROUTE_GWHISADDR6;

          route_Add(&r->ipv6routes, addrs, &dest, &gw);
        }
        free(nuke);
        break;
#endif

      case RAD_VENDOR_SPECIFIC:
        if ((res = rad_get_vendor_attr(&vendor, &data, &len)) <= 0) {
          log_Printf(LogERROR, "rad_get_vendor_attr: %s (failing!)\n",
                     rad_strerror(r->cx.rad));
          auth_Failure(r->cx.auth);
          rad_close(r->cx.rad);
          return;
        }

	switch (vendor) {
          case RAD_VENDOR_MICROSOFT:
            switch (res) {
#ifndef NODES
              case RAD_MICROSOFT_MS_CHAP_ERROR:
                free(r->errstr);
                if (len == 0)
                  r->errstr = NULL;
                else {
                  if (len < 3 || ((const char *)data)[1] != '=') {
                    /*
                     * Only point at the String field if we don't think the
                     * peer has misformatted the response.
                     */
                    data = (const char *)data + 1;
                    len--;
                  } else
                    log_Printf(LogWARN, "Warning: The MS-CHAP-Error "
                               "attribute is mis-formatted.  Compensating\n");
                  if ((r->errstr = rad_cvt_string((const char *)data,
                                                  len)) == NULL) {
                    log_Printf(LogERROR, "rad_cvt_string: %s\n",
                               rad_strerror(r->cx.rad));
                    auth_Failure(r->cx.auth);
                    rad_close(r->cx.rad);
                    return;
                  }
		  log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
			     " MS-CHAP-Error \"%s\"\n", r->errstr);
                }
                break;

              case RAD_MICROSOFT_MS_CHAP2_SUCCESS:
                free(r->msrepstr);
                if (len == 0)
                  r->msrepstr = NULL;
                else {
                  if (len < 3 || ((const char *)data)[1] != '=') {
                    /*
                     * Only point at the String field if we don't think the
                     * peer has misformatted the response.
                     */
                    data = (const char *)data + 1;
                    len--;
                  } else
                    log_Printf(LogWARN, "Warning: The MS-CHAP2-Success "
                               "attribute is mis-formatted.  Compensating\n");
                  if ((r->msrepstr = rad_cvt_string((const char *)data,
                                                    len)) == NULL) {
                    log_Printf(LogERROR, "rad_cvt_string: %s\n",
                               rad_strerror(r->cx.rad));
                    auth_Failure(r->cx.auth);
                    rad_close(r->cx.rad);
                    return;
                  }
		  log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
			     " MS-CHAP2-Success \"%s\"\n", r->msrepstr);
                }
                break;

              case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY:
                r->mppe.policy = rad_cvt_int(data);
		log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
			   " MS-MPPE-Encryption-Policy %s\n",
                           radius_policyname(r->mppe.policy));
                break;

              case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES:
                r->mppe.types = rad_cvt_int(data);
		log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
			   " MS-MPPE-Encryption-Types %s\n",
                           radius_typesname(r->mppe.types));
                break;

              case RAD_MICROSOFT_MS_MPPE_RECV_KEY:
                free(r->mppe.recvkey);
		demangle(r, data, len, &r->mppe.recvkey, &r->mppe.recvkeylen);
		log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
			   " MS-MPPE-Recv-Key ********\n");
                break;

              case RAD_MICROSOFT_MS_MPPE_SEND_KEY:
		demangle(r, data, len, &r->mppe.sendkey, &r->mppe.sendkeylen);
		log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
			   " MS-MPPE-Send-Key ********\n");
                break;
#endif

              default:
                log_Printf(LogDEBUG, "Dropping MICROSOFT vendor specific "
                           "RADIUS attribute %d\n", res);
                break;
            }
            break;

          default:
            log_Printf(LogDEBUG, "Dropping vendor %lu RADIUS attribute %d\n",
                       (unsigned long)vendor, res);
            break;
        }
        break;

      default:
        log_Printf(LogDEBUG, "Dropping RADIUS attribute %d\n", res);
        break;
    }
  }

  if (res == -1) {
    log_Printf(LogERROR, "rad_get_attr: %s (failing!)\n",
               rad_strerror(r->cx.rad));
    auth_Failure(r->cx.auth);
  } else if (got == RAD_ACCESS_REJECT)
    auth_Failure(r->cx.auth);
  else {
    r->valid = 1;
    auth_Success(r->cx.auth);
  }
  rad_close(r->cx.rad);
}
示例#11
0
static int
udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
{
	struct inpcb *inp;
	struct inpcbinfo *pcbinfo;
	struct sockaddr_in6 *sin6;
	int error;

	pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol);
	inp = sotoinpcb(so);
	sin6 = (struct sockaddr_in6 *)nam;
	KASSERT(inp != NULL, ("udp6_connect: inp == NULL"));

	/*
	 * XXXRW: Need to clarify locking of v4/v6 flags.
	 */
	INP_WLOCK(inp);
#ifdef INET
	if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
		struct sockaddr_in sin;

		if ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0) {
			error = EINVAL;
			goto out;
		}
		if (inp->inp_faddr.s_addr != INADDR_ANY) {
			error = EISCONN;
			goto out;
		}
		in6_sin6_2_sin(&sin, sin6);
		inp->inp_vflag |= INP_IPV4;
		inp->inp_vflag &= ~INP_IPV6;
		error = prison_remote_ip4(td->td_ucred, &sin.sin_addr);
		if (error != 0)
			goto out;
		INP_HASH_WLOCK(pcbinfo);
		error = in_pcbconnect(inp, (struct sockaddr *)&sin,
		    td->td_ucred);
		INP_HASH_WUNLOCK(pcbinfo);
		if (error == 0)
			soisconnected(so);
		goto out;
	}
#endif
	if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
		error = EISCONN;
		goto out;
	}
	inp->inp_vflag &= ~INP_IPV4;
	inp->inp_vflag |= INP_IPV6;
	error = prison_remote_ip6(td->td_ucred, &sin6->sin6_addr);
	if (error != 0)
		goto out;
	INP_HASH_WLOCK(pcbinfo);
	error = in6_pcbconnect(inp, nam, td->td_ucred);
	INP_HASH_WUNLOCK(pcbinfo);
	if (error == 0)
		soisconnected(so);
out:
	INP_WUNLOCK(inp);
	return (error);
}
示例#12
0
static void
outputpcb(int proto, const char *name, struct inpcb *inp, struct xsocket *so, struct tcpcb *tp)
{
	const char *vchar;
	static struct clockinfo clockinfo;

	if (clockinfo.hz == 0) {
		size_t size = sizeof(clockinfo);
		sysctlbyname("kern.clockrate", &clockinfo, &size, NULL, 0);
		if (clockinfo.hz == 0)
			clockinfo.hz = 100;
	}

	/* Ignore sockets for protocols other than the desired one. */
	if (so->xso_protocol != (int)proto)
		return;

	if ((af == AF_INET && (inp->inp_vflag & INP_IPV4) == 0)
#ifdef INET6
	    || (af == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0)
#endif /* INET6 */
	    || (af == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0
#ifdef INET6
		&& (inp->inp_vflag & INP_IPV6) == 0
#endif /* INET6 */
		))
	    ) {
		return;
	}
	if (!aflag && ( 
		(proto == IPPROTO_TCP && tp->t_state == TCPS_LISTEN) ||
		(af == AF_INET && inet_lnaof(inp->inp_laddr) == INADDR_ANY)
#ifdef INET6
	    || (af == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
#endif /* INET6 */
	    || (af == AF_UNSPEC && (((inp->inp_vflag & INP_IPV4) != 0 &&
		inet_lnaof(inp->inp_laddr) == INADDR_ANY)
#ifdef INET6
	    || ((inp->inp_vflag & INP_IPV6) != 0 &&
		IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
#endif
		  ))
	     )) {
		return;
	}

	if (ppr_first) {
		if (!Lflag) {
			printf("Active Internet connections");
			if (aflag)
				printf(" (including servers)");
		} else {
			printf("Current listen queue sizes "
				"(qlen/incqlen/maxqlen)");
		}
		putchar('\n');
		if (Aflag)
			printf("%-8.8s ", "Socket");
		if (Pflag)
			printf("%8.8s %8.8s %8.8s ", "TxWin", "Unacked", "RTT/ms");
		if (Lflag) {
			printf("%-5.5s %-14.14s %-22.22s\n",
				"Proto", "Listen", "Local Address");
		} else {
			printf((Aflag && !Wflag) ?
			    "%-5.5s %-6.6s %-6.6s %-17.17s %-17.17s %s\n" :
			    "%-5.5s %-6.6s %-6.6s %-21.21s %-21.21s %s\n",
			    "Proto", "Recv-Q", "Send-Q",
			    "Local Address", "Foreign Address",
			    "(state)");
		}
		ppr_first = 0;
	}
	if (Lflag && so->so_qlimit == 0)
		return;
	if (Aflag) {
		if (tp)
			printf("%8lx ", (u_long)inp->inp_ppcb);
		else
			printf("%8lx ", (u_long)so->so_pcb);
	}
	if (Pflag) {
		if (tp) {
			int window = MIN(tp->snd_cwnd, tp->snd_bwnd);
			if (window == 1073725440)
				printf("%8s ", "max");
			else
				printf("%8d ", (int)MIN(tp->snd_cwnd, tp->snd_bwnd));
			printf("%8d ", (int)(tp->snd_max - tp->snd_una));
			if (tp->t_srtt == 0)
			    printf("%8s ", "-");
			else
			    printf("%8.3f ", (double)tp->t_srtt * 1000.0 / TCP_RTT_SCALE / clockinfo.hz);
		} else {
			printf("%8s %8s %8s ", "-", "-", "-");
		}
	}
#ifdef INET6
	if ((inp->inp_vflag & INP_IPV6) != 0)
		vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? "46" : "6 ";
	else
#endif
		vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? "4 " : "  ";

	printf("%-3.3s%-2.2s ", name, vchar);
	if (Lflag) {
		char buf[15];

		snprintf(buf, sizeof(buf), "%d/%d/%d", so->so_qlen,
			 so->so_incqlen, so->so_qlimit);
		printf("%-13.13s ", buf);
	} else if (Bflag) {
		printf("%6ld %6ld ",
		       so->so_rcv.sb_hiwat,
		       so->so_snd.sb_hiwat);
	} else {
		printf("%6ld %6ld ",
		       so->so_rcv.sb_cc,
		       so->so_snd.sb_cc);
	}
	if (numeric_port) {
		if (inp->inp_vflag & INP_IPV4) {
			inetprint(&inp->inp_laddr, (int)inp->inp_lport,
				  name, 1);
			if (!Lflag)
				inetprint(&inp->inp_faddr,
					  (int)inp->inp_fport, name, 1);
		}
#ifdef INET6
		else if (inp->inp_vflag & INP_IPV6) {
			inet6print(&inp->in6p_laddr,
				   (int)inp->inp_lport, name, 1);
			if (!Lflag)
				inet6print(&inp->in6p_faddr,
					   (int)inp->inp_fport, name, 1);
		} /* else nothing printed now */
#endif /* INET6 */
	} else if (inp->inp_flags & INP_ANONPORT) {
		if (inp->inp_vflag & INP_IPV4) {
			inetprint(&inp->inp_laddr, (int)inp->inp_lport,
				  name, 1);
			if (!Lflag)
				inetprint(&inp->inp_faddr,
					  (int)inp->inp_fport, name, 0);
		}
#ifdef INET6
		else if (inp->inp_vflag & INP_IPV6) {
			inet6print(&inp->in6p_laddr,
				   (int)inp->inp_lport, name, 1);
			if (!Lflag)
				inet6print(&inp->in6p_faddr,
					   (int)inp->inp_fport, name, 0);
		} /* else nothing printed now */
#endif /* INET6 */
	} else {
		if (inp->inp_vflag & INP_IPV4) {
			inetprint(&inp->inp_laddr, (int)inp->inp_lport,
				  name, 0);
			if (!Lflag)
				inetprint(&inp->inp_faddr,
					  (int)inp->inp_fport, name,
					  inp->inp_lport !=
						inp->inp_fport);
		}
#ifdef INET6
		else if (inp->inp_vflag & INP_IPV6) {
			inet6print(&inp->in6p_laddr,
				   (int)inp->inp_lport, name, 0);
			if (!Lflag)
				inet6print(&inp->in6p_faddr,
					   (int)inp->inp_fport, name,
					   inp->inp_lport !=
						inp->inp_fport);
		} /* else nothing printed now */
#endif /* INET6 */
	}
	if (tp && !Lflag) {
		if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
			printf("%d", tp->t_state);
	      else {
			printf("%s", tcpstates[tp->t_state]);
#if defined(TF_NEEDSYN) && defined(TF_NEEDFIN)
		      /* Show T/TCP `hidden state' */
		      if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN))
			      putchar('*');
#endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */
	      }
	}
	putchar('\n');
}
示例#13
0
int
if_route6(const struct rt6 *rt, int action)
{
	struct nlmr *nlm;
	char metricsbuf[32];
	struct rtattr *metrics = (void *)metricsbuf;
	int retval = 0;

	nlm = calloc(1, sizeof(*nlm));
	if (nlm == NULL)
		return -1;
	nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
	nlm->hdr.nlmsg_type = RTM_NEWROUTE;
	nlm->hdr.nlmsg_flags = NLM_F_REQUEST;
	if (action == 0)
		nlm->hdr.nlmsg_flags |= NLM_F_REPLACE;
	else if (action == 1)
		nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
	else
		nlm->hdr.nlmsg_type = RTM_DELROUTE;
	nlm->rt.rtm_family = AF_INET6;
	nlm->rt.rtm_table = RT_TABLE_MAIN;

	if (action == -1 || action == -2)
		nlm->rt.rtm_scope = RT_SCOPE_NOWHERE;
	else {
		nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
		/* None interface subnet routes are static. */
		if (IN6_IS_ADDR_UNSPECIFIED(&rt->gate)) {
			nlm->rt.rtm_protocol = RTPROT_KERNEL;
			nlm->rt.rtm_scope = RT_SCOPE_LINK;
		} else
			nlm->rt.rtm_protocol = RTPROT_BOOT;
		nlm->rt.rtm_type = RTN_UNICAST;
	}

	nlm->rt.rtm_dst_len = ipv6_prefixlen(&rt->net);
	add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_DST,
	    &rt->dest.s6_addr, sizeof(rt->dest.s6_addr));

	/* If destination == gateway then don't add the gateway */
	if (!IN6_IS_ADDR_UNSPECIFIED(&rt->gate) &&
	    !IN6_ARE_ADDR_EQUAL(&rt->dest, &rt->gate))
		add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_GATEWAY,
		    &rt->gate.s6_addr, sizeof(rt->gate.s6_addr));

	add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_OIF, rt->iface->index);
	add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_PRIORITY, rt->metric);

	if (rt->mtu) {
		metrics->rta_type = RTA_METRICS;
		metrics->rta_len = RTA_LENGTH(0);
		rta_add_attr_32(metrics, sizeof(metricsbuf), RTAX_MTU, rt->mtu);
		add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_METRICS,
		    RTA_DATA(metrics), RTA_PAYLOAD(metrics));
	}

	if (send_netlink(&nlm->hdr) == -1)
		retval = -1;
	free(nlm);
	return retval;
	errno = ENOTSUP;
	return -1;
}
示例#14
0
int sendfromto(int s, void *buf, size_t len, int flags,
	       struct sockaddr *from, socklen_t fromlen,
	       struct sockaddr *to, socklen_t tolen)
{
	struct msghdr msgh;
	struct cmsghdr *cmsg;
	struct iovec iov;
	char cbuf[256];

#ifdef __FreeBSD__
	/*
	 *	FreeBSD is extra pedantic about the use of IP_SENDSRCADDR,
	 *	and sendmsg will fail with EINVAL if IP_SENDSRCADDR is used
	 *	with a socket which is bound to something other than
	 *	INADDR_ANY
	 */
	struct sockaddr bound;
	socklen_t bound_len = sizeof(bound);

	if (getsockname(s, &bound, &bound_len) < 0) {
		return -1;
	}

	switch (bound.sa_family) {
	case AF_INET:
		if (((struct sockaddr_in *) &bound)->sin_addr.s_addr != INADDR_ANY) {
			from = NULL;
		}
		break;

	case AF_INET6:
		if (!IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *) &bound)->sin6_addr)) {
			from = NULL;
		}
		break;
	}
#else
#  if !defined(IP_PKTINFO) && !defined(IP_SENDSRCADDR) && !defined(IPV6_PKTINFO)
	/*
	 *	If the sendmsg() flags aren't defined, fall back to
	 *	using sendto().
	 */
	from = NULL;
#  endif
#endif

	/*
	 *	Catch the case where the caller passes invalid arguments.
	 */
	if (!from || (fromlen == 0) || (from->sa_family == AF_UNSPEC)) {
		return sendto(s, buf, len, flags, to, tolen);
	}

	/* Set up control buffer iov and msgh structures. */
	memset(&cbuf, 0, sizeof(cbuf));
	memset(&msgh, 0, sizeof(msgh));
	memset(&iov, 0, sizeof(iov));
	iov.iov_base = buf;
	iov.iov_len = len;
	msgh.msg_iov = &iov;
	msgh.msg_iovlen = 1;
	msgh.msg_name = to;
	msgh.msg_namelen = tolen;

	if (from->sa_family == AF_INET) {
#if !defined(IP_PKTINFO) && !defined(IP_SENDSRCADDR)
		return sendto(s, buf, len, flags, to, tolen);
#else
		struct sockaddr_in *s4 = (struct sockaddr_in *) from;

#  ifdef IP_PKTINFO
		struct in_pktinfo *pkt;

		msgh.msg_control = cbuf;
		msgh.msg_controllen = CMSG_SPACE(sizeof(*pkt));

		cmsg = CMSG_FIRSTHDR(&msgh);
		cmsg->cmsg_level = SOL_IP;
		cmsg->cmsg_type = IP_PKTINFO;
		cmsg->cmsg_len = CMSG_LEN(sizeof(*pkt));

		pkt = (struct in_pktinfo *) CMSG_DATA(cmsg);
		memset(pkt, 0, sizeof(*pkt));
		pkt->ipi_spec_dst = s4->sin_addr;
#  endif

#  ifdef IP_SENDSRCADDR
		struct in_addr *in;

		msgh.msg_control = cbuf;
		msgh.msg_controllen = CMSG_SPACE(sizeof(*in));

		cmsg = CMSG_FIRSTHDR(&msgh);
		cmsg->cmsg_level = IPPROTO_IP;
		cmsg->cmsg_type = IP_SENDSRCADDR;
		cmsg->cmsg_len = CMSG_LEN(sizeof(*in));

		in = (struct in_addr *) CMSG_DATA(cmsg);
		*in = s4->sin_addr;
#  endif
#endif	/* IP_PKTINFO or IP_SENDSRCADDR */
	}

#ifdef AF_INET6
	else if (from->sa_family == AF_INET6) {
#  if !defined(IPV6_PKTINFO)
		return sendto(s, buf, len, flags, to, tolen);
#  else
		struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) from;

		struct in6_pktinfo *pkt;

		msgh.msg_control = cbuf;
		msgh.msg_controllen = CMSG_SPACE(sizeof(*pkt));

		cmsg = CMSG_FIRSTHDR(&msgh);
		cmsg->cmsg_level = IPPROTO_IPV6;
		cmsg->cmsg_type = IPV6_PKTINFO;
		cmsg->cmsg_len = CMSG_LEN(sizeof(*pkt));

		pkt = (struct in6_pktinfo *) CMSG_DATA(cmsg);
		memset(pkt, 0, sizeof(*pkt));
		pkt->ipi6_addr = s6->sin6_addr;
#  endif	/* IPV6_PKTINFO */
	}
#endif

	/*
	 *	Unknown address family.
	 */
	else {
		errno = EINVAL;
		return -1;
	}

	return sendmsg(s, &msgh, flags);
}
static bool inetAddressToSockaddr(JNIEnv* env, jobject inetAddress, int port, sockaddr_storage& ss, socklen_t& sa_len, bool map) {
    memset(&ss, 0, sizeof(ss));
    sa_len = 0;

    if (inetAddress == NULL) {
        jniThrowNullPointerException(env, NULL);
        return false;
    }

    // Get the address family.
    static jfieldID familyFid = env->GetFieldID(JniConstants::inetAddressClass, "family", "I");
    ss.ss_family = env->GetIntField(inetAddress, familyFid);
    if (ss.ss_family == AF_UNSPEC) {
        sa_len = sizeof(ss.ss_family);
        return true; // Job done!
    }

    // Check this is an address family we support.
    if (ss.ss_family != AF_INET && ss.ss_family != AF_INET6 && ss.ss_family != AF_UNIX) {
        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
                "inetAddressToSockaddr bad family: %i", ss.ss_family);
        return false;
    }

    // Get the byte array that stores the IP address bytes in the InetAddress.
    static jfieldID bytesFid = env->GetFieldID(JniConstants::inetAddressClass, "ipaddress", "[B");
    ScopedLocalRef<jbyteArray> addressBytes(env, reinterpret_cast<jbyteArray>(env->GetObjectField(inetAddress, bytesFid)));
    if (addressBytes.get() == NULL) {
        jniThrowNullPointerException(env, NULL);
        return false;
    }

    // Handle the AF_UNIX special case.
    if (ss.ss_family == AF_UNIX) {
        sockaddr_un& sun = reinterpret_cast<sockaddr_un&>(ss);

        size_t path_length = env->GetArrayLength(addressBytes.get());
        if (path_length >= sizeof(sun.sun_path)) {
            jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
                                 "inetAddressToSockaddr path too long for AF_UNIX: %i", path_length);
            return false;
        }

        // Copy the bytes...
        jbyte* dst = reinterpret_cast<jbyte*>(&sun.sun_path);
        memset(dst, 0, sizeof(sun.sun_path));
        env->GetByteArrayRegion(addressBytes.get(), 0, path_length, dst);
        sa_len = sizeof(sun.sun_path);
        return true;
    }

    // TODO: bionic's getnameinfo(3) seems to want its length parameter to be exactly
    // sizeof(sockaddr_in) for an IPv4 address and sizeof (sockaddr_in6) for an
    // IPv6 address. Fix getnameinfo so it accepts sizeof(sockaddr_storage), and
    // then unconditionally set sa_len to sizeof(sockaddr_storage) instead of having
    // to deal with this case by case.

    // We use AF_INET6 sockets, so we want an IPv6 address (which may be a IPv4-mapped address).
    sockaddr_in6& sin6 = reinterpret_cast<sockaddr_in6&>(ss);
    sin6.sin6_port = htons(port);
    if (ss.ss_family == AF_INET6) {
        // IPv6 address. Copy the bytes...
        jbyte* dst = reinterpret_cast<jbyte*>(&sin6.sin6_addr.s6_addr);
        env->GetByteArrayRegion(addressBytes.get(), 0, 16, dst);
        // ...and set the scope id...
        static jfieldID scopeFid = env->GetFieldID(JniConstants::inet6AddressClass, "scope_id", "I");
        sin6.sin6_scope_id = env->GetIntField(inetAddress, scopeFid);
        sa_len = sizeof(sockaddr_in6);
        return true;
    }

    // Deal with Inet4Address instances.
    if (map) {
        // We should represent this Inet4Address as an IPv4-mapped IPv6 sockaddr_in6.
        // Change the family...
        sin6.sin6_family = AF_INET6;
        // Copy the bytes...
        jbyte* dst = reinterpret_cast<jbyte*>(&sin6.sin6_addr.s6_addr[12]);
        env->GetByteArrayRegion(addressBytes.get(), 0, 4, dst);
        // INADDR_ANY and in6addr_any are both all-zeros...
        if (!IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr)) {
            // ...but all other IPv4-mapped addresses are ::ffff:a.b.c.d, so insert the ffff...
            memset(&(sin6.sin6_addr.s6_addr[10]), 0xff, 2);
        }
        sa_len = sizeof(sockaddr_in6);
    } else {
        // We should represent this Inet4Address as an IPv4 sockaddr_in.
        sockaddr_in& sin = reinterpret_cast<sockaddr_in&>(ss);
        sin.sin_port = htons(port);
        jbyte* dst = reinterpret_cast<jbyte*>(&sin.sin_addr.s_addr);
        env->GetByteArrayRegion(addressBytes.get(), 0, 4, dst);
        sa_len = sizeof(sockaddr_in);
    }
    return true;
}
示例#16
0
void
ip6_forward(struct mbuf *m, int srcrt)
{
	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
	struct sockaddr_in6 *dst;
	struct rtentry *rt;
	int error = 0, type = 0, code = 0;
	struct mbuf *mcopy = NULL;
	struct ifnet *origifp;	/* maybe unnecessary */
#ifdef IPSEC
	u_int8_t sproto = 0;
	struct m_tag *mtag;
	union sockaddr_union sdst;
	struct tdb_ident *tdbi;
	u_int32_t sspi;
	struct tdb *tdb;
	int s;
#endif /* IPSEC */
	u_int rtableid = 0;

	/*
	 * Do not forward packets to multicast destination (should be handled
	 * by ip6_mforward().
	 * Do not forward packets with unspecified source.  It was discussed
	 * in July 2000, on ipngwg mailing list.
	 */
	if ((m->m_flags & (M_BCAST|M_MCAST)) != 0 ||
	    IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
	    IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
		ip6stat.ip6s_cantforward++;
		/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
		if (ip6_log_time + ip6_log_interval < time_second) {
			ip6_log_time = time_second;
			log(LOG_DEBUG,
			    "cannot forward "
			    "from %s to %s nxt %d received on %s\n",
			    ip6_sprintf(&ip6->ip6_src),
			    ip6_sprintf(&ip6->ip6_dst),
			    ip6->ip6_nxt,
			    m->m_pkthdr.rcvif->if_xname);
		}
		m_freem(m);
		return;
	}

	if (ip6->ip6_hlim <= IPV6_HLIMDEC) {
		/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
		icmp6_error(m, ICMP6_TIME_EXCEEDED,
				ICMP6_TIME_EXCEED_TRANSIT, 0);
		return;
	}
	ip6->ip6_hlim -= IPV6_HLIMDEC;

#if NPF > 0
reroute:
#endif

#ifdef IPSEC
	if (!ipsec_in_use)
		goto done_spd;

	s = splnet();

	/*
	 * Check if there was an outgoing SA bound to the flow
	 * from a transport protocol.
	 */

	/* Do we have any pending SAs to apply ? */
	mtag = m_tag_find(m, PACKET_TAG_IPSEC_PENDING_TDB, NULL);
	if (mtag != NULL) {
#ifdef DIAGNOSTIC
		if (mtag->m_tag_len != sizeof (struct tdb_ident))
			panic("ip6_forward: tag of length %d (should be %d",
			    mtag->m_tag_len, sizeof (struct tdb_ident));
#endif
		tdbi = (struct tdb_ident *)(mtag + 1);
		tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto);
		if (tdb == NULL)
			error = -EINVAL;
		m_tag_delete(m, mtag);
	} else
		tdb = ipsp_spd_lookup(m, AF_INET6, sizeof(struct ip6_hdr),
		    &error, IPSP_DIRECTION_OUT, NULL, NULL);

	if (tdb == NULL) {
	        splx(s);

		if (error == 0) {
		        /*
			 * No IPsec processing required, we'll just send the
			 * packet out.
			 */
		        sproto = 0;

			/* Fall through to routing/multicast handling */
		} else {
		        /*
			 * -EINVAL is used to indicate that the packet should
			 * be silently dropped, typically because we've asked
			 * key management for an SA.
			 */
		        if (error == -EINVAL) /* Should silently drop packet */
				error = 0;

			goto freecopy;
		}
	} else {
		/* Loop detection */
		for (mtag = m_tag_first(m); mtag != NULL;
		    mtag = m_tag_next(m, mtag)) {
			if (mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_DONE &&
			    mtag->m_tag_id !=
			    PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED)
				continue;
			tdbi = (struct tdb_ident *)(mtag + 1);
			if (tdbi->spi == tdb->tdb_spi &&
			    tdbi->proto == tdb->tdb_sproto &&
			    !bcmp(&tdbi->dst, &tdb->tdb_dst,
			    sizeof(union sockaddr_union))) {
				splx(s);
				sproto = 0; /* mark as no-IPsec-needed */
				goto done_spd;
			}
		}

	        /* We need to do IPsec */
	        bcopy(&tdb->tdb_dst, &sdst, sizeof(sdst));
		sspi = tdb->tdb_spi;
		sproto = tdb->tdb_sproto;
	        splx(s);
	}

	/* Fall through to the routing/multicast handling code */
 done_spd:
#endif /* IPSEC */

#if NPF > 0
	rtableid = m->m_pkthdr.rdomain;
#endif

	/*
	 * Save at most ICMPV6_PLD_MAXLEN (= the min IPv6 MTU -
	 * size of IPv6 + ICMPv6 headers) bytes of the packet in case
	 * we need to generate an ICMP6 message to the src.
	 * Thanks to M_EXT, in most cases copy will not occur.
	 *
	 * It is important to save it before IPsec processing as IPsec
	 * processing may modify the mbuf.
	 */
	mcopy = m_copy(m, 0, imin(m->m_pkthdr.len, ICMPV6_PLD_MAXLEN));

	dst = &ip6_forward_rt.ro_dst;
	if (!srcrt) {
		/*
		 * ip6_forward_rt.ro_dst.sin6_addr is equal to ip6->ip6_dst
		 */
		if (ip6_forward_rt.ro_rt == 0 ||
		    (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) == 0 ||
		    ip6_forward_rtableid != rtableid) {
			if (ip6_forward_rt.ro_rt) {
				RTFREE(ip6_forward_rt.ro_rt);
				ip6_forward_rt.ro_rt = 0;
			}
			/* this probably fails but give it a try again */
			rtalloc_mpath((struct route *)&ip6_forward_rt,
			    &ip6->ip6_src.s6_addr32[0], rtableid);
			ip6_forward_rtableid = rtableid;
		}

		if (ip6_forward_rt.ro_rt == 0) {
			ip6stat.ip6s_noroute++;
			/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_noroute) */
			if (mcopy) {
				icmp6_error(mcopy, ICMP6_DST_UNREACH,
					    ICMP6_DST_UNREACH_NOROUTE, 0);
			}
			m_freem(m);
			return;
		}
	} else if (ip6_forward_rt.ro_rt == 0 ||
	   (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) == 0 ||
	   !IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &dst->sin6_addr) ||
	   ip6_forward_rtableid != rtableid) {
		if (ip6_forward_rt.ro_rt) {
			RTFREE(ip6_forward_rt.ro_rt);
			ip6_forward_rt.ro_rt = 0;
		}
		bzero(dst, sizeof(*dst));
		dst->sin6_len = sizeof(struct sockaddr_in6);
		dst->sin6_family = AF_INET6;
		dst->sin6_addr = ip6->ip6_dst;

		rtalloc_mpath((struct route *)&ip6_forward_rt,
		    &ip6->ip6_src.s6_addr32[0], rtableid);
		ip6_forward_rtableid = rtableid;

		if (ip6_forward_rt.ro_rt == 0) {
			ip6stat.ip6s_noroute++;
			/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_noroute) */
			if (mcopy) {
				icmp6_error(mcopy, ICMP6_DST_UNREACH,
					    ICMP6_DST_UNREACH_NOROUTE, 0);
			}
			m_freem(m);
			return;
		}
	}
	rt = ip6_forward_rt.ro_rt;

	/*
	 * Scope check: if a packet can't be delivered to its destination
	 * for the reason that the destination is beyond the scope of the
	 * source address, discard the packet and return an icmp6 destination
	 * unreachable error with Code 2 (beyond scope of source address).
	 * [draft-ietf-ipngwg-icmp-v3-00.txt, Section 3.1]
	 */
	if (in6_addr2scopeid(m->m_pkthdr.rcvif, &ip6->ip6_src) !=
	    in6_addr2scopeid(rt->rt_ifp, &ip6->ip6_src)) {
		ip6stat.ip6s_cantforward++;
		ip6stat.ip6s_badscope++;
		in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard);

		if (ip6_log_time + ip6_log_interval < time_second) {
			ip6_log_time = time_second;
			log(LOG_DEBUG,
			    "cannot forward "
			    "src %s, dst %s, nxt %d, rcvif %s, outif %s\n",
			    ip6_sprintf(&ip6->ip6_src),
			    ip6_sprintf(&ip6->ip6_dst),
			    ip6->ip6_nxt,
			    m->m_pkthdr.rcvif->if_xname, rt->rt_ifp->if_xname);
		}
		if (mcopy)
			icmp6_error(mcopy, ICMP6_DST_UNREACH,
				    ICMP6_DST_UNREACH_BEYONDSCOPE, 0);
		m_freem(m);
		goto freert;
	}

#ifdef IPSEC
	/*
	 * Check if the packet needs encapsulation.
	 * ipsp_process_packet will never come back to here.
	 * XXX ipsp_process_packet() calls ip6_output(), and there'll be no
	 * PMTU notification.  is it okay?
	 */
	if (sproto != 0) {
		s = splnet();

#if NPF > 0
		if (pf_test6(PF_OUT, &encif[0].sc_if, &m, NULL) != PF_PASS) {
			splx(s);
			error = EHOSTUNREACH;
			m_freem(m);
			goto senderr;
		}
		if (m == NULL) {
			splx(s);
			goto senderr;
		}
		ip6 = mtod(m, struct ip6_hdr *);
		/*
		 * PF_TAG_REROUTE handling or not...
		 * Packet is entering IPsec so the routing is
		 * already overruled by the IPsec policy.
		 * Until now the change was not reconsidered.
		 * What's the behaviour?
		 */
#endif
		tdb = gettdb(sspi, &sdst, sproto);
		if (tdb == NULL) {
			splx(s);
			error = EHOSTUNREACH;
			m_freem(m);
			goto senderr;	/*XXX*/
		}

		m->m_flags &= ~(M_BCAST | M_MCAST);	/* just in case */

		/* Callee frees mbuf */
		error = ipsp_process_packet(m, tdb, AF_INET6, 0);
		splx(s);
		m_freem(mcopy);
		goto freert;
	}
示例#17
0
文件: input.c 项目: nskeeper/improxy
void mcast_recv_mld(int sockfd, int version)
{
    unsigned char buf[MAX_RECV_BUF_LEN] = {0};
    int num = 0;
    pi_addr pig, pia;
    struct msghdr msg;
    struct sockaddr_in6 sa;
    struct iovec    iov;
    struct cmsghdr *cmsg;
    char           *ctrl = (char *) malloc(MAXCTRLSIZE);
    struct in6_pktinfo *info;
    unsigned int if_index = 0;
    struct mld_hdr  *p_mldh;
    imp_interface *p_if = NULL;

    /*To get the unique index of the interfacethe packet was received on*/
    bzero(&msg, sizeof(msg));
    iov.iov_base = buf;
    iov.iov_len = 2048;
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
    msg.msg_control = ctrl;
    msg.msg_controllen = MAXCTRLSIZE;
    msg.msg_name = &sa;
    msg.msg_namelen = sizeof(struct sockaddr_in6);

    num = recvmsg(get_igmp_mld_socket(AF_INET6), &msg, MSG_WAITALL);
    if (num <= 20) {
        IMP_LOG_ERROR("BAD packet received n=%d \n", num);
        free(ctrl);
        return;
    }

    for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
     cmsg = CMSG_NXTHDR(&msg, cmsg)) {

        if (cmsg->cmsg_type == IPV6_PKTINFO) {


            info = (struct in6_pktinfo *) CMSG_DATA(cmsg);
            if_index = info->ipi6_ifindex;
            imp_build_piaddr(AF_INET6, &info->ipi6_addr, &pig);
            imp_build_piaddr(AF_INET6, &sa.sin6_addr, &pia);
            IMP_LOG_DEBUG("from %s %s %d\n", imp_pi_ntoa(&pig), imp_pi_ntoa(&pia), if_index);
        }
    }
    free(ctrl);

    if (if_index == 0) {
        /*
         * Structure used to communicate from kernel to multicast router.
         * We'll overlay the structure onto an MLD header (not an IPv6 heder like igmpmsg{}
         * used for IPv4 implementation). This is because this structure will be passed via an
         * IPv6 raw socket, on wich an application will only receiver the payload i.e the data after
         * the IPv6 header and all the extension headers. (See section 3 of RFC 3542)
         */
        struct mrt6msg *p_mrmsg;
        int mif = 0;

        p_mrmsg = msg.msg_iov->iov_base;

        IMP_LOG_DEBUG("DUMP mrmsg:\n\tmif %d\n\tmsgtype %d\n\tsrc %s\n\tgroup %s\n",
        p_mrmsg->im6_mif, p_mrmsg->im6_msgtype, imp_inet6_ntoa(p_mrmsg->im6_src.s6_addr),
        imp_inet6_ntoa(p_mrmsg->im6_dst.s6_addr));

        imp_build_piaddr(AF_INET6, &p_mrmsg->im6_dst, &pig);
        imp_build_piaddr(AF_INET6, &p_mrmsg->im6_src, &pia);

          mif = k_get_vmif(get_up_if_index(), AF_INET6);

        IMP_LOG_DEBUG("k_get_vmif = %d im6_mif %d\n", mif, p_mrmsg->im6_mif);

        if (mif == p_mrmsg->im6_mif) {

            if_set ttls;

            bzero(&ttls, sizeof(ttls));

            /*get ttls*/
            if (imp_get_mfcc_ttls(&ttls, MAXVIFS, &pia, &pig) != 0) {

                IMP_LOG_DEBUG("add MFC:src -- %s  group -- %s\n\n", imp_pi_ntoa(&pia), imp_pi_ntoa(&pig));
                imp_membership_db_mfc_add(&pig, &pia, &ttls);
            }
        }
        return;

    }

    /* An MLDv2 Report MUST be sent with a valid IPv6 link-local source
     * address, or the unspecified address (::), if the sending interface
     * has not acquired a valid link-local address yet.
     * [rfc 3810 5.2.13]
    */
    if (!(IN6_IS_ADDR_LINKLOCAL(&sa.sin6_addr) || IN6_IS_ADDR_UNSPECIFIED(&sa.sin6_addr))) {

        IMP_LOG_ERROR("MLDv2 Report MUST be sent with a valid IPv6 link-local "
            "source address, or the unspecified address (::).\n");
        return;
    }


    /*return if the interface don't enable igmp*/
    for(p_if = imp_interface_first();p_if;p_if = LIST_NEXT(p_if, link))
    {
        if(p_if->if_index == if_index && p_if->if_addr.ss.ss_family == AF_INET6)
            break;
    }

    if (p_if == NULL) {

        IMP_LOG_WARNING("Don't exist this VIF\n");
        return;
    }

    p_mldh = msg.msg_iov->iov_base;

    switch (p_mldh->mld_type) {
        case MLD_LISTENER_REPORT:
        case MLD_LISTENER_REDUCTION:
            imp_input_report_mld(p_if, p_mldh);
            break;
        case MLD_V2_LISTENER_REPORT:
            if (version < IM_IGMPv3_MLDv2) {

                IMP_LOG_WARNING("current version is mldv%d\n", version - 1);
                return;
            }
            imp_input_report_mldv2(p_if, p_mldh, num);
            break;
        default:
            IMP_LOG_WARNING("unknown type %d\n", p_mldh->mld_type);
            break;

    }

}
示例#18
0
/*
 * Loop over a tdb chain, taking into consideration protocol tunneling. The
 * fourth argument is set if the first encapsulation header is already in
 * place.
 */
int
ipsp_process_packet(struct mbuf *m, struct tdb *tdb, int af, int tunalready)
{
	struct timeval tv;
	int i, off, error;
	struct mbuf *mp;
#ifdef INET6
	struct ip6_ext ip6e;
	int nxt;
	int dstopt = 0;
#endif

#ifdef INET
	int setdf = 0;
	struct ip *ip;
#endif /* INET */
#ifdef INET6
	struct ip6_hdr *ip6;
#endif /* INET6 */

	/* Check that the transform is allowed by the administrator. */
	if ((tdb->tdb_sproto == IPPROTO_ESP && !esp_enable) ||
	    (tdb->tdb_sproto == IPPROTO_AH && !ah_enable) ||
	    (tdb->tdb_sproto == IPPROTO_IPCOMP && !ipcomp_enable)) {
		DPRINTF(("ipsp_process_packet(): IPsec outbound packet "
		    "dropped due to policy (check your sysctls)\n"));
		m_freem(m);
		return EHOSTUNREACH;
	}

	/* Sanity check. */
	if (!tdb->tdb_xform) {
		DPRINTF(("ipsp_process_packet(): uninitialized TDB\n"));
		m_freem(m);
		return EHOSTUNREACH;
	}

	/* Check if the SPI is invalid. */
	if (tdb->tdb_flags & TDBF_INVALID) {
		DPRINTF(("ipsp_process_packet(): attempt to use invalid "
		    "SA %s/%08x/%u\n", ipsp_address(tdb->tdb_dst),
		    ntohl(tdb->tdb_spi), tdb->tdb_sproto));
		m_freem(m);
		return ENXIO;
	}

	/* Check that the network protocol is supported */
	switch (tdb->tdb_dst.sa.sa_family) {
#ifdef INET
	case AF_INET:
		break;
#endif /* INET */

#ifdef INET6
	case AF_INET6:
		break;
#endif /* INET6 */

	default:
		DPRINTF(("ipsp_process_packet(): attempt to use "
		    "SA %s/%08x/%u for protocol family %d\n",
		    ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi),
		    tdb->tdb_sproto, tdb->tdb_dst.sa.sa_family));
		m_freem(m);
		return ENXIO;
	}

	/*
	 * Register first use if applicable, setup relevant expiration timer.
	 */
	if (tdb->tdb_first_use == 0) {
		tdb->tdb_first_use = time_second;

		tv.tv_usec = 0;

		tv.tv_sec = tdb->tdb_first_use + tdb->tdb_exp_first_use;
		if (tdb->tdb_flags & TDBF_FIRSTUSE)
			timeout_add(&tdb->tdb_first_tmo,
			    hzto(&tv));

		tv.tv_sec = tdb->tdb_first_use + tdb->tdb_soft_first_use;
		if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE)
			timeout_add(&tdb->tdb_sfirst_tmo,
			    hzto(&tv));
	}

	/*
	 * Check for tunneling if we don't have the first header in place.
	 * When doing Ethernet-over-IP, we are handed an already-encapsulated
	 * frame, so we don't need to re-encapsulate.
	 */
	if (tunalready == 0) {
		/*
		 * If the target protocol family is different, we know we'll be
		 * doing tunneling.
		 */
		if (af == tdb->tdb_dst.sa.sa_family) {
#ifdef INET
			if (af == AF_INET)
				i = sizeof(struct ip);
#endif /* INET */

#ifdef INET6
			if (af == AF_INET6)
				i = sizeof(struct ip6_hdr);
#endif /* INET6 */

			/* Bring the network header in the first mbuf. */
			if (m->m_len < i) {
				if ((m = m_pullup(m, i)) == NULL)
					return ENOBUFS;
			}

#ifdef INET
			if (af == AF_INET) {
				ip = mtod(m, struct ip *);

				/*
				 * This is not a bridge packet, remember if we
				 * had IP_DF.
				 */
				setdf = ip->ip_off & htons(IP_DF);
			}
#endif /* INET */

#ifdef INET6
			if (af == AF_INET6)
				ip6 = mtod(m, struct ip6_hdr *);
#endif /* INET6 */
		}

		/* Do the appropriate encapsulation, if necessary. */
		if ((tdb->tdb_dst.sa.sa_family != af) || /* PF mismatch */
		    (tdb->tdb_flags & TDBF_TUNNELING) || /* Tunneling needed */
		    (tdb->tdb_xform->xf_type == XF_IP4) || /* ditto */
#ifdef INET
		    ((tdb->tdb_dst.sa.sa_family == AF_INET) &&
			(tdb->tdb_dst.sin.sin_addr.s_addr != INADDR_ANY) &&
			(tdb->tdb_dst.sin.sin_addr.s_addr != ip->ip_dst.s_addr)) ||
#endif /* INET */
#ifdef INET6
		    ((tdb->tdb_dst.sa.sa_family == AF_INET6) &&
			(!IN6_IS_ADDR_UNSPECIFIED(&tdb->tdb_dst.sin6.sin6_addr)) &&
			(!IN6_ARE_ADDR_EQUAL(&tdb->tdb_dst.sin6.sin6_addr,
			    &ip6->ip6_dst))) ||
#endif /* INET6 */
		    0) {
#ifdef INET
			/* Fix IPv4 header checksum and length. */
			if (af == AF_INET) {
				if (m->m_len < sizeof(struct ip))
					if ((m = m_pullup(m,
					    sizeof(struct ip))) == NULL)
						return ENOBUFS;

				ip = mtod(m, struct ip *);
				ip->ip_len = htons(m->m_pkthdr.len);
				ip->ip_sum = 0;
				ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
			}
#endif /* INET */

#ifdef INET6
			/* Fix IPv6 header payload length. */
			if (af == AF_INET6) {
				if (m->m_len < sizeof(struct ip6_hdr))
					if ((m = m_pullup(m,
					    sizeof(struct ip6_hdr))) == NULL)
						return ENOBUFS;

				if (m->m_pkthdr.len - sizeof(*ip6) >
				    IPV6_MAXPACKET) {
					/* No jumbogram support. */
					m_freem(m);
					return ENXIO;	/*?*/
				}
				ip6 = mtod(m, struct ip6_hdr *);
				ip6->ip6_plen = htons(m->m_pkthdr.len
				    - sizeof(*ip6));
			}
#endif /* INET6 */

			/* Encapsulate -- the last two arguments are unused. */
			error = ipip_output(m, tdb, &mp, 0, 0);
			if ((mp == NULL) && (!error))
				error = EFAULT;
			if (error) {
				if (mp)	{
					m_freem(mp);
					mp = NULL;
				}
				return error;
			}

			m = mp;
			mp = NULL;

#ifdef INET
			if (tdb->tdb_dst.sa.sa_family == AF_INET && setdf) {
				if (m->m_len < sizeof(struct ip))
					if ((m = m_pullup(m,
					    sizeof(struct ip))) == NULL)
						return ENOBUFS;

				ip = mtod(m, struct ip *);
				ip->ip_off |= htons(IP_DF);
			}
#endif

			/* Remember that we appended a tunnel header. */
			tdb->tdb_flags |= TDBF_USEDTUNNEL;
		}

		/* We may be done with this TDB */
		if (tdb->tdb_xform->xf_type == XF_IP4)
			return ipsp_process_done(m, tdb);
	} else {
示例#19
0
/*
 * Reads a linux sockaddr and does any necessary translation.
 * Linux sockaddrs don't have a length field, only a family.
 * Copy the osockaddr structure pointed to by osa to kernel, adjust
 * family and convert to sockaddr.
 */
static int
linux_getsockaddr(struct sockaddr **sap, const struct osockaddr *osa, int salen)
{
	struct sockaddr *sa;
	struct osockaddr *kosa;
#ifdef INET6
	struct sockaddr_in6 *sin6;
	int oldv6size;
#endif
	char *name;
	int bdom, error, hdrlen, namelen;

	if (salen < 2 || salen > UCHAR_MAX || !osa)
		return (EINVAL);

#ifdef INET6
	oldv6size = 0;
	/*
	 * Check for old (pre-RFC2553) sockaddr_in6. We may accept it
	 * if it's a v4-mapped address, so reserve the proper space
	 * for it.
	 */
	if (salen == sizeof(struct sockaddr_in6) - sizeof(uint32_t)) {
		salen += sizeof(uint32_t);
		oldv6size = 1;
	}
#endif

	kosa = malloc(salen, M_SONAME, M_WAITOK);

	if ((error = copyin(osa, kosa, salen)))
		goto out;

	bdom = linux_to_bsd_domain(kosa->sa_family);
	if (bdom == -1) {
		error = EAFNOSUPPORT;
		goto out;
	}

#ifdef INET6
	/*
	 * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6,
	 * which lacks the scope id compared with RFC2553 one. If we detect
	 * the situation, reject the address and write a message to system log.
	 *
	 * Still accept addresses for which the scope id is not used.
	 */
	if (oldv6size) {
		if (bdom == AF_INET6) {
			sin6 = (struct sockaddr_in6 *)kosa;
			if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ||
			    (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) &&
			     !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) &&
			     !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) &&
			     !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
			     !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) {
				sin6->sin6_scope_id = 0;
			} else {
				log(LOG_DEBUG,
				    "obsolete pre-RFC2553 sockaddr_in6 rejected\n");
				error = EINVAL;
				goto out;
			}
		} else
			salen -= sizeof(uint32_t);
	}
#endif
	if (bdom == AF_INET) {
		if (salen < sizeof(struct sockaddr_in)) {
			error = EINVAL;
			goto out;
		}
		salen = sizeof(struct sockaddr_in);
	}

	if (bdom == AF_LOCAL && salen > sizeof(struct sockaddr_un)) {
		hdrlen = offsetof(struct sockaddr_un, sun_path);
		name = ((struct sockaddr_un *)kosa)->sun_path;
		if (*name == '\0') {
			/*
		 	 * Linux abstract namespace starts with a NULL byte.
			 * XXX We do not support abstract namespace yet.
			 */
			namelen = strnlen(name + 1, salen - hdrlen - 1) + 1;
		} else
			namelen = strnlen(name, salen - hdrlen);
		salen = hdrlen + namelen;
		if (salen > sizeof(struct sockaddr_un)) {
			error = ENAMETOOLONG;
			goto out;
		}
	}
示例#20
0
int
ncprange_aton(struct ncprange *range, struct ncp *ncp, const char *data)
{
  int bits, len;
  char *wp;
  const char *cp;
  char *s;

  len = strcspn(data, "/");

  if (ncp && strncasecmp(data, "HISADDR", len) == 0) {
    range->ncprange_family = AF_INET;
    range->ncprange_ip4addr = ncp->ipcp.peer_ip;
    range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
    range->ncprange_ip4width = 32;
    return 1;
#ifndef NOINET6
  } else if (ncp && strncasecmp(data, "HISADDR6", len) == 0) {
    range->ncprange_family = AF_INET6;
    range->ncprange_ip6addr = ncp->ipv6cp.hisaddr.ncpaddr_ip6addr;
    range->ncprange_ip6width = 128;
    return 1;
#endif
  } else if (ncp && strncasecmp(data, "MYADDR", len) == 0) {
    range->ncprange_family = AF_INET;
    range->ncprange_ip4addr = ncp->ipcp.my_ip;
    range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
    range->ncprange_ip4width = 32;
    return 1;
#ifndef NOINET6
  } else if (ncp && strncasecmp(data, "MYADDR6", len) == 0) {
    range->ncprange_family = AF_INET6;
    range->ncprange_ip6addr = ncp->ipv6cp.myaddr.ncpaddr_ip6addr;
    range->ncprange_ip6width = 128;
    return 1;
#endif
  } else if (ncp && strncasecmp(data, "DNS0", len) == 0) {
    range->ncprange_family = AF_INET;
    range->ncprange_ip4addr = ncp->ipcp.ns.dns[0];
    range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
    range->ncprange_ip4width = 32;
    return 1;
  } else if (ncp && strncasecmp(data, "DNS1", len) == 0) {
    range->ncprange_family = AF_INET;
    range->ncprange_ip4addr = ncp->ipcp.ns.dns[1];
    range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
    range->ncprange_ip4width = 32;
    return 1;
  }

  s = (char *)alloca(len + 1);
  strncpy(s, data, len);
  s[len] = '\0';
  bits = -1;

  if (data[len] != '\0') {
    bits = strtol(data + len + 1, &wp, 0);
    if (*wp || wp == data + len + 1 || bits < 0 || bits > 128) {
      log_Printf(LogWARN, "ncprange_aton: bad mask width.\n");
      return 0;
    }
  }

  if ((cp = strchr(data, ':')) == NULL) {
    range->ncprange_family = AF_INET;

    range->ncprange_ip4addr = GetIpAddr(s);

    if (range->ncprange_ip4addr.s_addr == INADDR_NONE) {
      log_Printf(LogWARN, "ncprange_aton: %s: Bad address\n", s);
      return 0;
    }

    if (range->ncprange_ip4addr.s_addr == INADDR_ANY) {
      range->ncprange_ip4mask.s_addr = INADDR_ANY;
      range->ncprange_ip4width = 0;
    } else if (bits == -1) {
      range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
      range->ncprange_ip4width = 32;
    } else if (bits > 32) {
      log_Printf(LogWARN, "ncprange_aton: bad mask width.\n");
      return 0;
    } else {
      range->ncprange_ip4mask = bits2mask4(bits);
      range->ncprange_ip4width = bits;
    }

    return 1;
#ifndef NOINET6
  } else if (strchr(cp + 1, ':') != NULL) {
    range->ncprange_family = AF_INET6;

    if (inet_pton(AF_INET6, s, &range->ncprange_ip6addr) != 1) {
      log_Printf(LogWARN, "ncprange_aton: %s: Bad address\n", s);
      return 0;
    }

    if (IN6_IS_ADDR_UNSPECIFIED(&range->ncprange_ip6addr))
      range->ncprange_ip6width = 0;
    else
      range->ncprange_ip6width = (bits == -1) ? 128 : bits;
    return 1;
#endif
  }

  return 0;
}
示例#21
0
static void
process_rs(struct Interface *iface, unsigned char *msg, int len,
	struct sockaddr_in6 *addr)
{
	double delay;
	double next;
	struct timeval tv;
	uint8_t *opt_str;

	/* validation */
	len -= sizeof(struct nd_router_solicit);

	opt_str = (uint8_t *)(msg + sizeof(struct nd_router_solicit));

	while (len > 0)
	{
		int optlen;

		if (len < 2)
		{
			flog(LOG_WARNING, "trailing garbage in RS");
			return;
		}

		optlen = (opt_str[1] << 3);

		if (optlen == 0)
		{
			flog(LOG_WARNING, "zero length option in RS");
			return;
		}
		else if (optlen > len)
		{
			flog(LOG_WARNING, "option length greater than total length in RS");
			return;
		}

		if (*opt_str == ND_OPT_SOURCE_LINKADDR &&
		    IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr)) {
			flog(LOG_WARNING, "received icmpv6 RS packet with unspecified source address and there is a lladdr option");
			return;
		}

		len -= optlen;
		opt_str += optlen;
	}

	gettimeofday(&tv, NULL);

	delay = MAX_RA_DELAY_TIME * rand() / (RAND_MAX +1.0);

	if (iface->UnicastOnly) {
		send_ra_forall(iface, &addr->sin6_addr);
	}
	else if ( timevaldiff(&tv, &iface->last_multicast) / 1000.0 < iface->MinDelayBetweenRAs ) {
		/* last RA was sent only a few moments ago, don't send another immediately. */
		next = iface->MinDelayBetweenRAs - (tv.tv_sec + tv.tv_usec / 1000000.0) + (iface->last_multicast.tv_sec + iface->last_multicast.tv_usec / 1000000.0) + delay/1000.0;
		iface->next_multicast = next_timeval(next);
	}
	else {
		/* no RA sent in a while, send a multicast reply */
		send_ra_forall(iface, NULL);
		next = rand_between(iface->MinRtrAdvInterval, iface->MaxRtrAdvInterval);
		iface->next_multicast = next_timeval(next);
	}
}
示例#22
0
int
udp6_input(struct mbuf **mp, int *offp, int proto)
{
	struct mbuf *m = *mp;
	struct ip6_hdr *ip6;
	struct udphdr *uh;
	struct inpcb *in6p;
	struct  mbuf *opts = NULL;
	int off = *offp;
	int plen, ulen;
	struct sockaddr_in6 udp_in6;
	struct socket *so;
	struct inpcbinfo *pcbinfo = &udbinfo[0];

	IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE);

	ip6 = mtod(m, struct ip6_hdr *);

	udp_stat.udps_ipackets++;

	plen = ntohs(ip6->ip6_plen) - off + sizeof(*ip6);
	uh = (struct udphdr *)((caddr_t)ip6 + off);
	ulen = ntohs((u_short)uh->uh_ulen);

	if (plen != ulen) {
		udp_stat.udps_badlen++;
		goto bad;
	}

	/*
	 * Checksum extended UDP header and data.
	 */
	if (uh->uh_sum == 0)
		udp_stat.udps_nosum++;
	else if (in6_cksum(m, IPPROTO_UDP, off, ulen) != 0) {
		udp_stat.udps_badsum++;
		goto bad;
	}

	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
		struct	inpcb *last, *marker;

		/*
		 * Deliver a multicast datagram to all sockets
		 * for which the local and remote addresses and ports match
		 * those of the incoming datagram.  This allows more than
		 * one process to receive multicasts on the same port.
		 * (This really ought to be done for unicast datagrams as
		 * well, but that would cause problems with existing
		 * applications that open both address-specific sockets and
		 * a wildcard socket listening to the same port -- they would
		 * end up receiving duplicates of every unicast datagram.
		 * Those applications open the multiple sockets to overcome an
		 * inadequacy of the UDP socket interface, but for backwards
		 * compatibility we avoid the problem here rather than
		 * fixing the interface.  Maybe 4.5BSD will remedy this?)
		 */

		/*
		 * In a case that laddr should be set to the link-local
		 * address (this happens in RIPng), the multicast address
		 * specified in the received packet does not match with
		 * laddr. To cure this situation, the matching is relaxed
		 * if the receiving interface is the same as one specified
		 * in the socket and if the destination multicast address
		 * matches one of the multicast groups specified in the socket.
		 */

		/*
		 * Construct sockaddr format source address.
		 */
		init_sin6(&udp_in6, m); /* general init */
		udp_in6.sin6_port = uh->uh_sport;
		/*
		 * KAME note: traditionally we dropped udpiphdr from mbuf here.
		 */

		/*
		 * Locate pcb(s) for datagram.
		 * (Algorithm copied from raw_intr().)
		 */
		last = NULL;

		marker = in_pcbmarker();

		GET_PCBINFO_TOKEN(pcbinfo);

		LIST_INSERT_HEAD(&pcbinfo->pcblisthead, marker, inp_list);
		while ((in6p = LIST_NEXT(marker, inp_list)) != NULL) {
			LIST_REMOVE(marker, inp_list);
			LIST_INSERT_AFTER(in6p, marker, inp_list);

			if (in6p->inp_flags & INP_PLACEMARKER)
				continue;
			if (!INP_ISIPV6(in6p))
				continue;
			if (in6p->in6p_lport != uh->uh_dport)
				continue;
			if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) {
				if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr,
							&ip6->ip6_dst) &&
				    !in6_mcmatch(in6p, &ip6->ip6_dst,
						 m->m_pkthdr.rcvif))
					continue;
			}
			if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
				if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr,
							&ip6->ip6_src) ||
				   in6p->in6p_fport != uh->uh_sport)
					continue;
			}

			if (last != NULL) {
				struct mbuf *n;

				if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
					/*
					 * KAME NOTE: do not
					 * m_copy(m, offset, ...) above.
					 * ssb_appendaddr() expects M_PKTHDR,
					 * and m_copy() will copy M_PKTHDR
					 * only if offset is 0.
					 */
					so = last->in6p_socket;
					if ((last->in6p_flags & IN6P_CONTROLOPTS) ||
					    (so->so_options & SO_TIMESTAMP)) {
						ip6_savecontrol(last, &opts,
								ip6, n);
					}
					m_adj(n, off + sizeof(struct udphdr));
					lwkt_gettoken(&so->so_rcv.ssb_token);
					if (ssb_appendaddr(&so->so_rcv,
						    (struct sockaddr *)&udp_in6,
						    n, opts) == 0) {
						m_freem(n);
						if (opts)
							m_freem(opts);
						udp_stat.udps_fullsock++;
					} else {
						sorwakeup(so);
					}
					lwkt_reltoken(&so->so_rcv.ssb_token);
					opts = NULL;
				}
			}
			last = in6p;
			/*
			 * Don't look for additional matches if this one does
			 * not have either the SO_REUSEPORT or SO_REUSEADDR
			 * socket options set.  This heuristic avoids searching
			 * through all pcbs in the common case of a non-shared
			 * port.  It assumes that an application will never
			 * clear these options after setting them.
			 */
			if ((last->in6p_socket->so_options &
			     (SO_REUSEPORT | SO_REUSEADDR)) == 0)
				break;
		}
		LIST_REMOVE(marker, inp_list);

		REL_PCBINFO_TOKEN(pcbinfo);

		if (last == NULL) {
			/*
			 * No matching pcb found; discard datagram.
			 * (No need to send an ICMP Port Unreachable
			 * for a broadcast or multicast datgram.)
			 */
			udp_stat.udps_noport++;
			udp_stat.udps_noportmcast++;
			goto bad;
		}
		if (last->in6p_flags & IN6P_CONTROLOPTS
		    || last->in6p_socket->so_options & SO_TIMESTAMP)
			ip6_savecontrol(last, &opts, ip6, m);

		m_adj(m, off + sizeof(struct udphdr));
		so = last->in6p_socket;
		lwkt_gettoken(&so->so_rcv.ssb_token);
		if (ssb_appendaddr(&so->so_rcv, (struct sockaddr *)&udp_in6,
				   m, opts) == 0) {
			udp_stat.udps_fullsock++;
			lwkt_reltoken(&so->so_rcv.ssb_token);
			goto bad;
		}
		sorwakeup(so);
		lwkt_reltoken(&so->so_rcv.ssb_token);
		return IPPROTO_DONE;
	}
	/*
	 * Locate pcb for datagram.
	 */
	in6p = in6_pcblookup_hash(pcbinfo, &ip6->ip6_src, uh->uh_sport,
				  &ip6->ip6_dst, uh->uh_dport, 1,
				  m->m_pkthdr.rcvif);
	if (in6p == NULL) {
		if (log_in_vain) {
			char buf[INET6_ADDRSTRLEN];

			strcpy(buf, ip6_sprintf(&ip6->ip6_dst));
			log(LOG_INFO,
			    "Connection attempt to UDP [%s]:%d from [%s]:%d\n",
			    buf, ntohs(uh->uh_dport),
			    ip6_sprintf(&ip6->ip6_src), ntohs(uh->uh_sport));
		}
		udp_stat.udps_noport++;
		if (m->m_flags & M_MCAST) {
			kprintf("UDP6: M_MCAST is set in a unicast packet.\n");
			udp_stat.udps_noportmcast++;
			goto bad;
		}
		icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
		return IPPROTO_DONE;
	}

	/*
	 * Construct sockaddr format source address.
	 * Stuff source address and datagram in user buffer.
	 */
	init_sin6(&udp_in6, m); /* general init */
	udp_in6.sin6_port = uh->uh_sport;
	if (in6p->in6p_flags & IN6P_CONTROLOPTS
	    || in6p->in6p_socket->so_options & SO_TIMESTAMP)
		ip6_savecontrol(in6p, &opts, ip6, m);
	m_adj(m, off + sizeof(struct udphdr));
	so = in6p->in6p_socket;
	lwkt_gettoken(&so->so_rcv.ssb_token);
	if (ssb_appendaddr(&so->so_rcv, (struct sockaddr *)&udp_in6,
			   m, opts) == 0) {
		udp_stat.udps_fullsock++;
		lwkt_reltoken(&so->so_rcv.ssb_token);
		goto bad;
	}
	sorwakeup(so);
	lwkt_reltoken(&so->so_rcv.ssb_token);
	return IPPROTO_DONE;
bad:
	if (m)
		m_freem(m);
	if (opts)
		m_freem(opts);
	return IPPROTO_DONE;
}
示例#23
0
文件: net_udp.c 项目: mycp/mycp
static const char *udp_host_addr6(socket_udp *s)
{
#ifdef HAVE_IPv6
	static char		 hname[MAXHOSTNAMELEN];
	int 			 gai_err, newsock;
	struct addrinfo 	 hints, *ai;
	struct sockaddr_in6 	 local, addr6;
	int len = sizeof(local), result = 0;

	newsock=socket(AF_INET6, SOCK_DGRAM,0);
    memset ((char *)&addr6, 0, len);
    addr6.sin6_family = AF_INET6;
#ifdef HAVE_SIN6_LEN
    addr6.sin6_len    = len;
#endif
    bind (newsock, (struct sockaddr *) &addr6, len);
    addr6.sin6_addr = s->addr6;
    addr6.sin6_port = htons (s->rx_port);
    connect (newsock, (struct sockaddr *) &addr6, len);

    memset ((char *)&local, 0, len);
	if ((result = getsockname(newsock,(struct sockaddr *)&local, &len)) < 0){
		local.sin6_addr = in6addr_any;
		local.sin6_port = 0;
		debug_msg("getsockname failed\n");
	}

	close (newsock);

	if (IN6_IS_ADDR_UNSPECIFIED(&local.sin6_addr) || IN6_IS_ADDR_MULTICAST(&local.sin6_addr)) {
		if (gethostname(hname, MAXHOSTNAMELEN) != 0) {
			debug_msg("gethostname failed\n");
			abort();
		}
		
		hints.ai_protocol  = 0;
		hints.ai_flags     = 0;
		hints.ai_family    = AF_INET6;
		hints.ai_socktype  = SOCK_DGRAM;
		hints.ai_addrlen   = 0;
		hints.ai_canonname = NULL;
		hints.ai_addr      = NULL;
		hints.ai_next      = NULL;

		if ((gai_err = getaddrinfo(hname, NULL, &hints, &ai))) {
			debug_msg("getaddrinfo: %s: %s\n", hname, gai_strerror(gai_err));
			abort();
		}
		
		if (inet_ntopxp(AF_INET6, &(((struct sockaddr_in6 *)(ai->ai_addr))->sin6_addr), hname, MAXHOSTNAMELEN) == NULL) {
			debug_msg("inet_ntop: %s: \n", hname);
			abort();
		}
		freeaddrinfo(ai);
		return (const char*)hname;
	}
	if (inet_ntopxp(AF_INET6, &local.sin6_addr, hname, MAXHOSTNAMELEN) == NULL) {
		debug_msg("inet_ntop: %s: \n", hname);
		abort();
	}
	return (const char*)hname;
#else  /* HAVE_IPv6 */
	UNUSED(s);
	return "::";	/* The unspecified address... */
#endif /* HAVE_IPv6 */
}
示例#24
0
void us_mfa::handle_ipv6(int dev, uint8_t *buf, uint16_t len) {
	ip6_hdr *hdr = (ip6_hdr *)buf;

	if (len < sizeof(ip6_hdr))
		return;

	if (hdr->ip6_hlim <= 1)
		return;

	if (!IN6_IS_ADDR_MULTICAST(&hdr->ip6_dst))
		return;

	if (IN6_IS_ADDR_MULTICAST(&hdr->ip6_src) ||
		IN6_IS_ADDR_UNSPECIFIED(&hdr->ip6_src) ||
		IN6_IS_ADDR_LINKLOCAL(&hdr->ip6_src))
		return;

	/*
	 * Silently drop packets with scope reserved, interface-local or link-local.

	 * RFC 4291, Section 2.7.
	 * Nodes must not originate a packet to a multicast address whose scope
	 * field contains the reserved value 0; if such a packet is received, it
	 * must be silently dropped.
	 */
	if ((hdr->ip6_dst.s6_addr[1] & 0xc) == 0)
		return;

	/* Do we have a Hop by Hop header? */
	if (hdr->ip6_nxt == 0) {
		int spaceLeft = (((const ip6_ext *)(hdr + 1))->ip6e_len + 1) * 8;

		if (len < (sizeof(ip6_hdr) + spaceLeft))
			return;

		const uint8_t *ptr = buf + sizeof(ip6_hdr) + 2;

		while (spaceLeft > 0) {
			if (ptr[0] == 0) {
				/* Pad1 */
				spaceLeft--;
			} else {
				spaceLeft -= ptr[1] + 2;
				if (spaceLeft < 0) {
					/* Badly encoded HbH, discard packet */
					return;
				}

				if (ptr[0] != 1) {
					/* not PadN, check top-order 2 bits */

					switch (ptr[0] >> 6) {
					case 0:
						// skip option
						break;

					case 1:
						// discard packet
						return;

					case 2:
					case 3:
						// We handle 2 same as 3 as all of our destinations are
						// multicast

						// XXX send icmp parameter problem, code 2 to the source

						return;
					}
				}
			}
		}
	}
示例#25
0
/*
 *	Open a socket on the given IP and port.
 */
int fr_socket(fr_ipaddr_t *ipaddr, int port)
{
	int sockfd;
	struct sockaddr_storage salocal;
	socklen_t	salen;

	if ((port < 0) || (port > 65535)) {
		fr_strerror_printf("Port %d is out of allowed bounds", port);
		return -1;
	}

	sockfd = socket(ipaddr->af, SOCK_DGRAM, 0);
	if (sockfd < 0) {
		fr_strerror_printf("cannot open socket: %s", strerror(errno));
		return sockfd;
	}

#ifdef WITH_UDPFROMTO
	/*
	 *	Initialize udpfromto for all sockets.
	 */
	if (udpfromto_init(sockfd) != 0) {
		close(sockfd);
		fr_strerror_printf("cannot initialize udpfromto: %s", strerror(errno));
		return -1;
	}
#endif


	if (!fr_ipaddr2sockaddr(ipaddr, port, &salocal, &salen)) {
		return sockfd;
	}

#ifdef HAVE_STRUCT_SOCKADDR_IN6
	if (ipaddr->af == AF_INET6) {
		/*
		 *	Listening on '::' does NOT get you IPv4 to
		 *	IPv6 mapping.  You've got to listen on an IPv4
		 *	address, too.  This makes the rest of the server
		 *	design a little simpler.
		 */
#ifdef IPV6_V6ONLY

		if (IN6_IS_ADDR_UNSPECIFIED(&ipaddr->ipaddr.ip6addr)) {
			int on = 1;

			setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
				   (char *)&on, sizeof(on));
		}
#endif /* IPV6_V6ONLY */
	}
#endif /* HAVE_STRUCT_SOCKADDR_IN6 */

	if (ipaddr->af == AF_INET) {
		UNUSED int flag;
		
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
		/*
		 *	Disable PMTU discovery.  On Linux, this
		 *	also makes sure that the "don't fragment"
		 *	flag is zero.
		 */
		flag = IP_PMTUDISC_DONT;
		setsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER,
			   &flag, sizeof(flag));
#endif

#if defined(IP_DONTFRAG)
		/*
		 *	Ensure that the "don't fragment" flag is zero.
		 */
		flag = 0;
		setsockopt(sockfd, IPPROTO_IP, IP_DONTFRAG,
			   &flag, sizeof(flag));
#endif
	}

	if (bind(sockfd, (struct sockaddr *) &salocal, salen) < 0) {
		close(sockfd);
		fr_strerror_printf("cannot bind socket: %s", strerror(errno));
		return -1;
	}

	return sockfd;
}
示例#26
0
status_t
ipv6_setsockopt(net_protocol* _protocol, int level, int option,
	const void* value, int length)
{
	ipv6_protocol* protocol = (ipv6_protocol*)_protocol;

 	if (level == IPPROTO_IPV6) {
		// TODO: support more of these options

		if (option == IPV6_MULTICAST_IF) {
			if (length != sizeof(struct in6_addr))
				return B_BAD_VALUE;

			struct sockaddr_in6* address = new (std::nothrow) sockaddr_in6;
			if (address == NULL)
				return B_NO_MEMORY;

			if (user_memcpy(&address->sin6_addr, value, sizeof(in6_addr))
					!= B_OK) {
				delete address;
				return B_BAD_ADDRESS;
			}

			// Using the unspecifed address to remove the previous setting.
			if (IN6_IS_ADDR_UNSPECIFIED(&address->sin6_addr)) {
				delete address;
				delete protocol->multicast_address;
				protocol->multicast_address = NULL;
				return B_OK;
			}

			struct net_interface* interface
				= sDatalinkModule->get_interface_with_address(
					(sockaddr*)address);
			if (interface == NULL) {
				delete address;
				return EADDRNOTAVAIL;
			}

			delete protocol->multicast_address;
			protocol->multicast_address = (struct sockaddr*)address;
			return B_OK;
		}
		if (option == IPV6_MULTICAST_HOPS) {
			return set_int_option(protocol->multicast_time_to_live,
				value, length);
		}
		if (option == IPV6_MULTICAST_LOOP)
			return EOPNOTSUPP;
		if (option == IPV6_UNICAST_HOPS)
			return set_int_option(protocol->time_to_live, value, length);
		if (option == IPV6_V6ONLY)
			return EOPNOTSUPP;
		if (option == IPV6_RECVPKTINFO)
			return set_int_option(protocol->receive_pktinfo, value, length);
		if (option == IPV6_RECVHOPLIMIT)
			return set_int_option(protocol->receive_hoplimit, value, length);
		if (option == IPV6_JOIN_GROUP || option == IPV6_LEAVE_GROUP) {
			ipv6_mreq mreq;
			if (length != sizeof(ipv6_mreq))
				return B_BAD_VALUE;
			if (user_memcpy(&mreq, value, sizeof(ipv6_mreq)) != B_OK)
				return B_BAD_ADDRESS;

			return ipv6_delta_membership(protocol, option, mreq.ipv6mr_interface,
				&mreq.ipv6mr_multiaddr, NULL);
		}

		dprintf("IPv6::setsockopt(): set unknown option: %d\n", option);
		return ENOPROTOOPT;
	}

	return sSocketModule->set_option(protocol->socket, level, option,
		value, length);
}
示例#27
0
/*
 * Input an Neighbor Solicitation Message.
 *
 * Based on RFC 2461
 * Based on RFC 2462 (duplicated address detection)
 */
void
nd6_ns_input(struct mbuf *m, int off, int icmp6len)
{
	struct ifnet *ifp = m->m_pkthdr.rcvif;
	struct ifnet *cmpifp;
	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
	struct nd_neighbor_solicit *nd_ns;
	struct in6_addr saddr6 = ip6->ip6_src;
	struct in6_addr daddr6 = ip6->ip6_dst;
	struct in6_addr taddr6;
	struct in6_addr myaddr6;
	char *lladdr = NULL;
	struct ifaddr *ifa = NULL;
	int lladdrlen = 0;
	int anycast = 0, proxy = 0, tentative = 0;
	int tlladdr;
	union nd_opts ndopts;
	struct sockaddr_dl *proxydl = NULL;

	/*
	 * Collapse interfaces to the bridge for comparison and
	 * mac (llinfo) purposes.
	 */
	cmpifp = ifp;
	if (ifp->if_bridge)
		cmpifp = ifp->if_bridge;

#ifndef PULLDOWN_TEST
	IP6_EXTHDR_CHECK(m, off, icmp6len,);
	nd_ns = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off);
#else
	IP6_EXTHDR_GET(nd_ns, struct nd_neighbor_solicit *, m, off, icmp6len);
	if (nd_ns == NULL) {
		icmp6stat.icp6s_tooshort++;
		return;
	}
#endif
	ip6 = mtod(m, struct ip6_hdr *); /* adjust pointer for safety */
	taddr6 = nd_ns->nd_ns_target;

	if (ip6->ip6_hlim != 255) {
		nd6log((LOG_ERR,
		    "nd6_ns_input: invalid hlim (%d) from %s to %s on %s\n",
		    ip6->ip6_hlim, ip6_sprintf(&ip6->ip6_src),
		    ip6_sprintf(&ip6->ip6_dst), if_name(ifp)));
		goto bad;
	}

	if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) {
		/* dst has to be solicited node multicast address. */
		if (daddr6.s6_addr16[0] == IPV6_ADDR_INT16_MLL &&
		    /* don't check ifindex portion */
		    daddr6.s6_addr32[1] == 0 &&
		    daddr6.s6_addr32[2] == IPV6_ADDR_INT32_ONE &&
		    daddr6.s6_addr8[12] == 0xff) {
			; /* good */
		} else {
			nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet "
			    "(wrong ip6 dst)\n"));
			goto bad;
		}
	} else if (!nd6_onlink_ns_rfc4861) {
		/*
		 * Make sure the source address is from a neighbor's address.
		 *
		 * XXX probably only need to check cmpifp.
		 */
		if (in6ifa_ifplocaladdr(cmpifp, &saddr6) == NULL &&
		    in6ifa_ifplocaladdr(ifp, &saddr6) == NULL) {
			nd6log((LOG_INFO, "nd6_ns_input: "
			    "NS packet from non-neighbor\n"));
			goto bad;
		}
	}

	if (IN6_IS_ADDR_MULTICAST(&taddr6)) {
		nd6log((LOG_INFO, "nd6_ns_input: bad NS target (multicast)\n"));
		goto bad;
	}

	if (IN6_IS_SCOPE_LINKLOCAL(&taddr6))
		taddr6.s6_addr16[1] = htons(ifp->if_index);

	icmp6len -= sizeof(*nd_ns);
	nd6_option_init(nd_ns + 1, icmp6len, &ndopts);
	if (nd6_options(&ndopts) < 0) {
		nd6log((LOG_INFO,
		    "nd6_ns_input: invalid ND option, ignored\n"));
		/* nd6_options have incremented stats */
		goto freeit;
	}

	if (ndopts.nd_opts_src_lladdr) {
		lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
		lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
	}

	if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) && lladdr) {
		nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet "
		    "(link-layer address option)\n"));
		goto bad;
	}

	/*
	 * Attaching target link-layer address to the NA?
	 * (RFC 2461 7.2.4)
	 *
	 * NS IP dst is unicast/anycast			MUST NOT add
	 * NS IP dst is solicited-node multicast	MUST add
	 *
	 * In implementation, we add target link-layer address by default.
	 * We do not add one in MUST NOT cases.
	 */
#if 0 /* too much! */
	ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &daddr6);
	if (ifa && (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST))
		tlladdr = 0;
	else
#endif
	if (!IN6_IS_ADDR_MULTICAST(&daddr6))
		tlladdr = 0;
	else
		tlladdr = 1;

	/*
	 * Target address (taddr6) must be either:
	 * (1) Valid unicast/anycast address for my receiving interface.
	 * (2) Unicast or anycast address for which I'm offering proxy
	 *     service.
	 * (3) "tentative" address on which DAD is being performed.
	 */
	/* (1) and (3) check. */
#ifdef CARP
	if (ifp->if_carp)
		ifa = carp_iamatch6(ifp->if_carp, &taddr6);
	if (!ifa)
		ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
#else
	ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
#endif

	/*
	 * (2) Check proxying.  Requires ip6_forwarding to be turned on.
	 *
	 *     If the packet is anycast the target route must be on a
	 *     different interface because the anycast will get anything
	 *     on the current interface.
	 *
	 *     If the packet is unicast the target route may be on the
	 *     same interface.  If the gateway is a (typically manually
	 *     configured) link address we can directly offer it.
	 *     XXX for now we don't do this but instead offer ours and
	 *     presumably relay.
	 *
	 *     WARNING! Since this is a subnet proxy the interface proxying
	 *     the ND6 must be in promiscuous mode or it will not see the
	 *     solicited multicast requests for various hosts being proxied.
	 *
	 *     WARNING! Since this is a subnet proxy we have to treat bridge
	 *     interfaces as being the bridge itself so we do not proxy-nd6
	 *     between bridge interfaces (which are effectively switched).
	 *
	 *     (In the specific-host-proxy case via RTF_ANNOUNCE, which is
	 *     a bitch to configure, a specific multicast route is already
	 *     added for that host <-- NOT RECOMMENDED).
	 */
	if (!ifa && ip6_forwarding) {
		struct rtentry *rt;
		struct sockaddr_in6 tsin6;
		struct ifnet *rtifp;

		bzero(&tsin6, sizeof tsin6);
		tsin6.sin6_len = sizeof(struct sockaddr_in6);
		tsin6.sin6_family = AF_INET6;
		tsin6.sin6_addr = taddr6;

		rt = rtpurelookup((struct sockaddr *)&tsin6);
		rtifp = rt ? rt->rt_ifp : NULL;
		if (rtifp && rtifp->if_bridge)
			rtifp = rtifp->if_bridge;

		if (rt != NULL &&
		    (cmpifp != rtifp ||
		     (cmpifp == rtifp && (m->m_flags & M_MCAST) == 0))
		) {
			ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(cmpifp,
				IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
			nd6log((LOG_INFO,
			       "nd6_ns_input: nd6 proxy %s(%s)<-%s ifa %p\n",
			       if_name(cmpifp), if_name(ifp),
			       if_name(rtifp), ifa));
			if (ifa) {
				proxy = 1;
				/*
				 * Manual link address on same interface
				 * w/announce flag will proxy-arp using
				 * target mac, else our mac is used.
				 */
				if (cmpifp == rtifp &&
				    (rt->rt_flags & RTF_ANNOUNCE) &&
				    rt->rt_gateway->sa_family == AF_LINK) {
					proxydl = SDL(rt->rt_gateway);
				}
			}
		}
		if (rt != NULL)
			--rt->rt_refcnt;
	}
	if (ifa == NULL) {
		/*
		 * We've got an NS packet, and we don't have that adddress
		 * assigned for us.  We MUST silently ignore it.
		 * See RFC2461 7.2.3.
		 */
		goto freeit;
	}
	myaddr6 = *IFA_IN6(ifa);
	anycast = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST;
	tentative = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE;
	if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DUPLICATED)
		goto freeit;

	if (lladdr && ((cmpifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
		nd6log((LOG_INFO, "nd6_ns_input: lladdrlen mismatch for %s "
		    "(if %d, NS packet %d)\n",
		    ip6_sprintf(&taddr6), cmpifp->if_addrlen, lladdrlen - 2));
		goto bad;
	}

	if (IN6_ARE_ADDR_EQUAL(&myaddr6, &saddr6)) {
		nd6log((LOG_INFO, "nd6_ns_input: duplicate IP6 address %s\n",
		    ip6_sprintf(&saddr6)));
		goto freeit;
	}

	/*
	 * We have neighbor solicitation packet, with target address equals to
	 * one of my tentative address.
	 *
	 * src addr	how to process?
	 * ---		---
	 * multicast	of course, invalid (rejected in ip6_input)
	 * unicast	somebody is doing address resolution -> ignore
	 * unspec	dup address detection
	 *
	 * The processing is defined in RFC 2462.
	 */
	if (tentative) {
		/*
		 * If source address is unspecified address, it is for
		 * duplicated address detection.
		 *
		 * If not, the packet is for addess resolution;
		 * silently ignore it.
		 */
		if (IN6_IS_ADDR_UNSPECIFIED(&saddr6))
			nd6_dad_ns_input(ifa);

		goto freeit;
	}

	/*
	 * If the source address is unspecified address, entries must not
	 * be created or updated.
	 * It looks that sender is performing DAD.  Output NA toward
	 * all-node multicast address, to tell the sender that I'm using
	 * the address.
	 * S bit ("solicited") must be zero.
	 */
	if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) {
		saddr6 = kin6addr_linklocal_allnodes;
		saddr6.s6_addr16[1] = htons(cmpifp->if_index);
		nd6_na_output(cmpifp, &saddr6, &taddr6,
		    ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
		    (ip6_forwarding ? ND_NA_FLAG_ROUTER : 0),
		    tlladdr, (struct sockaddr *)proxydl);
		goto freeit;
	}

	nd6_cache_lladdr(cmpifp, &saddr6, lladdr, lladdrlen,
	    ND_NEIGHBOR_SOLICIT, 0);

	nd6_na_output(ifp, &saddr6, &taddr6,
	    ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
	    (ip6_forwarding ? ND_NA_FLAG_ROUTER : 0) | ND_NA_FLAG_SOLICITED,
	    tlladdr, (struct sockaddr *)proxydl);
freeit:
	m_freem(m);
	return;

bad:
	nd6log((LOG_ERR, "nd6_ns_input: src=%s\n", ip6_sprintf(&saddr6)));
	nd6log((LOG_ERR, "nd6_ns_input: dst=%s\n", ip6_sprintf(&daddr6)));
	nd6log((LOG_ERR, "nd6_ns_input: tgt=%s\n", ip6_sprintf(&taddr6)));
	icmp6stat.icp6s_badns++;
	m_freem(m);
}
示例#28
0
status_t
ipv6_send_routed_data(net_protocol* _protocol, struct net_route* route,
	net_buffer* buffer)
{
	if (route == NULL)
		return B_BAD_VALUE;

	ipv6_protocol* protocol = (ipv6_protocol*)_protocol;
	net_interface* interface = route->interface_address->interface;
	uint8 protocolNumber;
	if (protocol != NULL && protocol->socket != NULL)
		protocolNumber = protocol->socket->protocol;
	else
		protocolNumber = buffer->protocol;

	TRACE_SK(protocol, "SendRoutedData(%p, %p [%ld bytes])", route, buffer,
		buffer->size);

	sockaddr_in6& source = *(sockaddr_in6*)buffer->source;
	sockaddr_in6& destination = *(sockaddr_in6*)buffer->destination;

	buffer->flags &= ~(MSG_BCAST | MSG_MCAST);

	if (IN6_IS_ADDR_UNSPECIFIED(&destination.sin6_addr))
		return EDESTADDRREQ;

	if (IN6_IS_ADDR_MULTICAST(&destination.sin6_addr))
 		buffer->flags |= MSG_MCAST;

	uint16 dataLength = buffer->size;

	// Add IPv6 header

	NetBufferPrepend<ip6_hdr> header(buffer);
	if (header.Status() != B_OK)
		return header.Status();

	if (buffer->size > 0xffff)
		return EMSGSIZE;

	uint32 flowinfo = 0;
		// TODO: fill in the flow id from somewhere
	if (protocol) {
		// fill in traffic class
		flowinfo |= htonl(protocol->service_type << 20);
	}
	// set lower 28 bits
	header->ip6_flow = htonl(flowinfo) & IPV6_FLOWINFO_MASK;
	// set upper 4 bits
	header->ip6_vfc |= IPV6_VERSION;
	header->ip6_plen = htons(dataLength);
	header->ip6_nxt = protocolNumber;
	header->ip6_hlim = ip6_select_hoplimit(protocol, buffer);
	memcpy(&header->ip6_src, &source.sin6_addr, sizeof(in6_addr));
	memcpy(&header->ip6_dst, &destination.sin6_addr, sizeof(in6_addr));

	header.Sync();

	// write the checksum for ICMPv6 sockets
	if (protocolNumber == IPPROTO_ICMPV6
		&& dataLength >= sizeof(struct icmp6_hdr)) {
		NetBufferField<uint16,
			sizeof(ip6_hdr) + offsetof(icmp6_hdr, icmp6_cksum)>
			icmpChecksum(buffer);
		// first make sure the existing checksum is zero
		*icmpChecksum = 0;
		icmpChecksum.Sync();

		uint16 checksum = gBufferModule->checksum(buffer, sizeof(ip6_hdr),
			buffer->size - sizeof(ip6_hdr), false);
		checksum = ipv6_checksum(&header->ip6_src,
			&header->ip6_dst, dataLength, protocolNumber,
			checksum);
		*icmpChecksum = checksum;
	}

	char addrbuf[INET6_ADDRSTRLEN];
	TRACE_SK(protocol, "  SendRoutedData(): destination: %s",
		ip6_sprintf(&destination.sin6_addr, addrbuf));

	uint32 mtu = route->mtu ? route->mtu : interface->mtu;
	if (buffer->size > mtu) {
		// we need to fragment the packet
		return send_fragments(protocol, route, buffer, mtu);
	}

	return sDatalinkModule->send_routed_data(route, buffer);
}
示例#29
0
os_result
os_sockQueryIPv6Interfaces(
    os_ifAttributes *ifList,
    os_uint32 listSize,
    os_uint32 *validElements)
{
    os_result result = os_resultSuccess;
    os_result addressInfoResult =0;
    unsigned long returnedBytes;
    unsigned int listIndex;
    os_socket ifcs;
    int retVal, done;
    char* errorMessage;
    os_sockErrno errNo;

    PIP_ADAPTER_ADDRESSES pAddresses = NULL;
    PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
    PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
    unsigned long outBufLen = 0;
    /* Set the flags to pass to GetAdaptersAddresses*/
    unsigned long flags = GAA_FLAG_INCLUDE_PREFIX;
    int i = 0;

    /* IPv6 addition */
    SOCKET_ADDRESS_LIST* ipv6InterfaceList;

    *validElements = 0;
    listIndex = 0;

    outBufLen = sizeof (IP_ADAPTER_ADDRESSES);
    pAddresses = (IP_ADAPTER_ADDRESSES *) os_malloc(outBufLen);
    if (GetAdaptersAddresses(AF_INET6, flags, NULL, pAddresses, &outBufLen)
                                == ERROR_BUFFER_OVERFLOW) {
        os_free(pAddresses);
        pAddresses = (IP_ADAPTER_ADDRESSES *) os_malloc(outBufLen);
    }
    addressInfoResult = GetAdaptersAddresses(AF_INET6, flags, NULL, pAddresses, &outBufLen);

    /* Now do the IPv6 interfaces */
    ifcs = os_sockNew (AF_INET6, SOCK_DGRAM);

    if (ifcs != INVALID_SOCKET)
    {
        /* List returned from this control code query will need to be sized as 1 * SOCKET_ADDRESS_LIST + n * SOCKET_ADDRESS */
        ipv6InterfaceList = os_malloc(sizeof(SOCKET_ADDRESS_LIST) + ((MAX_INTERFACES - 1) * sizeof(SOCKET_ADDRESS)));
        memset(ipv6InterfaceList, 0, sizeof(SOCKET_ADDRESS_LIST) + ((MAX_INTERFACES - 1) * sizeof(SOCKET_ADDRESS)));
        retVal = WSAIoctl(ifcs, SIO_ADDRESS_LIST_QUERY, NULL, 0, ipv6InterfaceList,
                            sizeof(SOCKET_ADDRESS_LIST) + ((MAX_INTERFACES - 1) * sizeof(SOCKET_ADDRESS)),
                            &returnedBytes, 0, 0);

        if (retVal == SOCKET_ERROR && WSAGetLastError() == WSAEFAULT)
        {
            /* The buffer wasn't big enough. returnedBytes will now contain the required size
            so we can reallocate & try again */
            os_free(ipv6InterfaceList);
            ipv6InterfaceList = os_malloc(returnedBytes);
            memset(ipv6InterfaceList, 0, returnedBytes);
            retVal = WSAIoctl(ifcs, SIO_ADDRESS_LIST_QUERY, NULL, 0, ipv6InterfaceList,
                                returnedBytes, &returnedBytes, 0, 0);
        }

        if (retVal == SOCKET_ERROR)
        {
            errNo = os_sockError();
            errorMessage = os_sockErrnoToString(errNo);
            os_report(OS_ERROR, "os_sockQueryInterfaces", __FILE__, __LINE__, 0,
                      "Socket error calling WSAIoctl for IPv6 interfaces: %d %s", errNo, errorMessage);
            os_free(errorMessage);
            /* @todo Is it right to return a fail here ? Need to check on box w/ no IPv6 interfaces */
            result = os_resultFail;
        }
        else
        {
            for (i = 0; i < ipv6InterfaceList->iAddressCount; ++i)
            {
                if (ipv6InterfaceList->Address[i].lpSockaddr->sa_family == AF_INET6
                    && ! (IN6_IS_ADDR_UNSPECIFIED(&((os_sockaddr_in6 *)&ipv6InterfaceList->Address[i].lpSockaddr)->sin6_addr)))
                {
                    done = 0;
                    if (addressInfoResult == NO_ERROR) {
                        pCurrAddresses = pAddresses;
                        while (pCurrAddresses && !done) {
                            /* adapter needs to be enabled*/
                            if (pCurrAddresses->OperStatus == IfOperStatusUp) {
                                pUnicast = pCurrAddresses->FirstUnicastAddress;
                                while (pUnicast && !done) {
                                    /* check if interface ip matches adapter ip */
                                    if (os_sockaddrIPAddressEqual((os_sockaddr*) ipv6InterfaceList->Address[i].lpSockaddr,
                                                                   (os_sockaddr*) pUnicast->Address.lpSockaddr))
                                    {
                                        snprintf(ifList[listIndex].name,
                                                  OS_IFNAMESIZE, "%wS",
                                                  pCurrAddresses->FriendlyName);
                                        ifList[listIndex].interfaceIndexNo =
                                            (os_uint) pCurrAddresses->Ipv6IfIndex;
                                        done = 1;
                                    }
                                    pUnicast = pUnicast->Next;
                                }
                            }
                            pCurrAddresses = pCurrAddresses->Next;
                        }
                    }

                    /* if no name was found set this interface name to string
                    representation of the IPv6 address */
                    if (!done) {
                        os_sockaddrAddressToString((os_sockaddr*) ipv6InterfaceList->Address[i].lpSockaddr,
                                                    ifList[listIndex].name,
                                                    OS_IFNAMESIZE);
                        os_report(OS_WARNING,
                                 "os_sockQueryInterfaces", __FILE__, __LINE__, 0,
                                 "Unable to determine IPv6 adapter name. Setting instead to adapter address %s",
                                 ifList[listIndex].name);
                    }

                    ifList[listIndex].flags = 0;
                    ifList[listIndex].address = *((os_sockaddr_storage*) ipv6InterfaceList->Address[i].lpSockaddr);
                    listIndex++;
                    ++(*validElements);
                }
            }
        }
        os_sockFree (ifcs);
    }

    if (addressInfoResult == NO_ERROR) {
        os_free(pAddresses);
    }

    return result;
}
示例#30
0
void
ripng_print(netdissect_options *ndo, const u_char *dat, unsigned int length)
{
	register const struct rip6 *rp = (const struct rip6 *)dat;
	register const struct netinfo6 *ni;
	unsigned int length_left;
	u_int j;

	ND_TCHECK(rp->rip6_cmd);
	switch (rp->rip6_cmd) {

	case RIP6_REQUEST:
		length_left = length;
		if (length_left < (sizeof(struct rip6) - sizeof(struct netinfo6)))
			goto trunc;
		length_left -= (sizeof(struct rip6) - sizeof(struct netinfo6));
 		j = length_left / sizeof(*ni);
		if (j == 1) {
			ND_TCHECK(rp->rip6_nets);
			if (rp->rip6_nets->rip6_metric == HOPCNT_INFINITY6
			    &&  IN6_IS_ADDR_UNSPECIFIED(&rp->rip6_nets->rip6_dest)) {
				ND_PRINT((ndo, " ripng-req dump"));
				break;
			}
		}
		if (j * sizeof(*ni) != length_left)
			ND_PRINT((ndo, " ripng-req %u[%u]:", j, length));
		else
			ND_PRINT((ndo, " ripng-req %u:", j));
		for (ni = rp->rip6_nets; length_left >= sizeof(*ni);
		    length_left -= sizeof(*ni), ++ni) {
			ND_TCHECK(*ni);
			if (ndo->ndo_vflag > 1)
				ND_PRINT((ndo, "\n\t"));
			else
				ND_PRINT((ndo, " "));
			rip6_entry_print(ndo, ni, 0);
		}
		if (length_left != 0)
			goto trunc;
		break;
	case RIP6_RESPONSE:
		length_left = length;
		if (length_left < (sizeof(struct rip6) - sizeof(struct netinfo6)))
			goto trunc;
		length_left -= (sizeof(struct rip6) - sizeof(struct netinfo6));
		j = length_left / sizeof(*ni);
		if (j * sizeof(*ni) != length_left)
			ND_PRINT((ndo, " ripng-resp %d[%u]:", j, length));
		else
			ND_PRINT((ndo, " ripng-resp %d:", j));
		for (ni = rp->rip6_nets; length_left >= sizeof(*ni);
		    length_left -= sizeof(*ni), ++ni) {
			ND_TCHECK(*ni);
			if (ndo->ndo_vflag > 1)
				ND_PRINT((ndo, "\n\t"));
			else
				ND_PRINT((ndo, " "));
			rip6_entry_print(ndo, ni, ni->rip6_metric);
		}
		if (length_left != 0)
			goto trunc;
		break;
	default:
		ND_PRINT((ndo, " ripng-%d ?? %u", rp->rip6_cmd, length));
		break;
	}
	ND_TCHECK(rp->rip6_vers);
	if (rp->rip6_vers != RIP6_VERSION)
		ND_PRINT((ndo, " [vers %d]", rp->rip6_vers));
	return;

trunc:
	ND_PRINT((ndo, "[|ripng]"));
	return;
}