Ejemplo n.º 1
0
static int parse_layer4(struct packet *packet, u8 *layer4_start,
			int layer4_protocol, int layer4_bytes,
			u8 *packet_end, bool *is_inner, char **error)
{
	if (layer4_protocol == IPPROTO_TCP) {
		*is_inner = true;	/* found inner-most layer 4 */
		return parse_tcp(packet, layer4_start, layer4_bytes, packet_end,
				 error);
	} else if (layer4_protocol == IPPROTO_UDP) {
		*is_inner = true;	/* found inner-most layer 4 */
		return parse_udp(packet, layer4_start, layer4_bytes, packet_end,
				 error);
	} else if (layer4_protocol == IPPROTO_ICMP) {
		*is_inner = true;	/* found inner-most layer 4 */
		return parse_icmpv4(packet, layer4_start, layer4_bytes,
				    packet_end, error);
	} else if (layer4_protocol == IPPROTO_ICMPV6) {
		*is_inner = true;	/* found inner-most layer 4 */
		return parse_icmpv6(packet, layer4_start, layer4_bytes,
				    packet_end, error);
	} else if (layer4_protocol == IPPROTO_GRE) {
		*is_inner = false;
		return parse_gre(packet, layer4_start, layer4_bytes, packet_end,
				 error);
	} else if (layer4_protocol == IPPROTO_IPIP) {
		*is_inner = false;
		return parse_ipv4(packet, layer4_start, packet_end, error);
	} else if (layer4_protocol == IPPROTO_IPV6) {
		*is_inner = false;
		return parse_ipv6(packet, layer4_start, packet_end, error);
	}
	return PACKET_UNKNOWN_L4;
}
Ejemplo n.º 2
0
static int parse_layer3_packet(struct packet *packet,
			       u8 *header_start, u8 *packet_end,
			       char **error)
{
	u8 *p = header_start;
	/* Note that packet_end points to the byte beyond the end of packet. */
	struct ipv4 *ip = NULL;

	/* Examine IPv4/IPv6 header. */
	if (p + sizeof(struct ipv4) > packet_end) {
		asprintf(error, "IP header overflows packet");
		return PACKET_BAD;
	}

	/* Look at the IP version number, which is in the first 4 bits
	 * of both IPv4 and IPv6 packets.
	 */
	ip = (struct ipv4 *) (p);
	if (ip->version == 4)
		return parse_ipv4(packet, p, packet_end, error);
	else if (ip->version == 6)
		return parse_ipv6(packet, p, packet_end, error);

	asprintf(error, "Unsupported IP version");
	return PACKET_BAD;
}
Ejemplo n.º 3
0
static int parse_layer3_packet_by_proto(struct packet *packet,
					u16 proto, u8 *header_start,
					u8 *packet_end, char **error)
{
	u8 *p = header_start;

	if (proto == ETHERTYPE_IP) {
		struct ipv4 *ip = NULL;

		/* Examine IPv4 header. */
		if (p + sizeof(struct ipv4) > packet_end) {
			asprintf(error, "IPv4 header overflows packet");
			goto error_out;
		}

		/* Look at the IP version number, which is in the first 4 bits
		 * of both IPv4 and IPv6 packets.
		 */
		ip = (struct ipv4 *)p;
		if (ip->version == 4) {
			return parse_ipv4(packet, p, packet_end, error);
		} else {
			asprintf(error, "Bad IP version for ETHERTYPE_IP");
			goto error_out;
		}
	} else if (proto == ETHERTYPE_IPV6) {
		struct ipv6 *ip = NULL;

		/* Examine IPv6 header. */
		if (p + sizeof(struct ipv6) > packet_end) {
			asprintf(error, "IPv6 header overflows packet");
			goto error_out;
		}

		/* Look at the IP version number, which is in the first 4 bits
		 * of both IPv4 and IPv6 packets.
		 */
		ip = (struct ipv6 *)p;
		if (ip->version == 6) {
			return parse_ipv6(packet, p, packet_end, error);
		} else {
			asprintf(error, "Bad IP version for ETHERTYPE_IPV6");
			goto error_out;
		}
	} else if ((proto == ETHERTYPE_MPLS_UC) ||
		   (proto == ETHERTYPE_MPLS_MC)) {
		return parse_mpls(packet, p, packet_end, error);
	} else {
		return PACKET_UNKNOWN_L4;
	}

error_out:
	return PACKET_BAD;
}
Ejemplo n.º 4
0
/*
  parse an ip
 */
bool parse_ip(const char *addr, const char *ifaces, unsigned port, ctdb_sock_addr *saddr)
{
	char *p;
	bool ret;

	ZERO_STRUCTP(saddr); /* valgrind :-) */

	/* now is this a ipv4 or ipv6 address ?*/
	p = index(addr, ':');
	if (p == NULL) {
		ret = parse_ipv4(addr, port, &saddr->ip);
	} else {
		ret = parse_ipv6(addr, ifaces, port, saddr);
	}

	return ret;
}
Ejemplo n.º 5
0
static void test_parse_ipv6(const char *uri_text, const char *host,
                            unsigned short port, uint32_t scope_id) {
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0);
  grpc_resolved_address addr;
  char ntop_buf[INET6_ADDRSTRLEN];

  GPR_ASSERT(1 == parse_ipv6(uri, &addr));
  struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr.addr;
  GPR_ASSERT(AF_INET6 == addr_in6->sin6_family);
  GPR_ASSERT(NULL != grpc_inet_ntop(AF_INET6, &addr_in6->sin6_addr, ntop_buf,
                                    sizeof(ntop_buf)));
  GPR_ASSERT(0 == strcmp(ntop_buf, host));
  GPR_ASSERT(ntohs(addr_in6->sin6_port) == port);
  GPR_ASSERT(addr_in6->sin6_scope_id == scope_id);

  grpc_uri_destroy(uri);
  grpc_exec_ctx_finish(&exec_ctx);
}
Ejemplo n.º 6
0
/* parse ipv4 or ipv6 address
 */
