]>
Commit | Line | Data |
---|---|---|
b9e8b45a | 1 | /* |
48cecbdc | 2 | * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc. |
b9e8b45a BP |
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" | |
d31f1109 | 19 | #include <arpa/inet.h> |
6ca00f6f | 20 | #include <sys/socket.h> |
b9e8b45a | 21 | #include <netinet/in.h> |
bc7a5acd | 22 | #include <netinet/ip6.h> |
76343538 | 23 | #include <stdlib.h> |
d31f1109 | 24 | #include "byte-order.h" |
c97664b3 | 25 | #include "csum.h" |
12113c39 | 26 | #include "flow.h" |
7d48a4cc | 27 | #include "hmap.h" |
d31f1109 | 28 | #include "dynamic-string.h" |
b9e8b45a BP |
29 | #include "ofpbuf.h" |
30 | ||
d31f1109 JP |
31 | const struct in6_addr in6addr_exact = IN6ADDR_EXACT_INIT; |
32 | ||
093ca5b3 BP |
33 | /* Parses 's' as a 16-digit hexadecimal number representing a datapath ID. On |
34 | * success stores the dpid into '*dpidp' and returns true, on failure stores 0 | |
35 | * into '*dpidp' and returns false. | |
36 | * | |
37 | * Rejects an all-zeros dpid as invalid. */ | |
76343538 BP |
38 | bool |
39 | dpid_from_string(const char *s, uint64_t *dpidp) | |
40 | { | |
b123cc3c | 41 | *dpidp = (strlen(s) == 16 && strspn(s, "0123456789abcdefABCDEF") == 16 |
093ca5b3 | 42 | ? strtoull(s, NULL, 16) |
76343538 BP |
43 | : 0); |
44 | return *dpidp != 0; | |
45 | } | |
46 | ||
7d48a4cc BP |
47 | /* Returns true if 'ea' is a reserved address, that a bridge must never |
48 | * forward, false otherwise. | |
05be4e2c EJ |
49 | * |
50 | * If you change this function's behavior, please update corresponding | |
51 | * documentation in vswitch.xml at the same time. */ | |
52 | bool | |
53 | eth_addr_is_reserved(const uint8_t ea[ETH_ADDR_LEN]) | |
54 | { | |
7d48a4cc BP |
55 | struct eth_addr_node { |
56 | struct hmap_node hmap_node; | |
57 | uint64_t ea64; | |
05be4e2c EJ |
58 | }; |
59 | ||
7d48a4cc BP |
60 | static struct eth_addr_node nodes[] = { |
61 | /* STP, IEEE pause frames, and other reserved protocols. */ | |
62 | { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000000ULL }, | |
63 | { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000001ULL }, | |
64 | { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000002ULL }, | |
65 | { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000003ULL }, | |
66 | { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000004ULL }, | |
67 | { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000005ULL }, | |
68 | { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000006ULL }, | |
69 | { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000007ULL }, | |
70 | { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000008ULL }, | |
71 | { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000009ULL }, | |
72 | { HMAP_NODE_NULL_INITIALIZER, 0x0108c200000aULL }, | |
73 | { HMAP_NODE_NULL_INITIALIZER, 0x0108c200000bULL }, | |
74 | { HMAP_NODE_NULL_INITIALIZER, 0x0108c200000cULL }, | |
75 | { HMAP_NODE_NULL_INITIALIZER, 0x0108c200000dULL }, | |
76 | { HMAP_NODE_NULL_INITIALIZER, 0x0108c200000eULL }, | |
77 | { HMAP_NODE_NULL_INITIALIZER, 0x0108c200000fULL }, | |
78 | ||
79 | /* Extreme protocols. */ | |
80 | { HMAP_NODE_NULL_INITIALIZER, 0x00e02b000000ULL }, /* EDP. */ | |
81 | { HMAP_NODE_NULL_INITIALIZER, 0x00e02b000004ULL }, /* EAPS. */ | |
82 | { HMAP_NODE_NULL_INITIALIZER, 0x00e02b000006ULL }, /* EAPS. */ | |
83 | ||
84 | /* Cisco protocols. */ | |
85 | { HMAP_NODE_NULL_INITIALIZER, 0x01000c000000ULL }, /* ISL. */ | |
86 | { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccccULL }, /* PAgP, UDLD, CDP, | |
87 | * DTP, VTP. */ | |
88 | { HMAP_NODE_NULL_INITIALIZER, 0x01000ccccccdULL }, /* PVST+. */ | |
89 | { HMAP_NODE_NULL_INITIALIZER, 0x01000ccdcdcdULL }, /* STP Uplink Fast, | |
90 | * FlexLink. */ | |
91 | ||
92 | /* Cisco CFM. */ | |
93 | { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc0ULL }, | |
94 | { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc1ULL }, | |
95 | { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc2ULL }, | |
96 | { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc3ULL }, | |
97 | { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc4ULL }, | |
98 | { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc5ULL }, | |
99 | { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc6ULL }, | |
100 | { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc7ULL }, | |
101 | }; | |
05be4e2c | 102 | |
7d48a4cc BP |
103 | static struct hmap addrs = HMAP_INITIALIZER(&addrs); |
104 | struct eth_addr_node *node; | |
105 | uint64_t ea64; | |
05be4e2c | 106 | |
7d48a4cc BP |
107 | if (hmap_is_empty(&addrs)) { |
108 | for (node = nodes; node < &nodes[ARRAY_SIZE(nodes)]; node++) { | |
109 | hmap_insert(&addrs, &node->hmap_node, | |
110 | hash_2words(node->ea64, node->ea64 >> 32)); | |
111 | } | |
112 | } | |
05be4e2c | 113 | |
7d48a4cc BP |
114 | ea64 = eth_addr_to_uint64(ea); |
115 | HMAP_FOR_EACH_IN_BUCKET (node, hmap_node, hash_2words(ea64, ea64 >> 32), | |
116 | &addrs) { | |
117 | if (node->ea64 == ea64) { | |
05be4e2c EJ |
118 | return true; |
119 | } | |
120 | } | |
121 | return false; | |
122 | } | |
123 | ||
76343538 BP |
124 | bool |
125 | eth_addr_from_string(const char *s, uint8_t ea[ETH_ADDR_LEN]) | |
126 | { | |
127 | if (sscanf(s, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(ea)) | |
128 | == ETH_ADDR_SCAN_COUNT) { | |
129 | return true; | |
130 | } else { | |
131 | memset(ea, 0, ETH_ADDR_LEN); | |
132 | return false; | |
133 | } | |
134 | } | |
135 | ||
38f7147c | 136 | /* Fills 'b' with a Reverse ARP packet with Ethernet source address 'eth_src'. |
b9e8b45a | 137 | * This function is used by Open vSwitch to compose packets in cases where |
38f7147c EJ |
138 | * context is important but content doesn't (or shouldn't) matter. |
139 | * | |
140 | * The returned packet has enough headroom to insert an 802.1Q VLAN header if | |
141 | * desired. */ | |
b9e8b45a | 142 | void |
2ea838ac | 143 | compose_rarp(struct ofpbuf *b, const uint8_t eth_src[ETH_ADDR_LEN]) |
b9e8b45a | 144 | { |
38f7147c | 145 | struct eth_header *eth; |
7cb57d10 | 146 | struct arp_eth_header *arp; |
b9e8b45a | 147 | |
38f7147c EJ |
148 | ofpbuf_clear(b); |
149 | ofpbuf_prealloc_tailroom(b, ETH_HEADER_LEN + VLAN_HEADER_LEN | |
7cb57d10 | 150 | + ARP_ETH_HEADER_LEN); |
38f7147c EJ |
151 | ofpbuf_reserve(b, VLAN_HEADER_LEN); |
152 | eth = ofpbuf_put_uninit(b, sizeof *eth); | |
153 | memcpy(eth->eth_dst, eth_addr_broadcast, ETH_ADDR_LEN); | |
154 | memcpy(eth->eth_src, eth_src, ETH_ADDR_LEN); | |
155 | eth->eth_type = htons(ETH_TYPE_RARP); | |
156 | ||
7cb57d10 EJ |
157 | arp = ofpbuf_put_uninit(b, sizeof *arp); |
158 | arp->ar_hrd = htons(ARP_HRD_ETHERNET); | |
159 | arp->ar_pro = htons(ARP_PRO_IP); | |
160 | arp->ar_hln = sizeof arp->ar_sha; | |
161 | arp->ar_pln = sizeof arp->ar_spa; | |
162 | arp->ar_op = htons(ARP_OP_RARP); | |
163 | memcpy(arp->ar_sha, eth_src, ETH_ADDR_LEN); | |
164 | arp->ar_spa = htonl(0); | |
165 | memcpy(arp->ar_tha, eth_src, ETH_ADDR_LEN); | |
166 | arp->ar_tpa = htonl(0); | |
b9e8b45a | 167 | } |
d31f1109 | 168 | |
d9065a90 | 169 | /* Insert VLAN header according to given TCI. Packet passed must be Ethernet |
2f4ca41b | 170 | * packet. Ignores the CFI bit of 'tci' using 0 instead. |
7c66b273 BP |
171 | * |
172 | * Also sets 'packet->l2' to point to the new Ethernet header. */ | |
173 | void | |
d9065a90 | 174 | eth_push_vlan(struct ofpbuf *packet, ovs_be16 tci) |
7c66b273 BP |
175 | { |
176 | struct eth_header *eh = packet->data; | |
177 | struct vlan_eth_header *veh; | |
178 | ||
d9065a90 PS |
179 | /* Insert new 802.1Q header. */ |
180 | struct vlan_eth_header tmp; | |
181 | memcpy(tmp.veth_dst, eh->eth_dst, ETH_ADDR_LEN); | |
182 | memcpy(tmp.veth_src, eh->eth_src, ETH_ADDR_LEN); | |
183 | tmp.veth_type = htons(ETH_TYPE_VLAN); | |
2f4ca41b | 184 | tmp.veth_tci = tci & htons(~VLAN_CFI); |
d9065a90 PS |
185 | tmp.veth_next_type = eh->eth_type; |
186 | ||
187 | veh = ofpbuf_push_uninit(packet, VLAN_HEADER_LEN); | |
188 | memcpy(veh, &tmp, sizeof tmp); | |
7c66b273 | 189 | |
7c66b273 BP |
190 | packet->l2 = packet->data; |
191 | } | |
192 | ||
f4ebc25e BP |
193 | /* Removes outermost VLAN header (if any is present) from 'packet'. |
194 | * | |
b02475c5 SH |
195 | * 'packet->l2_5' should initially point to 'packet''s outer-most MPLS header |
196 | * or may be NULL if there are no MPLS headers. */ | |
f4ebc25e BP |
197 | void |
198 | eth_pop_vlan(struct ofpbuf *packet) | |
199 | { | |
200 | struct vlan_eth_header *veh = packet->l2; | |
201 | if (packet->size >= sizeof *veh | |
202 | && veh->veth_type == htons(ETH_TYPE_VLAN)) { | |
203 | struct eth_header tmp; | |
204 | ||
205 | memcpy(tmp.eth_dst, veh->veth_dst, ETH_ADDR_LEN); | |
206 | memcpy(tmp.eth_src, veh->veth_src, ETH_ADDR_LEN); | |
207 | tmp.eth_type = veh->veth_next_type; | |
208 | ||
209 | ofpbuf_pull(packet, VLAN_HEADER_LEN); | |
210 | packet->l2 = (char*)packet->l2 + VLAN_HEADER_LEN; | |
211 | memcpy(packet->data, &tmp, sizeof tmp); | |
212 | } | |
213 | } | |
214 | ||
b02475c5 SH |
215 | /* Return depth of mpls stack. |
216 | * | |
217 | * 'packet->l2_5' should initially point to 'packet''s outer-most MPLS header | |
218 | * or may be NULL if there are no MPLS headers. */ | |
219 | uint16_t | |
220 | eth_mpls_depth(const struct ofpbuf *packet) | |
221 | { | |
222 | struct mpls_hdr *mh = packet->l2_5; | |
223 | uint16_t depth; | |
224 | ||
225 | if (!mh) { | |
226 | return 0; | |
227 | } | |
228 | ||
229 | depth = 0; | |
230 | while (packet->size >= ((char *)mh - (char *)packet->data) + sizeof *mh) { | |
231 | depth++; | |
232 | if (mh->mpls_lse & htonl(MPLS_BOS_MASK)) { | |
233 | break; | |
234 | } | |
235 | mh++; | |
236 | } | |
237 | ||
238 | return depth; | |
239 | } | |
240 | ||
241 | /* Set ethertype of the packet. */ | |
242 | void | |
243 | set_ethertype(struct ofpbuf *packet, ovs_be16 eth_type) | |
244 | { | |
245 | struct eth_header *eh = packet->data; | |
246 | ||
247 | if (eh->eth_type == htons(ETH_TYPE_VLAN)) { | |
248 | ovs_be16 *p; | |
249 | p = (ovs_be16 *)((char *)(packet->l2_5 ? packet->l2_5 : packet->l3) - 2); | |
250 | *p = eth_type; | |
251 | } else { | |
252 | eh->eth_type = eth_type; | |
253 | } | |
254 | } | |
255 | ||
256 | static bool is_mpls(struct ofpbuf *packet) | |
257 | { | |
258 | return packet->l2_5 != NULL; | |
259 | } | |
260 | ||
261 | /* Set time to live (TTL) of an MPLS label stack entry (LSE). */ | |
b676167a | 262 | void |
b02475c5 SH |
263 | set_mpls_lse_ttl(ovs_be32 *lse, uint8_t ttl) |
264 | { | |
265 | *lse &= ~htonl(MPLS_TTL_MASK); | |
266 | *lse |= htonl((ttl << MPLS_TTL_SHIFT) & MPLS_TTL_MASK); | |
267 | } | |
268 | ||
269 | /* Set traffic class (TC) of an MPLS label stack entry (LSE). */ | |
270 | void | |
271 | set_mpls_lse_tc(ovs_be32 *lse, uint8_t tc) | |
272 | { | |
273 | *lse &= ~htonl(MPLS_TC_MASK); | |
274 | *lse |= htonl((tc << MPLS_TC_SHIFT) & MPLS_TC_MASK); | |
275 | } | |
276 | ||
277 | /* Set label of an MPLS label stack entry (LSE). */ | |
278 | void | |
279 | set_mpls_lse_label(ovs_be32 *lse, ovs_be32 label) | |
280 | { | |
281 | *lse &= ~htonl(MPLS_LABEL_MASK); | |
282 | *lse |= htonl((ntohl(label) << MPLS_LABEL_SHIFT) & MPLS_LABEL_MASK); | |
283 | } | |
284 | ||
285 | /* Set bottom of stack (BoS) bit of an MPLS label stack entry (LSE). */ | |
286 | void | |
287 | set_mpls_lse_bos(ovs_be32 *lse, uint8_t bos) | |
288 | { | |
289 | *lse &= ~htonl(MPLS_BOS_MASK); | |
290 | *lse |= htonl((bos << MPLS_BOS_SHIFT) & MPLS_BOS_MASK); | |
291 | } | |
292 | ||
293 | /* Compose an MPLS label stack entry (LSE) from its components: | |
294 | * label, traffic class (TC), time to live (TTL) and | |
295 | * bottom of stack (BoS) bit. */ | |
296 | ovs_be32 | |
297 | set_mpls_lse_values(uint8_t ttl, uint8_t tc, uint8_t bos, ovs_be32 label) | |
298 | { | |
299 | ovs_be32 lse = htonl(0); | |
300 | set_mpls_lse_ttl(&lse, ttl); | |
301 | set_mpls_lse_tc(&lse, tc); | |
302 | set_mpls_lse_bos(&lse, bos); | |
303 | set_mpls_lse_label(&lse, label); | |
304 | return lse; | |
305 | } | |
306 | ||
307 | /* Push an new MPLS stack entry onto the MPLS stack and adjust 'packet->l2' and | |
308 | * 'packet->l2_5' accordingly. The new entry will be the outermost entry on | |
309 | * the stack. | |
310 | * | |
311 | * Previous to calling this function, 'packet->l2_5' must be set; if the MPLS | |
312 | * label to be pushed will be the first label in 'packet', then it should be | |
313 | * the same as 'packet->l3'. */ | |
314 | static void | |
315 | push_mpls_lse(struct ofpbuf *packet, struct mpls_hdr *mh) | |
316 | { | |
317 | char * header; | |
318 | size_t len; | |
319 | header = ofpbuf_push_uninit(packet, MPLS_HLEN); | |
320 | len = (char *)packet->l2_5 - (char *)packet->l2; | |
321 | memmove(header, packet->l2, len); | |
322 | memcpy(header + len, mh, sizeof *mh); | |
323 | packet->l2 = (char*)packet->l2 - MPLS_HLEN; | |
324 | packet->l2_5 = (char*)packet->l2_5 - MPLS_HLEN; | |
325 | } | |
326 | ||
327 | /* Set MPLS label stack entry to outermost MPLS header.*/ | |
328 | void | |
329 | set_mpls_lse(struct ofpbuf *packet, ovs_be32 mpls_lse) | |
330 | { | |
331 | struct mpls_hdr *mh = packet->l2_5; | |
332 | ||
333 | /* Packet type should be MPLS to set label stack entry. */ | |
334 | if (is_mpls(packet)) { | |
335 | /* Update mpls label stack entry. */ | |
336 | mh->mpls_lse = mpls_lse; | |
337 | } | |
338 | } | |
339 | ||
340 | /* Push MPLS label stack entry 'lse' onto 'packet' as the the outermost MPLS | |
341 | * header. If 'packet' does not already have any MPLS labels, then its | |
342 | * Ethertype is changed to 'ethtype' (which must be an MPLS Ethertype). */ | |
343 | void | |
344 | push_mpls(struct ofpbuf *packet, ovs_be16 ethtype, ovs_be32 lse) | |
345 | { | |
346 | struct mpls_hdr mh; | |
347 | ||
348 | if (!eth_type_mpls(ethtype)) { | |
349 | return; | |
350 | } | |
351 | ||
352 | if (!is_mpls(packet)) { | |
353 | /* Set ethtype and MPLS label stack entry. */ | |
354 | set_ethertype(packet, ethtype); | |
355 | packet->l2_5 = packet->l3; | |
356 | } | |
357 | ||
358 | /* Push new MPLS shim header onto packet. */ | |
359 | mh.mpls_lse = lse; | |
360 | push_mpls_lse(packet, &mh); | |
361 | } | |
362 | ||
363 | /* If 'packet' is an MPLS packet, removes its outermost MPLS label stack entry. | |
364 | * If the label that was removed was the only MPLS label, changes 'packet''s | |
365 | * Ethertype to 'ethtype' (which ordinarily should not be an MPLS | |
366 | * Ethertype). */ | |
367 | void | |
368 | pop_mpls(struct ofpbuf *packet, ovs_be16 ethtype) | |
369 | { | |
370 | struct mpls_hdr *mh = NULL; | |
371 | ||
372 | if (is_mpls(packet)) { | |
373 | size_t len; | |
374 | mh = packet->l2_5; | |
375 | len = (char*)packet->l2_5 - (char*)packet->l2; | |
376 | /* If bottom of the stack set ethertype. */ | |
377 | if (mh->mpls_lse & htonl(MPLS_BOS_MASK)) { | |
b02475c5 | 378 | set_ethertype(packet, ethtype); |
2555b1db | 379 | packet->l2_5 = NULL; |
b02475c5 SH |
380 | } else { |
381 | packet->l2_5 = (char*)packet->l2_5 + MPLS_HLEN; | |
382 | } | |
383 | /* Shift the l2 header forward. */ | |
384 | memmove((char*)packet->data + MPLS_HLEN, packet->data, len); | |
385 | packet->size -= MPLS_HLEN; | |
386 | packet->data = (char*)packet->data + MPLS_HLEN; | |
387 | packet->l2 = (char*)packet->l2 + MPLS_HLEN; | |
388 | } | |
389 | } | |
390 | ||
e22f1753 BP |
391 | /* Converts hex digits in 'hex' to an Ethernet packet in '*packetp'. The |
392 | * caller must free '*packetp'. On success, returns NULL. On failure, returns | |
393 | * an error message and stores NULL in '*packetp'. */ | |
394 | const char * | |
395 | eth_from_hex(const char *hex, struct ofpbuf **packetp) | |
396 | { | |
397 | struct ofpbuf *packet; | |
398 | ||
399 | packet = *packetp = ofpbuf_new(strlen(hex) / 2); | |
400 | ||
401 | if (ofpbuf_put_hex(packet, hex, NULL)[0] != '\0') { | |
402 | ofpbuf_delete(packet); | |
403 | *packetp = NULL; | |
404 | return "Trailing garbage in packet data"; | |
405 | } | |
406 | ||
407 | if (packet->size < ETH_HEADER_LEN) { | |
408 | ofpbuf_delete(packet); | |
409 | *packetp = NULL; | |
410 | return "Packet data too short for Ethernet"; | |
411 | } | |
412 | ||
413 | return NULL; | |
414 | } | |
415 | ||
3b4d8ad3 JS |
416 | void |
417 | eth_format_masked(const uint8_t eth[ETH_ADDR_LEN], | |
418 | const uint8_t mask[ETH_ADDR_LEN], struct ds *s) | |
419 | { | |
420 | ds_put_format(s, ETH_ADDR_FMT, ETH_ADDR_ARGS(eth)); | |
73c0ce34 | 421 | if (mask && !eth_mask_is_exact(mask)) { |
3b4d8ad3 JS |
422 | ds_put_format(s, "/"ETH_ADDR_FMT, ETH_ADDR_ARGS(mask)); |
423 | } | |
424 | } | |
425 | ||
426 | void | |
427 | eth_addr_bitand(const uint8_t src[ETH_ADDR_LEN], | |
428 | const uint8_t mask[ETH_ADDR_LEN], | |
429 | uint8_t dst[ETH_ADDR_LEN]) | |
430 | { | |
431 | int i; | |
432 | ||
433 | for (i = 0; i < ETH_ADDR_LEN; i++) { | |
434 | dst[i] = src[i] & mask[i]; | |
435 | } | |
436 | } | |
437 | ||
aad29cd1 | 438 | /* Given the IP netmask 'netmask', returns the number of bits of the IP address |
c08201d6 BP |
439 | * that it specifies, that is, the number of 1-bits in 'netmask'. |
440 | * | |
441 | * If 'netmask' is not a CIDR netmask (see ip_is_cidr()), the return value will | |
442 | * still be in the valid range but isn't otherwise meaningful. */ | |
aad29cd1 BP |
443 | int |
444 | ip_count_cidr_bits(ovs_be32 netmask) | |
445 | { | |
aad29cd1 BP |
446 | return 32 - ctz(ntohl(netmask)); |
447 | } | |
448 | ||
449 | void | |
450 | ip_format_masked(ovs_be32 ip, ovs_be32 mask, struct ds *s) | |
451 | { | |
ed36537e | 452 | ds_put_format(s, IP_FMT, IP_ARGS(ip)); |
aad29cd1 BP |
453 | if (mask != htonl(UINT32_MAX)) { |
454 | if (ip_is_cidr(mask)) { | |
455 | ds_put_format(s, "/%d", ip_count_cidr_bits(mask)); | |
456 | } else { | |
ed36537e | 457 | ds_put_format(s, "/"IP_FMT, IP_ARGS(mask)); |
aad29cd1 BP |
458 | } |
459 | } | |
460 | } | |
461 | ||
462 | ||
d31f1109 JP |
463 | /* Stores the string representation of the IPv6 address 'addr' into the |
464 | * character array 'addr_str', which must be at least INET6_ADDRSTRLEN | |
465 | * bytes long. */ | |
466 | void | |
467 | format_ipv6_addr(char *addr_str, const struct in6_addr *addr) | |
468 | { | |
469 | inet_ntop(AF_INET6, addr, addr_str, INET6_ADDRSTRLEN); | |
470 | } | |
471 | ||
472 | void | |
473 | print_ipv6_addr(struct ds *string, const struct in6_addr *addr) | |
474 | { | |
aad29cd1 BP |
475 | char *dst; |
476 | ||
477 | ds_reserve(string, string->length + INET6_ADDRSTRLEN); | |
478 | ||
479 | dst = string->string + string->length; | |
480 | format_ipv6_addr(dst, addr); | |
481 | string->length += strlen(dst); | |
482 | } | |
d31f1109 | 483 | |
aad29cd1 BP |
484 | void |
485 | print_ipv6_masked(struct ds *s, const struct in6_addr *addr, | |
486 | const struct in6_addr *mask) | |
487 | { | |
488 | print_ipv6_addr(s, addr); | |
489 | if (mask && !ipv6_mask_is_exact(mask)) { | |
490 | if (ipv6_is_cidr(mask)) { | |
491 | int cidr_bits = ipv6_count_cidr_bits(mask); | |
492 | ds_put_format(s, "/%d", cidr_bits); | |
493 | } else { | |
494 | ds_put_char(s, '/'); | |
495 | print_ipv6_addr(s, mask); | |
496 | } | |
497 | } | |
d31f1109 JP |
498 | } |
499 | ||
500 | struct in6_addr ipv6_addr_bitand(const struct in6_addr *a, | |
501 | const struct in6_addr *b) | |
502 | { | |
503 | int i; | |
504 | struct in6_addr dst; | |
505 | ||
506 | #ifdef s6_addr32 | |
507 | for (i=0; i<4; i++) { | |
508 | dst.s6_addr32[i] = a->s6_addr32[i] & b->s6_addr32[i]; | |
509 | } | |
510 | #else | |
511 | for (i=0; i<16; i++) { | |
512 | dst.s6_addr[i] = a->s6_addr[i] & b->s6_addr[i]; | |
513 | } | |
514 | #endif | |
515 | ||
516 | return dst; | |
517 | } | |
518 | ||
519 | /* Returns an in6_addr consisting of 'mask' high-order 1-bits and 128-N | |
520 | * low-order 0-bits. */ | |
521 | struct in6_addr | |
522 | ipv6_create_mask(int mask) | |
523 | { | |
524 | struct in6_addr netmask; | |
525 | uint8_t *netmaskp = &netmask.s6_addr[0]; | |
526 | ||
527 | memset(&netmask, 0, sizeof netmask); | |
528 | while (mask > 8) { | |
529 | *netmaskp = 0xff; | |
530 | netmaskp++; | |
531 | mask -= 8; | |
532 | } | |
533 | ||
534 | if (mask) { | |
535 | *netmaskp = 0xff << (8 - mask); | |
536 | } | |
537 | ||
538 | return netmask; | |
539 | } | |
540 | ||
aad29cd1 BP |
541 | /* Given the IPv6 netmask 'netmask', returns the number of bits of the IPv6 |
542 | * address that it specifies, that is, the number of 1-bits in 'netmask'. | |
ff0b06ee BP |
543 | * 'netmask' must be a CIDR netmask (see ipv6_is_cidr()). |
544 | * | |
545 | * If 'netmask' is not a CIDR netmask (see ipv6_is_cidr()), the return value | |
546 | * will still be in the valid range but isn't otherwise meaningful. */ | |
d31f1109 JP |
547 | int |
548 | ipv6_count_cidr_bits(const struct in6_addr *netmask) | |
549 | { | |
550 | int i; | |
551 | int count = 0; | |
552 | const uint8_t *netmaskp = &netmask->s6_addr[0]; | |
553 | ||
d31f1109 JP |
554 | for (i=0; i<16; i++) { |
555 | if (netmaskp[i] == 0xff) { | |
556 | count += 8; | |
557 | } else { | |
558 | uint8_t nm; | |
559 | ||
560 | for(nm = netmaskp[i]; nm; nm <<= 1) { | |
561 | count++; | |
562 | } | |
563 | break; | |
564 | } | |
565 | ||
566 | } | |
567 | ||
568 | return count; | |
569 | } | |
570 | ||
d31f1109 JP |
571 | /* Returns true if 'netmask' is a CIDR netmask, that is, if it consists of N |
572 | * high-order 1-bits and 128-N low-order 0-bits. */ | |
573 | bool | |
574 | ipv6_is_cidr(const struct in6_addr *netmask) | |
575 | { | |
576 | const uint8_t *netmaskp = &netmask->s6_addr[0]; | |
577 | int i; | |
578 | ||
579 | for (i=0; i<16; i++) { | |
580 | if (netmaskp[i] != 0xff) { | |
581 | uint8_t x = ~netmaskp[i]; | |
582 | if (x & (x + 1)) { | |
583 | return false; | |
584 | } | |
585 | while (++i < 16) { | |
586 | if (netmaskp[i]) { | |
587 | return false; | |
588 | } | |
589 | } | |
590 | } | |
591 | } | |
592 | ||
593 | return true; | |
594 | } | |
c25c91fd | 595 | |
5de1bb5c BP |
596 | /* Populates 'b' with an Ethernet II packet headed with the given 'eth_dst', |
597 | * 'eth_src' and 'eth_type' parameters. A payload of 'size' bytes is allocated | |
598 | * in 'b' and returned. This payload may be populated with appropriate | |
75a4ead1 EJ |
599 | * information by the caller. Sets 'b''s 'l2' and 'l3' pointers to the |
600 | * Ethernet header and payload respectively. | |
eda1f38d BP |
601 | * |
602 | * The returned packet has enough headroom to insert an 802.1Q VLAN header if | |
603 | * desired. */ | |
40f78b38 | 604 | void * |
5de1bb5c BP |
605 | eth_compose(struct ofpbuf *b, const uint8_t eth_dst[ETH_ADDR_LEN], |
606 | const uint8_t eth_src[ETH_ADDR_LEN], uint16_t eth_type, | |
607 | size_t size) | |
c25c91fd | 608 | { |
40f78b38 | 609 | void *data; |
c25c91fd | 610 | struct eth_header *eth; |
c25c91fd EJ |
611 | |
612 | ofpbuf_clear(b); | |
613 | ||
eda1f38d BP |
614 | ofpbuf_prealloc_tailroom(b, ETH_HEADER_LEN + VLAN_HEADER_LEN + size); |
615 | ofpbuf_reserve(b, VLAN_HEADER_LEN); | |
40f78b38 EJ |
616 | eth = ofpbuf_put_uninit(b, ETH_HEADER_LEN); |
617 | data = ofpbuf_put_uninit(b, size); | |
c25c91fd | 618 | |
40f78b38 | 619 | memcpy(eth->eth_dst, eth_dst, ETH_ADDR_LEN); |
c25c91fd | 620 | memcpy(eth->eth_src, eth_src, ETH_ADDR_LEN); |
40f78b38 EJ |
621 | eth->eth_type = htons(eth_type); |
622 | ||
75a4ead1 EJ |
623 | b->l2 = eth; |
624 | b->l3 = data; | |
625 | ||
40f78b38 | 626 | return data; |
07a6cf77 EJ |
627 | } |
628 | ||
c97664b3 EJ |
629 | static void |
630 | packet_set_ipv4_addr(struct ofpbuf *packet, ovs_be32 *addr, ovs_be32 new_addr) | |
631 | { | |
632 | struct ip_header *nh = packet->l3; | |
633 | ||
634 | if (nh->ip_proto == IPPROTO_TCP && packet->l7) { | |
635 | struct tcp_header *th = packet->l4; | |
636 | ||
637 | th->tcp_csum = recalc_csum32(th->tcp_csum, *addr, new_addr); | |
638 | } else if (nh->ip_proto == IPPROTO_UDP && packet->l7) { | |
639 | struct udp_header *uh = packet->l4; | |
640 | ||
641 | if (uh->udp_csum) { | |
642 | uh->udp_csum = recalc_csum32(uh->udp_csum, *addr, new_addr); | |
643 | if (!uh->udp_csum) { | |
644 | uh->udp_csum = htons(0xffff); | |
645 | } | |
646 | } | |
647 | } | |
648 | nh->ip_csum = recalc_csum32(nh->ip_csum, *addr, new_addr); | |
649 | *addr = new_addr; | |
650 | } | |
651 | ||
bc7a5acd AA |
652 | /* Returns true, if packet contains at least one routing header where |
653 | * segements_left > 0. | |
654 | * | |
655 | * This function assumes that L3 and L4 markers are set in the packet. */ | |
656 | static bool | |
657 | packet_rh_present(struct ofpbuf *packet) | |
658 | { | |
659 | const struct ip6_hdr *nh; | |
660 | int nexthdr; | |
661 | size_t len; | |
662 | size_t remaining; | |
663 | uint8_t *data = packet->l3; | |
664 | ||
665 | remaining = (uint8_t *)packet->l4 - (uint8_t *)packet->l3; | |
666 | ||
667 | if (remaining < sizeof *nh) { | |
668 | return false; | |
669 | } | |
670 | nh = (struct ip6_hdr *)data; | |
671 | data += sizeof *nh; | |
672 | remaining -= sizeof *nh; | |
673 | nexthdr = nh->ip6_nxt; | |
674 | ||
675 | while (1) { | |
676 | if ((nexthdr != IPPROTO_HOPOPTS) | |
677 | && (nexthdr != IPPROTO_ROUTING) | |
678 | && (nexthdr != IPPROTO_DSTOPTS) | |
679 | && (nexthdr != IPPROTO_AH) | |
680 | && (nexthdr != IPPROTO_FRAGMENT)) { | |
681 | /* It's either a terminal header (e.g., TCP, UDP) or one we | |
682 | * don't understand. In either case, we're done with the | |
683 | * packet, so use it to fill in 'nw_proto'. */ | |
684 | break; | |
685 | } | |
686 | ||
687 | /* We only verify that at least 8 bytes of the next header are | |
688 | * available, but many of these headers are longer. Ensure that | |
689 | * accesses within the extension header are within those first 8 | |
690 | * bytes. All extension headers are required to be at least 8 | |
691 | * bytes. */ | |
692 | if (remaining < 8) { | |
693 | return false; | |
694 | } | |
695 | ||
696 | if (nexthdr == IPPROTO_AH) { | |
697 | /* A standard AH definition isn't available, but the fields | |
698 | * we care about are in the same location as the generic | |
699 | * option header--only the header length is calculated | |
700 | * differently. */ | |
701 | const struct ip6_ext *ext_hdr = (struct ip6_ext *)data; | |
702 | ||
703 | nexthdr = ext_hdr->ip6e_nxt; | |
704 | len = (ext_hdr->ip6e_len + 2) * 4; | |
705 | } else if (nexthdr == IPPROTO_FRAGMENT) { | |
706 | const struct ip6_frag *frag_hdr = (struct ip6_frag *)data; | |
707 | ||
708 | nexthdr = frag_hdr->ip6f_nxt; | |
709 | len = sizeof *frag_hdr; | |
710 | } else if (nexthdr == IPPROTO_ROUTING) { | |
711 | const struct ip6_rthdr *rh = (struct ip6_rthdr *)data; | |
712 | ||
713 | if (rh->ip6r_segleft > 0) { | |
714 | return true; | |
715 | } | |
716 | ||
717 | nexthdr = rh->ip6r_nxt; | |
718 | len = (rh->ip6r_len + 1) * 8; | |
719 | } else { | |
720 | const struct ip6_ext *ext_hdr = (struct ip6_ext *)data; | |
721 | ||
722 | nexthdr = ext_hdr->ip6e_nxt; | |
723 | len = (ext_hdr->ip6e_len + 1) * 8; | |
724 | } | |
725 | ||
726 | if (remaining < len) { | |
727 | return false; | |
728 | } | |
729 | remaining -= len; | |
730 | data += len; | |
731 | } | |
732 | ||
733 | return false; | |
734 | } | |
735 | ||
736 | static void | |
737 | packet_update_csum128(struct ofpbuf *packet, uint8_t proto, | |
738 | ovs_be32 addr[4], const ovs_be32 new_addr[4]) | |
739 | { | |
740 | if (proto == IPPROTO_TCP && packet->l7) { | |
741 | struct tcp_header *th = packet->l4; | |
742 | ||
743 | th->tcp_csum = recalc_csum128(th->tcp_csum, addr, new_addr); | |
744 | } else if (proto == IPPROTO_UDP && packet->l7) { | |
745 | struct udp_header *uh = packet->l4; | |
746 | ||
747 | if (uh->udp_csum) { | |
748 | uh->udp_csum = recalc_csum128(uh->udp_csum, addr, new_addr); | |
749 | if (!uh->udp_csum) { | |
750 | uh->udp_csum = htons(0xffff); | |
751 | } | |
752 | } | |
753 | } | |
754 | } | |
755 | ||
756 | static void | |
757 | packet_set_ipv6_addr(struct ofpbuf *packet, uint8_t proto, | |
758 | struct in6_addr *addr, const ovs_be32 new_addr[4], | |
759 | bool recalculate_csum) | |
760 | { | |
761 | if (recalculate_csum) { | |
762 | packet_update_csum128(packet, proto, (ovs_be32 *)addr, new_addr); | |
763 | } | |
764 | memcpy(addr, new_addr, sizeof(*addr)); | |
765 | } | |
766 | ||
767 | static void | |
768 | packet_set_ipv6_flow_label(ovs_be32 *flow_label, ovs_be32 flow_key) | |
769 | { | |
770 | *flow_label = (*flow_label & htonl(~IPV6_LABEL_MASK)) | flow_key; | |
771 | } | |
772 | ||
773 | static void | |
774 | packet_set_ipv6_tc(ovs_be32 *flow_label, uint8_t tc) | |
775 | { | |
776 | *flow_label = (*flow_label & htonl(0xF00FFFFF)) | htonl(tc << 20); | |
777 | } | |
778 | ||
c97664b3 EJ |
779 | /* Modifies the IPv4 header fields of 'packet' to be consistent with 'src', |
780 | * 'dst', 'tos', and 'ttl'. Updates 'packet''s L4 checksums as appropriate. | |
781 | * 'packet' must contain a valid IPv4 packet with correctly populated l[347] | |
782 | * markers. */ | |
783 | void | |
784 | packet_set_ipv4(struct ofpbuf *packet, ovs_be32 src, ovs_be32 dst, | |
785 | uint8_t tos, uint8_t ttl) | |
786 | { | |
787 | struct ip_header *nh = packet->l3; | |
788 | ||
789 | if (nh->ip_src != src) { | |
790 | packet_set_ipv4_addr(packet, &nh->ip_src, src); | |
791 | } | |
792 | ||
793 | if (nh->ip_dst != dst) { | |
794 | packet_set_ipv4_addr(packet, &nh->ip_dst, dst); | |
795 | } | |
796 | ||
797 | if (nh->ip_tos != tos) { | |
798 | uint8_t *field = &nh->ip_tos; | |
799 | ||
800 | nh->ip_csum = recalc_csum16(nh->ip_csum, htons((uint16_t) *field), | |
801 | htons((uint16_t) tos)); | |
802 | *field = tos; | |
803 | } | |
804 | ||
805 | if (nh->ip_ttl != ttl) { | |
806 | uint8_t *field = &nh->ip_ttl; | |
807 | ||
808 | nh->ip_csum = recalc_csum16(nh->ip_csum, htons(*field << 8), | |
809 | htons(ttl << 8)); | |
810 | *field = ttl; | |
811 | } | |
812 | } | |
813 | ||
bc7a5acd AA |
814 | /* Modifies the IPv6 header fields of 'packet' to be consistent with 'src', |
815 | * 'dst', 'traffic class', and 'next hop'. Updates 'packet''s L4 checksums as | |
816 | * appropriate. 'packet' must contain a valid IPv6 packet with correctly | |
817 | * populated l[347] markers. */ | |
818 | void | |
819 | packet_set_ipv6(struct ofpbuf *packet, uint8_t proto, const ovs_be32 src[4], | |
820 | const ovs_be32 dst[4], uint8_t key_tc, ovs_be32 key_fl, | |
821 | uint8_t key_hl) | |
822 | { | |
823 | struct ip6_hdr *nh = packet->l3; | |
824 | ||
825 | if (memcmp(&nh->ip6_src, src, sizeof(ovs_be32[4]))) { | |
826 | packet_set_ipv6_addr(packet, proto, &nh->ip6_src, src, true); | |
827 | } | |
828 | ||
829 | if (memcmp(&nh->ip6_dst, dst, sizeof(ovs_be32[4]))) { | |
830 | packet_set_ipv6_addr(packet, proto, &nh->ip6_dst, dst, | |
831 | !packet_rh_present(packet)); | |
832 | } | |
833 | ||
834 | packet_set_ipv6_tc(&nh->ip6_flow, key_tc); | |
835 | ||
836 | packet_set_ipv6_flow_label(&nh->ip6_flow, key_fl); | |
837 | ||
838 | nh->ip6_hlim = key_hl; | |
839 | } | |
840 | ||
c97664b3 EJ |
841 | static void |
842 | packet_set_port(ovs_be16 *port, ovs_be16 new_port, ovs_be16 *csum) | |
843 | { | |
844 | if (*port != new_port) { | |
845 | *csum = recalc_csum16(*csum, *port, new_port); | |
846 | *port = new_port; | |
847 | } | |
848 | } | |
849 | ||
850 | /* Sets the TCP source and destination port ('src' and 'dst' respectively) of | |
851 | * the TCP header contained in 'packet'. 'packet' must be a valid TCP packet | |
852 | * with its l4 marker properly populated. */ | |
853 | void | |
854 | packet_set_tcp_port(struct ofpbuf *packet, ovs_be16 src, ovs_be16 dst) | |
855 | { | |
856 | struct tcp_header *th = packet->l4; | |
857 | ||
858 | packet_set_port(&th->tcp_src, src, &th->tcp_csum); | |
859 | packet_set_port(&th->tcp_dst, dst, &th->tcp_csum); | |
860 | } | |
861 | ||
862 | /* Sets the UDP source and destination port ('src' and 'dst' respectively) of | |
863 | * the UDP header contained in 'packet'. 'packet' must be a valid UDP packet | |
864 | * with its l4 marker properly populated. */ | |
865 | void | |
866 | packet_set_udp_port(struct ofpbuf *packet, ovs_be16 src, ovs_be16 dst) | |
867 | { | |
868 | struct udp_header *uh = packet->l4; | |
869 | ||
870 | if (uh->udp_csum) { | |
871 | packet_set_port(&uh->udp_src, src, &uh->udp_csum); | |
872 | packet_set_port(&uh->udp_dst, dst, &uh->udp_csum); | |
873 | ||
874 | if (!uh->udp_csum) { | |
875 | uh->udp_csum = htons(0xffff); | |
876 | } | |
877 | } else { | |
878 | uh->udp_src = src; | |
879 | uh->udp_dst = dst; | |
880 | } | |
881 | } | |
12113c39 BP |
882 | |
883 | /* If 'packet' is a TCP packet, returns the TCP flags. Otherwise, returns 0. | |
884 | * | |
885 | * 'flow' must be the flow corresponding to 'packet' and 'packet''s header | |
886 | * pointers must be properly initialized (e.g. with flow_extract()). */ | |
887 | uint8_t | |
888 | packet_get_tcp_flags(const struct ofpbuf *packet, const struct flow *flow) | |
889 | { | |
cff78c88 | 890 | if (dl_type_is_ip_any(flow->dl_type) && |
e8c16d83 | 891 | flow->nw_proto == IPPROTO_TCP && packet->l7) { |
12113c39 BP |
892 | const struct tcp_header *tcp = packet->l4; |
893 | return TCP_FLAGS(tcp->tcp_ctl); | |
894 | } else { | |
895 | return 0; | |
896 | } | |
897 | } | |
7393104d BP |
898 | |
899 | /* Appends a string representation of the TCP flags value 'tcp_flags' | |
900 | * (e.g. obtained via packet_get_tcp_flags() or TCP_FLAGS) to 's', in the | |
901 | * format used by tcpdump. */ | |
902 | void | |
903 | packet_format_tcp_flags(struct ds *s, uint8_t tcp_flags) | |
904 | { | |
905 | if (!tcp_flags) { | |
906 | ds_put_cstr(s, "none"); | |
907 | return; | |
908 | } | |
909 | ||
910 | if (tcp_flags & TCP_SYN) { | |
911 | ds_put_char(s, 'S'); | |
912 | } | |
913 | if (tcp_flags & TCP_FIN) { | |
914 | ds_put_char(s, 'F'); | |
915 | } | |
916 | if (tcp_flags & TCP_PSH) { | |
917 | ds_put_char(s, 'P'); | |
918 | } | |
919 | if (tcp_flags & TCP_RST) { | |
920 | ds_put_char(s, 'R'); | |
921 | } | |
922 | if (tcp_flags & TCP_URG) { | |
923 | ds_put_char(s, 'U'); | |
924 | } | |
925 | if (tcp_flags & TCP_ACK) { | |
926 | ds_put_char(s, '.'); | |
927 | } | |
928 | if (tcp_flags & 0x40) { | |
929 | ds_put_cstr(s, "[40]"); | |
930 | } | |
931 | if (tcp_flags & 0x80) { | |
932 | ds_put_cstr(s, "[80]"); | |
933 | } | |
934 | } |