]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc. | |
3 | * | |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at: | |
7 | * | |
8 | * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
15 | */ | |
16 | ||
17 | #include <config.h> | |
18 | #include "packets.h" | |
19 | #include <sys/types.h> | |
20 | #include <netinet/in.h> | |
21 | #include <arpa/inet.h> | |
22 | #include <sys/socket.h> | |
23 | #include <netinet/ip6.h> | |
24 | #include <netinet/icmp6.h> | |
25 | #include <stdlib.h> | |
26 | #include <netdb.h> | |
27 | #include "byte-order.h" | |
28 | #include "csum.h" | |
29 | #include "crc32c.h" | |
30 | #include "flow.h" | |
31 | #include "openvswitch/hmap.h" | |
32 | #include "openvswitch/dynamic-string.h" | |
33 | #include "ovs-thread.h" | |
34 | #include "odp-util.h" | |
35 | #include "dp-packet.h" | |
36 | #include "unaligned.h" | |
37 | ||
38 | const struct in6_addr in6addr_exact = IN6ADDR_EXACT_INIT; | |
39 | const struct in6_addr in6addr_all_hosts = IN6ADDR_ALL_HOSTS_INIT; | |
40 | const struct in6_addr in6addr_all_routers = IN6ADDR_ALL_ROUTERS_INIT; | |
41 | ||
42 | struct in6_addr | |
43 | flow_tnl_dst(const struct flow_tnl *tnl) | |
44 | { | |
45 | return tnl->ip_dst ? in6_addr_mapped_ipv4(tnl->ip_dst) : tnl->ipv6_dst; | |
46 | } | |
47 | ||
48 | struct in6_addr | |
49 | flow_tnl_src(const struct flow_tnl *tnl) | |
50 | { | |
51 | return tnl->ip_src ? in6_addr_mapped_ipv4(tnl->ip_src) : tnl->ipv6_src; | |
52 | } | |
53 | ||
54 | /* Returns true if 's' consists entirely of hex digits, false otherwise. */ | |
55 | static bool | |
56 | is_all_hex(const char *s) | |
57 | { | |
58 | return s[strspn(s, "0123456789abcdefABCDEF")] == '\0'; | |
59 | } | |
60 | ||
61 | /* Parses 's' as a 16-digit hexadecimal number representing a datapath ID. On | |
62 | * success stores the dpid into '*dpidp' and returns true, on failure stores 0 | |
63 | * into '*dpidp' and returns false. | |
64 | * | |
65 | * Rejects an all-zeros dpid as invalid. */ | |
66 | bool | |
67 | dpid_from_string(const char *s, uint64_t *dpidp) | |
68 | { | |
69 | size_t len = strlen(s); | |
70 | *dpidp = ((len == 16 && is_all_hex(s)) | |
71 | || (len <= 18 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X') | |
72 | && is_all_hex(s + 2)) | |
73 | ? strtoull(s, NULL, 16) | |
74 | : 0); | |
75 | return *dpidp != 0; | |
76 | } | |
77 | ||
78 | uint64_t | |
79 | eth_addr_to_uint64(const struct eth_addr ea) | |
80 | { | |
81 | return (((uint64_t) ntohs(ea.be16[0]) << 32) | |
82 | | ((uint64_t) ntohs(ea.be16[1]) << 16) | |
83 | | ntohs(ea.be16[2])); | |
84 | } | |
85 | ||
86 | void | |
87 | eth_addr_from_uint64(uint64_t x, struct eth_addr *ea) | |
88 | { | |
89 | ea->be16[0] = htons(x >> 32); | |
90 | ea->be16[1] = htons((x & 0xFFFF0000) >> 16); | |
91 | ea->be16[2] = htons(x & 0xFFFF); | |
92 | } | |
93 | ||
94 | void | |
95 | eth_addr_mark_random(struct eth_addr *ea) | |
96 | { | |
97 | ea->ea[0] &= ~1; /* Unicast. */ | |
98 | ea->ea[0] |= 2; /* Private. */ | |
99 | } | |
100 | ||
101 | /* Returns true if 'ea' is a reserved address, that a bridge must never | |
102 | * forward, false otherwise. | |
103 | * | |
104 | * If you change this function's behavior, please update corresponding | |
105 | * documentation in vswitch.xml at the same time. */ | |
106 | bool | |
107 | eth_addr_is_reserved(const struct eth_addr ea) | |
108 | { | |
109 | struct eth_addr_node { | |
110 | struct hmap_node hmap_node; | |
111 | const uint64_t ea64; | |
112 | }; | |
113 | ||
114 | static struct eth_addr_node nodes[] = { | |
115 | /* STP, IEEE pause frames, and other reserved protocols. */ | |
116 | { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000000ULL }, | |
117 | { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000001ULL }, | |
118 | { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000002ULL }, | |
119 | { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000003ULL }, | |
120 | { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000004ULL }, | |
121 | { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000005ULL }, | |
122 | { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000006ULL }, | |
123 | { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000007ULL }, | |
124 | { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000008ULL }, | |
125 | { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000009ULL }, | |
126 | { HMAP_NODE_NULL_INITIALIZER, 0x0180c200000aULL }, | |
127 | { HMAP_NODE_NULL_INITIALIZER, 0x0180c200000bULL }, | |
128 | { HMAP_NODE_NULL_INITIALIZER, 0x0180c200000cULL }, | |
129 | { HMAP_NODE_NULL_INITIALIZER, 0x0180c200000dULL }, | |
130 | { HMAP_NODE_NULL_INITIALIZER, 0x0180c200000eULL }, | |
131 | { HMAP_NODE_NULL_INITIALIZER, 0x0180c200000fULL }, | |
132 | ||
133 | /* Extreme protocols. */ | |
134 | { HMAP_NODE_NULL_INITIALIZER, 0x00e02b000000ULL }, /* EDP. */ | |
135 | { HMAP_NODE_NULL_INITIALIZER, 0x00e02b000004ULL }, /* EAPS. */ | |
136 | { HMAP_NODE_NULL_INITIALIZER, 0x00e02b000006ULL }, /* EAPS. */ | |
137 | ||
138 | /* Cisco protocols. */ | |
139 | { HMAP_NODE_NULL_INITIALIZER, 0x01000c000000ULL }, /* ISL. */ | |
140 | { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccccULL }, /* PAgP, UDLD, CDP, | |
141 | * DTP, VTP. */ | |
142 | { HMAP_NODE_NULL_INITIALIZER, 0x01000ccccccdULL }, /* PVST+. */ | |
143 | { HMAP_NODE_NULL_INITIALIZER, 0x01000ccdcdcdULL }, /* STP Uplink Fast, | |
144 | * FlexLink. */ | |
145 | ||
146 | /* Cisco CFM. */ | |
147 | { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc0ULL }, | |
148 | { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc1ULL }, | |
149 | { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc2ULL }, | |
150 | { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc3ULL }, | |
151 | { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc4ULL }, | |
152 | { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc5ULL }, | |
153 | { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc6ULL }, | |
154 | { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc7ULL }, | |
155 | }; | |
156 | ||
157 | static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; | |
158 | struct eth_addr_node *node; | |
159 | static struct hmap addrs; | |
160 | uint64_t ea64; | |
161 | ||
162 | if (ovsthread_once_start(&once)) { | |
163 | hmap_init(&addrs); | |
164 | for (node = nodes; node < &nodes[ARRAY_SIZE(nodes)]; node++) { | |
165 | hmap_insert(&addrs, &node->hmap_node, hash_uint64(node->ea64)); | |
166 | } | |
167 | ovsthread_once_done(&once); | |
168 | } | |
169 | ||
170 | ea64 = eth_addr_to_uint64(ea); | |
171 | HMAP_FOR_EACH_IN_BUCKET (node, hmap_node, hash_uint64(ea64), &addrs) { | |
172 | if (node->ea64 == ea64) { | |
173 | return true; | |
174 | } | |
175 | } | |
176 | return false; | |
177 | } | |
178 | ||
179 | /* Attempts to parse 's' as an Ethernet address. If successful, stores the | |
180 | * address in 'ea' and returns true, otherwise zeros 'ea' and returns | |
181 | * false. This function checks trailing characters. */ | |
182 | bool | |
183 | eth_addr_from_string(const char *s, struct eth_addr *ea) | |
184 | { | |
185 | int n = 0; | |
186 | if (ovs_scan(s, ETH_ADDR_SCAN_FMT"%n", ETH_ADDR_SCAN_ARGS(*ea), &n) | |
187 | && !s[n]) { | |
188 | return true; | |
189 | } else { | |
190 | *ea = eth_addr_zero; | |
191 | return false; | |
192 | } | |
193 | } | |
194 | ||
195 | /* Fills 'b' with a Reverse ARP packet with Ethernet source address 'eth_src'. | |
196 | * This function is used by Open vSwitch to compose packets in cases where | |
197 | * context is important but content doesn't (or shouldn't) matter. | |
198 | * | |
199 | * The returned packet has enough headroom to insert an 802.1Q VLAN header if | |
200 | * desired. */ | |
201 | void | |
202 | compose_rarp(struct dp_packet *b, const struct eth_addr eth_src) | |
203 | { | |
204 | struct eth_header *eth; | |
205 | struct arp_eth_header *arp; | |
206 | ||
207 | dp_packet_clear(b); | |
208 | dp_packet_prealloc_tailroom(b, 2 + ETH_HEADER_LEN + VLAN_HEADER_LEN | |
209 | + ARP_ETH_HEADER_LEN); | |
210 | dp_packet_reserve(b, 2 + VLAN_HEADER_LEN); | |
211 | eth = dp_packet_put_uninit(b, sizeof *eth); | |
212 | eth->eth_dst = eth_addr_broadcast; | |
213 | eth->eth_src = eth_src; | |
214 | eth->eth_type = htons(ETH_TYPE_RARP); | |
215 | ||
216 | arp = dp_packet_put_uninit(b, sizeof *arp); | |
217 | arp->ar_hrd = htons(ARP_HRD_ETHERNET); | |
218 | arp->ar_pro = htons(ARP_PRO_IP); | |
219 | arp->ar_hln = sizeof arp->ar_sha; | |
220 | arp->ar_pln = sizeof arp->ar_spa; | |
221 | arp->ar_op = htons(ARP_OP_RARP); | |
222 | arp->ar_sha = eth_src; | |
223 | put_16aligned_be32(&arp->ar_spa, htonl(0)); | |
224 | arp->ar_tha = eth_src; | |
225 | put_16aligned_be32(&arp->ar_tpa, htonl(0)); | |
226 | ||
227 | dp_packet_reset_offsets(b); | |
228 | dp_packet_set_l3(b, arp); | |
229 | b->packet_type = htonl(PT_ETH); | |
230 | } | |
231 | ||
232 | /* Insert VLAN header according to given TCI. Packet passed must be Ethernet | |
233 | * packet. Ignores the CFI bit of 'tci' using 0 instead. | |
234 | * | |
235 | * Also adjusts the layer offsets accordingly. */ | |
236 | void | |
237 | eth_push_vlan(struct dp_packet *packet, ovs_be16 tpid, ovs_be16 tci) | |
238 | { | |
239 | struct vlan_eth_header *veh; | |
240 | ||
241 | /* Insert new 802.1Q header. */ | |
242 | veh = dp_packet_resize_l2(packet, VLAN_HEADER_LEN); | |
243 | memmove(veh, (char *)veh + VLAN_HEADER_LEN, 2 * ETH_ADDR_LEN); | |
244 | veh->veth_type = tpid; | |
245 | veh->veth_tci = tci & htons(~VLAN_CFI); | |
246 | } | |
247 | ||
248 | /* Removes outermost VLAN header (if any is present) from 'packet'. | |
249 | * | |
250 | * 'packet->l2_5' should initially point to 'packet''s outer-most VLAN header | |
251 | * or may be NULL if there are no VLAN headers. */ | |
252 | void | |
253 | eth_pop_vlan(struct dp_packet *packet) | |
254 | { | |
255 | struct vlan_eth_header *veh = dp_packet_eth(packet); | |
256 | ||
257 | if (veh && dp_packet_size(packet) >= sizeof *veh | |
258 | && eth_type_vlan(veh->veth_type)) { | |
259 | ||
260 | memmove((char *)veh + VLAN_HEADER_LEN, veh, 2 * ETH_ADDR_LEN); | |
261 | dp_packet_resize_l2(packet, -VLAN_HEADER_LEN); | |
262 | } | |
263 | } | |
264 | ||
265 | /* Push Ethernet header onto 'packet' assuming it is layer 3 */ | |
266 | void | |
267 | push_eth(struct dp_packet *packet, const struct eth_addr *dst, | |
268 | const struct eth_addr *src) | |
269 | { | |
270 | struct eth_header *eh; | |
271 | ||
272 | ovs_assert(!dp_packet_is_eth(packet)); | |
273 | eh = dp_packet_resize_l2(packet, ETH_HEADER_LEN); | |
274 | eh->eth_dst = *dst; | |
275 | eh->eth_src = *src; | |
276 | eh->eth_type = pt_ns_type_be(packet->packet_type); | |
277 | packet->packet_type = htonl(PT_ETH); | |
278 | } | |
279 | ||
280 | /* Removes Ethernet header, including VLAN header, from 'packet'. | |
281 | * | |
282 | * Previous to calling this function, 'ofpbuf_l3(packet)' must not be NULL */ | |
283 | void | |
284 | pop_eth(struct dp_packet *packet) | |
285 | { | |
286 | char *l2_5 = dp_packet_l2_5(packet); | |
287 | char *l3 = dp_packet_l3(packet); | |
288 | ovs_be16 ethertype; | |
289 | int increment; | |
290 | ||
291 | ovs_assert(dp_packet_is_eth(packet)); | |
292 | ovs_assert(l3 != NULL); | |
293 | ||
294 | if (l2_5) { | |
295 | increment = packet->l2_5_ofs; | |
296 | ethertype = *(ALIGNED_CAST(ovs_be16 *, (l2_5 - 2))); | |
297 | } else { | |
298 | increment = packet->l3_ofs; | |
299 | ethertype = *(ALIGNED_CAST(ovs_be16 *, (l3 - 2))); | |
300 | } | |
301 | ||
302 | dp_packet_resize_l2(packet, -increment); | |
303 | packet->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE, ntohs(ethertype)); | |
304 | } | |
305 | ||
306 | /* Set ethertype of the packet. */ | |
307 | static void | |
308 | set_ethertype(struct dp_packet *packet, ovs_be16 eth_type) | |
309 | { | |
310 | struct eth_header *eh = dp_packet_eth(packet); | |
311 | ||
312 | if (!eh) { | |
313 | return; | |
314 | } | |
315 | ||
316 | if (eth_type_vlan(eh->eth_type)) { | |
317 | ovs_be16 *p; | |
318 | char *l2_5 = dp_packet_l2_5(packet); | |
319 | ||
320 | p = ALIGNED_CAST(ovs_be16 *, | |
321 | (l2_5 ? l2_5 : (char *)dp_packet_l3(packet)) - 2); | |
322 | *p = eth_type; | |
323 | } else { | |
324 | eh->eth_type = eth_type; | |
325 | } | |
326 | } | |
327 | ||
328 | static bool is_mpls(struct dp_packet *packet) | |
329 | { | |
330 | return packet->l2_5_ofs != UINT16_MAX; | |
331 | } | |
332 | ||
333 | /* Set time to live (TTL) of an MPLS label stack entry (LSE). */ | |
334 | void | |
335 | set_mpls_lse_ttl(ovs_be32 *lse, uint8_t ttl) | |
336 | { | |
337 | *lse &= ~htonl(MPLS_TTL_MASK); | |
338 | *lse |= htonl((ttl << MPLS_TTL_SHIFT) & MPLS_TTL_MASK); | |
339 | } | |
340 | ||
341 | /* Set traffic class (TC) of an MPLS label stack entry (LSE). */ | |
342 | void | |
343 | set_mpls_lse_tc(ovs_be32 *lse, uint8_t tc) | |
344 | { | |
345 | *lse &= ~htonl(MPLS_TC_MASK); | |
346 | *lse |= htonl((tc << MPLS_TC_SHIFT) & MPLS_TC_MASK); | |
347 | } | |
348 | ||
349 | /* Set label of an MPLS label stack entry (LSE). */ | |
350 | void | |
351 | set_mpls_lse_label(ovs_be32 *lse, ovs_be32 label) | |
352 | { | |
353 | *lse &= ~htonl(MPLS_LABEL_MASK); | |
354 | *lse |= htonl((ntohl(label) << MPLS_LABEL_SHIFT) & MPLS_LABEL_MASK); | |
355 | } | |
356 | ||
357 | /* Set bottom of stack (BoS) bit of an MPLS label stack entry (LSE). */ | |
358 | void | |
359 | set_mpls_lse_bos(ovs_be32 *lse, uint8_t bos) | |
360 | { | |
361 | *lse &= ~htonl(MPLS_BOS_MASK); | |
362 | *lse |= htonl((bos << MPLS_BOS_SHIFT) & MPLS_BOS_MASK); | |
363 | } | |
364 | ||
365 | /* Compose an MPLS label stack entry (LSE) from its components: | |
366 | * label, traffic class (TC), time to live (TTL) and | |
367 | * bottom of stack (BoS) bit. */ | |
368 | ovs_be32 | |
369 | set_mpls_lse_values(uint8_t ttl, uint8_t tc, uint8_t bos, ovs_be32 label) | |
370 | { | |
371 | ovs_be32 lse = htonl(0); | |
372 | set_mpls_lse_ttl(&lse, ttl); | |
373 | set_mpls_lse_tc(&lse, tc); | |
374 | set_mpls_lse_bos(&lse, bos); | |
375 | set_mpls_lse_label(&lse, label); | |
376 | return lse; | |
377 | } | |
378 | ||
379 | /* Set MPLS label stack entry to outermost MPLS header.*/ | |
380 | void | |
381 | set_mpls_lse(struct dp_packet *packet, ovs_be32 mpls_lse) | |
382 | { | |
383 | /* Packet type should be MPLS to set label stack entry. */ | |
384 | if (is_mpls(packet)) { | |
385 | struct mpls_hdr *mh = dp_packet_l2_5(packet); | |
386 | ||
387 | /* Update mpls label stack entry. */ | |
388 | put_16aligned_be32(&mh->mpls_lse, mpls_lse); | |
389 | } | |
390 | } | |
391 | ||
392 | /* Push MPLS label stack entry 'lse' onto 'packet' as the outermost MPLS | |
393 | * header. If 'packet' does not already have any MPLS labels, then its | |
394 | * Ethertype is changed to 'ethtype' (which must be an MPLS Ethertype). */ | |
395 | void | |
396 | push_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse) | |
397 | { | |
398 | char * header; | |
399 | size_t len; | |
400 | ||
401 | if (!eth_type_mpls(ethtype)) { | |
402 | return; | |
403 | } | |
404 | ||
405 | if (!is_mpls(packet)) { | |
406 | /* Set MPLS label stack offset. */ | |
407 | packet->l2_5_ofs = packet->l3_ofs; | |
408 | } | |
409 | ||
410 | set_ethertype(packet, ethtype); | |
411 | ||
412 | /* Push new MPLS shim header onto packet. */ | |
413 | len = packet->l2_5_ofs; | |
414 | header = dp_packet_resize_l2_5(packet, MPLS_HLEN); | |
415 | memmove(header, header + MPLS_HLEN, len); | |
416 | memcpy(header + len, &lse, sizeof lse); | |
417 | ||
418 | pkt_metadata_init_conn(&packet->md); | |
419 | } | |
420 | ||
421 | /* If 'packet' is an MPLS packet, removes its outermost MPLS label stack entry. | |
422 | * If the label that was removed was the only MPLS label, changes 'packet''s | |
423 | * Ethertype to 'ethtype' (which ordinarily should not be an MPLS | |
424 | * Ethertype). */ | |
425 | void | |
426 | pop_mpls(struct dp_packet *packet, ovs_be16 ethtype) | |
427 | { | |
428 | if (is_mpls(packet)) { | |
429 | struct mpls_hdr *mh = dp_packet_l2_5(packet); | |
430 | size_t len = packet->l2_5_ofs; | |
431 | ||
432 | set_ethertype(packet, ethtype); | |
433 | if (get_16aligned_be32(&mh->mpls_lse) & htonl(MPLS_BOS_MASK)) { | |
434 | dp_packet_set_l2_5(packet, NULL); | |
435 | } | |
436 | /* Shift the l2 header forward. */ | |
437 | memmove((char*)dp_packet_data(packet) + MPLS_HLEN, dp_packet_data(packet), len); | |
438 | dp_packet_resize_l2_5(packet, -MPLS_HLEN); | |
439 | ||
440 | /* Invalidate offload flags as they are not valid after | |
441 | * decapsulation of MPLS header. */ | |
442 | dp_packet_reset_offload(packet); | |
443 | } | |
444 | } | |
445 | ||
446 | void | |
447 | push_nsh(struct dp_packet *packet, const struct nsh_hdr *nsh_hdr_src) | |
448 | { | |
449 | struct nsh_hdr *nsh; | |
450 | size_t length = nsh_hdr_len(nsh_hdr_src); | |
451 | uint8_t next_proto; | |
452 | ||
453 | switch (ntohl(packet->packet_type)) { | |
454 | case PT_ETH: | |
455 | next_proto = NSH_P_ETHERNET; | |
456 | break; | |
457 | case PT_IPV4: | |
458 | next_proto = NSH_P_IPV4; | |
459 | break; | |
460 | case PT_IPV6: | |
461 | next_proto = NSH_P_IPV6; | |
462 | break; | |
463 | case PT_NSH: | |
464 | next_proto = NSH_P_NSH; | |
465 | break; | |
466 | default: | |
467 | OVS_NOT_REACHED(); | |
468 | } | |
469 | ||
470 | nsh = (struct nsh_hdr *) dp_packet_push_uninit(packet, length); | |
471 | memcpy(nsh, nsh_hdr_src, length); | |
472 | nsh->next_proto = next_proto; | |
473 | packet->packet_type = htonl(PT_NSH); | |
474 | dp_packet_reset_offsets(packet); | |
475 | packet->l3_ofs = 0; | |
476 | } | |
477 | ||
478 | bool | |
479 | pop_nsh(struct dp_packet *packet) | |
480 | { | |
481 | struct nsh_hdr *nsh = (struct nsh_hdr *) dp_packet_l3(packet); | |
482 | size_t length; | |
483 | uint32_t next_pt; | |
484 | ||
485 | if (packet->packet_type == htonl(PT_NSH) && nsh) { | |
486 | switch (nsh->next_proto) { | |
487 | case NSH_P_ETHERNET: | |
488 | next_pt = PT_ETH; | |
489 | break; | |
490 | case NSH_P_IPV4: | |
491 | next_pt = PT_IPV4; | |
492 | break; | |
493 | case NSH_P_IPV6: | |
494 | next_pt = PT_IPV6; | |
495 | break; | |
496 | case NSH_P_NSH: | |
497 | next_pt = PT_NSH; | |
498 | break; | |
499 | default: | |
500 | /* Unknown inner packet type. Drop packet. */ | |
501 | return false; | |
502 | } | |
503 | ||
504 | length = nsh_hdr_len(nsh); | |
505 | dp_packet_reset_packet(packet, length); | |
506 | packet->packet_type = htonl(next_pt); | |
507 | /* Packet must be recirculated for further processing. */ | |
508 | } | |
509 | return true; | |
510 | } | |
511 | ||
512 | /* Converts hex digits in 'hex' to an Ethernet packet in '*packetp'. The | |
513 | * caller must free '*packetp'. On success, returns NULL. On failure, returns | |
514 | * an error message and stores NULL in '*packetp'. | |
515 | * | |
516 | * Aligns the L3 header of '*packetp' on a 32-bit boundary. */ | |
517 | const char * | |
518 | eth_from_hex(const char *hex, struct dp_packet **packetp) | |
519 | { | |
520 | struct dp_packet *packet; | |
521 | ||
522 | /* Use 2 bytes of headroom to 32-bit align the L3 header. */ | |
523 | packet = *packetp = dp_packet_new_with_headroom(strlen(hex) / 2, 2); | |
524 | ||
525 | if (dp_packet_put_hex(packet, hex, NULL)[0] != '\0') { | |
526 | dp_packet_delete(packet); | |
527 | *packetp = NULL; | |
528 | return "Trailing garbage in packet data"; | |
529 | } | |
530 | ||
531 | if (dp_packet_size(packet) < ETH_HEADER_LEN) { | |
532 | dp_packet_delete(packet); | |
533 | *packetp = NULL; | |
534 | return "Packet data too short for Ethernet"; | |
535 | } | |
536 | ||
537 | return NULL; | |
538 | } | |
539 | ||
540 | void | |
541 | eth_format_masked(const struct eth_addr eth, | |
542 | const struct eth_addr *mask, struct ds *s) | |
543 | { | |
544 | ds_put_format(s, ETH_ADDR_FMT, ETH_ADDR_ARGS(eth)); | |
545 | if (mask && !eth_mask_is_exact(*mask)) { | |
546 | ds_put_format(s, "/"ETH_ADDR_FMT, ETH_ADDR_ARGS(*mask)); | |
547 | } | |
548 | } | |
549 | ||
550 | void | |
551 | in6_addr_solicited_node(struct in6_addr *addr, const struct in6_addr *ip6) | |
552 | { | |
553 | union ovs_16aligned_in6_addr *taddr = | |
554 | (union ovs_16aligned_in6_addr *) addr; | |
555 | memset(taddr->be16, 0, sizeof(taddr->be16)); | |
556 | taddr->be16[0] = htons(0xff02); | |
557 | taddr->be16[5] = htons(0x1); | |
558 | taddr->be16[6] = htons(0xff00); | |
559 | memcpy(&addr->s6_addr[13], &ip6->s6_addr[13], 3); | |
560 | } | |
561 | ||
562 | /* | |
563 | * Generates ipv6 EUI64 address from the given eth addr | |
564 | * and prefix and stores it in 'lla' | |
565 | */ | |
566 | void | |
567 | in6_generate_eui64(struct eth_addr ea, const struct in6_addr *prefix, | |
568 | struct in6_addr *lla) | |
569 | { | |
570 | union ovs_16aligned_in6_addr *taddr = | |
571 | (union ovs_16aligned_in6_addr *) lla; | |
572 | union ovs_16aligned_in6_addr *prefix_taddr = | |
573 | (union ovs_16aligned_in6_addr *) prefix; | |
574 | taddr->be16[0] = prefix_taddr->be16[0]; | |
575 | taddr->be16[1] = prefix_taddr->be16[1]; | |
576 | taddr->be16[2] = prefix_taddr->be16[2]; | |
577 | taddr->be16[3] = prefix_taddr->be16[3]; | |
578 | taddr->be16[4] = htons(((ea.ea[0] ^ 0x02) << 8) | ea.ea[1]); | |
579 | taddr->be16[5] = htons(ea.ea[2] << 8 | 0x00ff); | |
580 | taddr->be16[6] = htons(0xfe << 8 | ea.ea[3]); | |
581 | taddr->be16[7] = ea.be16[2]; | |
582 | } | |
583 | ||
584 | /* Generates ipv6 link local address from the given eth addr | |
585 | * with prefix 'fe80::/64' and stores it in 'lla'. */ | |
586 | void | |
587 | in6_generate_lla(struct eth_addr ea, struct in6_addr *lla) | |
588 | { | |
589 | union ovs_16aligned_in6_addr *taddr = | |
590 | (union ovs_16aligned_in6_addr *) lla; | |
591 | memset(taddr->be16, 0, sizeof(taddr->be16)); | |
592 | taddr->be16[0] = htons(0xfe80); | |
593 | taddr->be16[4] = htons(((ea.ea[0] ^ 0x02) << 8) | ea.ea[1]); | |
594 | taddr->be16[5] = htons(ea.ea[2] << 8 | 0x00ff); | |
595 | taddr->be16[6] = htons(0xfe << 8 | ea.ea[3]); | |
596 | taddr->be16[7] = ea.be16[2]; | |
597 | } | |
598 | ||
599 | /* Returns true if 'addr' is a link local address. Otherwise, false. */ | |
600 | bool | |
601 | in6_is_lla(struct in6_addr *addr) | |
602 | { | |
603 | #ifdef s6_addr32 | |
604 | return addr->s6_addr32[0] == htonl(0xfe800000) && !(addr->s6_addr32[1]); | |
605 | #else | |
606 | return addr->s6_addr[0] == 0xfe && addr->s6_addr[1] == 0x80 && | |
607 | !(addr->s6_addr[2] | addr->s6_addr[3] | addr->s6_addr[4] | | |
608 | addr->s6_addr[5] | addr->s6_addr[6] | addr->s6_addr[7]); | |
609 | #endif | |
610 | } | |
611 | ||
612 | void | |
613 | ipv6_multicast_to_ethernet(struct eth_addr *eth, const struct in6_addr *ip6) | |
614 | { | |
615 | eth->ea[0] = 0x33; | |
616 | eth->ea[1] = 0x33; | |
617 | eth->ea[2] = ip6->s6_addr[12]; | |
618 | eth->ea[3] = ip6->s6_addr[13]; | |
619 | eth->ea[4] = ip6->s6_addr[14]; | |
620 | eth->ea[5] = ip6->s6_addr[15]; | |
621 | } | |
622 | ||
623 | /* Given the IP netmask 'netmask', returns the number of bits of the IP address | |
624 | * that it specifies, that is, the number of 1-bits in 'netmask'. | |
625 | * | |
626 | * If 'netmask' is not a CIDR netmask (see ip_is_cidr()), the return value will | |
627 | * still be in the valid range but isn't otherwise meaningful. */ | |
628 | int | |
629 | ip_count_cidr_bits(ovs_be32 netmask) | |
630 | { | |
631 | return 32 - ctz32(ntohl(netmask)); | |
632 | } | |
633 | ||
634 | void | |
635 | ip_format_masked(ovs_be32 ip, ovs_be32 mask, struct ds *s) | |
636 | { | |
637 | ds_put_format(s, IP_FMT, IP_ARGS(ip)); | |
638 | if (mask != OVS_BE32_MAX) { | |
639 | if (ip_is_cidr(mask)) { | |
640 | ds_put_format(s, "/%d", ip_count_cidr_bits(mask)); | |
641 | } else { | |
642 | ds_put_format(s, "/"IP_FMT, IP_ARGS(mask)); | |
643 | } | |
644 | } | |
645 | } | |
646 | ||
647 | /* Parses string 's', which must be an IP address. Stores the IP address into | |
648 | * '*ip'. Returns true if successful, otherwise false. */ | |
649 | bool | |
650 | ip_parse(const char *s, ovs_be32 *ip) | |
651 | { | |
652 | return inet_pton(AF_INET, s, ip) == 1; | |
653 | } | |
654 | ||
655 | /* Parses string 's', which must be an IP address with a port number | |
656 | * with ":" as a separator (e.g.: 192.168.1.2:80). | |
657 | * Stores the IP address into '*ip' and port number to '*port'. | |
658 | * | |
659 | * Returns NULL if successful, otherwise an error message that the caller must | |
660 | * free(). */ | |
661 | char * OVS_WARN_UNUSED_RESULT | |
662 | ip_parse_port(const char *s, ovs_be32 *ip, ovs_be16 *port) | |
663 | { | |
664 | int n = 0; | |
665 | if (ovs_scan(s, IP_PORT_SCAN_FMT"%n", IP_PORT_SCAN_ARGS(ip, port), &n) | |
666 | && !s[n]) { | |
667 | return NULL; | |
668 | } | |
669 | ||
670 | return xasprintf("%s: invalid IP address or port number", s); | |
671 | } | |
672 | ||
673 | /* Parses string 's', which must be an IP address with an optional netmask or | |
674 | * CIDR prefix length. Stores the IP address into '*ip', netmask into '*mask', | |
675 | * (255.255.255.255, if 's' lacks a netmask), and number of scanned characters | |
676 | * into '*n'. | |
677 | * | |
678 | * Returns NULL if successful, otherwise an error message that the caller must | |
679 | * free(). */ | |
680 | char * OVS_WARN_UNUSED_RESULT | |
681 | ip_parse_masked_len(const char *s, int *n, ovs_be32 *ip, | |
682 | ovs_be32 *mask) | |
683 | { | |
684 | int prefix; | |
685 | ||
686 | if (ovs_scan_len(s, n, IP_SCAN_FMT"/"IP_SCAN_FMT, | |
687 | IP_SCAN_ARGS(ip), IP_SCAN_ARGS(mask))) { | |
688 | /* OK. */ | |
689 | } else if (ovs_scan_len(s, n, IP_SCAN_FMT"/%d", | |
690 | IP_SCAN_ARGS(ip), &prefix)) { | |
691 | if (prefix < 0 || prefix > 32) { | |
692 | return xasprintf("%s: IPv4 network prefix bits not between 0 and " | |
693 | "32, inclusive", s); | |
694 | } | |
695 | *mask = be32_prefix_mask(prefix); | |
696 | } else if (ovs_scan_len(s, n, IP_SCAN_FMT, IP_SCAN_ARGS(ip))) { | |
697 | *mask = OVS_BE32_MAX; | |
698 | } else { | |
699 | return xasprintf("%s: invalid IP address", s); | |
700 | } | |
701 | return NULL; | |
702 | } | |
703 | ||
704 | /* This function is similar to ip_parse_masked_len(), but doesn't return the | |
705 | * number of scanned characters and expects 's' to end after the ip/(optional) | |
706 | * mask. | |
707 | * | |
708 | * Returns NULL if successful, otherwise an error message that the caller must | |
709 | * free(). */ | |
710 | char * OVS_WARN_UNUSED_RESULT | |
711 | ip_parse_masked(const char *s, ovs_be32 *ip, ovs_be32 *mask) | |
712 | { | |
713 | int n = 0; | |
714 | ||
715 | char *error = ip_parse_masked_len(s, &n, ip, mask); | |
716 | if (!error && s[n]) { | |
717 | return xasprintf("%s: invalid IP address", s); | |
718 | } | |
719 | return error; | |
720 | } | |
721 | ||
722 | /* Similar to ip_parse_masked_len(), but the mask, if present, must be a CIDR | |
723 | * mask and is returned as a prefix len in '*plen'. */ | |
724 | char * OVS_WARN_UNUSED_RESULT | |
725 | ip_parse_cidr_len(const char *s, int *n, ovs_be32 *ip, unsigned int *plen) | |
726 | { | |
727 | ovs_be32 mask; | |
728 | char *error; | |
729 | ||
730 | error = ip_parse_masked_len(s, n, ip, &mask); | |
731 | if (error) { | |
732 | return error; | |
733 | } | |
734 | ||
735 | if (!ip_is_cidr(mask)) { | |
736 | return xasprintf("%s: CIDR network required", s); | |
737 | } | |
738 | *plen = ip_count_cidr_bits(mask); | |
739 | return NULL; | |
740 | } | |
741 | ||
742 | /* Similar to ip_parse_cidr_len(), but doesn't return the number of scanned | |
743 | * characters and expects 's' to be NULL terminated at the end of the | |
744 | * ip/(optional) cidr. */ | |
745 | char * OVS_WARN_UNUSED_RESULT | |
746 | ip_parse_cidr(const char *s, ovs_be32 *ip, unsigned int *plen) | |
747 | { | |
748 | int n = 0; | |
749 | ||
750 | char *error = ip_parse_cidr_len(s, &n, ip, plen); | |
751 | if (!error && s[n]) { | |
752 | return xasprintf("%s: invalid IP address", s); | |
753 | } | |
754 | return error; | |
755 | } | |
756 | ||
757 | /* Parses string 's', which must be an IPv6 address. Stores the IPv6 address | |
758 | * into '*ip'. Returns true if successful, otherwise false. */ | |
759 | bool | |
760 | ipv6_parse(const char *s, struct in6_addr *ip) | |
761 | { | |
762 | return inet_pton(AF_INET6, s, ip) == 1; | |
763 | } | |
764 | ||
765 | /* Parses string 's', which must be an IPv6 address with an optional netmask or | |
766 | * CIDR prefix length. Stores the IPv6 address into '*ip' and the netmask into | |
767 | * '*mask' (if 's' does not contain a netmask, all-one-bits is assumed), and | |
768 | * number of scanned characters into '*n'. | |
769 | * | |
770 | * Returns NULL if successful, otherwise an error message that the caller must | |
771 | * free(). */ | |
772 | char * OVS_WARN_UNUSED_RESULT | |
773 | ipv6_parse_masked_len(const char *s, int *n, struct in6_addr *ip, | |
774 | struct in6_addr *mask) | |
775 | { | |
776 | char ipv6_s[IPV6_SCAN_LEN + 1]; | |
777 | int prefix; | |
778 | ||
779 | if (ovs_scan_len(s, n, " "IPV6_SCAN_FMT, ipv6_s) | |
780 | && ipv6_parse(ipv6_s, ip)) { | |
781 | if (ovs_scan_len(s, n, "/%d", &prefix)) { | |
782 | if (prefix < 0 || prefix > 128) { | |
783 | return xasprintf("%s: IPv6 network prefix bits not between 0 " | |
784 | "and 128, inclusive", s); | |
785 | } | |
786 | *mask = ipv6_create_mask(prefix); | |
787 | } else if (ovs_scan_len(s, n, "/"IPV6_SCAN_FMT, ipv6_s)) { | |
788 | if (!ipv6_parse(ipv6_s, mask)) { | |
789 | return xasprintf("%s: Invalid IPv6 mask", s); | |
790 | } | |
791 | /* OK. */ | |
792 | } else { | |
793 | /* OK. No mask. */ | |
794 | *mask = in6addr_exact; | |
795 | } | |
796 | return NULL; | |
797 | } | |
798 | return xasprintf("%s: invalid IPv6 address", s); | |
799 | } | |
800 | ||
801 | /* This function is similar to ipv6_parse_masked_len(), but doesn't return the | |
802 | * number of scanned characters and expects 's' to end following the | |
803 | * ipv6/(optional) mask. */ | |
804 | char * OVS_WARN_UNUSED_RESULT | |
805 | ipv6_parse_masked(const char *s, struct in6_addr *ip, struct in6_addr *mask) | |
806 | { | |
807 | int n = 0; | |
808 | ||
809 | char *error = ipv6_parse_masked_len(s, &n, ip, mask); | |
810 | if (!error && s[n]) { | |
811 | return xasprintf("%s: invalid IPv6 address", s); | |
812 | } | |
813 | return error; | |
814 | } | |
815 | ||
816 | /* Similar to ipv6_parse_masked_len(), but the mask, if present, must be a CIDR | |
817 | * mask and is returned as a prefix length in '*plen'. */ | |
818 | char * OVS_WARN_UNUSED_RESULT | |
819 | ipv6_parse_cidr_len(const char *s, int *n, struct in6_addr *ip, | |
820 | unsigned int *plen) | |
821 | { | |
822 | struct in6_addr mask; | |
823 | char *error; | |
824 | ||
825 | error = ipv6_parse_masked_len(s, n, ip, &mask); | |
826 | if (error) { | |
827 | return error; | |
828 | } | |
829 | ||
830 | if (!ipv6_is_cidr(&mask)) { | |
831 | return xasprintf("%s: IPv6 CIDR network required", s); | |
832 | } | |
833 | *plen = ipv6_count_cidr_bits(&mask); | |
834 | return NULL; | |
835 | } | |
836 | ||
837 | /* Similar to ipv6_parse_cidr_len(), but doesn't return the number of scanned | |
838 | * characters and expects 's' to end after the ipv6/(optional) cidr. */ | |
839 | char * OVS_WARN_UNUSED_RESULT | |
840 | ipv6_parse_cidr(const char *s, struct in6_addr *ip, unsigned int *plen) | |
841 | { | |
842 | int n = 0; | |
843 | ||
844 | char *error = ipv6_parse_cidr_len(s, &n, ip, plen); | |
845 | if (!error && s[n]) { | |
846 | return xasprintf("%s: invalid IPv6 address", s); | |
847 | } | |
848 | return error; | |
849 | } | |
850 | ||
851 | /* Stores the string representation of the IPv6 address 'addr' into the | |
852 | * character array 'addr_str', which must be at least INET6_ADDRSTRLEN | |
853 | * bytes long. */ | |
854 | void | |
855 | ipv6_format_addr(const struct in6_addr *addr, struct ds *s) | |
856 | { | |
857 | char *dst; | |
858 | ||
859 | ds_reserve(s, s->length + INET6_ADDRSTRLEN); | |
860 | ||
861 | dst = s->string + s->length; | |
862 | inet_ntop(AF_INET6, addr, dst, INET6_ADDRSTRLEN); | |
863 | s->length += strlen(dst); | |
864 | } | |
865 | ||
866 | /* Same as print_ipv6_addr, but optionally encloses the address in square | |
867 | * brackets. */ | |
868 | void | |
869 | ipv6_format_addr_bracket(const struct in6_addr *addr, struct ds *s, | |
870 | bool bracket) | |
871 | { | |
872 | if (bracket) { | |
873 | ds_put_char(s, '['); | |
874 | } | |
875 | ipv6_format_addr(addr, s); | |
876 | if (bracket) { | |
877 | ds_put_char(s, ']'); | |
878 | } | |
879 | } | |
880 | ||
881 | void | |
882 | ipv6_format_mapped(const struct in6_addr *addr, struct ds *s) | |
883 | { | |
884 | if (IN6_IS_ADDR_V4MAPPED(addr)) { | |
885 | ds_put_format(s, IP_FMT, addr->s6_addr[12], addr->s6_addr[13], | |
886 | addr->s6_addr[14], addr->s6_addr[15]); | |
887 | } else { | |
888 | ipv6_format_addr(addr, s); | |
889 | } | |
890 | } | |
891 | ||
892 | void | |
893 | ipv6_format_masked(const struct in6_addr *addr, const struct in6_addr *mask, | |
894 | struct ds *s) | |
895 | { | |
896 | ipv6_format_addr(addr, s); | |
897 | if (mask && !ipv6_mask_is_exact(mask)) { | |
898 | if (ipv6_is_cidr(mask)) { | |
899 | int cidr_bits = ipv6_count_cidr_bits(mask); | |
900 | ds_put_format(s, "/%d", cidr_bits); | |
901 | } else { | |
902 | ds_put_char(s, '/'); | |
903 | ipv6_format_addr(mask, s); | |
904 | } | |
905 | } | |
906 | } | |
907 | ||
908 | /* Stores the string representation of the IPv6 address 'addr' into the | |
909 | * character array 'addr_str', which must be at least INET6_ADDRSTRLEN | |
910 | * bytes long. If addr is IPv4-mapped, store an IPv4 dotted-decimal string. */ | |
911 | const char * | |
912 | ipv6_string_mapped(char *addr_str, const struct in6_addr *addr) | |
913 | { | |
914 | ovs_be32 ip; | |
915 | ip = in6_addr_get_mapped_ipv4(addr); | |
916 | if (ip) { | |
917 | return inet_ntop(AF_INET, &ip, addr_str, INET6_ADDRSTRLEN); | |
918 | } else { | |
919 | return inet_ntop(AF_INET6, addr, addr_str, INET6_ADDRSTRLEN); | |
920 | } | |
921 | } | |
922 | ||
923 | #ifdef s6_addr32 | |
924 | #define s6_addrX s6_addr32 | |
925 | #define IPV6_FOR_EACH(VAR) for (int VAR = 0; VAR < 4; VAR++) | |
926 | #else | |
927 | #define s6_addrX s6_addr | |
928 | #define IPV6_FOR_EACH(VAR) for (int VAR = 0; VAR < 16; VAR++) | |
929 | #endif | |
930 | ||
931 | struct in6_addr | |
932 | ipv6_addr_bitand(const struct in6_addr *a, const struct in6_addr *b) | |
933 | { | |
934 | struct in6_addr dst; | |
935 | IPV6_FOR_EACH (i) { | |
936 | dst.s6_addrX[i] = a->s6_addrX[i] & b->s6_addrX[i]; | |
937 | } | |
938 | return dst; | |
939 | } | |
940 | ||
941 | struct in6_addr | |
942 | ipv6_addr_bitxor(const struct in6_addr *a, const struct in6_addr *b) | |
943 | { | |
944 | struct in6_addr dst; | |
945 | IPV6_FOR_EACH (i) { | |
946 | dst.s6_addrX[i] = a->s6_addrX[i] ^ b->s6_addrX[i]; | |
947 | } | |
948 | return dst; | |
949 | } | |
950 | ||
951 | bool | |
952 | ipv6_is_zero(const struct in6_addr *a) | |
953 | { | |
954 | IPV6_FOR_EACH (i) { | |
955 | if (a->s6_addrX[i]) { | |
956 | return false; | |
957 | } | |
958 | } | |
959 | return true; | |
960 | } | |
961 | ||
962 | /* Returns an in6_addr consisting of 'mask' high-order 1-bits and 128-N | |
963 | * low-order 0-bits. */ | |
964 | struct in6_addr | |
965 | ipv6_create_mask(int mask) | |
966 | { | |
967 | struct in6_addr netmask; | |
968 | uint8_t *netmaskp = &netmask.s6_addr[0]; | |
969 | ||
970 | memset(&netmask, 0, sizeof netmask); | |
971 | while (mask > 8) { | |
972 | *netmaskp = 0xff; | |
973 | netmaskp++; | |
974 | mask -= 8; | |
975 | } | |
976 | ||
977 | if (mask) { | |
978 | *netmaskp = 0xff << (8 - mask); | |
979 | } | |
980 | ||
981 | return netmask; | |
982 | } | |
983 | ||
984 | /* Given the IPv6 netmask 'netmask', returns the number of bits of the IPv6 | |
985 | * address that it specifies, that is, the number of 1-bits in 'netmask'. | |
986 | * 'netmask' must be a CIDR netmask (see ipv6_is_cidr()). | |
987 | * | |
988 | * If 'netmask' is not a CIDR netmask (see ipv6_is_cidr()), the return value | |
989 | * will still be in the valid range but isn't otherwise meaningful. */ | |
990 | int | |
991 | ipv6_count_cidr_bits(const struct in6_addr *netmask) | |
992 | { | |
993 | int i; | |
994 | int count = 0; | |
995 | const uint8_t *netmaskp = &netmask->s6_addr[0]; | |
996 | ||
997 | for (i=0; i<16; i++) { | |
998 | if (netmaskp[i] == 0xff) { | |
999 | count += 8; | |
1000 | } else { | |
1001 | uint8_t nm; | |
1002 | ||
1003 | for(nm = netmaskp[i]; nm; nm <<= 1) { | |
1004 | count++; | |
1005 | } | |
1006 | break; | |
1007 | } | |
1008 | ||
1009 | } | |
1010 | ||
1011 | return count; | |
1012 | } | |
1013 | ||
1014 | /* Returns true if 'netmask' is a CIDR netmask, that is, if it consists of N | |
1015 | * high-order 1-bits and 128-N low-order 0-bits. */ | |
1016 | bool | |
1017 | ipv6_is_cidr(const struct in6_addr *netmask) | |
1018 | { | |
1019 | const uint8_t *netmaskp = &netmask->s6_addr[0]; | |
1020 | int i; | |
1021 | ||
1022 | for (i=0; i<16; i++) { | |
1023 | if (netmaskp[i] != 0xff) { | |
1024 | uint8_t x = ~netmaskp[i]; | |
1025 | if (x & (x + 1)) { | |
1026 | return false; | |
1027 | } | |
1028 | while (++i < 16) { | |
1029 | if (netmaskp[i]) { | |
1030 | return false; | |
1031 | } | |
1032 | } | |
1033 | } | |
1034 | } | |
1035 | ||
1036 | return true; | |
1037 | } | |
1038 | ||
1039 | /* Populates 'b' with an Ethernet II packet headed with the given 'eth_dst', | |
1040 | * 'eth_src' and 'eth_type' parameters. A payload of 'size' bytes is allocated | |
1041 | * in 'b' and returned. This payload may be populated with appropriate | |
1042 | * information by the caller. Sets 'b''s 'frame' pointer and 'l3' offset to | |
1043 | * the Ethernet header and payload respectively. Aligns b->l3 on a 32-bit | |
1044 | * boundary. | |
1045 | * | |
1046 | * The returned packet has enough headroom to insert an 802.1Q VLAN header if | |
1047 | * desired. */ | |
1048 | void * | |
1049 | eth_compose(struct dp_packet *b, const struct eth_addr eth_dst, | |
1050 | const struct eth_addr eth_src, uint16_t eth_type, | |
1051 | size_t size) | |
1052 | { | |
1053 | void *data; | |
1054 | struct eth_header *eth; | |
1055 | ||
1056 | ||
1057 | dp_packet_clear(b); | |
1058 | ||
1059 | /* The magic 2 here ensures that the L3 header (when it is added later) | |
1060 | * will be 32-bit aligned. */ | |
1061 | dp_packet_prealloc_tailroom(b, 2 + ETH_HEADER_LEN + VLAN_HEADER_LEN + size); | |
1062 | dp_packet_reserve(b, 2 + VLAN_HEADER_LEN); | |
1063 | eth = dp_packet_put_uninit(b, ETH_HEADER_LEN); | |
1064 | data = dp_packet_put_zeros(b, size); | |
1065 | ||
1066 | eth->eth_dst = eth_dst; | |
1067 | eth->eth_src = eth_src; | |
1068 | eth->eth_type = htons(eth_type); | |
1069 | ||
1070 | b->packet_type = htonl(PT_ETH); | |
1071 | dp_packet_reset_offsets(b); | |
1072 | dp_packet_set_l3(b, data); | |
1073 | ||
1074 | return data; | |
1075 | } | |
1076 | ||
1077 | void | |
1078 | packet_set_ipv4_addr(struct dp_packet *packet, | |
1079 | ovs_16aligned_be32 *addr, ovs_be32 new_addr) | |
1080 | { | |
1081 | struct ip_header *nh = dp_packet_l3(packet); | |
1082 | ovs_be32 old_addr = get_16aligned_be32(addr); | |
1083 | size_t l4_size = dp_packet_l4_size(packet); | |
1084 | ||
1085 | pkt_metadata_init_conn(&packet->md); | |
1086 | ||
1087 | if (nh->ip_proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) { | |
1088 | struct tcp_header *th = dp_packet_l4(packet); | |
1089 | ||
1090 | th->tcp_csum = recalc_csum32(th->tcp_csum, old_addr, new_addr); | |
1091 | } else if (nh->ip_proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN ) { | |
1092 | struct udp_header *uh = dp_packet_l4(packet); | |
1093 | ||
1094 | if (uh->udp_csum) { | |
1095 | uh->udp_csum = recalc_csum32(uh->udp_csum, old_addr, new_addr); | |
1096 | if (!uh->udp_csum) { | |
1097 | uh->udp_csum = htons(0xffff); | |
1098 | } | |
1099 | } | |
1100 | } | |
1101 | nh->ip_csum = recalc_csum32(nh->ip_csum, old_addr, new_addr); | |
1102 | put_16aligned_be32(addr, new_addr); | |
1103 | } | |
1104 | ||
1105 | /* Returns true, if packet contains at least one routing header where | |
1106 | * segements_left > 0. | |
1107 | * | |
1108 | * This function assumes that L3 and L4 offsets are set in the packet. */ | |
1109 | static bool | |
1110 | packet_rh_present(struct dp_packet *packet, uint8_t *nexthdr) | |
1111 | { | |
1112 | const struct ovs_16aligned_ip6_hdr *nh; | |
1113 | size_t len; | |
1114 | size_t remaining; | |
1115 | uint8_t *data = dp_packet_l3(packet); | |
1116 | ||
1117 | remaining = packet->l4_ofs - packet->l3_ofs; | |
1118 | if (remaining < sizeof *nh) { | |
1119 | return false; | |
1120 | } | |
1121 | nh = ALIGNED_CAST(struct ovs_16aligned_ip6_hdr *, data); | |
1122 | data += sizeof *nh; | |
1123 | remaining -= sizeof *nh; | |
1124 | *nexthdr = nh->ip6_nxt; | |
1125 | ||
1126 | while (1) { | |
1127 | if ((*nexthdr != IPPROTO_HOPOPTS) | |
1128 | && (*nexthdr != IPPROTO_ROUTING) | |
1129 | && (*nexthdr != IPPROTO_DSTOPTS) | |
1130 | && (*nexthdr != IPPROTO_AH) | |
1131 | && (*nexthdr != IPPROTO_FRAGMENT)) { | |
1132 | /* It's either a terminal header (e.g., TCP, UDP) or one we | |
1133 | * don't understand. In either case, we're done with the | |
1134 | * packet, so use it to fill in 'nw_proto'. */ | |
1135 | break; | |
1136 | } | |
1137 | ||
1138 | /* We only verify that at least 8 bytes of the next header are | |
1139 | * available, but many of these headers are longer. Ensure that | |
1140 | * accesses within the extension header are within those first 8 | |
1141 | * bytes. All extension headers are required to be at least 8 | |
1142 | * bytes. */ | |
1143 | if (remaining < 8) { | |
1144 | return false; | |
1145 | } | |
1146 | ||
1147 | if (*nexthdr == IPPROTO_AH) { | |
1148 | /* A standard AH definition isn't available, but the fields | |
1149 | * we care about are in the same location as the generic | |
1150 | * option header--only the header length is calculated | |
1151 | * differently. */ | |
1152 | const struct ip6_ext *ext_hdr = (struct ip6_ext *)data; | |
1153 | ||
1154 | *nexthdr = ext_hdr->ip6e_nxt; | |
1155 | len = (ext_hdr->ip6e_len + 2) * 4; | |
1156 | } else if (*nexthdr == IPPROTO_FRAGMENT) { | |
1157 | const struct ovs_16aligned_ip6_frag *frag_hdr | |
1158 | = ALIGNED_CAST(struct ovs_16aligned_ip6_frag *, data); | |
1159 | ||
1160 | *nexthdr = frag_hdr->ip6f_nxt; | |
1161 | len = sizeof *frag_hdr; | |
1162 | } else if (*nexthdr == IPPROTO_ROUTING) { | |
1163 | const struct ip6_rthdr *rh = (struct ip6_rthdr *)data; | |
1164 | ||
1165 | if (rh->ip6r_segleft > 0) { | |
1166 | return true; | |
1167 | } | |
1168 | ||
1169 | *nexthdr = rh->ip6r_nxt; | |
1170 | len = (rh->ip6r_len + 1) * 8; | |
1171 | } else { | |
1172 | const struct ip6_ext *ext_hdr = (struct ip6_ext *)data; | |
1173 | ||
1174 | *nexthdr = ext_hdr->ip6e_nxt; | |
1175 | len = (ext_hdr->ip6e_len + 1) * 8; | |
1176 | } | |
1177 | ||
1178 | if (remaining < len) { | |
1179 | return false; | |
1180 | } | |
1181 | remaining -= len; | |
1182 | data += len; | |
1183 | } | |
1184 | ||
1185 | return false; | |
1186 | } | |
1187 | ||
1188 | static void | |
1189 | packet_update_csum128(struct dp_packet *packet, uint8_t proto, | |
1190 | ovs_16aligned_be32 addr[4], | |
1191 | const struct in6_addr *new_addr) | |
1192 | { | |
1193 | size_t l4_size = dp_packet_l4_size(packet); | |
1194 | ||
1195 | if (proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) { | |
1196 | struct tcp_header *th = dp_packet_l4(packet); | |
1197 | ||
1198 | th->tcp_csum = recalc_csum128(th->tcp_csum, addr, new_addr); | |
1199 | } else if (proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN) { | |
1200 | struct udp_header *uh = dp_packet_l4(packet); | |
1201 | ||
1202 | if (uh->udp_csum) { | |
1203 | uh->udp_csum = recalc_csum128(uh->udp_csum, addr, new_addr); | |
1204 | if (!uh->udp_csum) { | |
1205 | uh->udp_csum = htons(0xffff); | |
1206 | } | |
1207 | } | |
1208 | } else if (proto == IPPROTO_ICMPV6 && | |
1209 | l4_size >= sizeof(struct icmp6_header)) { | |
1210 | struct icmp6_header *icmp = dp_packet_l4(packet); | |
1211 | ||
1212 | icmp->icmp6_cksum = recalc_csum128(icmp->icmp6_cksum, addr, new_addr); | |
1213 | } | |
1214 | } | |
1215 | ||
1216 | void | |
1217 | packet_set_ipv6_addr(struct dp_packet *packet, uint8_t proto, | |
1218 | ovs_16aligned_be32 addr[4], | |
1219 | const struct in6_addr *new_addr, | |
1220 | bool recalculate_csum) | |
1221 | { | |
1222 | if (recalculate_csum) { | |
1223 | packet_update_csum128(packet, proto, addr, new_addr); | |
1224 | } | |
1225 | memcpy(addr, new_addr, sizeof(ovs_be32[4])); | |
1226 | pkt_metadata_init_conn(&packet->md); | |
1227 | } | |
1228 | ||
1229 | static void | |
1230 | packet_set_ipv6_flow_label(ovs_16aligned_be32 *flow_label, ovs_be32 flow_key) | |
1231 | { | |
1232 | ovs_be32 old_label = get_16aligned_be32(flow_label); | |
1233 | ovs_be32 new_label = (old_label & htonl(~IPV6_LABEL_MASK)) | flow_key; | |
1234 | put_16aligned_be32(flow_label, new_label); | |
1235 | } | |
1236 | ||
1237 | static void | |
1238 | packet_set_ipv6_tc(ovs_16aligned_be32 *flow_label, uint8_t tc) | |
1239 | { | |
1240 | ovs_be32 old_label = get_16aligned_be32(flow_label); | |
1241 | ovs_be32 new_label = (old_label & htonl(0xF00FFFFF)) | htonl(tc << 20); | |
1242 | put_16aligned_be32(flow_label, new_label); | |
1243 | } | |
1244 | ||
1245 | /* Modifies the IPv4 header fields of 'packet' to be consistent with 'src', | |
1246 | * 'dst', 'tos', and 'ttl'. Updates 'packet''s L4 checksums as appropriate. | |
1247 | * 'packet' must contain a valid IPv4 packet with correctly populated l[347] | |
1248 | * markers. */ | |
1249 | void | |
1250 | packet_set_ipv4(struct dp_packet *packet, ovs_be32 src, ovs_be32 dst, | |
1251 | uint8_t tos, uint8_t ttl) | |
1252 | { | |
1253 | struct ip_header *nh = dp_packet_l3(packet); | |
1254 | ||
1255 | if (get_16aligned_be32(&nh->ip_src) != src) { | |
1256 | packet_set_ipv4_addr(packet, &nh->ip_src, src); | |
1257 | } | |
1258 | ||
1259 | if (get_16aligned_be32(&nh->ip_dst) != dst) { | |
1260 | packet_set_ipv4_addr(packet, &nh->ip_dst, dst); | |
1261 | } | |
1262 | ||
1263 | if (nh->ip_tos != tos) { | |
1264 | uint8_t *field = &nh->ip_tos; | |
1265 | ||
1266 | nh->ip_csum = recalc_csum16(nh->ip_csum, htons((uint16_t) *field), | |
1267 | htons((uint16_t) tos)); | |
1268 | *field = tos; | |
1269 | } | |
1270 | ||
1271 | if (nh->ip_ttl != ttl) { | |
1272 | uint8_t *field = &nh->ip_ttl; | |
1273 | ||
1274 | nh->ip_csum = recalc_csum16(nh->ip_csum, htons(*field << 8), | |
1275 | htons(ttl << 8)); | |
1276 | *field = ttl; | |
1277 | } | |
1278 | } | |
1279 | ||
1280 | /* Modifies the IPv6 header fields of 'packet' to be consistent with 'src', | |
1281 | * 'dst', 'traffic class', and 'next hop'. Updates 'packet''s L4 checksums as | |
1282 | * appropriate. 'packet' must contain a valid IPv6 packet with correctly | |
1283 | * populated l[34] offsets. */ | |
1284 | void | |
1285 | packet_set_ipv6(struct dp_packet *packet, const struct in6_addr *src, | |
1286 | const struct in6_addr *dst, uint8_t key_tc, ovs_be32 key_fl, | |
1287 | uint8_t key_hl) | |
1288 | { | |
1289 | struct ovs_16aligned_ip6_hdr *nh = dp_packet_l3(packet); | |
1290 | uint8_t proto = 0; | |
1291 | bool rh_present; | |
1292 | ||
1293 | rh_present = packet_rh_present(packet, &proto); | |
1294 | ||
1295 | if (memcmp(&nh->ip6_src, src, sizeof(ovs_be32[4]))) { | |
1296 | packet_set_ipv6_addr(packet, proto, nh->ip6_src.be32, src, true); | |
1297 | } | |
1298 | ||
1299 | if (memcmp(&nh->ip6_dst, dst, sizeof(ovs_be32[4]))) { | |
1300 | packet_set_ipv6_addr(packet, proto, nh->ip6_dst.be32, dst, | |
1301 | !rh_present); | |
1302 | } | |
1303 | ||
1304 | packet_set_ipv6_tc(&nh->ip6_flow, key_tc); | |
1305 | packet_set_ipv6_flow_label(&nh->ip6_flow, key_fl); | |
1306 | nh->ip6_hlim = key_hl; | |
1307 | } | |
1308 | ||
1309 | static void | |
1310 | packet_set_port(ovs_be16 *port, ovs_be16 new_port, ovs_be16 *csum) | |
1311 | { | |
1312 | if (*port != new_port) { | |
1313 | *csum = recalc_csum16(*csum, *port, new_port); | |
1314 | *port = new_port; | |
1315 | } | |
1316 | } | |
1317 | ||
1318 | /* Sets the TCP source and destination port ('src' and 'dst' respectively) of | |
1319 | * the TCP header contained in 'packet'. 'packet' must be a valid TCP packet | |
1320 | * with its l4 offset properly populated. */ | |
1321 | void | |
1322 | packet_set_tcp_port(struct dp_packet *packet, ovs_be16 src, ovs_be16 dst) | |
1323 | { | |
1324 | struct tcp_header *th = dp_packet_l4(packet); | |
1325 | ||
1326 | packet_set_port(&th->tcp_src, src, &th->tcp_csum); | |
1327 | packet_set_port(&th->tcp_dst, dst, &th->tcp_csum); | |
1328 | pkt_metadata_init_conn(&packet->md); | |
1329 | } | |
1330 | ||
1331 | /* Sets the UDP source and destination port ('src' and 'dst' respectively) of | |
1332 | * the UDP header contained in 'packet'. 'packet' must be a valid UDP packet | |
1333 | * with its l4 offset properly populated. */ | |
1334 | void | |
1335 | packet_set_udp_port(struct dp_packet *packet, ovs_be16 src, ovs_be16 dst) | |
1336 | { | |
1337 | struct udp_header *uh = dp_packet_l4(packet); | |
1338 | ||
1339 | if (uh->udp_csum) { | |
1340 | packet_set_port(&uh->udp_src, src, &uh->udp_csum); | |
1341 | packet_set_port(&uh->udp_dst, dst, &uh->udp_csum); | |
1342 | ||
1343 | if (!uh->udp_csum) { | |
1344 | uh->udp_csum = htons(0xffff); | |
1345 | } | |
1346 | } else { | |
1347 | uh->udp_src = src; | |
1348 | uh->udp_dst = dst; | |
1349 | } | |
1350 | pkt_metadata_init_conn(&packet->md); | |
1351 | } | |
1352 | ||
1353 | /* Sets the SCTP source and destination port ('src' and 'dst' respectively) of | |
1354 | * the SCTP header contained in 'packet'. 'packet' must be a valid SCTP packet | |
1355 | * with its l4 offset properly populated. */ | |
1356 | void | |
1357 | packet_set_sctp_port(struct dp_packet *packet, ovs_be16 src, ovs_be16 dst) | |
1358 | { | |
1359 | struct sctp_header *sh = dp_packet_l4(packet); | |
1360 | ovs_be32 old_csum, old_correct_csum, new_csum; | |
1361 | uint16_t tp_len = dp_packet_l4_size(packet); | |
1362 | ||
1363 | old_csum = get_16aligned_be32(&sh->sctp_csum); | |
1364 | put_16aligned_be32(&sh->sctp_csum, 0); | |
1365 | old_correct_csum = crc32c((void *)sh, tp_len); | |
1366 | ||
1367 | sh->sctp_src = src; | |
1368 | sh->sctp_dst = dst; | |
1369 | ||
1370 | new_csum = crc32c((void *)sh, tp_len); | |
1371 | put_16aligned_be32(&sh->sctp_csum, old_csum ^ old_correct_csum ^ new_csum); | |
1372 | pkt_metadata_init_conn(&packet->md); | |
1373 | } | |
1374 | ||
1375 | /* Sets the ICMP type and code of the ICMP header contained in 'packet'. | |
1376 | * 'packet' must be a valid ICMP packet with its l4 offset properly | |
1377 | * populated. */ | |
1378 | void | |
1379 | packet_set_icmp(struct dp_packet *packet, uint8_t type, uint8_t code) | |
1380 | { | |
1381 | struct icmp_header *ih = dp_packet_l4(packet); | |
1382 | ovs_be16 orig_tc = htons(ih->icmp_type << 8 | ih->icmp_code); | |
1383 | ovs_be16 new_tc = htons(type << 8 | code); | |
1384 | ||
1385 | if (orig_tc != new_tc) { | |
1386 | ih->icmp_type = type; | |
1387 | ih->icmp_code = code; | |
1388 | ||
1389 | ih->icmp_csum = recalc_csum16(ih->icmp_csum, orig_tc, new_tc); | |
1390 | } | |
1391 | pkt_metadata_init_conn(&packet->md); | |
1392 | } | |
1393 | ||
1394 | /* Sets the IGMP type to IGMP_HOST_MEMBERSHIP_QUERY and populates the | |
1395 | * v3 query header fields in 'packet'. 'packet' must be a valid IGMPv3 | |
1396 | * query packet with its l4 offset properly populated. | |
1397 | */ | |
1398 | void | |
1399 | packet_set_igmp3_query(struct dp_packet *packet, uint8_t max_resp, | |
1400 | ovs_be32 group, bool srs, uint8_t qrv, uint8_t qqic) | |
1401 | { | |
1402 | struct igmpv3_query_header *igh = dp_packet_l4(packet); | |
1403 | ovs_be16 orig_type_max_resp = | |
1404 | htons(igh->type << 8 | igh->max_resp); | |
1405 | ovs_be16 new_type_max_resp = | |
1406 | htons(IGMP_HOST_MEMBERSHIP_QUERY << 8 | max_resp); | |
1407 | ||
1408 | if (orig_type_max_resp != new_type_max_resp) { | |
1409 | igh->type = IGMP_HOST_MEMBERSHIP_QUERY; | |
1410 | igh->max_resp = max_resp; | |
1411 | igh->csum = recalc_csum16(igh->csum, orig_type_max_resp, | |
1412 | new_type_max_resp); | |
1413 | } | |
1414 | ||
1415 | ovs_be32 old_group = get_16aligned_be32(&igh->group); | |
1416 | ||
1417 | if (old_group != group) { | |
1418 | put_16aligned_be32(&igh->group, group); | |
1419 | igh->csum = recalc_csum32(igh->csum, old_group, group); | |
1420 | } | |
1421 | ||
1422 | /* See RFC 3376 4.1.6. */ | |
1423 | if (qrv > 7) { | |
1424 | qrv = 0; | |
1425 | } | |
1426 | ||
1427 | ovs_be16 orig_srs_qrv_qqic = htons(igh->srs_qrv << 8 | igh->qqic); | |
1428 | ovs_be16 new_srs_qrv_qqic = htons(srs << 11 | qrv << 8 | qqic); | |
1429 | ||
1430 | if (orig_srs_qrv_qqic != new_srs_qrv_qqic) { | |
1431 | igh->srs_qrv = (srs << 3 | qrv); | |
1432 | igh->qqic = qqic; | |
1433 | igh->csum = recalc_csum16(igh->csum, orig_srs_qrv_qqic, | |
1434 | new_srs_qrv_qqic); | |
1435 | } | |
1436 | } | |
1437 | ||
1438 | void | |
1439 | packet_set_nd_ext(struct dp_packet *packet, const ovs_16aligned_be32 rso_flags, | |
1440 | const uint8_t opt_type) | |
1441 | { | |
1442 | struct ovs_nd_msg *ns; | |
1443 | struct ovs_nd_lla_opt *opt; | |
1444 | int bytes_remain = dp_packet_l4_size(packet); | |
1445 | struct ovs_16aligned_ip6_hdr * nh = dp_packet_l3(packet); | |
1446 | uint32_t pseudo_hdr_csum = 0; | |
1447 | ||
1448 | if (OVS_UNLIKELY(bytes_remain < sizeof(*ns))) { | |
1449 | return; | |
1450 | } | |
1451 | ||
1452 | if (nh) { | |
1453 | pseudo_hdr_csum = packet_csum_pseudoheader6(nh); | |
1454 | } | |
1455 | ||
1456 | ns = dp_packet_l4(packet); | |
1457 | opt = &ns->options[0]; | |
1458 | ||
1459 | /* set RSO flags and option type */ | |
1460 | ns->rso_flags = rso_flags; | |
1461 | opt->type = opt_type; | |
1462 | ||
1463 | /* recalculate checksum */ | |
1464 | ovs_be16 *csum_value = &(ns->icmph.icmp6_cksum); | |
1465 | *csum_value = 0; | |
1466 | *csum_value = csum_finish(csum_continue(pseudo_hdr_csum, | |
1467 | &(ns->icmph), bytes_remain)); | |
1468 | ||
1469 | } | |
1470 | ||
1471 | void | |
1472 | packet_set_nd(struct dp_packet *packet, const struct in6_addr *target, | |
1473 | const struct eth_addr sll, const struct eth_addr tll) | |
1474 | { | |
1475 | struct ovs_nd_msg *ns; | |
1476 | struct ovs_nd_lla_opt *opt; | |
1477 | int bytes_remain = dp_packet_l4_size(packet); | |
1478 | ||
1479 | if (OVS_UNLIKELY(bytes_remain < sizeof(*ns))) { | |
1480 | return; | |
1481 | } | |
1482 | ||
1483 | ns = dp_packet_l4(packet); | |
1484 | opt = &ns->options[0]; | |
1485 | bytes_remain -= sizeof(*ns); | |
1486 | ||
1487 | if (memcmp(&ns->target, target, sizeof(ovs_be32[4]))) { | |
1488 | packet_set_ipv6_addr(packet, IPPROTO_ICMPV6, ns->target.be32, target, | |
1489 | true); | |
1490 | } | |
1491 | ||
1492 | while (bytes_remain >= ND_LLA_OPT_LEN && opt->len != 0) { | |
1493 | if (opt->type == ND_OPT_SOURCE_LINKADDR && opt->len == 1) { | |
1494 | if (!eth_addr_equals(opt->mac, sll)) { | |
1495 | ovs_be16 *csum = &(ns->icmph.icmp6_cksum); | |
1496 | ||
1497 | *csum = recalc_csum48(*csum, opt->mac, sll); | |
1498 | opt->mac = sll; | |
1499 | } | |
1500 | ||
1501 | /* A packet can only contain one SLL or TLL option */ | |
1502 | break; | |
1503 | } else if (opt->type == ND_OPT_TARGET_LINKADDR && opt->len == 1) { | |
1504 | if (!eth_addr_equals(opt->mac, tll)) { | |
1505 | ovs_be16 *csum = &(ns->icmph.icmp6_cksum); | |
1506 | ||
1507 | *csum = recalc_csum48(*csum, opt->mac, tll); | |
1508 | opt->mac = tll; | |
1509 | } | |
1510 | ||
1511 | /* A packet can only contain one SLL or TLL option */ | |
1512 | break; | |
1513 | } | |
1514 | ||
1515 | opt += opt->len; | |
1516 | bytes_remain -= opt->len * ND_LLA_OPT_LEN; | |
1517 | } | |
1518 | } | |
1519 | ||
1520 | const char * | |
1521 | packet_tcp_flag_to_string(uint32_t flag) | |
1522 | { | |
1523 | switch (flag) { | |
1524 | case TCP_FIN: | |
1525 | return "fin"; | |
1526 | case TCP_SYN: | |
1527 | return "syn"; | |
1528 | case TCP_RST: | |
1529 | return "rst"; | |
1530 | case TCP_PSH: | |
1531 | return "psh"; | |
1532 | case TCP_ACK: | |
1533 | return "ack"; | |
1534 | case TCP_URG: | |
1535 | return "urg"; | |
1536 | case TCP_ECE: | |
1537 | return "ece"; | |
1538 | case TCP_CWR: | |
1539 | return "cwr"; | |
1540 | case TCP_NS: | |
1541 | return "ns"; | |
1542 | case 0x200: | |
1543 | return "[200]"; | |
1544 | case 0x400: | |
1545 | return "[400]"; | |
1546 | case 0x800: | |
1547 | return "[800]"; | |
1548 | default: | |
1549 | return NULL; | |
1550 | } | |
1551 | } | |
1552 | ||
1553 | /* Appends a string representation of the TCP flags value 'tcp_flags' | |
1554 | * (e.g. from struct flow.tcp_flags or obtained via TCP_FLAGS) to 's', in the | |
1555 | * format used by tcpdump. */ | |
1556 | void | |
1557 | packet_format_tcp_flags(struct ds *s, uint16_t tcp_flags) | |
1558 | { | |
1559 | if (!tcp_flags) { | |
1560 | ds_put_cstr(s, "none"); | |
1561 | return; | |
1562 | } | |
1563 | ||
1564 | if (tcp_flags & TCP_SYN) { | |
1565 | ds_put_char(s, 'S'); | |
1566 | } | |
1567 | if (tcp_flags & TCP_FIN) { | |
1568 | ds_put_char(s, 'F'); | |
1569 | } | |
1570 | if (tcp_flags & TCP_PSH) { | |
1571 | ds_put_char(s, 'P'); | |
1572 | } | |
1573 | if (tcp_flags & TCP_RST) { | |
1574 | ds_put_char(s, 'R'); | |
1575 | } | |
1576 | if (tcp_flags & TCP_URG) { | |
1577 | ds_put_char(s, 'U'); | |
1578 | } | |
1579 | if (tcp_flags & TCP_ACK) { | |
1580 | ds_put_char(s, '.'); | |
1581 | } | |
1582 | if (tcp_flags & TCP_ECE) { | |
1583 | ds_put_cstr(s, "E"); | |
1584 | } | |
1585 | if (tcp_flags & TCP_CWR) { | |
1586 | ds_put_cstr(s, "C"); | |
1587 | } | |
1588 | if (tcp_flags & TCP_NS) { | |
1589 | ds_put_cstr(s, "N"); | |
1590 | } | |
1591 | if (tcp_flags & 0x200) { | |
1592 | ds_put_cstr(s, "[200]"); | |
1593 | } | |
1594 | if (tcp_flags & 0x400) { | |
1595 | ds_put_cstr(s, "[400]"); | |
1596 | } | |
1597 | if (tcp_flags & 0x800) { | |
1598 | ds_put_cstr(s, "[800]"); | |
1599 | } | |
1600 | } | |
1601 | ||
1602 | #define ARP_PACKET_SIZE (2 + ETH_HEADER_LEN + VLAN_HEADER_LEN + \ | |
1603 | ARP_ETH_HEADER_LEN) | |
1604 | ||
1605 | /* Clears 'b' and replaces its contents by an ARP frame with the specified | |
1606 | * 'arp_op', 'arp_sha', 'arp_tha', 'arp_spa', and 'arp_tpa'. The outer | |
1607 | * Ethernet frame is initialized with Ethernet source 'arp_sha' and destination | |
1608 | * 'arp_tha', except that destination ff:ff:ff:ff:ff:ff is used instead if | |
1609 | * 'broadcast' is true. Points the L3 header to the ARP header. */ | |
1610 | void | |
1611 | compose_arp(struct dp_packet *b, uint16_t arp_op, | |
1612 | const struct eth_addr arp_sha, const struct eth_addr arp_tha, | |
1613 | bool broadcast, ovs_be32 arp_spa, ovs_be32 arp_tpa) | |
1614 | { | |
1615 | compose_arp__(b); | |
1616 | ||
1617 | struct eth_header *eth = dp_packet_eth(b); | |
1618 | eth->eth_dst = broadcast ? eth_addr_broadcast : arp_tha; | |
1619 | eth->eth_src = arp_sha; | |
1620 | ||
1621 | struct arp_eth_header *arp = dp_packet_l3(b); | |
1622 | arp->ar_op = htons(arp_op); | |
1623 | arp->ar_sha = arp_sha; | |
1624 | arp->ar_tha = arp_tha; | |
1625 | put_16aligned_be32(&arp->ar_spa, arp_spa); | |
1626 | put_16aligned_be32(&arp->ar_tpa, arp_tpa); | |
1627 | } | |
1628 | ||
1629 | /* Clears 'b' and replaces its contents by an ARP frame. Sets the fields in | |
1630 | * the Ethernet and ARP headers that are fixed for ARP frames to those fixed | |
1631 | * values, and zeroes the other fields. Points the L3 header to the ARP | |
1632 | * header. */ | |
1633 | void | |
1634 | compose_arp__(struct dp_packet *b) | |
1635 | { | |
1636 | dp_packet_clear(b); | |
1637 | dp_packet_prealloc_tailroom(b, ARP_PACKET_SIZE); | |
1638 | dp_packet_reserve(b, 2 + VLAN_HEADER_LEN); | |
1639 | ||
1640 | struct eth_header *eth = dp_packet_put_zeros(b, sizeof *eth); | |
1641 | eth->eth_type = htons(ETH_TYPE_ARP); | |
1642 | ||
1643 | struct arp_eth_header *arp = dp_packet_put_zeros(b, sizeof *arp); | |
1644 | arp->ar_hrd = htons(ARP_HRD_ETHERNET); | |
1645 | arp->ar_pro = htons(ARP_PRO_IP); | |
1646 | arp->ar_hln = sizeof arp->ar_sha; | |
1647 | arp->ar_pln = sizeof arp->ar_spa; | |
1648 | ||
1649 | dp_packet_reset_offsets(b); | |
1650 | dp_packet_set_l3(b, arp); | |
1651 | ||
1652 | b->packet_type = htonl(PT_ETH); | |
1653 | } | |
1654 | ||
1655 | /* This function expects packet with ethernet header with correct | |
1656 | * l3 pointer set. */ | |
1657 | void * | |
1658 | compose_ipv6(struct dp_packet *packet, uint8_t proto, | |
1659 | const struct in6_addr *src, const struct in6_addr *dst, | |
1660 | uint8_t key_tc, ovs_be32 key_fl, uint8_t key_hl, int size) | |
1661 | { | |
1662 | struct ip6_hdr *nh; | |
1663 | void *data; | |
1664 | ||
1665 | nh = dp_packet_l3(packet); | |
1666 | nh->ip6_vfc = 0x60; | |
1667 | nh->ip6_nxt = proto; | |
1668 | nh->ip6_plen = htons(size); | |
1669 | data = dp_packet_put_zeros(packet, size); | |
1670 | dp_packet_set_l4(packet, data); | |
1671 | packet_set_ipv6(packet, src, dst, key_tc, key_fl, key_hl); | |
1672 | return data; | |
1673 | } | |
1674 | ||
1675 | /* Compose an IPv6 Neighbor Discovery Neighbor Solicitation message. */ | |
1676 | void | |
1677 | compose_nd_ns(struct dp_packet *b, const struct eth_addr eth_src, | |
1678 | const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst) | |
1679 | { | |
1680 | struct in6_addr sn_addr; | |
1681 | struct eth_addr eth_dst; | |
1682 | struct ovs_nd_msg *ns; | |
1683 | struct ovs_nd_lla_opt *lla_opt; | |
1684 | uint32_t icmp_csum; | |
1685 | ||
1686 | in6_addr_solicited_node(&sn_addr, ipv6_dst); | |
1687 | ipv6_multicast_to_ethernet(ð_dst, &sn_addr); | |
1688 | ||
1689 | eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN); | |
1690 | ns = compose_ipv6(b, IPPROTO_ICMPV6, ipv6_src, &sn_addr, | |
1691 | 0, 0, 255, ND_MSG_LEN + ND_LLA_OPT_LEN); | |
1692 | ||
1693 | ns->icmph.icmp6_type = ND_NEIGHBOR_SOLICIT; | |
1694 | ns->icmph.icmp6_code = 0; | |
1695 | put_16aligned_be32(&ns->rso_flags, htonl(0)); | |
1696 | ||
1697 | lla_opt = &ns->options[0]; | |
1698 | lla_opt->type = ND_OPT_SOURCE_LINKADDR; | |
1699 | lla_opt->len = 1; | |
1700 | ||
1701 | packet_set_nd(b, ipv6_dst, eth_src, eth_addr_zero); | |
1702 | ||
1703 | ns->icmph.icmp6_cksum = 0; | |
1704 | icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b)); | |
1705 | ns->icmph.icmp6_cksum = csum_finish( | |
1706 | csum_continue(icmp_csum, ns, ND_MSG_LEN + ND_LLA_OPT_LEN)); | |
1707 | } | |
1708 | ||
1709 | /* Compose an IPv6 Neighbor Discovery Neighbor Advertisement message. */ | |
1710 | void | |
1711 | compose_nd_na(struct dp_packet *b, | |
1712 | const struct eth_addr eth_src, const struct eth_addr eth_dst, | |
1713 | const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst, | |
1714 | ovs_be32 rso_flags) | |
1715 | { | |
1716 | struct ovs_nd_msg *na; | |
1717 | struct ovs_nd_lla_opt *lla_opt; | |
1718 | uint32_t icmp_csum; | |
1719 | ||
1720 | eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN); | |
1721 | na = compose_ipv6(b, IPPROTO_ICMPV6, ipv6_src, ipv6_dst, | |
1722 | 0, 0, 255, ND_MSG_LEN + ND_LLA_OPT_LEN); | |
1723 | ||
1724 | na->icmph.icmp6_type = ND_NEIGHBOR_ADVERT; | |
1725 | na->icmph.icmp6_code = 0; | |
1726 | put_16aligned_be32(&na->rso_flags, rso_flags); | |
1727 | ||
1728 | lla_opt = &na->options[0]; | |
1729 | lla_opt->type = ND_OPT_TARGET_LINKADDR; | |
1730 | lla_opt->len = 1; | |
1731 | ||
1732 | packet_set_nd(b, ipv6_src, eth_addr_zero, eth_src); | |
1733 | ||
1734 | na->icmph.icmp6_cksum = 0; | |
1735 | icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b)); | |
1736 | na->icmph.icmp6_cksum = csum_finish(csum_continue( | |
1737 | icmp_csum, na, ND_MSG_LEN + ND_LLA_OPT_LEN)); | |
1738 | } | |
1739 | ||
1740 | /* Compose an IPv6 Neighbor Discovery Router Advertisement message with | |
1741 | * Source Link-layer Address Option and MTU Option. | |
1742 | * Caller can call packet_put_ra_prefix_opt to append Prefix Information | |
1743 | * Options to composed messags in 'b'. */ | |
1744 | void | |
1745 | compose_nd_ra(struct dp_packet *b, | |
1746 | const struct eth_addr eth_src, const struct eth_addr eth_dst, | |
1747 | const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst, | |
1748 | uint8_t cur_hop_limit, uint8_t mo_flags, | |
1749 | ovs_be16 router_lt, ovs_be32 reachable_time, | |
1750 | ovs_be32 retrans_timer, uint32_t mtu) | |
1751 | { | |
1752 | /* Don't compose Router Advertisement packet with MTU Option if mtu | |
1753 | * value is 0. */ | |
1754 | bool with_mtu = mtu != 0; | |
1755 | size_t mtu_opt_len = with_mtu ? ND_MTU_OPT_LEN : 0; | |
1756 | ||
1757 | eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN); | |
1758 | ||
1759 | struct ovs_ra_msg *ra = compose_ipv6( | |
1760 | b, IPPROTO_ICMPV6, ipv6_src, ipv6_dst, 0, 0, 255, | |
1761 | RA_MSG_LEN + ND_LLA_OPT_LEN + mtu_opt_len); | |
1762 | ra->icmph.icmp6_type = ND_ROUTER_ADVERT; | |
1763 | ra->icmph.icmp6_code = 0; | |
1764 | ra->cur_hop_limit = cur_hop_limit; | |
1765 | ra->mo_flags = mo_flags; | |
1766 | ra->router_lifetime = router_lt; | |
1767 | ra->reachable_time = reachable_time; | |
1768 | ra->retrans_timer = retrans_timer; | |
1769 | ||
1770 | struct ovs_nd_lla_opt *lla_opt = ra->options; | |
1771 | lla_opt->type = ND_OPT_SOURCE_LINKADDR; | |
1772 | lla_opt->len = 1; | |
1773 | lla_opt->mac = eth_src; | |
1774 | ||
1775 | if (with_mtu) { | |
1776 | /* ovs_nd_mtu_opt has the same size with ovs_nd_lla_opt. */ | |
1777 | struct ovs_nd_mtu_opt *mtu_opt | |
1778 | = (struct ovs_nd_mtu_opt *)(lla_opt + 1); | |
1779 | mtu_opt->type = ND_OPT_MTU; | |
1780 | mtu_opt->len = 1; | |
1781 | mtu_opt->reserved = 0; | |
1782 | put_16aligned_be32(&mtu_opt->mtu, htonl(mtu)); | |
1783 | } | |
1784 | ||
1785 | ra->icmph.icmp6_cksum = 0; | |
1786 | uint32_t icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b)); | |
1787 | ra->icmph.icmp6_cksum = csum_finish(csum_continue( | |
1788 | icmp_csum, ra, RA_MSG_LEN + ND_LLA_OPT_LEN + mtu_opt_len)); | |
1789 | } | |
1790 | ||
1791 | /* Append an IPv6 Neighbor Discovery Prefix Information option to a | |
1792 | * Router Advertisement message. */ | |
1793 | void | |
1794 | packet_put_ra_prefix_opt(struct dp_packet *b, | |
1795 | uint8_t plen, uint8_t la_flags, | |
1796 | ovs_be32 valid_lifetime, ovs_be32 preferred_lifetime, | |
1797 | const ovs_be128 prefix) | |
1798 | { | |
1799 | size_t prev_l4_size = dp_packet_l4_size(b); | |
1800 | struct ip6_hdr *nh = dp_packet_l3(b); | |
1801 | nh->ip6_plen = htons(prev_l4_size + ND_PREFIX_OPT_LEN); | |
1802 | ||
1803 | struct ovs_nd_prefix_opt *prefix_opt = | |
1804 | dp_packet_put_uninit(b, sizeof *prefix_opt); | |
1805 | prefix_opt->type = ND_OPT_PREFIX_INFORMATION; | |
1806 | prefix_opt->len = 4; | |
1807 | prefix_opt->prefix_len = plen; | |
1808 | prefix_opt->la_flags = la_flags; | |
1809 | put_16aligned_be32(&prefix_opt->valid_lifetime, valid_lifetime); | |
1810 | put_16aligned_be32(&prefix_opt->preferred_lifetime, preferred_lifetime); | |
1811 | put_16aligned_be32(&prefix_opt->reserved, 0); | |
1812 | memcpy(prefix_opt->prefix.be32, prefix.be32, sizeof(ovs_be32[4])); | |
1813 | ||
1814 | struct ovs_ra_msg *ra = dp_packet_l4(b); | |
1815 | ra->icmph.icmp6_cksum = 0; | |
1816 | uint32_t icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b)); | |
1817 | ra->icmph.icmp6_cksum = csum_finish(csum_continue( | |
1818 | icmp_csum, ra, prev_l4_size + ND_PREFIX_OPT_LEN)); | |
1819 | } | |
1820 | ||
1821 | uint32_t | |
1822 | packet_csum_pseudoheader(const struct ip_header *ip) | |
1823 | { | |
1824 | uint32_t partial = 0; | |
1825 | ||
1826 | partial = csum_add32(partial, get_16aligned_be32(&ip->ip_src)); | |
1827 | partial = csum_add32(partial, get_16aligned_be32(&ip->ip_dst)); | |
1828 | partial = csum_add16(partial, htons(ip->ip_proto)); | |
1829 | partial = csum_add16(partial, htons(ntohs(ip->ip_tot_len) - | |
1830 | IP_IHL(ip->ip_ihl_ver) * 4)); | |
1831 | ||
1832 | return partial; | |
1833 | } | |
1834 | ||
1835 | #ifndef __CHECKER__ | |
1836 | uint32_t | |
1837 | packet_csum_pseudoheader6(const struct ovs_16aligned_ip6_hdr *ip6) | |
1838 | { | |
1839 | uint32_t partial = 0; | |
1840 | ||
1841 | partial = csum_continue(partial, &ip6->ip6_src, sizeof ip6->ip6_src); | |
1842 | partial = csum_continue(partial, &ip6->ip6_dst, sizeof ip6->ip6_dst); | |
1843 | partial = csum_add16(partial, htons(ip6->ip6_nxt)); | |
1844 | partial = csum_add16(partial, ip6->ip6_plen); | |
1845 | ||
1846 | return partial; | |
1847 | } | |
1848 | ||
1849 | /* Calculate the IPv6 upper layer checksum according to RFC2460. We pass the | |
1850 | ip6_nxt and ip6_plen values, so it will also work if extension headers | |
1851 | are present. */ | |
1852 | ovs_be16 | |
1853 | packet_csum_upperlayer6(const struct ovs_16aligned_ip6_hdr *ip6, | |
1854 | const void *data, uint8_t l4_protocol, | |
1855 | uint16_t l4_size) | |
1856 | { | |
1857 | uint32_t partial = 0; | |
1858 | ||
1859 | partial = csum_continue(partial, &ip6->ip6_src, sizeof ip6->ip6_src); | |
1860 | partial = csum_continue(partial, &ip6->ip6_dst, sizeof ip6->ip6_dst); | |
1861 | partial = csum_add16(partial, htons(l4_protocol)); | |
1862 | partial = csum_add16(partial, htons(l4_size)); | |
1863 | ||
1864 | partial = csum_continue(partial, data, l4_size); | |
1865 | ||
1866 | return csum_finish(partial); | |
1867 | } | |
1868 | #endif | |
1869 | ||
1870 | void | |
1871 | IP_ECN_set_ce(struct dp_packet *pkt, bool is_ipv6) | |
1872 | { | |
1873 | if (is_ipv6) { | |
1874 | ovs_16aligned_be32 *ip6 = dp_packet_l3(pkt); | |
1875 | ||
1876 | put_16aligned_be32(ip6, get_16aligned_be32(ip6) | | |
1877 | htonl(IP_ECN_CE << 20)); | |
1878 | } else { | |
1879 | struct ip_header *nh = dp_packet_l3(pkt); | |
1880 | uint8_t tos = nh->ip_tos; | |
1881 | ||
1882 | tos |= IP_ECN_CE; | |
1883 | if (nh->ip_tos != tos) { | |
1884 | nh->ip_csum = recalc_csum16(nh->ip_csum, htons(nh->ip_tos), | |
1885 | htons((uint16_t) tos)); | |
1886 | nh->ip_tos = tos; | |
1887 | } | |
1888 | } | |
1889 | } |