int parse_ip(str *s, struct ip_addr *ip, unsigned short *port)
{
	if (!s || !s->len) return -1;

	if (memchr(s->s, '.', s->len)) {
		/* ipv4 address */
		if (parse_ipv4(s, ip, port)) {
			LOG(L_ERR, "ERROR: parse_ip(): failed to parse ipv4 iddress: %.*s\n",
					s->len, s->s);
			return -1;
		}
	} else {
		/* ipv6 address */
		if (parse_ipv6(s, ip, port)) {
			LOG(L_ERR, "ERROR: parse_ip(): failed to parse ipv6 iddress: %.*s\n",
					s->len, s->s);
			return -1;
		}
	}

	return 0;
}
Ejemplo n.º 7
0
int handle_ingress(struct __sk_buff *skb)
{
	void *data = (void *)(long)skb->data;
	struct ethhdr *eth = data;
	void *data_end = (void *)(long)skb->data_end;
	uint64_t h_proto, nh_off;

	nh_off = sizeof(*eth);
	if (data + nh_off > data_end)
		return 0;

	h_proto = eth->h_proto;

	if (h_proto == ETH_P_8021Q || h_proto == ETH_P_8021AD) {
		struct vlan_hdr *vhdr;

		vhdr = data + nh_off;
		nh_off += sizeof(struct vlan_hdr);
		if (data + nh_off > data_end)
			return 0;
		h_proto = vhdr->h_vlan_encapsulated_proto;
	}
	if (h_proto == ETH_P_8021Q || h_proto == ETH_P_8021AD) {
		struct vlan_hdr *vhdr;

		vhdr = data + nh_off;
		nh_off += sizeof(struct vlan_hdr);
		if (data + nh_off > data_end)
			return 0;
		h_proto = vhdr->h_vlan_encapsulated_proto;
	}
	if (h_proto == htons(ETH_P_IP))
		return parse_ipv4(data, nh_off, data_end);
	else if (h_proto == htons(ETH_P_IPV6))
		return parse_ipv6(data, nh_off, data_end);
	return 0;
}
Ejemplo n.º 8
0
/* Initializes 'flow' members from 'packet', 'skb_priority', 'tnl', and
 * 'in_port'.
 *
 * Initializes 'packet' header pointers as follows:
 *
 *    - packet->l2 to the start of the Ethernet header.
 *
 *    - packet->l2_5 to the start of the MPLS shim header.
 *
 *    - packet->l3 to just past the Ethernet header, or just past the
 *      vlan_header if one is present, to the first byte of the payload of the
 *      Ethernet frame.
 *
 *    - packet->l4 to just past the IPv4 header, if one is present and has a
 *      correct length, and otherwise NULL.
 *
 *    - packet->l7 to just past the TCP/UDP/SCTP/ICMP header, if one is
 *      present and has a correct length, and otherwise NULL.
 */
void
flow_extract(struct ofpbuf *packet, uint32_t skb_priority, uint32_t pkt_mark,
             const struct flow_tnl *tnl, const union flow_in_port *in_port,
             struct flow *flow)
{
    struct ofpbuf b = *packet;
    struct eth_header *eth;

    COVERAGE_INC(flow_extract);

    memset(flow, 0, sizeof *flow);

    if (tnl) {
        ovs_assert(tnl != &flow->tunnel);
        flow->tunnel = *tnl;
    }
    if (in_port) {
        flow->in_port = *in_port;
    }
    flow->skb_priority = skb_priority;
    flow->pkt_mark = pkt_mark;

    packet->l2   = b.data;
    packet->l2_5 = NULL;
    packet->l3   = NULL;
    packet->l4   = NULL;
    packet->l7   = NULL;

    if (b.size < sizeof *eth) {
        return;
    }

    /* Link layer. */
    eth = b.data;
    memcpy(flow->dl_src, eth->eth_src, ETH_ADDR_LEN);
    memcpy(flow->dl_dst, eth->eth_dst, ETH_ADDR_LEN);

    /* dl_type, vlan_tci. */
    ofpbuf_pull(&b, ETH_ADDR_LEN * 2);
    if (eth->eth_type == htons(ETH_TYPE_VLAN)) {
        parse_vlan(&b, flow);
    }
    flow->dl_type = parse_ethertype(&b);

    /* Parse mpls, copy l3 ttl. */
    if (eth_type_mpls(flow->dl_type)) {
        packet->l2_5 = b.data;
        parse_mpls(&b, flow);
    }

