示例#1
0
static int get_req_size(struct arglist *def)
{
	char *gro = uml_vector_fetch_arg(def, "gro");
	long result;

	if (gro != NULL) {
		if (kstrtoul(gro, 10, &result) == 0) {
			if (result > 0)
				return 65536;
		}
	}
	return get_mtu(def) + ETH_HEADER_OTHER +
		get_headroom(def) + SAFETY_MARGIN;
}
示例#2
0
文件: lxc_user_nic.c 项目: 4b42/lxc
static bool create_nic(char *nic, char *br, int pid, char **cnic)
{
	char *veth1buf, *veth2buf;
	veth1buf = alloca(IFNAMSIZ);
	veth2buf = alloca(IFNAMSIZ);
	int ret, mtu;

	ret = snprintf(veth1buf, IFNAMSIZ, "%s", nic);
	if (ret < 0 || ret >= IFNAMSIZ) {
		fprintf(stderr, "host nic name too long\n");
		return false;
	}

	/* create the nics */
	if (instantiate_veth(veth1buf, &veth2buf) < 0) {
		fprintf(stderr, "Error creating veth tunnel\n");
		return false;
	}

	if (strcmp(br, "none") != 0) {
		/* copy the bridge's mtu to both ends */
		mtu = get_mtu(br);
		if (mtu != -1) {
			if (lxc_netdev_set_mtu(veth1buf, mtu) < 0 ||
					lxc_netdev_set_mtu(veth2buf, mtu) < 0) {
				fprintf(stderr, "Failed setting mtu\n");
				goto out_del;
			}
		}

		/* attach veth1 to bridge */
		if (lxc_bridge_attach(lxcpath, lxcname, br, veth1buf) < 0) {
			fprintf(stderr, "Error attaching %s to %s\n", veth1buf, br);
			goto out_del;
		}
	}

	/* pass veth2 to target netns */
	ret = lxc_netdev_move_by_name(veth2buf, pid, NULL);
	if (ret < 0) {
		fprintf(stderr, "Error moving %s to netns %d\n", veth2buf, pid);
		goto out_del;
	}
	*cnic = strdup(veth2buf);
	return true;

out_del:
	lxc_netdev_delete_by_name(veth1buf);
	return false;
}
示例#3
0
/*
 * Check whether an interface is up and ready for service
 *
 * Arguments:
 *	aip	pointer to network interface block
 *
 * Returns:
 *	0	interface not ready, errno has reason
 *	1	interface is ready to go (interface block is updated)
 *
 */
