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; }
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; }
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; }
/* 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; }
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); }
/* 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; }
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; }
/* 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); } } }
/* 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); } } }
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; }
/** * 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 *)ð->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; } }
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); }
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); } } } }
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; }