    /* Network layer. */
    packet->l3 = b.data;
    if (flow->dl_type == htons(ETH_TYPE_IP)) {
        const struct ip_header *nh = pull_ip(&b);
        if (nh) {
            packet->l4 = b.data;

            flow->nw_src = get_16aligned_be32(&nh->ip_src);
            flow->nw_dst = get_16aligned_be32(&nh->ip_dst);
            flow->nw_proto = nh->ip_proto;

            flow->nw_tos = nh->ip_tos;
            if (IP_IS_FRAGMENT(nh->ip_frag_off)) {
                flow->nw_frag = FLOW_NW_FRAG_ANY;
                if (nh->ip_frag_off & htons(IP_FRAG_OFF_MASK)) {
                    flow->nw_frag |= FLOW_NW_FRAG_LATER;
                }
            }
            flow->nw_ttl = nh->ip_ttl;

            if (!(nh->ip_frag_off & htons(IP_FRAG_OFF_MASK))) {
                if (flow->nw_proto == IPPROTO_TCP) {
                    parse_tcp(packet, &b, flow);
                } else if (flow->nw_proto == IPPROTO_UDP) {
                    parse_udp(packet, &b, flow);
                } else if (flow->nw_proto == IPPROTO_SCTP) {
                    parse_sctp(packet, &b, flow);
                } else if (flow->nw_proto == IPPROTO_ICMP) {
                    const struct icmp_header *icmp = pull_icmp(&b);
                    if (icmp) {
                        flow->tp_src = htons(icmp->icmp_type);
                        flow->tp_dst = htons(icmp->icmp_code);
                        packet->l7 = b.data;
                    }
                }
            }
        }
    } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
        if (parse_ipv6(&b, flow)) {
            return;
        }

        packet->l4 = b.data;
        if (flow->nw_proto == IPPROTO_TCP) {
            parse_tcp(packet, &b, flow);
        } else if (flow->nw_proto == IPPROTO_UDP) {
            parse_udp(packet, &b, flow);
        } else if (flow->nw_proto == IPPROTO_SCTP) {
            parse_sctp(packet, &b, flow);
        } else if (flow->nw_proto == IPPROTO_ICMPV6) {
            if (parse_icmpv6(&b, flow)) {
                packet->l7 = b.data;
            }
        }
    } else if (flow->dl_type == htons(ETH_TYPE_ARP) ||
               flow->dl_type == htons(ETH_TYPE_RARP)) {
        const struct arp_eth_header *arp = pull_arp(&b);
        if (arp && arp->ar_hrd == htons(1)
            && arp->ar_pro == htons(ETH_TYPE_IP)
            && arp->ar_hln == ETH_ADDR_LEN
            && arp->ar_pln == 4) {
            /* We only match on the lower 8 bits of the opcode. */
            if (ntohs(arp->ar_op) <= 0xff) {
                flow->nw_proto = ntohs(arp->ar_op);
            }

            flow->nw_src = get_16aligned_be32(&arp->ar_spa);
            flow->nw_dst = get_16aligned_be32(&arp->ar_tpa);
            memcpy(flow->arp_sha, arp->ar_sha, ETH_ADDR_LEN);
            memcpy(flow->arp_tha, arp->ar_tha, ETH_ADDR_LEN);
        }
    }
}
Ejemplo n.º 9
0
/* Initializes l3 and higher 'flow' members from 'packet'
 *
 * This should be called by or after flow_extract()
 *
 * Initializes 'packet' header pointers as follows:
 *
 *    - packet->l4 to just past the IPv4 header, if one is present and has a
 *      correct length, and otherwise NULL.
 *
 *    - packet->l7 to just past the TCP or UDP or ICMP header, if one is
 *      present and has a correct length, and otherwise NULL.
 */
