xref: /aosp_15_r20/kernel/tests/net/test/xfrm.py (revision 2f2c4c7ab4226c71756b9c31670392fdd6887c4f)
1*2f2c4c7aSAndroid Build Coastguard Worker#!/usr/bin/python3
2*2f2c4c7aSAndroid Build Coastguard Worker#
3*2f2c4c7aSAndroid Build Coastguard Worker# Copyright 2016 The Android Open Source Project
4*2f2c4c7aSAndroid Build Coastguard Worker#
5*2f2c4c7aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*2f2c4c7aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*2f2c4c7aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*2f2c4c7aSAndroid Build Coastguard Worker#
9*2f2c4c7aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0
10*2f2c4c7aSAndroid Build Coastguard Worker#
11*2f2c4c7aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*2f2c4c7aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*2f2c4c7aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*2f2c4c7aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*2f2c4c7aSAndroid Build Coastguard Worker# limitations under the License.
16*2f2c4c7aSAndroid Build Coastguard Worker
17*2f2c4c7aSAndroid Build Coastguard Worker"""Partial implementation of xfrm netlink code and socket options."""
18*2f2c4c7aSAndroid Build Coastguard Worker
19*2f2c4c7aSAndroid Build Coastguard Worker# pylint: disable=g-bad-todo
20*2f2c4c7aSAndroid Build Coastguard Worker
21*2f2c4c7aSAndroid Build Coastguard Workerimport os
22*2f2c4c7aSAndroid Build Coastguard Workerfrom socket import *  # pylint: disable=wildcard-import
23*2f2c4c7aSAndroid Build Coastguard Workerimport struct
24*2f2c4c7aSAndroid Build Coastguard Worker
25*2f2c4c7aSAndroid Build Coastguard Workerimport net_test
26*2f2c4c7aSAndroid Build Coastguard Workerimport csocket
27*2f2c4c7aSAndroid Build Coastguard Workerimport cstruct
28*2f2c4c7aSAndroid Build Coastguard Workerimport netlink
29*2f2c4c7aSAndroid Build Coastguard Worker
30*2f2c4c7aSAndroid Build Coastguard Worker
31*2f2c4c7aSAndroid Build Coastguard Worker# Netlink constants. See include/uapi/linux/xfrm.h.
32*2f2c4c7aSAndroid Build Coastguard Worker# Message types.
33*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_NEWSA = 16
34*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_DELSA = 17
35*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_GETSA = 18
36*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_NEWPOLICY = 19
37*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_DELPOLICY = 20
38*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_GETPOLICY = 21
39*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_ALLOCSPI = 22
40*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_ACQUIRE = 23
41*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_EXPIRE = 24
42*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_UPDPOLICY = 25
43*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_UPDSA = 26
44*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_POLEXPIRE = 27
45*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_FLUSHSA = 28
46*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_FLUSHPOLICY = 29
47*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_NEWAE = 30
48*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_GETAE = 31
49*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_REPORT = 32
50*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_MIGRATE = 33
51*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_NEWSADINFO = 34
52*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_GETSADINFO = 35
53*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_NEWSPDINFO = 36
54*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_GETSPDINFO = 37
55*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MSG_MAPPING = 38
56*2f2c4c7aSAndroid Build Coastguard Worker
57*2f2c4c7aSAndroid Build Coastguard Worker# Attributes.
58*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_UNSPEC = 0
59*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_ALG_AUTH = 1
60*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_ALG_CRYPT = 2
61*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_ALG_COMP = 3
62*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_ENCAP = 4
63*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_TMPL = 5
64*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_SA = 6
65*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_POLICY = 7
66*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_SEC_CTX = 8
67*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_LTIME_VAL = 9
68*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_REPLAY_VAL = 10
69*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_REPLAY_THRESH = 11
70*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_ETIMER_THRESH = 12
71*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_SRCADDR = 13
72*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_COADDR = 14
73*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_LASTUSED = 15
74*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_POLICY_TYPE = 16
75*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_MIGRATE = 17
76*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_ALG_AEAD = 18
77*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_KMADDRESS = 19
78*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_ALG_AUTH_TRUNC = 20
79*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_MARK = 21
80*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_TFCPAD = 22
81*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_REPLAY_ESN_VAL = 23
82*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_SA_EXTRA_FLAGS = 24
83*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_PROTO = 25
84*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_ADDRESS_FILTER = 26
85*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_PAD = 27
86*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_OFFLOAD_DEV = 28
87*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_OUTPUT_MARK = 29
88*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_INPUT_MARK = 30
89*2f2c4c7aSAndroid Build Coastguard WorkerXFRMA_IF_ID = 31
90*2f2c4c7aSAndroid Build Coastguard Worker
91*2f2c4c7aSAndroid Build Coastguard Worker# Other netlink constants. See include/uapi/linux/xfrm.h.
92*2f2c4c7aSAndroid Build Coastguard Worker
93*2f2c4c7aSAndroid Build Coastguard Worker# Directions.
94*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_POLICY_IN = 0
95*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_POLICY_OUT = 1
96*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_POLICY_FWD = 2
97*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_POLICY_MASK = 3
98*2f2c4c7aSAndroid Build Coastguard Worker
99*2f2c4c7aSAndroid Build Coastguard Worker# Policy sharing.
100*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_SHARE_ANY     = 0  #  /* No limitations */
101*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_SHARE_SESSION = 1  #  /* For this session only */
102*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_SHARE_USER    = 2  #  /* For this user only */
103*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_SHARE_UNIQUE  = 3  #  /* Use once */
104*2f2c4c7aSAndroid Build Coastguard Worker
105*2f2c4c7aSAndroid Build Coastguard Worker# Modes.
106*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MODE_TRANSPORT = 0
107*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MODE_TUNNEL = 1
108*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MODE_ROUTEOPTIMIZATION = 2
109*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MODE_IN_TRIGGER = 3
110*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MODE_BEET = 4
111*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_MODE_MAX = 5
112*2f2c4c7aSAndroid Build Coastguard Worker
113*2f2c4c7aSAndroid Build Coastguard Worker# Actions.
114*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_POLICY_ALLOW = 0
115*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_POLICY_BLOCK = 1
116*2f2c4c7aSAndroid Build Coastguard Worker
117*2f2c4c7aSAndroid Build Coastguard Worker# Policy flags.
118*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_POLICY_LOCALOK = 1
119*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_POLICY_ICMP = 2
120*2f2c4c7aSAndroid Build Coastguard Worker
121*2f2c4c7aSAndroid Build Coastguard Worker# State flags.
122*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_STATE_AF_UNSPEC = 32
123*2f2c4c7aSAndroid Build Coastguard Worker
124*2f2c4c7aSAndroid Build Coastguard Worker# XFRM algorithm names, as defined in net/xfrm/xfrm_algo.c.
125*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_EALG_CBC_AES = b"cbc(aes)"
126*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_EALG_CTR_AES = b"rfc3686(ctr(aes))"
127*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_AALG_HMAC_MD5 = b"hmac(md5)"
128*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_AALG_HMAC_SHA1 = b"hmac(sha1)"
129*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_AALG_HMAC_SHA256 = b"hmac(sha256)"
130*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_AALG_HMAC_SHA384 = b"hmac(sha384)"
131*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_AALG_HMAC_SHA512 = b"hmac(sha512)"
132*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_AALG_AUTH_XCBC_AES = b"xcbc(aes)"
133*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_AEAD_GCM_AES = b"rfc4106(gcm(aes))"
134*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_AEAD_CHACHA20_POLY1305 = b"rfc7539esp(chacha20,poly1305)"
135*2f2c4c7aSAndroid Build Coastguard Worker
136*2f2c4c7aSAndroid Build Coastguard Worker# Data structure formats.
137*2f2c4c7aSAndroid Build Coastguard Worker# These aren't constants, they're classes. So, pylint: disable=invalid-name
138*2f2c4c7aSAndroid Build Coastguard WorkerXfrmSelector = cstruct.Struct(
139*2f2c4c7aSAndroid Build Coastguard Worker    "XfrmSelector", "=16s16sHHHHHBBBxxxiI",
140*2f2c4c7aSAndroid Build Coastguard Worker    "daddr saddr dport dport_mask sport sport_mask "
141*2f2c4c7aSAndroid Build Coastguard Worker    "family prefixlen_d prefixlen_s proto ifindex user")
142*2f2c4c7aSAndroid Build Coastguard Worker
143*2f2c4c7aSAndroid Build Coastguard WorkerXfrmMigrate = cstruct.Struct(
144*2f2c4c7aSAndroid Build Coastguard Worker    "XfrmMigrate", "=16s16s16s16sBBxxIHH",
145*2f2c4c7aSAndroid Build Coastguard Worker    "old_daddr old_saddr new_daddr new_saddr proto "
146*2f2c4c7aSAndroid Build Coastguard Worker    "mode reqid old_family new_family")
147*2f2c4c7aSAndroid Build Coastguard Worker
148*2f2c4c7aSAndroid Build Coastguard WorkerXfrmLifetimeCfg = cstruct.Struct(
149*2f2c4c7aSAndroid Build Coastguard Worker    "XfrmLifetimeCfg", "=QQQQQQQQ",
150*2f2c4c7aSAndroid Build Coastguard Worker    "soft_byte hard_byte soft_packet hard_packet "
151*2f2c4c7aSAndroid Build Coastguard Worker    "soft_add_expires hard_add_expires soft_use_expires hard_use_expires")
152*2f2c4c7aSAndroid Build Coastguard Worker
153*2f2c4c7aSAndroid Build Coastguard WorkerXfrmLifetimeCur = cstruct.Struct(
154*2f2c4c7aSAndroid Build Coastguard Worker    "XfrmLifetimeCur", "=QQQQ", "bytes packets add_time use_time")
155*2f2c4c7aSAndroid Build Coastguard Worker
156*2f2c4c7aSAndroid Build Coastguard WorkerXfrmAlgo = cstruct.Struct("XfrmAlgo", "=64AI", "name key_len")
157*2f2c4c7aSAndroid Build Coastguard Worker
158*2f2c4c7aSAndroid Build Coastguard WorkerXfrmAlgoAuth = cstruct.Struct("XfrmAlgoAuth", "=64AII",
159*2f2c4c7aSAndroid Build Coastguard Worker                              "name key_len trunc_len")
160*2f2c4c7aSAndroid Build Coastguard Worker
161*2f2c4c7aSAndroid Build Coastguard WorkerXfrmAlgoAead = cstruct.Struct("XfrmAlgoAead", "=64AII", "name key_len icv_len")
162*2f2c4c7aSAndroid Build Coastguard Worker
163*2f2c4c7aSAndroid Build Coastguard WorkerXfrmStats = cstruct.Struct(
164*2f2c4c7aSAndroid Build Coastguard Worker    "XfrmStats", "=III", "replay_window replay integrity_failed")
165*2f2c4c7aSAndroid Build Coastguard Worker
166*2f2c4c7aSAndroid Build Coastguard WorkerXfrmId = cstruct.Struct("XfrmId", "!16sIBxxx", "daddr spi proto")
167*2f2c4c7aSAndroid Build Coastguard Worker
168*2f2c4c7aSAndroid Build Coastguard WorkerXfrmUserTmpl = cstruct.Struct(
169*2f2c4c7aSAndroid Build Coastguard Worker    "XfrmUserTmpl", "=SHxx16sIBBBxIII",
170*2f2c4c7aSAndroid Build Coastguard Worker    "id family saddr reqid mode share optional aalgos ealgos calgos",
171*2f2c4c7aSAndroid Build Coastguard Worker    [XfrmId])
172*2f2c4c7aSAndroid Build Coastguard Worker
173*2f2c4c7aSAndroid Build Coastguard WorkerXfrmEncapTmpl = cstruct.Struct(
174*2f2c4c7aSAndroid Build Coastguard Worker    "XfrmEncapTmpl", "=HHHxx16s", "type sport dport oa")
175*2f2c4c7aSAndroid Build Coastguard Worker
176*2f2c4c7aSAndroid Build Coastguard WorkerXfrmUsersaInfo = cstruct.Struct(
177*2f2c4c7aSAndroid Build Coastguard Worker    "XfrmUsersaInfo", "=SS16sSSSIIHBBB7x",
178*2f2c4c7aSAndroid Build Coastguard Worker    "sel id saddr lft curlft stats seq reqid family mode replay_window flags",
179*2f2c4c7aSAndroid Build Coastguard Worker    [XfrmSelector, XfrmId, XfrmLifetimeCfg, XfrmLifetimeCur, XfrmStats])
180*2f2c4c7aSAndroid Build Coastguard Worker
181*2f2c4c7aSAndroid Build Coastguard WorkerXfrmUserSpiInfo = cstruct.Struct(
182*2f2c4c7aSAndroid Build Coastguard Worker    "XfrmUserSpiInfo", "=SII", "info min max", [XfrmUsersaInfo])
183*2f2c4c7aSAndroid Build Coastguard Worker
184*2f2c4c7aSAndroid Build Coastguard Worker# Technically the family is a 16-bit field, but only a few families are in use,
185*2f2c4c7aSAndroid Build Coastguard Worker# and if we pretend it's 8 bits (i.e., use "Bx" instead of "H") we can think
186*2f2c4c7aSAndroid Build Coastguard Worker# of the whole structure as being in network byte order.
187*2f2c4c7aSAndroid Build Coastguard WorkerXfrmUsersaId = cstruct.Struct(
188*2f2c4c7aSAndroid Build Coastguard Worker    "XfrmUsersaId", "!16sIBxBx", "daddr spi family proto")
189*2f2c4c7aSAndroid Build Coastguard Worker
190*2f2c4c7aSAndroid Build Coastguard Worker# xfrm.h - struct xfrm_userpolicy_info
191*2f2c4c7aSAndroid Build Coastguard WorkerXfrmUserpolicyInfo = cstruct.Struct(
192*2f2c4c7aSAndroid Build Coastguard Worker    "XfrmUserpolicyInfo", "=SSSIIBBBBxxxx",
193*2f2c4c7aSAndroid Build Coastguard Worker    "sel lft curlft priority index dir action flags share",
194*2f2c4c7aSAndroid Build Coastguard Worker    [XfrmSelector, XfrmLifetimeCfg, XfrmLifetimeCur])
195*2f2c4c7aSAndroid Build Coastguard Worker
196*2f2c4c7aSAndroid Build Coastguard WorkerXfrmUserpolicyId = cstruct.Struct(
197*2f2c4c7aSAndroid Build Coastguard Worker        "XfrmUserpolicyId", "=SIBxxx", "sel index dir", [XfrmSelector])
198*2f2c4c7aSAndroid Build Coastguard Worker
199*2f2c4c7aSAndroid Build Coastguard WorkerXfrmUsersaFlush = cstruct.Struct("XfrmUsersaFlush", "=B", "proto")
200*2f2c4c7aSAndroid Build Coastguard Worker
201*2f2c4c7aSAndroid Build Coastguard WorkerXfrmMark = cstruct.Struct("XfrmMark", "=II", "mark mask")
202*2f2c4c7aSAndroid Build Coastguard Worker
203*2f2c4c7aSAndroid Build Coastguard Worker# Socket options. See include/uapi/linux/in.h.
204*2f2c4c7aSAndroid Build Coastguard WorkerIP_IPSEC_POLICY = 16
205*2f2c4c7aSAndroid Build Coastguard WorkerIP_XFRM_POLICY = 17
206*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_IPSEC_POLICY = 34
207*2f2c4c7aSAndroid Build Coastguard WorkerIPV6_XFRM_POLICY = 35
208*2f2c4c7aSAndroid Build Coastguard Worker
209*2f2c4c7aSAndroid Build Coastguard Worker# UDP encapsulation constants. See include/uapi/linux/udp.h.
210*2f2c4c7aSAndroid Build Coastguard WorkerUDP_ENCAP = 100
211*2f2c4c7aSAndroid Build Coastguard WorkerUDP_ENCAP_ESPINUDP_NON_IKE = 1
212*2f2c4c7aSAndroid Build Coastguard WorkerUDP_ENCAP_ESPINUDP = 2
213*2f2c4c7aSAndroid Build Coastguard Worker
214*2f2c4c7aSAndroid Build Coastguard Worker_INF = 2 ** 64 -1
215*2f2c4c7aSAndroid Build Coastguard WorkerNO_LIFETIME_CFG = XfrmLifetimeCfg((_INF, _INF, _INF, _INF, 0, 0, 0, 0))
216*2f2c4c7aSAndroid Build Coastguard WorkerNO_LIFETIME_CUR = b"\x00" * len(XfrmLifetimeCur)
217*2f2c4c7aSAndroid Build Coastguard Worker
218*2f2c4c7aSAndroid Build Coastguard Worker# IPsec constants.
219*2f2c4c7aSAndroid Build Coastguard WorkerIPSEC_PROTO_ANY = 255
220*2f2c4c7aSAndroid Build Coastguard Worker
221*2f2c4c7aSAndroid Build Coastguard Worker# ESP header, not technically XFRM but we need a place for a protocol
222*2f2c4c7aSAndroid Build Coastguard Worker# header and this is the only one we have.
223*2f2c4c7aSAndroid Build Coastguard Worker# TODO: move this somewhere more appropriate when possible
224*2f2c4c7aSAndroid Build Coastguard WorkerEspHdr = cstruct.Struct("EspHdr", "!II", "spi seqnum")
225*2f2c4c7aSAndroid Build Coastguard Worker
226*2f2c4c7aSAndroid Build Coastguard Worker# Local constants.
227*2f2c4c7aSAndroid Build Coastguard Worker_DEFAULT_REPLAY_WINDOW = 32
228*2f2c4c7aSAndroid Build Coastguard WorkerALL_ALGORITHMS = 0xffffffff
229*2f2c4c7aSAndroid Build Coastguard Worker
230*2f2c4c7aSAndroid Build Coastguard Worker# Policy-SA match method (for VTI/XFRM-I).
231*2f2c4c7aSAndroid Build Coastguard WorkerMATCH_METHOD_ALL = "all"
232*2f2c4c7aSAndroid Build Coastguard WorkerMATCH_METHOD_MARK = "mark"
233*2f2c4c7aSAndroid Build Coastguard WorkerMATCH_METHOD_IFID = "ifid"
234*2f2c4c7aSAndroid Build Coastguard Worker
235*2f2c4c7aSAndroid Build Coastguard Worker
236*2f2c4c7aSAndroid Build Coastguard Workerdef RawAddress(addr):
237*2f2c4c7aSAndroid Build Coastguard Worker  """Converts an IP address string to binary format."""
238*2f2c4c7aSAndroid Build Coastguard Worker  family = AF_INET6 if ":" in addr else AF_INET
239*2f2c4c7aSAndroid Build Coastguard Worker  return inet_pton(family, addr)
240*2f2c4c7aSAndroid Build Coastguard Worker
241*2f2c4c7aSAndroid Build Coastguard Worker
242*2f2c4c7aSAndroid Build Coastguard Workerdef PaddedAddress(addr):
243*2f2c4c7aSAndroid Build Coastguard Worker  """Converts an IP address string to binary format for InetDiagSockId."""
244*2f2c4c7aSAndroid Build Coastguard Worker  padded = RawAddress(addr)
245*2f2c4c7aSAndroid Build Coastguard Worker  if len(padded) < 16:
246*2f2c4c7aSAndroid Build Coastguard Worker    padded += b"\x00" * (16 - len(padded))
247*2f2c4c7aSAndroid Build Coastguard Worker  return padded
248*2f2c4c7aSAndroid Build Coastguard Worker
249*2f2c4c7aSAndroid Build Coastguard Worker
250*2f2c4c7aSAndroid Build Coastguard WorkerXFRM_ADDR_ANY = PaddedAddress("::")
251*2f2c4c7aSAndroid Build Coastguard Worker
252*2f2c4c7aSAndroid Build Coastguard Worker
253*2f2c4c7aSAndroid Build Coastguard Workerdef EmptySelector(family):
254*2f2c4c7aSAndroid Build Coastguard Worker  """A selector that matches all packets of the specified address family."""
255*2f2c4c7aSAndroid Build Coastguard Worker  return XfrmSelector(family=family)
256*2f2c4c7aSAndroid Build Coastguard Worker
257*2f2c4c7aSAndroid Build Coastguard Worker
258*2f2c4c7aSAndroid Build Coastguard Workerdef SrcDstSelector(src, dst):
259*2f2c4c7aSAndroid Build Coastguard Worker  """A selector that matches packets between the specified IP addresses."""
260*2f2c4c7aSAndroid Build Coastguard Worker  srcver = csocket.AddressVersion(src)
261*2f2c4c7aSAndroid Build Coastguard Worker  dstver = csocket.AddressVersion(dst)
262*2f2c4c7aSAndroid Build Coastguard Worker  if srcver != dstver:
263*2f2c4c7aSAndroid Build Coastguard Worker    raise ValueError("Cross-address family selector specified: %s -> %s" %
264*2f2c4c7aSAndroid Build Coastguard Worker                     (src, dst))
265*2f2c4c7aSAndroid Build Coastguard Worker  prefixlen = net_test.AddressLengthBits(srcver)
266*2f2c4c7aSAndroid Build Coastguard Worker  family = net_test.GetAddressFamily(srcver)
267*2f2c4c7aSAndroid Build Coastguard Worker  return XfrmSelector(saddr=PaddedAddress(src), daddr=PaddedAddress(dst),
268*2f2c4c7aSAndroid Build Coastguard Worker      prefixlen_s=prefixlen, prefixlen_d=prefixlen, family=family)
269*2f2c4c7aSAndroid Build Coastguard Worker
270*2f2c4c7aSAndroid Build Coastguard Worker
271*2f2c4c7aSAndroid Build Coastguard Workerdef UserPolicy(direction, selector):
272*2f2c4c7aSAndroid Build Coastguard Worker  """Create an IPsec policy.
273*2f2c4c7aSAndroid Build Coastguard Worker
274*2f2c4c7aSAndroid Build Coastguard Worker  Args:
275*2f2c4c7aSAndroid Build Coastguard Worker    direction: XFRM_POLICY_IN or XFRM_POLICY_OUT
276*2f2c4c7aSAndroid Build Coastguard Worker    selector: An XfrmSelector, the packets to transform.
277*2f2c4c7aSAndroid Build Coastguard Worker
278*2f2c4c7aSAndroid Build Coastguard Worker  Return: a XfrmUserpolicyInfo cstruct.
279*2f2c4c7aSAndroid Build Coastguard Worker  """
280*2f2c4c7aSAndroid Build Coastguard Worker  # Create a user policy that specifies that all packets in the specified
281*2f2c4c7aSAndroid Build Coastguard Worker  # direction matching the selector should be encrypted.
282*2f2c4c7aSAndroid Build Coastguard Worker  return XfrmUserpolicyInfo(
283*2f2c4c7aSAndroid Build Coastguard Worker      sel=selector,
284*2f2c4c7aSAndroid Build Coastguard Worker      lft=NO_LIFETIME_CFG,
285*2f2c4c7aSAndroid Build Coastguard Worker      curlft=NO_LIFETIME_CUR,
286*2f2c4c7aSAndroid Build Coastguard Worker      dir=direction,
287*2f2c4c7aSAndroid Build Coastguard Worker      action=XFRM_POLICY_ALLOW,
288*2f2c4c7aSAndroid Build Coastguard Worker      flags=XFRM_POLICY_LOCALOK,
289*2f2c4c7aSAndroid Build Coastguard Worker      share=XFRM_SHARE_UNIQUE)
290*2f2c4c7aSAndroid Build Coastguard Worker
291*2f2c4c7aSAndroid Build Coastguard Worker
292*2f2c4c7aSAndroid Build Coastguard Workerdef UserTemplate(family, spi, reqid, tun_addrs):
293*2f2c4c7aSAndroid Build Coastguard Worker  """Create an ESP policy and template.
294*2f2c4c7aSAndroid Build Coastguard Worker
295*2f2c4c7aSAndroid Build Coastguard Worker  Args:
296*2f2c4c7aSAndroid Build Coastguard Worker    spi: 32-bit SPI in host byte order
297*2f2c4c7aSAndroid Build Coastguard Worker    reqid: 32-bit ID matched against SAs
298*2f2c4c7aSAndroid Build Coastguard Worker    tun_addrs: A tuple of (local, remote) addresses for tunnel mode, or None
299*2f2c4c7aSAndroid Build Coastguard Worker      to request a transport mode SA.
300*2f2c4c7aSAndroid Build Coastguard Worker
301*2f2c4c7aSAndroid Build Coastguard Worker  Return: a tuple of XfrmUserpolicyInfo, XfrmUserTmpl
302*2f2c4c7aSAndroid Build Coastguard Worker  """
303*2f2c4c7aSAndroid Build Coastguard Worker  # For transport mode, set template source and destination are empty.
304*2f2c4c7aSAndroid Build Coastguard Worker  # For tunnel mode, explicitly specify source and destination addresses.
305*2f2c4c7aSAndroid Build Coastguard Worker  if tun_addrs is None:
306*2f2c4c7aSAndroid Build Coastguard Worker    mode = XFRM_MODE_TRANSPORT
307*2f2c4c7aSAndroid Build Coastguard Worker    saddr = XFRM_ADDR_ANY
308*2f2c4c7aSAndroid Build Coastguard Worker    daddr = XFRM_ADDR_ANY
309*2f2c4c7aSAndroid Build Coastguard Worker  else:
310*2f2c4c7aSAndroid Build Coastguard Worker    mode = XFRM_MODE_TUNNEL
311*2f2c4c7aSAndroid Build Coastguard Worker    saddr = PaddedAddress(tun_addrs[0])
312*2f2c4c7aSAndroid Build Coastguard Worker    daddr = PaddedAddress(tun_addrs[1])
313*2f2c4c7aSAndroid Build Coastguard Worker
314*2f2c4c7aSAndroid Build Coastguard Worker  # Create a template that specifies the SPI and the protocol.
315*2f2c4c7aSAndroid Build Coastguard Worker  xfrmid = XfrmId(daddr=daddr, spi=spi, proto=IPPROTO_ESP)
316*2f2c4c7aSAndroid Build Coastguard Worker  template = XfrmUserTmpl(
317*2f2c4c7aSAndroid Build Coastguard Worker      id=xfrmid,
318*2f2c4c7aSAndroid Build Coastguard Worker      family=family,
319*2f2c4c7aSAndroid Build Coastguard Worker      saddr=saddr,
320*2f2c4c7aSAndroid Build Coastguard Worker      reqid=reqid,
321*2f2c4c7aSAndroid Build Coastguard Worker      mode=mode,
322*2f2c4c7aSAndroid Build Coastguard Worker      share=XFRM_SHARE_UNIQUE,
323*2f2c4c7aSAndroid Build Coastguard Worker      optional=0,  #require
324*2f2c4c7aSAndroid Build Coastguard Worker      aalgos=ALL_ALGORITHMS,
325*2f2c4c7aSAndroid Build Coastguard Worker      ealgos=ALL_ALGORITHMS,
326*2f2c4c7aSAndroid Build Coastguard Worker      calgos=ALL_ALGORITHMS)
327*2f2c4c7aSAndroid Build Coastguard Worker
328*2f2c4c7aSAndroid Build Coastguard Worker  return template
329*2f2c4c7aSAndroid Build Coastguard Worker
330*2f2c4c7aSAndroid Build Coastguard Worker
331*2f2c4c7aSAndroid Build Coastguard Workerdef ExactMatchMark(mark):
332*2f2c4c7aSAndroid Build Coastguard Worker  """An XfrmMark that matches only the specified mark."""
333*2f2c4c7aSAndroid Build Coastguard Worker  return XfrmMark((mark, 0xffffffff))
334*2f2c4c7aSAndroid Build Coastguard Worker
335*2f2c4c7aSAndroid Build Coastguard Worker
336*2f2c4c7aSAndroid Build Coastguard Workerclass Xfrm(netlink.NetlinkSocket):
337*2f2c4c7aSAndroid Build Coastguard Worker  """Netlink interface to xfrm."""
338*2f2c4c7aSAndroid Build Coastguard Worker
339*2f2c4c7aSAndroid Build Coastguard Worker  DEBUG = False
340*2f2c4c7aSAndroid Build Coastguard Worker
341*2f2c4c7aSAndroid Build Coastguard Worker  def __init__(self):
342*2f2c4c7aSAndroid Build Coastguard Worker    super(Xfrm, self).__init__(netlink.NETLINK_XFRM)
343*2f2c4c7aSAndroid Build Coastguard Worker
344*2f2c4c7aSAndroid Build Coastguard Worker  def _GetConstantName(self, value, prefix):
345*2f2c4c7aSAndroid Build Coastguard Worker    return super(Xfrm, self)._GetConstantName(__name__, value, prefix)
346*2f2c4c7aSAndroid Build Coastguard Worker
347*2f2c4c7aSAndroid Build Coastguard Worker  def MaybeDebugCommand(self, command, flags, data):
348*2f2c4c7aSAndroid Build Coastguard Worker    if "ALL" not in self.NL_DEBUG and "XFRM" not in self.NL_DEBUG:
349*2f2c4c7aSAndroid Build Coastguard Worker      return
350*2f2c4c7aSAndroid Build Coastguard Worker
351*2f2c4c7aSAndroid Build Coastguard Worker    if command == XFRM_MSG_GETSA:
352*2f2c4c7aSAndroid Build Coastguard Worker      if flags & netlink.NLM_F_DUMP:
353*2f2c4c7aSAndroid Build Coastguard Worker        struct_type = XfrmUsersaInfo
354*2f2c4c7aSAndroid Build Coastguard Worker      else:
355*2f2c4c7aSAndroid Build Coastguard Worker        struct_type = XfrmUsersaId
356*2f2c4c7aSAndroid Build Coastguard Worker    elif command == XFRM_MSG_DELSA:
357*2f2c4c7aSAndroid Build Coastguard Worker      struct_type = XfrmUsersaId
358*2f2c4c7aSAndroid Build Coastguard Worker    elif command == XFRM_MSG_ALLOCSPI:
359*2f2c4c7aSAndroid Build Coastguard Worker      struct_type = XfrmUserSpiInfo
360*2f2c4c7aSAndroid Build Coastguard Worker    elif command == XFRM_MSG_NEWPOLICY:
361*2f2c4c7aSAndroid Build Coastguard Worker      struct_type = XfrmUserpolicyInfo
362*2f2c4c7aSAndroid Build Coastguard Worker    else:
363*2f2c4c7aSAndroid Build Coastguard Worker      struct_type = None
364*2f2c4c7aSAndroid Build Coastguard Worker
365*2f2c4c7aSAndroid Build Coastguard Worker    cmdname = self._GetConstantName(command, "XFRM_MSG_")
366*2f2c4c7aSAndroid Build Coastguard Worker    if struct_type:
367*2f2c4c7aSAndroid Build Coastguard Worker      print("%s %s" % (cmdname, str(self._ParseNLMsg(data, struct_type))))
368*2f2c4c7aSAndroid Build Coastguard Worker    else:
369*2f2c4c7aSAndroid Build Coastguard Worker      print("%s" % cmdname)
370*2f2c4c7aSAndroid Build Coastguard Worker
371*2f2c4c7aSAndroid Build Coastguard Worker  def _Decode(self, command, unused_msg, nla_type, nla_data, nested):
372*2f2c4c7aSAndroid Build Coastguard Worker    """Decodes netlink attributes to Python types."""
373*2f2c4c7aSAndroid Build Coastguard Worker    name = self._GetConstantName(nla_type, "XFRMA_")
374*2f2c4c7aSAndroid Build Coastguard Worker
375*2f2c4c7aSAndroid Build Coastguard Worker    if name in ["XFRMA_ALG_CRYPT", "XFRMA_ALG_AUTH"]:
376*2f2c4c7aSAndroid Build Coastguard Worker      data = cstruct.Read(nla_data, XfrmAlgo)[0]
377*2f2c4c7aSAndroid Build Coastguard Worker    elif name == "XFRMA_ALG_AUTH_TRUNC":
378*2f2c4c7aSAndroid Build Coastguard Worker      data = cstruct.Read(nla_data, XfrmAlgoAuth)[0]
379*2f2c4c7aSAndroid Build Coastguard Worker    elif name == "XFRMA_ENCAP":
380*2f2c4c7aSAndroid Build Coastguard Worker      data = cstruct.Read(nla_data, XfrmEncapTmpl)[0]
381*2f2c4c7aSAndroid Build Coastguard Worker    elif name == "XFRMA_MARK":
382*2f2c4c7aSAndroid Build Coastguard Worker      data = cstruct.Read(nla_data, XfrmMark)[0]
383*2f2c4c7aSAndroid Build Coastguard Worker    elif name == "XFRMA_OUTPUT_MARK":
384*2f2c4c7aSAndroid Build Coastguard Worker      data = struct.unpack("=I", nla_data)[0]
385*2f2c4c7aSAndroid Build Coastguard Worker    elif name == "XFRMA_TMPL":
386*2f2c4c7aSAndroid Build Coastguard Worker      data = cstruct.Read(nla_data, XfrmUserTmpl)[0]
387*2f2c4c7aSAndroid Build Coastguard Worker    elif name == "XFRMA_IF_ID":
388*2f2c4c7aSAndroid Build Coastguard Worker      data = struct.unpack("=I", nla_data)[0]
389*2f2c4c7aSAndroid Build Coastguard Worker    else:
390*2f2c4c7aSAndroid Build Coastguard Worker      data = nla_data
391*2f2c4c7aSAndroid Build Coastguard Worker
392*2f2c4c7aSAndroid Build Coastguard Worker    return name, data
393*2f2c4c7aSAndroid Build Coastguard Worker
394*2f2c4c7aSAndroid Build Coastguard Worker  def _UpdatePolicyInfo(self, msg, policy, tmpl, mark, xfrm_if_id):
395*2f2c4c7aSAndroid Build Coastguard Worker    """Send a policy to the Security Policy Database"""
396*2f2c4c7aSAndroid Build Coastguard Worker    nlattrs = []
397*2f2c4c7aSAndroid Build Coastguard Worker    if tmpl is not None:
398*2f2c4c7aSAndroid Build Coastguard Worker      nlattrs.append((XFRMA_TMPL, tmpl))
399*2f2c4c7aSAndroid Build Coastguard Worker    if mark is not None:
400*2f2c4c7aSAndroid Build Coastguard Worker      nlattrs.append((XFRMA_MARK, mark))
401*2f2c4c7aSAndroid Build Coastguard Worker    if xfrm_if_id is not None:
402*2f2c4c7aSAndroid Build Coastguard Worker      nlattrs.append((XFRMA_IF_ID, struct.pack("=I", xfrm_if_id)))
403*2f2c4c7aSAndroid Build Coastguard Worker    self.SendXfrmNlRequest(msg, policy, nlattrs)
404*2f2c4c7aSAndroid Build Coastguard Worker
405*2f2c4c7aSAndroid Build Coastguard Worker  def AddPolicyInfo(self, policy, tmpl, mark, xfrm_if_id=None):
406*2f2c4c7aSAndroid Build Coastguard Worker    """Add a new policy to the Security Policy Database
407*2f2c4c7aSAndroid Build Coastguard Worker
408*2f2c4c7aSAndroid Build Coastguard Worker    If the policy exists, then return an error (EEXIST).
409*2f2c4c7aSAndroid Build Coastguard Worker
410*2f2c4c7aSAndroid Build Coastguard Worker    Args:
411*2f2c4c7aSAndroid Build Coastguard Worker      policy: an unpacked XfrmUserpolicyInfo
412*2f2c4c7aSAndroid Build Coastguard Worker      tmpl: an unpacked XfrmUserTmpl
413*2f2c4c7aSAndroid Build Coastguard Worker      mark: an unpacked XfrmMark
414*2f2c4c7aSAndroid Build Coastguard Worker      xfrm_if_id: the XFRM interface ID as an integer, or None
415*2f2c4c7aSAndroid Build Coastguard Worker    """
416*2f2c4c7aSAndroid Build Coastguard Worker    self._UpdatePolicyInfo(XFRM_MSG_NEWPOLICY, policy, tmpl, mark, xfrm_if_id)
417*2f2c4c7aSAndroid Build Coastguard Worker
418*2f2c4c7aSAndroid Build Coastguard Worker  def UpdatePolicyInfo(self, policy, tmpl, mark, xfrm_if_id):
419*2f2c4c7aSAndroid Build Coastguard Worker    """Update an existing policy in the Security Policy Database
420*2f2c4c7aSAndroid Build Coastguard Worker
421*2f2c4c7aSAndroid Build Coastguard Worker    If the policy does not exist, then create it; otherwise, update the
422*2f2c4c7aSAndroid Build Coastguard Worker    existing policy record.
423*2f2c4c7aSAndroid Build Coastguard Worker
424*2f2c4c7aSAndroid Build Coastguard Worker    Args:
425*2f2c4c7aSAndroid Build Coastguard Worker      policy: an unpacked XfrmUserpolicyInfo
426*2f2c4c7aSAndroid Build Coastguard Worker      tmpl: an unpacked XfrmUserTmpl to update
427*2f2c4c7aSAndroid Build Coastguard Worker      mark: an unpacked XfrmMark to match the existing policy or None
428*2f2c4c7aSAndroid Build Coastguard Worker      xfrm_if_id: an XFRM interface ID or None
429*2f2c4c7aSAndroid Build Coastguard Worker    """
430*2f2c4c7aSAndroid Build Coastguard Worker    self._UpdatePolicyInfo(XFRM_MSG_UPDPOLICY, policy, tmpl, mark, xfrm_if_id)
431*2f2c4c7aSAndroid Build Coastguard Worker
432*2f2c4c7aSAndroid Build Coastguard Worker  def DeletePolicyInfo(self, selector, direction, mark, xfrm_if_id=None):
433*2f2c4c7aSAndroid Build Coastguard Worker    """Delete a policy from the Security Policy Database
434*2f2c4c7aSAndroid Build Coastguard Worker
435*2f2c4c7aSAndroid Build Coastguard Worker    Args:
436*2f2c4c7aSAndroid Build Coastguard Worker      selector: an XfrmSelector matching the policy to delete
437*2f2c4c7aSAndroid Build Coastguard Worker      direction: policy direction
438*2f2c4c7aSAndroid Build Coastguard Worker      mark: an unpacked XfrmMark to match the policy or None
439*2f2c4c7aSAndroid Build Coastguard Worker    """
440*2f2c4c7aSAndroid Build Coastguard Worker    nlattrs = []
441*2f2c4c7aSAndroid Build Coastguard Worker    if mark is not None:
442*2f2c4c7aSAndroid Build Coastguard Worker      nlattrs.append((XFRMA_MARK, mark))
443*2f2c4c7aSAndroid Build Coastguard Worker    if xfrm_if_id is not None:
444*2f2c4c7aSAndroid Build Coastguard Worker      nlattrs.append((XFRMA_IF_ID, struct.pack("=I", xfrm_if_id)))
445*2f2c4c7aSAndroid Build Coastguard Worker    self.SendXfrmNlRequest(XFRM_MSG_DELPOLICY,
446*2f2c4c7aSAndroid Build Coastguard Worker                           XfrmUserpolicyId(sel=selector, dir=direction),
447*2f2c4c7aSAndroid Build Coastguard Worker                           nlattrs)
448*2f2c4c7aSAndroid Build Coastguard Worker
449*2f2c4c7aSAndroid Build Coastguard Worker  # TODO: this function really needs to be in netlink.py
450*2f2c4c7aSAndroid Build Coastguard Worker  def SendXfrmNlRequest(self, msg_type, req, nlattrs=None,
451*2f2c4c7aSAndroid Build Coastguard Worker                        flags=netlink.NLM_F_ACK|netlink.NLM_F_REQUEST):
452*2f2c4c7aSAndroid Build Coastguard Worker    """Sends a netlink request message
453*2f2c4c7aSAndroid Build Coastguard Worker
454*2f2c4c7aSAndroid Build Coastguard Worker    Args:
455*2f2c4c7aSAndroid Build Coastguard Worker      msg_type: an XFRM_MSG_* type
456*2f2c4c7aSAndroid Build Coastguard Worker      req: an unpacked netlink request message body cstruct
457*2f2c4c7aSAndroid Build Coastguard Worker      nlattrs: an unpacked list of two-tuples of (NLATTR_* type, body) where
458*2f2c4c7aSAndroid Build Coastguard Worker          the body is an unpacked cstruct
459*2f2c4c7aSAndroid Build Coastguard Worker      flags: a list of flags for the expected handling; if no flags are
460*2f2c4c7aSAndroid Build Coastguard Worker          provided, an ACK response is assumed.
461*2f2c4c7aSAndroid Build Coastguard Worker    """
462*2f2c4c7aSAndroid Build Coastguard Worker    msg = req.Pack()
463*2f2c4c7aSAndroid Build Coastguard Worker    if nlattrs is None:
464*2f2c4c7aSAndroid Build Coastguard Worker      nlattrs = []
465*2f2c4c7aSAndroid Build Coastguard Worker    for attr_type, attr_msg in nlattrs:
466*2f2c4c7aSAndroid Build Coastguard Worker      # TODO: find a better way to deal with the fact that many XFRM messages
467*2f2c4c7aSAndroid Build Coastguard Worker      # use nlattrs that aren't cstructs.
468*2f2c4c7aSAndroid Build Coastguard Worker      #
469*2f2c4c7aSAndroid Build Coastguard Worker      # This code allows callers to pass in either something that has a Pack()
470*2f2c4c7aSAndroid Build Coastguard Worker      # method or a packed netlink attr, but not other types of attributes.
471*2f2c4c7aSAndroid Build Coastguard Worker      # Alternatives include:
472*2f2c4c7aSAndroid Build Coastguard Worker      #
473*2f2c4c7aSAndroid Build Coastguard Worker      # 1. Require callers to marshal netlink attributes themselves and call
474*2f2c4c7aSAndroid Build Coastguard Worker      #    _SendNlRequest directly. Delete this method.
475*2f2c4c7aSAndroid Build Coastguard Worker      # 2. Rename this function to _SendXfrmNlRequestCstructOnly (or other name
476*2f2c4c7aSAndroid Build Coastguard Worker      #    that makes it clear that this only takes cstructs). Switch callers
477*2f2c4c7aSAndroid Build Coastguard Worker      #    that need non-cstruct elements to calling _SendNlRequest directly.
478*2f2c4c7aSAndroid Build Coastguard Worker      # 3. Make this function somehow automatically detect what to do for
479*2f2c4c7aSAndroid Build Coastguard Worker      #    all types of XFRM attributes today and in the future. This may be
480*2f2c4c7aSAndroid Build Coastguard Worker      #    feasible because all XFRM attributes today occupy the same number
481*2f2c4c7aSAndroid Build Coastguard Worker      #    space, but what about nested attributes? It is unlikley feasible via
482*2f2c4c7aSAndroid Build Coastguard Worker      #    things like "if isinstance(attr_msg, str): ...", because that would
483*2f2c4c7aSAndroid Build Coastguard Worker      #    not be able to determine the right size or byte order for non-struct
484*2f2c4c7aSAndroid Build Coastguard Worker      #    types such as int.
485*2f2c4c7aSAndroid Build Coastguard Worker      # 4. Define fictitious cstructs which have no correspondence to actual
486*2f2c4c7aSAndroid Build Coastguard Worker      #    kernel structs such as the following to represent a raw integer.
487*2f2c4c7aSAndroid Build Coastguard Worker      #    XfrmAttrOutputMark = cstruct.Struct("=I", mark)
488*2f2c4c7aSAndroid Build Coastguard Worker      if hasattr(attr_msg, "Pack"):
489*2f2c4c7aSAndroid Build Coastguard Worker        attr_msg = attr_msg.Pack()
490*2f2c4c7aSAndroid Build Coastguard Worker      msg += self._NlAttr(attr_type, attr_msg)
491*2f2c4c7aSAndroid Build Coastguard Worker    return self._SendNlRequest(msg_type, msg, flags)
492*2f2c4c7aSAndroid Build Coastguard Worker
493*2f2c4c7aSAndroid Build Coastguard Worker  def AddSaInfo(self, src, dst, spi, mode, reqid, encryption, auth_trunc, aead,
494*2f2c4c7aSAndroid Build Coastguard Worker                encap, mark, output_mark, is_update=False, xfrm_if_id=None):
495*2f2c4c7aSAndroid Build Coastguard Worker    """Adds an IPsec security association.
496*2f2c4c7aSAndroid Build Coastguard Worker
497*2f2c4c7aSAndroid Build Coastguard Worker    Args:
498*2f2c4c7aSAndroid Build Coastguard Worker      src: A string, the source IP address. May be a wildcard in transport mode.
499*2f2c4c7aSAndroid Build Coastguard Worker      dst: A string, the destination IP address. Forms part of the XFRM ID, and
500*2f2c4c7aSAndroid Build Coastguard Worker        must match the destination address of the packets sent by this SA.
501*2f2c4c7aSAndroid Build Coastguard Worker      spi: An integer, the SPI.
502*2f2c4c7aSAndroid Build Coastguard Worker      mode: An IPsec mode such as XFRM_MODE_TRANSPORT.
503*2f2c4c7aSAndroid Build Coastguard Worker      reqid: A request ID. Can be used in policies to match the SA.
504*2f2c4c7aSAndroid Build Coastguard Worker      encryption: A tuple of an XfrmAlgo and raw key bytes, or None.
505*2f2c4c7aSAndroid Build Coastguard Worker      auth_trunc: A tuple of an XfrmAlgoAuth and raw key bytes, or None.
506*2f2c4c7aSAndroid Build Coastguard Worker      aead: A tuple of an XfrmAlgoAead and raw key bytes, or None.
507*2f2c4c7aSAndroid Build Coastguard Worker      encap: An XfrmEncapTmpl structure, or None.
508*2f2c4c7aSAndroid Build Coastguard Worker      mark: A mark match specifier, such as returned by ExactMatchMark(), or
509*2f2c4c7aSAndroid Build Coastguard Worker        None for an SA that matches all possible marks.
510*2f2c4c7aSAndroid Build Coastguard Worker      output_mark: An integer, the output mark. 0 means unset.
511*2f2c4c7aSAndroid Build Coastguard Worker      is_update: If true, update an existing SA otherwise create a new SA. For
512*2f2c4c7aSAndroid Build Coastguard Worker        compatibility reasons, this value defaults to False.
513*2f2c4c7aSAndroid Build Coastguard Worker      xfrm_if_id: The XFRM interface ID, or None.
514*2f2c4c7aSAndroid Build Coastguard Worker    """
515*2f2c4c7aSAndroid Build Coastguard Worker    proto = IPPROTO_ESP
516*2f2c4c7aSAndroid Build Coastguard Worker    xfrm_id = XfrmId((PaddedAddress(dst), spi, proto))
517*2f2c4c7aSAndroid Build Coastguard Worker    family = AF_INET6 if ":" in dst else AF_INET
518*2f2c4c7aSAndroid Build Coastguard Worker
519*2f2c4c7aSAndroid Build Coastguard Worker    nlattrs = b""
520*2f2c4c7aSAndroid Build Coastguard Worker    if encryption is not None:
521*2f2c4c7aSAndroid Build Coastguard Worker      enc, key = encryption
522*2f2c4c7aSAndroid Build Coastguard Worker      nlattrs += self._NlAttr(XFRMA_ALG_CRYPT, enc.Pack() + key)
523*2f2c4c7aSAndroid Build Coastguard Worker
524*2f2c4c7aSAndroid Build Coastguard Worker    if auth_trunc is not None:
525*2f2c4c7aSAndroid Build Coastguard Worker      auth, key = auth_trunc
526*2f2c4c7aSAndroid Build Coastguard Worker      nlattrs += self._NlAttr(XFRMA_ALG_AUTH_TRUNC, auth.Pack() + key)
527*2f2c4c7aSAndroid Build Coastguard Worker
528*2f2c4c7aSAndroid Build Coastguard Worker    if aead is not None:
529*2f2c4c7aSAndroid Build Coastguard Worker      aead_alg, key = aead
530*2f2c4c7aSAndroid Build Coastguard Worker      nlattrs += self._NlAttr(XFRMA_ALG_AEAD, aead_alg.Pack() + key)
531*2f2c4c7aSAndroid Build Coastguard Worker
532*2f2c4c7aSAndroid Build Coastguard Worker    # if a user provides either mark or mask, then we send the mark attribute
533*2f2c4c7aSAndroid Build Coastguard Worker    if mark is not None:
534*2f2c4c7aSAndroid Build Coastguard Worker      nlattrs += self._NlAttr(XFRMA_MARK, mark.Pack())
535*2f2c4c7aSAndroid Build Coastguard Worker    if encap is not None:
536*2f2c4c7aSAndroid Build Coastguard Worker      nlattrs += self._NlAttr(XFRMA_ENCAP, encap.Pack())
537*2f2c4c7aSAndroid Build Coastguard Worker    if output_mark is not None:
538*2f2c4c7aSAndroid Build Coastguard Worker      nlattrs += self._NlAttrU32(XFRMA_OUTPUT_MARK, output_mark)
539*2f2c4c7aSAndroid Build Coastguard Worker    if xfrm_if_id is not None:
540*2f2c4c7aSAndroid Build Coastguard Worker      nlattrs += self._NlAttrU32(XFRMA_IF_ID, xfrm_if_id)
541*2f2c4c7aSAndroid Build Coastguard Worker
542*2f2c4c7aSAndroid Build Coastguard Worker    # The kernel ignores these on input, so make them empty.
543*2f2c4c7aSAndroid Build Coastguard Worker    cur = XfrmLifetimeCur()
544*2f2c4c7aSAndroid Build Coastguard Worker    stats = XfrmStats()
545*2f2c4c7aSAndroid Build Coastguard Worker    seq = 0
546*2f2c4c7aSAndroid Build Coastguard Worker    replay = _DEFAULT_REPLAY_WINDOW
547*2f2c4c7aSAndroid Build Coastguard Worker
548*2f2c4c7aSAndroid Build Coastguard Worker    # The XFRM_STATE_AF_UNSPEC flag determines how AF_UNSPEC selectors behave.
549*2f2c4c7aSAndroid Build Coastguard Worker    #
550*2f2c4c7aSAndroid Build Coastguard Worker    # - If the flag is not set, an AF_UNSPEC selector has its family changed to
551*2f2c4c7aSAndroid Build Coastguard Worker    #   the SA family, which in our case is the address family of dst.
552*2f2c4c7aSAndroid Build Coastguard Worker    # - If the flag is set, an AF_UNSPEC selector is left as is. In transport
553*2f2c4c7aSAndroid Build Coastguard Worker    #   mode this fails with EPROTONOSUPPORT, but in tunnel mode, it results in
554*2f2c4c7aSAndroid Build Coastguard Worker    #   a dual-stack SA that can tunnel both IPv4 and IPv6 packets.
555*2f2c4c7aSAndroid Build Coastguard Worker    #
556*2f2c4c7aSAndroid Build Coastguard Worker    # This allows us to pass an empty selector to the kernel regardless of which
557*2f2c4c7aSAndroid Build Coastguard Worker    # mode we're in: when creating transport mode SAs, the kernel will pick the
558*2f2c4c7aSAndroid Build Coastguard Worker    # selector family based on the SA family, and when creating tunnel mode SAs,
559*2f2c4c7aSAndroid Build Coastguard Worker    # we'll just create SAs that select both IPv4 and IPv6 traffic, and leave it
560*2f2c4c7aSAndroid Build Coastguard Worker    # up to the policy selectors to determine what traffic we actually want to
561*2f2c4c7aSAndroid Build Coastguard Worker    # transform.
562*2f2c4c7aSAndroid Build Coastguard Worker    flags = XFRM_STATE_AF_UNSPEC if mode == XFRM_MODE_TUNNEL else 0
563*2f2c4c7aSAndroid Build Coastguard Worker    selector = EmptySelector(AF_UNSPEC)
564*2f2c4c7aSAndroid Build Coastguard Worker
565*2f2c4c7aSAndroid Build Coastguard Worker    sa = XfrmUsersaInfo((selector, xfrm_id, PaddedAddress(src), NO_LIFETIME_CFG,
566*2f2c4c7aSAndroid Build Coastguard Worker                         cur, stats, seq, reqid, family, mode, replay, flags))
567*2f2c4c7aSAndroid Build Coastguard Worker    msg = sa.Pack() + nlattrs
568*2f2c4c7aSAndroid Build Coastguard Worker    flags = netlink.NLM_F_REQUEST | netlink.NLM_F_ACK
569*2f2c4c7aSAndroid Build Coastguard Worker    nl_msg_type = XFRM_MSG_UPDSA if is_update else XFRM_MSG_NEWSA
570*2f2c4c7aSAndroid Build Coastguard Worker    self._SendNlRequest(nl_msg_type, msg, flags)
571*2f2c4c7aSAndroid Build Coastguard Worker
572*2f2c4c7aSAndroid Build Coastguard Worker  def DeleteSaInfo(self, dst, spi, proto, mark=None, xfrm_if_id=None):
573*2f2c4c7aSAndroid Build Coastguard Worker    """Delete an SA from the SAD
574*2f2c4c7aSAndroid Build Coastguard Worker
575*2f2c4c7aSAndroid Build Coastguard Worker    Args:
576*2f2c4c7aSAndroid Build Coastguard Worker      dst: A string, the destination IP address. Forms part of the XFRM ID, and
577*2f2c4c7aSAndroid Build Coastguard Worker        must match the destination address of the packets sent by this SA.
578*2f2c4c7aSAndroid Build Coastguard Worker      spi: An integer, the SPI.
579*2f2c4c7aSAndroid Build Coastguard Worker      proto: The protocol DB of the SA, such as IPPROTO_ESP.
580*2f2c4c7aSAndroid Build Coastguard Worker      mark: A mark match specifier, such as returned by ExactMatchMark(), or
581*2f2c4c7aSAndroid Build Coastguard Worker        None for an SA without a Mark attribute.
582*2f2c4c7aSAndroid Build Coastguard Worker    """
583*2f2c4c7aSAndroid Build Coastguard Worker    family = AF_INET6 if ":" in dst else AF_INET
584*2f2c4c7aSAndroid Build Coastguard Worker    usersa_id = XfrmUsersaId((PaddedAddress(dst), spi, family, proto))
585*2f2c4c7aSAndroid Build Coastguard Worker    nlattrs = []
586*2f2c4c7aSAndroid Build Coastguard Worker    if mark is not None:
587*2f2c4c7aSAndroid Build Coastguard Worker      nlattrs.append((XFRMA_MARK, mark))
588*2f2c4c7aSAndroid Build Coastguard Worker    if xfrm_if_id is not None:
589*2f2c4c7aSAndroid Build Coastguard Worker      nlattrs.append((XFRMA_IF_ID, struct.pack("=I", xfrm_if_id)))
590*2f2c4c7aSAndroid Build Coastguard Worker    self.SendXfrmNlRequest(XFRM_MSG_DELSA, usersa_id, nlattrs)
591*2f2c4c7aSAndroid Build Coastguard Worker
592*2f2c4c7aSAndroid Build Coastguard Worker  def AllocSpi(self, dst, proto, min_spi, max_spi):
593*2f2c4c7aSAndroid Build Coastguard Worker    """Allocate (reserve) an SPI.
594*2f2c4c7aSAndroid Build Coastguard Worker
595*2f2c4c7aSAndroid Build Coastguard Worker    This sends an XFRM_MSG_ALLOCSPI message and returns the resulting
596*2f2c4c7aSAndroid Build Coastguard Worker    XfrmUsersaInfo struct.
597*2f2c4c7aSAndroid Build Coastguard Worker
598*2f2c4c7aSAndroid Build Coastguard Worker    Args:
599*2f2c4c7aSAndroid Build Coastguard Worker      dst: A string, the destination IP address. Forms part of the XFRM ID, and
600*2f2c4c7aSAndroid Build Coastguard Worker        must match the destination address of the packets sent by this SA.
601*2f2c4c7aSAndroid Build Coastguard Worker      proto: the protocol DB of the SA, such as IPPROTO_ESP.
602*2f2c4c7aSAndroid Build Coastguard Worker      min_spi: The minimum value of the acceptable SPI range (inclusive).
603*2f2c4c7aSAndroid Build Coastguard Worker      max_spi: The maximum value of the acceptable SPI range (inclusive).
604*2f2c4c7aSAndroid Build Coastguard Worker    """
605*2f2c4c7aSAndroid Build Coastguard Worker    spi = XfrmUserSpiInfo(b"\x00" * len(XfrmUserSpiInfo))
606*2f2c4c7aSAndroid Build Coastguard Worker    spi.min = min_spi
607*2f2c4c7aSAndroid Build Coastguard Worker    spi.max = max_spi
608*2f2c4c7aSAndroid Build Coastguard Worker    spi.info.id.daddr = PaddedAddress(dst)
609*2f2c4c7aSAndroid Build Coastguard Worker    spi.info.id.proto = proto
610*2f2c4c7aSAndroid Build Coastguard Worker    spi.info.family = AF_INET6 if ":" in dst else AF_INET
611*2f2c4c7aSAndroid Build Coastguard Worker
612*2f2c4c7aSAndroid Build Coastguard Worker    msg = spi.Pack()
613*2f2c4c7aSAndroid Build Coastguard Worker    flags = netlink.NLM_F_REQUEST
614*2f2c4c7aSAndroid Build Coastguard Worker    self._SendNlRequest(XFRM_MSG_ALLOCSPI, msg, flags)
615*2f2c4c7aSAndroid Build Coastguard Worker    # Read the response message.
616*2f2c4c7aSAndroid Build Coastguard Worker    data = self._Recv()
617*2f2c4c7aSAndroid Build Coastguard Worker    nl_hdr, data = cstruct.Read(data, netlink.NLMsgHdr)
618*2f2c4c7aSAndroid Build Coastguard Worker    if nl_hdr.type == XFRM_MSG_NEWSA:
619*2f2c4c7aSAndroid Build Coastguard Worker      return XfrmUsersaInfo(data)
620*2f2c4c7aSAndroid Build Coastguard Worker    if nl_hdr.type == netlink.NLMSG_ERROR:
621*2f2c4c7aSAndroid Build Coastguard Worker      error = -netlink.NLMsgErr(data).error
622*2f2c4c7aSAndroid Build Coastguard Worker      raise IOError(error, os.strerror(error))
623*2f2c4c7aSAndroid Build Coastguard Worker    raise ValueError("Unexpected netlink message type: %d" % nl_hdr.type)
624*2f2c4c7aSAndroid Build Coastguard Worker
625*2f2c4c7aSAndroid Build Coastguard Worker  def DumpSaInfo(self):
626*2f2c4c7aSAndroid Build Coastguard Worker    return self._Dump(XFRM_MSG_GETSA, None, XfrmUsersaInfo)
627*2f2c4c7aSAndroid Build Coastguard Worker
628*2f2c4c7aSAndroid Build Coastguard Worker  def DumpPolicyInfo(self):
629*2f2c4c7aSAndroid Build Coastguard Worker    return self._Dump(XFRM_MSG_GETPOLICY, None, XfrmUserpolicyInfo)
630*2f2c4c7aSAndroid Build Coastguard Worker
631*2f2c4c7aSAndroid Build Coastguard Worker  def FindSaInfo(self, spi):
632*2f2c4c7aSAndroid Build Coastguard Worker    sainfo = [sa for sa, attrs in self.DumpSaInfo() if sa.id.spi == spi]
633*2f2c4c7aSAndroid Build Coastguard Worker    return sainfo[0] if sainfo else None
634*2f2c4c7aSAndroid Build Coastguard Worker
635*2f2c4c7aSAndroid Build Coastguard Worker  def FlushPolicyInfo(self):
636*2f2c4c7aSAndroid Build Coastguard Worker    """Send a Netlink Request to Flush all records from the SPD"""
637*2f2c4c7aSAndroid Build Coastguard Worker    flags = netlink.NLM_F_REQUEST | netlink.NLM_F_ACK
638*2f2c4c7aSAndroid Build Coastguard Worker    self._SendNlRequest(XFRM_MSG_FLUSHPOLICY, b"", flags)
639*2f2c4c7aSAndroid Build Coastguard Worker
640*2f2c4c7aSAndroid Build Coastguard Worker  def FlushSaInfo(self):
641*2f2c4c7aSAndroid Build Coastguard Worker    usersa_flush = XfrmUsersaFlush((IPSEC_PROTO_ANY,))
642*2f2c4c7aSAndroid Build Coastguard Worker    flags = netlink.NLM_F_REQUEST | netlink.NLM_F_ACK
643*2f2c4c7aSAndroid Build Coastguard Worker    self._SendNlRequest(XFRM_MSG_FLUSHSA, usersa_flush.Pack(), flags)
644*2f2c4c7aSAndroid Build Coastguard Worker
645*2f2c4c7aSAndroid Build Coastguard Worker  def CreateTunnel(self, direction, selector, src, dst, spi, encryption,
646*2f2c4c7aSAndroid Build Coastguard Worker                   auth_trunc, mark, output_mark, xfrm_if_id, match_method):
647*2f2c4c7aSAndroid Build Coastguard Worker    """Create an XFRM Tunnel Consisting of a Policy and an SA.
648*2f2c4c7aSAndroid Build Coastguard Worker
649*2f2c4c7aSAndroid Build Coastguard Worker    Create a unidirectional XFRM tunnel, which entails one Policy and one
650*2f2c4c7aSAndroid Build Coastguard Worker    security association.
651*2f2c4c7aSAndroid Build Coastguard Worker
652*2f2c4c7aSAndroid Build Coastguard Worker    Args:
653*2f2c4c7aSAndroid Build Coastguard Worker      direction: XFRM_POLICY_IN or XFRM_POLICY_OUT
654*2f2c4c7aSAndroid Build Coastguard Worker      selector: An XfrmSelector that specifies the packets to be transformed.
655*2f2c4c7aSAndroid Build Coastguard Worker        This is only applied to the policy; the selector in the SA is always
656*2f2c4c7aSAndroid Build Coastguard Worker        empty. If the passed-in selector is None, then the tunnel is made
657*2f2c4c7aSAndroid Build Coastguard Worker        dual-stack. This requires two policies, one for IPv4 and one for IPv6.
658*2f2c4c7aSAndroid Build Coastguard Worker      src: The source address of the tunneled packets
659*2f2c4c7aSAndroid Build Coastguard Worker      dst: The destination address of the tunneled packets
660*2f2c4c7aSAndroid Build Coastguard Worker      spi: The SPI for the IPsec SA that encapsulates the tunneled packet
661*2f2c4c7aSAndroid Build Coastguard Worker      encryption: A tuple (XfrmAlgo, key), the encryption parameters.
662*2f2c4c7aSAndroid Build Coastguard Worker      auth_trunc: A tuple (XfrmAlgoAuth, key), the authentication parameters.
663*2f2c4c7aSAndroid Build Coastguard Worker      mark: An XfrmMark, the mark used for selecting packets to be tunneled, and
664*2f2c4c7aSAndroid Build Coastguard Worker        for matching the security policy. None means unspecified.
665*2f2c4c7aSAndroid Build Coastguard Worker      output_mark: The mark used to select the underlying network for packets
666*2f2c4c7aSAndroid Build Coastguard Worker        outbound from xfrm. None means unspecified.
667*2f2c4c7aSAndroid Build Coastguard Worker      xfrm_if_id: The ID of the XFRM interface to use or None.
668*2f2c4c7aSAndroid Build Coastguard Worker      match_method: One of MATCH_METHOD_[MARK | ALL | IFID]. This determines how
669*2f2c4c7aSAndroid Build Coastguard Worker        SAs and policies are matched.
670*2f2c4c7aSAndroid Build Coastguard Worker    """
671*2f2c4c7aSAndroid Build Coastguard Worker    outer_family = net_test.GetAddressFamily(net_test.GetAddressVersion(dst))
672*2f2c4c7aSAndroid Build Coastguard Worker
673*2f2c4c7aSAndroid Build Coastguard Worker    # SA mark is currently unused due to UPDSA not updating marks.
674*2f2c4c7aSAndroid Build Coastguard Worker    # Kept as documentation of ideal/desired behavior.
675*2f2c4c7aSAndroid Build Coastguard Worker    if match_method == MATCH_METHOD_MARK:
676*2f2c4c7aSAndroid Build Coastguard Worker      # sa_mark = mark
677*2f2c4c7aSAndroid Build Coastguard Worker      tmpl_spi = 0
678*2f2c4c7aSAndroid Build Coastguard Worker      if_id = None
679*2f2c4c7aSAndroid Build Coastguard Worker    elif match_method == MATCH_METHOD_ALL:
680*2f2c4c7aSAndroid Build Coastguard Worker      # sa_mark = mark
681*2f2c4c7aSAndroid Build Coastguard Worker      tmpl_spi = spi
682*2f2c4c7aSAndroid Build Coastguard Worker      if_id = xfrm_if_id
683*2f2c4c7aSAndroid Build Coastguard Worker    elif match_method == MATCH_METHOD_IFID:
684*2f2c4c7aSAndroid Build Coastguard Worker      # sa_mark = None
685*2f2c4c7aSAndroid Build Coastguard Worker      tmpl_spi = 0
686*2f2c4c7aSAndroid Build Coastguard Worker      if_id = xfrm_if_id
687*2f2c4c7aSAndroid Build Coastguard Worker    else:
688*2f2c4c7aSAndroid Build Coastguard Worker      raise ValueError("Unknown match_method supplied: %s" % match_method)
689*2f2c4c7aSAndroid Build Coastguard Worker
690*2f2c4c7aSAndroid Build Coastguard Worker    # Device code does not use mark; during AllocSpi, the mark is unset, and
691*2f2c4c7aSAndroid Build Coastguard Worker    # UPDSA does not update marks at this time. Actual use case will have no
692*2f2c4c7aSAndroid Build Coastguard Worker    # mark set. Test this use case.
693*2f2c4c7aSAndroid Build Coastguard Worker    self.AddSaInfo(src, dst, spi, XFRM_MODE_TUNNEL, 0, encryption, auth_trunc,
694*2f2c4c7aSAndroid Build Coastguard Worker                   None, None, None, output_mark, xfrm_if_id=xfrm_if_id)
695*2f2c4c7aSAndroid Build Coastguard Worker
696*2f2c4c7aSAndroid Build Coastguard Worker    if selector is None:
697*2f2c4c7aSAndroid Build Coastguard Worker      selectors = [EmptySelector(AF_INET), EmptySelector(AF_INET6)]
698*2f2c4c7aSAndroid Build Coastguard Worker    else:
699*2f2c4c7aSAndroid Build Coastguard Worker      selectors = [selector]
700*2f2c4c7aSAndroid Build Coastguard Worker
701*2f2c4c7aSAndroid Build Coastguard Worker    for selector in selectors:
702*2f2c4c7aSAndroid Build Coastguard Worker      policy = UserPolicy(direction, selector)
703*2f2c4c7aSAndroid Build Coastguard Worker      tmpl = UserTemplate(outer_family, tmpl_spi, 0, (src, dst))
704*2f2c4c7aSAndroid Build Coastguard Worker      self.AddPolicyInfo(policy, tmpl, mark, xfrm_if_id=xfrm_if_id)
705*2f2c4c7aSAndroid Build Coastguard Worker
706*2f2c4c7aSAndroid Build Coastguard Worker  def DeleteTunnel(self, direction, selector, dst, spi, mark, xfrm_if_id):
707*2f2c4c7aSAndroid Build Coastguard Worker    if mark is not None:
708*2f2c4c7aSAndroid Build Coastguard Worker      mark = ExactMatchMark(mark)
709*2f2c4c7aSAndroid Build Coastguard Worker
710*2f2c4c7aSAndroid Build Coastguard Worker    self.DeleteSaInfo(dst, spi, IPPROTO_ESP, mark, xfrm_if_id)
711*2f2c4c7aSAndroid Build Coastguard Worker    if selector is None:
712*2f2c4c7aSAndroid Build Coastguard Worker      selectors = [EmptySelector(AF_INET), EmptySelector(AF_INET6)]
713*2f2c4c7aSAndroid Build Coastguard Worker    else:
714*2f2c4c7aSAndroid Build Coastguard Worker      selectors = [selector]
715*2f2c4c7aSAndroid Build Coastguard Worker    for selector in selectors:
716*2f2c4c7aSAndroid Build Coastguard Worker      self.DeletePolicyInfo(selector, direction, mark, xfrm_if_id)
717*2f2c4c7aSAndroid Build Coastguard Worker
718*2f2c4c7aSAndroid Build Coastguard Worker  def MigrateTunnel(self, direction, selector, old_saddr, old_daddr,
719*2f2c4c7aSAndroid Build Coastguard Worker                    new_saddr, new_daddr, spi,
720*2f2c4c7aSAndroid Build Coastguard Worker                    encryption, auth_trunc, aead,
721*2f2c4c7aSAndroid Build Coastguard Worker                    encap, new_output_mark, xfrm_if_id):
722*2f2c4c7aSAndroid Build Coastguard Worker    """Update addresses and underlying network of Policies and an SA
723*2f2c4c7aSAndroid Build Coastguard Worker
724*2f2c4c7aSAndroid Build Coastguard Worker    Args:
725*2f2c4c7aSAndroid Build Coastguard Worker      direction: XFRM_POLICY_IN or XFRM_POLICY_OUT
726*2f2c4c7aSAndroid Build Coastguard Worker      selector: An XfrmSelector of the tunnel that needs to be updated.
727*2f2c4c7aSAndroid Build Coastguard Worker        If the passed-in selector is None, it means the tunnel is
728*2f2c4c7aSAndroid Build Coastguard Worker        dual-stack and thus both IPv4 and IPv6 policies will be updated.
729*2f2c4c7aSAndroid Build Coastguard Worker      old_saddr: the old (current) source address of the tunnel
730*2f2c4c7aSAndroid Build Coastguard Worker      old_daddr: the old (current) destination address of the tunnel
731*2f2c4c7aSAndroid Build Coastguard Worker      new_saddr: the new source address the IPsec SA will be migrated to
732*2f2c4c7aSAndroid Build Coastguard Worker      new_daddr: the new destination address the tunnel will be migrated to
733*2f2c4c7aSAndroid Build Coastguard Worker      spi: The SPI for the IPsec SA that encapsulates the tunneled packets
734*2f2c4c7aSAndroid Build Coastguard Worker      encryption: A tuple of an XfrmAlgo and raw key bytes, or None.
735*2f2c4c7aSAndroid Build Coastguard Worker      auth_trunc: A tuple of an XfrmAlgoAuth and raw key bytes, or None.
736*2f2c4c7aSAndroid Build Coastguard Worker      aead: A tuple of an XfrmAlgoAead and raw key bytes, or None.
737*2f2c4c7aSAndroid Build Coastguard Worker      encap: An XfrmEncapTmpl structure, or None.
738*2f2c4c7aSAndroid Build Coastguard Worker      new_output_mark: The mark used to select the new underlying network
739*2f2c4c7aSAndroid Build Coastguard Worker        for packets outbound from xfrm. None means unspecified.
740*2f2c4c7aSAndroid Build Coastguard Worker      xfrm_if_id: The XFRM interface ID
741*2f2c4c7aSAndroid Build Coastguard Worker    """
742*2f2c4c7aSAndroid Build Coastguard Worker
743*2f2c4c7aSAndroid Build Coastguard Worker    if selector is None:
744*2f2c4c7aSAndroid Build Coastguard Worker      selectors = [EmptySelector(AF_INET), EmptySelector(AF_INET6)]
745*2f2c4c7aSAndroid Build Coastguard Worker    else:
746*2f2c4c7aSAndroid Build Coastguard Worker      selectors = [selector]
747*2f2c4c7aSAndroid Build Coastguard Worker
748*2f2c4c7aSAndroid Build Coastguard Worker    nlattrs = []
749*2f2c4c7aSAndroid Build Coastguard Worker    xfrmMigrate = XfrmMigrate((PaddedAddress(old_daddr), PaddedAddress(old_saddr),
750*2f2c4c7aSAndroid Build Coastguard Worker                      PaddedAddress(new_daddr), PaddedAddress(new_saddr),
751*2f2c4c7aSAndroid Build Coastguard Worker                      IPPROTO_ESP, XFRM_MODE_TUNNEL, 0,
752*2f2c4c7aSAndroid Build Coastguard Worker                      net_test.GetAddressFamily(net_test.GetAddressVersion(old_saddr)),
753*2f2c4c7aSAndroid Build Coastguard Worker                      net_test.GetAddressFamily(net_test.GetAddressVersion(new_saddr))))
754*2f2c4c7aSAndroid Build Coastguard Worker    nlattrs.append((XFRMA_MIGRATE, xfrmMigrate))
755*2f2c4c7aSAndroid Build Coastguard Worker
756*2f2c4c7aSAndroid Build Coastguard Worker    if xfrm_if_id is not None:
757*2f2c4c7aSAndroid Build Coastguard Worker      nlattrs.append((XFRMA_IF_ID, struct.pack("=I", xfrm_if_id)))
758*2f2c4c7aSAndroid Build Coastguard Worker
759*2f2c4c7aSAndroid Build Coastguard Worker    for selector in selectors:
760*2f2c4c7aSAndroid Build Coastguard Worker      self.SendXfrmNlRequest(XFRM_MSG_MIGRATE,
761*2f2c4c7aSAndroid Build Coastguard Worker                             XfrmUserpolicyId(sel=selector, dir=direction), nlattrs)
762*2f2c4c7aSAndroid Build Coastguard Worker
763*2f2c4c7aSAndroid Build Coastguard Worker    # UPDSA is called exclusively to update the set_mark=new_output_mark.
764*2f2c4c7aSAndroid Build Coastguard Worker    self.AddSaInfo(new_saddr, new_daddr, spi, XFRM_MODE_TUNNEL, 0, encryption,
765*2f2c4c7aSAndroid Build Coastguard Worker                   auth_trunc, aead, encap, None, new_output_mark, True, xfrm_if_id)
766*2f2c4c7aSAndroid Build Coastguard Worker
767*2f2c4c7aSAndroid Build Coastguard Worker
768*2f2c4c7aSAndroid Build Coastguard Workerif __name__ == "__main__":
769*2f2c4c7aSAndroid Build Coastguard Worker  x = Xfrm()
770*2f2c4c7aSAndroid Build Coastguard Worker  print(x.DumpSaInfo())
771*2f2c4c7aSAndroid Build Coastguard Worker  print(x.DumpPolicyInfo())
772