int
atmarp_if_ready(Atmarp_intf *aip)
{
	int			i, len, mtu, rc, sel;
	Atmarp			*aap = NULL;
	struct atminfreq	air;
	struct air_netif_rsp	*netif_rsp = NULL;
	struct air_int_rsp	*intf_rsp = NULL;
	struct sockaddr_in	*ip_addr;
	struct sockaddr_in	subnet_mask;
	Atm_addr_nsap		*anp;

	/*
	 * Get the IP address and physical interface name
	 * associated with the network interface
	 */
	UM_ZERO(&air, sizeof(struct atminfreq));
	air.air_opcode = AIOCS_INF_NIF;
	strcpy(air.air_netif_intf, aip->ai_intf);
	len = do_info_ioctl(&air, sizeof(struct air_netif_rsp));
	if (len <= 0) {
		goto if_ready_fail;
	}
	netif_rsp = (struct air_netif_rsp *)air.air_buf_addr;

	ip_addr = (struct sockaddr_in *)&netif_rsp->anp_proto_addr;
	if (ip_addr->sin_family != AF_INET ||
			ip_addr->sin_addr.s_addr == 0) {
		errno = EAFNOSUPPORT;
		goto if_ready_fail;
	}

	/*
	 * Get the MTU for the network interface
	 */
	mtu = get_mtu(aip->ai_intf);
	if (mtu < 0) {
		goto if_ready_fail;
	}


	/*
	 * Get the subnet mask associated with the
	 * network interface
	 */
	rc = get_subnet_mask(aip->ai_intf, &subnet_mask);
	if (rc || subnet_mask.sin_family != AF_INET) {
		goto if_ready_fail;
	}

	/*
	 * Get physical interface information
	 */
	UM_ZERO(&air, sizeof(struct atminfreq));
	air.air_opcode = AIOCS_INF_INT;
	strcpy(air.air_int_intf, netif_rsp->anp_phy_intf);
	len = do_info_ioctl(&air, sizeof(struct air_int_rsp));
	if (len <= 0) {
		goto if_ready_fail;
	}
	intf_rsp = (struct air_int_rsp *)air.air_buf_addr;

	/*
	 * Check the signalling manager
	 */
	if (intf_rsp->anp_sig_proto != ATM_SIG_UNI30 &&
			intf_rsp->anp_sig_proto != ATM_SIG_UNI31 &&
			intf_rsp->anp_sig_proto != ATM_SIG_UNI40) {
		errno = EINVAL;
		goto if_ready_fail;
	}

	/*
	 * Check the interface state
	 */
	if (intf_rsp->anp_sig_state != UNISIG_ACTIVE) {
		errno = EINVAL;
		goto if_ready_fail;
	}

	/*
	 * Check the address format
	 */
	if (intf_rsp->anp_addr.address_format != T_ATM_ENDSYS_ADDR &&
			!(intf_rsp->anp_addr.address_format ==
				T_ATM_E164_ADDR &&
			intf_rsp->anp_subaddr.address_format ==
				T_ATM_ENDSYS_ADDR)) {
		errno = EINVAL;
		goto if_ready_fail;
	}

	/*
	 * Find the selector byte value for the interface
	 */
	for (i=0; i<strlen(aip->ai_intf); i++) {
		if (aip->ai_intf[i] >= '0' &&
				aip->ai_intf[i] <= '9')
			break;
	}
	sel = atoi(&aip->ai_intf[i]);

	/*
	 * Make sure we're the server for this interface's LIS
	 */
	if (!atmarp_is_server(aip)) {
		rc = EINVAL;
		goto if_ready_fail;
	}

	/*
	 * If we already have the interface active and the address
	 * hasn't changed, return
	 */
	if (aip->ai_state != AI_STATE_NULL &&
			bcmp((caddr_t) &((struct sockaddr_in *)
				&netif_rsp->anp_proto_addr)->sin_addr,
				(caddr_t)&aip->ai_ip_addr,
				sizeof(aip->ai_ip_addr)) == 0 &&
			ATM_ADDR_EQUAL(&intf_rsp->anp_addr,
				&aip->ai_atm_addr) &&
			ATM_ADDR_EQUAL(&intf_rsp->anp_subaddr,
				&aip->ai_atm_subaddr)) {
		return(1);
	}

	/*
	 * Delete any existing ATMARP cache entry for this interface
	 */
	ATMARP_LOOKUP(aip, aip->ai_ip_addr.s_addr, aap);
	if (aap) {
		ATMARP_DELETE(aip, aap);
		UM_FREE(aap);
	}

	/*
	 * Update the interface entry
	 */
	aip->ai_ip_addr = ((struct sockaddr_in *)
			&netif_rsp->anp_proto_addr)->sin_addr;
	aip->ai_subnet_mask = subnet_mask.sin_addr;
	aip->ai_mtu = mtu + 8;
	ATM_ADDR_COPY(&intf_rsp->anp_addr,
			&aip->ai_atm_addr);
	ATM_ADDR_COPY(&intf_rsp->anp_subaddr,
			&aip->ai_atm_subaddr);
	anp = (Atm_addr_nsap *)aip->ai_atm_addr.address;
	if (aip->ai_atm_addr.address_format == T_ATM_ENDSYS_ADDR) {
		anp->aan_sel = sel;
	} else if (aip->ai_atm_addr.address_format ==
				T_ATM_E164_ADDR &&
			aip->ai_atm_subaddr.address_format ==
				T_ATM_ENDSYS_ADDR) {
		anp->aan_sel = sel;
	}

	/*
	 * Get a new ATMARP cache for the interface
	 */
	aap = (Atmarp *)UM_ALLOC(sizeof(Atmarp));
	if (!aap) {
		atmarp_mem_err("atmarp_if_ready: sizeof(Atmarp)");
	}
	UM_ZERO(aap, sizeof(Atmarp));
	
	/*
	 * Fill out the entry
	 */
	aap->aa_dstip = aip->ai_ip_addr;
	ATM_ADDR_COPY(&intf_rsp->anp_addr, &aap->aa_dstatm);
	ATM_ADDR_COPY(&intf_rsp->anp_subaddr,
			&aap->aa_dstatmsub);
	aap->aa_key.key_len = SCSP_ATMARP_KEY_LEN;
	scsp_cache_key(&aap->aa_dstatm, &aap->aa_dstip,
			SCSP_ATMARP_KEY_LEN, aap->aa_key.key);
	aap->aa_oid.id_len = SCSP_ATMARP_ID_LEN;
	aap->aa_seq = SCSP_CSA_SEQ_MIN;
	UM_COPY(&aap->aa_dstip.s_addr, aap->aa_oid.id,
			SCSP_ATMARP_ID_LEN);
	aap->aa_intf = aip;
	aap->aa_flags = AAF_SERVER;
	aap->aa_origin = UAO_LOCAL;

	/*
	 * Add the entry to the cache
	 */
	ATMARP_ADD(aip, aap);
	
	/*
	 * Free dynamic data
	 */
	UM_FREE(netif_rsp);
	UM_FREE(intf_rsp);

	return(1);

if_ready_fail:
	if (netif_rsp)
		UM_FREE(netif_rsp);
	if (intf_rsp)
		UM_FREE(intf_rsp);

	return(0);
}
示例#4
0
int check_tun(const struct arguments *args,
              const struct epoll_event *ev,
              const int epoll_fd,
              int sessions, int maxsessions) {
    // Check tun error
    if (ev->events & EPOLLERR) {
        log_android(ANDROID_LOG_ERROR, "tun %d exception", args->tun);
        if (fcntl(args->tun, F_GETFL) < 0) {
            log_android(ANDROID_LOG_ERROR, "fcntl tun %d F_GETFL error %d: %s",
                        args->tun, errno, strerror(errno));
            report_exit(args, "fcntl tun %d F_GETFL error %d: %s",
                        args->tun, errno, strerror(errno));
        } else
            report_exit(args, "tun %d exception", args->tun);
        return -1;
    }

    // Check tun read
    if (ev->events & EPOLLIN) {
        uint8_t *buffer = malloc(get_mtu());
        ssize_t length = read(args->tun, buffer, get_mtu());
        if (length < 0) {
            free(buffer);

            log_android(ANDROID_LOG_ERROR, "tun %d read error %d: %s",
                        args->tun, errno, strerror(errno));
            if (errno == EINTR || errno == EAGAIN)
                // Retry later
                return 0;
            else {
                report_exit(args, "tun %d read error %d: %s",
                            args->tun, errno, strerror(errno));
                return -1;
            }
        }
        else if (length > 0) {
            // Write pcap record
            if (pcap_file != NULL)
                write_pcap_rec(buffer, (size_t) length);

            if (length > max_tun_msg) {
                max_tun_msg = length;
                log_android(ANDROID_LOG_WARN, "Maximum tun msg length %d", max_tun_msg);
            }

            // Handle IP from tun
            handle_ip(args, buffer, (size_t) length, epoll_fd, sessions, maxsessions);

            free(buffer);
        }
        else {
            // tun eof
            free(buffer);

            log_android(ANDROID_LOG_ERROR, "tun %d empty read", args->tun);
            report_exit(args, "tun %d empty read", args->tun);
            return -1;
        }
    }

    return 0;
}
示例#5
0
uint16_t get_default_mss(int version) {
    if (version == 4)
        return (uint16_t) (get_mtu() - sizeof(struct iphdr) - sizeof(struct tcphdr));
    else
        return (uint16_t) (get_mtu() - sizeof(struct ip6_hdr) - sizeof(struct tcphdr));
}
示例#6
0
文件: lxc_user_nic.c 项目: d4s/lxc
static int create_nic(char *nic, char *br, int pid, char **cnic)
{
	char veth1buf[IFNAMSIZ], veth2buf[IFNAMSIZ];
	int mtu, ret;

	ret = snprintf(veth1buf, IFNAMSIZ, "%s", nic);
	if (ret < 0 || ret >= IFNAMSIZ) {
		usernic_error("%s", "Could not create nic name\n");
		return -1;
	}

	ret = snprintf(veth2buf, IFNAMSIZ, "%sp", veth1buf);
	if (ret < 0 || ret >= IFNAMSIZ) {
		usernic_error("%s\n", "Could not create nic name");
		return -1;
	}
	/* create the nics */
	ret = instantiate_veth(veth1buf, veth2buf);
	if (ret < 0) {
		usernic_error("%s", "Error creating veth tunnel\n");
		return -1;
	}

	if (strcmp(br, "none")) {
		/* copy the bridge's mtu to both ends */
		mtu = get_mtu(br);
		if (mtu > 0) {
			ret = lxc_netdev_set_mtu(veth1buf, mtu);
			if (ret < 0) {
				usernic_error("Failed to set mtu to %d on %s\n",
					      mtu, veth1buf);
				goto out_del;
			}

			ret = lxc_netdev_set_mtu(veth2buf, mtu);
			if (ret < 0) {
				usernic_error("Failed to set mtu to %d on %s\n",
					      mtu, veth2buf);
				goto out_del;
			}
		}

		/* attach veth1 to bridge */
		ret = lxc_bridge_attach(br, veth1buf);
		if (ret < 0) {
			usernic_error("Error attaching %s to %s\n", veth1buf, br);
			goto out_del;
		}
	}

	/* pass veth2 to target netns */
	ret = lxc_netdev_move_by_name(veth2buf, pid, NULL);
	if (ret < 0) {
		usernic_error("Error moving %s to network namespace of %d\n",
			      veth2buf, pid);
		goto out_del;
	}

	*cnic = strdup(veth2buf);
	if (!*cnic) {
		usernic_error("Failed to copy string \"%s\"\n", veth2buf);
		return -1;
	}

	return 0;

out_del:
	lxc_netdev_delete_by_name(veth1buf);
	return -1;
}
示例#7
0
size_t send_message (const interface_t *iface, const dhcp_t *dhcp,
					 unsigned long xid, char type,
					 const options_t *options)
{
	dhcpmessage_t message;
	struct udp_dhcp_packet packet;
	unsigned char *m = (unsigned char *) &message;
	unsigned char *p = (unsigned char *) &message.options;
	unsigned char *n_params = NULL;
	unsigned long l;
	struct in_addr from;
	struct in_addr to;
	long up = uptime() - iface->start_uptime;
	uint32_t ul;
	uint16_t sz;
	unsigned int message_length;

	if (!iface || !options || !dhcp)
		return -1;

	memset (&from, 0, sizeof (from));
	memset (&to, 0, sizeof (to));

	if (type == DHCP_RELEASE)
		to.s_addr = dhcp->serveraddress.s_addr;

	memset (&message, 0, sizeof (dhcpmessage_t));

	if (type == DHCP_INFORM ||
		type == DHCP_RELEASE ||
		type == DHCP_REQUEST)
	{
		message.ciaddr = iface->previous_address.s_addr;
		from.s_addr = iface->previous_address.s_addr;
	}

	message.op = DHCP_BOOTREQUEST;
	message.hwtype = iface->family;
	switch (iface->family) {
		case ARPHRD_ETHER:
		case ARPHRD_IEEE802:
			message.hwlen = ETHER_ADDR_LEN;
			memcpy (&message.chaddr, &iface->hwaddr, ETHER_ADDR_LEN);
			break;
		case ARPHRD_IEEE1394:
		case ARPHRD_INFINIBAND:
			if (message.ciaddr == 0)
				message.flags = htons (BROADCAST_FLAG);
			message.hwlen = 0;
			break;
		default:
			logger (LOG_ERR, "dhcp: unknown hardware type %d", iface->family);
	}

	if (up < 0 || up > UINT16_MAX)
		message.secs = htons ((short) UINT16_MAX);
	else
		message.secs = htons (up);
	message.xid = xid;
	message.cookie = htonl (MAGIC_COOKIE);

	*p++ = DHCP_MESSAGETYPE; 
	*p++ = 1;
	*p++ = type;

	if (type == DHCP_REQUEST) {
		*p++ = DHCP_MAXMESSAGESIZE;
		*p++ = 2;
		sz = get_mtu (iface->name);
		if (sz < MTU_MIN) {
			if (set_mtu (iface->name, MTU_MIN) == 0)
				sz = MTU_MIN;
		}
		sz = htons (sz);
		memcpy (p, &sz, 2);
		p += 2;
	}

#define PUTADDR(_type, _val) \
	{ \
		*p++ = _type; \
		*p++ = 4; \
		memcpy (p, &_val.s_addr, 4); \
		p += 4; \
	}
	if (dhcp->address.s_addr != 0 && iface->previous_address.s_addr == 0
		&& type != DHCP_RELEASE)
		PUTADDR (DHCP_ADDRESS, dhcp->address);

	if (dhcp->serveraddress.s_addr != 0 && dhcp->address.s_addr !=0 &&
		(iface->previous_address.s_addr == 0 || type == DHCP_RELEASE))
		PUTADDR (DHCP_SERVERIDENTIFIER, dhcp->serveraddress);
#undef PUTADDR

	if (type == DHCP_REQUEST || type == DHCP_DISCOVER) {
		if (options->leasetime != 0) {
			*p++ = DHCP_LEASETIME;
			*p++ = 4;
			ul = htonl (options->leasetime);
			memcpy (p, &ul, 4);
			p += 4;
		}
	}

	if (type == DHCP_DISCOVER || type == DHCP_INFORM || type == DHCP_REQUEST) {
		*p++ = DHCP_PARAMETERREQUESTLIST;
		n_params = p;
		*p++ = 0;

		/* Only request DNSSERVER in discover to keep the packets small.
		   RFC2131 Section 3.5 states that the REQUEST must include the list
		   from the DISCOVER message, so I think we can safely do this. */

		if (type == DHCP_DISCOVER)
			*p++ = DHCP_DNSSERVER;
		else {
			*p++ = DHCP_RENEWALTIME;
			*p++ = DHCP_REBINDTIME;
			*p++ = DHCP_NETMASK;
			*p++ = DHCP_BROADCAST;
			*p++ = DHCP_CSR;
			/* RFC 3442 states classless static routes should be before routers
			 * and static routes as classless static routes override them both */
			*p++ = DHCP_STATICROUTE;
			*p++ = DHCP_ROUTERS;
			*p++ = DHCP_HOSTNAME;
			*p++ = DHCP_DNSSEARCH;
			*p++ = DHCP_DNSDOMAIN;
			*p++ = DHCP_DNSSERVER;
			*p++ = DHCP_NISDOMAIN;
			*p++ = DHCP_NISSERVER;
			*p++ = DHCP_NTPSERVER;
			*p++ = DHCP_MTU;
			*p++ = DHCP_ROOTPATH;
			/* These parameters were requested by dhcpcd-2.0 and earlier
			   but we never did anything with them */
			/*    *p++ = DHCP_DEFAULTIPTTL;
			 *p++ = DHCP_MASKDISCOVERY;
			 *p++ = DHCP_ROUTERDISCOVERY; */
		}

		*n_params = p - n_params - 1;

		if (*options->hostname) {
			if (options->fqdn == FQDN_DISABLE) {
				*p++ = DHCP_HOSTNAME;
				*p++ = l = strlen (options->hostname);
				memcpy (p, options->hostname, l);
				p += l;
			} else {
				/* Draft IETF DHC-FQDN option (81) */
				*p++ = DHCP_FQDN;
				*p++ = (l = strlen (options->hostname)) + 3;
				/* Flags: 0000NEOS
				 * S: 1 => Client requests Server to update A RR in DNS as well as PTR
				 * O: 1 => Server indicates to client that DNS has been updated
				 * E: 1 => Name data is DNS format
				 * N: 1 => Client requests Server to not update DNS
				 */
				*p++ = options->fqdn & 0x9;
				*p++ = 0; /* rcode1, response from DNS server for PTR RR */
				*p++ = 0; /* rcode2, response from DNS server for A RR if S=1 */
				memcpy (p, options->hostname, l);
				p += l;
			}
		}
	}

	if (type != DHCP_DECLINE && type != DHCP_RELEASE) {
		if (options->userclass_len > 0) {
			*p++ = DHCP_USERCLASS;
			*p++ = options->userclass_len;
			memcpy (p, &options->userclass, options->userclass_len);
			p += options->userclass_len;
		}

		*p++ = DHCP_CLASSID;
		*p++ = l = strlen (options->classid);
		memcpy (p, options->classid, l);
		p += l;
	}

	*p++ = DHCP_CLIENTID;
	if (options->clientid[0]) {
		l = strlen (options->clientid);
		*p++ = l + 1;
		*p++ = 0; /* string */
		memcpy (p, options->clientid, l);
		p += l;
	} else {
		*p++ = iface->hwlen + 1;
		*p++ = iface->family;
		memcpy (p, iface->hwaddr, iface->hwlen);
		p += iface->hwlen;
	}

#ifdef BOOTP_MESSAGE_LENTH_MIN
	/* Some crappy DHCP servers think they have to obey the BOOTP minimum
	 * messag length. They are wrong, but we should still cater for them */
	while (p - m < BOOTP_MESSAGE_LENTH_MIN - 1)
		*p++ = DHCP_PAD;
#endif

	*p++ = DHCP_END;
	message_length = p - m;

	memset (&packet, 0, sizeof (struct udp_dhcp_packet));
	make_dhcp_packet (&packet, (unsigned char *) &message, message_length,
					  from, to);

	logger (LOG_DEBUG, "sending %s with xid 0x%lx", dhcp_message[(int) type], xid);
	return send_packet (iface, ETHERTYPE_IP, (unsigned char *) &packet,
						message_length + sizeof (struct ip) +
						sizeof (struct udphdr));
}
ssize_t
make_message(struct dhcp_message **message,
	     const struct interface *iface, const struct dhcp_lease *lease,
	     uint32_t xid, uint8_t type, const struct options *options)
{
	struct dhcp_message *dhcp;
	uint8_t *m, *lp, *p;
	uint8_t *n_params = NULL;
	time_t up = uptime() - iface->start_uptime;
	uint32_t ul;
	uint16_t sz;
	const struct dhcp_opt *opt;
	size_t len;
	const char *hp;

	dhcp = xzalloc(sizeof (*dhcp));
	m = (uint8_t *)dhcp;
	p = dhcp->options;

	if ((type == DHCP_INFORM ||
	     type == DHCP_RELEASE ||
	     type == DHCP_REQUEST) &&
	    !IN_LINKLOCAL(ntohl(iface->addr.s_addr)))
	{
		dhcp->ciaddr = iface->addr.s_addr;
		/* Just incase we haven't actually configured the address yet */
		if (type == DHCP_INFORM && iface->addr.s_addr == 0)
			dhcp->ciaddr = lease->addr.s_addr;
		/* Zero the address if we're currently on a different subnet */
		if (type == DHCP_REQUEST &&
		    iface->net.s_addr != lease->net.s_addr)
			dhcp->ciaddr = 0;
	}

	dhcp->op = DHCP_BOOTREQUEST;
	dhcp->hwtype = iface->family;
	switch (iface->family) {
	case ARPHRD_ETHER:
	case ARPHRD_IEEE802:
		dhcp->hwlen = ETHER_ADDR_LEN;
		memcpy(&dhcp->chaddr, &iface->hwaddr, ETHER_ADDR_LEN);
		break;
	case ARPHRD_IEEE1394:
	case ARPHRD_INFINIBAND:
		dhcp->hwlen = 0;
		if (dhcp->ciaddr == 0 &&
		    type != DHCP_DECLINE && type != DHCP_RELEASE)
			dhcp->flags = htons(BROADCAST_FLAG);
		break;
	}

	if (type != DHCP_DECLINE && type != DHCP_RELEASE) {
		if (up < 0 || up > (time_t)UINT16_MAX)
			dhcp->secs = htons((uint16_t)UINT16_MAX);
		else
			dhcp->secs = htons(up);
	}
	dhcp->xid = xid;
	dhcp->cookie = htonl(MAGIC_COOKIE);

	*p++ = DHO_MESSAGETYPE; 
	*p++ = 1;
	*p++ = type;

	if (iface->clientid) {
		*p++ = DHO_CLIENTID;
		memcpy(p, iface->clientid, iface->clientid[0] + 1);
		p += iface->clientid[0] + 1;
	}

	if (lease->addr.s_addr && !IN_LINKLOCAL(htonl(lease->addr.s_addr))) {
		if (type == DHCP_DECLINE ||
		    type == DHCP_DISCOVER ||
		    (type == DHCP_REQUEST &&
		     lease->addr.s_addr != iface->addr.s_addr))
		{
			PUTADDR(DHO_IPADDRESS, lease->addr);
			if (lease->server.s_addr)
				PUTADDR(DHO_SERVERID, lease->server);
		}
	}

	if (type == DHCP_DECLINE) {
		*p++ = DHO_MESSAGE;
		len = strlen(DAD);
		*p++ = len;
		memcpy(p, DAD, len);
		p += len;
	}

	if (type == DHCP_RELEASE) {
		if (lease->server.s_addr)
			PUTADDR(DHO_SERVERID, lease->server);
	}

	if (type == DHCP_DISCOVER ||
	    type == DHCP_INFORM ||
	    type == DHCP_REQUEST)
	{
		*p++ = DHO_MAXMESSAGESIZE;
		*p++ = 2;
		sz = get_mtu(iface->name);
		if (sz < MTU_MIN) {
			if (set_mtu(iface->name, MTU_MIN) == 0)
				sz = MTU_MIN;
		}
		sz = htons(sz);
		memcpy(p, &sz, 2);
		p += 2;

		if (options->userclass[0]) {
			*p++ = DHO_USERCLASS;
			memcpy(p, options->userclass, options->userclass[0] + 1);
			p += options->userclass[0] + 1;
		}

		if (options->vendorclassid[0]) {
			*p++ = DHO_VENDORCLASSID;
			memcpy(p, options->vendorclassid,
			       options->vendorclassid[0] + 1);
			p += options->vendorclassid[0] + 1;
		}

		if (type != DHCP_INFORM) {
			if (options->leasetime != 0) {
				*p++ = DHO_LEASETIME;
				*p++ = 4;
				ul = htonl(options->leasetime);
				memcpy(p, &ul, 4);
				p += 4;
			}
		}

		/* Regardless of RFC2132, we should always send a hostname
		 * upto the first dot (the short hostname) as otherwise
		 * confuses some DHCP servers when updating DNS.
		 * The FQDN option should be used if a FQDN is required. */
		if (options->hostname[0]) {
			*p++ = DHO_HOSTNAME;
			hp = strchr(options->hostname, '.');
			if (hp)
				len = hp - options->hostname;
			else
				len = strlen(options->hostname);
			*p++ = len;
			memcpy(p, options->hostname, len);
			p += len;
		}
		if (options->fqdn != FQDN_DISABLE) {
			/* IETF DHC-FQDN option (81), RFC4702 */
			*p++ = DHO_FQDN;
			lp = p;
			*p++ = 3;
			/*
			 * Flags: 0000NEOS
			 * S: 1 => Client requests Server to update
			 *         a RR in DNS as well as PTR
			 * O: 1 => Server indicates to client that
			 *         DNS has been updated
			 * E: 1 => Name data is DNS format
			 * N: 1 => Client requests Server to not
			 *         update DNS
			 */
			*p++ = (options->fqdn & 0x09) | 0x04;
			*p++ = 0; /* from server for PTR RR */
			*p++ = 0; /* from server for A RR if S=1 */
			ul = encode_rfc1035(options->hostname, p);
			*lp += ul;
			p += ul;
		}

		/* vendor is already encoded correctly, so just add it */
		if (options->vendor[0]) {
			*p++ = DHO_VENDOR;
			memcpy(p, options->vendor, options->vendor[0] + 1);
			p += options->vendor[0] + 1;
		}

		*p++ = DHO_PARAMETERREQUESTLIST;
		n_params = p;
		*p++ = 0;
		for (opt = dhcp_opts; opt->option; opt++) {
			if (!(opt->type & REQUEST || 
			      has_option_mask(options->requestmask, opt->option)))
				continue;
			switch (opt->option) {
			case DHO_RENEWALTIME:	/* FALLTHROUGH */
			case DHO_REBINDTIME:
				if (type == DHCP_INFORM)
					continue;
				break;
			}
			*p++ = opt->option;
		}
		*n_params = p - n_params - 1;
	}
	*p++ = DHO_END;

#ifdef BOOTP_MESSAGE_LENTH_MIN
	/* Some crappy DHCP servers think they have to obey the BOOTP minimum
	 * message length.
	 * They are wrong, but we should still cater for them. */
	while (p - m < BOOTP_MESSAGE_LENTH_MIN)
		*p++ = DHO_PAD;
#endif

	*message = dhcp;
	return p - m;
}
示例#9
0
size_t send_message (const interface_t *iface, const dhcp_t *dhcp,
					 unsigned long xid, char type,
					 const options_t *options)
{
	struct udp_dhcp_packet *packet;
	dhcpmessage_t *message;
	unsigned char *m;
	unsigned char *p;
	unsigned char *n_params = NULL;
	unsigned long l;
	struct in_addr from;
	struct in_addr to;
	time_t up = uptime() - iface->start_uptime;
	uint32_t ul;
	uint16_t sz;
	unsigned int message_length;
	size_t retval;

	if (!iface || !options || !dhcp)
		return -1;

	memset (&from, 0, sizeof (from));
	memset (&to, 0, sizeof (to));

	if (type == DHCP_RELEASE)
		to.s_addr = dhcp->serveraddress.s_addr;

	message = xmalloc (sizeof (dhcpmessage_t));
	memset (message, 0, sizeof (dhcpmessage_t));
	m = (unsigned char *) message;
	p = (unsigned char *) &message->options;

	if ((type == DHCP_INFORM ||
		type == DHCP_RELEASE ||
		type == DHCP_REQUEST) &&
		! IN_LINKLOCAL (iface->previous_address.s_addr))
	{
		message->ciaddr = iface->previous_address.s_addr;
		from.s_addr = iface->previous_address.s_addr;

		/* Just incase we haven't actually configured the address yet */
		if (type == DHCP_INFORM && iface->previous_address.s_addr == 0)
			message->ciaddr = dhcp->address.s_addr;
		
		/* Zero the address if we're currently on a different subnet */
		if (type == DHCP_REQUEST &&
			iface->previous_netmask.s_addr != dhcp->netmask.s_addr)
			message->ciaddr = from.s_addr = 0;
	}

	message->op = DHCP_BOOTREQUEST;
	message->hwtype = iface->family;
	switch (iface->family) {
		case ARPHRD_ETHER:
		case ARPHRD_IEEE802:
			message->hwlen = ETHER_ADDR_LEN;
			memcpy (&message->chaddr, &iface->hwaddr, ETHER_ADDR_LEN);
			break;
		case ARPHRD_IEEE1394:
		case ARPHRD_INFINIBAND:
			if (message->ciaddr == 0)
				message->flags = (int16_t) htons (BROADCAST_FLAG);
			message->hwlen = 0;
			break;
		default:
			logger (LOG_ERR, "dhcp: unknown hardware type %d", iface->family);
	}

	if (up < 0 || up > UINT16_MAX)
		message->secs = htons ((short) UINT16_MAX);
	else
		message->secs = htons (up);
	message->xid = xid;
	message->cookie = htonl (MAGIC_COOKIE);

	*p++ = DHCP_MESSAGETYPE; 
	*p++ = 1;
	*p++ = type;

	if (type == DHCP_REQUEST) {
		*p++ = DHCP_MAXMESSAGESIZE;
		*p++ = 2;
		sz = get_mtu (iface->name);
		if (sz < MTU_MIN) {
			if (set_mtu (iface->name, MTU_MIN) == 0)
				sz = MTU_MIN;
		}
		sz = htons (sz);
		memcpy (p, &sz, 2);
		p += 2;
	}

	if (type != DHCP_INFORM) {
#define PUTADDR(_type, _val) \
		{ \
			*p++ = _type; \
			*p++ = 4; \
			memcpy (p, &_val.s_addr, 4); \
			p += 4; \
		}
		if (IN_LINKLOCAL (dhcp->address.s_addr))
			logger (LOG_ERR, "cannot request a link local address");
		else {
			if (dhcp->address.s_addr != iface->previous_address.s_addr &&
				type != DHCP_RELEASE)
				PUTADDR (DHCP_ADDRESS, dhcp->address);

			if (dhcp->serveraddress.s_addr != 0 && dhcp->address.s_addr !=0 &&
				(iface->previous_address.s_addr == 0 || type == DHCP_RELEASE))
				PUTADDR (DHCP_SERVERIDENTIFIER, dhcp->serveraddress);
		}
#undef PUTADDR
	}

	if (type == DHCP_REQUEST || type == DHCP_DISCOVER) {
		if (options->leasetime != 0) {
			*p++ = DHCP_LEASETIME;
			*p++ = 4;
			ul = htonl (options->leasetime);
			memcpy (p, &ul, 4);
			p += 4;
		}
	}

	if (type == DHCP_DISCOVER || type == DHCP_INFORM || type == DHCP_REQUEST) {
		*p++ = DHCP_PARAMETERREQUESTLIST;
		n_params = p;
		*p++ = 0;

		/* Only request DNSSERVER in discover to keep the packets small.
		   RFC2131 Section 3.5 states that the REQUEST must include the list
		   from the DISCOVER message, so I think we can safely do this. */

		if (type == DHCP_DISCOVER && ! options->test)
			*p++ = DHCP_DNSSERVER;
		else {
			if (type != DHCP_INFORM) {
				*p++ = DHCP_RENEWALTIME;
				*p++ = DHCP_REBINDTIME;
			}
			*p++ = DHCP_NETMASK;
			*p++ = DHCP_BROADCAST;
			*p++ = DHCP_CSR;
			/* RFC 3442 states classless static routes should be before routers
			 * and static routes as classless static routes override them both */
			*p++ = DHCP_STATICROUTE;
			*p++ = DHCP_ROUTERS;
			*p++ = DHCP_HOSTNAME;
			*p++ = DHCP_DNSSEARCH;
			*p++ = DHCP_DNSDOMAIN;
			*p++ = DHCP_DNSSERVER;
			*p++ = DHCP_NISDOMAIN;
			*p++ = DHCP_NISSERVER;
			*p++ = DHCP_NTPSERVER;
			*p++ = DHCP_MTU;
			*p++ = DHCP_ROOTPATH;
			*p++ = DHCP_SIPSERVER;
		}

		*n_params = p - n_params - 1;

		if (options->hostname[0]) {
			if (options->fqdn == FQDN_DISABLE) {
				*p++ = DHCP_HOSTNAME;
				*p++ = l = strlen (options->hostname);
				memcpy (p, options->hostname, l);
				p += l;
			} else {
				/* Draft IETF DHC-FQDN option (81) */
				*p++ = DHCP_FQDN;
				*p++ = (l = strlen (options->hostname)) + 3;
				/* Flags: 0000NEOS
				 * S: 1 => Client requests Server to update A RR in DNS as well as PTR
				 * O: 1 => Server indicates to client that DNS has been updated
				 * E: 1 => Name data is DNS format
				 * N: 1 => Client requests Server to not update DNS
				 */
				*p++ = options->fqdn & 0x9;
				*p++ = 0; /* rcode1, response from DNS server for PTR RR */
				*p++ = 0; /* rcode2, response from DNS server for A RR if S=1 */
				memcpy (p, options->hostname, l);
				p += l;
			}
		}
	}

	if (type != DHCP_DECLINE && type != DHCP_RELEASE) {
		if (options->userclass_len > 0) {
			*p++ = DHCP_USERCLASS;
			*p++ = options->userclass_len;
			memcpy (p, &options->userclass, options->userclass_len);
			p += options->userclass_len;
		}

		if (options->classid_len > 0) {
			*p++ = DHCP_CLASSID;
			*p++ = options->classid_len;
			memcpy (p, options->classid, options->classid_len);
			p += options->classid_len;
		}
	}

	*p++ = DHCP_CLIENTID;
	if (options->clientid_len > 0) {
		*p++ = options->clientid_len + 1;
		*p++ = 0; /* string */
		memcpy (p, options->clientid, options->clientid_len);
		p += options->clientid_len;
#ifdef ENABLE_DUID
	} else if (iface->duid && options->clientid_len != -1) {
		*p++ = iface->duid_length + 5;
		*p++ = 255; /* RFC 4361 */

		/* IAID is 4 bytes, so if the interface name is 4 bytes then use it */
		if (strlen (iface->name) == 4) {
			memcpy (p, iface->name, 4);
		} else {
			/* Name isn't 4 bytes, so use the index */
			ul = htonl (if_nametoindex (iface->name));
			memcpy (p, &ul, 4);
		}
		p += 4;

		memcpy (p, iface->duid, iface->duid_length);
		p += iface->duid_length;
#endif
	} else {
		*p++ = iface->hwlen + 1;
		*p++ = iface->family;
		memcpy (p, iface->hwaddr, iface->hwlen);
		p += iface->hwlen;
	}

	*p++ = DHCP_END;

#ifdef BOOTP_MESSAGE_LENTH_MIN
	/* Some crappy DHCP servers think they have to obey the BOOTP minimum
	 * messag length. They are wrong, but we should still cater for them */
	while (p - m < BOOTP_MESSAGE_LENTH_MIN)
		*p++ = DHCP_PAD;
#endif

	message_length = p - m;

	packet = xmalloc (sizeof (struct udp_dhcp_packet));
	memset (packet, 0, sizeof (struct udp_dhcp_packet));
	make_dhcp_packet (packet, (unsigned char *) message, message_length,
					  from, to);
	free (message);

	logger (LOG_DEBUG, "sending %s with xid 0x%lx",
			dhcp_message[(int) type], xid);
	retval = send_packet (iface, ETHERTYPE_IP, (unsigned char *) packet,
						  message_length + sizeof (struct ip) +
						  sizeof (struct udphdr));
	free (packet);
	return (retval);
}
示例#10
0
void ring_bond_ib::create_slave_list(in_addr_t local_if, ring_resource_creation_info_t* p_ring_info, bool active_slaves[], uint16_t pkey)
{
	for (uint32_t i = 0; i < m_n_num_resources; i++) {
		m_bond_rings[i] = new ring_ib(local_if, &p_ring_info[i], 1, active_slaves[i], pkey, get_mtu(), this); // get_mtu() reads the MTU from ifconfig when created. Now passing it to its slaves. could have sent 0 here, as the MTU of the bond is already on the bond
		if (m_min_devices_tx_inline < 0)
			m_min_devices_tx_inline = m_bond_rings[i]->get_max_tx_inline();
		else
			m_min_devices_tx_inline = min(m_min_devices_tx_inline, m_bond_rings[i]->get_max_tx_inline());
		if (active_slaves[i]) {
			m_active_rings[i] = m_bond_rings[i];
		} else {
			m_active_rings[i] = NULL;
		}
	}
	close_gaps_active_rings();
}
示例#11
0
static int get_interfaces(struct if_stats *ifs)
{
    char buf[PAGE_SIZE];
    char *p;
    int ret, nr, fd;

    fd = open(PROC_NET_DEV, O_RDONLY);
    if (fd < 0) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    ret = read(fd, buf, sizeof(buf) - 1);
    if (ret < 0) {
        perror("read");
        exit(EXIT_FAILURE);
    } else if (!ret) {
        fprintf(stderr, "reading " PROC_NET_DEV " returned premature EOF\n");
        exit(EXIT_FAILURE);
    }
    buf[ret] = '\0';

    /* skip down to the third line */
    p = strchr(buf, '\n');
    if (!p) {
        fprintf(stderr, "parsing " PROC_NET_DEV " failed unexpectedly\n");
        exit(EXIT_FAILURE);
    }
    p = strchr(p + 1, '\n');
    if (!p) {
        fprintf(stderr, "parsing " PROC_NET_DEV " failed unexpectedly\n");
        exit(EXIT_FAILURE);
    }
    p += 1;

    /*
     * Key:
     * if: (Rx) bytes packets errs drop fifo frame compressed multicast \
     *     (Tx) bytes packets errs drop fifo colls carrier compressed
     */
    for (nr = 0; nr < MAX_IF; nr++) {
        char *c;

        ret = sscanf(p, "%" STR(IFNAMSIZ) "s", ifs->name);
        if (ret != 1) {
            fprintf(stderr, "parsing " PROC_NET_DEV " failed unexpectedly\n");
            exit(EXIT_FAILURE);
        }

        /*
         * This works around a bug in the proc file where large interface names
         * or Rx byte counts eat the delimiter, breaking sscanf.
         */
        c = strchr(ifs->name, ':');
        if (c)
            *c = '\0';

        p = strchr(p, ':') + 1;

        ret = sscanf(p, "%u %u %u %u %*u %*u %*u %*u %u %u %u %u %*u %*u "
                     "%*u %*u\n", &ifs->rx_bytes, &ifs->rx_packets,
                     &ifs->rx_errors, &ifs->rx_dropped, &ifs->tx_bytes,
                     &ifs->tx_packets, &ifs->tx_errors, &ifs->tx_dropped);
        if (ret != 8) {
            fprintf(stderr, "parsing " PROC_NET_DEV " failed unexpectedly\n");
            exit(EXIT_FAILURE);
        }

        ifs->mtu = get_mtu(ifs->name);

        p = strchr(p, '\n') + 1;
        if (*p == '\0') {
            nr++;
            break;
        }

        ifs++;
    }

    ret = close(fd);
    if (ret) {
        perror("close");
        exit(EXIT_FAILURE);
    }

    return nr;
}
示例#12
0
void ring_bond_eth::create_slave_list(in_addr_t local_if, ring_resource_creation_info_t* p_ring_info, bool active_slaves[], uint16_t vlan)
{
	for (uint32_t i = 0; i < m_n_num_resources; i++) {
		m_bond_rings[i] = new ring_eth(local_if, &p_ring_info[i], 1, active_slaves[i], vlan, get_mtu(), this);
		if (m_min_devices_tx_inline < 0)
			m_min_devices_tx_inline = m_bond_rings[i]->get_max_tx_inline();
		else
			m_min_devices_tx_inline = min(m_min_devices_tx_inline, m_bond_rings[i]->get_max_tx_inline());
		if (active_slaves[i]) {
			m_active_rings[i] = m_bond_rings[i];
		} else {
			m_active_rings[i] = NULL;
		}
	}
	close_gaps_active_rings();
}
示例#13
0
文件: net.c 项目: enukane/netbsd-src
struct if_head *
discover_interfaces(struct dhcpcd_ctx *ctx, int argc, char * const *argv)
{
	struct ifaddrs *ifaddrs, *ifa;
	char *p;
	int i, sdl_type;
	struct if_head *ifs;
	struct interface *ifp;
#ifdef __linux__
	char ifn[IF_NAMESIZE];
#endif
#ifdef INET
	const struct sockaddr_in *addr;
	const struct sockaddr_in *net;
	const struct sockaddr_in *dst;
#endif
#ifdef INET6
	const struct sockaddr_in6 *sin6;
	int ifa_flags;
#endif
#ifdef AF_LINK
	const struct sockaddr_dl *sdl;
#ifdef SIOCGIFPRIORITY
	struct ifreq ifr;
	int s_inet;
#endif
#ifdef IFLR_ACTIVE
	struct if_laddrreq iflr;
	int s_link;
#endif

#ifdef SIOCGIFPRIORITY
	if ((s_inet = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
		return NULL;
#endif
#ifdef IFLR_ACTIVE
	if ((s_link = socket(AF_LINK, SOCK_DGRAM, 0)) == -1) {
#ifdef SIOCGIFPRIORITY
		close(s_inet);
#endif
		return NULL;
	}
	memset(&iflr, 0, sizeof(iflr));
#endif
#elif AF_PACKET
	const struct sockaddr_ll *sll;
#endif

	if (getifaddrs(&ifaddrs) == -1)
		return NULL;
	ifs = malloc(sizeof(*ifs));
	if (ifs == NULL)
		return NULL;
	TAILQ_INIT(ifs);

	for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
		if (ifa->ifa_addr != NULL) {
#ifdef AF_LINK
			if (ifa->ifa_addr->sa_family != AF_LINK)
				continue;
#elif AF_PACKET
			if (ifa->ifa_addr->sa_family != AF_PACKET)
				continue;
#endif
		}

		/* Ensure that the interface name has settled */
		if (!dev_initialized(ctx, ifa->ifa_name))
			continue;

		/* It's possible for an interface to have >1 AF_LINK.
		 * For our purposes, we use the first one. */
		TAILQ_FOREACH(ifp, ifs, next) {
			if (strcmp(ifp->name, ifa->ifa_name) == 0)
				break;
		}
		if (ifp)
			continue;
		if (argc > 0) {
			for (i = 0; i < argc; i++) {
#ifdef __linux__
				/* Check the real interface name */
				strlcpy(ifn, argv[i], sizeof(ifn));
				p = strchr(ifn, ':');
				if (p)
					*p = '\0';
				if (strcmp(ifn, ifa->ifa_name) == 0)
					break;
#else
				if (strcmp(argv[i], ifa->ifa_name) == 0)
					break;
#endif
			}
			if (i == argc)
				continue;
			p = argv[i];
		} else {
			p = ifa->ifa_name;
			/* -1 means we're discovering against a specific
			 * interface, but we still need the below rules
			 * to apply. */
			if (argc == -1 && strcmp(argv[0], ifa->ifa_name) != 0)
				continue;
		}
		for (i = 0; i < ctx->ifdc; i++)
			if (!fnmatch(ctx->ifdv[i], p, 0))
				break;
		if (i < ctx->ifdc)
			continue;
		for (i = 0; i < ctx->ifac; i++)
			if (!fnmatch(ctx->ifav[i], p, 0))
				break;
		if (ctx->ifac && i == ctx->ifac)
			continue;

		if (if_vimaster(ifa->ifa_name) == 1) {
			syslog(argc ? LOG_ERR : LOG_DEBUG,
				"%s: is a Virtual Interface Master, skipping",
				ifa->ifa_name);
			continue;
		}

		ifp = calloc(1, sizeof(*ifp));
		if (ifp == NULL) {
			syslog(LOG_ERR, "%s: %m", __func__);
			break;
		}
		ifp->ctx = ctx;
		strlcpy(ifp->name, p, sizeof(ifp->name));
		ifp->flags = ifa->ifa_flags;

		/* Bring the interface up if not already */
		if (!(ifp->flags & IFF_UP)
#ifdef SIOCGIFMEDIA
		    && carrier_status(ifp) != LINK_UNKNOWN
#endif
		   )
		{
			if (up_interface(ifp) == 0)
				ctx->options |= DHCPCD_WAITUP;
			else
				syslog(LOG_ERR, "%s: up_interface: %m",
				    ifp->name);
		}

		sdl_type = 0;
		/* Don't allow loopback unless explicit */
		if (ifp->flags & IFF_LOOPBACK) {
			if (argc == 0 && ctx->ifac == 0) {
				free_interface(ifp);
				continue;
			}
		} else if (ifa->ifa_addr != NULL) {
#ifdef AF_LINK
			sdl = (const struct sockaddr_dl *)(void *)ifa->ifa_addr;

#ifdef IFLR_ACTIVE
			/* We need to check for active address */
			strlcpy(iflr.iflr_name, ifp->name,
			    sizeof(iflr.iflr_name));
			memcpy(&iflr.addr, ifa->ifa_addr,
			    MIN(ifa->ifa_addr->sa_len, sizeof(iflr.addr)));
			iflr.flags = IFLR_PREFIX;
			iflr.prefixlen = sdl->sdl_alen * NBBY;
			if (ioctl(s_link, SIOCGLIFADDR, &iflr) == -1 ||
			    !(iflr.flags & IFLR_ACTIVE))
			{
				free_interface(ifp);
				continue;
			}
#endif

			ifp->index = sdl->sdl_index;
			sdl_type = sdl->sdl_type;
			switch(sdl->sdl_type) {
			case IFT_BRIDGE: /* FALLTHROUGH */
			case IFT_L2VLAN: /* FALLTHOUGH */
			case IFT_L3IPVLAN: /* FALLTHROUGH */
			case IFT_ETHER:
				ifp->family = ARPHRD_ETHER;
				break;
			case IFT_IEEE1394:
				ifp->family = ARPHRD_IEEE1394;
				break;
#ifdef IFT_INFINIBAND
			case IFT_INFINIBAND:
				ifp->family = ARPHRD_INFINIBAND;
				break;
#endif
			}
			ifp->hwlen = sdl->sdl_alen;
#ifndef CLLADDR
#  define CLLADDR(s) ((const char *)((s)->sdl_data + (s)->sdl_nlen))
#endif
			memcpy(ifp->hwaddr, CLLADDR(sdl), ifp->hwlen);
#elif AF_PACKET
			sll = (const struct sockaddr_ll *)(void *)ifa->ifa_addr;
			ifp->index = sll->sll_ifindex;
			ifp->family = sdl_type = sll->sll_hatype;
			ifp->hwlen = sll->sll_halen;
			if (ifp->hwlen != 0)
				memcpy(ifp->hwaddr, sll->sll_addr, ifp->hwlen);
#endif
		}
#ifdef __linux__
		/* PPP addresses on Linux don't have hardware addresses */
		else
			ifp->index = if_nametoindex(ifp->name);
#endif

		/* We only work on ethernet by default */
		if (!(ifp->flags & IFF_POINTOPOINT) &&
		    ifp->family != ARPHRD_ETHER)
		{
			if (argc == 0 && ctx->ifac == 0) {
				free_interface(ifp);
				continue;
			}
			switch (ifp->family) {
			case ARPHRD_IEEE1394: /* FALLTHROUGH */
			case ARPHRD_INFINIBAND:
				/* We don't warn for supported families */
				break;
			default:
				syslog(LOG_WARNING,
				    "%s: unsupported interface type %.2x"
				    ", falling back to ethernet",
				    ifp->name, sdl_type);
				ifp->family = ARPHRD_ETHER;
				break;
			}
		}

		/* Handle any platform init for the interface */
		if (if_init(ifp) == -1) {
			syslog(LOG_ERR, "%s: if_init: %m", p);
			free_interface(ifp);
			continue;
		}

		/* Ensure that the MTU is big enough for DHCP */
		if (get_mtu(ifp->name) < MTU_MIN &&
		    set_mtu(ifp->name, MTU_MIN) == -1)
		{
			syslog(LOG_ERR, "%s: set_mtu: %m", p);
			free_interface(ifp);
			continue;
		}

#ifdef SIOCGIFPRIORITY
		/* Respect the interface priority */
		memset(&ifr, 0, sizeof(ifr));
		strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
		if (ioctl(s_inet, SIOCGIFPRIORITY, &ifr) == 0)
			ifp->metric = ifr.ifr_metric;
#else
		/* We reserve the 100 range for virtual interfaces, if and when
		 * we can work them out. */
		ifp->metric = 200 + ifp->index;
		if (getifssid(ifp->name, ifp->ssid) != -1) {
			ifp->wireless = 1;
			ifp->metric += 100;
		}
#endif

		TAILQ_INSERT_TAIL(ifs, ifp, next);
	}

	for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
		if (ifa->ifa_addr == NULL)
			continue;
		switch(ifa->ifa_addr->sa_family) {
#ifdef INET
		case AF_INET:
			addr = (const struct sockaddr_in *)
			    (void *)ifa->ifa_addr;
			net = (const struct sockaddr_in *)
			    (void *)ifa->ifa_netmask;
			if (ifa->ifa_flags & IFF_POINTOPOINT)
				dst = (const struct sockaddr_in *)
				    (void *)ifa->ifa_dstaddr;
			else
				dst = NULL;
			ipv4_handleifa(ctx, RTM_NEWADDR, ifs, ifa->ifa_name,
				&addr->sin_addr,
				&net->sin_addr,
				dst ? &dst->sin_addr : NULL);
			break;
#endif
#ifdef INET6
		case AF_INET6:
			sin6 = (const struct sockaddr_in6 *)
			    (void *)ifa->ifa_addr;
			ifa_flags = in6_addr_flags(ifa->ifa_name,
			    &sin6->sin6_addr);
			if (ifa_flags != -1)
				ipv6_handleifa(ctx, RTM_NEWADDR, ifs,
				    ifa->ifa_name,
				    &sin6->sin6_addr, ifa_flags);
			break;
#endif
		}
	}

	freeifaddrs(ifaddrs);

#ifdef SIOCGIFPRIORITY
	close(s_inet);
#endif
#ifdef IFLR_ACTIVE
	close(s_link);
#endif

	return ifs;
}
示例#14
0
/*
 * Get informtion about a server from the kernel
 *
 * Arguments:
 *	ssp	pointer to the server block
 *
 * Returns:
 *	0	server info is OK
 *	errno	server is not ready
 *
 */