void
flow_extract_l3_onwards(struct ofpbuf *packet, struct flow *flow,
                        ovs_be16 dl_type)
{
    struct ofpbuf b;

    ofpbuf_use_const(&b, packet->l3, packet->size -
                     (size_t)((char *)packet->l3 - (char *)packet->l2));

    /* Network layer. */
    if (dl_type == htons(ETH_TYPE_IP)) {
        const struct ip_header *nh = pull_ip(&b);
        if (nh) {
            packet->l4 = b.data;

            flow->nw_src = get_unaligned_be32(&nh->ip_src);
            flow->nw_dst = get_unaligned_be32(&nh->ip_dst);
            flow->nw_proto = nh->ip_proto;

            flow->nw_tos = nh->ip_tos;
            if (IP_IS_FRAGMENT(nh->ip_frag_off)) {
                flow->nw_frag = FLOW_NW_FRAG_ANY;
                if (nh->ip_frag_off & htons(IP_FRAG_OFF_MASK)) {
                    flow->nw_frag |= FLOW_NW_FRAG_LATER;
                }
            }
            flow->nw_ttl = nh->ip_ttl;

            if (!(nh->ip_frag_off & htons(IP_FRAG_OFF_MASK))) {
                if (flow->nw_proto == IPPROTO_TCP) {
                    parse_tcp(packet, &b, flow);
                } else if (flow->nw_proto == IPPROTO_UDP) {
                    parse_udp(packet, &b, flow);
                } else if (flow->nw_proto == IPPROTO_ICMP) {
                    const struct icmp_header *icmp = pull_icmp(&b);
                    if (icmp) {
                        flow->tp_src = htons(icmp->icmp_type);
                        flow->tp_dst = htons(icmp->icmp_code);
                        packet->l7 = b.data;
                    }
                }
            }
        }
    } else if (dl_type == htons(ETH_TYPE_IPV6)) {
        if (parse_ipv6(&b, flow)) {
            return;
        }

        packet->l4 = b.data;
        if (flow->nw_proto == IPPROTO_TCP) {
            parse_tcp(packet, &b, flow);
        } else if (flow->nw_proto == IPPROTO_UDP) {
            parse_udp(packet, &b, flow);
        } else if (flow->nw_proto == IPPROTO_ICMPV6) {
            if (parse_icmpv6(&b, flow)) {
                packet->l7 = b.data;
            }
        }
    } else if (dl_type == htons(ETH_TYPE_ARP) ||
               dl_type == htons(ETH_TYPE_RARP)) {
        const struct arp_eth_header *arp = pull_arp(&b);
        if (arp && arp->ar_hrd == htons(1)
            && arp->ar_pro == htons(ETH_TYPE_IP)
            && arp->ar_hln == ETH_ADDR_LEN
            && arp->ar_pln == 4) {
            /* We only match on the lower 8 bits of the opcode. */
            if (ntohs(arp->ar_op) <= 0xff) {
                flow->nw_proto = ntohs(arp->ar_op);
            }

            flow->nw_src = arp->ar_spa;
            flow->nw_dst = arp->ar_tpa;
            memcpy(flow->arp_sha, arp->ar_sha, ETH_ADDR_LEN);
            memcpy(flow->arp_tha, arp->ar_tha, ETH_ADDR_LEN);
        }
    }
}
Ejemplo n.º 10
0
static int parse_hostport(int* type, struct ip_addr* ip, unsigned int* port, 
						  cfg_token_t* token, cfg_parser_t* st)
{
	int ret;
	cfg_token_t t;
    cfg_option_t* opt;

	ret = cfg_get_token(&t, st, 0);
	if (ret < 0) return -1;
	if (ret > 0) {
		ERR("%s:%d:%d: Missing IP address\n", st->file, 
			token->start.line, token->start.col);
		return -1;
	}

	if (t.type == '[') {
		if (parse_ipv6(ip, &t, st) < 0) return -1;
	} else if (t.type == CFG_TOKEN_ALPHA) {
		opt = cfg_lookup_token(token_default, &t.val);
		if (opt) {
			*type = TLS_DOMAIN_DEF;
			     /* Default domain */
			return 0;
		} else {
			if (parse_ipv4(ip, &t, st) < 0) return -1;
		}
	} else {
		ERR("%s:%d:%d: Syntax error, IP address expected\n", 
		    st->file, t.start.line, t.start.col);
		return -1;
	}
	*type = 0;

	     /* Parse port */
	ret = cfg_get_token(&t, st, 0);
	if (ret < 0) return -1;
	if (ret > 0) {
		ERR("%s:%d:%d: Syntax error, ':' expected\n", st->file, st->line, 
			st->col);
		return -1;
	}
	
	if (t.type != ':') {
		ERR("%s:%d:%d: Syntax error, ':' expected\n", 
		    st->file, t.start.line, t.start.col);
		return -1;
	}	
	
	ret = cfg_get_token(&t, st, 0);
	if (ret < 0) return -1;
	if (ret > 0) {
		ERR("%s:%d:%d: Premature end of file, port number missing\n", 
		    st->file, t.start.line, t.start.col);
		return -1;
	}
	
	if (t.type != CFG_TOKEN_ALPHA || (str2int(&t.val, port) < 0)) {
		ERR("%s:%d:%d: Invalid port number '%.*s'\n", 
		    st->file, t.start.line, t.start.col, STR_FMT(&t.val));
		return -1;
	}		
	return 0;
}
Ejemplo n.º 11
0
/**
 * Simple packet parser: eth, VLAN, IP, TCP/UDP/ICMP
 *
 * Internal function: caller is resposible for passing only valid packet handles
 * , lengths and offsets (usually done&called in packet input).
 *
 * @param pkt        Packet handle
 * @param len        Packet length in bytes
 * @param frame_offset  Byte offset to L2 header
 */
