static int parse_ipv6_net(const char *in, struct rte_acl_field field[4]) { int32_t rc; const char *mp; uint32_t i, m, v[4]; const uint32_t nbu32 = sizeof(uint32_t) * CHAR_BIT; // TODO may be replaced by inet_pton with some refactoring /* get address. */ rc = parse_ipv6_addr(in, &mp, v, '/'); if (rc != 0) return rc; /* get mask. */ GET_CB_FIELD(mp, m, 0, CHAR_BIT * sizeof(v), 0); /* put all together. */ for (i = 0; i != RTE_DIM(v); i++) { if (m >= (i + 1) * nbu32) field[i].mask_range.u32 = nbu32; else field[i].mask_range.u32 = m > (i * nbu32) ? m - (i * 32) : 0; field[i].value.u32 = v[i]; } return 0; }
/** * Parses IPv4 and IPv6 addresses. The latter requires IPv6 support to be * enabled. * * For convenience, if the first character is '[' then the address is parsed * as an IPv6 one and the trailing ']' is both expected and swallowed. This * allows the routine to be used when parsing "ipv4:port" or "[ipv6]:port" * strings. * * @param s The string to parse. * @param endptr This will point to the first character after the parsed * address. * @param addr_ptr If not NULL, it is set to the parsed host address or * ``zero_host_addr'' on failure. * @return Returns TRUE on success; otherwise FALSE. */ bool string_to_host_addr(const char *s, const char **endptr, host_addr_t *addr_ptr) { uint32 ip; bool brackets = FALSE; g_assert(s); if ('[' == *s) { brackets = TRUE; s++; } if (!brackets && string_to_ip_strict(s, &ip, endptr)) { if (addr_ptr) { *addr_ptr = host_addr_get_ipv4(ip); } return TRUE; } else { uint8 ipv6[16]; const char *end; bool ok; ok = parse_ipv6_addr(s, ipv6, &end); if (ok) { if (addr_ptr) { *addr_ptr = host_addr_peek_ipv6(ipv6); } if (brackets) { if (']' == *end) { end++; } else { ok = FALSE; /* Trailing ']' required if we had '[' */ } } } if (endptr != NULL) *endptr = end; if (ok) return TRUE; /* FALL THROUGH */ } if (addr_ptr) *addr_ptr = zero_host_addr; return FALSE; }
void Alpha::functionTaskTask0() { ipstack::Interface* interface = setupEthernet(); if (interface==0) { // ethernet setup failed System::haltsystem(); } // You can ping CiAO IP now by using // * ping 10.0.3.2 (for icmp ping) // * ping6 fe80::6655:44ff:fe33:2211%tap0 (for icmp ping with ipv6 on tap0 device) // * echoping -u 10.0.3.2 (for udp ping; use ipv4 addresses, ipv6 is not supported by echoping for udp) // * sendip -p ipv6 -p udp -us 5070 -ud 8 -d "Hello" -v fe80::6655:44ff:fe33:2211 (for ipv6 udp ping) // * telnet 10.0.3.2 (for testing the tcp reset capability; use ipv4 or ipv6 address) // * Send udp to port 88 to get it printed out // Setup test ipv6 address: we will ping that address (and test the ndp address resolution) ipstack::ipv6addr testipv6; if (!parse_ipv6_addr("fe80:0:0:0:a81a:54ff:fef0:3f", testipv6)) { System::haltsystem(); } ICMPv6_Socket &icmpv6instance = ICMPv6_Socket::instance(); icmpv6instance.ipv6.set_dst_addr(testipv6); // src address is determined automatically // Setup test ipv4 address: we will ping that address (and test the arp address resolution) UInt32 testipv4 = IPv4_Packet::convert_ipv4_addr(10,0,3,1); ICMPv4_Socket &icmpv4instance = ICMPv4_Socket::instance(); icmpv4instance.ipv4.set_dst_addr(testipv4); // src address has been set above SendBuffer* sbi; const char teststring[] = "HELLO"; IP::UDP_Socket<1514,1,128,2> socket; socket.set_sport(88); socket.bind(); // listen printf("Send IPv4 ping\n"); sbi = icmpv4instance.requestSendBuffer(ICMP_Packet::ICMP_HEADER_SIZE+sizeof(teststring)); if (sbi) { sbi->mark("IPv4 ping"); ICMP_Packet* icmp = (ICMP_Packet*)sbi->getDataPointer(); icmp->set_type(ICMP_Packet::ICMP_TYPE_ECHO_REQUEST); icmp->set_code(ICMP_Packet::ICMP_CODE_ECHO); sbi->writtenToDataPointer(ICMP_Packet::ICMP_HEADER_SIZE); sbi->write(teststring, sizeof(teststring)); icmpv4instance.send(sbi); } printf("Send IPv6 ping\n"); sbi = icmpv6instance.requestSendBuffer(ICMPv6_Packet::ICMP_HEADER_SIZE+sizeof(teststring)+sizeof(UInt32)); if (sbi) { sbi->mark("IPv6 ping"); ICMPv6_Packet* icmp = (ICMPv6_Packet*)sbi->getDataPointer(); icmp->set_type(ICMPv6_Packet::ICMP_TYPE_ECHO_REQUEST); icmp->set_code(ICMPv6_Packet::ICMP_CODE_ECHO_REQUEST); sbi->writtenToDataPointer(ICMPv6_Packet::ICMP_HEADER_SIZE); // write seq and id UInt32 idAndSeq = 0xcaffee; sbi->write(&idAndSeq, sizeof(idAndSeq)); // write payload sbi->write(teststring, sizeof(teststring)); icmpv6instance.send(sbi); } printf("Start udp listen on port %u\n", socket.get_sport()); while(1) { ReceiveBuffer* rbuffer = socket.receiveBlock(); ReceiveBufferUDPIPv6* ipv6udp = ReceiveBufferUDPIPv6::cast(rbuffer); ReceiveBufferUDPIPv4* ipv4udp = ReceiveBufferUDPIPv4::cast(rbuffer); if (ipv6udp) { printf("Received IPv6/UDP. Bytes: %u\n", rbuffer->getSize()); char ipstrbuffer[50] = {0}; ipstack::ipv6_addr_toString(ipv6udp->getRemoteInfo()->ipv6, ipstrbuffer); printf(" Remote IPv6-Address: %s, Port: %u\n", ipstrbuffer, ipv4udp->getRemoteInfo()->remoteport); } else if (ipv4udp) { printf("Received IPv4/UDP. Bytes: %u\n", rbuffer->getSize()); UInt8 a,b,c,d; IPv4_Packet::convert_ipv4_addr(ipv4udp->getRemoteInfo()->ipv4, a, b, c, d); printf(" Remote IPv4-Address: %u.%u.%u.%u, Port: %u\n", a,b,c,d, ipv4udp->getRemoteInfo()->remoteport); } else { printf("error, udp ip version unknown. Bytes: %u\n", rbuffer->getSize()); } ReceiveBuffer::free(rbuffer); } }
void parse_sp6_tokens(char **tokens, uint32_t n_tokens, struct parse_status *status) { struct acl6_rules *rule_ipv6 = NULL; uint32_t *ri = NULL; /* rule index */ uint32_t ti = 0; /* token index */ uint32_t esp_p = 0; uint32_t protect_p = 0; uint32_t bypass_p = 0; uint32_t discard_p = 0; uint32_t pri_p = 0; uint32_t src_p = 0; uint32_t dst_p = 0; uint32_t proto_p = 0; uint32_t sport_p = 0; uint32_t dport_p = 0; if (strcmp(tokens[1], "in") == 0) { ri = &nb_acl6_rules_in; APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too " "many sp rules, abort insertion\n"); if (status->status < 0) return; rule_ipv6 = &acl6_rules_in[*ri]; } else if (strcmp(tokens[1], "out") == 0) { ri = &nb_acl6_rules_out; APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too " "many sp rules, abort insertion\n"); if (status->status < 0) return; rule_ipv6 = &acl6_rules_out[*ri]; } else { APP_CHECK(0, status, "unrecognized input \"%s\", expect" " \"in\" or \"out\"\n", tokens[ti]); return; } rule_ipv6->data.category_mask = 1; for (ti = 2; ti < n_tokens; ti++) { if (strcmp(tokens[ti], "esp") == 0) { /* currently do nothing */ APP_CHECK_PRESENCE(esp_p, tokens[ti], status); if (status->status < 0) return; esp_p = 1; continue; } if (strcmp(tokens[ti], "protect") == 0) { APP_CHECK_PRESENCE(protect_p, tokens[ti], status); if (status->status < 0) return; APP_CHECK(bypass_p == 0, status, "conflict item " "between \"%s\" and \"%s\"", tokens[ti], "bypass"); if (status->status < 0) return; APP_CHECK(discard_p == 0, status, "conflict item " "between \"%s\" and \"%s\"", tokens[ti], "discard"); if (status->status < 0) return; INCREMENT_TOKEN_INDEX(ti, n_tokens, status); if (status->status < 0) return; APP_CHECK_TOKEN_IS_NUM(tokens, ti, status); if (status->status < 0) return; rule_ipv6->data.userdata = PROTECT(atoi(tokens[ti])); protect_p = 1; continue; } if (strcmp(tokens[ti], "bypass") == 0) { APP_CHECK_PRESENCE(bypass_p, tokens[ti], status); if (status->status < 0) return; APP_CHECK(protect_p == 0, status, "conflict item " "between \"%s\" and \"%s\"", tokens[ti], "protect"); if (status->status < 0) return; APP_CHECK(discard_p == 0, status, "conflict item " "between \"%s\" and \"%s\"", tokens[ti], "discard"); if (status->status < 0) return; rule_ipv6->data.userdata = BYPASS; bypass_p = 1; continue; } if (strcmp(tokens[ti], "discard") == 0) { APP_CHECK_PRESENCE(discard_p, tokens[ti], status); if (status->status < 0) return; APP_CHECK(protect_p == 0, status, "conflict item " "between \"%s\" and \"%s\"", tokens[ti], "protect"); if (status->status < 0) return; APP_CHECK(bypass_p == 0, status, "conflict item " "between \"%s\" and \"%s\"", tokens[ti], "discard"); if (status->status < 0) return; rule_ipv6->data.userdata = DISCARD; discard_p = 1; continue; } if (strcmp(tokens[ti], "pri") == 0) { APP_CHECK_PRESENCE(pri_p, tokens[ti], status); if (status->status < 0) return; INCREMENT_TOKEN_INDEX(ti, n_tokens, status); if (status->status < 0) return; APP_CHECK_TOKEN_IS_NUM(tokens, ti, status); if (status->status < 0) return; rule_ipv6->data.priority = atoi(tokens[ti]); pri_p = 1; continue; } if (strcmp(tokens[ti], "src") == 0) { struct in6_addr ip; uint32_t depth; APP_CHECK_PRESENCE(src_p, tokens[ti], status); if (status->status < 0) return; INCREMENT_TOKEN_INDEX(ti, n_tokens, status); if (status->status < 0) return; APP_CHECK(parse_ipv6_addr(tokens[ti], &ip, &depth) == 0, status, "unrecognized " "input \"%s\", expect valid ipv6 " "addr", tokens[ti]); if (status->status < 0) return; rule_ipv6->field[1].value.u32 = (uint32_t)ip.s6_addr[0] << 24 | (uint32_t)ip.s6_addr[1] << 16 | (uint32_t)ip.s6_addr[2] << 8 | (uint32_t)ip.s6_addr[3]; rule_ipv6->field[1].mask_range.u32 = (depth > 32) ? 32 : depth; depth = (depth > 32) ? (depth - 32) : 0; rule_ipv6->field[2].value.u32 = (uint32_t)ip.s6_addr[4] << 24 | (uint32_t)ip.s6_addr[5] << 16 | (uint32_t)ip.s6_addr[6] << 8 | (uint32_t)ip.s6_addr[7]; rule_ipv6->field[2].mask_range.u32 = (depth > 32) ? 32 : depth; depth = (depth > 32) ? (depth - 32) : 0; rule_ipv6->field[3].value.u32 = (uint32_t)ip.s6_addr[8] << 24 | (uint32_t)ip.s6_addr[9] << 16 | (uint32_t)ip.s6_addr[10] << 8 | (uint32_t)ip.s6_addr[11]; rule_ipv6->field[3].mask_range.u32 = (depth > 32) ? 32 : depth; depth = (depth > 32) ? (depth - 32) : 0; rule_ipv6->field[4].value.u32 = (uint32_t)ip.s6_addr[12] << 24 | (uint32_t)ip.s6_addr[13] << 16 | (uint32_t)ip.s6_addr[14] << 8 | (uint32_t)ip.s6_addr[15]; rule_ipv6->field[4].mask_range.u32 = (depth > 32) ? 32 : depth; src_p = 1; continue; } if (strcmp(tokens[ti], "dst") == 0) { struct in6_addr ip; uint32_t depth; APP_CHECK_PRESENCE(dst_p, tokens[ti], status); if (status->status < 0) return; INCREMENT_TOKEN_INDEX(ti, n_tokens, status); if (status->status < 0) return; APP_CHECK(parse_ipv6_addr(tokens[ti], &ip, &depth) == 0, status, "unrecognized " "input \"%s\", expect valid ipv6 " "addr", tokens[ti]); if (status->status < 0) return; rule_ipv6->field[5].value.u32 = (uint32_t)ip.s6_addr[0] << 24 | (uint32_t)ip.s6_addr[1] << 16 | (uint32_t)ip.s6_addr[2] << 8 | (uint32_t)ip.s6_addr[3]; rule_ipv6->field[5].mask_range.u32 = (depth > 32) ? 32 : depth; depth = (depth > 32) ? (depth - 32) : 0; rule_ipv6->field[6].value.u32 = (uint32_t)ip.s6_addr[4] << 24 | (uint32_t)ip.s6_addr[5] << 16 | (uint32_t)ip.s6_addr[6] << 8 | (uint32_t)ip.s6_addr[7]; rule_ipv6->field[6].mask_range.u32 = (depth > 32) ? 32 : depth; depth = (depth > 32) ? (depth - 32) : 0; rule_ipv6->field[7].value.u32 = (uint32_t)ip.s6_addr[8] << 24 | (uint32_t)ip.s6_addr[9] << 16 | (uint32_t)ip.s6_addr[10] << 8 | (uint32_t)ip.s6_addr[11]; rule_ipv6->field[7].mask_range.u32 = (depth > 32) ? 32 : depth; depth = (depth > 32) ? (depth - 32) : 0; rule_ipv6->field[8].value.u32 = (uint32_t)ip.s6_addr[12] << 24 | (uint32_t)ip.s6_addr[13] << 16 | (uint32_t)ip.s6_addr[14] << 8 | (uint32_t)ip.s6_addr[15]; rule_ipv6->field[8].mask_range.u32 = (depth > 32) ? 32 : depth; dst_p = 1; continue; } if (strcmp(tokens[ti], "proto") == 0) { uint16_t low, high; APP_CHECK_PRESENCE(proto_p, tokens[ti], status); if (status->status < 0) return; INCREMENT_TOKEN_INDEX(ti, n_tokens, status); if (status->status < 0) return; APP_CHECK(parse_range(tokens[ti], &low, &high) == 0, status, "unrecognized input \"%s\"" ", expect \"from:to\"", tokens[ti]); if (status->status < 0) return; APP_CHECK(low <= 0xff, status, "proto low " "over-limit"); if (status->status < 0) return; APP_CHECK(high <= 0xff, status, "proto high " "over-limit"); if (status->status < 0) return; rule_ipv6->field[0].value.u8 = (uint8_t)low; rule_ipv6->field[0].mask_range.u8 = (uint8_t)high; proto_p = 1; continue; } if (strcmp(tokens[ti], "sport") == 0) { uint16_t port_low, port_high; APP_CHECK_PRESENCE(sport_p, tokens[ti], status); if (status->status < 0) return; INCREMENT_TOKEN_INDEX(ti, n_tokens, status); if (status->status < 0) return; APP_CHECK(parse_range(tokens[ti], &port_low, &port_high) == 0, status, "unrecognized " "input \"%s\", expect \"port_from:" "port_to\"", tokens[ti]); if (status->status < 0) return; rule_ipv6->field[9].value.u16 = port_low; rule_ipv6->field[9].mask_range.u16 = port_high; sport_p = 1; continue; } if (strcmp(tokens[ti], "dport") == 0) { uint16_t port_low, port_high; APP_CHECK_PRESENCE(dport_p, tokens[ti], status); if (status->status < 0) return; INCREMENT_TOKEN_INDEX(ti, n_tokens, status); if (status->status < 0) return; APP_CHECK(parse_range(tokens[ti], &port_low, &port_high) == 0, status, "unrecognized " "input \"%s\", expect \"port_from:" "port_to\"", tokens[ti]); if (status->status < 0) return; rule_ipv6->field[10].value.u16 = port_low; rule_ipv6->field[10].mask_range.u16 = port_high; dport_p = 1; continue; } /* unrecognizeable input */ APP_CHECK(0, status, "unrecognized input \"%s\"", tokens[ti]); return; } /* check if argument(s) are missing */ APP_CHECK(esp_p == 1, status, "missing argument \"esp\""); if (status->status < 0) return; APP_CHECK(protect_p | bypass_p | discard_p, status, "missing " "argument \"protect\", \"bypass\", or \"discard\""); if (status->status < 0) return; *ri = *ri + 1; }
/** * Parse an IPv6 Geo IP line and record the range in the database. */ static void gip_parse_ipv6(const char *line, int linenum) { const char *end; uint16 code; int error; uint8 ip[16]; unsigned bits; /* * Each line looks like: * * 2a03:be00::/32 nl * * The leading part up to the space is the IPv6 network in CIDR format. * The trailing word is the 2-letter ISO country code. */ if (!parse_ipv6_addr(line, ip, &end)) { g_warning("%s, line %d: bad IPv6 network address \"%s\"", gip_source[GIP_IPV6].file, linenum, line); return; } if ('/' != *end) { g_warning("%s, line %d: missing network separator in \"%s\"", gip_source[GIP_IPV6].file, linenum, line); return; } bits = parse_uint(end + 1, &end, 10, &error); if (error) { g_warning("%s, line %d: cannot parse network bit amount in \"%s\"", gip_source[GIP_IPV6].file, linenum, line); return; } if (bits > 128) { g_warning("%s, line %d: invalid bit amount %u in \"%s\"", gip_source[GIP_IPV6].file, linenum, bits, line); return; } if (!is_ascii_space(*end)) { g_warning("%s, line %d: missing spaces after network in \"%s\"", gip_source[GIP_IPV6].file, linenum, line); return; } while (is_ascii_space(*end)) end++; if ('\0' == *end) { g_warning("%s, line %d: missing country code in \"%s\"", gip_source[GIP_IPV6].file, linenum, line); return; } code = iso3166_encode_cc(end); if (ISO3166_INVALID == code) { g_warning("%s, line %d: bad country code in \"%s\"", gip_source[GIP_IPV6].file, linenum, line); return; } error = iprange_add_cidr6(geo_db, ip, bits, (code + 1) << 1); if (IPR_ERR_OK != error) { g_warning("%s, line %d: cannot insert %s/%u: %s", gip_source[GIP_IPV6].file, linenum, ipv6_to_string(ip), bits, iprange_strerror(error)); } }
int app_pipeline_fc_load_file_ipv6(char *filename, struct pipeline_fc_key *keys, uint32_t *port_ids, uint32_t *flow_ids, uint32_t *n_keys, uint32_t *line) { FILE *f = NULL; char file_buf[1024]; uint32_t i, l; /* Check input arguments */ if ((filename == NULL) || (keys == NULL) || (port_ids == NULL) || (flow_ids == NULL) || (n_keys == NULL) || (*n_keys == 0) || (line == NULL)) { if (line) *line = 0; return -1; } /* Open input file */ f = fopen(filename, "r"); if (f == NULL) { *line = 0; return -1; } /* Read file */ for (i = 0, l = 1; i < *n_keys; l++) { char *tokens[32]; uint32_t n_tokens = RTE_DIM(tokens); struct in6_addr sipaddr, dipaddr; uint16_t sport, dport; uint8_t proto; uint32_t portid, flowid; int status; if (fgets(file_buf, sizeof(file_buf), f) == NULL) break; status = parse_tokenize_string(file_buf, tokens, &n_tokens); if (status) goto error3; if ((n_tokens == 0) || (tokens[0][0] == '#')) continue; if ((n_tokens != 10) || strcmp(tokens[0], "ipv6") || parse_ipv6_addr(tokens[1], &sipaddr) || parse_ipv6_addr(tokens[2], &dipaddr) || parser_read_uint16(&sport, tokens[3]) || parser_read_uint16(&dport, tokens[4]) || parser_read_uint8(&proto, tokens[5]) || strcmp(tokens[6], "port") || parser_read_uint32(&portid, tokens[7]) || strcmp(tokens[8], "id") || parser_read_uint32(&flowid, tokens[9])) goto error3; keys[i].type = FLOW_KEY_IPV6_5TUPLE; memcpy(keys[i].key.ipv6_5tuple.ip_src, sipaddr.s6_addr, sizeof(sipaddr.s6_addr)); memcpy(keys[i].key.ipv6_5tuple.ip_dst, dipaddr.s6_addr, sizeof(dipaddr.s6_addr)); keys[i].key.ipv6_5tuple.port_src = sport; keys[i].key.ipv6_5tuple.port_dst = dport; keys[i].key.ipv6_5tuple.proto = proto; port_ids[i] = portid; flow_ids[i] = flowid; if (app_pipeline_fc_key_check(&keys[i])) goto error3; i++; } /* Close file */ *n_keys = i; fclose(f); return 0; error3: *line = l; fclose(f); return -1; }