From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from gandalf.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by passt.top (Postfix) with ESMTPS id B802A5A0279 for ; Mon, 19 Feb 2024 03:59:30 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202312; t=1708311565; bh=326QAIZGHLemn/r3jMMAcvQe8Q+CV+o8lNaQ89/51Pc=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=ViuonaVtyCVryF+fUqq/+DMTEUGulYzkE/a1j7bEzcFmFnPr7h5U7DwiJlxwE+UGN UPPR0eP/cck+ZBixgnybtohwvVpk1+7kHdG2Omb0qIwNnPolpU3E2cdLdyUXop1VKx ntq73YqRi+7temwzF/Gcazi0HuwpnO+O2OWbSdQukO6j70VSdvA0Zw+mbBtOWA4uou f+/pkyu5Hmn2LsBwZ4TFrvkZD+4LO2ryvwfUjKGCu3tzTn6RPkMSeOTZknobs98tr1 k8+8VFSwids0UcMy6rbIR0MmoawJIUKHXAWOCGqNFpW05QnZftsGwZkfUAT+48cSXj xwQ9rVS6CUl7g== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4TdS1T2kYYz4wcK; Mon, 19 Feb 2024 13:59:25 +1100 (AEDT) Date: Mon, 19 Feb 2024 13:59:06 +1100 From: David Gibson To: Laurent Vivier Subject: Re: [PATCH v3 5/9] util: move IP stuff from util.[ch] to ip.[ch] Message-ID: References: <20240217150725.661467-1-lvivier@redhat.com> <20240217150725.661467-6-lvivier@redhat.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="o0217O+MkZsDOYHy" Content-Disposition: inline In-Reply-To: <20240217150725.661467-6-lvivier@redhat.com> Message-ID-Hash: IBCAL57YSODNYTDWYQGWRH24MGIPT7DV X-Message-ID-Hash: IBCAL57YSODNYTDWYQGWRH24MGIPT7DV X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: passt-dev@passt.top X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: --o0217O+MkZsDOYHy Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Sat, Feb 17, 2024 at 04:07:21PM +0100, Laurent Vivier wrote: > Introduce ip.[ch] file to encapsulate IP protocol handling functions and > structures. Modify various files to include the new header ip.h when > it's needed. >=20 > Signed-off-by: Laurent Vivier > Reviewed-by: David Gibson > --- >=20 > Notes: > v3: > - rewrap rational Tangential English usage note. "rationale" is different from "rational", though they're related. "Rationale" is the noun - "an explanation of the reason for the thing", "rational" is an adjective - "sensible, logical, having a rationale". (Except of course that in maths "rational" is also a noun - "a number expressible as a ratio"). > - add David's R-b > =20 > v2: > - update rational and comments >=20 > Makefile | 8 ++--- > conf.c | 1 + > dhcp.c | 1 + > flow.c | 1 + > icmp.c | 1 + > ip.c | 72 +++++++++++++++++++++++++++++++++++++++++++ > ip.h | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++ > ndp.c | 1 + > port_fwd.c | 1 + > qrap.c | 1 + > tap.c | 1 + > tcp.c | 1 + > tcp_splice.c | 1 + > udp.c | 1 + > util.c | 55 --------------------------------- > util.h | 76 ---------------------------------------------- > 16 files changed, 173 insertions(+), 135 deletions(-) > create mode 100644 ip.c > create mode 100644 ip.h >=20 > diff --git a/Makefile b/Makefile > index 156398b3844e..e1ebb454bc6b 100644 > --- a/Makefile > +++ b/Makefile > @@ -45,7 +45,7 @@ FLAGS +=3D -DVERSION=3D\"$(VERSION)\" > FLAGS +=3D -DDUAL_STACK_SOCKETS=3D$(DUAL_STACK_SOCKETS) > =20 > PASST_SRCS =3D arch.c arp.c checksum.c conf.c dhcp.c dhcpv6.c flow.c icm= p.c \ > - igmp.c iov.c isolation.c lineread.c log.c mld.c ndp.c netlink.c \ > + igmp.c iov.c ip.c isolation.c lineread.c log.c mld.c ndp.c netlink.c \ > packet.c passt.c pasta.c pcap.c pif.c port_fwd.c tap.c tcp.c \ > tcp_splice.c udp.c util.c > QRAP_SRCS =3D qrap.c > @@ -54,9 +54,9 @@ SRCS =3D $(PASST_SRCS) $(QRAP_SRCS) > MANPAGES =3D passt.1 pasta.1 qrap.1 > =20 > PASST_HEADERS =3D arch.h arp.h checksum.h conf.h dhcp.h dhcpv6.h flow.h \ > - flow_table.h icmp.h inany.h iov.h isolation.h lineread.h log.h ndp.h \ > - netlink.h packet.h passt.h pasta.h pcap.h pif.h port_fwd.h siphash.h \ > - tap.h tcp.h tcp_conn.h tcp_splice.h udp.h util.h > + flow_table.h icmp.h inany.h iov.h ip.h isolation.h lineread.h log.h \ > + ndp.h netlink.h packet.h passt.h pasta.h pcap.h pif.h port_fwd.h \ > + siphash.h tap.h tcp.h tcp_conn.h tcp_splice.h udp.h util.h > HEADERS =3D $(PASST_HEADERS) seccomp.h > =20 > C :=3D \#include \nstruct tcp_info x =3D { .tcpi_snd_wnd = =3D 0 }; > diff --git a/conf.c b/conf.c > index 5e15b665be9c..93bfda331349 100644 > --- a/conf.c > +++ b/conf.c > @@ -35,6 +35,7 @@ > #include > =20 > #include "util.h" > +#include "ip.h" > #include "passt.h" > #include "netlink.h" > #include "udp.h" > diff --git a/dhcp.c b/dhcp.c > index 110772867632..ff4834a3dce9 100644 > --- a/dhcp.c > +++ b/dhcp.c > @@ -25,6 +25,7 @@ > #include > =20 > #include "util.h" > +#include "ip.h" > #include "checksum.h" > #include "packet.h" > #include "passt.h" > diff --git a/flow.c b/flow.c > index 5e94a7a949e5..73d52bda8774 100644 > --- a/flow.c > +++ b/flow.c > @@ -11,6 +11,7 @@ > #include > =20 > #include "util.h" > +#include "ip.h" > #include "passt.h" > #include "siphash.h" > #include "inany.h" > diff --git a/icmp.c b/icmp.c > index 9434fc5a7490..3b85a8578316 100644 > --- a/icmp.c > +++ b/icmp.c > @@ -33,6 +33,7 @@ > =20 > #include "packet.h" > #include "util.h" > +#include "ip.h" > #include "passt.h" > #include "tap.h" > #include "log.h" > diff --git a/ip.c b/ip.c > new file mode 100644 > index 000000000000..2cc7f6548aff > --- /dev/null > +++ b/ip.c > @@ -0,0 +1,72 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > + > +/* PASST - Plug A Simple Socket Transport > + * for qemu/UNIX domain socket mode > + * > + * PASTA - Pack A Subtle Tap Abstraction > + * for network namespace/tap device mode > + * > + * ip.c - IP related functions > + * > + * Copyright (c) 2020-2021 Red Hat GmbH > + * Author: Stefano Brivio > + */ > + > +#include > +#include "util.h" > +#include "ip.h" > + > +#define IPV6_NH_OPT(nh) \ > + ((nh) =3D=3D 0 || (nh) =3D=3D 43 || (nh) =3D=3D 44 || (nh) =3D=3D 5= 0 || \ > + (nh) =3D=3D 51 || (nh) =3D=3D 60 || (nh) =3D=3D 135 || (nh) =3D=3D 1= 39 || \ > + (nh) =3D=3D 140 || (nh) =3D=3D 253 || (nh) =3D=3D 254) > + > +/** > + * ipv6_l4hdr() - Find pointer to L4 header in IPv6 packet and extract p= rotocol > + * @p: Packet pool, packet number @idx has IPv6 header at @offset > + * @idx: Index of packet in pool > + * @offset: Pre-calculated IPv6 header offset > + * @proto: Filled with L4 protocol number > + * @dlen: Data length (payload excluding header extensions), set on retu= rn > + * > + * Return: pointer to L4 header, NULL if not found > + */ > +char *ipv6_l4hdr(const struct pool *p, int idx, size_t offset, uint8_t *= proto, > + size_t *dlen) > +{ > + const struct ipv6_opt_hdr *o; > + const struct ipv6hdr *ip6h; > + char *base; > + int hdrlen; > + uint8_t nh; > + > + base =3D packet_get(p, idx, 0, 0, NULL); > + ip6h =3D packet_get(p, idx, offset, sizeof(*ip6h), dlen); > + if (!ip6h) > + return NULL; > + > + offset +=3D sizeof(*ip6h); > + > + nh =3D ip6h->nexthdr; > + if (!IPV6_NH_OPT(nh)) > + goto found; > + > + while ((o =3D packet_get_try(p, idx, offset, sizeof(*o), dlen))) { > + nh =3D o->nexthdr; > + hdrlen =3D (o->hdrlen + 1) * 8; > + > + if (IPV6_NH_OPT(nh)) > + offset +=3D hdrlen; > + else > + goto found; > + } > + > + return NULL; > + > +found: > + if (nh =3D=3D 59) > + return NULL; > + > + *proto =3D nh; > + return base + offset; > +} > diff --git a/ip.h b/ip.h > new file mode 100644 > index 000000000000..b2e08bc049f3 > --- /dev/null > +++ b/ip.h > @@ -0,0 +1,86 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later > + * Copyright (c) 2021 Red Hat GmbH > + * Author: Stefano Brivio > + */ > + > +#ifndef IP_H > +#define IP_H > + > +#include > +#include > + > +#define IN4_IS_ADDR_UNSPECIFIED(a) \ > + ((a)->s_addr =3D=3D htonl_constant(INADDR_ANY)) > +#define IN4_IS_ADDR_BROADCAST(a) \ > + ((a)->s_addr =3D=3D htonl_constant(INADDR_BROADCAST)) > +#define IN4_IS_ADDR_LOOPBACK(a) \ > + (ntohl((a)->s_addr) >> IN_CLASSA_NSHIFT =3D=3D IN_LOOPBACKNET) > +#define IN4_IS_ADDR_MULTICAST(a) \ > + (IN_MULTICAST(ntohl((a)->s_addr))) > +#define IN4_ARE_ADDR_EQUAL(a, b) \ > + (((struct in_addr *)(a))->s_addr =3D=3D ((struct in_addr *)b)->s_addr) > +#define IN4ADDR_LOOPBACK_INIT \ > + { .s_addr =3D htonl_constant(INADDR_LOOPBACK) } > +#define IN4ADDR_ANY_INIT \ > + { .s_addr =3D htonl_constant(INADDR_ANY) } > + > +#define L2_BUF_IP4_INIT(proto) \ > + { \ > + .version =3D 4, \ > + .ihl =3D 5, \ > + .tos =3D 0, \ > + .tot_len =3D 0, \ > + .id =3D 0, \ > + .frag_off =3D 0, \ > + .ttl =3D 0xff, \ > + .protocol =3D (proto), \ > + .saddr =3D 0, \ > + .daddr =3D 0, \ > + } > +#define L2_BUF_IP4_PSUM(proto) ((uint32_t)htons_constant(0x4500) + \ > + (uint32_t)htons_constant(0xff00 | (proto))) > + > +#define L2_BUF_IP6_INIT(proto) \ > + { \ > + .priority =3D 0, \ > + .version =3D 6, \ > + .flow_lbl =3D { 0 }, \ > + .payload_len =3D 0, \ > + .nexthdr =3D (proto), \ > + .hop_limit =3D 255, \ > + .saddr =3D IN6ADDR_ANY_INIT, \ > + .daddr =3D IN6ADDR_ANY_INIT, \ > + } > + > +struct ipv6hdr { > +#pragma GCC diagnostic push > +#pragma GCC diagnostic ignored "-Wpedantic" > +#if __BYTE_ORDER =3D=3D __BIG_ENDIAN > + uint8_t version:4, > + priority:4; > +#else > + uint8_t priority:4, > + version:4; > +#endif > +#pragma GCC diagnostic pop > + uint8_t flow_lbl[3]; > + > + uint16_t payload_len; > + uint8_t nexthdr; > + uint8_t hop_limit; > + > + struct in6_addr saddr; > + struct in6_addr daddr; > +}; > + > +struct ipv6_opt_hdr { > + uint8_t nexthdr; > + uint8_t hdrlen; > + /* > + * TLV encoded option data follows. > + */ > +} __attribute__((packed)); /* required for some archs */ > + > +char *ipv6_l4hdr(const struct pool *p, int idx, size_t offset, uint8_t *= proto, > + size_t *dlen); > +#endif /* IP_H */ > diff --git a/ndp.c b/ndp.c > index 4c85ab8bcaee..c58f4b222b76 100644 > --- a/ndp.c > +++ b/ndp.c > @@ -28,6 +28,7 @@ > =20 > #include "checksum.h" > #include "util.h" > +#include "ip.h" > #include "passt.h" > #include "tap.h" > #include "log.h" > diff --git a/port_fwd.c b/port_fwd.c > index 6f6c836c57ad..e1ec31e2232c 100644 > --- a/port_fwd.c > +++ b/port_fwd.c > @@ -21,6 +21,7 @@ > #include > =20 > #include "util.h" > +#include "ip.h" > #include "port_fwd.h" > #include "passt.h" > #include "lineread.h" > diff --git a/qrap.c b/qrap.c > index 97f350a4bf0b..d59670621731 100644 > --- a/qrap.c > +++ b/qrap.c > @@ -32,6 +32,7 @@ > #include > =20 > #include "util.h" > +#include "ip.h" > #include "passt.h" > #include "arp.h" > =20 > diff --git a/tap.c b/tap.c > index 396dee7eef25..3ea03f720d6d 100644 > --- a/tap.c > +++ b/tap.c > @@ -45,6 +45,7 @@ > =20 > #include "checksum.h" > #include "util.h" > +#include "ip.h" > #include "passt.h" > #include "arp.h" > #include "dhcp.h" > diff --git a/tcp.c b/tcp.c > index 2ab443d5c3f2..45ef5146729a 100644 > --- a/tcp.c > +++ b/tcp.c > @@ -289,6 +289,7 @@ > =20 > #include "checksum.h" > #include "util.h" > +#include "ip.h" > #include "passt.h" > #include "tap.h" > #include "siphash.h" > diff --git a/tcp_splice.c b/tcp_splice.c > index 26d32065cd47..66575ca95a1e 100644 > --- a/tcp_splice.c > +++ b/tcp_splice.c > @@ -49,6 +49,7 @@ > #include > =20 > #include "util.h" > +#include "ip.h" > #include "passt.h" > #include "log.h" > #include "tcp_splice.h" > diff --git a/udp.c b/udp.c > index 933f24b81616..56b58bd8b43a 100644 > --- a/udp.c > +++ b/udp.c > @@ -112,6 +112,7 @@ > =20 > #include "checksum.h" > #include "util.h" > +#include "ip.h" > #include "passt.h" > #include "tap.h" > #include "pcap.h" > diff --git a/util.c b/util.c > index 21b35ff94db1..f73ea1d98a09 100644 > --- a/util.c > +++ b/util.c > @@ -30,61 +30,6 @@ > #include "packet.h" > #include "log.h" > =20 > -#define IPV6_NH_OPT(nh) \ > - ((nh) =3D=3D 0 || (nh) =3D=3D 43 || (nh) =3D=3D 44 || (nh) =3D=3D 5= 0 || \ > - (nh) =3D=3D 51 || (nh) =3D=3D 60 || (nh) =3D=3D 135 || (nh) =3D=3D 1= 39 || \ > - (nh) =3D=3D 140 || (nh) =3D=3D 253 || (nh) =3D=3D 254) > - > -/** > - * ipv6_l4hdr() - Find pointer to L4 header in IPv6 packet and extract p= rotocol > - * @p: Packet pool, packet number @idx has IPv6 header at @offset > - * @idx: Index of packet in pool > - * @offset: Pre-calculated IPv6 header offset > - * @proto: Filled with L4 protocol number > - * @dlen: Data length (payload excluding header extensions), set on retu= rn > - * > - * Return: pointer to L4 header, NULL if not found > - */ > -char *ipv6_l4hdr(const struct pool *p, int idx, size_t offset, uint8_t *= proto, > - size_t *dlen) > -{ > - const struct ipv6_opt_hdr *o; > - const struct ipv6hdr *ip6h; > - char *base; > - int hdrlen; > - uint8_t nh; > - > - base =3D packet_get(p, idx, 0, 0, NULL); > - ip6h =3D packet_get(p, idx, offset, sizeof(*ip6h), dlen); > - if (!ip6h) > - return NULL; > - > - offset +=3D sizeof(*ip6h); > - > - nh =3D ip6h->nexthdr; > - if (!IPV6_NH_OPT(nh)) > - goto found; > - > - while ((o =3D packet_get_try(p, idx, offset, sizeof(*o), dlen))) { > - nh =3D o->nexthdr; > - hdrlen =3D (o->hdrlen + 1) * 8; > - > - if (IPV6_NH_OPT(nh)) > - offset +=3D hdrlen; > - else > - goto found; > - } > - > - return NULL; > - > -found: > - if (nh =3D=3D 59) > - return NULL; > - > - *proto =3D nh; > - return base + offset; > -} > - > /** > * sock_l4() - Create and bind socket for given L4, add to epoll list > * @c: Execution context > diff --git a/util.h b/util.h > index d2320f8cc99a..f7c3dfee9972 100644 > --- a/util.h > +++ b/util.h > @@ -110,22 +110,6 @@ > #define htonl_constant(x) (__bswap_constant_32(x)) > #endif > =20 > -#define IN4_IS_ADDR_UNSPECIFIED(a) \ > - ((a)->s_addr =3D=3D htonl_constant(INADDR_ANY)) > -#define IN4_IS_ADDR_BROADCAST(a) \ > - ((a)->s_addr =3D=3D htonl_constant(INADDR_BROADCAST)) > -#define IN4_IS_ADDR_LOOPBACK(a) \ > - (ntohl((a)->s_addr) >> IN_CLASSA_NSHIFT =3D=3D IN_LOOPBACKNET) > -#define IN4_IS_ADDR_MULTICAST(a) \ > - (IN_MULTICAST(ntohl((a)->s_addr))) > -#define IN4_ARE_ADDR_EQUAL(a, b) \ > - (((struct in_addr *)(a))->s_addr =3D=3D ((struct in_addr *)b)->s_addr) > -#define IN4ADDR_LOOPBACK_INIT \ > - { .s_addr =3D htonl_constant(INADDR_LOOPBACK) } > -#define IN4ADDR_ANY_INIT \ > - { .s_addr =3D htonl_constant(INADDR_ANY) } > - > - > #define NS_FN_STACK_SIZE (RLIMIT_STACK_VAL * 1024 / 8) > int do_clone(int (*fn)(void *), char *stack_area, size_t stack_size, int= flags, > void *arg); > @@ -138,34 +122,6 @@ int do_clone(int (*fn)(void *), char *stack_area, si= ze_t stack_size, int flags, > (void *)(arg)); \ > } while (0) > =20 > -#define L2_BUF_IP4_INIT(proto) \ > - { \ > - .version =3D 4, \ > - .ihl =3D 5, \ > - .tos =3D 0, \ > - .tot_len =3D 0, \ > - .id =3D 0, \ > - .frag_off =3D 0, \ > - .ttl =3D 0xff, \ > - .protocol =3D (proto), \ > - .saddr =3D 0, \ > - .daddr =3D 0, \ > - } > -#define L2_BUF_IP4_PSUM(proto) ((uint32_t)htons_constant(0x4500) + \ > - (uint32_t)htons_constant(0xff00 | (proto))) > - > -#define L2_BUF_IP6_INIT(proto) \ > - { \ > - .priority =3D 0, \ > - .version =3D 6, \ > - .flow_lbl =3D { 0 }, \ > - .payload_len =3D 0, \ > - .nexthdr =3D (proto), \ > - .hop_limit =3D 255, \ > - .saddr =3D IN6ADDR_ANY_INIT, \ > - .daddr =3D IN6ADDR_ANY_INIT, \ > - } > - > #define RCVBUF_BIG (2UL * 1024 * 1024) > #define SNDBUF_BIG (4UL * 1024 * 1024) > #define SNDBUF_SMALL (128UL * 1024) > @@ -173,45 +129,13 @@ int do_clone(int (*fn)(void *), char *stack_area, s= ize_t stack_size, int flags, > #include > #include > #include > -#include > =20 > #include "packet.h" > =20 > struct ctx; > =20 > -struct ipv6hdr { > -#pragma GCC diagnostic push > -#pragma GCC diagnostic ignored "-Wpedantic" > -#if __BYTE_ORDER =3D=3D __BIG_ENDIAN > - uint8_t version:4, > - priority:4; > -#else > - uint8_t priority:4, > - version:4; > -#endif > -#pragma GCC diagnostic pop > - uint8_t flow_lbl[3]; > - > - uint16_t payload_len; > - uint8_t nexthdr; > - uint8_t hop_limit; > - > - struct in6_addr saddr; > - struct in6_addr daddr; > -}; > - > -struct ipv6_opt_hdr { > - uint8_t nexthdr; > - uint8_t hdrlen; > - /* > - * TLV encoded option data follows. > - */ > -} __attribute__((packed)); /* required for some archs */ > - > /* cppcheck-suppress funcArgNamesDifferent */ > __attribute__ ((weak)) int ffsl(long int i) { return __builtin_ffsl(i); } > -char *ipv6_l4hdr(const struct pool *p, int idx, size_t offset, uint8_t *= proto, > - size_t *dlen); > int sock_l4(const struct ctx *c, int af, uint8_t proto, > const void *bind_addr, const char *ifname, uint16_t port, > uint32_t data); --=20 David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson --o0217O+MkZsDOYHy Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAEBCAAdFiEEO+dNsU4E3yXUXRK2zQJF27ox2GcFAmXSw/kACgkQzQJF27ox 2GdbYRAAleOVIlrF6q2lTai3A4bytstoNnL+HkTjOXZbF80NwFY3gej3aIUJmGBj jWV8Z4OiIx98vXBgsbk5F6YlXIlRVemW9kW3YpqVFl1SFxw/aEqa/K4FY6C6yjnP +/a7WLjQzWhW1x/0i1alYt/w5ZDX6kREcQmCRWdx2qBDJ2sS7OMgBng5n46QAicm KXaAXl0gkkJB5oli/AtJXpAgS03o/myrXVjFEmVx21ctDCGukk5PywXaiu0i9gft 5dsrNj08962TqqkTKywsGd70lCzK6ukMTyDFnzHtjTLPCkUdikfd66d58cYkJq6O f82kcWX788g/pjbWb8JSNPgPVMp4gEErkpgeeanv51Tq6Z+y2u8mXCr0vUb2Tk2a +QmzH8EDtHH/WRPHuIzvMzhU5JZMKqukbM+hU+Xiw/VZdfkrCK/mNtR+9iUgw6ID s48WVPwK0fSr8K4MuEnEoSjfeX+uUpdeqFaCu1LOQzdAloKdHV+X4NCfg2/XgLYw gvrFGQFWvflnDo4uKDfU58ND2rZgUpkS059wGEmmR23Wc/eBabcRabXJg0ZnM5R+ qG42BjBstbOiHXP1txFCD/4GIt6ZrC1lXNOhO1IEo4Q9MiKMXF1DilxJE55sfLZY a431yUQ7XCQFLY4v86XXmqfYdJzyNDlURApgPU/p1iQ8gES73IA= =mszh -----END PGP SIGNATURE----- --o0217O+MkZsDOYHy--