void odp_packet_parse(odp_packet_t pkt, size_t len, size_t frame_offset)
{
	odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt);
	odp_ethhdr_t *eth;
	odp_vlanhdr_t *vlan;
	odp_ipv4hdr_t *ipv4;
	odp_ipv6hdr_t *ipv6;
	uint16_t ethtype;
	size_t offset = 0;
	uint8_t ip_proto = 0;

	pkt_hdr->input_flags.eth = 1;
	pkt_hdr->frame_offset = frame_offset;
	pkt_hdr->frame_len = len;

	if (odp_unlikely(len < ODP_ETH_LEN_MIN)) {
		pkt_hdr->error_flags.frame_len = 1;
		return;
	} else if (len > ODP_ETH_LEN_MAX) {
		pkt_hdr->input_flags.jumbo = 1;
	}

	/* Assume valid L2 header, no CRC/FCS check in SW */
	pkt_hdr->input_flags.l2 = 1;
	pkt_hdr->l2_offset = frame_offset;

	eth = (odp_ethhdr_t *)odp_packet_start(pkt);
	ethtype = odp_be_to_cpu_16(eth->type);
	vlan = (odp_vlanhdr_t *)&eth->type;

	if (ethtype == ODP_ETHTYPE_VLAN_OUTER) {
		pkt_hdr->input_flags.vlan_qinq = 1;
		ethtype = odp_be_to_cpu_16(vlan->tpid);
		offset += sizeof(odp_vlanhdr_t);
		vlan = &vlan[1];
	}

	if (ethtype == ODP_ETHTYPE_VLAN) {
		pkt_hdr->input_flags.vlan = 1;
		ethtype = odp_be_to_cpu_16(vlan->tpid);
		offset += sizeof(odp_vlanhdr_t);
	}

	/* Set l3_offset+flag only for known ethtypes */
	switch (ethtype) {
	case ODP_ETHTYPE_IPV4:
		pkt_hdr->input_flags.ipv4 = 1;
		pkt_hdr->input_flags.l3 = 1;
		pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN + offset;
		ipv4 = (odp_ipv4hdr_t *)odp_packet_l3(pkt);
		ip_proto = parse_ipv4(pkt_hdr, ipv4, &offset);
		break;
	case ODP_ETHTYPE_IPV6:
		pkt_hdr->input_flags.ipv6 = 1;
		pkt_hdr->input_flags.l3 = 1;
		pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN + offset;
		ipv6 = (odp_ipv6hdr_t *)odp_packet_l3(pkt);
		ip_proto = parse_ipv6(pkt_hdr, ipv6, &offset);
		break;
	case ODP_ETHTYPE_ARP:
		pkt_hdr->input_flags.arp = 1;
		/* fall through */
	default:
		ip_proto = 0;
		break;
	}

	switch (ip_proto) {
	case ODP_IPPROTO_UDP:
		pkt_hdr->input_flags.udp = 1;
		pkt_hdr->input_flags.l4 = 1;
		pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
		break;
	case ODP_IPPROTO_TCP:
		pkt_hdr->input_flags.tcp = 1;
		pkt_hdr->input_flags.l4 = 1;
		pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
		break;
	case ODP_IPPROTO_SCTP:
		pkt_hdr->input_flags.sctp = 1;
		pkt_hdr->input_flags.l4 = 1;
		pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
		break;
	case ODP_IPPROTO_ICMP:
		pkt_hdr->input_flags.icmp = 1;
		pkt_hdr->input_flags.l4 = 1;
		pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
		break;
	default:
		/* 0 or unhandled IP protocols, don't set L4 flag+offset */
		if (pkt_hdr->input_flags.ipv6) {
			/* IPv6 next_hdr is not L4, mark as IP-option instead */
			pkt_hdr->input_flags.ipopt = 1;
		}
		break;
	}
}
Ejemplo n.º 12
0
Archivo: if.c Proyecto: yellowman/nsh
int
intip(char *ifname, int ifs, int argc, char **argv)
{
	int s, set, flags, argcmax;
	char *msg, *cmdname;
	ip_t ip;
	/* ipv4 structures */
	struct in_addr in4dest;
	struct ifaliasreq ip4req;
	/* ipv6 structures */
	struct in6_addr in6dest;
	struct in6_aliasreq ip6req;

	if (NO_ARG(argv[0])) {
		set = 0;
		argc--;
		argv++;
	} else
		set = 1;

	/*
	 * We use this function for ip and alias setup since they are
	 * the same thing.
	 */
	if (isprefix(argv[0], "alias")) {
		cmdname = "alias";
	} else if (isprefix(argv[0], "ip")) {
		cmdname = "ip";
	} else {
		printf("%% intip: Internal error\n");
		return 0;
	}

	argc--;
	argv++;

	flags = get_ifflags(ifname, ifs);
	if (flags & IFF_POINTOPOINT) {
		argcmax = 2;
		msg = "destination";
	} else if (flags & IFF_BROADCAST) {
		argcmax = 2;
		msg = "broadcast";
	} else {
		argcmax = 1;
		msg = NULL;
	}

	if (argc < 1 || argc > argcmax) {
		printf("%% %s <address>/<bits> %s%s%s\n", cmdname,
		    msg ? "[" : "", msg ? msg : "", msg ? "]" : "");
		printf("%% %s <address>/<netmask> %s%s%s\n", cmdname,
		    msg ? "[" : "", msg ? msg : "", msg ? "]" : "");
		printf("%% no %s <address>[/bits]\n", cmdname);
		printf("%% no %s <address>[/netmask]\n", cmdname);
		return(0);
	}

	/* ignore 'address' keyword, don't print error */
	if (isprefix(argv[0], "address")) {
		argc--;
		argv++;
	}

	if (isprefix(argv[0], "dhcp")) {
		char *args[] = { PKILL, "dhclient", ifname, '\0' };
		char *args_set[] = { DHCLIENT, ifname, '\0' };
		char leasefile[sizeof(LEASEPREFIX)+1+IFNAMSIZ];

		if (set)
			cmdargs(DHCLIENT, args_set);
		else {
			cmdargs(PKILL, args);
			snprintf(leasefile, sizeof(leasefile), "%s.%s",
			    LEASEPREFIX, ifname);
			rmtemp(leasefile);
		}
		return(0);
	}

	memset(&ip, 0, sizeof(ip));
	parse_ip_pfx(argv[0], NO_NETMASK, &ip);

	if (ip.family == 0)
		/* bad IP specified */
		return(0);

	if (set && !(flags & IFF_POINTOPOINT) && ip.bitlen == -1) {
		printf("%% Netmask not specified\n");
		return(0);
	}
	
	if (ip.bitlen == -1) {
		/*
		 * No netmask specified, set the field at 0.
		 * The kernel mostly ignores netmask for PTP interfaces,
		 * but won't allow anything less than a /128 for an IPv6
		 * PTP interface.
		 */
		if (!(flags & IFF_POINTOPOINT))
			ip.bitlen = 0;
		else if (ip.family == AF_INET)
			ip.bitlen = 32;
		else if (ip.family == AF_INET6)
			ip.bitlen = 128;
	}

	switch(ip.family) {
	case AF_INET:
		memset(&in4dest, 0, sizeof(in4dest));
		if (argc == 2 && !inet_pton(AF_INET, argv[1], &in4dest)) {
			printf("%% Invalid %s address\n", msg);
			return(0);
		}
		memset(&ip4req, 0, sizeof(ip4req));
		pack_ifaliasreq(&ip4req, &ip, &in4dest, ifname);
		/* do it */
		if (ioctl(ifs, set ? SIOCAIFADDR : SIOCDIFADDR, &ip4req) < 0)
			printf("%% intip: SIOC%sIFADDR: %s\n", set ? "A" : "D",
			    strerror(errno));
		break;
	case AF_INET6:
		memset(&in6dest, 0, sizeof(in6dest));
		if (argc == 2 && parse_ipv6(argv[1], &in6dest) != 0) {
			printf("%% Invalid destination address %s\n", argv[1]);
			return(0);
		}
		memset(&ip6req, 0, sizeof(ip6req));
		pack_in6aliasreq(&ip6req, &ip, &in6dest, ifname);
		/* get inet6 socket */
		s = socket(PF_INET6, SOCK_DGRAM, 0);
		if (s < 0) {
			printf("%% socket failed: %s\n", strerror(errno));
			return(0);
		}
		/* turn on inet6 */
		addaf(ifname, AF_INET6, ifs);
		/* do it */
		if (ioctl(s, set ? SIOCAIFADDR_IN6 : SIOCDIFADDR_IN6, &ip6req)
		    < 0) {
			if (!set && errno == EADDRNOTAVAIL)
				printf("%% IP address not found on %s\n",
				    ifname);
			else
				printf("%% intip: SIOC%sIFADDR_IN6: %s\n",
				    set ? "A" : "D", strerror(errno));
		} else {
			ipv6ll_db_store(
			    (struct sockaddr_in6 *)&ip6req.ifra_addr,
			    (struct sockaddr_in6 *)&ip6req.ifra_prefixmask,
			    set ? DB_X_ENABLE : DB_X_REMOVE, ifname);
		}
		close(s);
		break;
	default:
		printf("%% unknown address family: %d\n", ip.family);
		break;
	}
	return(0);
}
Ejemplo n.º 13
0
static int parse_layer2_packet(struct packet *packet, int in_bytes,
				       char **error)
{
	u8 *p = packet->buffer;
	/* Note that packet_end points to the byte beyond the end of packet. */
	u8 *packet_end = packet->buffer + in_bytes;
	struct ether_header *ether = NULL;

	/* Find Ethernet header */
	if (p + sizeof(*ether) > packet_end) {
		asprintf(error, "Ethernet header overflows packet");
		goto error_out;
	}
	ether = (struct ether_header *)p;
	p += sizeof(*ether);

	if (ntohs(ether->ether_type) == ETHERTYPE_IP) {
		struct ipv4 *ip = NULL;

		/* Examine IPv4 header. */
		if (p + sizeof(struct ipv4) > packet_end) {
			asprintf(error, "IPv4 header overflows packet");
			goto error_out;
		}

		/* Look at the IP version number, which is in the first 4 bits
		 * of both IPv4 and IPv6 packets.
		 */
		ip = (struct ipv4 *)p;
		if (ip->version == 4) {
			return parse_ipv4(packet, p, packet_end, error);
		} else {
			asprintf(error, "Bad IP version for ETHERTYPE_IP");
			goto error_out;
		}
	} else if (ntohs(ether->ether_type) == ETHERTYPE_IPV6) {
		struct ipv6 *ip = NULL;

		/* Examine IPv6 header. */
		if (p + sizeof(struct ipv6) > packet_end) {
			asprintf(error, "IPv6 header overflows packet");
			goto error_out;
		}

		/* Look at the IP version number, which is in the first 4 bits
		 * of both IPv4 and IPv6 packets.
		 */
		ip = (struct ipv6 *)p;
		if (ip->version == 6) {
			return parse_ipv6(packet, p, packet_end, error);
		} else {
			asprintf(error, "Bad IP version for ETHERTYPE_IPV6");
			goto error_out;
		}
	} else {
		return PACKET_UNKNOWN_L4;
	}

error_out:
	return PACKET_BAD;
}
/* Initializes 'flow' members from 'packet', 'tun_id', and 'ofp_in_port'.
 * Initializes 'packet' header pointers as follows:
 *
 *    - packet->l2 to the start of the Ethernet header.
 *
 *    - packet->l3 to just past the Ethernet header, or just past the
 *      vlan_header if one is present, to the first byte of the payload of the
 *      Ethernet frame.
 *
 *    - packet->l4 to just past the IPv4 header, if one is present and has a
 *      correct length, and otherwise NULL.
 *
 *    - packet->l7 to just past the TCP or UDP or ICMP header, if one is
 *      present and has a correct length, and otherwise NULL.
 */
