]> git.proxmox.com Git - ovs.git/blame - lib/packets.c
Fix build on FreeBSD.
[ovs.git] / lib / packets.c
CommitLineData
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
28const 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
35bool
36dpid_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
44bool
45eth_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.) */
66void
67compose_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. */
83void
d9065a90 84eth_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()). */
106int
107ip_count_cidr_bits(ovs_be32 netmask)
108{
109 assert(ip_is_cidr(netmask));
110 return 32 - ctz(ntohl(netmask));
111}
112
113void
114ip_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. */
130void
131format_ipv6_addr(char *addr_str, const struct in6_addr *addr)
132{
133 inet_ntop(AF_INET6, addr, addr_str, INET6_ADDRSTRLEN);
134}
135
136void
137print_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
148void
149print_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
164struct 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. */
185struct in6_addr
186ipv6_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
208int
209ipv6_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. */
236bool
237ipv6_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 266void *
5de1bb5c
BP
267eth_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
295void *
296snap_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}