2 * Copyright (c) 2017 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
17 * @brief NAT64 IPv6 to IPv4 translation (inside to outside network)
20 #include <snat/nat64.h>
21 #include <vnet/ip/ip6_to_ip4.h>
22 #include <vnet/fib/fib_table.h>
25 static u8 well_known_prefix[] = {
26 0x00, 0x64, 0xff, 0x9b,
27 0x00, 0x00, 0x00, 0x00,
28 0x00, 0x00, 0x00, 0x00,
29 0x00, 0x00, 0x00, 0x00
37 } nat64_in2out_trace_t;
40 format_nat64_in2out_trace (u8 * s, va_list * args)
42 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
43 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
44 nat64_in2out_trace_t *t = va_arg (*args, nat64_in2out_trace_t *);
47 format (s, "NAT64-in2out: sw_if_index %d, next index %d", t->sw_if_index,
53 vlib_node_registration_t nat64_in2out_node;
55 #define foreach_nat64_in2out_error \
56 _(UNSUPPORTED_PROTOCOL, "unsupported protocol") \
57 _(IN2OUT_PACKETS, "good in2out packets processed") \
58 _(NO_TRANSLATION, "no translation") \
63 #define _(sym,str) NAT64_IN2OUT_ERROR_##sym,
64 foreach_nat64_in2out_error
67 } nat64_in2out_error_t;
69 static char *nat64_in2out_error_strings[] = {
70 #define _(sym,string) string,
71 foreach_nat64_in2out_error
77 NAT64_IN2OUT_NEXT_IP4_LOOKUP,
78 NAT64_IN2OUT_NEXT_IP6_LOOKUP,
79 NAT64_IN2OUT_NEXT_DROP,
81 } nat64_in2out_next_t;
83 typedef struct nat64_in2out_set_ctx_t_
87 } nat64_in2out_set_ctx_t;
90 * @brief Check whether is a hairpinning.
92 * If the destination IP address of the packet is an IPv4 address assigned to
93 * the NAT64 itself, then the packet is a hairpin packet.
95 * param dst_addr Destination address of the packet.
97 * @returns 1 if hairpinning, otherwise 0.
99 static_always_inline int
100 is_hairpinning (ip6_address_t * dst_addr)
102 nat64_main_t *nm = &nat64_main;
105 for (i = 0; i < vec_len (nm->addr_pool); i++)
107 if (nm->addr_pool[i].addr.as_u32 == dst_addr->as_u32[3])
115 nat64_in2out_tcp_udp_set_cb (ip6_header_t * ip6, ip4_header_t * ip4,
118 nat64_main_t *nm = &nat64_main;
119 nat64_in2out_set_ctx_t *ctx = arg;
120 nat64_db_bib_entry_t *bibe;
121 nat64_db_st_entry_t *ste;
122 ip46_address_t saddr, daddr;
123 u32 sw_if_index, fib_index;
124 udp_header_t *udp = ip6_next_header (ip6);
125 snat_protocol_t proto = ip_proto_to_snat_proto (ip6->protocol);
126 u16 sport = udp->src_port;
127 u16 dport = udp->dst_port;
129 sw_if_index = vnet_buffer (ctx->b)->sw_if_index[VLIB_RX];
131 fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6, sw_if_index);
133 saddr.as_u64[0] = ip6->src_address.as_u64[0];
134 saddr.as_u64[1] = ip6->src_address.as_u64[1];
135 daddr.as_u64[0] = ip6->dst_address.as_u64[0];
136 daddr.as_u64[1] = ip6->dst_address.as_u64[1];
139 nat64_db_st_entry_find (&nm->db, &saddr, &daddr, sport, dport, proto,
144 bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
151 nat64_db_bib_entry_find (&nm->db, &saddr, sport, proto, fib_index, 1);
156 ip4_address_t out_addr;
157 if (nat64_alloc_out_addr_and_port
158 (fib_index, proto, &out_addr, &out_port))
162 nat64_db_bib_entry_create (&nm->db, &ip6->src_address, &out_addr,
163 sport, clib_host_to_net_u16 (out_port),
164 fib_index, proto, 0);
170 nat64_db_st_entry_create (&nm->db, bibe, &ip6->dst_address,
176 nat64_session_reset_timeout (ste, ctx->vm);
178 ip4->src_address.as_u32 = bibe->out_addr.as_u32;
179 udp->src_port = bibe->out_port;
181 ip4->dst_address.as_u32 = daddr.ip4.as_u32;
183 if (proto == SNAT_PROTOCOL_TCP)
187 tcp_header_t *tcp = ip6_next_header (ip6);
189 checksum = &tcp->checksum;
190 csum = ip_csum_sub_even (*checksum, sport);
191 csum = ip_csum_add_even (csum, udp->src_port);
192 *checksum = ip_csum_fold (csum);
199 nat64_in2out_icmp_set_cb (ip6_header_t * ip6, ip4_header_t * ip4, void *arg)
201 nat64_main_t *nm = &nat64_main;
202 nat64_in2out_set_ctx_t *ctx = arg;
203 nat64_db_bib_entry_t *bibe;
204 nat64_db_st_entry_t *ste;
205 ip46_address_t saddr, daddr;
206 u32 sw_if_index, fib_index;
207 icmp46_header_t *icmp = ip6_next_header (ip6);
209 sw_if_index = vnet_buffer (ctx->b)->sw_if_index[VLIB_RX];
211 fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6, sw_if_index);
213 saddr.as_u64[0] = ip6->src_address.as_u64[0];
214 saddr.as_u64[1] = ip6->src_address.as_u64[1];
215 daddr.as_u64[0] = ip6->dst_address.as_u64[0];
216 daddr.as_u64[1] = ip6->dst_address.as_u64[1];
218 if (icmp->type == ICMP4_echo_request || icmp->type == ICMP4_echo_reply)
220 u16 in_id = ((u16 *) (icmp))[2];
222 nat64_db_st_entry_find (&nm->db, &saddr, &daddr, in_id, 0,
223 SNAT_PROTOCOL_ICMP, fib_index, 1);
228 nat64_db_bib_entry_by_index (&nm->db, SNAT_PROTOCOL_ICMP,
236 nat64_db_bib_entry_find (&nm->db, &saddr, in_id,
237 SNAT_PROTOCOL_ICMP, fib_index, 1);
242 ip4_address_t out_addr;
243 if (nat64_alloc_out_addr_and_port
244 (fib_index, SNAT_PROTOCOL_ICMP, &out_addr, &out_id))
248 nat64_db_bib_entry_create (&nm->db, &ip6->src_address,
250 clib_host_to_net_u16 (out_id),
251 fib_index, SNAT_PROTOCOL_ICMP, 0);
256 nat64_db_st_entry_create (&nm->db, bibe, &ip6->dst_address,
262 nat64_session_reset_timeout (ste, ctx->vm);
264 ip4->src_address.as_u32 = bibe->out_addr.as_u32;
265 ((u16 *) (icmp))[2] = bibe->out_port;
267 ip4->dst_address.as_u32 = daddr.ip4.as_u32;
271 if (!vec_len (nm->addr_pool))
274 ip4->src_address.as_u32 = nm->addr_pool[0].addr.as_u32;
275 ip4->dst_address.as_u32 = daddr.ip4.as_u32;
282 nat64_in2out_inner_icmp_set_cb (ip6_header_t * ip6, ip4_header_t * ip4,
285 nat64_main_t *nm = &nat64_main;
286 nat64_in2out_set_ctx_t *ctx = arg;
287 nat64_db_st_entry_t *ste;
288 nat64_db_bib_entry_t *bibe;
289 ip46_address_t saddr, daddr;
290 u32 sw_if_index, fib_index;
291 snat_protocol_t proto = ip_proto_to_snat_proto (ip6->protocol);
293 sw_if_index = vnet_buffer (ctx->b)->sw_if_index[VLIB_RX];
295 fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6, sw_if_index);
297 saddr.as_u64[0] = ip6->src_address.as_u64[0];
298 saddr.as_u64[1] = ip6->src_address.as_u64[1];
299 daddr.as_u64[0] = ip6->dst_address.as_u64[0];
300 daddr.as_u64[1] = ip6->dst_address.as_u64[1];
302 if (proto == SNAT_PROTOCOL_ICMP)
304 icmp46_header_t *icmp = ip6_next_header (ip6);
305 u16 in_id = ((u16 *) (icmp))[2];
308 (icmp->type == ICMP4_echo_request
309 || icmp->type == ICMP4_echo_reply))
313 nat64_db_st_entry_find (&nm->db, &daddr, &saddr, in_id, 0, proto,
318 bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
322 ip4->dst_address.as_u32 = bibe->out_addr.as_u32;
323 ((u16 *) (icmp))[2] = bibe->out_port;
324 ip4->src_address.as_u32 = saddr.ip4.as_u32;
328 udp_header_t *udp = ip6_next_header (ip6);
329 tcp_header_t *tcp = ip6_next_header (ip6);
333 u16 sport = udp->src_port;
334 u16 dport = udp->dst_port;
337 nat64_db_st_entry_find (&nm->db, &daddr, &saddr, dport, sport, proto,
342 bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
346 ip4->dst_address.as_u32 = bibe->out_addr.as_u32;
347 udp->dst_port = bibe->out_port;
348 ip4->src_address.as_u32 = saddr.ip4.as_u32;
350 if (proto == SNAT_PROTOCOL_TCP)
351 checksum = &tcp->checksum;
353 checksum = &udp->checksum;
354 csum = ip_csum_sub_even (*checksum, dport);
355 csum = ip_csum_add_even (csum, udp->dst_port);
356 *checksum = ip_csum_fold (csum);
363 nat64_in2out_tcp_udp_hairpinning (vlib_main_t * vm, vlib_buffer_t * b,
366 nat64_main_t *nm = &nat64_main;
367 nat64_db_bib_entry_t *bibe;
368 nat64_db_st_entry_t *ste;
369 ip46_address_t saddr, daddr;
370 u32 sw_if_index, fib_index;
371 udp_header_t *udp = ip6_next_header (ip6);
372 tcp_header_t *tcp = ip6_next_header (ip6);
373 snat_protocol_t proto = ip_proto_to_snat_proto (ip6->protocol);
374 u16 sport = udp->src_port;
375 u16 dport = udp->dst_port;
379 sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
381 fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6, sw_if_index);
383 saddr.as_u64[0] = ip6->src_address.as_u64[0];
384 saddr.as_u64[1] = ip6->src_address.as_u64[1];
385 daddr.as_u64[0] = ip6->dst_address.as_u64[0];
386 daddr.as_u64[1] = ip6->dst_address.as_u64[1];
388 if (proto == SNAT_PROTOCOL_UDP)
389 checksum = &udp->checksum;
391 checksum = &tcp->checksum;
393 csum = ip_csum_sub_even (*checksum, ip6->src_address.as_u64[0]);
394 csum = ip_csum_sub_even (csum, ip6->src_address.as_u64[1]);
395 csum = ip_csum_sub_even (csum, ip6->dst_address.as_u64[0]);
396 csum = ip_csum_sub_even (csum, ip6->dst_address.as_u64[1]);
397 csum = ip_csum_sub_even (csum, sport);
398 csum = ip_csum_sub_even (csum, dport);
401 nat64_db_st_entry_find (&nm->db, &saddr, &daddr, sport, dport, proto,
406 bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
413 nat64_db_bib_entry_find (&nm->db, &saddr, sport, proto, fib_index, 1);
418 ip4_address_t out_addr;
419 if (nat64_alloc_out_addr_and_port
420 (fib_index, proto, &out_addr, &out_port))
424 nat64_db_bib_entry_create (&nm->db, &ip6->src_address, &out_addr,
425 sport, clib_host_to_net_u16 (out_port),
426 fib_index, proto, 0);
432 nat64_db_st_entry_create (&nm->db, bibe, &ip6->dst_address,
438 nat64_session_reset_timeout (ste, vm);
440 sport = udp->src_port = bibe->out_port;
441 memcpy (&ip6->src_address, well_known_prefix, sizeof (ip6_address_t));
442 saddr.ip6.as_u32[3] = ip6->src_address.as_u32[3] = bibe->out_addr.as_u32;
444 saddr.ip6.as_u32[0] = 0;
445 saddr.ip6.as_u32[1] = 0;
446 saddr.ip6.as_u32[2] = 0;
447 daddr.ip6.as_u32[0] = 0;
448 daddr.ip6.as_u32[1] = 0;
449 daddr.ip6.as_u32[2] = 0;
452 nat64_db_st_entry_find (&nm->db, &daddr, &saddr, dport, sport, proto, 0,
457 bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
463 bibe = nat64_db_bib_entry_find (&nm->db, &daddr, dport, proto, 0, 0);
469 nat64_db_st_entry_create (&nm->db, bibe, &ip6->src_address,
473 ip6->dst_address.as_u64[0] = bibe->in_addr.as_u64[0];
474 ip6->dst_address.as_u64[1] = bibe->in_addr.as_u64[1];
475 udp->dst_port = bibe->in_port;
477 csum = ip_csum_add_even (csum, ip6->src_address.as_u64[0]);
478 csum = ip_csum_add_even (csum, ip6->src_address.as_u64[1]);
479 csum = ip_csum_add_even (csum, ip6->dst_address.as_u64[0]);
480 csum = ip_csum_add_even (csum, ip6->dst_address.as_u64[1]);
481 csum = ip_csum_add_even (csum, udp->src_port);
482 csum = ip_csum_add_even (csum, udp->dst_port);
483 *checksum = ip_csum_fold (csum);
489 nat64_in2out_icmp_hairpinning (vlib_main_t * vm, vlib_buffer_t * b,
492 nat64_main_t *nm = &nat64_main;
493 nat64_db_bib_entry_t *bibe;
494 nat64_db_st_entry_t *ste;
495 icmp46_header_t *icmp = ip6_next_header (ip6);
496 ip6_header_t *inner_ip6;
497 ip46_address_t saddr, daddr;
498 u32 sw_if_index, fib_index;
499 snat_protocol_t proto;
502 u16 *checksum, sport, dport;
505 if (icmp->type == ICMP6_echo_request || icmp->type == ICMP6_echo_reply)
508 inner_ip6 = (ip6_header_t *) u8_ptr_add (icmp, 8);
510 proto = ip_proto_to_snat_proto (inner_ip6->protocol);
512 if (proto == SNAT_PROTOCOL_ICMP)
515 sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
517 fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6, sw_if_index);
519 saddr.as_u64[0] = inner_ip6->src_address.as_u64[0];
520 saddr.as_u64[1] = inner_ip6->src_address.as_u64[1];
521 daddr.as_u64[0] = inner_ip6->dst_address.as_u64[0];
522 daddr.as_u64[1] = inner_ip6->dst_address.as_u64[1];
524 udp = ip6_next_header (inner_ip6);
525 tcp = ip6_next_header (inner_ip6);
527 sport = udp->src_port;
528 dport = udp->dst_port;
530 if (proto == SNAT_PROTOCOL_UDP)
531 checksum = &udp->checksum;
533 checksum = &tcp->checksum;
535 csum = ip_csum_sub_even (*checksum, inner_ip6->src_address.as_u64[0]);
536 csum = ip_csum_sub_even (csum, inner_ip6->src_address.as_u64[1]);
537 csum = ip_csum_sub_even (csum, inner_ip6->dst_address.as_u64[0]);
538 csum = ip_csum_sub_even (csum, inner_ip6->dst_address.as_u64[1]);
539 csum = ip_csum_sub_even (csum, sport);
540 csum = ip_csum_sub_even (csum, dport);
543 nat64_db_st_entry_find (&nm->db, &daddr, &saddr, dport, sport, proto,
549 bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
553 dport = udp->dst_port = bibe->out_port;
554 memcpy (&inner_ip6->dst_address, well_known_prefix, sizeof (ip6_address_t));
555 daddr.ip6.as_u32[3] = inner_ip6->dst_address.as_u32[3] =
556 bibe->out_addr.as_u32;
558 saddr.ip6.as_u32[0] = 0;
559 saddr.ip6.as_u32[1] = 0;
560 saddr.ip6.as_u32[2] = 0;
561 daddr.ip6.as_u32[0] = 0;
562 daddr.ip6.as_u32[1] = 0;
563 daddr.ip6.as_u32[2] = 0;
566 nat64_db_st_entry_find (&nm->db, &saddr, &daddr, sport, dport, proto, 0,
571 bibe = nat64_db_bib_entry_by_index (&nm->db, proto, ste->bibe_index);
575 inner_ip6->src_address.as_u64[0] = bibe->in_addr.as_u64[0];
576 inner_ip6->src_address.as_u64[1] = bibe->in_addr.as_u64[1];
577 udp->src_port = bibe->in_port;
579 csum = ip_csum_add_even (csum, inner_ip6->src_address.as_u64[0]);
580 csum = ip_csum_add_even (csum, inner_ip6->src_address.as_u64[1]);
581 csum = ip_csum_add_even (csum, inner_ip6->dst_address.as_u64[0]);
582 csum = ip_csum_add_even (csum, inner_ip6->dst_address.as_u64[1]);
583 csum = ip_csum_add_even (csum, udp->src_port);
584 csum = ip_csum_add_even (csum, udp->dst_port);
585 *checksum = ip_csum_fold (csum);
587 if (!vec_len (nm->addr_pool))
590 memcpy (&ip6->src_address, well_known_prefix, sizeof (ip6_address_t));
591 ip6->src_address.as_u32[3] = nm->addr_pool[0].addr.as_u32;
592 ip6->dst_address.as_u64[0] = inner_ip6->src_address.as_u64[0];
593 ip6->dst_address.as_u64[1] = inner_ip6->src_address.as_u64[1];
596 csum = ip_csum_with_carry (0, ip6->payload_length);
597 csum = ip_csum_with_carry (csum, clib_host_to_net_u16 (ip6->protocol));
598 csum = ip_csum_with_carry (csum, ip6->src_address.as_u64[0]);
599 csum = ip_csum_with_carry (csum, ip6->src_address.as_u64[1]);
600 csum = ip_csum_with_carry (csum, ip6->dst_address.as_u64[0]);
601 csum = ip_csum_with_carry (csum, ip6->dst_address.as_u64[1]);
603 ip_incremental_checksum (csum, icmp,
604 clib_net_to_host_u16 (ip6->payload_length));
605 icmp->checksum = ~ip_csum_fold (csum);
611 nat64_in2out_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
612 vlib_frame_t * frame)
614 u32 n_left_from, *from, *to_next;
615 nat64_in2out_next_t next_index;
616 u32 pkts_processed = 0;
618 from = vlib_frame_vector_args (frame);
619 n_left_from = frame->n_vectors;
620 next_index = node->cached_next_index;
622 while (n_left_from > 0)
626 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
628 while (n_left_from > 0 && n_left_to_next > 0)
634 u16 l4_offset0, frag_offset0;
637 nat64_in2out_set_ctx_t ctx0;
639 /* speculatively enqueue b0 to the current next frame */
647 b0 = vlib_get_buffer (vm, bi0);
648 ip60 = vlib_buffer_get_current (b0);
653 next0 = NAT64_IN2OUT_NEXT_IP4_LOOKUP;
657 (ip60, b0->current_length, &l4_protocol0, &l4_offset0,
660 next0 = NAT64_IN2OUT_NEXT_DROP;
661 b0->error = node->errors[NAT64_IN2OUT_ERROR_UNKNOWN];
665 proto0 = ip_proto_to_snat_proto (l4_protocol0);
666 if (PREDICT_FALSE ((proto0 == ~0) || (frag_offset0 != 0)))
668 next0 = NAT64_IN2OUT_NEXT_DROP;
670 node->errors[NAT64_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
674 if (proto0 == SNAT_PROTOCOL_ICMP)
676 if (is_hairpinning (&ip60->dst_address))
678 next0 = NAT64_IN2OUT_NEXT_IP6_LOOKUP;
679 if (nat64_in2out_icmp_hairpinning (vm, b0, ip60))
681 next0 = NAT64_IN2OUT_NEXT_DROP;
683 node->errors[NAT64_IN2OUT_ERROR_NO_TRANSLATION];
689 (b0, nat64_in2out_icmp_set_cb, &ctx0,
690 nat64_in2out_inner_icmp_set_cb, &ctx0))
692 next0 = NAT64_IN2OUT_NEXT_DROP;
693 b0->error = node->errors[NAT64_IN2OUT_ERROR_NO_TRANSLATION];
699 if (is_hairpinning (&ip60->dst_address))
701 next0 = NAT64_IN2OUT_NEXT_IP6_LOOKUP;
702 if (nat64_in2out_tcp_udp_hairpinning (vm, b0, ip60))
704 next0 = NAT64_IN2OUT_NEXT_DROP;
706 node->errors[NAT64_IN2OUT_ERROR_NO_TRANSLATION];
711 if (ip6_to_ip4_tcp_udp
712 (b0, nat64_in2out_tcp_udp_set_cb, &ctx0, 0))
714 next0 = NAT64_IN2OUT_NEXT_DROP;
715 b0->error = node->errors[NAT64_IN2OUT_ERROR_NO_TRANSLATION];
721 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
722 && (b0->flags & VLIB_BUFFER_IS_TRACED)))
724 nat64_in2out_trace_t *t =
725 vlib_add_trace (vm, node, b0, sizeof (*t));
726 t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
727 t->next_index = next0;
730 pkts_processed += next0 != NAT64_IN2OUT_NEXT_DROP;
732 /* verify speculative enqueue, maybe switch current next frame */
733 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
734 n_left_to_next, bi0, next0);
736 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
738 vlib_node_increment_counter (vm, nat64_in2out_node.index,
739 NAT64_IN2OUT_ERROR_IN2OUT_PACKETS,
741 return frame->n_vectors;
745 VLIB_REGISTER_NODE (nat64_in2out_node) = {
746 .function = nat64_in2out_node_fn,.name = "nat64-in2out",
747 .vector_size = sizeof (u32),
748 .format_trace = format_nat64_in2out_trace,
749 .type = VLIB_NODE_TYPE_INTERNAL,
750 .n_errors = ARRAY_LEN (nat64_in2out_error_strings),
751 .error_strings = nat64_in2out_error_strings,
753 /* edit / add dispositions here */
755 [NAT64_IN2OUT_NEXT_DROP] = "error-drop",
756 [NAT64_IN2OUT_NEXT_IP4_LOOKUP] = "ip4-lookup",
757 [NAT64_IN2OUT_NEXT_IP6_LOOKUP] = "ip6-lookup",
762 VLIB_NODE_FUNCTION_MULTIARCH (nat64_in2out_node, nat64_in2out_node_fn);
765 * fd.io coding-style-patch-verification: ON
768 * eval: (c-set-style "gnu")