void
flow_extract(struct ofpbuf *packet, uint32_t priority, ovs_be64 tun_id,
             uint16_t ofp_in_port, struct flow *flow)
{
    struct ofpbuf b = *packet;
    struct eth_header *eth;

    COVERAGE_INC(flow_extract);

    memset(flow, 0, sizeof *flow);
    flow->tun_id = tun_id;
    flow->in_port = ofp_in_port;
    flow->priority = priority;

    packet->l2 = b.data;
    packet->l3 = NULL;
    packet->l4 = NULL;
    packet->l7 = NULL;

    if (b.size < sizeof *eth) {
        return;
    }

    /* Link layer. */
    eth = b.data;
    memcpy(flow->dl_src, eth->eth_src, ETH_ADDR_LEN);
    memcpy(flow->dl_dst, eth->eth_dst, ETH_ADDR_LEN);

    /* dl_type, vlan_tci. */
    ofpbuf_pull(&b, ETH_ADDR_LEN * 2);
    if (eth->eth_type == htons(ETH_TYPE_VLAN)) {
        parse_vlan(&b, flow);
    }
    flow->dl_type = parse_ethertype(&b);

    /* Network layer. */
    packet->l3 = b.data;
    if (flow->dl_type == htons(ETH_TYPE_IP)) {
        const struct ip_header *nh = pull_ip(&b);
        if (nh) {
            packet->l4 = b.data;

            flow->nw_src = get_unaligned_be32(&nh->ip_src);
            flow->nw_dst = get_unaligned_be32(&nh->ip_dst);
            flow->nw_proto = nh->ip_proto;

            flow->nw_tos = nh->ip_tos;
            if (IP_IS_FRAGMENT(nh->ip_frag_off)) {
                flow->nw_frag = FLOW_NW_FRAG_ANY;
                if (nh->ip_frag_off & htons(IP_FRAG_OFF_MASK)) {
                    flow->nw_frag |= FLOW_NW_FRAG_LATER;
                }
            }
            flow->nw_ttl = nh->ip_ttl;

            if (!(nh->ip_frag_off & htons(IP_FRAG_OFF_MASK))) {
                if (flow->nw_proto == IPPROTO_TCP) {
                    parse_tcp(packet, &b, flow);
                } else if (flow->nw_proto == IPPROTO_UDP) {
                    parse_udp(packet, &b, flow);
                } else if (flow->nw_proto == IPPROTO_ICMP) {
                    const struct icmp_header *icmp = pull_icmp(&b);
                    if (icmp) {
                        flow->tp_src = htons(icmp->icmp_type);
                        flow->tp_dst = htons(icmp->icmp_code);
                        packet->l7 = b.data;
                    }
                }
            }
        }
    } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
        if (parse_ipv6(&b, flow)) {
            return;
        }

        packet->l4 = b.data;
        if (flow->nw_proto == IPPROTO_TCP) {
            parse_tcp(packet, &b, flow);
        } else if (flow->nw_proto == IPPROTO_UDP) {
            parse_udp(packet, &b, flow);
        } else if (flow->nw_proto == IPPROTO_ICMPV6) {
            if (parse_icmpv6(&b, flow)) {
                packet->l7 = b.data;
            }
        }
    } else if (flow->dl_type == htons(ETH_TYPE_ARP)) {
        const struct arp_eth_header *arp = pull_arp(&b);
        if (arp && arp->ar_hrd == htons(1)
            && arp->ar_pro == htons(ETH_TYPE_IP)
            && arp->ar_hln == ETH_ADDR_LEN
            && arp->ar_pln == 4) {
            /* We only match on the lower 8 bits of the opcode. */
            if (ntohs(arp->ar_op) <= 0xff) {
                flow->nw_proto = ntohs(arp->ar_op);
            }

            if ((flow->nw_proto == ARP_OP_REQUEST)
                || (flow->nw_proto == ARP_OP_REPLY)) {
                flow->nw_src = arp->ar_spa;
                flow->nw_dst = arp->ar_tpa;
                memcpy(flow->arp_sha, arp->ar_sha, ETH_ADDR_LEN);
                memcpy(flow->arp_tha, arp->ar_tha, ETH_ADDR_LEN);
            }
        }
    }
}
Ejemplo n.º 15
0
static bool update_service_property(DBusMessageIter *arg, void *user_data)
{
	struct connman_service *service = user_data;
	const char *name, *value;
	gboolean boolean_value;
	char **array;
	int length;

	if (cui_dbus_get_basic(arg, DBUS_TYPE_STRING, &name) != 0)
		return FALSE;

	dbus_message_iter_next(arg);

	if (g_strcmp0(name, "Name") == 0) {
		cui_dbus_get_basic_variant(arg, DBUS_TYPE_STRING, &value);
		service->name = g_strdup(value);
	} else if (g_strcmp0(name, "Type") == 0) {
		cui_dbus_get_basic_variant(arg, DBUS_TYPE_STRING, &value);
		service->type = g_strdup(value);
	} else if (g_strcmp0(name, "Security") == 0) {
		cui_dbus_get_array(arg, DBUS_TYPE_STRING, &length, &array);

		g_free(service->security);
		if (array != NULL) {
			service->security = g_strjoinv(";", array);
			g_free(array);
		} else
			service->security = NULL;
	} else if (g_strcmp0(name, "Immutable") == 0) {
		cui_dbus_get_basic_variant(arg,
				DBUS_TYPE_BOOLEAN, &boolean_value);
		service->immutable = boolean_value;
	} else if (g_strcmp0(name, PROPERTY(SERVICE_STATE)) == 0) {
		cui_dbus_get_basic_variant(arg, DBUS_TYPE_STRING, &value);

		service->state = string2enum_state(value);

		service->update_index = SERVICE_STATE;
	} else if (g_strcmp0(name, PROPERTY(SERVICE_ERROR)) == 0) {
		cui_dbus_get_basic_variant(arg, DBUS_TYPE_STRING, &value);

		g_free(service->error);
		service->error = g_strdup(value);

		service->update_index = SERVICE_ERROR;
	} else if (g_strcmp0(name, PROPERTY(SERVICE_STRENGTH)) == 0) {
		uint8_t uint8_value;

		cui_dbus_get_basic_variant(arg, DBUS_TYPE_BYTE, &uint8_value);
		service->strength = uint8_value;

		service->update_index = SERVICE_STRENGTH;
	} else if (g_strcmp0(name, PROPERTY(SERVICE_FAVORITE)) == 0) {
		cui_dbus_get_basic_variant(arg,
				DBUS_TYPE_BOOLEAN, &boolean_value);
		service->favorite = boolean_value;

		service->update_index = SERVICE_FAVORITE;
	} else if (g_strcmp0(name, PROPERTY(SERVICE_AUTOCONNECT)) == 0) {
		cui_dbus_get_basic_variant(arg,
				DBUS_TYPE_BOOLEAN, &boolean_value);
		service->autoconnect = boolean_value;

		service->update_index = SERVICE_AUTOCONNECT;
	} else if (g_strcmp0(name, PROPERTY(SERVICE_ROAMING)) == 0) {
		cui_dbus_get_basic_variant(arg,
				DBUS_TYPE_BOOLEAN, &boolean_value);
		service->roaming = boolean_value;

		service->update_index = SERVICE_ROAMING;
	} else if (g_strcmp0(name, PROPERTY(SERVICE_NAMESERVERS)) == 0) {
		cui_dbus_get_array(arg, DBUS_TYPE_STRING, &length, &array);

		g_free(service->nameservers);
		if (array != NULL) {
			service->nameservers = g_strjoinv(";", array);
			g_free(array);
		} else
			service->nameservers = NULL;

		service->update_index = SERVICE_NAMESERVERS;
	} else if (g_strcmp0(name,
			PROPERTY(SERVICE_NAMESERVERS_CONFIGURATION)) == 0) {
		cui_dbus_get_array(arg, DBUS_TYPE_STRING, &length, &array);

		g_free(service->nameservers_conf);
		if (array != NULL) {
			service->nameservers_conf = g_strjoinv(";", array);
			g_free(array);
		} else
			 service->nameservers_conf = NULL;

		service->update_index = SERVICE_NAMESERVERS_CONFIGURATION;
	} else if (g_strcmp0(name, PROPERTY(SERVICE_DOMAINS)) == 0) {
		cui_dbus_get_array(arg, DBUS_TYPE_STRING, &length, &array);

		g_free(service->domains);
		if (array != NULL) {
			service->domains = g_strjoinv(";", array);
			g_free(array);
		} else
			service->domains = NULL;

		service->update_index = SERVICE_DOMAINS;
	} else if (g_strcmp0(name,
			PROPERTY(SERVICE_DOMAINS_CONFIGURATION)) == 0) {
		cui_dbus_get_array(arg, DBUS_TYPE_STRING, &length, &array);

		g_free(service->domains_conf);
		if (array != NULL) {
			service->domains_conf = g_strjoinv(";", array);
			g_free(array);
		} else
			service->domains_conf = NULL;

		service->update_index = SERVICE_DOMAINS_CONFIGURATION;
	} else if (g_strcmp0(name, PROPERTY(SERVICE_TIMESERVERS)) == 0) {
		cui_dbus_get_array(arg, DBUS_TYPE_STRING, &length, &array);

		g_free(service->timeservers);
		if (array != NULL) {
			service->timeservers = g_strjoinv(";", array);
			g_free(array);
		} else
			service->timeservers = NULL;

		service->update_index = SERVICE_TIMESERVERS;
	} else if (g_strcmp0(name,
			PROPERTY(SERVICE_TIMESERVERS_CONFIGURATION)) == 0) {
		cui_dbus_get_array(arg, DBUS_TYPE_STRING, &length, &array);

		g_free(service->timeservers_conf);
		if (array != NULL) {
			service->timeservers_conf = g_strjoinv(";", array);
			g_free(array);
		} else
			service->timeservers_conf = NULL;

		service->update_index = SERVICE_TIMESERVERS_CONFIGURATION;
	} else if (g_strcmp0(name, PROPERTY(SERVICE_IPv4)) == 0) {
		service->ipv4 = parse_ipv4(arg, service->ipv4);
		service->update_index = SERVICE_IPv4;
	} else if (g_strcmp0(name,
			PROPERTY(SERVICE_IPv4_CONFIGURATION)) == 0) {
		service->ipv4_conf = parse_ipv4(arg, service->ipv4_conf);
		service->update_index = SERVICE_IPv4_CONFIGURATION;
	} else if (g_strcmp0(name, PROPERTY(SERVICE_IPv6)) == 0) {
		service->ipv6 = parse_ipv6(arg, service->ipv6);
		service->update_index = SERVICE_IPv6;
	} else if (g_strcmp0(name,
			PROPERTY(SERVICE_IPv6_CONFIGURATION)) == 0) {
		service->ipv6_conf = parse_ipv6(arg, service->ipv6_conf);
		service->update_index = SERVICE_IPv6_CONFIGURATION;
	} else if (g_strcmp0(name, PROPERTY(SERVICE_PROXY)) == 0) {
		service->proxy = parse_proxy(arg, service->proxy);
		service->update_index = SERVICE_PROXY;
	} else if (g_strcmp0(name,
			PROPERTY(SERVICE_PROXY_CONFIGURATION)) == 0) {
		service->proxy_conf = parse_proxy(arg, service->proxy_conf);
		service->update_index = SERVICE_PROXY_CONFIGURATION;
	} else if (g_strcmp0(name, PROPERTY(SERVICE_PROVIDER)) == 0) {
		service->provider = parse_provider(arg, service->provider);
		service->update_index = SERVICE_PROVIDER;
	} else if (g_strcmp0(name, PROPERTY(SERVICE_ETHERNET)) == 0) {
		service->ethernet = parse_ethernet(arg, service->ethernet);
		service->update_index = SERVICE_ETHERNET;
	}

	return FALSE;
}