]>
Commit | Line | Data |
---|---|---|
b9e8b45a | 1 | /* |
2c5f293c | 2 | * Copyright (c) 2009, 2010, 2011 Nicira Networks. |
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 JP |
19 | #include <assert.h> |
20 | #include <arpa/inet.h> | |
6ca00f6f | 21 | #include <sys/socket.h> |
b9e8b45a | 22 | #include <netinet/in.h> |
76343538 | 23 | #include <stdlib.h> |
d31f1109 JP |
24 | #include "byte-order.h" |
25 | #include "dynamic-string.h" | |
b9e8b45a BP |
26 | #include "ofpbuf.h" |
27 | ||
d31f1109 JP |
28 | const struct in6_addr in6addr_exact = IN6ADDR_EXACT_INIT; |
29 | ||
093ca5b3 BP |
30 | /* Parses 's' as a 16-digit hexadecimal number representing a datapath ID. On |
31 | * success stores the dpid into '*dpidp' and returns true, on failure stores 0 | |
32 | * into '*dpidp' and returns false. | |
33 | * | |
34 | * Rejects an all-zeros dpid as invalid. */ | |
76343538 BP |
35 | bool |
36 | dpid_from_string(const char *s, uint64_t *dpidp) | |
37 | { | |
b123cc3c | 38 | *dpidp = (strlen(s) == 16 && strspn(s, "0123456789abcdefABCDEF") == 16 |
093ca5b3 | 39 | ? strtoull(s, NULL, 16) |
76343538 BP |
40 | : 0); |
41 | return *dpidp != 0; | |
42 | } | |
43 | ||
44 | bool | |
45 | eth_addr_from_string(const char *s, uint8_t ea[ETH_ADDR_LEN]) | |
46 | { | |
47 | if (sscanf(s, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(ea)) | |
48 | == ETH_ADDR_SCAN_COUNT) { | |
49 | return true; | |
50 | } else { | |
51 | memset(ea, 0, ETH_ADDR_LEN); | |
52 | return false; | |
53 | } | |
54 | } | |
55 | ||
b9e8b45a BP |
56 | /* Fills 'b' with an 802.2 SNAP packet with Ethernet source address 'eth_src', |
57 | * the Nicira OUI as SNAP organization and 'snap_type' as SNAP type. The text | |
58 | * string in 'tag' is enclosed as the packet payload. | |
59 | * | |
60 | * This function is used by Open vSwitch to compose packets in cases where | |
61 | * context is important but content doesn't (or shouldn't) matter. For this | |
62 | * purpose, 'snap_type' should be a random number and 'tag' should be an | |
63 | * English phrase that explains the purpose of the packet. (The English phrase | |
64 | * gives hapless admins running Wireshark the opportunity to figure out what's | |
65 | * going on.) */ | |
66 | void | |
67 | compose_benign_packet(struct ofpbuf *b, const char *tag, uint16_t snap_type, | |
68 | const uint8_t eth_src[ETH_ADDR_LEN]) | |
69 | { | |
2c5f293c BP |
70 | size_t tag_size = strlen(tag) + 1; |
71 | char *payload; | |
b9e8b45a | 72 | |
2c5f293c BP |
73 | payload = snap_compose(b, eth_addr_broadcast, eth_src, 0x002320, snap_type, |
74 | tag_size + ETH_ADDR_LEN); | |
75 | memcpy(payload, tag, tag_size); | |
76 | memcpy(payload + tag_size, eth_src, ETH_ADDR_LEN); | |
b9e8b45a | 77 | } |
d31f1109 | 78 | |
d9065a90 PS |
79 | /* Insert VLAN header according to given TCI. Packet passed must be Ethernet |
80 | * packet. | |
7c66b273 BP |
81 | * |
82 | * Also sets 'packet->l2' to point to the new Ethernet header. */ | |
83 | void | |
d9065a90 | 84 | eth_push_vlan(struct ofpbuf *packet, ovs_be16 tci) |
7c66b273 BP |
85 | { |
86 | struct eth_header *eh = packet->data; | |
87 | struct vlan_eth_header *veh; | |
88 | ||
d9065a90 PS |
89 | /* Insert new 802.1Q header. */ |
90 | struct vlan_eth_header tmp; | |
91 | memcpy(tmp.veth_dst, eh->eth_dst, ETH_ADDR_LEN); | |
92 | memcpy(tmp.veth_src, eh->eth_src, ETH_ADDR_LEN); | |
93 | tmp.veth_type = htons(ETH_TYPE_VLAN); | |
94 | tmp.veth_tci = tci; | |
95 | tmp.veth_next_type = eh->eth_type; | |
96 | ||
97 | veh = ofpbuf_push_uninit(packet, VLAN_HEADER_LEN); | |
98 | memcpy(veh, &tmp, sizeof tmp); | |
7c66b273 | 99 | |
7c66b273 BP |
100 | packet->l2 = packet->data; |
101 | } | |
102 | ||
aad29cd1 BP |
103 | /* Given the IP netmask 'netmask', returns the number of bits of the IP address |
104 | * that it specifies, that is, the number of 1-bits in 'netmask'. 'netmask' | |
105 | * must be a CIDR netmask (see ip_is_cidr()). */ | |
106 | int | |
107 | ip_count_cidr_bits(ovs_be32 netmask) | |
108 | { | |
109 | assert(ip_is_cidr(netmask)); | |
110 | return 32 - ctz(ntohl(netmask)); | |
111 | } | |
112 | ||
113 | void | |
114 | ip_format_masked(ovs_be32 ip, ovs_be32 mask, struct ds *s) | |
115 | { | |
116 | ds_put_format(s, IP_FMT, IP_ARGS(&ip)); | |
117 | if (mask != htonl(UINT32_MAX)) { | |
118 | if (ip_is_cidr(mask)) { | |
119 | ds_put_format(s, "/%d", ip_count_cidr_bits(mask)); | |
120 | } else { | |
121 | ds_put_format(s, "/"IP_FMT, IP_ARGS(&mask)); | |
122 | } | |
123 | } | |
124 | } | |
125 | ||
126 | ||
d31f1109 JP |
127 | /* Stores the string representation of the IPv6 address 'addr' into the |
128 | * character array 'addr_str', which must be at least INET6_ADDRSTRLEN | |
129 | * bytes long. */ | |
130 | void | |
131 | format_ipv6_addr(char *addr_str, const struct in6_addr *addr) | |
132 | { | |
133 | inet_ntop(AF_INET6, addr, addr_str, INET6_ADDRSTRLEN); | |
134 | } | |
135 | ||
136 | void | |
137 | print_ipv6_addr(struct ds *string, const struct in6_addr *addr) | |
138 | { | |
aad29cd1 BP |
139 | char *dst; |
140 | ||
141 | ds_reserve(string, string->length + INET6_ADDRSTRLEN); | |
142 | ||
143 | dst = string->string + string->length; | |
144 | format_ipv6_addr(dst, addr); | |
145 | string->length += strlen(dst); | |
146 | } | |
d31f1109 | 147 | |
aad29cd1 BP |
148 | void |
149 | print_ipv6_masked(struct ds *s, const struct in6_addr *addr, | |
150 | const struct in6_addr *mask) | |
151 | { | |
152 | print_ipv6_addr(s, addr); | |
153 | if (mask && !ipv6_mask_is_exact(mask)) { | |
154 | if (ipv6_is_cidr(mask)) { | |
155 | int cidr_bits = ipv6_count_cidr_bits(mask); | |
156 | ds_put_format(s, "/%d", cidr_bits); | |
157 | } else { | |
158 | ds_put_char(s, '/'); | |
159 | print_ipv6_addr(s, mask); | |
160 | } | |
161 | } | |
d31f1109 JP |
162 | } |
163 | ||
164 | struct in6_addr ipv6_addr_bitand(const struct in6_addr *a, | |
165 | const struct in6_addr *b) | |
166 | { | |
167 | int i; | |
168 | struct in6_addr dst; | |
169 | ||
170 | #ifdef s6_addr32 | |
171 | for (i=0; i<4; i++) { | |
172 | dst.s6_addr32[i] = a->s6_addr32[i] & b->s6_addr32[i]; | |
173 | } | |
174 | #else | |
175 | for (i=0; i<16; i++) { | |
176 | dst.s6_addr[i] = a->s6_addr[i] & b->s6_addr[i]; | |
177 | } | |
178 | #endif | |
179 | ||
180 | return dst; | |
181 | } | |
182 | ||
183 | /* Returns an in6_addr consisting of 'mask' high-order 1-bits and 128-N | |
184 | * low-order 0-bits. */ | |
185 | struct in6_addr | |
186 | ipv6_create_mask(int mask) | |
187 | { | |
188 | struct in6_addr netmask; | |
189 | uint8_t *netmaskp = &netmask.s6_addr[0]; | |
190 | ||
191 | memset(&netmask, 0, sizeof netmask); | |
192 | while (mask > 8) { | |
193 | *netmaskp = 0xff; | |
194 | netmaskp++; | |
195 | mask -= 8; | |
196 | } | |
197 | ||
198 | if (mask) { | |
199 | *netmaskp = 0xff << (8 - mask); | |
200 | } | |
201 | ||
202 | return netmask; | |
203 | } | |
204 | ||
aad29cd1 BP |
205 | /* Given the IPv6 netmask 'netmask', returns the number of bits of the IPv6 |
206 | * address that it specifies, that is, the number of 1-bits in 'netmask'. | |
207 | * 'netmask' must be a CIDR netmask (see ipv6_is_cidr()). */ | |
d31f1109 JP |
208 | int |
209 | ipv6_count_cidr_bits(const struct in6_addr *netmask) | |
210 | { | |
211 | int i; | |
212 | int count = 0; | |
213 | const uint8_t *netmaskp = &netmask->s6_addr[0]; | |
214 | ||
215 | assert(ipv6_is_cidr(netmask)); | |
216 | ||
217 | for (i=0; i<16; i++) { | |
218 | if (netmaskp[i] == 0xff) { | |
219 | count += 8; | |
220 | } else { | |
221 | uint8_t nm; | |
222 | ||
223 | for(nm = netmaskp[i]; nm; nm <<= 1) { | |
224 | count++; | |
225 | } | |
226 | break; | |
227 | } | |
228 | ||
229 | } | |
230 | ||
231 | return count; | |
232 | } | |
233 | ||
d31f1109 JP |
234 | /* Returns true if 'netmask' is a CIDR netmask, that is, if it consists of N |
235 | * high-order 1-bits and 128-N low-order 0-bits. */ | |
236 | bool | |
237 | ipv6_is_cidr(const struct in6_addr *netmask) | |
238 | { | |
239 | const uint8_t *netmaskp = &netmask->s6_addr[0]; | |
240 | int i; | |
241 | ||
242 | for (i=0; i<16; i++) { | |
243 | if (netmaskp[i] != 0xff) { | |
244 | uint8_t x = ~netmaskp[i]; | |
245 | if (x & (x + 1)) { | |
246 | return false; | |
247 | } | |
248 | while (++i < 16) { | |
249 | if (netmaskp[i]) { | |
250 | return false; | |
251 | } | |
252 | } | |
253 | } | |
254 | } | |
255 | ||
256 | return true; | |
257 | } | |
c25c91fd | 258 | |
5de1bb5c BP |
259 | /* Populates 'b' with an Ethernet II packet headed with the given 'eth_dst', |
260 | * 'eth_src' and 'eth_type' parameters. A payload of 'size' bytes is allocated | |
261 | * in 'b' and returned. This payload may be populated with appropriate | |
eda1f38d BP |
262 | * information by the caller. |
263 | * | |
264 | * The returned packet has enough headroom to insert an 802.1Q VLAN header if | |
265 | * desired. */ | |
40f78b38 | 266 | void * |
5de1bb5c BP |
267 | eth_compose(struct ofpbuf *b, const uint8_t eth_dst[ETH_ADDR_LEN], |
268 | const uint8_t eth_src[ETH_ADDR_LEN], uint16_t eth_type, | |
269 | size_t size) | |
c25c91fd | 270 | { |
40f78b38 | 271 | void *data; |
c25c91fd | 272 | struct eth_header *eth; |
c25c91fd EJ |
273 | |
274 | ofpbuf_clear(b); | |
275 | ||
eda1f38d BP |
276 | ofpbuf_prealloc_tailroom(b, ETH_HEADER_LEN + VLAN_HEADER_LEN + size); |
277 | ofpbuf_reserve(b, VLAN_HEADER_LEN); | |
40f78b38 EJ |
278 | eth = ofpbuf_put_uninit(b, ETH_HEADER_LEN); |
279 | data = ofpbuf_put_uninit(b, size); | |
c25c91fd | 280 | |
40f78b38 | 281 | memcpy(eth->eth_dst, eth_dst, ETH_ADDR_LEN); |
c25c91fd | 282 | memcpy(eth->eth_src, eth_src, ETH_ADDR_LEN); |
40f78b38 EJ |
283 | eth->eth_type = htons(eth_type); |
284 | ||
285 | return data; | |
07a6cf77 EJ |
286 | } |
287 | ||
5de1bb5c BP |
288 | /* Populates 'b' with an Ethernet LLC+SNAP packet headed with the given |
289 | * 'eth_dst', 'eth_src', 'snap_org', and 'snap_type'. A payload of 'size' | |
290 | * bytes is allocated in 'b' and returned. This payload may be populated with | |
eda1f38d BP |
291 | * appropriate information by the caller. |
292 | * | |
293 | * The returned packet has enough headroom to insert an 802.1Q VLAN header if | |
294 | * desired. */ | |
5de1bb5c BP |
295 | void * |
296 | snap_compose(struct ofpbuf *b, const uint8_t eth_dst[ETH_ADDR_LEN], | |
297 | const uint8_t eth_src[ETH_ADDR_LEN], | |
298 | unsigned int oui, uint16_t snap_type, size_t size) | |
299 | { | |
300 | struct eth_header *eth; | |
301 | struct llc_snap_header *llc_snap; | |
302 | void *payload; | |
303 | ||
304 | /* Compose basic packet structure. (We need the payload size to stick into | |
305 | * the 802.2 header.) */ | |
306 | ofpbuf_clear(b); | |
eda1f38d BP |
307 | ofpbuf_prealloc_tailroom(b, ETH_HEADER_LEN + VLAN_HEADER_LEN |
308 | + LLC_SNAP_HEADER_LEN + size); | |
309 | ofpbuf_reserve(b, VLAN_HEADER_LEN); | |
5de1bb5c BP |
310 | eth = ofpbuf_put_zeros(b, ETH_HEADER_LEN); |
311 | llc_snap = ofpbuf_put_zeros(b, LLC_SNAP_HEADER_LEN); | |
312 | payload = ofpbuf_put_uninit(b, size); | |
313 | ||
314 | /* Compose 802.2 header. */ | |
315 | memcpy(eth->eth_dst, eth_dst, ETH_ADDR_LEN); | |
316 | memcpy(eth->eth_src, eth_src, ETH_ADDR_LEN); | |
317 | eth->eth_type = htons(b->size - ETH_HEADER_LEN); | |
318 | ||
319 | /* Compose LLC, SNAP headers. */ | |
320 | llc_snap->llc.llc_dsap = LLC_DSAP_SNAP; | |
321 | llc_snap->llc.llc_ssap = LLC_SSAP_SNAP; | |
322 | llc_snap->llc.llc_cntl = LLC_CNTL_SNAP; | |
323 | llc_snap->snap.snap_org[0] = oui >> 16; | |
324 | llc_snap->snap.snap_org[1] = oui >> 8; | |
325 | llc_snap->snap.snap_org[2] = oui; | |
326 | llc_snap->snap.snap_type = htons(snap_type); | |
327 | ||
328 | return payload; | |
329 | } |