int
scsp_get_server_info(Scsp_server *ssp)
{
	int			i, len, mtu, rc, sel;
	struct atminfreq	air;
	struct air_netif_rsp	*netif_rsp = NULL;
	struct air_int_rsp	*intf_rsp = NULL;
	struct air_cfg_rsp	*cfg_rsp = NULL;
	struct sockaddr_in	*ip_addr;
	Atm_addr_nsap		*anp;

	/*
	 * Make sure we're the server for the interface
	 */
	if (!scsp_is_atmarp_server(ssp->ss_intf)) {
		rc = EINVAL;
		goto server_info_done;
	}

	/*
	 * Get the IP address and physical interface name
	 * associated with the network interface
	 */
	UM_ZERO(&air, sizeof(struct atminfreq));
	air.air_opcode = AIOCS_INF_NIF;
	strcpy(air.air_netif_intf, ssp->ss_intf);
	len = do_info_ioctl(&air, sizeof(struct air_netif_rsp));
	if (len <= 0) {
		rc = EIO;
		goto server_info_done;
	}
	netif_rsp = (struct air_netif_rsp *)air.air_buf_addr;

	ip_addr = (struct sockaddr_in *)&netif_rsp->anp_proto_addr;
	if (ip_addr->sin_family != AF_INET ||
			ip_addr->sin_addr.s_addr == 0) {
		rc = EADDRNOTAVAIL;
		goto server_info_done;
	}

	/*
	 * Get the MTU for the network interface
	 */
	mtu = get_mtu(ssp->ss_intf);
	if (mtu < 0) {
		rc = EIO;
		goto server_info_done;
	}

	/*
	 * Get the ATM address associated with the
	 * physical interface
	 */
	UM_ZERO(&air, sizeof(struct atminfreq));
	air.air_opcode = AIOCS_INF_INT;
	strcpy(air.air_int_intf, netif_rsp->anp_phy_intf);
	len = do_info_ioctl(&air, sizeof(struct air_int_rsp));
	if (len <= 0) {
		rc = EIO;
		goto server_info_done;
	}
	intf_rsp = (struct air_int_rsp *)air.air_buf_addr;

	/*
	 * Make sure we're running UNI signalling
	 */
	if (intf_rsp->anp_sig_proto != ATM_SIG_UNI30 &&
			intf_rsp->anp_sig_proto != ATM_SIG_UNI31 &&
			intf_rsp->anp_sig_proto != ATM_SIG_UNI40) {
		rc = EINVAL;
		goto server_info_done;
	}

	/*
	 * Check the physical interface's state
	 */
	if (intf_rsp->anp_sig_state != UNISIG_ACTIVE) {
		rc = EHOSTDOWN;
		goto server_info_done;
	}

	/*
	 * Make sure the interface's address is valid
	 */
	if (intf_rsp->anp_addr.address_format != T_ATM_ENDSYS_ADDR &&
			!(intf_rsp->anp_addr.address_format ==
				T_ATM_E164_ADDR &&
			intf_rsp->anp_subaddr.address_format ==
				T_ATM_ENDSYS_ADDR)) {
		rc = EINVAL;
		goto server_info_done;
	}

	/*
	 * Find the selector byte value for the interface
	 */
	for (i=0; i<strlen(ssp->ss_intf); i++) {
		if (ssp->ss_intf[i] >= '0' &&
				ssp->ss_intf[i] <= '9')
			break;
	}
	sel = atoi(&ssp->ss_intf[i]);

	/*
	 * Get configuration information associated with the
	 * physical interface
	 */
	UM_ZERO(&air, sizeof(struct atminfreq));
	air.air_opcode = AIOCS_INF_CFG;
	strcpy(air.air_int_intf, netif_rsp->anp_phy_intf);
	len = do_info_ioctl(&air, sizeof(struct air_cfg_rsp));
	if (len <= 0) {
		rc = EIO;
		goto server_info_done;
	}
	cfg_rsp = (struct air_cfg_rsp *)air.air_buf_addr;

	/*
	 * Update the server entry
	 */
	UM_COPY(&ip_addr->sin_addr, ssp->ss_lsid.id, ssp->ss_id_len);
	ssp->ss_lsid.id_len = ssp->ss_id_len;
	ssp->ss_mtu = mtu + 8;
	ATM_ADDR_COPY(&intf_rsp->anp_addr, &ssp->ss_addr);
	ATM_ADDR_COPY(&intf_rsp->anp_subaddr, &ssp->ss_subaddr);
	if (ssp->ss_addr.address_format == T_ATM_ENDSYS_ADDR) {
		anp = (Atm_addr_nsap *)ssp->ss_addr.address;
		anp->aan_sel = sel;
	} else if (ssp->ss_addr.address_format == T_ATM_E164_ADDR &&
			ssp->ss_subaddr.address_format ==
				T_ATM_ENDSYS_ADDR) {
		anp = (Atm_addr_nsap *)ssp->ss_subaddr.address;
		anp->aan_sel = sel;
	}
	ssp->ss_media = cfg_rsp->acp_cfg.ac_media;
	rc = 0;

	/*
	 * Free dynamic data
	 */
server_info_done:
	if (netif_rsp)
		UM_FREE(netif_rsp);
	if (intf_rsp)
		UM_FREE(intf_rsp);
	if (cfg_rsp)
		UM_FREE(cfg_rsp);

	return(rc);
}
示例#15
0
JNIEXPORT jint JNICALL
Java_eu_faircode_netguard_ServiceSinkhole_jni_1get_1mtu(JNIEnv *env, jobject instance) {
    return get_mtu();
}
int rdt_connect(struct in_addr dst, int scid, int dcid)
{
        int n, fd;
        pid_t pid;
        struct sockaddr_un un;
        struct in_addr src;
        struct conn_info conn_info;

        if (signal(SIGINT, sig_hand) == SIG_ERR ||
            signal(SIGHUP, sig_hand) == SIG_ERR ||
            signal(SIGQUIT, sig_hand) == SIG_ERR)
        {
                err_sys("signal() error");
        }

        src = get_addr(dst);
        pid = getpid();

        /* allocate share area for send
         * and recv process.
         */
        conn_alloc(); 
        conn_info.cact = ACTIVE;
        conn_info.pid = pid;
        conn_info.src = conn_user->src = src;
        conn_info.dst = conn_user->dst = dst;
        conn_info.scid = conn_user->scid = scid;
        conn_info.dcid = conn_user->dcid = dcid;
        conn_user->sndfd = make_fifo(pid, "snd");
        conn_user->rcvfd = make_fifo(pid, "rcv");
        conn_user->sfd = make_sock();
	conn_user->seq = conn_user->ack = 0;

        if (!mtu) {
                if (dev[0] == 0 && !get_dev(src, dev))
                        err_quit("can't get dev name");
                mtu = get_mtu(dev);
        }
        n = min(mtu, 1500);
        conn_user->mss = n;
        if ((conn_user->sndpkt = malloc(n)) == NULL)
                err_sys("malloc() sndpkt error");
        if ((conn_user->rcvpkt = malloc(n)) == NULL)
                err_sys("malloc() rcvpkt error");

        if ((fd = ux_cli(RDT_UX_SOCK, &un)) < 0)
                err_sys("ux_cli() error");
        n = sizeof(struct conn_info);
        if (sendto(fd, &conn_info, n, 0, (struct sockaddr *)&un,
                                sizeof(struct sockaddr_un)) != n)
        {
                err_sys("sendto() error");
        }
	get_pkt(conn_user->sndfd, &conn_info, NULL, 0);
	conn_user->scid = conn_info.scid;

        if (rexmt_pkt(conn_user, RDT_REQ, NULL, 0) < 0)
                err_sys("rexmt_pkt() error");

        fprintf(stderr, "rdt_connect() succeed\n");
        pkt_debug((struct rdthdr *)conn_user->sndpkt);
        
        return(0);

}