Compare commits

...

59 Commits

Author SHA1 Message Date
Sukchan Lee
e7c261d0d3 Release v2.1.5 2021-02-02 14:50:15 -05:00
Sukchan Lee
e7cb25ac9b asn1c: MME crash is resolved (#783) 2021-02-02 14:27:03 -05:00
Sukchan Lee
f47f65a51c fix: asn1c decode problem for NGReset (#773) 2021-02-02 13:33:09 -05:00
Sukchan Lee
0311d2255c Oops! remove debug info 2021-02-01 10:17:49 -05:00
Sukchan Lee
d9417be9a6 feat: Handling Duplicated PDU Session ID
TS29.502 5.2.2.3.11 AMF requested PDU Session Release due to duplciated
PDU Session Id
2021-02-01 10:14:27 -05:00
Sukchan Lee
373ba1452f log: update debug info for S1AP/NGAP (#785) 2021-02-01 08:52:22 -05:00
smartVan
848b7ffc29 modify handover request and uplink ran status transfer debug info (#785) 2021-02-01 00:50:22 -05:00
Sukchan Lee
ff5236f3e0 feat: Indirect Data Forwarding in N2-Handover 2021-01-31 23:01:15 -05:00
Sukchan Lee
388e64213f etc: miscellaneous work (#779)
o Check IMEISV length == 16 digits
o Add Relative Capabity comment in the configuration file
2021-01-29 00:10:17 -05:00
Sukchan Lee
49a9e58efe feat: Add N2-Handover 2021-01-28 14:23:54 -05:00
Sukchan Lee
0fc5190a09 etc: coding convection (#778) 2021-01-28 14:23:22 -05:00
smartVan
19014a3a25 modify udr smf selection subscription data (#778) 2021-01-28 14:18:02 -05:00
Sukchan Lee
ada01fca8f spec: S1AP/NGAP update to v16.4.0(2021-01-04) 2021-01-24 23:43:42 -05:00
Sukchan Lee
61778f9142 fix: UE Context Request IE handling (#771) 2021-01-23 13:42:59 -05:00
Sukchan Lee
776d323a16 fix: Change UE Context Request IE handling (#771)
Previously, AMF would sends PDUSessionResourceSetupRequest
when the following conditions were met:
- gNB didn't send UE Context Request IE of InitialUEMessage
- AMF should send SMF generated TRANSFER message(PDU_RES_SETUP_REQ)
to the gNB

However, in issues #771, the gNB did not accept
PDUSessionResourceSetupRequest. Perhaps the gNB engineer thought
that if gNB needs to send data traffic to the UE, AMF should send
an InitialContextSetupRequest regardless of UE Context Request IE.
This is because gNB requires the kgNB security context
for data connection.

So, in this case, Open5GS-AMF decided to send
an InitialContexSetupRequest regardless of
whether it received UE Context Request IE of InitialUEMessage.
2021-01-23 11:56:04 -05:00
Sukchan Lee
9eac90252e fix: AMF/SMF/UDM crash issues resolved (#770/#771) 2021-01-22 22:17:01 -05:00
Sukchan Lee
708784e222 fix: User Location in UplinkNASTrasnport (#772)
- Based on pull request #772
- Add 4G EPC User Location Information handling
- Copy ran_ue/enb_ue context to amf_ue/mme_ue context
2021-01-20 10:03:32 -05:00
smartVan
50db1aaeb1 handle user location in ngap uplink nas transport (#772) 2021-01-20 09:27:57 -05:00
Sukchan Lee
8e29eb2417 Update document for v2.1.4 2021-01-18 21:35:08 -05:00
Sukchan Lee
0552bc49c9 Release v2.1.4 2021-01-18 19:16:24 -05:00
Sukchan Lee
c9363b1320 5gc: Paging was added 2021-01-18 11:48:35 -05:00
Sukchan Lee
408c378b94 doc: update sponsor link 2021-01-13 08:38:24 -05:00
Sukchan Lee
bfa6eae71c Oops! remove style tag 2021-01-11 23:53:40 -05:00
Sukchan Lee
55e9f08430 Add special sponsors 2021-01-11 11:10:17 -05:00
Supreeth Herle
1c13d7f5ec Legacy support for pre-release LTE 11 devices while performing VoLTE call (#757)
* AAR Media-Sub-Component modification for more UEs support

* Introduce parameter for legacy support for pre-release LTE 11 devices to do calling

IE (IPV4-local-addr field ) is not supported on
the LTE pre release-11 UEs. In order for the call
to work the local address in packet filter must
be replaced by any.

Parameter: no_ipv4v6_local_addr_in_packet_filter
2021-01-11 08:03:52 -05:00
Sukchan Lee
8d0ce5b03c Oops! Remove bearer after sending reject (#755) 2021-01-11 00:01:28 -05:00
Sukchan Lee
5fb0611cb2 fix: Derive ESM cause from GTP-Cause (#755) 2021-01-10 23:36:12 -05:00
Sukchan Lee
d6ed13968d Release v2.1.3 2021-01-08 23:22:22 -05:00
Sukchan Lee
f15d2c96fe remove math library for time string conversion 2021-01-08 23:16:54 -05:00
Sukchan Lee
508a78d43b Update document for v2.1.3 2021-01-08 22:58:23 -05:00
Sukchan Lee
f250b6e411 Release v2.1.3 2021-01-08 22:48:43 -05:00
Sukchan Lee
d17ea0f135 fix: update test code 2021-01-08 22:30:31 -05:00
Sukchan Lee
b4358fe703 fix: Add dedicated bearer activation reject (#755) 2021-01-08 15:09:02 -05:00
Sukchan Lee
e531ccab5a fix: The SBI time string converting error in 32bit 2021-01-08 10:42:51 -05:00
Sukchan Lee
a0ebf20c88 Release v2.1.2 2021-01-08 00:30:45 -05:00
Sukchan Lee
31cc259ee4 fix: release error 2021-01-08 00:24:00 -05:00
Sukchan Lee
e803b01d9c Update document for v2.1.2 2021-01-07 23:39:17 -05:00
Sukchan Lee
0c61e7b70b Release v2.1.2 2021-01-07 23:07:09 -05:00
Sukchan Lee
80e337b465 fix: update to avoid MME crash (#721) 2021-01-07 23:01:02 -05:00
Sukchan Lee
6946dc4998 fix: update to avoid MME crash (#708) 2021-01-07 22:41:13 -05:00
Sukchan Lee
7b29cdf898 Handling UEContextRequest of InitialUEMessage 2021-01-07 22:26:06 -05:00
Sukchan Lee
7dd4609c0f fix: increase mempool to support 1024UEs (#753) 2021-01-07 13:18:45 -05:00
smartVan
060d2a08f5 remove repeated qer in handling create pdr (#749) 2021-01-06 23:32:12 -05:00
Sukchan Lee
c9cfc4cf6e etc: update debug message 2021-01-04 23:24:22 -05:00
Sukchan Lee
a96d3ca0fa feat: Add multiple session 2021-01-03 23:29:01 -05:00
Sukchan Lee
1238b30526 Oops! remove test code 2021-01-03 01:07:09 -05:00
Sukchan Lee
70a7bac6b2 feat: Add 5G Core Xn Handover (#726) 2021-01-03 00:50:59 -05:00
Sukchan Lee
b329b09573 fix: add SCTP ppid and stream_no (#743) 2021-01-02 10:03:35 -05:00
Sukchan Lee
88346c0141 fix: SBI heartbeat timer usage changed (#741) 2021-01-01 15:56:46 -05:00
Sukchan Lee
b35eb9fcf4 fix: Receive HTTP2 message up to 8192bytes (#738) 2020-12-31 22:36:33 -05:00
Sukchan Lee
79b0552bb0 test: for checking issues #736 2020-12-31 21:55:11 -05:00
Sukchan Lee
235a041b8d feat: Add dedicated QoS flow 2020-12-31 21:07:08 -05:00
Sukchan Lee
65aea5ebf2 test: Use milliseconds in RFC3339 (#727) 2020-12-29 13:26:36 -05:00
Sukchan Lee
4115799c2a fix: NRF notification send all information (#737) 2020-12-28 23:36:02 -05:00
Sukchan Lee
efd1780745 fix: update NRF issues (#727,#728,#729,#730) 2020-12-24 15:41:31 -05:00
Kenny Barlee
dcec18a3d8 Doc update - 01 Quickstart (#731)
* text update 01-quickstart

* text update, diagrams 01-quickstart
2020-12-23 16:25:26 -05:00
Sukchan Lee
371e22c96b fix: AMF sets default DNN if UE does not send it. 2020-12-21 14:49:05 -05:00
Tim Gates
171f15f684 docs: fix simple typo, speciic -> specific (#724)
There is a small typo in lib/asn1c/common/constr_TYPE.h.

Should read `specific` rather than `speciic`.
2020-12-19 16:10:00 -05:00
Sukchan Lee
ef3e7b2528 docs: update release notes for v2.1.1 2020-12-16 23:11:19 -05:00
3461 changed files with 310523 additions and 99087 deletions

View File

@@ -3,13 +3,22 @@
If you find Open5GS useful for work, please consider supporting this Open Source project by [Becoming a sponsor](https://github.com/sponsors/acetcom). To manage the funding transactions transparently, you can donate through [OpenCollective](https://opencollective.com/open5gs). If you find Open5GS useful for work, please consider supporting this Open Source project by [Becoming a sponsor](https://github.com/sponsors/acetcom). To manage the funding transactions transparently, you can donate through [OpenCollective](https://opencollective.com/open5gs).
<h3 align="center">Special Sponsor</h3> <h3 align="center">Special Sponsor</h3>
<!--special start--> <table>
<tbody>
<p align="center"> <tr>
<td align="center" valign="middle">
<a href="https://nextepc.com/" target="_blank"> <a href="https://nextepc.com/" target="_blank">
<img width="260px" src="https://open5gs.org/assets/img/nextepc_logo.jpg"> <img width="260px" src="https://open5gs.org/assets/img/nextepc_logo.jpg">
</a> </a>
</p> </td>
<td align="center" valign="middle">
<a href="https://sdr.eee.strath.ac.uk/" target="_blank">
<img width="260px" src="https://open5gs.org/assets/img/strath.png">
</a>
</td>
</tr>
</tbody>
</table>
<h3 align="center">Sponsors</h3> <h3 align="center">Sponsors</h3>
<table> <table>
@@ -38,9 +47,11 @@ If you find Open5GS useful for work, please consider supporting this Open Source
If you don't understand something about Open5GS, the [https://open5gs.org/open5gs/docs/](https://open5gs.org/open5gs/docs/) is a great place to look for answers. If you don't understand something about Open5GS, the [https://open5gs.org/open5gs/docs/](https://open5gs.org/open5gs/docs/) is a great place to look for answers.
## Technical Discussion ## Community
Problem with Open5GS can be filed as [issues](https://github.com/open5gs/open5gs/issues) in this repository. Voice and text chat are available in Open5GS's [Discord](https://discordapp.com/) workspace. Use [this link](https://discord.gg/GreNkuc) to get started. - Problem with Open5GS can be filed as [issues](https://github.com/open5gs/open5gs/issues) in this repository.
- Other topics related to this project are happening on the [discussions](https://github.com/open5gs/open5gs/discussions).
- Voice and text chat are available in Open5GS's [Discord](https://discordapp.com/) workspace. Use [this link](https://discord.gg/GreNkuc) to get started.
## Contributing ## Contributing

View File

@@ -9,6 +9,7 @@ parameter:
# no_upf: true # no_upf: true
# no_ausf: true # no_ausf: true
# no_udm: true # no_udm: true
# no_pcf: true
# no_udr: true # no_udr: true
# no_mme: true # no_mme: true
# no_sgwc: true # no_sgwc: true

View File

@@ -9,6 +9,7 @@ parameter:
# no_upf: true # no_upf: true
# no_ausf: true # no_ausf: true
# no_udm: true # no_udm: true
# no_pcf: true
# no_udr: true # no_udr: true
# no_mme: true # no_mme: true
# no_sgwc: true # no_sgwc: true
@@ -97,9 +98,9 @@ sgwc:
- addr: 127.0.0.3 - addr: 127.0.0.3
smf: smf:
sbi: # sbi:
- addr: 127.0.0.4 # - addr: 127.0.0.4
port: 7777 # port: 7777
gtpc: gtpc:
- addr: 127.0.0.4 - addr: 127.0.0.4
- addr: ::1 - addr: ::1
@@ -211,12 +212,12 @@ pcrf:
- identity: smf.localdomain - identity: smf.localdomain
addr: 127.0.0.4 addr: 127.0.0.4
nrf: #nrf:
sbi: # sbi:
- addr: # - addr:
- 127.0.0.10 # - 127.0.0.10
- ::1 # - ::1
port: 7777 # port: 7777
ausf: ausf:
sbi: sbi:

View File

@@ -38,6 +38,7 @@ example_conf = '''
310014.yaml 310014.yaml
csfb.yaml csfb.yaml
volte.yaml volte.yaml
vonr.yaml
minimal.yaml minimal.yaml
srslte.yaml srslte.yaml
sample.yaml sample.yaml

View File

@@ -9,6 +9,7 @@ parameter:
# no_upf: true # no_upf: true
# no_ausf: true # no_ausf: true
# no_udm: true # no_udm: true
# no_pcf: true
# no_udr: true # no_udr: true
# no_mme: true # no_mme: true
# no_sgwc: true # no_sgwc: true

View File

@@ -160,6 +160,10 @@ logger:
# #
# amf_name: amf1.open5gs.amf.5gc.mnc70.mcc901.3gppnetwork.org # amf_name: amf1.open5gs.amf.5gc.mnc70.mcc901.3gppnetwork.org
# #
# <Relative Capacity> - Default(255)
#
# relative_capacity: 100
#
amf: amf:
sbi: sbi:
- addr: 127.0.0.5 - addr: 127.0.0.5
@@ -260,19 +264,20 @@ max:
# #
# pool: # pool:
# #
# o The Number of Default Memory Pool Size # o The default memory pool size was set assuming 1024 UEs.
# To connect more UEs, you need to increase the size further.
# #
# - Pool-size 128 => 32768 Number # - Pool-size 128 => 65536 Number
# - Pool-size 256 => 4096 Number # - Pool-size 256 => 8192 Number
# - Pool-size 512 => 2048 Number # - Pool-size 512 => 4096 Number
# - Pool-size 1024 => 1024 Number # - Pool-size 1024 => 1024 Number
# - Pool-size 2048 => 512 Number # - Pool-size 2048 => 512 Number
# - Pool-size 8192 => 128 Number # - Pool-size 8192 => 128 Number
# - Pool-size 1024*1024 => 8 Number # - Pool-size 1024*1024 => 8 Number
# #
# 128: 32768 # 128: 65536
# 256: 4096 # 256: 8192
# 512: 2048 # 512: 4096
# 1024: 1024 # 1024: 1024
# 2048: 512 # 2048: 512
# 8192: 128 # 8192: 128
@@ -283,19 +288,28 @@ pool:
# #
# time: # time:
# #
# o NF Instance Heartbeat (Default : 10 seconds) # o NF Instance Heartbeat (Default : 0)
# NFs will not send heart-beat timer in NFProfile
# NRF will send heart-beat timer in NFProfile
# #
# o NF Instance Heartbeat (Disabled) # o NF Instance Heartbeat (20 seconds)
# nf_instance: # NFs will send heart-beat timer (20 seconds) in NFProfile
# heartbeat: 0 # NRF can change heart-beat timer in NFProfile
# #
# o NF Instance Heartbeat (10 seconds)
# nf_instance: # nf_instance:
# heartbeat: 10 # heartbeat: 20
# #
# o Message Wait Duration (Default : 10,000 ms = 10 seconds) # o Message Wait Duration (Default : 10,000 ms = 10 seconds)
# #
# o Message Wait Duration (3000 ms) # o Message Wait Duration (3000 ms)
# message: # message:
# duration: 3000 # duration: 3000
#
# o Handover Wait Duration (Default : 300 ms)
# Time to wait for AMF to send UEContextReleaseCommand
# to the source gNB after receiving HandoverNotify
#
# o Handover Wait Duration (500ms)
# handover:
# duration: 500
time: time:

View File

@@ -136,19 +136,20 @@ max:
# #
# pool: # pool:
# #
# o The Number of Default Memory Pool Size # o The default memory pool size was set assuming 1024 UEs.
# To connect more UEs, you need to increase the size further.
# #
# - Pool-size 128 => 32768 Number # - Pool-size 128 => 65536 Number
# - Pool-size 256 => 4096 Number # - Pool-size 256 => 8192 Number
# - Pool-size 512 => 2048 Number # - Pool-size 512 => 4096 Number
# - Pool-size 1024 => 1024 Number # - Pool-size 1024 => 1024 Number
# - Pool-size 2048 => 512 Number # - Pool-size 2048 => 512 Number
# - Pool-size 8192 => 128 Number # - Pool-size 8192 => 128 Number
# - Pool-size 1024*1024 => 8 Number # - Pool-size 1024*1024 => 8 Number
# #
# 128: 32768 # 128: 65536
# 256: 4096 # 256: 8192
# 512: 2048 # 512: 4096
# 1024: 1024 # 1024: 1024
# 2048: 512 # 2048: 512
# 8192: 128 # 8192: 128
@@ -159,15 +160,16 @@ pool:
# #
# time: # time:
# #
# o NF Instance Heartbeat (Default : 10 seconds) # o NF Instance Heartbeat (Default : 0)
# NFs will not send heart-beat timer in NFProfile
# NRF will send heart-beat timer in NFProfile
# #
# o NF Instance Heartbeat (Disabled) # o NF Instance Heartbeat (20 seconds)
# nf_instance: # NFs will send heart-beat timer (20 seconds) in NFProfile
# heartbeat: 0 # NRF can change heart-beat timer in NFProfile
# #
# o NF Instance Heartbeat (10 seconds)
# nf_instance: # nf_instance:
# heartbeat: 10 # heartbeat: 20
# #
# o Message Wait Duration (Default : 10,000 ms = 10 seconds) # o Message Wait Duration (Default : 10,000 ms = 10 seconds)
# #

View File

@@ -62,19 +62,20 @@ max:
# #
# pool: # pool:
# #
# o The Number of Default Memory Pool Size # o The default memory pool size was set assuming 1024 UEs.
# To connect more UEs, you need to increase the size further.
# #
# - Pool-size 128 => 32768 Number # - Pool-size 128 => 65536 Number
# - Pool-size 256 => 4096 Number # - Pool-size 256 => 8192 Number
# - Pool-size 512 => 2048 Number # - Pool-size 512 => 4096 Number
# - Pool-size 1024 => 1024 Number # - Pool-size 1024 => 1024 Number
# - Pool-size 2048 => 512 Number # - Pool-size 2048 => 512 Number
# - Pool-size 8192 => 128 Number # - Pool-size 8192 => 128 Number
# - Pool-size 1024*1024 => 8 Number # - Pool-size 1024*1024 => 8 Number
# #
# 128: 32768 # 128: 65536
# 256: 4096 # 256: 8192
# 512: 2048 # 512: 4096
# 1024: 1024 # 1024: 1024
# 2048: 512 # 2048: 512
# 8192: 128 # 8192: 128

View File

@@ -201,6 +201,10 @@ logger:
# #
# mme_name: open5gs-mme0 # mme_name: open5gs-mme0
# #
# <Relative Capacity> - Default(255)
#
# relative_capacity: 100
#
mme: mme:
freeDiameter: @sysconfdir@/freeDiameter/mme.conf freeDiameter: @sysconfdir@/freeDiameter/mme.conf
s1ap: s1ap:
@@ -369,19 +373,20 @@ max:
# #
# pool: # pool:
# #
# o The Number of Default Memory Pool Size # o The default memory pool size was set assuming 1024 UEs.
# To connect more UEs, you need to increase the size further.
# #
# - Pool-size 128 => 32768 Number # - Pool-size 128 => 65536 Number
# - Pool-size 256 => 4096 Number # - Pool-size 256 => 8192 Number
# - Pool-size 512 => 2048 Number # - Pool-size 512 => 4096 Number
# - Pool-size 1024 => 1024 Number # - Pool-size 1024 => 1024 Number
# - Pool-size 2048 => 512 Number # - Pool-size 2048 => 512 Number
# - Pool-size 8192 => 128 Number # - Pool-size 8192 => 128 Number
# - Pool-size 1024*1024 => 8 Number # - Pool-size 1024*1024 => 8 Number
# #
# 128: 32768 # 128: 65536
# 256: 4096 # 256: 8192
# 512: 2048 # 512: 4096
# 1024: 1024 # 1024: 1024
# 2048: 512 # 2048: 512
# 8192: 128 # 8192: 128
@@ -412,4 +417,12 @@ sctp:
# o Message Wait Duration (3000 ms) # o Message Wait Duration (3000 ms)
# message: # message:
# duration: 3000 # duration: 3000
#
# o Handover Wait Duration (Default : 300 ms)
# Time to wait for MME to send UEContextReleaseCommand
# to the source eNB after receiving HandoverNotify
#
# o Handover Wait Duration (500ms)
# handover:
# duration: 500
time: time:

View File

@@ -108,19 +108,20 @@ max:
# #
# pool: # pool:
# #
# o The Number of Default Memory Pool Size # o The default memory pool size was set assuming 1024 UEs.
# To connect more UEs, you need to increase the size further.
# #
# - Pool-size 128 => 32768 Number # - Pool-size 128 => 65536 Number
# - Pool-size 256 => 4096 Number # - Pool-size 256 => 8192 Number
# - Pool-size 512 => 2048 Number # - Pool-size 512 => 4096 Number
# - Pool-size 1024 => 1024 Number # - Pool-size 1024 => 1024 Number
# - Pool-size 2048 => 512 Number # - Pool-size 2048 => 512 Number
# - Pool-size 8192 => 128 Number # - Pool-size 8192 => 128 Number
# - Pool-size 1024*1024 => 8 Number # - Pool-size 1024*1024 => 8 Number
# #
# 128: 32768 # 128: 65536
# 256: 4096 # 256: 8192
# 512: 2048 # 512: 4096
# 1024: 1024 # 1024: 1024
# 2048: 512 # 2048: 512
# 8192: 128 # 8192: 128
@@ -131,6 +132,16 @@ pool:
# #
# time: # time:
# #
# o NF Instance Heartbeat (Default : 10 seconds)
#
# o NF Instance Heartbeat (Disabled)
# nf_instance:
# heartbeat: 0
#
# o NF Instance Heartbeat (5 seconds)
# nf_instance:
# heartbeat: 5
#
# o NF Instance Validity (Default : 3600 seconds = 1 hour) # o NF Instance Validity (Default : 3600 seconds = 1 hour)
# #
# o NF Instance Validity (10 seconds) # o NF Instance Validity (10 seconds)

View File

@@ -138,19 +138,20 @@ max:
# #
# pool: # pool:
# #
# o The Number of Default Memory Pool Size # o The default memory pool size was set assuming 1024 UEs.
# To connect more UEs, you need to increase the size further.
# #
# - Pool-size 128 => 32768 Number # - Pool-size 128 => 65536 Number
# - Pool-size 256 => 4096 Number # - Pool-size 256 => 8192 Number
# - Pool-size 512 => 2048 Number # - Pool-size 512 => 4096 Number
# - Pool-size 1024 => 1024 Number # - Pool-size 1024 => 1024 Number
# - Pool-size 2048 => 512 Number # - Pool-size 2048 => 512 Number
# - Pool-size 8192 => 128 Number # - Pool-size 8192 => 128 Number
# - Pool-size 1024*1024 => 8 Number # - Pool-size 1024*1024 => 8 Number
# #
# 128: 32768 # 128: 65536
# 256: 4096 # 256: 8192
# 512: 2048 # 512: 4096
# 1024: 1024 # 1024: 1024
# 2048: 512 # 2048: 512
# 8192: 128 # 8192: 128
@@ -161,15 +162,16 @@ pool:
# #
# time: # time:
# #
# o NF Instance Heartbeat (Default : 10 seconds) # o NF Instance Heartbeat (Default : 0)
# NFs will not send heart-beat timer in NFProfile
# NRF will send heart-beat timer in NFProfile
# #
# o NF Instance Heartbeat (Disabled) # o NF Instance Heartbeat (20 seconds)
# nf_instance: # NFs will send heart-beat timer (20 seconds) in NFProfile
# heartbeat: 0 # NRF can change heart-beat timer in NFProfile
# #
# o NF Instance Heartbeat (10 seconds)
# nf_instance: # nf_instance:
# heartbeat: 10 # heartbeat: 20
# #
# o Message Wait Duration (Default : 10,000 ms = 10 seconds) # o Message Wait Duration (Default : 10,000 ms = 10 seconds)
# #

View File

@@ -46,6 +46,10 @@ pcrf:
# o Disable Stateless Address Autoconfiguration for IPv6 # o Disable Stateless Address Autoconfiguration for IPv6
# no_slaac: true # no_slaac: true
# #
# o Legacy support for pre-release LTE 11 devices to do calling
# - Replace IPv4/v6 local addr field in AAR Media-Subcomponent AVP by any
# no_ipv4v6_local_addr_in_packet_filter: true
#
parameter: parameter:
# #
@@ -61,19 +65,20 @@ max:
# #
# pool: # pool:
# #
# o The Number of Default Memory Pool Size # o The default memory pool size was set assuming 1024 UEs.
# To connect more UEs, you need to increase the size further.
# #
# - Pool-size 128 => 32768 Number # - Pool-size 128 => 65536 Number
# - Pool-size 256 => 4096 Number # - Pool-size 256 => 8192 Number
# - Pool-size 512 => 2048 Number # - Pool-size 512 => 4096 Number
# - Pool-size 1024 => 1024 Number # - Pool-size 1024 => 1024 Number
# - Pool-size 2048 => 512 Number # - Pool-size 2048 => 512 Number
# - Pool-size 8192 => 128 Number # - Pool-size 8192 => 128 Number
# - Pool-size 1024*1024 => 8 Number # - Pool-size 1024*1024 => 8 Number
# #
# 128: 32768 # 128: 65536
# 256: 4096 # 256: 8192
# 512: 2048 # 512: 4096
# 1024: 1024 # 1024: 1024
# 2048: 512 # 2048: 512
# 8192: 128 # 8192: 128

View File

@@ -143,19 +143,20 @@ max:
# #
# pool: # pool:
# #
# o The Number of Default Memory Pool Size # o The default memory pool size was set assuming 1024 UEs.
# To connect more UEs, you need to increase the size further.
# #
# - Pool-size 128 => 32768 Number # - Pool-size 128 => 65536 Number
# - Pool-size 256 => 4096 Number # - Pool-size 256 => 8192 Number
# - Pool-size 512 => 2048 Number # - Pool-size 512 => 4096 Number
# - Pool-size 1024 => 1024 Number # - Pool-size 1024 => 1024 Number
# - Pool-size 2048 => 512 Number # - Pool-size 2048 => 512 Number
# - Pool-size 8192 => 128 Number # - Pool-size 8192 => 128 Number
# - Pool-size 1024*1024 => 8 Number # - Pool-size 1024*1024 => 8 Number
# #
# 128: 32768 # 128: 65536
# 256: 4096 # 256: 8192
# 512: 2048 # 512: 4096
# 1024: 1024 # 1024: 1024
# 2048: 512 # 2048: 512
# 8192: 128 # 8192: 128

View File

@@ -134,19 +134,20 @@ max:
# #
# pool: # pool:
# #
# o The Number of Default Memory Pool Size # o The default memory pool size was set assuming 1024 UEs.
# To connect more UEs, you need to increase the size further.
# #
# - Pool-size 128 => 32768 Number # - Pool-size 128 => 65536 Number
# - Pool-size 256 => 4096 Number # - Pool-size 256 => 8192 Number
# - Pool-size 512 => 2048 Number # - Pool-size 512 => 4096 Number
# - Pool-size 1024 => 1024 Number # - Pool-size 1024 => 1024 Number
# - Pool-size 2048 => 512 Number # - Pool-size 2048 => 512 Number
# - Pool-size 8192 => 128 Number # - Pool-size 8192 => 128 Number
# - Pool-size 1024*1024 => 8 Number # - Pool-size 1024*1024 => 8 Number
# #
# 128: 32768 # 128: 65536
# 256: 4096 # 256: 8192
# 512: 2048 # 512: 4096
# 1024: 1024 # 1024: 1024
# 2048: 512 # 2048: 512
# 8192: 128 # 8192: 128

View File

@@ -313,19 +313,20 @@ max:
# #
# pool: # pool:
# #
# o The Number of Default Memory Pool Size # o The default memory pool size was set assuming 1024 UEs.
# To connect more UEs, you need to increase the size further.
# #
# - Pool-size 128 => 32768 Number # - Pool-size 128 => 65536 Number
# - Pool-size 256 => 4096 Number # - Pool-size 256 => 8192 Number
# - Pool-size 512 => 2048 Number # - Pool-size 512 => 4096 Number
# - Pool-size 1024 => 1024 Number # - Pool-size 1024 => 1024 Number
# - Pool-size 2048 => 512 Number # - Pool-size 2048 => 512 Number
# - Pool-size 8192 => 128 Number # - Pool-size 8192 => 128 Number
# - Pool-size 1024*1024 => 8 Number # - Pool-size 1024*1024 => 8 Number
# #
# 128: 32768 # 128: 65536
# 256: 4096 # 256: 8192
# 512: 2048 # 512: 4096
# 1024: 1024 # 1024: 1024
# 2048: 512 # 2048: 512
# 8192: 128 # 8192: 128
@@ -336,19 +337,29 @@ pool:
# #
# time: # time:
# #
# o NF Instance Heartbeat (Default : 10 seconds) # o NF Instance Heartbeat (Default : 0)
# NFs will not send heart-beat timer in NFProfile
# NRF will send heart-beat timer in NFProfile
# #
# o NF Instance Heartbeat (Disabled) # o NF Instance Heartbeat (20 seconds)
# nf_instance: # NFs will send heart-beat timer (20 seconds) in NFProfile
# heartbeat: 0 # NRF can change heart-beat timer in NFProfile
# #
# o NF Instance Heartbeat (10 seconds)
# nf_instance: # nf_instance:
# heartbeat: 10 # heartbeat: 20
# #
# o Message Wait Duration (Default : 10,000 ms = 10 seconds) # o Message Wait Duration (Default : 10,000 ms = 10 seconds)
# #
# o Message Wait Duration (3000 ms) # o Message Wait Duration (3000 ms)
# message: # message:
# duration: 3000 # duration: 3000
#
# o Handover Wait Duration (Default : 300 ms)
# Time to wait for SMF to send
# PFCP Session Modification Request(Remove Indirect Tunnel) to the UPF
# after sending Nsmf_PDUSession_UpdateSMContext Response(hoState:COMPLETED)
#
# o Handover Wait Duration (500ms)
# handover:
# duration: 500
time: time:

View File

@@ -136,19 +136,20 @@ max:
# #
# pool: # pool:
# #
# o The Number of Default Memory Pool Size # o The default memory pool size was set assuming 1024 UEs.
# To connect more UEs, you need to increase the size further.
# #
# - Pool-size 128 => 32768 Number # - Pool-size 128 => 65536 Number
# - Pool-size 256 => 4096 Number # - Pool-size 256 => 8192 Number
# - Pool-size 512 => 2048 Number # - Pool-size 512 => 4096 Number
# - Pool-size 1024 => 1024 Number # - Pool-size 1024 => 1024 Number
# - Pool-size 2048 => 512 Number # - Pool-size 2048 => 512 Number
# - Pool-size 8192 => 128 Number # - Pool-size 8192 => 128 Number
# - Pool-size 1024*1024 => 8 Number # - Pool-size 1024*1024 => 8 Number
# #
# 128: 32768 # 128: 65536
# 256: 4096 # 256: 8192
# 512: 2048 # 512: 4096
# 1024: 1024 # 1024: 1024
# 2048: 512 # 2048: 512
# 8192: 128 # 8192: 128
@@ -159,15 +160,16 @@ pool:
# #
# time: # time:
# #
# o NF Instance Heartbeat (Default : 10 seconds) # o NF Instance Heartbeat (Default : 0)
# NFs will not send heart-beat timer in NFProfile
# NRF will send heart-beat timer in NFProfile
# #
# o NF Instance Heartbeat (Disabled) # o NF Instance Heartbeat (20 seconds)
# nf_instance: # NFs will send heart-beat timer (20 seconds) in NFProfile
# heartbeat: 0 # NRF can change heart-beat timer in NFProfile
# #
# o NF Instance Heartbeat (10 seconds)
# nf_instance: # nf_instance:
# heartbeat: 10 # heartbeat: 20
# #
# o Message Wait Duration (Default : 10,000 ms = 10 seconds) # o Message Wait Duration (Default : 10,000 ms = 10 seconds)
# #

View File

@@ -138,19 +138,20 @@ max:
# #
# pool: # pool:
# #
# o The Number of Default Memory Pool Size # o The default memory pool size was set assuming 1024 UEs.
# To connect more UEs, you need to increase the size further.
# #
# - Pool-size 128 => 32768 Number # - Pool-size 128 => 65536 Number
# - Pool-size 256 => 4096 Number # - Pool-size 256 => 8192 Number
# - Pool-size 512 => 2048 Number # - Pool-size 512 => 4096 Number
# - Pool-size 1024 => 1024 Number # - Pool-size 1024 => 1024 Number
# - Pool-size 2048 => 512 Number # - Pool-size 2048 => 512 Number
# - Pool-size 8192 => 128 Number # - Pool-size 8192 => 128 Number
# - Pool-size 1024*1024 => 8 Number # - Pool-size 1024*1024 => 8 Number
# #
# 128: 32768 # 128: 65536
# 256: 4096 # 256: 8192
# 512: 2048 # 512: 4096
# 1024: 1024 # 1024: 1024
# 2048: 512 # 2048: 512
# 8192: 128 # 8192: 128
@@ -161,7 +162,16 @@ pool:
# #
# time: # time:
# #
# o NF Instance Heartbeat (Default : 10 seconds) # o NF Instance Heartbeat (Default : 0)
# NFs will not send heart-beat timer in NFProfile
# NRF will send heart-beat timer in NFProfile
#
# o NF Instance Heartbeat (20 seconds)
# NFs will send heart-beat timer (20 seconds) in NFProfile
# NRF can change heart-beat timer in NFProfile
#
# nf_instance:
# heartbeat: 20
# #
# o NF Instance Heartbeat (Disabled) # o NF Instance Heartbeat (Disabled)
# nf_instance: # nf_instance:

View File

@@ -219,19 +219,20 @@ max:
# #
# pool: # pool:
# #
# o The Number of Default Memory Pool Size # o The default memory pool size was set assuming 1024 UEs.
# To connect more UEs, you need to increase the size further.
# #
# - Pool-size 128 => 32768 Number # - Pool-size 128 => 65536 Number
# - Pool-size 256 => 4096 Number # - Pool-size 256 => 8192 Number
# - Pool-size 512 => 2048 Number # - Pool-size 512 => 4096 Number
# - Pool-size 1024 => 1024 Number # - Pool-size 1024 => 1024 Number
# - Pool-size 2048 => 512 Number # - Pool-size 2048 => 512 Number
# - Pool-size 8192 => 128 Number # - Pool-size 8192 => 128 Number
# - Pool-size 1024*1024 => 8 Number # - Pool-size 1024*1024 => 8 Number
# #
# 128: 32768 # 128: 65536
# 256: 4096 # 256: 8192
# 512: 2048 # 512: 4096
# 1024: 1024 # 1024: 1024
# 2048: 512 # 2048: 512
# 8192: 128 # 8192: 128

View File

@@ -9,6 +9,7 @@ parameter:
# no_upf: true # no_upf: true
# no_ausf: true # no_ausf: true
# no_udm: true # no_udm: true
# no_pcf: true
# no_udr: true # no_udr: true
# no_mme: true # no_mme: true
# no_sgwc: true # no_sgwc: true

View File

@@ -9,6 +9,7 @@ parameter:
# no_upf: true # no_upf: true
# no_ausf: true # no_ausf: true
# no_udm: true # no_udm: true
# no_pcf: true
# no_udr: true # no_udr: true
# no_mme: true # no_mme: true
# no_sgwc: true # no_sgwc: true
@@ -63,9 +64,9 @@ sgwc:
- addr: 127.0.0.3 - addr: 127.0.0.3
smf: smf:
sbi: # sbi:
- addr: 127.0.0.4 # - addr: 127.0.0.4
port: 7777 # port: 7777
gtpc: gtpc:
- addr: 127.0.0.4 - addr: 127.0.0.4
- addr: ::1 - addr: ::1
@@ -177,12 +178,12 @@ pcrf:
- identity: smf.localdomain - identity: smf.localdomain
addr: 127.0.0.4 addr: 127.0.0.4
nrf: #nrf:
sbi: # sbi:
- addr: # - addr:
- 127.0.0.10 # - 127.0.0.10
- ::1 # - ::1
port: 7777 # port: 7777
ausf: ausf:
sbi: sbi:

View File

@@ -9,6 +9,7 @@ parameter:
# no_upf: true # no_upf: true
# no_ausf: true # no_ausf: true
# no_udm: true # no_udm: true
# no_pcf: true
# no_udr: true # no_udr: true
# no_mme: true # no_mme: true
# no_sgwc: true # no_sgwc: true
@@ -63,9 +64,9 @@ sgwc:
- addr: 127.0.0.3 - addr: 127.0.0.3
smf: smf:
sbi: # sbi:
- addr: 127.0.0.4 # - addr: 127.0.0.4
port: 7777 # port: 7777
gtpc: gtpc:
- addr: 127.0.0.4 - addr: 127.0.0.4
- addr: ::1 - addr: ::1
@@ -182,12 +183,12 @@ pcrf:
- identity: pcscf.localdomain - identity: pcscf.localdomain
addr: 127.0.0.1 addr: 127.0.0.1
nrf: #nrf:
sbi: # sbi:
- addr: # - addr:
- 127.0.0.10 # - 127.0.0.10
- ::1 # - ::1
port: 7777 # port: 7777
ausf: ausf:
sbi: sbi:

211
configs/vonr.yaml.in Normal file
View File

@@ -0,0 +1,211 @@
db_uri: mongodb://localhost/open5gs
logger:
parameter:
# no_nrf: true
# no_amf: true
# no_smf: true
# no_upf: true
# no_ausf: true
# no_udm: true
# no_pcf: true
# no_udr: true
# no_mme: true
# no_sgwc: true
# no_sgwu: true
# no_pcrf: true
# no_hss: true
mme:
freeDiameter:
identity: mme.localdomain
realm: localdomain
listen_on: 127.0.0.2
load_extension:
- module: @freediameter_extensions_builddir@/dbg_msg_dumps.fdx
conf: 0x8888
- module: @freediameter_extensions_builddir@/dict_rfc5777.fdx
- module: @freediameter_extensions_builddir@/dict_mip6i.fdx
- module: @freediameter_extensions_builddir@/dict_nasreq.fdx
- module: @freediameter_extensions_builddir@/dict_nas_mipv6.fdx
- module: @freediameter_extensions_builddir@/dict_dcca.fdx
- module: @freediameter_extensions_builddir@/dict_dcca_3gpp.fdx
connect:
- identity: hss.localdomain
addr: 127.0.0.8
s1ap:
- addr: 127.0.0.2
gtpc:
- addr: 127.0.0.2
gummei:
plmn_id:
mcc: 901
mnc: 70
mme_gid: 2
mme_code: 1
tai:
plmn_id:
mcc: 901
mnc: 70
tac: 1
security:
integrity_order : [ EIA2, EIA1, EIA0 ]
ciphering_order : [ EEA0, EEA1, EEA2 ]
network_name:
full: Open5GS
sgwc:
gtpc:
- addr: 127.0.0.3
pfcp:
- addr: 127.0.0.3
smf:
sbi:
- addr: 127.0.0.4
port: 7777
gtpc:
- addr: 127.0.0.4
- addr: ::1
pfcp:
- addr: 127.0.0.4
pdn:
- addr: 10.45.0.1/16
- addr: cafe::1/64
dns:
- 8.8.8.8
- 8.8.4.4
- 2001:4860:4860::8888
- 2001:4860:4860::8844
p-cscf:
- 127.0.0.1
- ::1
mtu: 1400
freeDiameter:
identity: smf.localdomain
realm: localdomain
listen_on: 127.0.0.4
load_extension:
- module: @freediameter_extensions_builddir@/dbg_msg_dumps.fdx
conf: 0x8888
- module: @freediameter_extensions_builddir@/dict_rfc5777.fdx
- module: @freediameter_extensions_builddir@/dict_mip6i.fdx
- module: @freediameter_extensions_builddir@/dict_nasreq.fdx
- module: @freediameter_extensions_builddir@/dict_nas_mipv6.fdx
- module: @freediameter_extensions_builddir@/dict_dcca.fdx
- module: @freediameter_extensions_builddir@/dict_dcca_3gpp.fdx
connect:
- identity: pcrf.localdomain
addr: 127.0.0.9
amf:
sbi:
- addr: 127.0.0.5
port: 7777
ngap:
- addr: 127.0.0.5
guami:
- plmn_id:
mcc: 901
mnc: 70
amf_id:
region: 2
set: 1
tai:
- plmn_id:
mcc: 901
mnc: 70
tac: 1
plmn_support:
- plmn_id:
mcc: 901
mnc: 70
s_nssai:
- sst: 1
security:
integrity_order : [ NIA2, NIA1, NIA0 ]
ciphering_order : [ NEA0, NEA1, NEA2 ]
network_name:
full: Open5GS
amf_name: open5gs-amf0
sgwu:
gtpu:
- addr: 127.0.0.6
pfcp:
- addr: 127.0.0.6
upf:
pfcp:
- addr: 127.0.0.7
gtpu:
- addr: 127.0.0.7
pdn:
- addr: 10.45.0.1/16
- addr: cafe::1/64
hss:
freeDiameter:
identity: hss.localdomain
realm: localdomain
listen_on: 127.0.0.8
load_extension:
- module: @freediameter_extensions_builddir@/dbg_msg_dumps.fdx
conf: 0x8888
- module: @freediameter_extensions_builddir@/dict_rfc5777.fdx
- module: @freediameter_extensions_builddir@/dict_mip6i.fdx
- module: @freediameter_extensions_builddir@/dict_nasreq.fdx
- module: @freediameter_extensions_builddir@/dict_nas_mipv6.fdx
- module: @freediameter_extensions_builddir@/dict_dcca.fdx
- module: @freediameter_extensions_builddir@/dict_dcca_3gpp.fdx
connect:
- identity: mme.localdomain
addr: 127.0.0.2
pcrf:
freeDiameter:
identity: pcrf.localdomain
realm: localdomain
listen_on: 127.0.0.9
load_extension:
- module: @freediameter_extensions_builddir@/dbg_msg_dumps.fdx
conf: 0x8888
- module: @freediameter_extensions_builddir@/dict_rfc5777.fdx
- module: @freediameter_extensions_builddir@/dict_mip6i.fdx
- module: @freediameter_extensions_builddir@/dict_nasreq.fdx
- module: @freediameter_extensions_builddir@/dict_nas_mipv6.fdx
- module: @freediameter_extensions_builddir@/dict_dcca.fdx
- module: @freediameter_extensions_builddir@/dict_dcca_3gpp.fdx
connect:
- identity: smf.localdomain
addr: 127.0.0.4
- identity: pcscf.localdomain
addr: 127.0.0.1
nrf:
sbi:
- addr:
- 127.0.0.10
- ::1
port: 7777
ausf:
sbi:
- addr: 127.0.0.11
port: 7777
udm:
sbi:
- addr: 127.0.0.12
port: 7777
pcf:
sbi:
- addr: 127.0.0.13
port: 7777
udr:
sbi:
- addr: 127.0.0.20
port: 7777

72
debian/changelog vendored
View File

@@ -1,3 +1,75 @@
open5gs (2.1.5) unstable; urgency=medium
* Bug Fixed
-- Sukchan Lee <acetcom@gmail.com> Tue, 02 Feb 2021 14:47:59 -0500
open5gs (2.1.5~bionic) bionic; urgency=medium
* Bug Fixed
-- Sukchan Lee <acetcom@gmail.com> Tue, 02 Feb 2021 14:46:57 -0500
open5gs (2.1.5~focal) focal; urgency=medium
* Bug Fixed
-- Sukchan Lee <acetcom@gmail.com> Tue, 02 Feb 2021 14:45:48 -0500
open5gs (2.1.4) unstable; urgency=medium
* Paging was added
-- Sukchan Lee <acetcom@gmail.com> Mon, 18 Jan 2021 19:14:26 -0500
open5gs (2.1.4~bionic) bionic; urgency=medium
* Paging was added
-- Sukchan Lee <acetcom@gmail.com> Mon, 18 Jan 2021 19:13:26 -0500
open5gs (2.1.4~focal) focal; urgency=medium
* Paging was added
-- Sukchan Lee <acetcom@gmail.com> Mon, 18 Jan 2021 19:12:06 -0500
open5gs (2.1.3) unstable; urgency=medium
* Bug Fixed
-- Sukchan Lee <acetcom@gmail.com> Fri, 08 Jan 2021 23:20:33 -0500
open5gs (2.1.3~bionic1) bionic; urgency=medium
* Bug Fixed
-- Sukchan Lee <acetcom@gmail.com> Fri, 08 Jan 2021 23:19:22 -0500
open5gs (2.1.3~focal1) focal; urgency=medium
* Bug Fixed
-- Sukchan Lee <acetcom@gmail.com> Fri, 08 Jan 2021 23:17:48 -0500
open5gs (2.1.2) unstable; urgency=medium
* Bug Fixed
-- Sukchan Lee <acetcom@gmail.com> Fri, 08 Jan 2021 00:28:16 -0500
open5gs (2.1.2~bionic1) bionic; urgency=medium
* Bug Fixed
-- Sukchan Lee <acetcom@gmail.com> Fri, 08 Jan 2021 00:27:09 -0500
open5gs (2.1.2~focal1) focal; urgency=medium
* Bug Fixed
-- Sukchan Lee <acetcom@gmail.com> Fri, 08 Jan 2021 00:25:31 -0500
open5gs (2.1.1) unstable; urgency=medium open5gs (2.1.1) unstable; urgency=medium
* Bug Fixed * Bug Fixed

2
debian/rules vendored
View File

@@ -14,4 +14,4 @@ override_dh_install:
dh_install --sourcedir=obj-$(DEB_HOST_GNU_TYPE) dh_install --sourcedir=obj-$(DEB_HOST_GNU_TYPE)
override_dh_auto_test: override_dh_auto_test:
cd obj-$(DEB_HOST_GNU_TYPE) && meson test --suite unit cd obj-$(DEB_HOST_GNU_TYPE) && meson test -v --suite unit

View File

@@ -2,11 +2,72 @@
title: Quickstart title: Quickstart
--- ---
**Note:** Open5GS supports installation of packages in *Debian/Ubuntu and openSUSE* environments. *CentOS, Fedora, and Mac OSX* require you to [build with source code]({{ site.url }}{{ site.baseurl }}/docs/guide/02-building-open5gs-from-sources) ## 1. Introduction to Open5GS
---
Welcome! If you want to set up your first Open5GS core you have come to the right place. Before we get started, we'll spend a moment to understand the basic architecture of the software.
**TL;DR:** Open5GS contains a series of software components and network functions that implement the 4G/ 5G NSA and 5G SA core functions. If you know what each of these do already and how they interface with each other, skip to section 2.
{: .notice--info}
<style>
img {
max-width: 100%;
height: auto;
}
</style>
![Open5GS Diagram]({{ site.url }}{{ site.baseurl }}/assets/images/Open5GS_CUPS-01.jpg)
[[Higher quality PDF diagram available HERE]]({{ site.url }}{{ site.baseurl }}/assets/images/Open5GS_CUPS-01.pdf)
#### 4G/ 5G NSA Core
The Open5GS 4G/ 5G NSA Core contains the following components:
* MME - Mobility Management Entity
* HSS - Home Subscriber Server
* PCRF - Policy and Charging Rules Function
* SGWC - Serving Gateway Control Plane
* SGWU - Serving Gateway User Plane
* PGWC/SMF - Packet Gateway Control Plane / (component contained in Open5GS SMF)
* PGWU/UPF - Packet Gateway User Plane / (component contained in Open5GS UPF)
The core has two main planes: the control plane and the user plane. These are physically separated in Open5GS as CUPS (control/ user plane separation) is implemented.
The MME is the main **control plane** hub of the core. It primarily manages sessions, mobilty, paging and bearers. It links to the HSS, which generates SIM authentication vectors and holds the subscriber profile; and also to the SGWC and PGWC/SMF, which are the control planes of the gateway servers. All the eNBs in the mobile network (4G basestations) connect to the MME. The final element of the control plane is the PCRF, which sits in-between the PGWC/SMF and the HSS, and handles charging and enforces subscriber policies.
The **user plane** carries user data packets between the eNB/ NSA gNB (5G NSA basestations) and the external WAN. The two user plane core components are the SGWU and PGWU/UPF. Each of these connect back to their control plane counterparts. eNBs/ NSA gNBs connect to the SGWU, which connects to the PGWU/UPF, and on to the WAN. *By having the control and user planes physically separated like this, it means you can deploy multiple user plane servers in the field (eg somewhere with a high speed Internet connection), whilst keeping control functionality centralised. This enables support of MEC use cases, for example.*
All of these Open5GS components have config files. Each config file contains the component's IP bind addresses/ local Interface names **and** the IP addresses/ DNS names of the other components it needs to connect to. We'll come back to this in Section 3.
#### 5G SA Core
The Open5GS 5G SA Core contains the following functions:
* AMF - Access and Mobility Management Function
* SMF - Session Management Function
* UPF - User Plane Function
* AUSF - Authentication Server Function
* NRF - NF Repository Function
* UDM - Unified Data Management
* UDR - Unified Data Repository
* PCF - Policy and Charging Function
The 5G SA core works in a different way to the 4G core - it uses a **Service Based Architecture** (SBI). **Control plane** functions are configured to register with the NRF, and the NRF then helps them discover the other core functions. Running through the other functions: The AMF handles connection and mobility management; a subset of what the 4G MME is tasked with. gNBs (5G basestations) connect to the AMF. The UDM, AUSF and UDR carry out similar operations as the 4G HSS, generating SIM authentication vectors and holding the subscriber profile. Session management is all handled by the SMF (previously the responsibility of the 4G MME/ SGWC/ PGWC). Finally there is the PCF, used for charging and enforcing subscriber policies.
The 5G SA core **user plane** is much simpler, as it only contains a single function. The UPF carries user data packets between the gNB and the external WAN. It connects back to the SMF too.
With the exception of the SMF and UPF, all config files for the 5G SA core functions only contain the function's IP bind addresses/ local Interface names and the IP address/ DNS name of the NRF.
## 2. Install Open5GS with a Package Manager
---
**Note:** Package managers can be used to install Open5GS in *Debian/Ubuntu and openSUSE* environments (for major and minor builds). *CentOS, Fedora, and Mac OSX* require you to [build with source code]({{ site.url }}{{ site.baseurl }}/docs/guide/02-building-open5gs-from-sources).
{: .notice--warning}
**Note:** Nighly builds are offered by [Osmocom](https://osmocom.org) on [OBS](https://build.opensuse.org/package/show/network:osmocom:nightly/open5gs). Scroll down to use a nightly build package.
{: .notice--warning} {: .notice--warning}
### Install Open5GS with a Package Manager
---
#### Ubuntu #### Ubuntu
@@ -51,11 +112,21 @@ https://download.opensuse.org/repositories/home:/acetcom:/open5gs:/latest/xUbunt
https://download.opensuse.org/repositories/home:/acetcom:/open5gs:/latest/xUbuntu_20.10/ https://download.opensuse.org/repositories/home:/acetcom:/open5gs:/latest/xUbuntu_20.10/
``` ```
#### openSUSE
[Martin Hauke](https://build.opensuse.org/user/show/mnhauke) packaged Open5GS for *openSUSE* on [OBS](https://build.opensuse.org/package/show/home:mnhauke:open5gs/open5gs).
```bash
$ sudo zypper addrepo -f obs://home:mnhauke:open5gs home:mnhauke:open5gs
$ sudo zypper install mongodb-server mongodb-shell
$ sudo zypper install open5gs
```
#### Nightly Builds #### Nightly Builds
Nightly bulit package are provided by [Osmocom](https://osmocom.org) on [OBS](https://build.opensuse.org/package/show/network:osmocom:nightly/open5gs). On *Ubuntu 20.04* you can install it like this: Nightly bulit package are provided by [Osmocom](https://osmocom.org) on [OBS](https://build.opensuse.org/package/show/network:osmocom:nightly/open5gs). On *Ubuntu 20.04* you can install it like this:
``` ```bash
$ sudo apt update $ sudo apt update
$ sudo apt install wget gnupg $ sudo apt install wget gnupg
$ wget -qO - https://download.opensuse.org/repositories/network:/osmocom:/nightly/xUbuntu_20.04/Release.key | sudo apt-key add - $ wget -qO - https://download.opensuse.org/repositories/network:/osmocom:/nightly/xUbuntu_20.04/Release.key | sudo apt-key add -
@@ -78,144 +149,14 @@ https://download.opensuse.org/repositories/network:/osmocom:/nightly/xUbuntu_20.
https://download.opensuse.org/repositories/network:/osmocom:/nightly/xUbuntu_20.10/ https://download.opensuse.org/repositories/network:/osmocom:/nightly/xUbuntu_20.10/
``` ```
#### openSUSE
[Martin Hauke](https://build.opensuse.org/user/show/mnhauke) packaged Open5GS for *openSUSE* on [OBS](https://build.opensuse.org/package/show/home:mnhauke:open5gs/open5gs). ## 3. Install the WebUI of Open5GS
```bash
$ sudo zypper addrepo -f obs://home:mnhauke:open5gs home:mnhauke:open5gs
$ sudo zypper install mongodb-server mongodb-shell
$ sudo zypper install open5gs
```
### Configure Open5GS
--- ---
##### 5G Core The WebUI allows you to interactively edit subscriber data. While it is not essential to use this, it makes things easier when you are just starting out on your Open5GS adventure. (A [command line tool](https://github.com/{{ site.github_username }}/open5gs/blob/master/misc/db/open5gs-dbctl) is available for advanced users).
Modify [install/etc/open5gs/amf.yaml](https://github.com/{{ site.github_username }}/open5gs/blob/master/configs/open5gs/amf.yaml.in) to set the NGAP IP address, PLMN ID, TAC and NSSAI.
```diff [Node.js](https://nodejs.org/) is required to install the WebUI of Open5GS
$ diff -u /etc/open5gs/amf.yaml.old /etc/open5gs/amf.yaml
--- amf.yaml 2020-09-05 20:52:28.652234967 -0400
+++ amf.yaml.new 2020-09-05 20:55:07.453114885 -0400
@@ -165,23 +165,23 @@
- addr: 127.0.0.5
port: 7777
ngap:
- - addr: 127.0.0.5
+ - addr: 10.10.0.5
guami:
- plmn_id:
- mcc: 901
- mnc: 70
+ mcc: 001
+ mnc: 01
amf_id:
region: 2
set: 1
tai:
- plmn_id:
- mcc: 901
- mnc: 70
- tac: 1
+ mcc: 001
+ mnc: 01
+ tac: 2
plmn:
- plmn_id:
- mcc: 901
- mnc: 70
+ mcc: 001
+ mnc: 01
s_nssai:
- sst: 1
security:
```
Modify [install/etc/open5gs/upf.yaml](https://github.com/{{ site.github_username }}/open5gs/blob/master/configs/open5gs/upf.yaml.in) to set the GTP-U and PFCP IP address.
```diff
$ diff -u /etc/open5gs/upf.yaml.old /etc/open5gs/upf.yaml
--- upf.yaml 2020-09-05 20:52:28.652234967 -0400
+++ upf.yaml.new 2020-09-05 20:52:55.279052142 -0400
@@ -137,9 +137,7 @@
pfcp:
- addr: 127.0.0.7
gtpu:
- - addr:
- - 127.0.0.7
- - ::1
+ - addr: 10.11.0.7
pdn:
- addr: 10.45.0.1/16
- addr: cafe::1/64
```
##### 4G EPC
Modify [install/etc/open5gs/mme.yaml](https://github.com/{{ site.github_username }}/open5gs/blob/master/configs/open5gs/mme.yaml.in) to set the S1AP IP address, PLMN ID, and TAC.
```diff
$ diff -u /etc/open5gs/mme.yaml.old /etc/open5gs/mme.yaml
--- mme.yaml 2020-09-05 20:52:28.648235143 -0400
+++ mme.yaml.new 2020-09-05 20:56:05.434484208 -0400
@@ -204,20 +204,20 @@
mme:
freeDiameter: /home/acetcom/Documents/git/open5gs/install/etc/freeDiameter/mme.conf
s1ap:
- addr: 127.0.0.2
+ addr: 10.10.0.2
gtpc:
addr: 127.0.0.2
gummei:
plmn_id:
- mcc: 901
- mnc: 70
+ mcc: 001
+ mnc: 01
mme_gid: 2
mme_code: 1
tai:
plmn_id:
- mcc: 901
- mnc: 70
- tac: 1
+ mcc: 001
+ mnc: 01
+ tac: 2
security:
integrity_order : [ EIA1, EIA2, EIA0 ]
ciphering_order : [ EEA0, EEA1, EEA2 ]
```
Modify [install/etc/open5gs/sgwu.yaml](https://github.com/{{ site.github_username }}/open5gs/blob/master/configs/open5gs/sgwu.yaml.in) to set the GTP-U IP address.
```diff
$ diff -u /etc/open5gs/sgwu.yaml.old /etc/open5gs/sgwu.yaml
--- sgwu.yaml 2020-09-05 20:50:39.393022566 -0400
+++ sgwu.yaml.new 2020-09-05 20:51:06.667838823 -0400
@@ -51,7 +51,7 @@
#
sgwu:
gtpu:
- addr: 127.0.0.6
+ addr: 10.11.0.6
pfcp:
addr: 127.0.0.6
```
After changing conf files, please restart Open5GS daemons.
```bash
$ sudo systemctl restart open5gs-amfd.service
$ sudo systemctl restart open5gs-upfd.service
$ sudo systemctl restart open5gs-mmed.service
$ sudo systemctl restart open5gs-sgwud.service
```
### Install WebUI of Open5GS
---
[Node.js](https://nodejs.org/) is required to install WebUI of Open5GS
1. *Debian and Ubuntu* based Linux distributions can install [Node.js](https://nodejs.org/) as follows: 1. *Debian and Ubuntu* based Linux distributions can install [Node.js](https://nodejs.org/) as follows:
@@ -238,7 +179,180 @@ You can now install WebUI of Open5GS.
$ curl -sL {{ site.url }}{{ site.baseurl }}/assets/webui/install | sudo -E bash - $ curl -sL {{ site.url }}{{ site.baseurl }}/assets/webui/install | sudo -E bash -
``` ```
### Register Subscriber Information ## 4. Configure Open5GS
---
Okay - you have installed the software, now what to do with it? Well, there are some tweaks you will need to make to the config files, and you will need to enter subscriber data into your HSS/ UDR. You will also need to set some IP Table rules to bridge the PGWU/UPF to the WAN.
Out of the box, the default configurations see all of the Open5GS components fully configured for use on a single computer. They are set to communicate with each other using the local loopback address space (`127.0.0.X`). The default addresses for each of the bind interfaces for these components and functions are as follows:
```
MongoDB = 127.0.0.1 (subscriber data) - http://localhost:3000
MME-s1ap = 127.0.0.2 :36412 for S1-MME
MME-gtpc = 127.0.0.2 :2123 for S11
MME-frDi = 127.0.0.2 :3868 for S6a auth
SGWC-gtpc = 127.0.0.3 :2123 for S11
SGWC-pfcp = 127.0.0.3 :8805 for Sxa
SMF-gtpc = 127.0.0.4 :2123 for S5/8c, N11
SMF-pfcp = 127.0.0.4 :8805 for N4
SMF-frDi = 127.0.0.4 :3868 for Gx auth
SMF-sbi = 127.0.0.4 :7777 for 5G SBI (N7,N10,N11)
AMF-ngap = 127.0.0.5 :38412 for N2
AMF-sbi = 127.0.0.5 :7777 for 5G SBI (N8,N12,N11)
SGWU-pfcp = 127.0.0.6 :8805 for Sxa
SGWU-gtpu = 127.0.0.6 :2152 for S1-U, S5/8u
UPF-pfcp = 127.0.0.7 :8805 for N4
UPF-gtpu = 127.0.0.7 :2152 for S5/8u, N3
HSS-frDi = 127.0.0.8 :3868 for S6a auth
PCRF-frDi = 127.0.0.9 :3868 for Gx auth
NRF-sbi = 127.0.0.10:7777 for 5G SBI
AUSF-sbi = 127.0.0.11:7777 for 5G SBI
UDM-sbi = 127.0.0.12:7777 for 5G SBI
PCF-sbi = 127.0.0.13:7777 for 5G SBI
UDR-sbi = 127.0.0.20:7777 for 5G SBI
```
#### Setup a 4G/ 5G NSA Core
You will need to modify your 4G MME config to support your PLMN and TAC. The international test PLMN is 001/01, and the international private network PLMN is 999/99. You should stick to using either of these PLMNs unless you have been issued a PLMN by your national regulator. (This PLMN will need to be configured in your eNB).
If you are aiming to connect an external eNB to your core, you will also need to change the S1AP bind address of the MME **and** the GTP-U bind address of the SGWU. If you are running an eNB stack locally, you will not need to make these changes.
Modify [/etc/open5gs/mme.yaml](https://github.com/{{ site.github_username }}/open5gs/blob/master/configs/open5gs/mme.yaml.in) to set the S1AP IP address, PLMN ID, and TAC.
```diff
$ diff -u /etc/open5gs/mme.yaml.old /etc/open5gs/mme.yaml
mme:
freeDiameter: /etc/freeDiameter/mme.conf
s1ap:
- addr: 127.0.0.2
+ addr: 10.10.0.2 # for external eNB - a local address that can be reached by the eNB
gtpc:
addr: 127.0.0.2
gummei:
plmn_id:
- mcc: 901
- mnc: 70
+ mcc: 001 # set your PLMN-MCC
+ mnc: 01 # set your PLMN-MNC
mme_gid: 2
mme_code: 1
tai:
plmn_id:
- mcc: 901
- mnc: 70
- tac: 1
+ mcc: 001 # set your PLMN-MCC
+ mnc: 01 # set your PLMN-MNC
+ tac: 2 # should match the TAC used by your eNB
security:
```
Modify [/etc/open5gs/sgwu.yaml](https://github.com/{{ site.github_username }}/open5gs/blob/master/configs/open5gs/sgwu.yaml.in) to set the GTP-U IP address.
```diff
$ diff -u /etc/open5gs/sgwu.yaml.old /etc/open5gs/sgwu.yaml
sgwu:
gtpu:
- addr: 127.0.0.6
+ addr: 10.11.0.6 # for external eNB - a local address that can be reached by the eNB
pfcp:
addr: 127.0.0.6
```
After changing config files, please restart Open5GS daemons.
```bash
$ sudo systemctl restart open5gs-mmed
$ sudo systemctl restart open5gs-sgwud
```
#### Setup a 5G Core
You will need to modify your 5G AMF config to support your PLMN and TAC. The international test PLMN is 001/01, and the international private network PLMN is 999/99. You should stick to using either of these PLMNs unless you have been issued a PLMN by your national regulator. (This PLMN will need to be configured in your gNB).
If you are aiming to connect an external gNB to your core, you will also need to change the NGAP bind address of the AMF **and** the GTPU bind address of the UPF. If you are running an gNB stack locally, you will not need to make these changes.
Modify [/etc/open5gs/amf.yaml](https://github.com/{{ site.github_username }}/open5gs/blob/master/configs/open5gs/amf.yaml.in) to set the NGAP IP address, PLMN ID, TAC and NSSAI.
```diff
$ diff -u /etc/open5gs/amf.yaml.old /etc/open5gs/amf.yaml
amf:
sbi:
- addr: 127.0.0.5
port: 7777
ngap:
- - addr: 127.0.0.5
+ - addr: 10.10.0.5 # for external gNB - a local address that can be reached by the gNB
guami:
- plmn_id:
- mcc: 901
- mnc: 70
+ mcc: 001 # set your PLMN-MCC
+ mnc: 01 # set your PLMN-MNC
amf_id:
region: 2
set: 1
tai:
- plmn_id:
- mcc: 901
- mnc: 70
- tac: 1
+ mcc: 001 # set your PLMN-MCC
+ mnc: 01 # set your PLMN-MNC
+ tac: 2 # should match the TAC used by your gNB
plmn:
- plmn_id:
- mcc: 901
- mnc: 70
+ mcc: 001 # set your PLMN-MCC
+ mnc: 01 # set your PLMN-MNC
s_nssai:
- sst: 1
security:
```
Modify [/etc/open5gs/upf.yaml](https://github.com/{{ site.github_username }}/open5gs/blob/master/configs/open5gs/upf.yaml.in) to set the GTP-U address.
```diff
$ diff -u /etc/open5gs/upf.yaml.old /etc/open5gs/upf.yaml
upf:
pfcp:
- addr: 127.0.0.7
gtpu:
- - addr: 127.0.0.7
+ - addr: 10.11.0.7 # for external gNB - a local address that can be reached by the gNB
pdn:
- addr: 10.45.0.1/16
- addr: cafe::1/64
```
After changing config files, please restart Open5GS daemons.
```bash
$ sudo systemctl restart open5gs-amfd
$ sudo systemctl restart open5gs-upfd
```
#### Register Subscriber Information
--- ---
Connect to `http://localhost:3000` and login with **admin** account. Connect to `http://localhost:3000` and login with **admin** account.
@@ -256,15 +370,21 @@ To add subscriber information, you can do WebUI operations in the following orde
3. Fill the IMSI, security context(K, OPc, AMF), and APN of the subscriber. 3. Fill the IMSI, security context(K, OPc, AMF), and APN of the subscriber.
4. Click `SAVE` Button 4. Click `SAVE` Button
**Tip:** This addition immediately affects Open5GS without restaring any daemon. Enter the subscriber details of your SIM cards using this tool, to save the subscriber profile in the HSS and UDR MongoDB database backend. If you are using test SIMs, the details are normally printed on the card.
**Tip:** Subscribers added with this tool immediately register in the Open5GS HSS/ UDR without the need to restart any daemon.
{: .notice--info} {: .notice--info}
### Adding a route for UE to have Internet connectivity {#UEInternet} #### Adding a route for the UE to have WAN connectivity {#UEInternet}
--- ---
If your phone can connect to internet, you must run the following command in Open5GS-PGW installed host. In order to bridge between the PGWU/UPF and WAN (Internet), you must enable IP forwarding and add a NAT rule to your IP Tables.
**Note:** For the first run, it makes things simpler if you do not have any rules in the IP/NAT tables. If a program such as docker has already set up a rule, you will need to add rules differently.
{: .notice--danger}
You can check your current IP Table rules with the following commands (these tables are empty):
```bash ```bash
### Check IP Tables ### Check IP Tables
$ sudo iptables -L $ sudo iptables -L
@@ -290,7 +410,10 @@ target prot opt source destination
Chain POSTROUTING (policy ACCEPT) Chain POSTROUTING (policy ACCEPT)
target prot opt source destination target prot opt source destination
```
To enable forwarding and add the NAT rule, enter
```bash
### Enable IPv4 Forwarding ### Enable IPv4 Forwarding
$ sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward" $ sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
@@ -298,19 +421,71 @@ $ sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
$ sudo iptables -t nat -A POSTROUTING -s 10.45.0.0/16 ! -o ogstun -j MASQUERADE $ sudo iptables -t nat -A POSTROUTING -s 10.45.0.0/16 ! -o ogstun -j MASQUERADE
``` ```
**Note:** For the first time, it is a good condition if you do not have any rules in the IP/NAT tables. If a program such as docker has already set up a rule, you will need to add a rule differently.
{: .notice--danger}
### Turn on your gNB/eNB and Phone ## 5. Turn on your eNB/gNB and UE
--- ---
- Connect your gNB/eNB to the IP of your server via the standard NGAP/S1AP port of SCTP 38412/36412 (for AMF/MME)
- You can see actual traffic through wireshark -- [[srsenb.pcapng]]({{ site.url }}{{ site.baseurl }}/assets/pcapng/srsenb.pcapng). First, connect your eNB/gNB to the Open5GS core:
- You can view the log at `/var/log/open5gs/*.log`. * Make sure the PLMN and TAC of the eNB/gNB matches the settings in your MME/AMF
* Connect your eNB/gNB to the IP of your server via the standard S1AP/NGAP SCTP port 36412/38412 (for MME/AMF)
* Your eNB/gNB should report a successful S1/NG connection - congrats, your core is fully working!
* You can see actual traffic through wireshark -- [[srsenb.pcapng]]({{ site.url }}{{ site.baseurl }}/assets/pcapng/srsenb.pcapng).
* You can view the log at `/var/log/open5gs/*.log`, eg:
```bash
### Watch the live MME log
tail -f /var/log/open5gs/mme.log
```
Next, try to attach a UE to the basestation:
* Insert your SIM card to the UE
* Set the UE's APN to match the APN you configured in the Open5GS WebUI
* Toggle the UE in and out of flight mode
* If it doesn't automatically connect, try manually searching for a network
* If the PLMN set on the SIM card does not match the PLMN being used by the radio, you will need to ensure 'data roaming' on the UE is switched on
## 6. Starting and Stopping Open5GS
---
When you install the software using the package manager, it is setup to run as a systemd service. You can stop and restart the components and network functions as follows:
```bash
$ sudo systemctl stop open5gs-mmed
$ sudo systemctl stop open5gs-sgwcd
$ sudo systemctl stop open5gs-smfd
$ sudo systemctl stop open5gs-amfd
$ sudo systemctl stop open5gs-sgwud
$ sudo systemctl stop open5gs-upfd
$ sudo systemctl stop open5gs-hssd
$ sudo systemctl stop open5gs-pcrfd
$ sudo systemctl stop open5gs-nrfd
$ sudo systemctl stop open5gs-ausfd
$ sudo systemctl stop open5gs-udmd
$ sudo systemctl stop open5gs-pcfd
$ sudo systemctl stop open5gs-udrd
$ sudo systemctl stop open5gs-webui
```
```bash
$ sudo systemctl restart open5gs-mmed
$ sudo systemctl restart open5gs-sgwcd
$ sudo systemctl restart open5gs-smfd
$ sudo systemctl restart open5gs-amfd
$ sudo systemctl restart open5gs-sgwud
$ sudo systemctl restart open5gs-upfd
$ sudo systemctl restart open5gs-hssd
$ sudo systemctl restart open5gs-pcrfd
$ sudo systemctl restart open5gs-nrfd
$ sudo systemctl restart open5gs-ausfd
$ sudo systemctl restart open5gs-udmd
$ sudo systemctl restart open5gs-pcfd
$ sudo systemctl restart open5gs-udrd
$ sudo systemctl restart open5gs-webui
```
### Uninstall Open5GS and WebUI ## 7. Uninstall Open5GS and WebUI
How to remove Open5GS package: To remove the Open5GS packages:
1. On *Ubuntu/Debian*: 1. On *Ubuntu/Debian*:

View File

@@ -3,6 +3,13 @@ title: Now in the Github Issue
head_inline: "<style> .blue { color: blue; } </style>" head_inline: "<style> .blue { color: blue; } </style>"
--- ---
<style>
img {
max-width: 100%;
height: auto;
}
</style>
#### Cannot open shared object file when running daemon #### Cannot open shared object file when running daemon
An error occurred when running as follows. An error occurred when running as follows.
@@ -176,15 +183,15 @@ $ sudo systemctl restart open5gs-upfd.service
By default, wireshark cannot decode NAS-5GS message when the security header type is "Integrity protected and ciphered". By default, wireshark cannot decode NAS-5GS message when the security header type is "Integrity protected and ciphered".
![Wireshark cannot decode]({{ site.url }}{{ site.baseurl }}/assets/images/wireshark_cannot_decode_nas_5gs.png){: height="100%" width="100%"} ![Wireshark cannot decode]({{ site.url }}{{ site.baseurl }}/assets/images/wireshark_cannot_decode_nas_5gs.png)
You need to turn on "Try to detect and decode 5G-EA0 ciphered messages" in the wireshark perference menu. You need to turn on "Try to detect and decode 5G-EA0 ciphered messages" in the wireshark perference menu.
![Wireshark perference]({{ site.url }}{{ site.baseurl }}/assets/images/wireshark_preference.png){: height="100%" width="100%"} ![Wireshark perference]({{ site.url }}{{ site.baseurl }}/assets/images/wireshark_preference.png)
Now, you can see the NAS-5GS message in the wireshark. Now, you can see the NAS-5GS message in the wireshark.
![Wireshark can decode]({{ site.url }}{{ site.baseurl }}/assets/images/wireshark_can_decode_nas_5gs.png){: height="100%" width="100%"} ![Wireshark can decode]({{ site.url }}{{ site.baseurl }}/assets/images/wireshark_can_decode_nas_5gs.png)
#### Test failed (e.g. `meson test -v`) #### Test failed (e.g. `meson test -v`)

View File

@@ -13,8 +13,8 @@ Open5GS is a C-language Open Source implementation of 5GC and EPC, i.e. the core
- AES, Snow3G, ZUC algorithms for encryption - AES, Snow3G, ZUC algorithms for encryption
- Support of USIM cards using Milenage - Support of USIM cards using Milenage
- IPv6 support - IPv6 support
- Multiple PDU session resource(EPC only) - Multiple PDU session
- S1/X2 Handover(EPC only) - S1/X2 and Xn Handover
- CSFB(Circuit Switched Fall Back) and SMSoS(SMS Over SGs) - CSFB(Circuit Switched Fall Back) and SMSoS(SMS Over SGs)
- VoLTE(Voice over LTE) - VoLTE(Voice over LTE)

View File

@@ -0,0 +1,16 @@
---
title: "v2.1.1 - 4G EPC Hotfix"
date: 2020-12-16 11:08:00 -0500
categories:
- Release
tags:
- News
- Release
head_inline: "<style> ul { padding-bottom: 1em; } </style>"
---
#### Bug Fixes
- Fix the assertion BUG with Unexpected PDN Type ([#721](https://github.com/open5gs/open5gs/issues/721)) -- [cecrevier](https://github.com/cecrevier)
Download -- [v2.1.1.tar.gz](https://github.com/open5gs/open5gs/archive/v2.1.1.tar.gz)
{: .notice--info}

View File

@@ -0,0 +1,35 @@
---
title: "v2.1.3 - 5GC improvements"
date: 2021-01-08 22:50:00 -0500
categories:
- Release
tags:
- News
- Release
head_inline: "<style> ul { padding-bottom: 1em; } </style>"
---
#### New features
- [5GC] Dedicated QoS flow & Multiple PDU session ([235a041](https://github.com/open5gs/open5gs/commit/235a041b8d7638db931114ace49e4f771508830f), [a96d3ca](https://github.com/open5gs/open5gs/commit/a96d3ca0fa88828f4efb1135ebcb8a88d8bdc66c))
- [5GC] Xn Handover ([#726](https://github.com/open5gs/open5gs/pull/726)) -- [lester-001](https://github.com/lester-001)
#### Test
- [5GC] 1024 UEs Registration ([#753](https://github.com/open5gs/open5gs/issues/753)) -- [mmailand](https://github.com/mmailand)
#### Enhancement
- [AMF] Handling UEContextRequest of InitialUEMessage ([7b29cdf](https://github.com/open5gs/open5gs/commit/7b29cdf89871be0a00c0dd907ae5da7bcf88e305))
#### Bug Fixes
- [SBI] Time string conversion error on 32bit machine ([a0ebf20](https://github.com/open5gs/open5gs/commit/e531ccab5a82698dad46d5d9d41a0e0c496b5ed6))
- [MME] Add handler for NAS EPS activate_dedicated EPS bearer context reject ([#755](https://github.com/open5gs/open5gs/pull/755)) -- [herlesupreeth](https://github.com/herlesupreeth)
- [PFCP] Remvoe repeated QER in handling Create-PDR ([#749](https://github.com/open5gs/open5gs/pull/749)) -- [zhonglin6666](https://github.com/zhonglin6666)
- [AMF] Re-add SCTP ppid and stream-no ([#743](https://github.com/open5gs/open5gs/issues/743)) -- [aligungr](https://github.com/aligungr)
- [5GC] Fix wrong usage of SBI heartbeat timer ([#741](https://github.com/open5gs/open5gs/issues/741)) -- [fatihozer90](https://github.com/fatihozer90)
- [5GC] Fix the problem of receiving large HTTP2 message(Max: 8,192 bytes) ([#738](https://github.com/open5gs/open5gs/issues/738)) -- [fatihozer90](https://github.com/fatihozer90)
- [NRF] Support subscrCond ([#730](https://github.com/open5gs/open5gs/issues/730)) -- [fatihozer90](https://github.com/fatihozer90)
- [NRF] Many BUG fixes ([#727](https://github.com/open5gs/open5gs/issues/727), [#728](https://github.com/open5gs/open5gs/issues/728), [#729](https://github.com/open5gs/open5gs/issues/729), [#737](https://github.com/open5gs/open5gs/issues/737)) -- [fatihozer90](https://github.com/fatihozer90)
- [AMF] AMF sets default DNN if UE does not sent it
- [MME] Fix the MME crash ([#708](https://github.com/open5gs/open5gs/issues/708), [#721](https://github.com/open5gs/open5gs/issues/721)) -- [cecrevier](https://github.com/cecrevier)
Download -- [v2.1.3.tar.gz](https://github.com/open5gs/open5gs/archive/v2.1.3.tar.gz)
{: .notice--info}

View File

@@ -0,0 +1,23 @@
---
title: "v2.1.4 - Paging was added"
date: 2021-01-18 21:23:00 -0500
categories:
- Release
tags:
- News
- Release
head_inline: "<style> ul { padding-bottom: 1em; } </style>"
---
#### New feature
- [5GC] Paging ([c9363b1](https://github.com/open5gs/open5gs/commit/c9363b132093581b6fd2ce794aa63cd597bf83a6))
#### Enhancement
- [PFCP] Legacy support for pre-release LTE11 devices while performing VoLTE call([#757](https://github.com/open5gs/open5gs/pull/757)) -- [herlesupreeth](https://github.com/herlesupreeth)
#### Bug Fixes
- [EPC] Use ESM cause(43:Invalid EPS bearer identity) if SGW-C sends GTP cause(Context Not Found) ([#755](https://github.com/open5gs/open5gs/issues/755)) -- [herlesupreeth](https://github.com/herlesupreeth)
- [MME] fix a bug where SCTP stream number was not set while sending S1-Paging message. ([c9363b1](https://github.com/open5gs/open5gs/commit/c9363b132093581b6fd2ce794aa63cd597bf83a6))
Download -- [v2.1.4.tar.gz](https://github.com/open5gs/open5gs/archive/v2.1.4.tar.gz)
{: .notice--info}

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 KiB

File diff suppressed because one or more lines are too long

View File

@@ -183,8 +183,8 @@ static void app_context_prepare(void)
recalculate_pool_size(); recalculate_pool_size();
/* 10 second */ /* <Heartbeat Checking Interval>
self.time.nf_instance.heartbeat_interval = 10; * Heartbeat Interval(e.g: 10 seconds) + No Heartbeat Margin(1 second) */
self.time.nf_instance.no_heartbeat_margin = 1; self.time.nf_instance.no_heartbeat_margin = 1;
/* 3600 seconds = 1 hour */ /* 3600 seconds = 1 hour */
@@ -203,6 +203,14 @@ static void app_context_prepare(void)
*/ */
self.time.message.duration = ogs_time_from_sec(10); self.time.message.duration = ogs_time_from_sec(10);
/*
* Handover Wait Duration : 300 ms (Default)
*
* Time to wait for AMF/MME to send UEContextReleaseCommand
* to the source gNB/eNB after receiving HandoverNotify
*/
self.time.handover.duration = ogs_time_from_msec(300);
regenerate_all_timer_duration(); regenerate_all_timer_duration();
} }
@@ -327,6 +335,10 @@ int ogs_app_context_parse_config(void)
} else if (!strcmp(parameter_key, "use_openair")) { } else if (!strcmp(parameter_key, "use_openair")) {
self.parameter.use_openair = self.parameter.use_openair =
ogs_yaml_iter_bool(&parameter_iter); ogs_yaml_iter_bool(&parameter_iter);
} else if (!strcmp(
parameter_key, "no_ipv4v6_local_addr_in_packet_filter")) {
self.parameter.no_ipv4v6_local_addr_in_packet_filter =
ogs_yaml_iter_bool(&parameter_iter);
} else } else
ogs_warn("unknown key `%s`", parameter_key); ogs_warn("unknown key `%s`", parameter_key);
} }
@@ -478,13 +490,31 @@ int ogs_app_context_parse_config(void)
if (!strcmp(msg_key, "duration")) { if (!strcmp(msg_key, "duration")) {
const char *v = ogs_yaml_iter_value(&msg_iter); const char *v = ogs_yaml_iter_value(&msg_iter);
if (v) { if (v) {
self.time.message.duration = self.time.message.duration =
ogs_time_from_msec(atoll(v)); ogs_time_from_msec(atoll(v));
regenerate_all_timer_duration(); regenerate_all_timer_duration();
} }
} else } else
ogs_warn("unknown key `%s`", msg_key); ogs_warn("unknown key `%s`", msg_key);
} }
} else if (!strcmp(time_key, "handover")) {
ogs_yaml_iter_t msg_iter;
ogs_yaml_iter_recurse(&time_iter, &msg_iter);
while (ogs_yaml_iter_next(&msg_iter)) {
const char *msg_key =
ogs_yaml_iter_key(&msg_iter);
ogs_assert(msg_key);
if (!strcmp(msg_key, "duration")) {
const char *v = ogs_yaml_iter_value(&msg_iter);
if (v) {
self.time.handover.duration =
ogs_time_from_msec(atoll(v));
}
} else
ogs_warn("unknown key `%s`", msg_key);
}
} else } else
ogs_warn("unknown key `%s`", time_key); ogs_warn("unknown key `%s`", time_key);
} }

View File

@@ -74,6 +74,7 @@ typedef struct ogs_app_context_s {
int no_slaac; int no_slaac;
int use_openair; int use_openair;
int no_ipv4v6_local_addr_in_packet_filter;
} parameter; } parameter;
ogs_sockopt_t sockopt; ogs_sockopt_t sockopt;
@@ -145,6 +146,12 @@ typedef struct ogs_app_context_s {
ogs_time_t no_heartbeat_duration; ogs_time_t no_heartbeat_duration;
} pfcp; } pfcp;
} message; } message;
struct {
ogs_time_t duration;
ogs_time_t complete_delay;
} handover;
} time; } time;
} ogs_app_context_t; } ogs_app_context_t;

View File

@@ -4,447 +4,72 @@
*/ */
#include <asn_internal.h> #include <asn_internal.h>
#include <ANY.h> #include <ANY.h>
#include <errno.h>
asn_OCTET_STRING_specifics_t asn_SPC_ANY_specs = { asn_OCTET_STRING_specifics_t asn_SPC_ANY_specs = {
sizeof(ANY_t), sizeof(ANY_t),
offsetof(ANY_t, _asn_ctx), offsetof(ANY_t, _asn_ctx),
ASN_OSUBV_ANY ASN_OSUBV_ANY
}; };
asn_TYPE_operation_t asn_OP_ANY = { asn_TYPE_operation_t asn_OP_ANY = {
OCTET_STRING_free, OCTET_STRING_free,
OCTET_STRING_print, #if !defined(ASN_DISABLE_PRINT_SUPPORT)
OCTET_STRING_compare, OCTET_STRING_print,
OCTET_STRING_decode_ber,
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
ANY_encode_xer,
#ifdef ASN_DISABLE_OER_SUPPORT
0,
0,
#else #else
0, 0,
0, #endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
#endif /* ASN_DISABLE_OER_SUPPORT */ OCTET_STRING_compare,
#ifdef ASN_DISABLE_PER_SUPPORT #if !defined(ASN_DISABLE_BER_SUPPORT)
0, 0, 0, 0, OCTET_STRING_decode_ber,
OCTET_STRING_encode_der,
#else #else
ANY_decode_uper, 0,
ANY_encode_uper, 0,
ANY_decode_aper, #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
ANY_encode_aper, #if !defined(ASN_DISABLE_XER_SUPPORT)
#endif /* ASN_DISABLE_PER_SUPPORT */ OCTET_STRING_decode_xer_hex,
0, /* Random fill is not defined for ANY type */ ANY_encode_xer,
0 /* Use generic outmost tag fetcher */ #else
0,
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
0,
0,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
ANY_decode_uper,
ANY_encode_uper,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
ANY_decode_aper,
ANY_encode_aper,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
0, /* Random fill is not defined for ANY type */
0 /* Use generic outmost tag fetcher */
}; };
asn_TYPE_descriptor_t asn_DEF_ANY = { asn_TYPE_descriptor_t asn_DEF_ANY = {
"ANY", "ANY",
"ANY", "ANY",
&asn_OP_ANY, &asn_OP_ANY,
0, 0, 0, 0, 0, 0, 0, 0,
{ 0, 0, asn_generic_no_constraint }, /* No constraints */ {
0, 0, /* No members */ #if !defined(ASN_DISABLE_OER_SUPPORT)
&asn_SPC_ANY_specs, 0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
asn_generic_no_constraint
}, /* No constraints */
0, 0, /* No members */
&asn_SPC_ANY_specs,
}; };
#undef RETURN
#define RETURN(_code) \
do { \
asn_dec_rval_t tmprval; \
tmprval.code = _code; \
tmprval.consumed = consumed_myself; \
return tmprval; \
} while(0)
asn_enc_rval_t
ANY_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
enum xer_encoder_flags_e flags, asn_app_consume_bytes_f *cb,
void *app_key) {
if(flags & XER_F_CANONICAL) {
/*
* Canonical XER-encoding of ANY type is not supported.
*/
ASN__ENCODE_FAILED;
}
/* Dump as binary */
return OCTET_STRING_encode_xer(td, sptr, ilevel, flags, cb, app_key);
}
struct _callback_arg {
uint8_t *buffer;
size_t offset;
size_t size;
};
static int ANY__consume_bytes(const void *buffer, size_t size, void *key);
int
ANY_fromType(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr) {
struct _callback_arg arg;
asn_enc_rval_t erval = {0,0,0};
if(!st || !td) {
errno = EINVAL;
return -1;
}
if(!sptr) {
if(st->buf) FREEMEM(st->buf);
st->size = 0;
return 0;
}
arg.offset = arg.size = 0;
arg.buffer = 0;
erval = der_encode(td, sptr, ANY__consume_bytes, &arg);
if(erval.encoded == -1) {
if(arg.buffer) FREEMEM(arg.buffer);
return -1;
}
assert((size_t)erval.encoded == arg.offset);
if(st->buf) FREEMEM(st->buf);
st->buf = arg.buffer;
st->size = arg.offset;
return 0;
}
int
ANY_fromType_aper(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr) {
uint8_t *buffer = NULL;
ssize_t erval;
if(!st || !td) {
errno = EINVAL;
return -1;
}
if(!sptr) {
if(st->buf) FREEMEM(st->buf);
st->size = 0;
return 0;
}
erval = aper_encode_to_new_buffer(td, td->encoding_constraints.per_constraints, sptr, (void**)&buffer);
if(erval == -1) {
if(buffer) FREEMEM(buffer);
return -1;
}
assert((size_t)erval > 0);
if(st->buf) FREEMEM(st->buf);
st->buf = buffer;
st->size = erval;
return 0;
}
ANY_t *
ANY_new_fromType(asn_TYPE_descriptor_t *td, void *sptr) {
ANY_t tmp;
ANY_t *st;
if(!td || !sptr) {
errno = EINVAL;
return 0;
}
memset(&tmp, 0, sizeof(tmp));
if(ANY_fromType(&tmp, td, sptr)) return 0;
st = (ANY_t *)CALLOC(1, sizeof(ANY_t));
if(st) {
*st = tmp;
return st;
} else {
FREEMEM(tmp.buf);
return 0;
}
}
ANY_t *
ANY_new_fromType_aper(asn_TYPE_descriptor_t *td, void *sptr) {
ANY_t tmp;
ANY_t *st;
if(!td || !sptr) {
errno = EINVAL;
return 0;
}
memset(&tmp, 0, sizeof(tmp));
if(ANY_fromType_aper(&tmp, td, sptr)) return 0;
st = (ANY_t *)CALLOC(1, sizeof(ANY_t));
if(st) {
*st = tmp;
return st;
} else {
FREEMEM(tmp.buf);
return 0;
}
}
int
ANY_to_type(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr) {
asn_dec_rval_t rval;
void *newst = 0;
if(!st || !td || !struct_ptr) {
errno = EINVAL;
return -1;
}
if(st->buf == 0) {
/* Nothing to convert, make it empty. */
*struct_ptr = (void *)0;
return 0;
}
rval = ber_decode(0, td, (void **)&newst, st->buf, st->size);
if(rval.code == RC_OK) {
*struct_ptr = newst;
return 0;
} else {
/* Remove possibly partially decoded data. */
ASN_STRUCT_FREE(*td, newst);
return -1;
}
}
int
ANY_to_type_aper(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr) {
asn_dec_rval_t rval;
void *newst = 0;
if(!st || !td || !struct_ptr) {
errno = EINVAL;
return -1;
}
if(st->buf == 0) {
/* Nothing to convert, make it empty. */
*struct_ptr = (void *)0;
return 0;
}
rval = aper_decode(0, td, (void **)&newst, st->buf, st->size, 0, 0);
if(rval.code == RC_OK) {
*struct_ptr = newst;
return 0;
} else {
/* Remove possibly partially decoded data. */
ASN_STRUCT_FREE(*td, newst);
return -1;
}
}
static int ANY__consume_bytes(const void *buffer, size_t size, void *key) {
struct _callback_arg *arg = (struct _callback_arg *)key;
if((arg->offset + size) >= arg->size) {
size_t nsize = (arg->size ? arg->size << 2 : 16) + size;
void *p = REALLOC(arg->buffer, nsize);
if(!p) return -1;
arg->buffer = (uint8_t *)p;
arg->size = nsize;
}
memcpy(arg->buffer + arg->offset, buffer, size);
arg->offset += size;
assert(arg->offset < arg->size);
return 0;
}
#ifndef ASN_DISABLE_PER_SUPPORT
asn_dec_rval_t
ANY_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints, void **sptr,
asn_per_data_t *pd) {
const asn_OCTET_STRING_specifics_t *specs =
td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_SPC_ANY_specs;
size_t consumed_myself = 0;
int repeat;
ANY_t *st = (ANY_t *)*sptr;
(void)opt_codec_ctx;
(void)constraints;
/*
* Allocate the structure.
*/
if(!st) {
st = (ANY_t *)(*sptr = CALLOC(1, specs->struct_size));
if(!st) RETURN(RC_FAIL);
}
ASN_DEBUG("UPER Decoding ANY type");
st->size = 0;
do {
ssize_t raw_len;
ssize_t len_bytes;
ssize_t len_bits;
void *p;
int ret;
/* Get the PER length */
raw_len = uper_get_length(pd, -1, 0, &repeat);
if(raw_len < 0) RETURN(RC_WMORE);
if(raw_len == 0 && st->buf) break;
ASN_DEBUG("Got PER length len %" ASN_PRI_SIZE ", %s (%s)", raw_len,
repeat ? "repeat" : "once", td->name);
len_bytes = raw_len;
len_bits = len_bytes * 8;
p = REALLOC(st->buf, st->size + len_bytes + 1);
if(!p) RETURN(RC_FAIL);
st->buf = (uint8_t *)p;
ret = per_get_many_bits(pd, &st->buf[st->size], 0, len_bits);
if(ret < 0) RETURN(RC_WMORE);
consumed_myself += len_bits;
st->size += len_bytes;
} while(repeat);
st->buf[st->size] = 0; /* nul-terminate */
RETURN(RC_OK);
}
asn_enc_rval_t
ANY_encode_uper(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints, const void *sptr,
asn_per_outp_t *po) {
const ANY_t *st = (const ANY_t *)sptr;
asn_enc_rval_t er = {0, 0, 0};
const uint8_t *buf;
size_t size;
int ret;
(void)constraints;
if(!st || (!st->buf && st->size)) ASN__ENCODE_FAILED;
buf = st->buf;
size = st->size;
do {
int need_eom = 0;
ssize_t may_save = uper_put_length(po, size, &need_eom);
if(may_save < 0) ASN__ENCODE_FAILED;
ret = per_put_many_bits(po, buf, may_save * 8);
if(ret) ASN__ENCODE_FAILED;
buf += may_save;
size -= may_save;
assert(!(may_save & 0x07) || !size);
if(need_eom && uper_put_length(po, 0, 0))
ASN__ENCODE_FAILED; /* End of Message length */
} while(size);
ASN__ENCODED_OK(er);
}
asn_dec_rval_t
ANY_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints, void **sptr,
asn_per_data_t *pd) {
const asn_OCTET_STRING_specifics_t *specs =
td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_SPC_ANY_specs;
size_t consumed_myself = 0;
int repeat;
ANY_t *st = (ANY_t *)*sptr;
(void)opt_codec_ctx;
(void)constraints;
/*
* Allocate the structure.
*/
if(!st) {
st = (ANY_t *)(*sptr = CALLOC(1, specs->struct_size));
if(!st) RETURN(RC_FAIL);
}
ASN_DEBUG("APER Decoding ANY type");
st->size = 0;
do {
ssize_t raw_len;
ssize_t len_bytes;
ssize_t len_bits;
void *p;
int ret;
/* Get the PER length */
raw_len = aper_get_length(pd, -1, 0, &repeat);
if(raw_len < 0) RETURN(RC_WMORE);
if(raw_len == 0 && st->buf) break;
ASN_DEBUG("Got PER length len %" ASN_PRI_SIZE ", %s (%s)", raw_len,
repeat ? "repeat" : "once", td->name);
len_bytes = raw_len;
len_bits = len_bytes * 8;
p = REALLOC(st->buf, st->size + len_bytes + 1);
if(!p) RETURN(RC_FAIL);
st->buf = (uint8_t *)p;
ret = per_get_many_bits(pd, &st->buf[st->size], 0, len_bits);
if(ret < 0) RETURN(RC_WMORE);
consumed_myself += len_bits;
st->size += len_bytes;
} while(repeat);
st->buf[st->size] = 0; /* nul-terminate */
RETURN(RC_OK);
}
asn_enc_rval_t
ANY_encode_aper(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints, const void *sptr,
asn_per_outp_t *po) {
const ANY_t *st = (const ANY_t *)sptr;
asn_enc_rval_t er = {0, 0, 0};
const uint8_t *buf;
size_t size;
int ret;
(void)constraints;
if(!st || (!st->buf && st->size)) ASN__ENCODE_FAILED;
buf = st->buf;
size = st->size;
do {
int need_eom = 0;
ssize_t may_save = uper_put_length(po, size, &need_eom);
if(may_save < 0) ASN__ENCODE_FAILED;
ret = per_put_many_bits(po, buf, may_save * 8);
if(ret) ASN__ENCODE_FAILED;
buf += may_save;
size -= may_save;
assert(!(may_save & 0x07) || !size);
if(need_eom && uper_put_length(po, 0, 0))
ASN__ENCODE_FAILED; /* End of Message length */
} while(size);
ASN__ENCODED_OK(er);
}
#endif /* ASN_DISABLE_PER_SUPPORT */

View File

@@ -22,23 +22,34 @@ extern asn_TYPE_descriptor_t asn_DEF_ANY;
extern asn_TYPE_operation_t asn_OP_ANY; extern asn_TYPE_operation_t asn_OP_ANY;
extern asn_OCTET_STRING_specifics_t asn_SPC_ANY_specs; extern asn_OCTET_STRING_specifics_t asn_SPC_ANY_specs;
asn_struct_free_f ANY_free; #define ANY_free OCTET_STRING_free
asn_struct_print_f ANY_print;
ber_type_decoder_f ANY_decode_ber; #if !defined(ASN_DISABLE_PRINT_SUPPORT)
der_type_encoder_f ANY_encode_der; #define ANY_print OCTET_STRING_print
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
#define ANY_compare OCTET_STRING_compare
#define ANY_constraint asn_generic_no_constraint
#if !defined(ASN_DISABLE_BER_SUPPORT)
#define ANY_decode_ber OCTET_STRING_decode_ber
#define ANY_encode_der OCTET_STRING_encode_der
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
#if !defined(ASN_DISABLE_XER_SUPPORT)
#define ANY_decode_xer OCTET_STRING_decode_xer_hex
xer_type_encoder_f ANY_encode_xer; xer_type_encoder_f ANY_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
per_type_decoder_f ANY_decode_uper; per_type_decoder_f ANY_decode_uper;
per_type_encoder_f ANY_encode_uper; per_type_encoder_f ANY_encode_uper;
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
per_type_decoder_f ANY_decode_aper; per_type_decoder_f ANY_decode_aper;
per_type_encoder_f ANY_encode_aper; per_type_encoder_f ANY_encode_aper;
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#define ANY_free OCTET_STRING_free
#define ANY_print OCTET_STRING_print
#define ANY_compare OCTET_STRING_compare
#define ANY_constraint asn_generic_no_constraint
#define ANY_decode_ber OCTET_STRING_decode_ber
#define ANY_encode_der OCTET_STRING_encode_der
#define ANY_decode_xer OCTET_STRING_decode_xer_hex
/****************************** /******************************
* Handy conversion routines. * * Handy conversion routines. *
@@ -46,13 +57,17 @@ per_type_encoder_f ANY_encode_aper;
/* Convert another ASN.1 type into the ANY. This implies DER encoding. */ /* Convert another ASN.1 type into the ANY. This implies DER encoding. */
int ANY_fromType(ANY_t *, asn_TYPE_descriptor_t *td, void *struct_ptr); int ANY_fromType(ANY_t *, asn_TYPE_descriptor_t *td, void *struct_ptr);
int ANY_fromType_aper(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr);
ANY_t *ANY_new_fromType(asn_TYPE_descriptor_t *td, void *struct_ptr); ANY_t *ANY_new_fromType(asn_TYPE_descriptor_t *td, void *struct_ptr);
#if !defined(ASN_DISABLE_APER_SUPPORT)
int ANY_fromType_aper(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr);
ANY_t *ANY_new_fromType_aper(asn_TYPE_descriptor_t *td, void *sptr); ANY_t *ANY_new_fromType_aper(asn_TYPE_descriptor_t *td, void *sptr);
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
/* Convert the contents of the ANY type into the specified type. */ /* Convert the contents of the ANY type into the specified type. */
int ANY_to_type(ANY_t *, asn_TYPE_descriptor_t *td, void **struct_ptr); int ANY_to_type(ANY_t *, asn_TYPE_descriptor_t *td, void **struct_ptr);
#if !defined(ASN_DISABLE_APER_SUPPORT)
int ANY_to_type_aper(ANY_t *, asn_TYPE_descriptor_t *td, void **struct_ptr); int ANY_to_type_aper(ANY_t *, asn_TYPE_descriptor_t *td, void **struct_ptr);
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#define ANY_fromBuf(s, buf, size) OCTET_STRING_fromBuf((s), (buf), (size)) #define ANY_fromBuf(s, buf, size) OCTET_STRING_fromBuf((s), (buf), (size))
#define ANY_new_fromBuf(buf, size) OCTET_STRING_new_fromBuf( \ #define ANY_new_fromBuf(buf, size) OCTET_STRING_new_fromBuf( \

190
lib/asn1c/common/ANY_aper.c Normal file
View File

@@ -0,0 +1,190 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <ANY.h>
#include <errno.h>
#undef RETURN
#define RETURN(_code) \
do { \
asn_dec_rval_t tmprval; \
tmprval.code = _code; \
tmprval.consumed = consumed_myself; \
return tmprval; \
} while(0)
int
ANY_fromType_aper(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr) {
uint8_t *buffer = NULL;
ssize_t erval;
if(!st || !td) {
errno = EINVAL;
return -1;
}
if(!sptr) {
if(st->buf) FREEMEM(st->buf);
st->size = 0;
return 0;
}
erval = aper_encode_to_new_buffer(td, td->encoding_constraints.per_constraints, sptr, (void**)&buffer);
if(erval == -1) {
if(buffer) FREEMEM(buffer);
return -1;
}
assert((size_t)erval > 0);
if(st->buf) FREEMEM(st->buf);
st->buf = buffer;
st->size = erval;
return 0;
}
ANY_t *
ANY_new_fromType_aper(asn_TYPE_descriptor_t *td, void *sptr) {
ANY_t tmp;
ANY_t *st;
if(!td || !sptr) {
errno = EINVAL;
return 0;
}
memset(&tmp, 0, sizeof(tmp));
if(ANY_fromType_aper(&tmp, td, sptr)) return 0;
st = (ANY_t *)CALLOC(1, sizeof(ANY_t));
if(st) {
*st = tmp;
return st;
} else {
FREEMEM(tmp.buf);
return 0;
}
}
int
ANY_to_type_aper(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr) {
asn_dec_rval_t rval;
void *newst = 0;
if(!st || !td || !struct_ptr) {
errno = EINVAL;
return -1;
}
if(st->buf == 0) {
/* Nothing to convert, make it empty. */
*struct_ptr = (void *)0;
return 0;
}
rval = aper_decode(0, td, (void **)&newst, st->buf, st->size, 0, 0);
if(rval.code == RC_OK) {
*struct_ptr = newst;
return 0;
} else {
/* Remove possibly partially decoded data. */
ASN_STRUCT_FREE(*td, newst);
return -1;
}
}
asn_dec_rval_t
ANY_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints, void **sptr,
asn_per_data_t *pd) {
const asn_OCTET_STRING_specifics_t *specs =
td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_SPC_ANY_specs;
size_t consumed_myself = 0;
int repeat;
ANY_t *st = (ANY_t *)*sptr;
(void)opt_codec_ctx;
(void)constraints;
/*
* Allocate the structure.
*/
if(!st) {
st = (ANY_t *)(*sptr = CALLOC(1, specs->struct_size));
if(!st) RETURN(RC_FAIL);
}
ASN_DEBUG("APER Decoding ANY type");
st->size = 0;
do {
ssize_t raw_len;
ssize_t len_bytes;
ssize_t len_bits;
void *p;
int ret;
/* Get the PER length */
raw_len = aper_get_length(pd, -1, 0, &repeat);
if(raw_len < 0) RETURN(RC_WMORE);
if(raw_len == 0 && st->buf) break;
ASN_DEBUG("Got PER length len %" ASN_PRI_SIZE ", %s (%s)", raw_len,
repeat ? "repeat" : "once", td->name);
len_bytes = raw_len;
len_bits = len_bytes * 8;
p = REALLOC(st->buf, st->size + len_bytes + 1);
if(!p) RETURN(RC_FAIL);
st->buf = (uint8_t *)p;
ret = per_get_many_bits(pd, &st->buf[st->size], 0, len_bits);
if(ret < 0) RETURN(RC_WMORE);
consumed_myself += len_bits;
st->size += len_bytes;
} while(repeat);
st->buf[st->size] = 0; /* nul-terminate */
RETURN(RC_OK);
}
asn_enc_rval_t
ANY_encode_aper(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints, const void *sptr,
asn_per_outp_t *po) {
const ANY_t *st = (const ANY_t *)sptr;
asn_enc_rval_t er = {0, 0, 0};
const uint8_t *buf;
size_t size;
int ret;
(void)constraints;
if(!st || (!st->buf && st->size)) ASN__ENCODE_FAILED;
buf = st->buf;
size = st->size;
do {
int need_eom = 0;
ssize_t may_save = aper_put_length(po, -1, size, &need_eom);
if(may_save < 0) ASN__ENCODE_FAILED;
ret = per_put_many_bits(po, buf, may_save * 8);
if(ret) ASN__ENCODE_FAILED;
buf += may_save;
size -= may_save;
assert(!(may_save & 0x07) || !size);
if(need_eom && aper_put_length(po, -1, 0, 0))
ASN__ENCODE_FAILED; /* End of Message length */
} while(size);
ASN__ENCODED_OK(er);
}

View File

@@ -4,61 +4,89 @@
*/ */
#include <asn_internal.h> #include <asn_internal.h>
#include <BIT_STRING.h> #include <BIT_STRING.h>
#include <asn_internal.h>
/* /*
* BIT STRING basic type description. * BIT STRING basic type description.
*/ */
static const ber_tlv_tag_t asn_DEF_BIT_STRING_tags[] = { static const ber_tlv_tag_t asn_DEF_BIT_STRING_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (3 << 2)) (ASN_TAG_CLASS_UNIVERSAL | (3 << 2))
}; };
asn_OCTET_STRING_specifics_t asn_SPC_BIT_STRING_specs = { asn_OCTET_STRING_specifics_t asn_SPC_BIT_STRING_specs = {
sizeof(BIT_STRING_t), sizeof(BIT_STRING_t),
offsetof(BIT_STRING_t, _asn_ctx), offsetof(BIT_STRING_t, _asn_ctx),
ASN_OSUBV_BIT ASN_OSUBV_BIT
}; };
asn_TYPE_operation_t asn_OP_BIT_STRING = { asn_TYPE_operation_t asn_OP_BIT_STRING = {
OCTET_STRING_free, /* Implemented in terms of OCTET STRING */ OCTET_STRING_free, /* Implemented in terms of OCTET STRING */
BIT_STRING_print, #if !defined(ASN_DISABLE_PRINT_SUPPORT)
BIT_STRING_compare, BIT_STRING_print,
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
OCTET_STRING_encode_der, /* Implemented in terms of OCTET STRING */
OCTET_STRING_decode_xer_binary,
BIT_STRING_encode_xer,
#ifdef ASN_DISABLE_OER_SUPPORT
0,
0,
#else #else
BIT_STRING_decode_oer, 0,
BIT_STRING_encode_oer, #endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
#endif /* ASN_DISABLE_OER_SUPPORT */ BIT_STRING_compare,
#ifdef ASN_DISABLE_PER_SUPPORT #if !defined(ASN_DISABLE_BER_SUPPORT)
0, OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
0, OCTET_STRING_encode_der, /* Implemented in terms of OCTET STRING */
0,
0,
#else #else
BIT_STRING_decode_uper, /* Unaligned PER decoder */ 0,
BIT_STRING_encode_uper, /* Unaligned PER encoder */ 0,
OCTET_STRING_decode_aper, /* Aligned PER decoder */ #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
OCTET_STRING_encode_aper, /* Aligned PER encoder */ #if !defined(ASN_DISABLE_XER_SUPPORT)
#endif /* ASN_DISABLE_PER_SUPPORT */ OCTET_STRING_decode_xer_binary,
BIT_STRING_random_fill, BIT_STRING_encode_xer,
0 /* Use generic outmost tag fetcher */ #else
0,
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
BIT_STRING_decode_oer,
BIT_STRING_encode_oer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
BIT_STRING_decode_uper, /* Unaligned PER decoder */
BIT_STRING_encode_uper, /* Unaligned PER encoder */
#else
0,
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
OCTET_STRING_decode_aper, /* Aligned PER decoder */
OCTET_STRING_encode_aper, /* Aligned PER encoder */
#else
0,
0,
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
BIT_STRING_random_fill,
#else
0,
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
0 /* Use generic outmost tag fetcher */
}; };
asn_TYPE_descriptor_t asn_DEF_BIT_STRING = { asn_TYPE_descriptor_t asn_DEF_BIT_STRING = {
"BIT STRING", "BIT STRING",
"BIT_STRING", "BIT_STRING",
&asn_OP_BIT_STRING, &asn_OP_BIT_STRING,
asn_DEF_BIT_STRING_tags, asn_DEF_BIT_STRING_tags,
sizeof(asn_DEF_BIT_STRING_tags) sizeof(asn_DEF_BIT_STRING_tags)
/ sizeof(asn_DEF_BIT_STRING_tags[0]), / sizeof(asn_DEF_BIT_STRING_tags[0]),
asn_DEF_BIT_STRING_tags, /* Same as above */ asn_DEF_BIT_STRING_tags, /* Same as above */
sizeof(asn_DEF_BIT_STRING_tags) sizeof(asn_DEF_BIT_STRING_tags)
/ sizeof(asn_DEF_BIT_STRING_tags[0]), / sizeof(asn_DEF_BIT_STRING_tags[0]),
{ 0, 0, BIT_STRING_constraint }, {
0, 0, /* No members */ #if !defined(ASN_DISABLE_OER_SUPPORT)
&asn_SPC_BIT_STRING_specs 0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
BIT_STRING_constraint
},
0, 0, /* No members */
&asn_SPC_BIT_STRING_specs
}; };
/* /*
@@ -87,136 +115,10 @@ BIT_STRING_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
return 0; return 0;
} }
static const char *_bit_pattern[16] = {
"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
};
asn_enc_rval_t
BIT_STRING_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_enc_rval_t er = {0, 0, 0};
char scratch[128];
char *p = scratch;
char *scend = scratch + (sizeof(scratch) - 10);
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
int xcan = (flags & XER_F_CANONICAL);
uint8_t *buf;
uint8_t *end;
if(!st || !st->buf)
ASN__ENCODE_FAILED;
er.encoded = 0;
buf = st->buf;
end = buf + st->size - 1; /* Last byte is special */
/*
* Binary dump
*/
for(; buf < end; buf++) {
int v = *buf;
int nline = xcan?0:(((buf - st->buf) % 8) == 0);
if(p >= scend || nline) {
ASN__CALLBACK(scratch, p - scratch);
p = scratch;
if(nline) ASN__TEXT_INDENT(1, ilevel);
}
memcpy(p + 0, _bit_pattern[v >> 4], 4);
memcpy(p + 4, _bit_pattern[v & 0x0f], 4);
p += 8;
}
if(!xcan && ((buf - st->buf) % 8) == 0)
ASN__TEXT_INDENT(1, ilevel);
ASN__CALLBACK(scratch, p - scratch);
p = scratch;
if(buf == end) {
int v = *buf;
int ubits = st->bits_unused;
int i;
for(i = 7; i >= ubits; i--)
*p++ = (v & (1 << i)) ? 0x31 : 0x30;
ASN__CALLBACK(scratch, p - scratch);
}
if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
ASN__ENCODED_OK(er);
cb_failed:
ASN__ENCODE_FAILED;
}
/*
* BIT STRING specific contents printer.
*/
int
BIT_STRING_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
const char * const h2c = "0123456789ABCDEF";
char scratch[64];
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
uint8_t *buf;
uint8_t *end;
char *p = scratch;
(void)td; /* Unused argument */
if(!st || !st->buf)
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
ilevel++;
buf = st->buf;
end = buf + st->size;
/*
* Hexadecimal dump.
*/
for(; buf < end; buf++) {
if((buf - st->buf) % 16 == 0 && (st->size > 16)
&& buf != st->buf) {
_i_INDENT(1);
/* Dump the string */
if(cb(scratch, p - scratch, app_key) < 0) return -1;
p = scratch;
}
*p++ = h2c[*buf >> 4];
*p++ = h2c[*buf & 0x0F];
*p++ = 0x20;
}
if(p > scratch) {
p--; /* Eat the tailing space */
if((st->size > 16)) {
_i_INDENT(1);
}
/* Dump the incomplete 16-bytes row */
if(cb(scratch, p - scratch, app_key) < 0)
return -1;
}
if(st->bits_unused) {
int ret = snprintf(scratch, sizeof(scratch), " (%d bit%s unused)",
st->bits_unused, st->bits_unused == 1 ? "" : "s");
assert(ret > 0 && ret < (ssize_t)sizeof(scratch));
if(ret > 0 && ret < (ssize_t)sizeof(scratch)
&& cb(scratch, ret, app_key) < 0)
return -1;
}
return 0;
}
/* /*
* Non-destructively remove the trailing 0-bits from the given bit string. * Non-destructively remove the trailing 0-bits from the given bit string.
*/ */
static const BIT_STRING_t * const BIT_STRING_t *
BIT_STRING__compactify(const BIT_STRING_t *st, BIT_STRING_t *tmp) { BIT_STRING__compactify(const BIT_STRING_t *st, BIT_STRING_t *tmp) {
const uint8_t *b; const uint8_t *b;
union { union {
@@ -271,6 +173,7 @@ BIT_STRING_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
const BIT_STRING_t *b = BIT_STRING__compactify(bptr, &compact_b); const BIT_STRING_t *b = BIT_STRING__compactify(bptr, &compact_b);
const asn_OCTET_STRING_specifics_t *specs = td->specifics; const asn_OCTET_STRING_specifics_t *specs = td->specifics;
(void)specs;
assert(specs && specs->subvariant == ASN_OSUBV_BIT); assert(specs && specs->subvariant == ASN_OSUBV_BIT);
if(a && b) { if(a && b) {
@@ -303,354 +206,3 @@ BIT_STRING_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
return 1; return 1;
} }
} }
#ifndef ASN_DISABLE_PER_SUPPORT
#undef RETURN
#define RETURN(_code) \
do { \
asn_dec_rval_t tmprval; \
tmprval.code = _code; \
tmprval.consumed = consumed_myself; \
return tmprval; \
} while(0)
static asn_per_constraint_t asn_DEF_BIT_STRING_constraint_size = {
APC_SEMI_CONSTRAINED, -1, -1, 0, 0};
asn_dec_rval_t
BIT_STRING_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints, void **sptr,
asn_per_data_t *pd) {
const asn_OCTET_STRING_specifics_t *specs = td->specifics
? (const asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_SPC_BIT_STRING_specs;
const asn_per_constraints_t *pc =
constraints ? constraints : td->encoding_constraints.per_constraints;
const asn_per_constraint_t *csiz;
asn_dec_rval_t rval = { RC_OK, 0 };
BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
ssize_t consumed_myself = 0;
int repeat;
(void)opt_codec_ctx;
if(pc) {
csiz = &pc->size;
} else {
csiz = &asn_DEF_BIT_STRING_constraint_size;
}
if(specs->subvariant != ASN_OSUBV_BIT) {
ASN_DEBUG("Subvariant %d is not BIT OSUBV_BIT", specs->subvariant);
RETURN(RC_FAIL);
}
/*
* Allocate the string.
*/
if(!st) {
st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
if(!st) RETURN(RC_FAIL);
}
ASN_DEBUG("PER Decoding %s size %ld .. %ld bits %d",
csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible",
csiz->lower_bound, csiz->upper_bound, csiz->effective_bits);
if(csiz->flags & APC_EXTENSIBLE) {
int inext = per_get_few_bits(pd, 1);
if(inext < 0) RETURN(RC_WMORE);
if(inext) {
csiz = &asn_DEF_BIT_STRING_constraint_size;
}
}
if(csiz->effective_bits >= 0) {
FREEMEM(st->buf);
st->size = (csiz->upper_bound + 7) >> 3;
st->buf = (uint8_t *)MALLOC(st->size + 1);
if(!st->buf) { st->size = 0; RETURN(RC_FAIL); }
}
/* X.691, #16.5: zero-length encoding */
/* X.691, #16.6: short fixed length encoding (up to 2 octets) */
/* X.691, #16.7: long fixed length encoding (up to 64K octets) */
if(csiz->effective_bits == 0) {
int ret;
ASN_DEBUG("Encoding BIT STRING size %ld", csiz->upper_bound);
ret = per_get_many_bits(pd, st->buf, 0, csiz->upper_bound);
if(ret < 0) RETURN(RC_WMORE);
consumed_myself += csiz->upper_bound;
st->buf[st->size] = 0;
st->bits_unused = (8 - (csiz->upper_bound & 0x7)) & 0x7;
RETURN(RC_OK);
}
st->size = 0;
do {
ssize_t raw_len;
ssize_t len_bytes;
ssize_t len_bits;
void *p;
int ret;
/* Get the PER length */
raw_len = uper_get_length(pd, csiz->effective_bits, csiz->lower_bound,
&repeat);
if(raw_len < 0) RETURN(RC_WMORE);
if(raw_len == 0 && st->buf) break;
ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
(long)csiz->effective_bits, (long)raw_len,
repeat ? "repeat" : "once", td->name);
len_bits = raw_len;
len_bytes = (len_bits + 7) >> 3;
if(len_bits & 0x7) st->bits_unused = 8 - (len_bits & 0x7);
/* len_bits be multiple of 16K if repeat is set */
p = REALLOC(st->buf, st->size + len_bytes + 1);
if(!p) RETURN(RC_FAIL);
st->buf = (uint8_t *)p;
ret = per_get_many_bits(pd, &st->buf[st->size], 0, len_bits);
if(ret < 0) RETURN(RC_WMORE);
st->size += len_bytes;
} while(repeat);
st->buf[st->size] = 0; /* nul-terminate */
return rval;
}
asn_enc_rval_t
BIT_STRING_encode_uper(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, asn_per_outp_t *po) {
const asn_OCTET_STRING_specifics_t *specs =
td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_SPC_BIT_STRING_specs;
const asn_per_constraints_t *pc =
constraints ? constraints : td->encoding_constraints.per_constraints;
const asn_per_constraint_t *csiz;
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
BIT_STRING_t compact_bstr; /* Do not modify this directly! */
asn_enc_rval_t er = { 0, 0, 0 };
int inext = 0; /* Lies not within extension root */
size_t size_in_bits;
const uint8_t *buf;
int ret;
int ct_extensible;
if(!st || (!st->buf && st->size))
ASN__ENCODE_FAILED;
if(specs->subvariant == ASN_OSUBV_BIT) {
if((st->size == 0 && st->bits_unused) || (st->bits_unused & ~7))
ASN__ENCODE_FAILED;
} else {
ASN__ENCODE_FAILED;
}
if(pc) {
csiz = &pc->size;
} else {
csiz = &asn_DEF_BIT_STRING_constraint_size;
}
ct_extensible = csiz->flags & APC_EXTENSIBLE;
/* Figure out the size without the trailing bits */
st = BIT_STRING__compactify(st, &compact_bstr);
size_in_bits = 8 * st->size - st->bits_unused;
ASN_DEBUG(
"Encoding %s into %" ASN_PRI_SIZE " bits"
" (%ld..%ld, effective %d)%s",
td->name, size_in_bits, csiz->lower_bound, csiz->upper_bound,
csiz->effective_bits, ct_extensible ? " EXT" : "");
/* Figure out whether size lies within PER visible constraint */
if(csiz->effective_bits >= 0) {
if((ssize_t)size_in_bits > csiz->upper_bound) {
if(ct_extensible) {
csiz = &asn_DEF_BIT_STRING_constraint_size;
inext = 1;
} else {
ASN__ENCODE_FAILED;
}
}
} else {
inext = 0;
}
if(ct_extensible) {
/* Declare whether length is [not] within extension root */
if(per_put_few_bits(po, inext, 1))
ASN__ENCODE_FAILED;
}
if(csiz->effective_bits >= 0 && !inext) {
int add_trailer = (ssize_t)size_in_bits < csiz->lower_bound;
ASN_DEBUG(
"Encoding %" ASN_PRI_SIZE " bytes (%ld), length (in %d bits) trailer %d; actual "
"value %" ASN_PRI_SSIZE "",
st->size, size_in_bits - csiz->lower_bound, csiz->effective_bits,
add_trailer,
add_trailer ? 0 : (ssize_t)size_in_bits - csiz->lower_bound);
ret = per_put_few_bits(
po, add_trailer ? 0 : (ssize_t)size_in_bits - csiz->lower_bound,
csiz->effective_bits);
if(ret) ASN__ENCODE_FAILED;
ret = per_put_many_bits(po, st->buf, size_in_bits);
if(ret) ASN__ENCODE_FAILED;
if(add_trailer) {
static const uint8_t zeros[16];
size_t trailing_zero_bits = csiz->lower_bound - size_in_bits;
while(trailing_zero_bits > 0) {
if(trailing_zero_bits > 8 * sizeof(zeros)) {
ret = per_put_many_bits(po, zeros, 8 * sizeof(zeros));
trailing_zero_bits -= 8 * sizeof(zeros);
} else {
ret = per_put_many_bits(po, zeros, trailing_zero_bits);
trailing_zero_bits = 0;
}
if(ret) ASN__ENCODE_FAILED;
}
}
ASN__ENCODED_OK(er);
}
ASN_DEBUG("Encoding %" ASN_PRI_SIZE " bytes", st->size);
buf = st->buf;
do {
int need_eom = 0;
ssize_t maySave = uper_put_length(po, size_in_bits, &need_eom);
if(maySave < 0) ASN__ENCODE_FAILED;
ASN_DEBUG("Encoding %" ASN_PRI_SSIZE " of %" ASN_PRI_SIZE "", maySave, size_in_bits);
ret = per_put_many_bits(po, buf, maySave);
if(ret) ASN__ENCODE_FAILED;
buf += maySave >> 3;
size_in_bits -= maySave;
assert(!(maySave & 0x07) || !size_in_bits);
if(need_eom && uper_put_length(po, 0, 0))
ASN__ENCODE_FAILED; /* End of Message length */
} while(size_in_bits);
ASN__ENCODED_OK(er);
}
#endif /* ASN_DISABLE_PER_SUPPORT */
asn_random_fill_result_t
BIT_STRING_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
const asn_encoding_constraints_t *constraints,
size_t max_length) {
const asn_OCTET_STRING_specifics_t *specs =
td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_SPC_BIT_STRING_specs;
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
static unsigned lengths[] = {0, 1, 2, 3, 4, 8,
126, 127, 128, 16383, 16384, 16385,
65534, 65535, 65536, 65537};
uint8_t *buf;
uint8_t *bend;
uint8_t *b;
size_t rnd_bits, rnd_len;
BIT_STRING_t *st;
if(max_length == 0) return result_skipped;
switch(specs->subvariant) {
case ASN_OSUBV_ANY:
return result_failed;
case ASN_OSUBV_BIT:
break;
default:
break;
}
/* Figure out how far we should go */
rnd_bits = lengths[asn_random_between(
0, sizeof(lengths) / sizeof(lengths[0]) - 1)];
if(!constraints || !constraints->per_constraints)
constraints = &td->encoding_constraints;
if(constraints->per_constraints) {
const asn_per_constraint_t *pc = &constraints->per_constraints->size;
if(pc->flags & APC_CONSTRAINED) {
long suggested_upper_bound = pc->upper_bound < (ssize_t)max_length
? pc->upper_bound
: (ssize_t)max_length;
if(max_length < (size_t)pc->lower_bound) {
return result_skipped;
}
if(pc->flags & APC_EXTENSIBLE) {
switch(asn_random_between(0, 5)) {
case 0:
if(pc->lower_bound > 0) {
rnd_bits = pc->lower_bound - 1;
break;
}
/* Fall through */
case 1:
rnd_bits = pc->upper_bound + 1;
break;
case 2:
/* Keep rnd_bits from the table */
if(rnd_bits < max_length) {
break;
}
/* Fall through */
default:
rnd_bits = asn_random_between(pc->lower_bound,
suggested_upper_bound);
}
} else {
rnd_bits =
asn_random_between(pc->lower_bound, suggested_upper_bound);
}
} else {
rnd_bits = asn_random_between(0, max_length - 1);
}
} else if(rnd_bits >= max_length) {
rnd_bits = asn_random_between(0, max_length - 1);
}
rnd_len = (rnd_bits + 7) / 8;
buf = CALLOC(1, rnd_len + 1);
if(!buf) return result_failed;
bend = &buf[rnd_len];
for(b = buf; b < bend; b++) {
*(uint8_t *)b = asn_random_between(0, 255);
}
*b = 0; /* Zero-terminate just in case. */
if(*sptr) {
st = *sptr;
FREEMEM(st->buf);
} else {
st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
if(!st) {
FREEMEM(buf);
return result_failed;
}
}
st->buf = buf;
st->size = rnd_len;
st->bits_unused = (8 - (rnd_bits & 0x7)) & 0x7;
if(st->bits_unused) {
assert(st->size > 0);
st->buf[st->size-1] &= 0xff << st->bits_unused;
}
result_ok.length = st->size;
return result_ok;
}

View File

@@ -24,22 +24,45 @@ extern asn_TYPE_descriptor_t asn_DEF_BIT_STRING;
extern asn_TYPE_operation_t asn_OP_BIT_STRING; extern asn_TYPE_operation_t asn_OP_BIT_STRING;
extern asn_OCTET_STRING_specifics_t asn_SPC_BIT_STRING_specs; extern asn_OCTET_STRING_specifics_t asn_SPC_BIT_STRING_specs;
asn_struct_print_f BIT_STRING_print; /* Human-readable output */ #define BIT_STRING_free OCTET_STRING_free
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
asn_struct_print_f BIT_STRING_print; /* Human-readable output */
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
asn_struct_compare_f BIT_STRING_compare; asn_struct_compare_f BIT_STRING_compare;
asn_constr_check_f BIT_STRING_constraint; asn_constr_check_f BIT_STRING_constraint;
#if !defined(ASN_DISABLE_BER_SUPPORT)
#define BIT_STRING_decode_ber OCTET_STRING_decode_ber
#define BIT_STRING_encode_der OCTET_STRING_encode_der
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
#if !defined(ASN_DISABLE_XER_SUPPORT)
#define BIT_STRING_decode_xer OCTET_STRING_decode_xer_binary
xer_type_encoder_f BIT_STRING_encode_xer; xer_type_encoder_f BIT_STRING_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
oer_type_decoder_f BIT_STRING_decode_oer; oer_type_decoder_f BIT_STRING_decode_oer;
oer_type_encoder_f BIT_STRING_encode_oer; oer_type_encoder_f BIT_STRING_encode_oer;
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
per_type_decoder_f BIT_STRING_decode_uper; per_type_decoder_f BIT_STRING_decode_uper;
per_type_encoder_f BIT_STRING_encode_uper; per_type_encoder_f BIT_STRING_encode_uper;
asn_random_fill_f BIT_STRING_random_fill; #endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
#define BIT_STRING_decode_aper OCTET_STRING_decode_aper
#define BIT_STRING_encode_aper OCTET_STRING_encode_aper
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#define BIT_STRING_free OCTET_STRING_free #if !defined(ASN_DISABLE_RFILL_SUPPORT)
#define BIT_STRING_decode_ber OCTET_STRING_decode_ber asn_random_fill_f BIT_STRING_random_fill;
#define BIT_STRING_encode_der OCTET_STRING_encode_der #endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
#define BIT_STRING_decode_xer OCTET_STRING_decode_xer_binary
#define BIT_STRING_decode_aper OCTET_STRING_decode_aper const BIT_STRING_t *BIT_STRING__compactify(const BIT_STRING_t *st, BIT_STRING_t *tmp);
#define BIT_STRING_encode_aper OCTET_STRING_encode_aper
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <BIT_STRING.h>
/*
* BIT STRING specific contents printer.
*/
int
BIT_STRING_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
const char * const h2c = "0123456789ABCDEF";
char scratch[64];
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
uint8_t *buf;
uint8_t *end;
char *p = scratch;
(void)td; /* Unused argument */
if(!st || !st->buf)
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
ilevel++;
buf = st->buf;
end = buf + st->size;
/*
* Hexadecimal dump.
*/
for(; buf < end; buf++) {
if((buf - st->buf) % 16 == 0 && (st->size > 16)
&& buf != st->buf) {
_i_INDENT(1);
/* Dump the string */
if(cb(scratch, p - scratch, app_key) < 0) return -1;
p = scratch;
}
*p++ = h2c[*buf >> 4];
*p++ = h2c[*buf & 0x0F];
*p++ = 0x20;
}
if(p > scratch) {
p--; /* Eat the tailing space */
if((st->size > 16)) {
_i_INDENT(1);
}
/* Dump the incomplete 16-bytes row */
if(cb(scratch, p - scratch, app_key) < 0)
return -1;
}
if(st->bits_unused) {
int ret = snprintf(scratch, sizeof(scratch), " (%d bit%s unused)",
st->bits_unused, st->bits_unused == 1 ? "" : "s");
assert(ret > 0 && ret < (ssize_t)sizeof(scratch));
if(ret > 0 && ret < (ssize_t)sizeof(scratch)
&& cb(scratch, ret, app_key) < 0)
return -1;
}
return 0;
}

View File

@@ -0,0 +1,124 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <BIT_STRING.h>
asn_random_fill_result_t
BIT_STRING_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
const asn_encoding_constraints_t *constraints,
size_t max_length) {
const asn_OCTET_STRING_specifics_t *specs =
td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_SPC_BIT_STRING_specs;
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
static unsigned lengths[] = {0, 1, 2, 3, 4, 8,
126, 127, 128, 16383, 16384, 16385,
65534, 65535, 65536, 65537};
uint8_t *buf;
uint8_t *bend;
uint8_t *b;
size_t rnd_bits, rnd_len;
BIT_STRING_t *st;
if(max_length == 0) return result_skipped;
switch(specs->subvariant) {
case ASN_OSUBV_ANY:
return result_failed;
case ASN_OSUBV_BIT:
break;
default:
break;
}
/* Figure out how far we should go */
rnd_bits = lengths[asn_random_between(
0, sizeof(lengths) / sizeof(lengths[0]) - 1)];
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
if(!constraints || !constraints->per_constraints)
constraints = &td->encoding_constraints;
if(constraints->per_constraints) {
const asn_per_constraint_t *pc = &constraints->per_constraints->size;
if(pc->flags & APC_CONSTRAINED) {
long suggested_upper_bound = pc->upper_bound < (ssize_t)max_length
? pc->upper_bound
: (ssize_t)max_length;
if(max_length < (size_t)pc->lower_bound) {
return result_skipped;
}
if(pc->flags & APC_EXTENSIBLE) {
switch(asn_random_between(0, 5)) {
case 0:
if(pc->lower_bound > 0) {
rnd_bits = pc->lower_bound - 1;
break;
}
/* Fall through */
case 1:
rnd_bits = pc->upper_bound + 1;
break;
case 2:
/* Keep rnd_bits from the table */
if(rnd_bits < max_length) {
break;
}
/* Fall through */
default:
rnd_bits = asn_random_between(pc->lower_bound,
suggested_upper_bound);
}
} else {
rnd_bits =
asn_random_between(pc->lower_bound, suggested_upper_bound);
}
} else {
rnd_bits = asn_random_between(0, max_length - 1);
}
} else {
#else
if(!constraints) constraints = &td->encoding_constraints;
{
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
if(rnd_bits >= max_length) {
rnd_bits = asn_random_between(0, max_length - 1);
}
}
rnd_len = (rnd_bits + 7) / 8;
buf = CALLOC(1, rnd_len + 1);
if(!buf) return result_failed;
bend = &buf[rnd_len];
for(b = buf; b < bend; b++) {
*(uint8_t *)b = asn_random_between(0, 255);
}
*b = 0; /* Zero-terminate just in case. */
if(*sptr) {
st = *sptr;
FREEMEM(st->buf);
} else {
st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
if(!st) {
FREEMEM(buf);
return result_failed;
}
}
st->buf = buf;
st->size = rnd_len;
st->bits_unused = (8 - (rnd_bits & 0x7)) & 0x7;
if(st->bits_unused) {
assert(st->size > 0);
st->buf[st->size-1] &= 0xff << st->bits_unused;
}
result_ok.length = st->size;
return result_ok;
}

View File

@@ -9,50 +9,78 @@
* GraphicString basic type description. * GraphicString basic type description.
*/ */
static const ber_tlv_tag_t asn_DEF_GraphicString_tags[] = { static const ber_tlv_tag_t asn_DEF_GraphicString_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (25 << 2)), /* [UNIVERSAL 25] IMPLICIT ...*/ (ASN_TAG_CLASS_UNIVERSAL | (25 << 2)), /* [UNIVERSAL 25] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */ (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
}; };
asn_TYPE_operation_t asn_OP_GraphicString = { asn_TYPE_operation_t asn_OP_GraphicString = {
OCTET_STRING_free, OCTET_STRING_free,
OCTET_STRING_print, /* non-ascii string */ #if !defined(ASN_DISABLE_PRINT_SUPPORT)
OCTET_STRING_compare, OCTET_STRING_print, /* non-ascii string */
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_hex,
OCTET_STRING_encode_xer, /* Can't expect it to be ASCII/UTF8 */
#ifdef ASN_DISABLE_OER_SUPPORT
0,
0,
#else #else
OCTET_STRING_decode_oer, 0,
OCTET_STRING_encode_oer, #endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
#endif /* ASN_DISABLE_OER_SUPPORT */ OCTET_STRING_compare,
#ifdef ASN_DISABLE_PER_SUPPORT #if !defined(ASN_DISABLE_BER_SUPPORT)
0, OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
0, OCTET_STRING_encode_der,
0,
0,
#else #else
OCTET_STRING_decode_uper, /* Implemented in terms of OCTET STRING */ 0,
OCTET_STRING_encode_uper, 0,
OCTET_STRING_decode_aper, /* Implemented in terms of OCTET STRING */ #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
OCTET_STRING_encode_aper, #if !defined(ASN_DISABLE_XER_SUPPORT)
#endif /* ASN_DISABLE_PER_SUPPORT */ OCTET_STRING_decode_xer_hex,
OCTET_STRING_random_fill, OCTET_STRING_encode_xer, /* Can't expect it to be ASCII/UTF8 */
0 /* Use generic outmost tag fetcher */ #else
0,
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OCTET_STRING_decode_oer,
OCTET_STRING_encode_oer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
OCTET_STRING_decode_uper, /* Implemented in terms of OCTET STRING */
OCTET_STRING_encode_uper,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
OCTET_STRING_decode_aper, /* Implemented in terms of OCTET STRING */
OCTET_STRING_encode_aper,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
OCTET_STRING_random_fill,
#else
0,
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
0 /* Use generic outmost tag fetcher */
}; };
asn_TYPE_descriptor_t asn_DEF_GraphicString = { asn_TYPE_descriptor_t asn_DEF_GraphicString = {
"GraphicString", "GraphicString",
"GraphicString", "GraphicString",
&asn_OP_GraphicString, &asn_OP_GraphicString,
asn_DEF_GraphicString_tags, asn_DEF_GraphicString_tags,
sizeof(asn_DEF_GraphicString_tags) sizeof(asn_DEF_GraphicString_tags)
/ sizeof(asn_DEF_GraphicString_tags[0]) - 1, / sizeof(asn_DEF_GraphicString_tags[0]) - 1,
asn_DEF_GraphicString_tags, asn_DEF_GraphicString_tags,
sizeof(asn_DEF_GraphicString_tags) sizeof(asn_DEF_GraphicString_tags)
/ sizeof(asn_DEF_GraphicString_tags[0]), / sizeof(asn_DEF_GraphicString_tags[0]),
{ 0, 0, asn_generic_unknown_constraint }, {
0, 0, /* No members */ #if !defined(ASN_DISABLE_OER_SUPPORT)
0 /* No specifics */ 0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
asn_generic_unknown_constraint
},
0, 0, /* No members */
0 /* No specifics */
}; };

View File

@@ -16,18 +16,34 @@ typedef OCTET_STRING_t GraphicString_t; /* Implemented via OCTET STRING */
extern asn_TYPE_descriptor_t asn_DEF_GraphicString; extern asn_TYPE_descriptor_t asn_DEF_GraphicString;
extern asn_TYPE_operation_t asn_OP_GraphicString; extern asn_TYPE_operation_t asn_OP_GraphicString;
#define GraphicString_free OCTET_STRING_free #define GraphicString_free OCTET_STRING_free
#define GraphicString_print OCTET_STRING_print
#define GraphicString_compare OCTET_STRING_compare #if !defined(ASN_DISABLE_PRINT_SUPPORT)
#define GraphicString_constraint asn_generic_unknown_constraint #define GraphicString_print OCTET_STRING_print
#define GraphicString_decode_ber OCTET_STRING_decode_ber #endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
#define GraphicString_encode_der OCTET_STRING_encode_der
#define GraphicString_decode_xer OCTET_STRING_decode_xer_hex #define GraphicString_compare OCTET_STRING_compare
#define GraphicString_encode_xer OCTET_STRING_encode_xer
#define GraphicString_decode_uper OCTET_STRING_decode_uper #define GraphicString_constraint asn_generic_unknown_constraint
#define GraphicString_encode_uper OCTET_STRING_encode_uper
#define GraphicString_decode_aper OCTET_STRING_decode_aper #if !defined(ASN_DISABLE_BER_SUPPORT)
#define GraphicString_encode_aper OCTET_STRING_encode_aper #define GraphicString_decode_ber OCTET_STRING_decode_ber
#define GraphicString_encode_der OCTET_STRING_encode_der
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
#if !defined(ASN_DISABLE_XER_SUPPORT)
#define GraphicString_decode_xer OCTET_STRING_decode_xer_hex
#define GraphicString_encode_xer OCTET_STRING_encode_xer
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
#define GraphicString_decode_uper OCTET_STRING_decode_uper
#define GraphicString_encode_uper OCTET_STRING_encode_uper
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
#define GraphicString_decode_aper OCTET_STRING_decode_aper
#define GraphicString_encode_aper OCTET_STRING_encode_aper
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#ifdef __cplusplus #ifdef __cplusplus
} }

File diff suppressed because it is too large Load Diff

View File

@@ -35,21 +35,48 @@ typedef struct asn_INTEGER_specifics_s {
int field_unsigned; /* Signed=0, unsigned=1 */ int field_unsigned; /* Signed=0, unsigned=1 */
} asn_INTEGER_specifics_t; } asn_INTEGER_specifics_t;
#define INTEGER_free ASN__PRIMITIVE_TYPE_free ssize_t INTEGER__dump(const asn_TYPE_descriptor_t *td,
#define INTEGER_decode_ber ber_decode_primitive const INTEGER_t *st,
#define INTEGER_constraint asn_generic_no_constraint asn_app_consume_bytes_f *cb,
void *app_key, int plainOrXER);
#define INTEGER_free ASN__PRIMITIVE_TYPE_free
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
asn_struct_print_f INTEGER_print; asn_struct_print_f INTEGER_print;
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
asn_struct_compare_f INTEGER_compare; asn_struct_compare_f INTEGER_compare;
#define INTEGER_constraint asn_generic_no_constraint
#if !defined(ASN_DISABLE_BER_SUPPORT)
#define INTEGER_decode_ber ber_decode_primitive
der_type_encoder_f INTEGER_encode_der; der_type_encoder_f INTEGER_encode_der;
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
#if !defined(ASN_DISABLE_XER_SUPPORT)
xer_type_decoder_f INTEGER_decode_xer; xer_type_decoder_f INTEGER_decode_xer;
xer_type_encoder_f INTEGER_encode_xer; xer_type_encoder_f INTEGER_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
oer_type_decoder_f INTEGER_decode_oer; oer_type_decoder_f INTEGER_decode_oer;
oer_type_encoder_f INTEGER_encode_oer; oer_type_encoder_f INTEGER_encode_oer;
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
per_type_decoder_f INTEGER_decode_uper; per_type_decoder_f INTEGER_decode_uper;
per_type_encoder_f INTEGER_encode_uper; per_type_encoder_f INTEGER_encode_uper;
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
per_type_decoder_f INTEGER_decode_aper; per_type_decoder_f INTEGER_decode_aper;
per_type_encoder_f INTEGER_encode_aper; per_type_encoder_f INTEGER_encode_aper;
asn_random_fill_f INTEGER_random_fill; #endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
asn_random_fill_f INTEGER_random_fill;
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
/*********************************** /***********************************
* Some handy conversion routines. * * Some handy conversion routines. *

View File

@@ -0,0 +1,304 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <INTEGER.h>
asn_dec_rval_t
INTEGER_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
asn_dec_rval_t rval = { RC_OK, 0 };
INTEGER_t *st = (INTEGER_t *)*sptr;
const asn_per_constraint_t *ct;
int repeat;
(void)opt_codec_ctx;
if(!st) {
st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
if(!st) ASN__DECODE_FAILED;
}
if(!constraints) constraints = td->encoding_constraints.per_constraints;
ct = constraints ? &constraints->value : 0;
if(ct && ct->flags & APC_EXTENSIBLE) {
int inext = per_get_few_bits(pd, 1);
if(inext < 0) ASN__DECODE_STARVED;
if(inext) ct = 0;
}
FREEMEM(st->buf);
st->buf = 0;
st->size = 0;
if(ct) {
if(ct->flags & APC_SEMI_CONSTRAINED) {
st->buf = (uint8_t *)CALLOC(1, 2);
if(!st->buf) ASN__DECODE_FAILED;
st->size = 1;
} else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) {
size_t size = (ct->range_bits + 7) >> 3;
st->buf = (uint8_t *)MALLOC(1 + size + 1);
if(!st->buf) ASN__DECODE_FAILED;
st->size = size;
}
}
/* X.691, #12.2.2 */
if(ct && ct->flags != APC_UNCONSTRAINED) {
/* #10.5.6 */
ASN_DEBUG("Integer with range %d bits", ct->range_bits);
if(ct->range_bits >= 0) {
if (ct->range_bits > 16) {
int max_range_bytes = (ct->range_bits >> 3) +
(((ct->range_bits % 8) > 0) ? 1 : 0);
int length = 0, i;
long value = 0;
for (i = 1; ; i++) {
int upper = 1 << i;
if (upper >= max_range_bytes)
break;
}
ASN_DEBUG("Can encode %d (%d bytes) in %d bits", ct->range_bits,
max_range_bytes, i);
if ((length = per_get_few_bits(pd, i)) < 0)
ASN__DECODE_FAILED;
/* X.691 #12.2.6 length determinant + lb (1) */
length += 1;
ASN_DEBUG("Got length %d", length);
if (aper_get_align(pd) != 0)
ASN__DECODE_FAILED;
while (length--) {
int buf = per_get_few_bits(pd, 8);
if (buf < 0)
ASN__DECODE_FAILED;
value += (((long)buf) << (8 * length));
}
value += ct->lower_bound;
if((specs && specs->field_unsigned)
? asn_uint642INTEGER(st, (unsigned long)value)
: asn_int642INTEGER(st, value))
ASN__DECODE_FAILED;
ASN_DEBUG("Got value %ld + low %ld",
value, ct->lower_bound);
} else {
long value = 0;
if (ct->range_bits < 8) {
value = per_get_few_bits(pd, ct->range_bits);
if(value < 0) ASN__DECODE_STARVED;
} else if (ct->range_bits == 8) {
if (aper_get_align(pd) < 0)
ASN__DECODE_FAILED;
value = per_get_few_bits(pd, ct->range_bits);
if(value < 0) ASN__DECODE_STARVED;
} else {
/* Align */
if (aper_get_align(pd) < 0)
ASN__DECODE_FAILED;
value = per_get_few_bits(pd, 16);
if(value < 0) ASN__DECODE_STARVED;
}
value += ct->lower_bound;
if((specs && specs->field_unsigned)
? asn_ulong2INTEGER(st, value)
: asn_long2INTEGER(st, value))
ASN__DECODE_FAILED;
ASN_DEBUG("Got value %ld + low %ld",
value, ct->lower_bound);
}
return rval;
} else {
ASN__DECODE_FAILED;
}
} else {
ASN_DEBUG("Decoding unconstrained integer %s", td->name);
}
/* X.691, #12.2.3, #12.2.4 */
do {
ssize_t len;
void *p;
int ret;
/* Get the PER length */
len = aper_get_length(pd, -1, -1, &repeat);
if(len < 0) ASN__DECODE_STARVED;
p = REALLOC(st->buf, st->size + len + 1);
if(!p) ASN__DECODE_FAILED;
st->buf = (uint8_t *)p;
ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len);
if(ret < 0) ASN__DECODE_STARVED;
st->size += len;
} while(repeat);
st->buf[st->size] = 0; /* JIC */
/* #12.2.3 */
if(ct && ct->lower_bound) {
/*
* TODO: replace by in-place arithmetics.
*/
long value;
if(asn_INTEGER2long(st, &value))
ASN__DECODE_FAILED;
if(asn_long2INTEGER(st, value + ct->lower_bound))
ASN__DECODE_FAILED;
}
return rval;
}
asn_enc_rval_t
INTEGER_encode_aper(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, asn_per_outp_t *po) {
const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
asn_enc_rval_t er = {0,0,0};
const INTEGER_t *st = (const INTEGER_t *)sptr;
const uint8_t *buf;
const uint8_t *end;
const asn_per_constraint_t *ct;
long value = 0;
if(!st || st->size == 0) ASN__ENCODE_FAILED;
if(!constraints) constraints = td->encoding_constraints.per_constraints;
ct = constraints ? &constraints->value : 0;
er.encoded = 0;
if(ct) {
int inext = 0;
if(specs && specs->field_unsigned) {
unsigned long uval;
if(asn_INTEGER2ulong(st, &uval))
ASN__ENCODE_FAILED;
/* Check proper range */
if(ct->flags & APC_SEMI_CONSTRAINED) {
if(uval < (unsigned long)ct->lower_bound)
inext = 1;
} else if(ct->range_bits >= 0) {
if(uval < (unsigned long)ct->lower_bound
|| uval > (unsigned long)ct->upper_bound)
inext = 1;
}
ASN_DEBUG("Value %lu (%02x/%lu) lb %ld ub %ld %s",
uval, st->buf[0], st->size,
ct->lower_bound, ct->upper_bound,
inext ? "ext" : "fix");
value = uval;
} else {
if(asn_INTEGER2long(st, &value)) ASN__ENCODE_FAILED;
/* Check proper range */
if(ct->flags & APC_SEMI_CONSTRAINED) {
if(value < ct->lower_bound)
inext = 1;
} else if(ct->range_bits >= 0) {
if(value < ct->lower_bound
|| value > ct->upper_bound)
inext = 1;
}
ASN_DEBUG("Value %lu (%02x/%lu) lb %ld ub %ld %s",
value, st->buf[0], st->size,
ct->lower_bound, ct->upper_bound,
inext ? "ext" : "fix");
}
if(ct->flags & APC_EXTENSIBLE) {
if(per_put_few_bits(po, inext, 1))
ASN__ENCODE_FAILED;
if(inext) ct = 0;
} else if(inext) {
ASN__ENCODE_FAILED;
}
}
/* X.691, #12.2.2 */
if(ct && ct->range_bits >= 0) {
unsigned long v;
/* #10.5.6 */
ASN_DEBUG("Encoding integer %ld (%lu) with range %d bits",
value, value - ct->lower_bound, ct->range_bits);
v = value - ct->lower_bound;
/* #12 <= 8 -> alignment ? */
int range = ct->upper_bound - ct->lower_bound + 1;
if (ct->range_bits < 8 || (ct->range_bits == 8 && range < 256)) {
if(per_put_few_bits(po, 0x00 | v, ct->range_bits))
ASN__ENCODE_FAILED;
} else if (ct->range_bits == 8) {
if(aper_put_align(po) < 0)
ASN__ENCODE_FAILED;
if(per_put_few_bits(po, 0x00 | v, ct->range_bits))
ASN__ENCODE_FAILED;
} else if (ct->range_bits <= 16) {
/* Consume the bytes to align on octet */
if(aper_put_align(po) < 0)
ASN__ENCODE_FAILED;
if(per_put_few_bits(po, 0x0000 | v, 16))
ASN__ENCODE_FAILED;
} else {
/* TODO: extend to >64 bits */
int64_t v64 = v;
int i, j;
int max_range_bytes = (ct->range_bits >> 3) +
(((ct->range_bits % 8) > 0) ? 1 : 0);
for (i = 1; ; i++) {
int upper = 1 << i;
if (upper >= max_range_bytes)
break;
}
for (j = sizeof(int64_t) -1; j != 0; j--) {
int64_t val;
val = v64 >> (j * 8);
if (val != 0)
break;
}
/* Putting length in the minimum number of bits ex: 5 = 3bits */
if (per_put_few_bits(po, j, i))
ASN__ENCODE_FAILED;
/* Consume the bits to align on octet */
if (aper_put_align(po) < 0)
ASN__ENCODE_FAILED;
/* Put the value */
for (i = 0; i <= j; i++) {
if(per_put_few_bits(po, (v64 >> (8 * (j - i))) & 0xff, 8))
ASN__ENCODE_FAILED;
}
}
ASN__ENCODED_OK(er);
}
if(ct && ct->lower_bound) {
ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound);
/* TODO: adjust lower bound */
ASN__ENCODE_FAILED;
}
for(buf = st->buf, end = st->buf + st->size; buf < end;) {
int need_eom = 0;
ssize_t mayEncode = aper_put_length(po, -1, end - buf, &need_eom);
if(mayEncode < 0)
ASN__ENCODE_FAILED;
if(per_put_many_bits(po, buf, 8 * mayEncode))
ASN__ENCODE_FAILED;
buf += mayEncode;
if(need_eom && aper_put_length(po, -1, 0, 0)) ASN__ENCODE_FAILED;
}
ASN__ENCODED_OK(er);
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <INTEGER.h>
/*
* INTEGER specific human-readable output.
*/
int
INTEGER_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
const INTEGER_t *st = (const INTEGER_t *)sptr;
ssize_t ret;
(void)ilevel;
if(!st || !st->buf)
ret = cb("<absent>", 8, app_key);
else
ret = INTEGER__dump(td, st, cb, app_key, 0);
return (ret < 0) ? -1 : 0;
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <INTEGER.h>
asn_random_fill_result_t
INTEGER_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
const asn_encoding_constraints_t *constraints,
size_t max_length) {
const asn_INTEGER_specifics_t *specs =
(const asn_INTEGER_specifics_t *)td->specifics;
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
INTEGER_t *st = *sptr;
const asn_INTEGER_enum_map_t *emap;
size_t emap_len;
intmax_t value;
int find_inside_map;
if(max_length == 0) return result_skipped;
if(st == NULL) {
st = (INTEGER_t *)CALLOC(1, sizeof(*st));
if(st == NULL) {
return result_failed;
}
}
if(specs) {
emap = specs->value2enum;
emap_len = specs->map_count;
if(specs->strict_enumeration) {
find_inside_map = emap_len > 0;
} else {
find_inside_map = emap_len ? asn_random_between(0, 1) : 0;
}
} else {
emap = 0;
emap_len = 0;
find_inside_map = 0;
}
if(find_inside_map) {
assert(emap_len > 0);
value = emap[asn_random_between(0, emap_len - 1)].nat_value;
} else {
static const long variants[] = {
-65536, -65535, -65534, -32769, -32768, -32767, -16385, -16384,
-16383, -257, -256, -255, -254, -129, -128, -127,
-126, -1, 0, 1, 126, 127, 128, 129,
254, 255, 256, 257, 16383, 16384, 16385, 32767,
32768, 32769, 65534, 65535, 65536, 65537};
if(specs && specs->field_unsigned) {
assert(variants[18] == 0);
value = variants[asn_random_between(
18, sizeof(variants) / sizeof(variants[0]) - 1)];
} else {
value = variants[asn_random_between(
0, sizeof(variants) / sizeof(variants[0]) - 1)];
}
if(!constraints) constraints = &td->encoding_constraints;
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
const asn_per_constraints_t *ct;
ct = constraints ? constraints->per_constraints : 0;
if(ct && (ct->value.flags & APC_CONSTRAINED)) {
if(value < ct->value.lower_bound || value > ct->value.upper_bound) {
value = asn_random_between(ct->value.lower_bound,
ct->value.upper_bound);
}
}
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
}
if(asn_imax2INTEGER(st, value)) {
if(st == *sptr) {
ASN_STRUCT_RESET(*td, st);
} else {
ASN_STRUCT_FREE(*td, st);
}
return result_failed;
} else {
*sptr = st;
result_ok.length = st->size;
return result_ok;
}
}

View File

@@ -3,55 +3,83 @@
* Redistribution and modifications are permitted subject to BSD license. * Redistribution and modifications are permitted subject to BSD license.
*/ */
#include <asn_internal.h> #include <asn_internal.h>
#include <asn_codecs_prim.h>
#include <NULL.h> #include <NULL.h>
/* /*
* NULL basic type description. * NULL basic type description.
*/ */
static const ber_tlv_tag_t asn_DEF_NULL_tags[] = { static const ber_tlv_tag_t asn_DEF_NULL_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (5 << 2)) (ASN_TAG_CLASS_UNIVERSAL | (5 << 2))
}; };
asn_TYPE_operation_t asn_OP_NULL = { asn_TYPE_operation_t asn_OP_NULL = {
NULL_free, NULL_free,
NULL_print, #if !defined(ASN_DISABLE_PRINT_SUPPORT)
NULL_compare, NULL_print,
NULL_decode_ber,
NULL_encode_der, /* Special handling of DER encoding */
NULL_decode_xer,
NULL_encode_xer,
#ifdef ASN_DISABLE_OER_SUPPORT
0,
0,
#else #else
NULL_decode_oer, 0,
NULL_encode_oer, #endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
#endif /* ASN_DISABLE_OER_SUPPORT */ NULL_compare,
#ifdef ASN_DISABLE_PER_SUPPORT #if !defined(ASN_DISABLE_BER_SUPPORT)
0, NULL_decode_ber,
0, NULL_encode_der, /* Special handling of DER encoding */
0,
0,
#else #else
NULL_decode_uper, /* Unaligned PER decoder */ 0,
NULL_encode_uper, /* Unaligned PER encoder */ 0,
NULL_decode_aper, /* Aligned PER decoder */ #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
NULL_encode_aper, /* Aligned PER encoder */ #if !defined(ASN_DISABLE_XER_SUPPORT)
#endif /* ASN_DISABLE_PER_SUPPORT */ NULL_decode_xer,
NULL_random_fill, NULL_encode_xer,
0 /* Use generic outmost tag fetcher */ #else
0,
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
NULL_decode_oer,
NULL_encode_oer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
NULL_decode_uper, /* Unaligned PER decoder */
NULL_encode_uper, /* Unaligned PER encoder */
#else
0,
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
NULL_decode_aper, /* Aligned PER decoder */
NULL_encode_aper, /* Aligned PER encoder */
#else
0,
0,
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
NULL_random_fill,
#else
0,
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
0 /* Use generic outmost tag fetcher */
}; };
asn_TYPE_descriptor_t asn_DEF_NULL = { asn_TYPE_descriptor_t asn_DEF_NULL = {
"NULL", "NULL",
"NULL", "NULL",
&asn_OP_NULL, &asn_OP_NULL,
asn_DEF_NULL_tags, asn_DEF_NULL_tags,
sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]), sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]),
asn_DEF_NULL_tags, /* Same as above */ asn_DEF_NULL_tags, /* Same as above */
sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]), sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]),
{ 0, 0, asn_generic_no_constraint }, {
0, 0, /* No members */ #if !defined(ASN_DISABLE_OER_SUPPORT)
0 /* No specifics */ 0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
asn_generic_no_constraint
},
0, 0, /* No members */
0 /* No specifics */
}; };
void void
@@ -71,106 +99,6 @@ NULL_free(const asn_TYPE_descriptor_t *td, void *ptr,
} }
} }
/*
* Decode NULL type.
*/
asn_dec_rval_t
NULL_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void **bool_value,
const void *buf_ptr, size_t size, int tag_mode) {
NULL_t *st = (NULL_t *)*bool_value;
asn_dec_rval_t rval;
ber_tlv_len_t length;
if(st == NULL) {
st = (NULL_t *)(*bool_value = CALLOC(1, sizeof(*st)));
if(st == NULL) {
rval.code = RC_FAIL;
rval.consumed = 0;
return rval;
}
}
ASN_DEBUG("Decoding %s as NULL (tm=%d)", td->name, tag_mode);
/*
* Check tags.
*/
rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size, tag_mode, 0,
&length, 0);
if(rval.code != RC_OK) {
return rval;
}
// X.690-201508, #8.8.2, length shall be zero.
if(length != 0) {
ASN_DEBUG("Decoding %s as NULL failed: too much data", td->name);
rval.code = RC_FAIL;
rval.consumed = 0;
return rval;
}
return rval;
}
asn_enc_rval_t
NULL_encode_der(const asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode,
ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb, void *app_key) {
asn_enc_rval_t erval = {0,0,0};
erval.encoded = der_write_tags(td, 0, tag_mode, 0, tag, cb, app_key);
if(erval.encoded == -1) {
erval.failed_type = td;
erval.structure_ptr = ptr;
}
ASN__ENCODED_OK(erval);
}
asn_enc_rval_t
NULL_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
enum xer_encoder_flags_e flags, asn_app_consume_bytes_f *cb,
void *app_key) {
asn_enc_rval_t er = {0,0,0};
(void)td;
(void)sptr;
(void)ilevel;
(void)flags;
(void)cb;
(void)app_key;
/* XMLNullValue is empty */
er.encoded = 0;
ASN__ENCODED_OK(er);
}
static enum xer_pbd_rval
NULL__xer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,
const void *chunk_buf, size_t chunk_size) {
(void)td;
(void)sptr;
(void)chunk_buf; /* Going to be empty according to the rules below. */
/*
* There must be no content in self-terminating <NULL/> tag.
*/
if(chunk_size)
return XPBD_BROKEN_ENCODING;
else
return XPBD_BODY_CONSUMED;
}
asn_dec_rval_t
NULL_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void **sptr,
const char *opt_mname, const void *buf_ptr, size_t size) {
return xer_decode_primitive(opt_codec_ctx, td,
sptr, sizeof(NULL_t), opt_mname, buf_ptr, size,
NULL__xer_body_decode);
}
int int
NULL_compare(const asn_TYPE_descriptor_t *td, const void *a, const void *b) { NULL_compare(const asn_TYPE_descriptor_t *td, const void *a, const void *b) {
(void)td; (void)td;
@@ -178,180 +106,3 @@ NULL_compare(const asn_TYPE_descriptor_t *td, const void *a, const void *b) {
(void)b; (void)b;
return 0; return 0;
} }
int
NULL_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
(void)td; /* Unused argument */
(void)ilevel; /* Unused argument */
if(sptr) {
return (cb("<present>", 9, app_key) < 0) ? -1 : 0;
} else {
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
}
}
#ifndef ASN_DISABLE_OER_SUPPORT
asn_dec_rval_t
NULL_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td,
const asn_oer_constraints_t *constraints, void **sptr,
const void *ptr, size_t size) {
asn_dec_rval_t rv = {RC_OK, 0};
(void)opt_codec_ctx;
(void)td;
(void)constraints;
(void)ptr;
(void)size;
if(!*sptr) {
*sptr = MALLOC(sizeof(NULL_t));
if(*sptr) {
*(NULL_t *)*sptr = 0;
} else {
ASN__DECODE_FAILED;
}
}
return rv;
}
asn_enc_rval_t
NULL_encode_oer(const asn_TYPE_descriptor_t *td,
const asn_oer_constraints_t *constraints, const void *sptr,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_enc_rval_t er = {0,0,0};
(void)td;
(void)sptr;
(void)constraints;
(void)cb;
(void)app_key;
er.encoded = 0; /* Encoding in 0 bytes. */
ASN__ENCODED_OK(er);
}
#endif /* ASN_DISABLE_OER_SUPPORT */
#ifndef ASN_DISABLE_PER_SUPPORT
asn_dec_rval_t
NULL_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints, void **sptr,
asn_per_data_t *pd) {
asn_dec_rval_t rv;
(void)opt_codec_ctx;
(void)td;
(void)constraints;
(void)pd;
if(!*sptr) {
*sptr = MALLOC(sizeof(NULL_t));
if(*sptr) {
*(NULL_t *)*sptr = 0;
} else {
ASN__DECODE_FAILED;
}
}
/*
* NULL type does not have content octets.
*/
rv.code = RC_OK;
rv.consumed = 0;
return rv;
}
asn_enc_rval_t
NULL_encode_uper(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints, const void *sptr,
asn_per_outp_t *po) {
asn_enc_rval_t er = {0,0,0};
(void)td;
(void)constraints;
(void)sptr;
(void)po;
er.encoded = 0;
ASN__ENCODED_OK(er);
}
asn_dec_rval_t
NULL_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
asn_dec_rval_t rv = {RC_OK, 0};
(void)opt_codec_ctx;
(void)td;
(void)constraints;
(void)pd;
if(!*sptr) {
*sptr = MALLOC(sizeof(NULL_t));
if(*sptr) {
*(NULL_t *)*sptr = 0;
} else {
ASN__DECODE_FAILED;
}
}
/*
* NULL type does not have content octets.
*/
rv.code = RC_OK;
rv.consumed = 0;
return rv;
}
asn_enc_rval_t
NULL_encode_aper(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, asn_per_outp_t *po) {
asn_enc_rval_t er = {0,0,0};
(void)td;
(void)constraints;
(void)sptr;
(void)po;
er.encoded = 0;
ASN__ENCODED_OK(er);
}
#endif /* ASN_DISABLE_PER_SUPPORT */
asn_random_fill_result_t
NULL_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
const asn_encoding_constraints_t *constr,
size_t max_length) {
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
NULL_t *st = *sptr;
(void)td;
(void)constr;
if(max_length == 0) return result_skipped;
if(st == NULL) {
st = (NULL_t *)(*sptr = CALLOC(1, sizeof(*st)));
if(st == NULL) {
return result_failed;
}
}
return result_ok;
}

View File

@@ -21,21 +21,42 @@ extern asn_TYPE_descriptor_t asn_DEF_NULL;
extern asn_TYPE_operation_t asn_OP_NULL; extern asn_TYPE_operation_t asn_OP_NULL;
asn_struct_free_f NULL_free; asn_struct_free_f NULL_free;
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
asn_struct_print_f NULL_print; asn_struct_print_f NULL_print;
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
asn_struct_compare_f NULL_compare; asn_struct_compare_f NULL_compare;
#define NULL_constraint asn_generic_no_constraint
#if !defined(ASN_DISABLE_BER_SUPPORT)
ber_type_decoder_f NULL_decode_ber; ber_type_decoder_f NULL_decode_ber;
der_type_encoder_f NULL_encode_der; der_type_encoder_f NULL_encode_der;
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
#if !defined(ASN_DISABLE_XER_SUPPORT)
xer_type_decoder_f NULL_decode_xer; xer_type_decoder_f NULL_decode_xer;
xer_type_encoder_f NULL_encode_xer; xer_type_encoder_f NULL_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
oer_type_decoder_f NULL_decode_oer; oer_type_decoder_f NULL_decode_oer;
oer_type_encoder_f NULL_encode_oer; oer_type_encoder_f NULL_encode_oer;
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
per_type_decoder_f NULL_decode_uper; per_type_decoder_f NULL_decode_uper;
per_type_encoder_f NULL_encode_uper; per_type_encoder_f NULL_encode_uper;
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
per_type_decoder_f NULL_decode_aper; per_type_decoder_f NULL_decode_aper;
per_type_encoder_f NULL_encode_aper; per_type_encoder_f NULL_encode_aper;
asn_random_fill_f NULL_random_fill; #endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#define NULL_constraint asn_generic_no_constraint #if !defined(ASN_DISABLE_RFILL_SUPPORT)
asn_random_fill_f NULL_random_fill;
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <NULL.h>
asn_dec_rval_t
NULL_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
asn_dec_rval_t rv = {RC_OK, 0};
(void)opt_codec_ctx;
(void)td;
(void)constraints;
(void)pd;
if(!*sptr) {
*sptr = MALLOC(sizeof(NULL_t));
if(*sptr) {
*(NULL_t *)*sptr = 0;
} else {
ASN__DECODE_FAILED;
}
}
/*
* NULL type does not have content octets.
*/
rv.code = RC_OK;
rv.consumed = 0;
return rv;
}
asn_enc_rval_t
NULL_encode_aper(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, asn_per_outp_t *po) {
asn_enc_rval_t er = {0,0,0};
(void)td;
(void)constraints;
(void)sptr;
(void)po;
er.encoded = 0;
ASN__ENCODED_OK(er);
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <NULL.h>
int
NULL_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
(void)td; /* Unused argument */
(void)ilevel; /* Unused argument */
if(sptr) {
return (cb("<present>", 9, app_key) < 0) ? -1 : 0;
} else {
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <NULL.h>
asn_random_fill_result_t
NULL_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
const asn_encoding_constraints_t *constr,
size_t max_length) {
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
NULL_t *st = *sptr;
(void)td;
(void)constr;
if(max_length == 0) return result_skipped;
if(st == NULL) {
st = (NULL_t *)(*sptr = CALLOC(1, sizeof(*st)));
if(st == NULL) {
return result_failed;
}
}
return result_ok;
}

View File

@@ -16,360 +16,88 @@
* NativeEnumerated basic type description. * NativeEnumerated basic type description.
*/ */
static const ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = { static const ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (10 << 2)) (ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
}; };
asn_TYPE_operation_t asn_OP_NativeEnumerated = { asn_TYPE_operation_t asn_OP_NativeEnumerated = {
NativeInteger_free, NativeInteger_free,
NativeInteger_print, #if !defined(ASN_DISABLE_PRINT_SUPPORT)
NativeInteger_compare, NativeInteger_print,
NativeInteger_decode_ber,
NativeInteger_encode_der,
NativeInteger_decode_xer,
NativeEnumerated_encode_xer,
#ifdef ASN_DISABLE_OER_SUPPORT
0,
0,
#else #else
NativeEnumerated_decode_oer, 0,
NativeEnumerated_encode_oer, #endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
#endif /* ASN_DISABLE_OER_SUPPORT */ NativeInteger_compare,
#ifdef ASN_DISABLE_PER_SUPPORT #if !defined(ASN_DISABLE_BER_SUPPORT)
0, NativeInteger_decode_ber,
0, NativeInteger_encode_der,
0,
0,
#else #else
NativeEnumerated_decode_uper, 0,
NativeEnumerated_encode_uper, 0,
NativeEnumerated_decode_aper, #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
NativeEnumerated_encode_aper, #if !defined(ASN_DISABLE_XER_SUPPORT)
#endif /* ASN_DISABLE_PER_SUPPORT */ NativeInteger_decode_xer,
NativeEnumerated_random_fill, NativeEnumerated_encode_xer,
0 /* Use generic outmost tag fetcher */ #else
0,
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
NativeEnumerated_decode_oer,
NativeEnumerated_encode_oer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
NativeEnumerated_decode_uper,
NativeEnumerated_encode_uper,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
NativeEnumerated_decode_aper,
NativeEnumerated_encode_aper,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
NativeEnumerated_random_fill,
#else
0,
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
0 /* Use generic outmost tag fetcher */
}; };
asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = { asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
"ENUMERATED", /* The ASN.1 type is still ENUMERATED */ "ENUMERATED", /* The ASN.1 type is still ENUMERATED */
"ENUMERATED", "ENUMERATED",
&asn_OP_NativeEnumerated, &asn_OP_NativeEnumerated,
asn_DEF_NativeEnumerated_tags, asn_DEF_NativeEnumerated_tags,
sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]), sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
asn_DEF_NativeEnumerated_tags, /* Same as above */ asn_DEF_NativeEnumerated_tags, /* Same as above */
sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]), sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
{ 0, 0, asn_generic_no_constraint }, {
0, 0, /* No members */ #if !defined(ASN_DISABLE_OER_SUPPORT)
0 /* No specifics */ 0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
asn_generic_no_constraint
},
0, 0, /* No members */
0 /* No specifics */
}; };
asn_enc_rval_t #if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
NativeEnumerated_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr, int
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
const asn_INTEGER_specifics_t *specs =
(const asn_INTEGER_specifics_t *)td->specifics;
asn_enc_rval_t er = {0,0,0};
const long *native = (const long *)sptr;
const asn_INTEGER_enum_map_t *el;
(void)ilevel;
(void)flags;
if(!native) ASN__ENCODE_FAILED;
el = INTEGER_map_value2enum(specs, *native);
if(el) {
er.encoded =
asn__format_to_callback(cb, app_key, "<%s/>", el->enum_name);
if(er.encoded < 0) ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
} else {
ASN_DEBUG(
"ASN.1 forbids dealing with "
"unknown value of ENUMERATED type");
ASN__ENCODE_FAILED;
}
}
asn_dec_rval_t
NativeEnumerated_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
void **sptr, asn_per_data_t *pd) {
const asn_INTEGER_specifics_t *specs = td->specifics;
asn_dec_rval_t rval = { RC_OK, 0 };
long *native = (long *)*sptr;
const asn_per_constraint_t *ct;
long value;
(void)opt_codec_ctx;
if(constraints) ct = &constraints->value;
else if(td->encoding_constraints.per_constraints)
ct = &td->encoding_constraints.per_constraints->value;
else ASN__DECODE_FAILED; /* Mandatory! */
if(!specs) ASN__DECODE_FAILED;
if(!native) {
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
if(!native) ASN__DECODE_FAILED;
}
ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
if(ct->flags & APC_EXTENSIBLE) {
int inext = per_get_few_bits(pd, 1);
if(inext < 0) ASN__DECODE_STARVED;
if(inext) ct = 0;
}
if(ct && ct->range_bits >= 0) {
value = per_get_few_bits(pd, ct->range_bits);
if(value < 0) ASN__DECODE_STARVED;
if(value >= (specs->extension
? specs->extension - 1 : specs->map_count))
ASN__DECODE_FAILED;
} else {
if(!specs->extension)
ASN__DECODE_FAILED;
/*
* X.691, #10.6: normally small non-negative whole number;
*/
value = uper_get_nsnnwn(pd);
if(value < 0) ASN__DECODE_STARVED;
value += specs->extension - 1;
if(value >= specs->map_count)
ASN__DECODE_FAILED;
}
*native = specs->value2enum[value].nat_value;
ASN_DEBUG("Decoded %s = %ld", td->name, *native);
return rval;
}
static int
NativeEnumerated__compar_value2enum(const void *ap, const void *bp) { NativeEnumerated__compar_value2enum(const void *ap, const void *bp) {
const asn_INTEGER_enum_map_t *a = ap; const asn_INTEGER_enum_map_t *a = ap;
const asn_INTEGER_enum_map_t *b = bp; const asn_INTEGER_enum_map_t *b = bp;
if(a->nat_value == b->nat_value) if(a->nat_value == b->nat_value)
return 0; return 0;
if(a->nat_value < b->nat_value) if(a->nat_value < b->nat_value)
return -1; return -1;
return 1; return 1;
}
asn_enc_rval_t
NativeEnumerated_encode_uper(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, asn_per_outp_t *po) {
const asn_INTEGER_specifics_t *specs =
(const asn_INTEGER_specifics_t *)td->specifics;
asn_enc_rval_t er = {0,0,0};
long native, value;
const asn_per_constraint_t *ct;
int inext = 0;
asn_INTEGER_enum_map_t key;
const asn_INTEGER_enum_map_t *kf;
if(!sptr) ASN__ENCODE_FAILED;
if(!specs) ASN__ENCODE_FAILED;
if(constraints) ct = &constraints->value;
else if(td->encoding_constraints.per_constraints)
ct = &td->encoding_constraints.per_constraints->value;
else ASN__ENCODE_FAILED; /* Mandatory! */
ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
er.encoded = 0;
native = *(const long *)sptr;
key.nat_value = native;
kf = bsearch(&key, specs->value2enum, specs->map_count,
sizeof(key), NativeEnumerated__compar_value2enum);
if(!kf) {
ASN_DEBUG("No element corresponds to %ld", native);
ASN__ENCODE_FAILED;
}
value = kf - specs->value2enum;
if(ct->range_bits >= 0) {
int cmpWith = specs->extension
? specs->extension - 1 : specs->map_count;
if(value >= cmpWith)
inext = 1;
}
if(ct->flags & APC_EXTENSIBLE) {
if(per_put_few_bits(po, inext, 1))
ASN__ENCODE_FAILED;
if(inext) ct = 0;
} else if(inext) {
ASN__ENCODE_FAILED;
}
if(ct && ct->range_bits >= 0) {
if(per_put_few_bits(po, value, ct->range_bits))
ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
}
if(!specs->extension)
ASN__ENCODE_FAILED;
/*
* X.691, #10.6: normally small non-negative whole number;
*/
ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
value, specs->extension, inext,
value - (inext ? (specs->extension - 1) : 0));
if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
}
asn_dec_rval_t
NativeEnumerated_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
void **sptr, asn_per_data_t *pd) {
const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
asn_dec_rval_t rval = { RC_OK, 0 };
long *native = (long *)*sptr;
const asn_per_constraint_t *ct;
long value;
(void)opt_codec_ctx;
if(constraints) ct = &constraints->value;
else if(td->encoding_constraints.per_constraints)
ct = &td->encoding_constraints.per_constraints->value;
else ASN__DECODE_FAILED; /* Mandatory! */
if(!specs) ASN__DECODE_FAILED;
if(!native) {
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
if(!native) ASN__DECODE_FAILED;
}
ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
if(ct->flags & APC_EXTENSIBLE) {
int inext = per_get_few_bits(pd, 1);
if(inext < 0) ASN__DECODE_STARVED;
if(inext) ct = 0;
}
/* Deal with APER padding */
if(ct && ct->upper_bound >= 255) {
int padding = 0;
padding = (8 - (pd->moved % 8)) % 8;
ASN_DEBUG("For NativeEnumerated %s,offset= %lu Padding bits = %d", td->name, pd->moved, padding);
ASN_DEBUG("For NativeEnumerated %s, upper bound = %lu", td->name, ct->upper_bound);
if(padding > 0)
per_get_few_bits(pd, padding);
}
if(ct && ct->range_bits >= 0) {
value = per_get_few_bits(pd, ct->range_bits);
if(value < 0) ASN__DECODE_STARVED;
if(value >= (specs->extension
? specs->extension - 1 : specs->map_count))
ASN__DECODE_FAILED;
} else {
if(!specs->extension)
ASN__DECODE_FAILED;
/*
* X.691, #10.6: normally small non-negative whole number;
*/
/* XXX handle indefinite index length > 64k */
value = aper_get_nsnnwn(pd, 65537);
if(value < 0) ASN__DECODE_STARVED;
value += specs->extension - 1;
//if(value >= specs->map_count)
// ASN__DECODE_FAILED;
if(value >= specs->map_count) {
ASN_DEBUG("Decoded unknown index value %s = %ld", td->name, value);
/* unknown index. Workaround => set the first enumeration value */
*native = specs->value2enum[0].nat_value;
return rval;
}
}
*native = specs->value2enum[value].nat_value;
ASN_DEBUG("Decoded %s = %ld", td->name, *native);
return rval;
}
asn_enc_rval_t
NativeEnumerated_encode_aper(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, asn_per_outp_t *po) {
const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
asn_enc_rval_t er = {0,0,0};
long native, value;
const asn_per_constraint_t *ct;
int inext = 0;
asn_INTEGER_enum_map_t key;
asn_INTEGER_enum_map_t *kf;
if(!sptr) ASN__ENCODE_FAILED;
if(!specs) ASN__ENCODE_FAILED;
if(constraints) ct = &constraints->value;
else if(td->encoding_constraints.per_constraints)
ct = &td->encoding_constraints.per_constraints->value;
else ASN__ENCODE_FAILED; /* Mandatory! */
ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
er.encoded = 0;
native = *(const long *)sptr;
if(native < 0) ASN__ENCODE_FAILED;
key.nat_value = native;
kf = bsearch(&key, specs->value2enum, specs->map_count,
sizeof(key), NativeEnumerated__compar_value2enum);
if(!kf) {
ASN_DEBUG("No element corresponds to %ld", native);
ASN__ENCODE_FAILED;
}
value = kf - specs->value2enum;
if(ct->range_bits >= 0) {
int cmpWith = specs->extension
? specs->extension - 1 : specs->map_count;
if(value >= cmpWith)
inext = 1;
}
if(ct->flags & APC_EXTENSIBLE) {
if(per_put_few_bits(po, inext, 1))
ASN__ENCODE_FAILED;
if(inext) ct = 0;
} else if(inext) {
ASN__ENCODE_FAILED;
}
if(ct && ct->range_bits >= 0) {
if(per_put_few_bits(po, value, ct->range_bits))
ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
}
if(!specs->extension)
ASN__ENCODE_FAILED;
/*
* X.691, #10.6: normally small non-negative whole number;
*/
ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
value, specs->extension, inext,
value - (inext ? (specs->extension - 1) : 0));
if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
} }
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */

View File

@@ -21,22 +21,49 @@ extern "C" {
extern asn_TYPE_descriptor_t asn_DEF_NativeEnumerated; extern asn_TYPE_descriptor_t asn_DEF_NativeEnumerated;
extern asn_TYPE_operation_t asn_OP_NativeEnumerated; extern asn_TYPE_operation_t asn_OP_NativeEnumerated;
xer_type_encoder_f NativeEnumerated_encode_xer; #define NativeEnumerated_free NativeInteger_free
oer_type_decoder_f NativeEnumerated_decode_oer;
oer_type_encoder_f NativeEnumerated_encode_oer; #if !defined(ASN_DISABLE_PRINT_SUPPORT)
per_type_decoder_f NativeEnumerated_decode_uper; #define NativeEnumerated_print NativeInteger_print
per_type_encoder_f NativeEnumerated_encode_uper; #endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
per_type_decoder_f NativeEnumerated_decode_aper;
per_type_encoder_f NativeEnumerated_encode_aper; #define NativeEnumerated_compare NativeInteger_compare
#define NativeEnumerated_free NativeInteger_free
#define NativeEnumerated_print NativeInteger_print
#define NativeEnumerated_compare NativeInteger_compare
#define NativeEnumerated_random_fill NativeInteger_random_fill
#define NativeEnumerated_constraint asn_generic_no_constraint #define NativeEnumerated_constraint asn_generic_no_constraint
#if !defined(ASN_DISABLE_BER_SUPPORT)
#define NativeEnumerated_decode_ber NativeInteger_decode_ber #define NativeEnumerated_decode_ber NativeInteger_decode_ber
#define NativeEnumerated_encode_der NativeInteger_encode_der #define NativeEnumerated_encode_der NativeInteger_encode_der
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
#if !defined(ASN_DISABLE_XER_SUPPORT)
#define NativeEnumerated_decode_xer NativeInteger_decode_xer #define NativeEnumerated_decode_xer NativeInteger_decode_xer
xer_type_encoder_f NativeEnumerated_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
oer_type_decoder_f NativeEnumerated_decode_oer;
oer_type_encoder_f NativeEnumerated_encode_oer;
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
per_type_decoder_f NativeEnumerated_decode_uper;
per_type_encoder_f NativeEnumerated_encode_uper;
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
per_type_decoder_f NativeEnumerated_decode_aper;
per_type_encoder_f NativeEnumerated_encode_aper;
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
#define NativeEnumerated_random_fill NativeInteger_random_fill
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
int NativeEnumerated__compar_value2enum(
const void *ap,
const void *bp);
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -0,0 +1,155 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <NativeEnumerated.h>
asn_dec_rval_t
NativeEnumerated_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
void **sptr, asn_per_data_t *pd) {
const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
asn_dec_rval_t rval = { RC_OK, 0 };
long *native = (long *)*sptr;
const asn_per_constraint_t *ct;
long value;
(void)opt_codec_ctx;
if(constraints) ct = &constraints->value;
else if(td->encoding_constraints.per_constraints)
ct = &td->encoding_constraints.per_constraints->value;
else ASN__DECODE_FAILED; /* Mandatory! */
if(!specs) ASN__DECODE_FAILED;
if(!native) {
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
if(!native) ASN__DECODE_FAILED;
}
ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
if(ct->flags & APC_EXTENSIBLE) {
int inext = per_get_few_bits(pd, 1);
if(inext < 0) ASN__DECODE_STARVED;
if(inext) ct = 0;
}
/* Deal with APER padding */
if(ct && ct->upper_bound >= 255) {
int padding = 0;
padding = (8 - (pd->moved % 8)) % 8;
ASN_DEBUG("For NativeEnumerated %s,offset= %lu Padding bits = %d", td->name, pd->moved, padding);
ASN_DEBUG("For NativeEnumerated %s, upper bound = %lu", td->name, ct->upper_bound);
if(padding > 0)
per_get_few_bits(pd, padding);
}
if(ct && ct->range_bits >= 0) {
value = per_get_few_bits(pd, ct->range_bits);
if(value < 0) ASN__DECODE_STARVED;
if(value >= (specs->extension
? specs->extension - 1 : specs->map_count))
ASN__DECODE_FAILED;
} else {
if(!specs->extension)
ASN__DECODE_FAILED;
/*
* X.691, #10.6: normally small non-negative whole number;
*/
/* XXX handle indefinite index length > 64k */
value = aper_get_nsnnwn(pd, 65537);
if(value < 0) ASN__DECODE_STARVED;
value += specs->extension - 1;
//if(value >= specs->map_count)
// ASN__DECODE_FAILED;
if(value >= specs->map_count) {
ASN_DEBUG("Decoded unknown index value %s = %ld", td->name, value);
/* unknown index. Workaround => set the first enumeration value */
*native = specs->value2enum[0].nat_value;
return rval;
}
}
*native = specs->value2enum[value].nat_value;
ASN_DEBUG("Decoded %s = %ld", td->name, *native);
return rval;
}
asn_enc_rval_t
NativeEnumerated_encode_aper(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, asn_per_outp_t *po) {
const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
asn_enc_rval_t er = {0,0,0};
long native, value;
const asn_per_constraint_t *ct;
int inext = 0;
asn_INTEGER_enum_map_t key;
asn_INTEGER_enum_map_t *kf;
if(!sptr) ASN__ENCODE_FAILED;
if(!specs) ASN__ENCODE_FAILED;
if(constraints) ct = &constraints->value;
else if(td->encoding_constraints.per_constraints)
ct = &td->encoding_constraints.per_constraints->value;
else ASN__ENCODE_FAILED; /* Mandatory! */
ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
er.encoded = 0;
native = *(const long *)sptr;
if(native < 0) ASN__ENCODE_FAILED;
key.nat_value = native;
kf = bsearch(&key, specs->value2enum, specs->map_count,
sizeof(key), NativeEnumerated__compar_value2enum);
if(!kf) {
ASN_DEBUG("No element corresponds to %ld", native);
ASN__ENCODE_FAILED;
}
value = kf - specs->value2enum;
if(ct->range_bits >= 0) {
int cmpWith = specs->extension
? specs->extension - 1 : specs->map_count;
if(value >= cmpWith)
inext = 1;
}
if(ct->flags & APC_EXTENSIBLE) {
if(per_put_few_bits(po, inext, 1))
ASN__ENCODE_FAILED;
if(inext) ct = 0;
} else if(inext) {
ASN__ENCODE_FAILED;
}
if(ct && ct->range_bits >= 0) {
if(per_put_few_bits(po, value, ct->range_bits))
ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
}
if(!specs->extension)
ASN__ENCODE_FAILED;
/*
* X.691, #10.6: normally small non-negative whole number;
*/
ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
value, specs->extension, inext,
value - (inext ? (specs->extension - 1) : 0));
if(aper_put_nsnnwn(po,
ct->upper_bound - ct->lower_bound + 1,
value - (inext ? (specs->extension - 1) : 0)))
ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
}

View File

@@ -17,408 +17,79 @@
* NativeInteger basic type description. * NativeInteger basic type description.
*/ */
static const ber_tlv_tag_t asn_DEF_NativeInteger_tags[] = { static const ber_tlv_tag_t asn_DEF_NativeInteger_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (2 << 2)) (ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
}; };
asn_TYPE_operation_t asn_OP_NativeInteger = { asn_TYPE_operation_t asn_OP_NativeInteger = {
NativeInteger_free, NativeInteger_free,
NativeInteger_print, #if !defined(ASN_DISABLE_PRINT_SUPPORT)
NativeInteger_compare, NativeInteger_print,
NativeInteger_decode_ber,
NativeInteger_encode_der,
NativeInteger_decode_xer,
NativeInteger_encode_xer,
#ifdef ASN_DISABLE_OER_SUPPORT
0,
0,
#else #else
NativeInteger_decode_oer, /* OER decoder */ 0,
NativeInteger_encode_oer, /* Canonical OER encoder */ #endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
#endif /* ASN_DISABLE_OER_SUPPORT */ NativeInteger_compare,
#ifdef ASN_DISABLE_PER_SUPPORT #if !defined(ASN_DISABLE_BER_SUPPORT)
0, NativeInteger_decode_ber,
0, NativeInteger_encode_der,
0,
0,
#else #else
NativeInteger_decode_uper, /* Unaligned PER decoder */ 0,
NativeInteger_encode_uper, /* Unaligned PER encoder */ 0,
NativeInteger_decode_aper, /* Aligned PER decoder */ #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
NativeInteger_encode_aper, /* Aligned PER encoder */ #if !defined(ASN_DISABLE_XER_SUPPORT)
#endif /* ASN_DISABLE_PER_SUPPORT */ NativeInteger_decode_xer,
NativeInteger_random_fill, NativeInteger_encode_xer,
0 /* Use generic outmost tag fetcher */ #else
0,
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
NativeInteger_decode_oer, /* OER decoder */
NativeInteger_encode_oer, /* Canonical OER encoder */
#else
0,
0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
NativeInteger_decode_uper, /* Unaligned PER decoder */
NativeInteger_encode_uper, /* Unaligned PER encoder */
#else
0,
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
NativeInteger_decode_aper, /* Aligned PER decoder */
NativeInteger_encode_aper, /* Aligned PER encoder */
#else
0,
0,
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
NativeInteger_random_fill,
#else
0,
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
0 /* Use generic outmost tag fetcher */
}; };
asn_TYPE_descriptor_t asn_DEF_NativeInteger = { asn_TYPE_descriptor_t asn_DEF_NativeInteger = {
"INTEGER", /* The ASN.1 type is still INTEGER */ "INTEGER", /* The ASN.1 type is still INTEGER */
"INTEGER", "INTEGER",
&asn_OP_NativeInteger, &asn_OP_NativeInteger,
asn_DEF_NativeInteger_tags, asn_DEF_NativeInteger_tags,
sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]), sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
asn_DEF_NativeInteger_tags, /* Same as above */ asn_DEF_NativeInteger_tags, /* Same as above */
sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]), sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
{ 0, 0, asn_generic_no_constraint }, {
0, 0, /* No members */ #if !defined(ASN_DISABLE_OER_SUPPORT)
0 /* No specifics */ 0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
asn_generic_no_constraint
},
0, 0, /* No members */
0 /* No specifics */
}; };
/*
* Decode INTEGER type.
*/
asn_dec_rval_t
NativeInteger_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void **nint_ptr,
const void *buf_ptr, size_t size, int tag_mode) {
const asn_INTEGER_specifics_t *specs =
(const asn_INTEGER_specifics_t *)td->specifics;
long *native = (long *)*nint_ptr;
asn_dec_rval_t rval;
ber_tlv_len_t length;
/*
* If the structure is not there, allocate it.
*/
if(native == NULL) {
native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
if(native == NULL) {
rval.code = RC_FAIL;
rval.consumed = 0;
return rval;
}
}
ASN_DEBUG("Decoding %s as INTEGER (tm=%d)",
td->name, tag_mode);
/*
* Check tags.
*/
rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
tag_mode, 0, &length, 0);
if(rval.code != RC_OK)
return rval;
ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
/*
* Make sure we have this length.
*/
buf_ptr = ((const char *)buf_ptr) + rval.consumed;
size -= rval.consumed;
if(length > (ber_tlv_len_t)size) {
rval.code = RC_WMORE;
rval.consumed = 0;
return rval;
}
/*
* ASN.1 encoded INTEGER: buf_ptr, length
* Fill the native, at the same time checking for overflow.
* If overflow occurred, return with RC_FAIL.
*/
{
INTEGER_t tmp;
union {
const void *constbuf;
void *nonconstbuf;
} unconst_buf;
long l;
unconst_buf.constbuf = buf_ptr;
tmp.buf = (uint8_t *)unconst_buf.nonconstbuf;
tmp.size = length;
if((specs&&specs->field_unsigned)
? asn_INTEGER2ulong(&tmp, (unsigned long *)&l) /* sic */
: asn_INTEGER2long(&tmp, &l)) {
rval.code = RC_FAIL;
rval.consumed = 0;
return rval;
}
*native = l;
}
rval.code = RC_OK;
rval.consumed += length;
ASN_DEBUG("Took %ld/%ld bytes to encode %s (%ld)",
(long)rval.consumed, (long)length, td->name, (long)*native);
return rval;
}
/*
* Encode the NativeInteger using the standard INTEGER type DER encoder.
*/
asn_enc_rval_t
NativeInteger_encode_der(const asn_TYPE_descriptor_t *sd, const void *ptr,
int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
unsigned long native = *(const unsigned long *)ptr; /* Disable sign ext. */
asn_enc_rval_t erval = {0,0,0};
INTEGER_t tmp;
#ifdef WORDS_BIGENDIAN /* Opportunistic optimization */
tmp.buf = (uint8_t *)&native;
tmp.size = sizeof(native);
#else /* Works even if WORDS_BIGENDIAN is not set where should've been */
uint8_t buf[sizeof(native)];
uint8_t *p;
/* Prepare a fake INTEGER */
for(p = buf + sizeof(buf) - 1; p >= buf; p--, native >>= 8)
*p = (uint8_t)native;
tmp.buf = buf;
tmp.size = sizeof(buf);
#endif /* WORDS_BIGENDIAN */
/* Encode fake INTEGER */
erval = INTEGER_encode_der(sd, &tmp, tag_mode, tag, cb, app_key);
if(erval.structure_ptr == &tmp) {
erval.structure_ptr = ptr;
}
return erval;
}
/*
* Decode the chunk of XML text encoding INTEGER.
*/
asn_dec_rval_t
NativeInteger_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void **sptr,
const char *opt_mname, const void *buf_ptr,
size_t size) {
const asn_INTEGER_specifics_t *specs =
(const asn_INTEGER_specifics_t *)td->specifics;
asn_dec_rval_t rval;
INTEGER_t st;
void *st_ptr = (void *)&st;
long *native = (long *)*sptr;
if(!native) {
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
if(!native) ASN__DECODE_FAILED;
}
memset(&st, 0, sizeof(st));
rval = INTEGER_decode_xer(opt_codec_ctx, td, &st_ptr,
opt_mname, buf_ptr, size);
if(rval.code == RC_OK) {
long l;
if((specs&&specs->field_unsigned)
? asn_INTEGER2ulong(&st, (unsigned long *)&l) /* sic */
: asn_INTEGER2long(&st, &l)) {
rval.code = RC_FAIL;
rval.consumed = 0;
} else {
*native = l;
}
} else {
/*
* Cannot restart from the middle;
* there is no place to save state in the native type.
* Request a continuation from the very beginning.
*/
rval.consumed = 0;
}
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &st);
return rval;
}
asn_enc_rval_t
NativeInteger_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
const asn_INTEGER_specifics_t *specs =
(const asn_INTEGER_specifics_t *)td->specifics;
char scratch[32]; /* Enough for 64-bit int */
asn_enc_rval_t er = {0,0,0};
const long *native = (const long *)sptr;
(void)ilevel;
(void)flags;
if(!native) ASN__ENCODE_FAILED;
er.encoded = snprintf(scratch, sizeof(scratch),
(specs && specs->field_unsigned)
? "%lu" : "%ld", *native);
if(er.encoded <= 0 || (size_t)er.encoded >= sizeof(scratch)
|| cb(scratch, er.encoded, app_key) < 0)
ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
}
#ifndef ASN_DISABLE_PER_SUPPORT
asn_dec_rval_t
NativeInteger_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints, void **sptr,
asn_per_data_t *pd) {
const asn_INTEGER_specifics_t *specs =
(const asn_INTEGER_specifics_t *)td->specifics;
asn_dec_rval_t rval;
long *native = (long *)*sptr;
INTEGER_t tmpint;
void *tmpintptr = &tmpint;
(void)opt_codec_ctx;
ASN_DEBUG("Decoding NativeInteger %s (UPER)", td->name);
if(!native) {
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
if(!native) ASN__DECODE_FAILED;
}
memset(&tmpint, 0, sizeof tmpint);
rval = INTEGER_decode_uper(opt_codec_ctx, td, constraints,
&tmpintptr, pd);
if(rval.code == RC_OK) {
if((specs&&specs->field_unsigned)
? asn_INTEGER2ulong(&tmpint, (unsigned long *)native)
: asn_INTEGER2long(&tmpint, native))
rval.code = RC_FAIL;
else
ASN_DEBUG("NativeInteger %s got value %ld",
td->name, *native);
}
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
return rval;
}
asn_enc_rval_t
NativeInteger_encode_uper(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, asn_per_outp_t *po) {
const asn_INTEGER_specifics_t *specs =
(const asn_INTEGER_specifics_t *)td->specifics;
asn_enc_rval_t er = {0,0,0};
long native;
INTEGER_t tmpint;
if(!sptr) ASN__ENCODE_FAILED;
native = *(const long *)sptr;
ASN_DEBUG("Encoding NativeInteger %s %ld (UPER)", td->name, native);
memset(&tmpint, 0, sizeof(tmpint));
if((specs&&specs->field_unsigned)
? asn_ulong2INTEGER(&tmpint, native)
: asn_long2INTEGER(&tmpint, native))
ASN__ENCODE_FAILED;
er = INTEGER_encode_uper(td, constraints, &tmpint, po);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
return er;
}
asn_dec_rval_t
NativeInteger_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
asn_dec_rval_t rval;
long *native = (long *)*sptr;
INTEGER_t tmpint;
void *tmpintptr = &tmpint;
(void)opt_codec_ctx;
ASN_DEBUG("Decoding NativeInteger %s (APER)", td->name);
if(!native) {
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
if(!native) ASN__DECODE_FAILED;
}
memset(&tmpint, 0, sizeof tmpint);
rval = INTEGER_decode_aper(opt_codec_ctx, td, constraints,
&tmpintptr, pd);
if(rval.code == RC_OK) {
if((specs&&specs->field_unsigned)
? asn_INTEGER2ulong(&tmpint, (unsigned long *)native)
: asn_INTEGER2long(&tmpint, native))
rval.code = RC_FAIL;
else
ASN_DEBUG("NativeInteger %s got value %ld",
td->name, *native);
}
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
return rval;
}
asn_enc_rval_t
NativeInteger_encode_aper(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, asn_per_outp_t *po) {
const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
asn_enc_rval_t er = {0,0,0};
long native;
INTEGER_t tmpint;
if(!sptr) ASN__ENCODE_FAILED;
native = *(const long *)sptr;
ASN_DEBUG("Encoding NativeInteger %s %ld (APER)", td->name, native);
memset(&tmpint, 0, sizeof(tmpint));
if((specs&&specs->field_unsigned)
? asn_ulong2INTEGER(&tmpint, (unsigned long)native)
: asn_long2INTEGER(&tmpint, native))
ASN__ENCODE_FAILED;
er = INTEGER_encode_aper(td, constraints, &tmpint, po);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
return er;
}
#endif /* ASN_DISABLE_PER_SUPPORT */
/*
* INTEGER specific human-readable output.
*/
int
NativeInteger_print(const asn_TYPE_descriptor_t *td, const void *sptr,
int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
const asn_INTEGER_specifics_t *specs =
(const asn_INTEGER_specifics_t *)td->specifics;
const long *native = (const long *)sptr;
char scratch[32]; /* Enough for 64-bit int */
int ret;
(void)td; /* Unused argument */
(void)ilevel; /* Unused argument */
if(native) {
long value = *native;
ret = snprintf(scratch, sizeof(scratch),
(specs && specs->field_unsigned) ? "%lu" : "%ld", value);
assert(ret > 0 && (size_t)ret < sizeof(scratch));
if(cb(scratch, ret, app_key) < 0) return -1;
if(specs && (value >= 0 || !specs->field_unsigned)) {
const asn_INTEGER_enum_map_t *el =
INTEGER_map_value2enum(specs, value);
if(el) {
if(cb(" (", 2, app_key) < 0) return -1;
if(cb(el->enum_name, el->enum_len, app_key) < 0) return -1;
if(cb(")", 1, app_key) < 0) return -1;
}
}
return 0;
} else {
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
}
}
void void
NativeInteger_free(const asn_TYPE_descriptor_t *td, void *ptr, NativeInteger_free(const asn_TYPE_descriptor_t *td, void *ptr,
enum asn_struct_free_method method) { enum asn_struct_free_method method) {
@@ -474,77 +145,3 @@ NativeInteger_compare(const asn_TYPE_descriptor_t *td, const void *aptr, const v
return 1; return 1;
} }
} }
asn_random_fill_result_t
NativeInteger_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
const asn_encoding_constraints_t *constraints,
size_t max_length) {
const asn_INTEGER_specifics_t *specs =
(const asn_INTEGER_specifics_t *)td->specifics;
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
long *st = *sptr;
const asn_INTEGER_enum_map_t *emap;
size_t emap_len;
intmax_t value;
int find_inside_map;
if(max_length == 0) return result_skipped;
if(st == NULL) {
st = (long *)CALLOC(1, sizeof(*st));
if(st == NULL) {
return result_failed;
}
}
if(specs) {
emap = specs->value2enum;
emap_len = specs->map_count;
if(specs->strict_enumeration) {
find_inside_map = emap_len > 0;
} else {
find_inside_map = emap_len ? asn_random_between(0, 1) : 0;
}
} else {
emap = 0;
emap_len = 0;
find_inside_map = 0;
}
if(find_inside_map) {
assert(emap_len > 0);
value = emap[asn_random_between(0, emap_len - 1)].nat_value;
} else {
const asn_per_constraints_t *ct;
static const long variants[] = {
-65536, -65535, -65534, -32769, -32768, -32767, -16385, -16384,
-16383, -257, -256, -255, -254, -129, -128, -127,
-126, -1, 0, 1, 126, 127, 128, 129,
254, 255, 256, 257, 16383, 16384, 16385, 32767,
32768, 32769, 65534, 65535, 65536, 65537};
if(specs && specs->field_unsigned) {
assert(variants[18] == 0);
value = variants[asn_random_between(
18, sizeof(variants) / sizeof(variants[0]) - 1)];
} else {
value = variants[asn_random_between(
0, sizeof(variants) / sizeof(variants[0]) - 1)];
}
if(!constraints) constraints = &td->encoding_constraints;
ct = constraints ? constraints->per_constraints : 0;
if(ct && (ct->value.flags & APC_CONSTRAINED)) {
if(value < ct->value.lower_bound || value > ct->value.upper_bound) {
value = asn_random_between(ct->value.lower_bound,
ct->value.upper_bound);
}
}
}
*sptr = st;
*st = value;
return result_ok;
}

View File

@@ -22,22 +22,43 @@ extern "C" {
extern asn_TYPE_descriptor_t asn_DEF_NativeInteger; extern asn_TYPE_descriptor_t asn_DEF_NativeInteger;
extern asn_TYPE_operation_t asn_OP_NativeInteger; extern asn_TYPE_operation_t asn_OP_NativeInteger;
asn_struct_free_f NativeInteger_free; asn_struct_free_f NativeInteger_free;
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
asn_struct_print_f NativeInteger_print; asn_struct_print_f NativeInteger_print;
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
asn_struct_compare_f NativeInteger_compare; asn_struct_compare_f NativeInteger_compare;
#define NativeInteger_constraint asn_generic_no_constraint
#if !defined(ASN_DISABLE_BER_SUPPORT)
ber_type_decoder_f NativeInteger_decode_ber; ber_type_decoder_f NativeInteger_decode_ber;
der_type_encoder_f NativeInteger_encode_der; der_type_encoder_f NativeInteger_encode_der;
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
#if !defined(ASN_DISABLE_XER_SUPPORT)
xer_type_decoder_f NativeInteger_decode_xer; xer_type_decoder_f NativeInteger_decode_xer;
xer_type_encoder_f NativeInteger_encode_xer; xer_type_encoder_f NativeInteger_encode_xer;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
oer_type_decoder_f NativeInteger_decode_oer; oer_type_decoder_f NativeInteger_decode_oer;
oer_type_encoder_f NativeInteger_encode_oer; oer_type_encoder_f NativeInteger_encode_oer;
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
per_type_decoder_f NativeInteger_decode_uper; per_type_decoder_f NativeInteger_decode_uper;
per_type_encoder_f NativeInteger_encode_uper; per_type_encoder_f NativeInteger_encode_uper;
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
per_type_decoder_f NativeInteger_decode_aper; per_type_decoder_f NativeInteger_decode_aper;
per_type_encoder_f NativeInteger_encode_aper; per_type_encoder_f NativeInteger_encode_aper;
asn_random_fill_f NativeInteger_random_fill; #endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#define NativeInteger_constraint asn_generic_no_constraint #if !defined(ASN_DISABLE_RFILL_SUPPORT)
asn_random_fill_f NativeInteger_random_fill;
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <NativeInteger.h>
asn_dec_rval_t
NativeInteger_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
asn_dec_rval_t rval;
long *native = (long *)*sptr;
INTEGER_t tmpint;
void *tmpintptr = &tmpint;
(void)opt_codec_ctx;
ASN_DEBUG("Decoding NativeInteger %s (APER)", td->name);
if(!native) {
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
if(!native) ASN__DECODE_FAILED;
}
memset(&tmpint, 0, sizeof tmpint);
rval = INTEGER_decode_aper(opt_codec_ctx, td, constraints,
&tmpintptr, pd);
if(rval.code == RC_OK) {
if((specs&&specs->field_unsigned)
? asn_INTEGER2ulong(&tmpint, (unsigned long *)native)
: asn_INTEGER2long(&tmpint, native))
rval.code = RC_FAIL;
else
ASN_DEBUG("NativeInteger %s got value %ld",
td->name, *native);
}
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
return rval;
}
asn_enc_rval_t
NativeInteger_encode_aper(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, asn_per_outp_t *po) {
const asn_INTEGER_specifics_t *specs = (const asn_INTEGER_specifics_t *)td->specifics;
asn_enc_rval_t er = {0,0,0};
long native;
INTEGER_t tmpint;
if(!sptr) ASN__ENCODE_FAILED;
native = *(const long *)sptr;
ASN_DEBUG("Encoding NativeInteger %s %ld (APER)", td->name, native);
memset(&tmpint, 0, sizeof(tmpint));
if((specs&&specs->field_unsigned)
? asn_ulong2INTEGER(&tmpint, (unsigned long)native)
: asn_long2INTEGER(&tmpint, native))
ASN__ENCODE_FAILED;
er = INTEGER_encode_aper(td, constraints, &tmpint, po);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
return er;
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <NativeInteger.h>
/*
* INTEGER specific human-readable output.
*/
int
NativeInteger_print(const asn_TYPE_descriptor_t *td, const void *sptr,
int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
const asn_INTEGER_specifics_t *specs =
(const asn_INTEGER_specifics_t *)td->specifics;
const long *native = (const long *)sptr;
char scratch[32]; /* Enough for 64-bit int */
int ret;
(void)td; /* Unused argument */
(void)ilevel; /* Unused argument */
if(native) {
long value = *native;
ret = snprintf(scratch, sizeof(scratch),
(specs && specs->field_unsigned) ? "%lu" : "%ld", value);
assert(ret > 0 && (size_t)ret < sizeof(scratch));
if(cb(scratch, ret, app_key) < 0) return -1;
if(specs && (value >= 0 || !specs->field_unsigned)) {
const asn_INTEGER_enum_map_t *el =
INTEGER_map_value2enum(specs, value);
if(el) {
if(cb(" (", 2, app_key) < 0) return -1;
if(cb(el->enum_name, el->enum_len, app_key) < 0) return -1;
if(cb(")", 1, app_key) < 0) return -1;
}
}
return 0;
} else {
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <NativeInteger.h>
asn_random_fill_result_t
NativeInteger_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
const asn_encoding_constraints_t *constraints,
size_t max_length) {
const asn_INTEGER_specifics_t *specs =
(const asn_INTEGER_specifics_t *)td->specifics;
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
long *st = *sptr;
const asn_INTEGER_enum_map_t *emap;
size_t emap_len;
intmax_t value;
int find_inside_map;
if(max_length == 0) return result_skipped;
if(st == NULL) {
st = (long *)CALLOC(1, sizeof(*st));
if(st == NULL) {
return result_failed;
}
}
if(specs) {
emap = specs->value2enum;
emap_len = specs->map_count;
if(specs->strict_enumeration) {
find_inside_map = emap_len > 0;
} else {
find_inside_map = emap_len ? asn_random_between(0, 1) : 0;
}
} else {
emap = 0;
emap_len = 0;
find_inside_map = 0;
}
if(find_inside_map) {
assert(emap_len > 0);
value = emap[asn_random_between(0, emap_len - 1)].nat_value;
} else {
static const long variants[] = {
-65536, -65535, -65534, -32769, -32768, -32767, -16385, -16384,
-16383, -257, -256, -255, -254, -129, -128, -127,
-126, -1, 0, 1, 126, 127, 128, 129,
254, 255, 256, 257, 16383, 16384, 16385, 32767,
32768, 32769, 65534, 65535, 65536, 65537};
if(specs && specs->field_unsigned) {
assert(variants[18] == 0);
value = variants[asn_random_between(
18, sizeof(variants) / sizeof(variants[0]) - 1)];
} else {
value = variants[asn_random_between(
0, sizeof(variants) / sizeof(variants[0]) - 1)];
}
if(!constraints) constraints = &td->encoding_constraints;
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
const asn_per_constraints_t *ct;
ct = constraints ? constraints->per_constraints : 0;
if(ct && (ct->value.flags & APC_CONSTRAINED)) {
if(value < ct->value.lower_bound || value > ct->value.upper_bound) {
value = asn_random_between(ct->value.lower_bound,
ct->value.upper_bound);
}
}
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
}
*sptr = st;
*st = value;
return result_ok;
}

View File

@@ -5,7 +5,7 @@
#include <asn_internal.h> #include <asn_internal.h>
#include <INTEGER.h> #include <INTEGER.h>
#include <OBJECT_IDENTIFIER.h> #include <OBJECT_IDENTIFIER.h>
#include <OCTET_STRING.h> #include <asn_codecs_prim.h>
#include <limits.h> /* for CHAR_BIT */ #include <limits.h> /* for CHAR_BIT */
#include <errno.h> #include <errno.h>
@@ -13,50 +13,79 @@
* OBJECT IDENTIFIER basic type description. * OBJECT IDENTIFIER basic type description.
*/ */
static const ber_tlv_tag_t asn_DEF_OBJECT_IDENTIFIER_tags[] = { static const ber_tlv_tag_t asn_DEF_OBJECT_IDENTIFIER_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (6 << 2)) (ASN_TAG_CLASS_UNIVERSAL | (6 << 2))
}; };
asn_TYPE_operation_t asn_OP_OBJECT_IDENTIFIER = { asn_TYPE_operation_t asn_OP_OBJECT_IDENTIFIER = {
ASN__PRIMITIVE_TYPE_free, ASN__PRIMITIVE_TYPE_free,
OBJECT_IDENTIFIER_print, #if !defined(ASN_DISABLE_PRINT_SUPPORT)
OCTET_STRING_compare, /* Implemented in terms of a string comparison */ OBJECT_IDENTIFIER_print,
ber_decode_primitive,
der_encode_primitive,
OBJECT_IDENTIFIER_decode_xer,
OBJECT_IDENTIFIER_encode_xer,
#ifdef ASN_DISABLE_OER_SUPPORT
0,
0,
#else #else
OBJECT_IDENTIFIER_decode_oer, 0,
OBJECT_IDENTIFIER_encode_oer, #endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
#endif /* ASN_DISABLE_OER_SUPPORT */ OCTET_STRING_compare, /* Implemented in terms of a string comparison */
#ifdef ASN_DISABLE_PER_SUPPORT #if !defined(ASN_DISABLE_BER_SUPPORT)
0, ber_decode_primitive,
0, der_encode_primitive,
0,
0,
#else #else
OCTET_STRING_decode_uper, 0,
OCTET_STRING_encode_uper, 0,
OCTET_STRING_decode_aper, #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
OCTET_STRING_encode_aper, #if !defined(ASN_DISABLE_XER_SUPPORT)
#endif /* ASN_DISABLE_PER_SUPPORT */ OBJECT_IDENTIFIER_decode_xer,
OBJECT_IDENTIFIER_random_fill, OBJECT_IDENTIFIER_encode_xer,
0 /* Use generic outmost tag fetcher */ #else
0,
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OBJECT_IDENTIFIER_decode_oer,
OBJECT_IDENTIFIER_encode_oer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
OCTET_STRING_decode_aper,
OCTET_STRING_encode_aper,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
OBJECT_IDENTIFIER_random_fill,
#else
0,
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
0 /* Use generic outmost tag fetcher */
}; };
asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER = { asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER = {
"OBJECT IDENTIFIER", "OBJECT IDENTIFIER",
"OBJECT_IDENTIFIER", "OBJECT_IDENTIFIER",
&asn_OP_OBJECT_IDENTIFIER, &asn_OP_OBJECT_IDENTIFIER,
asn_DEF_OBJECT_IDENTIFIER_tags, asn_DEF_OBJECT_IDENTIFIER_tags,
sizeof(asn_DEF_OBJECT_IDENTIFIER_tags) sizeof(asn_DEF_OBJECT_IDENTIFIER_tags)
/ sizeof(asn_DEF_OBJECT_IDENTIFIER_tags[0]), / sizeof(asn_DEF_OBJECT_IDENTIFIER_tags[0]),
asn_DEF_OBJECT_IDENTIFIER_tags, /* Same as above */ asn_DEF_OBJECT_IDENTIFIER_tags, /* Same as above */
sizeof(asn_DEF_OBJECT_IDENTIFIER_tags) sizeof(asn_DEF_OBJECT_IDENTIFIER_tags)
/ sizeof(asn_DEF_OBJECT_IDENTIFIER_tags[0]), / sizeof(asn_DEF_OBJECT_IDENTIFIER_tags[0]),
{ 0, 0, OBJECT_IDENTIFIER_constraint }, {
0, 0, /* No members */ #if !defined(ASN_DISABLE_OER_SUPPORT)
0 /* No specifics */ 0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
OBJECT_IDENTIFIER_constraint
},
0, 0, /* No members */
0 /* No specifics */
}; };
int int
@@ -143,11 +172,12 @@ OBJECT_IDENTIFIER_get_single_arc(const uint8_t *arcbuf, size_t arcbuf_len,
} }
static ssize_t ssize_t
OBJECT_IDENTIFIER__dump_body(const OBJECT_IDENTIFIER_t *st, OBJECT_IDENTIFIER__dump_body(const OBJECT_IDENTIFIER_t *st,
asn_app_consume_bytes_f *cb, void *app_key) { asn_app_consume_bytes_f *cb, void *app_key) {
char scratch[32]; char scratch[32];
asn_oid_arc_t arc0, arc1; asn_oid_arc_t arc0 = 0;
asn_oid_arc_t arc1 = 0;
size_t produced = 0; size_t produced = 0;
size_t off = 0; size_t off = 0;
ssize_t rd; ssize_t rd;
@@ -195,105 +225,11 @@ OBJECT_IDENTIFIER__dump_body(const OBJECT_IDENTIFIER_t *st,
return produced; return produced;
} }
static enum xer_pbd_rval
OBJECT_IDENTIFIER__xer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,
const void *chunk_buf, size_t chunk_size) {
OBJECT_IDENTIFIER_t *st = (OBJECT_IDENTIFIER_t *)sptr;
const char *chunk_end = (const char *)chunk_buf + chunk_size;
const char *endptr;
asn_oid_arc_t s_arcs[10];
asn_oid_arc_t *arcs = s_arcs;
ssize_t num_arcs;
ssize_t ret;
(void)td;
num_arcs = OBJECT_IDENTIFIER_parse_arcs(
(const char *)chunk_buf, chunk_size, arcs,
sizeof(s_arcs) / sizeof(s_arcs[0]), &endptr);
if(num_arcs < 0) {
/* Expecting more than zero arcs */
return XPBD_BROKEN_ENCODING;
} else if(num_arcs == 0) {
return XPBD_NOT_BODY_IGNORE;
}
assert(endptr == chunk_end);
if((size_t)num_arcs > sizeof(s_arcs)/sizeof(s_arcs[0])) {
arcs = (asn_oid_arc_t *)MALLOC(num_arcs * sizeof(asn_oid_arc_t));
if(!arcs) return XPBD_SYSTEM_FAILURE;
ret = OBJECT_IDENTIFIER_parse_arcs((const char *)chunk_buf, chunk_size,
arcs, num_arcs, &endptr);
if(ret != num_arcs)
return XPBD_SYSTEM_FAILURE; /* assert?.. */
}
/*
* Convert arcs into BER representation.
*/
ret = OBJECT_IDENTIFIER_set_arcs(st, arcs, num_arcs);
if(arcs != s_arcs) FREEMEM(arcs);
return ret ? XPBD_SYSTEM_FAILURE : XPBD_BODY_CONSUMED;
}
asn_dec_rval_t
OBJECT_IDENTIFIER_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void **sptr,
const char *opt_mname, const void *buf_ptr,
size_t size) {
return xer_decode_primitive(opt_codec_ctx, td,
sptr, sizeof(OBJECT_IDENTIFIER_t), opt_mname,
buf_ptr, size, OBJECT_IDENTIFIER__xer_body_decode);
}
asn_enc_rval_t
OBJECT_IDENTIFIER_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
const OBJECT_IDENTIFIER_t *st = (const OBJECT_IDENTIFIER_t *)sptr;
asn_enc_rval_t er = {0,0,0};
(void)ilevel;
(void)flags;
if(!st || !st->buf) {
ASN__ENCODE_FAILED;
}
er.encoded = OBJECT_IDENTIFIER__dump_body(st, cb, app_key);
if(er.encoded < 0) ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
}
int
OBJECT_IDENTIFIER_print(const asn_TYPE_descriptor_t *td, const void *sptr,
int ilevel, asn_app_consume_bytes_f *cb,
void *app_key) {
const OBJECT_IDENTIFIER_t *st = (const OBJECT_IDENTIFIER_t *)sptr;
(void)td; /* Unused argument */
(void)ilevel; /* Unused argument */
if(!st || !st->buf)
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
/* Dump preamble */
if(cb("{ ", 2, app_key) < 0)
return -1;
if(OBJECT_IDENTIFIER__dump_body(st, cb, app_key) < 0) {
return -1;
}
return (cb(" }", 2, app_key) < 0) ? -1 : 0;
}
ssize_t ssize_t
OBJECT_IDENTIFIER_get_arcs(const OBJECT_IDENTIFIER_t *st, asn_oid_arc_t *arcs, OBJECT_IDENTIFIER_get_arcs(const OBJECT_IDENTIFIER_t *st, asn_oid_arc_t *arcs,
size_t arc_slots) { size_t arc_slots) {
asn_oid_arc_t arc0, arc1; asn_oid_arc_t arc0 = 0;
asn_oid_arc_t arc1 = 0;
size_t num_arcs = 0; size_t num_arcs = 0;
size_t off; size_t off;
ssize_t rd; ssize_t rd;
@@ -588,69 +524,3 @@ OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t oid_txt_length,
errno = EINVAL; /* Broken OID */ errno = EINVAL; /* Broken OID */
return -1; return -1;
} }
/*
* Generate values from the list of interesting values, or just a random
* value up to the upper limit.
*/
static asn_oid_arc_t
OBJECT_IDENTIFIER__biased_random_arc(asn_oid_arc_t upper_bound) {
const asn_oid_arc_t values[] = {0, 1, 127, 128, 129, 254, 255, 256};
size_t idx;
switch(asn_random_between(0, 2)) {
case 0:
idx = asn_random_between(0, sizeof(values) / sizeof(values[0]) - 1);
if(values[idx] < upper_bound) {
return values[idx];
}
/* Fall through */
case 1:
return asn_random_between(0, upper_bound);
case 2:
default:
return upper_bound;
}
}
asn_random_fill_result_t
OBJECT_IDENTIFIER_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
const asn_encoding_constraints_t *constraints,
size_t max_length) {
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
OBJECT_IDENTIFIER_t *st;
asn_oid_arc_t arcs[5];
size_t arcs_len = asn_random_between(2, 5);
size_t i;
(void)constraints;
if(max_length < arcs_len) return result_skipped;
if(*sptr) {
st = *sptr;
} else {
st = CALLOC(1, sizeof(*st));
}
arcs[0] = asn_random_between(0, 2);
arcs[1] = OBJECT_IDENTIFIER__biased_random_arc(
arcs[0] <= 1 ? 39 : (ASN_OID_ARC_MAX - 80));
for(i = 2; i < arcs_len; i++) {
arcs[i] = OBJECT_IDENTIFIER__biased_random_arc(ASN_OID_ARC_MAX);
}
if(OBJECT_IDENTIFIER_set_arcs(st, arcs, arcs_len)) {
if(st != *sptr) {
ASN_STRUCT_FREE(*td, st);
}
return result_failed;
}
*sptr = st;
result_ok.length = st->size;
return result_ok;
}

View File

@@ -21,23 +21,47 @@ typedef ASN__PRIMITIVE_TYPE_t OBJECT_IDENTIFIER_t;
extern asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER; extern asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER;
extern asn_TYPE_operation_t asn_OP_OBJECT_IDENTIFIER; extern asn_TYPE_operation_t asn_OP_OBJECT_IDENTIFIER;
ssize_t OBJECT_IDENTIFIER__dump_body(const OBJECT_IDENTIFIER_t *st,
asn_app_consume_bytes_f *cb,
void *app_key);
#define OBJECT_IDENTIFIER_free ASN__PRIMITIVE_TYPE_free
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
asn_struct_print_f OBJECT_IDENTIFIER_print; asn_struct_print_f OBJECT_IDENTIFIER_print;
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
#define OBJECT_IDENTIFIER_compare OCTET_STRING_compare
asn_constr_check_f OBJECT_IDENTIFIER_constraint; asn_constr_check_f OBJECT_IDENTIFIER_constraint;
der_type_encoder_f OBJECT_IDENTIFIER_encode_der;
#if !defined(ASN_DISABLE_BER_SUPPORT)
#define OBJECT_IDENTIFIER_decode_ber ber_decode_primitive
#define OBJECT_IDENTIFIER_encode_der der_encode_primitive
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
#if !defined(ASN_DISABLE_XER_SUPPORT)
xer_type_decoder_f OBJECT_IDENTIFIER_decode_xer; xer_type_decoder_f OBJECT_IDENTIFIER_decode_xer;
xer_type_encoder_f OBJECT_IDENTIFIER_encode_xer; xer_type_encoder_f OBJECT_IDENTIFIER_encode_xer;
asn_random_fill_f OBJECT_IDENTIFIER_random_fill; #endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#define OBJECT_IDENTIFIER_free ASN__PRIMITIVE_TYPE_free #if !defined(ASN_DISABLE_OER_SUPPORT)
#define OBJECT_IDENTIFIER_compare OCTET_STRING_compare #define OBJECT_IDENTIFIER_decode_oer oer_decode_primitive
#define OBJECT_IDENTIFIER_decode_ber ber_decode_primitive #define OBJECT_IDENTIFIER_encode_oer oer_encode_primitive
#define OBJECT_IDENTIFIER_encode_der der_encode_primitive #endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#define OBJECT_IDENTIFIER_decode_oer oer_decode_primitive
#define OBJECT_IDENTIFIER_encode_oer oer_encode_primitive #if !defined(ASN_DISABLE_UPER_SUPPORT)
#define OBJECT_IDENTIFIER_decode_uper OCTET_STRING_decode_uper #define OBJECT_IDENTIFIER_decode_uper OCTET_STRING_decode_uper
#define OBJECT_IDENTIFIER_encode_uper OCTET_STRING_encode_uper #define OBJECT_IDENTIFIER_encode_uper OCTET_STRING_encode_uper
#define OBJECT_IDENTIFIER_decode_aper OCTET_STRING_decode_aper #endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#define OBJECT_IDENTIFIER_encode_aper OCTET_STRING_encode_aper #if !defined(ASN_DISABLE_APER_SUPPORT)
#define OBJECT_IDENTIFIER_decode_aper OCTET_STRING_decode_aper
#define OBJECT_IDENTIFIER_encode_aper OCTET_STRING_encode_aper
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
asn_random_fill_f OBJECT_IDENTIFIER_random_fill;
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
/********************************** /**********************************
* Some handy conversion routines * * Some handy conversion routines *

View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <OBJECT_IDENTIFIER.h>
int
OBJECT_IDENTIFIER_print(const asn_TYPE_descriptor_t *td, const void *sptr,
int ilevel, asn_app_consume_bytes_f *cb,
void *app_key) {
const OBJECT_IDENTIFIER_t *st = (const OBJECT_IDENTIFIER_t *)sptr;
(void)td; /* Unused argument */
(void)ilevel; /* Unused argument */
if(!st || !st->buf)
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
/* Dump preamble */
if(cb("{ ", 2, app_key) < 0)
return -1;
if(OBJECT_IDENTIFIER__dump_body(st, cb, app_key) < 0) {
return -1;
}
return (cb(" }", 2, app_key) < 0) ? -1 : 0;
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <OBJECT_IDENTIFIER.h>
/*
* Generate values from the list of interesting values, or just a random
* value up to the upper limit.
*/
static asn_oid_arc_t
OBJECT_IDENTIFIER__biased_random_arc(asn_oid_arc_t upper_bound) {
const asn_oid_arc_t values[] = {0, 1, 127, 128, 129, 254, 255, 256};
size_t idx;
switch(asn_random_between(0, 2)) {
case 0:
idx = asn_random_between(0, sizeof(values) / sizeof(values[0]) - 1);
if(values[idx] < upper_bound) {
return values[idx];
}
/* Fall through */
case 1:
return asn_random_between(0, upper_bound);
case 2:
default:
return upper_bound;
}
}
asn_random_fill_result_t
OBJECT_IDENTIFIER_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
const asn_encoding_constraints_t *constraints,
size_t max_length) {
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
OBJECT_IDENTIFIER_t *st;
asn_oid_arc_t arcs[5];
size_t arcs_len = asn_random_between(2, 5);
size_t i;
(void)constraints;
if(max_length < arcs_len) return result_skipped;
if(*sptr) {
st = *sptr;
} else {
st = CALLOC(1, sizeof(*st));
}
arcs[0] = asn_random_between(0, 2);
arcs[1] = OBJECT_IDENTIFIER__biased_random_arc(
arcs[0] <= 1 ? 39 : (ASN_OID_ARC_MAX - 80));
for(i = 2; i < arcs_len; i++) {
arcs[i] = OBJECT_IDENTIFIER__biased_random_arc(ASN_OID_ARC_MAX);
}
if(OBJECT_IDENTIFIER_set_arcs(st, arcs, arcs_len)) {
if(st != *sptr) {
ASN_STRUCT_FREE(*td, st);
}
return result_failed;
}
*sptr = st;
result_ok.length = st->size;
return result_ok;
}

File diff suppressed because it is too large Load Diff

View File

@@ -22,27 +22,68 @@ extern asn_TYPE_descriptor_t asn_DEF_OCTET_STRING;
extern asn_TYPE_operation_t asn_OP_OCTET_STRING; extern asn_TYPE_operation_t asn_OP_OCTET_STRING;
asn_struct_free_f OCTET_STRING_free; asn_struct_free_f OCTET_STRING_free;
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
asn_struct_print_f OCTET_STRING_print; asn_struct_print_f OCTET_STRING_print;
asn_struct_print_f OCTET_STRING_print_utf8; asn_struct_print_f OCTET_STRING_print_utf8;
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
asn_struct_compare_f OCTET_STRING_compare; asn_struct_compare_f OCTET_STRING_compare;
#define OCTET_STRING_constraint asn_generic_no_constraint
#if !defined(ASN_DISABLE_BER_SUPPORT)
ber_type_decoder_f OCTET_STRING_decode_ber; ber_type_decoder_f OCTET_STRING_decode_ber;
der_type_encoder_f OCTET_STRING_encode_der; der_type_encoder_f OCTET_STRING_encode_der;
xer_type_decoder_f OCTET_STRING_decode_xer_hex; /* Hexadecimal */ #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
xer_type_decoder_f OCTET_STRING_decode_xer_binary; /* 01010111010 */
xer_type_decoder_f OCTET_STRING_decode_xer_utf8; /* ASCII/UTF-8 */ #if !defined(ASN_DISABLE_XER_SUPPORT)
xer_type_decoder_f OCTET_STRING_decode_xer_hex; /* Hexadecimal */
xer_type_decoder_f OCTET_STRING_decode_xer_binary; /* 01010111010 */
xer_type_decoder_f OCTET_STRING_decode_xer_utf8; /* ASCII/UTF-8 */
xer_type_encoder_f OCTET_STRING_encode_xer; xer_type_encoder_f OCTET_STRING_encode_xer;
xer_type_encoder_f OCTET_STRING_encode_xer_utf8; xer_type_encoder_f OCTET_STRING_encode_xer_utf8;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
oer_type_decoder_f OCTET_STRING_decode_oer; oer_type_decoder_f OCTET_STRING_decode_oer;
oer_type_encoder_f OCTET_STRING_encode_oer; oer_type_encoder_f OCTET_STRING_encode_oer;
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
per_type_decoder_f OCTET_STRING_decode_uper; per_type_decoder_f OCTET_STRING_decode_uper;
per_type_encoder_f OCTET_STRING_encode_uper; per_type_encoder_f OCTET_STRING_encode_uper;
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
per_type_decoder_f OCTET_STRING_decode_aper; per_type_decoder_f OCTET_STRING_decode_aper;
per_type_encoder_f OCTET_STRING_encode_aper; per_type_encoder_f OCTET_STRING_encode_aper;
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
asn_random_fill_f OCTET_STRING_random_fill; asn_random_fill_f OCTET_STRING_random_fill;
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
#define OCTET_STRING_constraint asn_generic_no_constraint #if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
#define OCTET_STRING_decode_xer OCTET_STRING_decode_xer_hex int OCTET_STRING_per_get_characters(
asn_per_data_t *po,
uint8_t *buf,
size_t units,
unsigned int bpc,
unsigned int unit_bits,
long lb,
long ub,
const asn_per_constraints_t *pc);
int OCTET_STRING_per_put_characters(
asn_per_outp_t *po,
const uint8_t *buf,
size_t units,
unsigned int bpc,
unsigned int unit_bits,
long lb,
long ub,
const asn_per_constraints_t *pc);
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
/****************************** /******************************
* Handy conversion routines. * * Handy conversion routines. *
******************************/ ******************************/
@@ -95,6 +136,23 @@ size_t OCTET_STRING_random_length_constrained(
const asn_TYPE_descriptor_t *, const asn_encoding_constraints_t *, const asn_TYPE_descriptor_t *, const asn_encoding_constraints_t *,
size_t max_length); size_t max_length);
#if !defined(ASN_DISABLE_BER_SUPPORT)
struct _stack_el {
ber_tlv_len_t left; /* What's left to read (or -1) */
ber_tlv_len_t got; /* What was actually processed */
unsigned cont_level; /* Depth of subcontainment */
int want_nulls; /* Want null "end of content" octets? */
int bits_chopped; /* Flag in BIT STRING mode */
ber_tlv_tag_t tag; /* For debugging purposes */
struct _stack_el *prev;
struct _stack_el *next;
};
struct _stack {
struct _stack_el *tail;
struct _stack_el *cur_ptr;
};
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -0,0 +1,412 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <OCTET_STRING.h>
#include <BIT_STRING.h> /* for .bits_unused member */
#undef RETURN
#define RETURN(_code) do {\
asn_dec_rval_t tmprval;\
tmprval.code = _code;\
tmprval.consumed = consumed_myself;\
return tmprval;\
} while(0)
static asn_per_constraints_t asn_DEF_OCTET_STRING_constraints = {
{ APC_CONSTRAINED, 8, 8, 0, 255 },
{ APC_SEMI_CONSTRAINED, -1, -1, 0, 0 },
0, 0
};
asn_dec_rval_t
OCTET_STRING_decode_aper(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
void **sptr, asn_per_data_t *pd) {
const asn_OCTET_STRING_specifics_t *specs = td->specifics
? (const asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_SPC_OCTET_STRING_specs;
const asn_per_constraints_t *pc = constraints
? constraints
: td->encoding_constraints.per_constraints;
const asn_per_constraint_t *cval;
const asn_per_constraint_t *csiz;
asn_dec_rval_t rval = { RC_OK, 0 };
BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
ssize_t consumed_myself = 0;
int repeat;
enum {
OS__BPC_BIT = 0,
OS__BPC_CHAR = 1,
OS__BPC_U16 = 2,
OS__BPC_U32 = 4
} bpc; /* Bytes per character */
unsigned int unit_bits;
unsigned int canonical_unit_bits;
(void)opt_codec_ctx;
if(pc) {
cval = &pc->value;
csiz = &pc->size;
} else {
cval = &asn_DEF_OCTET_STRING_constraints.value;
csiz = &asn_DEF_OCTET_STRING_constraints.size;
}
switch(specs->subvariant) {
default:
/*
case ASN_OSUBV_ANY:
ASN_DEBUG("Unrecognized subvariant %d", specs->subvariant);
RETURN(RC_FAIL);
*/
case ASN_OSUBV_BIT:
canonical_unit_bits = unit_bits = 1;
bpc = OS__BPC_BIT;
break;
case ASN_OSUBV_ANY:
case ASN_OSUBV_STR:
canonical_unit_bits = unit_bits = 8;
/*
if(cval->flags & APC_CONSTRAINED)
unit_bits = cval->range_bits;
*/
bpc = OS__BPC_CHAR;
break;
case ASN_OSUBV_U16:
canonical_unit_bits = unit_bits = 16;
if(cval->flags & APC_CONSTRAINED)
unit_bits = cval->range_bits;
bpc = OS__BPC_U16;
break;
case ASN_OSUBV_U32:
canonical_unit_bits = unit_bits = 32;
if(cval->flags & APC_CONSTRAINED)
unit_bits = cval->range_bits;
bpc = OS__BPC_U32;
break;
}
/*
* Allocate the string.
*/
if(!st) {
st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
if(!st) RETURN(RC_FAIL);
}
ASN_DEBUG("PER Decoding %s size %ld .. %ld bits %d",
csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible",
csiz->lower_bound, csiz->upper_bound, csiz->effective_bits);
if(csiz->flags & APC_EXTENSIBLE) {
int inext = per_get_few_bits(pd, 1);
if(inext < 0) RETURN(RC_WMORE);
if(inext) {
csiz = &asn_DEF_OCTET_STRING_constraints.size;
cval = &asn_DEF_OCTET_STRING_constraints.value;
unit_bits = canonical_unit_bits;
}
}
if(csiz->effective_bits >= 0) {
FREEMEM(st->buf);
if(bpc) {
st->size = csiz->upper_bound * bpc;
} else {
st->size = (csiz->upper_bound + 7) >> 3;
}
st->buf = (uint8_t *)MALLOC(st->size + 1);
if(!st->buf) { st->size = 0; RETURN(RC_FAIL); }
}
/* X.691, #16.5: zero-length encoding */
/* X.691, #16.6: short fixed length encoding (up to 2 octets) */
/* X.691, #16.7: long fixed length encoding (up to 64K octets) */
if(csiz->effective_bits == 0) {
int ret;
/* X.691 #16 NOTE 1 for fixed length (<= 16 bits) strings */
if (st->size > 2 || csiz->range_bits != 0) {
if (aper_get_align(pd) < 0)
RETURN(RC_FAIL);
}
if(bpc) {
ASN_DEBUG("Decoding OCTET STRING size %ld",
csiz->upper_bound);
ret = OCTET_STRING_per_get_characters(pd, st->buf,
csiz->upper_bound,
bpc, unit_bits,
cval->lower_bound,
cval->upper_bound,
pc);
if(ret > 0) RETURN(RC_FAIL);
} else {
ASN_DEBUG("Decoding BIT STRING size %ld",
csiz->upper_bound);
ret = per_get_many_bits(pd, st->buf, 0,
unit_bits * csiz->upper_bound);
}
if(ret < 0) RETURN(RC_WMORE);
consumed_myself += unit_bits * csiz->upper_bound;
st->buf[st->size] = 0;
if(bpc == 0) {
int ubs = (csiz->upper_bound & 0x7);
st->bits_unused = ubs ? 8 - ubs : 0;
}
RETURN(RC_OK);
}
st->size = 0;
do {
ssize_t raw_len;
ssize_t len_bytes;
ssize_t len_bits;
void *p;
int ret;
repeat = 0;
/* Get the PER length */
if (csiz->upper_bound - csiz->lower_bound == 0)
/* Indefinite length case */
raw_len = aper_get_length(pd, -1, csiz->effective_bits, &repeat);
else
raw_len = aper_get_length(pd, csiz->upper_bound - csiz->lower_bound + 1, csiz->effective_bits, &repeat);
if(raw_len < 0) RETURN(RC_WMORE);
raw_len += csiz->lower_bound;
ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
(long)csiz->effective_bits, (long)raw_len,
repeat ? "repeat" : "once", td->name);
/* X.691 #16 NOTE 1 for fixed length (<=16 bits) strings */
if ((raw_len > 2) || (csiz->upper_bound > 2) || (csiz->range_bits != 0))
{
if (aper_get_align(pd) < 0)
RETURN(RC_FAIL);
}
if(bpc) {
len_bytes = raw_len * bpc;
len_bits = len_bytes * unit_bits;
} else {
len_bits = raw_len;
len_bytes = (len_bits + 7) >> 3;
if(len_bits & 0x7)
st->bits_unused = 8 - (len_bits & 0x7);
/* len_bits be multiple of 16K if repeat is set */
}
p = REALLOC(st->buf, st->size + len_bytes + 1);
if(!p) RETURN(RC_FAIL);
st->buf = (uint8_t *)p;
if(bpc) {
ret = OCTET_STRING_per_get_characters(pd,
&st->buf[st->size],
raw_len, bpc,
unit_bits,
cval->lower_bound,
cval->upper_bound,
pc);
if(ret > 0) RETURN(RC_FAIL);
} else {
ret = per_get_many_bits(pd, &st->buf[st->size],
0, len_bits);
}
if(ret < 0) RETURN(RC_WMORE);
st->size += len_bytes;
} while(repeat);
st->buf[st->size] = 0; /* nul-terminate */
return rval;
}
asn_enc_rval_t
OCTET_STRING_encode_aper(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, asn_per_outp_t *po) {
const asn_OCTET_STRING_specifics_t *specs = td->specifics
? (const asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_SPC_OCTET_STRING_specs;
const asn_per_constraints_t *pc = constraints
? constraints
: td->encoding_constraints.per_constraints;
const asn_per_constraint_t *cval;
const asn_per_constraint_t *csiz;
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
asn_enc_rval_t er = { 0, 0, 0 };
int inext = 0; /* Lies not within extension root */
unsigned int unit_bits;
unsigned int canonical_unit_bits;
unsigned int sizeinunits;
const uint8_t *buf;
int ret;
enum {
OS__BPC_BIT = 0,
OS__BPC_CHAR = 1,
OS__BPC_U16 = 2,
OS__BPC_U32 = 4
} bpc; /* Bytes per character */
int ct_extensible;
if(!st || (!st->buf && st->size))
ASN__ENCODE_FAILED;
if(pc) {
cval = &pc->value;
csiz = &pc->size;
} else {
cval = &asn_DEF_OCTET_STRING_constraints.value;
csiz = &asn_DEF_OCTET_STRING_constraints.size;
}
ct_extensible = csiz->flags & APC_EXTENSIBLE;
switch(specs->subvariant) {
default:
/*
case ASN_OSUBV_ANY:
ASN__ENCODE_FAILED;
*/
case ASN_OSUBV_BIT:
canonical_unit_bits = unit_bits = 1;
bpc = OS__BPC_BIT;
sizeinunits = st->size * 8 - (st->bits_unused & 0x07);
ASN_DEBUG("BIT STRING of %d bytes",
sizeinunits);
break;
case ASN_OSUBV_ANY:
case ASN_OSUBV_STR:
canonical_unit_bits = unit_bits = 8;
/*
if(cval->flags & APC_CONSTRAINED)
unit_bits = 8;
*/
bpc = OS__BPC_CHAR;
sizeinunits = st->size;
break;
case ASN_OSUBV_U16:
canonical_unit_bits = unit_bits = 16;
if(cval->flags & APC_CONSTRAINED)
unit_bits = cval->range_bits;
bpc = OS__BPC_U16;
sizeinunits = st->size / 2;
break;
case ASN_OSUBV_U32:
canonical_unit_bits = unit_bits = 32;
if(cval->flags & APC_CONSTRAINED)
unit_bits = cval->range_bits;
bpc = OS__BPC_U32;
sizeinunits = st->size / 4;
break;
}
ASN_DEBUG("Encoding %s into %d units of %d bits"
" (%ld..%ld, effective %d)%s",
td->name, sizeinunits, unit_bits,
csiz->lower_bound, csiz->upper_bound,
csiz->effective_bits, ct_extensible ? " EXT" : "");
/* Figure out wheter size lies within PER visible constraint */
if(csiz->effective_bits >= 0) {
if((int)sizeinunits < csiz->lower_bound
|| (int)sizeinunits > csiz->upper_bound) {
if(ct_extensible) {
cval = &asn_DEF_OCTET_STRING_constraints.value;
csiz = &asn_DEF_OCTET_STRING_constraints.size;
unit_bits = canonical_unit_bits;
inext = 1;
} else
ASN__ENCODE_FAILED;
}
} else {
inext = 0;
}
if(ct_extensible) {
/* Declare whether length is [not] within extension root */
if(per_put_few_bits(po, inext, 1))
ASN__ENCODE_FAILED;
}
/* X.691, #16.5: zero-length encoding */
/* X.691, #16.6: short fixed length encoding (up to 2 octets) */
/* X.691, #16.7: long fixed length encoding (up to 64K octets) */
if(csiz->effective_bits >= 0) {
ASN_DEBUG("Encoding %lu bytes (%ld), length in %d bits",
st->size, sizeinunits - csiz->lower_bound,
csiz->effective_bits);
if (csiz->effective_bits > 0) {
ret = aper_put_length(po,
csiz->upper_bound - csiz->lower_bound + 1,
sizeinunits - csiz->lower_bound, 0);
if(ret) ASN__ENCODE_FAILED;
}
if (csiz->effective_bits > 0 || (st->size > 2)
|| (csiz->upper_bound > (2 * 8 / unit_bits))
|| (csiz->range_bits != 0))
{ /* X.691 #16 NOTE 1 for fixed length (<=16 bits) strings*/
if (aper_put_align(po) < 0)
ASN__ENCODE_FAILED;
}
if(bpc) {
ret = OCTET_STRING_per_put_characters(po, st->buf,
sizeinunits,
bpc, unit_bits,
cval->lower_bound,
cval->upper_bound,
pc);
} else {
ret = per_put_many_bits(po, st->buf,
sizeinunits * unit_bits);
}
if(ret) ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
}
ASN_DEBUG("Encoding %lu bytes", st->size);
if(sizeinunits == 0) {
if(aper_put_length(po, -1, 0, 0))
ASN__ENCODE_FAILED;
ASN__ENCODED_OK(er);
}
buf = st->buf;
while(sizeinunits) {
int need_eom = 0;
ssize_t maySave = aper_put_length(po, -1, sizeinunits, &need_eom);
if(maySave < 0) ASN__ENCODE_FAILED;
ASN_DEBUG("Encoding %ld of %ld",
(long)maySave, (long)sizeinunits);
if(bpc) {
ret = OCTET_STRING_per_put_characters(po, buf, maySave,
bpc, unit_bits,
cval->lower_bound,
cval->upper_bound,
pc);
} else {
ret = per_put_many_bits(po, buf, maySave * unit_bits);
}
if(ret) ASN__ENCODE_FAILED;
if(bpc)
buf += maySave * bpc;
else
buf += maySave >> 3;
sizeinunits -= maySave;
assert(!(maySave & 0x07) || !sizeinunits);
if(need_eom && aper_put_length(po, -1, 0, 0))
ASN__ENCODE_FAILED; /* End of Message length */
}
ASN__ENCODED_OK(er);
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <OCTET_STRING.h>
int
OCTET_STRING_print(const asn_TYPE_descriptor_t *td, const void *sptr,
int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
const char * const h2c = "0123456789ABCDEF";
const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
char scratch[16 * 3 + 4];
char *p = scratch;
uint8_t *buf;
uint8_t *end;
size_t i;
(void)td; /* Unused argument */
if(!st || (!st->buf && st->size))
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
/*
* Dump the contents of the buffer in hexadecimal.
*/
buf = st->buf;
end = buf + st->size;
for(i = 0; buf < end; buf++, i++) {
if(!(i % 16) && (i || st->size > 16)) {
if(cb(scratch, p - scratch, app_key) < 0)
return -1;
_i_INDENT(1);
p = scratch;
}
*p++ = h2c[(*buf >> 4) & 0x0F];
*p++ = h2c[*buf & 0x0F];
*p++ = 0x20;
}
if(p > scratch) {
p--; /* Remove the tail space */
if(cb(scratch, p - scratch, app_key) < 0)
return -1;
}
return 0;
}
int
OCTET_STRING_print_utf8(const asn_TYPE_descriptor_t *td, const void *sptr,
int ilevel, asn_app_consume_bytes_f *cb,
void *app_key) {
const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
(void)td; /* Unused argument */
(void)ilevel; /* Unused argument */
if(st && (st->buf || !st->size)) {
return (cb(st->buf, st->size, app_key) < 0) ? -1 : 0;
} else {
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
}
}

View File

@@ -0,0 +1,209 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <OCTET_STRING.h>
/*
* Biased function for randomizing character values around their limits.
*/
static uint32_t
OCTET_STRING__random_char(unsigned long lb, unsigned long ub) {
assert(lb <= ub);
switch(asn_random_between(0, 16)) {
case 0:
if(lb < ub) return lb + 1;
/* Fall through */
case 1:
return lb;
case 2:
if(lb < ub) return ub - 1;
/* Fall through */
case 3:
return ub;
default:
return asn_random_between(lb, ub);
}
}
asn_random_fill_result_t
OCTET_STRING_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
const asn_encoding_constraints_t *constraints,
size_t max_length) {
const asn_OCTET_STRING_specifics_t *specs = td->specifics
? (const asn_OCTET_STRING_specifics_t *)td->specifics
: &asn_SPC_OCTET_STRING_specs;
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
unsigned int unit_bytes = 1;
unsigned long clb = 0; /* Lower bound on char */
unsigned long cub = 255; /* Higher bound on char value */
uint8_t *buf;
uint8_t *bend;
uint8_t *b;
size_t rnd_len;
OCTET_STRING_t *st;
if(max_length == 0 && !*sptr) return result_skipped;
switch(specs->subvariant) {
default:
case ASN_OSUBV_ANY:
return result_failed;
case ASN_OSUBV_BIT:
/* Handled by BIT_STRING itself. */
return result_failed;
case ASN_OSUBV_STR:
unit_bytes = 1;
clb = 0;
cub = 255;
break;
case ASN_OSUBV_U16:
unit_bytes = 2;
clb = 0;
cub = 65535;
break;
case ASN_OSUBV_U32:
unit_bytes = 4;
clb = 0;
cub = 0x10FFFF;
break;
}
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
if(!constraints || !constraints->per_constraints)
constraints = &td->encoding_constraints;
if(constraints->per_constraints) {
const asn_per_constraint_t *pc = &constraints->per_constraints->value;
if(pc->flags & APC_SEMI_CONSTRAINED) {
clb = pc->lower_bound;
} else if(pc->flags & APC_CONSTRAINED) {
clb = pc->lower_bound;
cub = pc->upper_bound;
}
}
#else
if(!constraints) constraints = &td->encoding_constraints;
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
rnd_len =
OCTET_STRING_random_length_constrained(td, constraints, max_length);
buf = CALLOC(unit_bytes, rnd_len + 1);
if(!buf) return result_failed;
bend = &buf[unit_bytes * rnd_len];
switch(unit_bytes) {
case 1:
for(b = buf; b < bend; b += unit_bytes) {
*(uint8_t *)b = OCTET_STRING__random_char(clb, cub);
}
*(uint8_t *)b = 0;
break;
case 2:
for(b = buf; b < bend; b += unit_bytes) {
uint32_t code = OCTET_STRING__random_char(clb, cub);
b[0] = code >> 8;
b[1] = code;
}
*(uint16_t *)b = 0;
break;
case 4:
for(b = buf; b < bend; b += unit_bytes) {
uint32_t code = OCTET_STRING__random_char(clb, cub);
b[0] = code >> 24;
b[1] = code >> 16;
b[2] = code >> 8;
b[3] = code;
}
*(uint32_t *)b = 0;
break;
}
if(*sptr) {
st = *sptr;
FREEMEM(st->buf);
} else {
st = (OCTET_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
if(!st) {
FREEMEM(buf);
return result_failed;
}
}
st->buf = buf;
st->size = unit_bytes * rnd_len;
result_ok.length = st->size;
return result_ok;
}
size_t
OCTET_STRING_random_length_constrained(
const asn_TYPE_descriptor_t *td,
const asn_encoding_constraints_t *constraints, size_t max_length) {
const unsigned lengths[] = {0, 1, 2, 3, 4, 8,
126, 127, 128, 16383, 16384, 16385,
65534, 65535, 65536, 65537};
size_t rnd_len;
/* Figure out how far we should go */
rnd_len = lengths[asn_random_between(
0, sizeof(lengths) / sizeof(lengths[0]) - 1)];
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
if(!constraints || !constraints->per_constraints)
constraints = &td->encoding_constraints;
if(constraints->per_constraints) {
const asn_per_constraint_t *pc = &constraints->per_constraints->size;
if(pc->flags & APC_CONSTRAINED) {
long suggested_upper_bound = pc->upper_bound < (ssize_t)max_length
? pc->upper_bound
: (ssize_t)max_length;
if(max_length <= (size_t)pc->lower_bound) {
return pc->lower_bound;
}
if(pc->flags & APC_EXTENSIBLE) {
switch(asn_random_between(0, 5)) {
case 0:
if(pc->lower_bound > 0) {
rnd_len = pc->lower_bound - 1;
break;
}
/* Fall through */
case 1:
rnd_len = pc->upper_bound + 1;
break;
case 2:
/* Keep rnd_len from the table */
if(rnd_len <= max_length) {
break;
}
/* Fall through */
default:
rnd_len = asn_random_between(pc->lower_bound,
suggested_upper_bound);
}
} else {
rnd_len =
asn_random_between(pc->lower_bound, suggested_upper_bound);
}
} else {
rnd_len = asn_random_between(0, max_length);
}
} else {
#else
if(!constraints) constraints = &td->encoding_constraints;
{
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
if(rnd_len > max_length) {
rnd_len = asn_random_between(0, max_length);
}
}
return rnd_len;
}

View File

@@ -5,505 +5,54 @@
#include <asn_internal.h> #include <asn_internal.h>
#include <OPEN_TYPE.h> #include <OPEN_TYPE.h>
#include <constr_CHOICE.h> #include <constr_CHOICE.h>
#include <per_opentype.h>
#include <errno.h>
asn_TYPE_operation_t asn_OP_OPEN_TYPE = { asn_TYPE_operation_t asn_OP_OPEN_TYPE = {
OPEN_TYPE_free, OPEN_TYPE_free,
OPEN_TYPE_print, #if !defined(ASN_DISABLE_PRINT_SUPPORT)
OPEN_TYPE_compare, OPEN_TYPE_print,
OPEN_TYPE_decode_ber,
OPEN_TYPE_encode_der,
OPEN_TYPE_decode_xer,
OPEN_TYPE_encode_xer,
#ifdef ASN_DISABLE_OER_SUPPORT
0, 0, /* No OER support, use "-gen-OER" to enable */
#else #else
OPEN_TYPE_decode_oer, 0,
OPEN_TYPE_encode_oer, #endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
#endif OPEN_TYPE_compare,
#ifdef ASN_DISABLE_PER_SUPPORT #if !defined(ASN_DISABLE_BER_SUPPORT)
0, 0, 0, 0, OPEN_TYPE_decode_ber,
OPEN_TYPE_encode_der,
#else #else
OPEN_TYPE_decode_uper, 0,
OPEN_TYPE_encode_uper, 0,
OPEN_TYPE_decode_aper, #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
OPEN_TYPE_encode_aper, #if !defined(ASN_DISABLE_XER_SUPPORT)
#endif OPEN_TYPE_decode_xer,
0, /* Random fill is not supported for open type */ OPEN_TYPE_encode_xer,
0 /* Use generic outmost tag fetcher */ #else
0,
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OPEN_TYPE_decode_oer,
OPEN_TYPE_encode_oer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
OPEN_TYPE_decode_uper,
OPEN_TYPE_encode_uper,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
OPEN_TYPE_decode_aper,
OPEN_TYPE_encode_aper,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
0, /* Random fill is not supported for open type */
#else
0,
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
0 /* Use generic outmost tag fetcher */
}; };
#undef ADVANCE
#define ADVANCE(num_bytes) \
do { \
size_t num = num_bytes; \
ptr = ((const char *)ptr) + num; \
size -= num; \
consumed_myself += num; \
} while(0)
asn_dec_rval_t
OPEN_TYPE_ber_get(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void *sptr,
const asn_TYPE_member_t *elm, const void *ptr, size_t size) {
size_t consumed_myself = 0;
asn_type_selector_result_t selected;
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
void *inner_value;
asn_dec_rval_t rv;
if(!(elm->flags & ATF_OPEN_TYPE)) {
ASN__DECODE_FAILED;
}
if(!elm->type_selector) {
ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
td->name, elm->name, elm->type->name);
ASN__DECODE_FAILED;
}
selected = elm->type_selector(td, sptr);
if(!selected.presence_index) {
ASN__DECODE_FAILED;
}
/* Fetch the pointer to this member */
if(elm->flags & ATF_POINTER) {
memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
} else {
memb_ptr = (char *)sptr + elm->memb_offset;
memb_ptr2 = &memb_ptr;
}
if(*memb_ptr2 != NULL) {
/* Make sure we reset the structure first before encoding */
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0) != 0) {
ASN__DECODE_FAILED;
}
}
inner_value =
(char *)*memb_ptr2
+ elm->type->elements[selected.presence_index - 1].memb_offset;
ASN_DEBUG("presence %d\n", selected.presence_index);
rv = selected.type_descriptor->op->ber_decoder(
opt_codec_ctx, selected.type_descriptor, &inner_value, ptr, size,
elm->tag_mode);
ADVANCE(rv.consumed);
rv.consumed = 0;
switch(rv.code) {
case RC_OK:
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
selected.presence_index)
== 0) {
rv.code = RC_OK;
rv.consumed = consumed_myself;
return rv;
} else {
/* Oh, now a full-blown failure failure */
}
/* Fall through */
case RC_FAIL:
rv.consumed = consumed_myself;
/* Fall through */
case RC_WMORE:
break;
}
if(*memb_ptr2) {
if(elm->flags & ATF_POINTER) {
ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
*memb_ptr2 = NULL;
} else {
ASN_STRUCT_RESET(*selected.type_descriptor,
inner_value);
}
}
return rv;
}
asn_dec_rval_t
OPEN_TYPE_xer_get(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void *sptr,
const asn_TYPE_member_t *elm, const void *ptr, size_t size) {
size_t consumed_myself = 0;
asn_type_selector_result_t selected;
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
void *inner_value;
asn_dec_rval_t rv;
int xer_context = 0;
ssize_t ch_size;
pxer_chunk_type_e ch_type;
if(!(elm->flags & ATF_OPEN_TYPE)) {
ASN__DECODE_FAILED;
}
if(!elm->type_selector) {
ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
td->name, elm->name, elm->type->name);
ASN__DECODE_FAILED;
}
selected = elm->type_selector(td, sptr);
if(!selected.presence_index) {
ASN__DECODE_FAILED;
}
/* Fetch the pointer to this member */
assert(elm->flags == ATF_OPEN_TYPE);
if(elm->flags & ATF_POINTER) {
memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
} else {
memb_ptr = (char *)sptr + elm->memb_offset;
memb_ptr2 = &memb_ptr;
}
if(*memb_ptr2 != NULL) {
/* Make sure we reset the structure first before encoding */
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0)
!= 0) {
ASN__DECODE_FAILED;
}
}
/*
* Confirm wrapper.
*/
for(;;) {
ch_size = xer_next_token(&xer_context, ptr, size, &ch_type);
if(ch_size < 0) {
ASN__DECODE_FAILED;
} else {
switch(ch_type) {
case PXER_WMORE:
ASN__DECODE_STARVED;
case PXER_COMMENT:
case PXER_TEXT:
ADVANCE(ch_size);
continue;
case PXER_TAG:
break;
}
break;
}
}
/*
* Wrapper value confirmed.
*/
switch(xer_check_tag(ptr, ch_size, elm->name)) {
case XCT_OPENING:
ADVANCE(ch_size);
break;
case XCT_BROKEN:
default:
ASN__DECODE_FAILED;
}
inner_value =
(char *)*memb_ptr2
+ elm->type->elements[selected.presence_index - 1].memb_offset;
rv = selected.type_descriptor->op->xer_decoder(
opt_codec_ctx, selected.type_descriptor, &inner_value, NULL, ptr, size);
ADVANCE(rv.consumed);
rv.consumed = 0;
switch(rv.code) {
case RC_OK:
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
selected.presence_index)
== 0) {
break;
} else {
rv.code = RC_FAIL;
}
/* Fall through */
case RC_FAIL:
/* Point to a best position where failure occurred */
rv.consumed = consumed_myself;
/* Fall through */
case RC_WMORE:
/* Wrt. rv.consumed==0:
* In case a genuine RC_WMORE, the whole Open Type decoding
* will have to be restarted.
*/
if(*memb_ptr2) {
if(elm->flags & ATF_POINTER) {
ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
*memb_ptr2 = NULL;
} else {
ASN_STRUCT_RESET(*selected.type_descriptor,
inner_value);
}
}
return rv;
}
/*
* Finalize wrapper.
*/
for(;;) {
ch_size = xer_next_token(&xer_context, ptr, size, &ch_type);
if(ch_size < 0) {
ASN__DECODE_FAILED;
} else {
switch(ch_type) {
case PXER_WMORE:
ASN__DECODE_STARVED;
case PXER_COMMENT:
case PXER_TEXT:
ADVANCE(ch_size);
continue;
case PXER_TAG:
break;
}
break;
}
}
/*
* Wrapper value confirmed.
*/
switch(xer_check_tag(ptr, ch_size, elm->name)) {
case XCT_CLOSING:
ADVANCE(ch_size);
break;
case XCT_BROKEN:
default:
ASN__DECODE_FAILED;
}
rv.consumed += consumed_myself;
return rv;
}
#ifndef ASN_DISABLE_PER_SUPPORT
asn_dec_rval_t
OPEN_TYPE_uper_get(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void *sptr,
const asn_TYPE_member_t *elm, asn_per_data_t *pd) {
asn_type_selector_result_t selected;
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
void *inner_value;
asn_dec_rval_t rv;
if(!(elm->flags & ATF_OPEN_TYPE)) {
ASN__DECODE_FAILED;
}
if(!elm->type_selector) {
ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
td->name, elm->name, elm->type->name);
ASN__DECODE_FAILED;
}
selected = elm->type_selector(td, sptr);
if(!selected.presence_index) {
ASN__DECODE_FAILED;
}
/* Fetch the pointer to this member */
assert(elm->flags == ATF_OPEN_TYPE);
if(elm->flags & ATF_POINTER) {
memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
} else {
memb_ptr = (char *)sptr + elm->memb_offset;
memb_ptr2 = &memb_ptr;
}
if(*memb_ptr2 != NULL) {
/* Make sure we reset the structure first before encoding */
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0)
!= 0) {
ASN__DECODE_FAILED;
}
}
inner_value =
(char *)*memb_ptr2
+ elm->type->elements[selected.presence_index - 1].memb_offset;
rv = uper_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL,
&inner_value, pd);
switch(rv.code) {
case RC_OK:
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
selected.presence_index)
== 0) {
break;
} else {
rv.code = RC_FAIL;
}
/* Fall through */
case RC_WMORE:
case RC_FAIL:
if(*memb_ptr2) {
if(elm->flags & ATF_POINTER) {
ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
*memb_ptr2 = NULL;
} else {
ASN_STRUCT_RESET(*selected.type_descriptor,
inner_value);
}
}
}
return rv;
}
asn_enc_rval_t
OPEN_TYPE_encode_uper(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, asn_per_outp_t *po) {
const void *memb_ptr; /* Pointer to the member */
asn_TYPE_member_t *elm; /* CHOICE's element */
asn_enc_rval_t er = {0,0,0};
unsigned present;
(void)constraints;
present = CHOICE_variant_get_presence(td, sptr);
if(present == 0 || present > td->elements_count) {
ASN__ENCODE_FAILED;
} else {
present--;
}
ASN_DEBUG("Encoding %s OPEN TYPE element %d", td->name, present);
elm = &td->elements[present];
if(elm->flags & ATF_POINTER) {
/* Member is a pointer to another structure */
memb_ptr =
*(const void *const *)((const char *)sptr + elm->memb_offset);
if(!memb_ptr) ASN__ENCODE_FAILED;
} else {
memb_ptr = (const char *)sptr + elm->memb_offset;
}
if(uper_open_type_put(elm->type, NULL, memb_ptr, po) < 0) {
ASN__ENCODE_FAILED;
}
er.encoded = 0;
ASN__ENCODED_OK(er);
}
asn_dec_rval_t
OPEN_TYPE_aper_get(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void *sptr,
const asn_TYPE_member_t *elm, asn_per_data_t *pd) {
asn_type_selector_result_t selected;
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
void *inner_value;
asn_dec_rval_t rv;
if(!(elm->flags & ATF_OPEN_TYPE)) {
ASN__DECODE_FAILED;
}
if(!elm->type_selector) {
ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
td->name, elm->name, elm->type->name);
ASN__DECODE_FAILED;
}
selected = elm->type_selector(td, sptr);
if(!selected.presence_index) {
ASN__DECODE_FAILED;
}
/* Fetch the pointer to this member */
assert(elm->flags == ATF_OPEN_TYPE);
if(elm->flags & ATF_POINTER) {
memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
} else {
memb_ptr = (char *)sptr + elm->memb_offset;
memb_ptr2 = &memb_ptr;
}
if(*memb_ptr2 != NULL) {
/* Make sure we reset the structure first before encoding */
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0)
!= 0) {
ASN__DECODE_FAILED;
}
}
inner_value =
(char *)*memb_ptr2
+ elm->type->elements[selected.presence_index - 1].memb_offset;
rv = aper_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL,
&inner_value, pd);
switch(rv.code) {
case RC_OK:
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
selected.presence_index)
== 0) {
break;
} else {
rv.code = RC_FAIL;
}
/* Fall through */
case RC_WMORE:
case RC_FAIL:
if(*memb_ptr2) {
if(elm->flags & ATF_POINTER) {
ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
*memb_ptr2 = NULL;
} else {
ASN_STRUCT_RESET(*selected.type_descriptor,
inner_value);
}
}
}
return rv;
}
asn_enc_rval_t
OPEN_TYPE_encode_aper(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, asn_per_outp_t *po) {
const void *memb_ptr; /* Pointer to the member */
asn_TYPE_member_t *elm; /* CHOICE's element */
asn_enc_rval_t er = {0,0,0};
unsigned present;
(void)constraints;
present = CHOICE_variant_get_presence(td, sptr);
if(present == 0 || present > td->elements_count) {
ASN__ENCODE_FAILED;
} else {
present--;
}
ASN_DEBUG("Encoding %s OPEN TYPE element %d", td->name, present);
elm = &td->elements[present];
if(elm->flags & ATF_POINTER) {
/* Member is a pointer to another structure */
memb_ptr =
*(const void *const *)((const char *)sptr + elm->memb_offset);
if(!memb_ptr) ASN__ENCODE_FAILED;
} else {
memb_ptr = (const char *)sptr + elm->memb_offset;
}
if(aper_open_type_put(elm->type, NULL, memb_ptr, po) < 0) {
ASN__ENCODE_FAILED;
}
er.encoded = 0;
ASN__ENCODED_OK(er);
}
#endif /* ASN_DISABLE_PER_SUPPORT */

View File

@@ -6,69 +6,97 @@
#define ASN_OPEN_TYPE_H #define ASN_OPEN_TYPE_H
#include <asn_application.h> #include <asn_application.h>
///////////#include <per_support.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define OPEN_TYPE_free CHOICE_free
#define OPEN_TYPE_print CHOICE_print
#define OPEN_TYPE_compare CHOICE_compare
#define OPEN_TYPE_constraint CHOICE_constraint
#define OPEN_TYPE_decode_ber NULL
#define OPEN_TYPE_encode_der CHOICE_encode_der
#define OPEN_TYPE_decode_xer NULL
#define OPEN_TYPE_encode_xer CHOICE_encode_xer
#define OPEN_TYPE_decode_oer NULL
#define OPEN_TYPE_encode_oer CHOICE_encode_oer
#define OPEN_TYPE_decode_uper NULL
#define OPEN_TYPE_decode_aper NULL
extern asn_TYPE_operation_t asn_OP_OPEN_TYPE;
/* /*
* Decode an Open Type which is potentially constraiend * Decode an Open Type which is potentially constraiend
* by the other members of the parent structure. * by the other members of the parent structure.
*/ */
asn_dec_rval_t OPEN_TYPE_ber_get(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *parent_type,
void *parent_structure,
const asn_TYPE_member_t *element,
const void *ptr, size_t size);
asn_dec_rval_t OPEN_TYPE_xer_get(const asn_codec_ctx_t *opt_codec_ctx, #undef ADVANCE
const asn_TYPE_descriptor_t *parent_type, #define ADVANCE(num_bytes) \
void *parent_structure, do { \
const asn_TYPE_member_t *element, size_t num = num_bytes; \
const void *ptr, size_t size); ptr = ((const char *)ptr) + num; \
size -= num; \
consumed_myself += num; \
} while(0)
asn_dec_rval_t OPEN_TYPE_oer_get(const asn_codec_ctx_t *opt_codec_ctx, #define OPEN_TYPE_free CHOICE_free
const asn_TYPE_descriptor_t *parent_type,
void *parent_structure,
asn_TYPE_member_t *element, const void *ptr,
size_t size);
asn_dec_rval_t OPEN_TYPE_uper_get(const asn_codec_ctx_t *opt_codec_ctx, #if !defined(ASN_DISABLE_PRINT_SUPPORT)
const asn_TYPE_descriptor_t *parent_type, #define OPEN_TYPE_print CHOICE_print
void *parent_structure, #endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
const asn_TYPE_member_t *element,
asn_per_data_t *pd);
asn_dec_rval_t OPEN_TYPE_aper_get(const asn_codec_ctx_t *opt_codec_ctx, #define OPEN_TYPE_compare CHOICE_compare
const asn_TYPE_descriptor_t *parent_type,
void *parent_structure,
const asn_TYPE_member_t *element,
asn_per_data_t *pd);
#define OPEN_TYPE_constraint CHOICE_constraint
#if !defined(ASN_DISABLE_BER_SUPPORT)
asn_dec_rval_t OPEN_TYPE_ber_get(
const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *parent_type,
void *parent_structure,
const asn_TYPE_member_t *element,
const void *ptr, size_t size);
#define OPEN_TYPE_decode_ber NULL
#define OPEN_TYPE_encode_der CHOICE_encode_der
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
#if !defined(ASN_DISABLE_XER_SUPPORT)
asn_dec_rval_t OPEN_TYPE_xer_get(
const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *parent_type,
void *parent_structure,
const asn_TYPE_member_t *element,
const void *ptr, size_t size);
#define OPEN_TYPE_decode_xer NULL
#define OPEN_TYPE_encode_xer CHOICE_encode_xer
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
asn_dec_rval_t OPEN_TYPE_oer_get(
const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *parent_type,
void *parent_structure,
asn_TYPE_member_t *element, const void *ptr,
size_t size);
#define OPEN_TYPE_decode_oer NULL
#define OPEN_TYPE_encode_oer CHOICE_encode_oer
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
asn_dec_rval_t OPEN_TYPE_uper_get(
const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *parent_type,
void *parent_structure,
const asn_TYPE_member_t *element,
asn_per_data_t *pd);
#define OPEN_TYPE_decode_uper NULL
asn_enc_rval_t OPEN_TYPE_encode_uper( asn_enc_rval_t OPEN_TYPE_encode_uper(
const asn_TYPE_descriptor_t *type_descriptor, const asn_TYPE_descriptor_t *type_descriptor,
const asn_per_constraints_t *constraints, const void *struct_ptr, const asn_per_constraints_t *constraints, const void *struct_ptr,
asn_per_outp_t *per_output); asn_per_outp_t *per_output);
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
asn_dec_rval_t OPEN_TYPE_aper_get(
const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *parent_type,
void *parent_structure,
const asn_TYPE_member_t *element,
asn_per_data_t *pd);
#define OPEN_TYPE_decode_aper NULL
asn_enc_rval_t OPEN_TYPE_encode_aper( asn_enc_rval_t OPEN_TYPE_encode_aper(
const asn_TYPE_descriptor_t *type_descriptor, const asn_TYPE_descriptor_t *type_descriptor,
const asn_per_constraints_t *constraints, const void *struct_ptr, const asn_per_constraints_t *constraints, const void *struct_ptr,
asn_per_outp_t *per_output); asn_per_outp_t *per_output);
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
extern asn_TYPE_operation_t asn_OP_OPEN_TYPE;
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -0,0 +1,119 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <OPEN_TYPE.h>
#include <constr_CHOICE.h>
#include <aper_opentype.h>
asn_dec_rval_t
OPEN_TYPE_aper_get(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void *sptr,
const asn_TYPE_member_t *elm, asn_per_data_t *pd) {
asn_type_selector_result_t selected;
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
void *inner_value;
asn_dec_rval_t rv;
if(!(elm->flags & ATF_OPEN_TYPE)) {
ASN__DECODE_FAILED;
}
if(!elm->type_selector) {
ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
td->name, elm->name, elm->type->name);
ASN__DECODE_FAILED;
}
selected = elm->type_selector(td, sptr);
if(!selected.presence_index) {
ASN__DECODE_FAILED;
}
/* Fetch the pointer to this member */
assert(elm->flags == ATF_OPEN_TYPE);
if(elm->flags & ATF_POINTER) {
memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
} else {
memb_ptr = (char *)sptr + elm->memb_offset;
memb_ptr2 = &memb_ptr;
}
if(*memb_ptr2 != NULL) {
/* Make sure we reset the structure first before encoding */
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0)
!= 0) {
ASN__DECODE_FAILED;
}
}
inner_value =
(char *)*memb_ptr2
+ elm->type->elements[selected.presence_index - 1].memb_offset;
rv = aper_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL,
&inner_value, pd);
switch(rv.code) {
case RC_OK:
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
selected.presence_index)
== 0) {
break;
} else {
rv.code = RC_FAIL;
}
/* Fall through */
case RC_WMORE:
case RC_FAIL:
if(*memb_ptr2) {
if(elm->flags & ATF_POINTER) {
ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
*memb_ptr2 = NULL;
} else {
ASN_STRUCT_RESET(*selected.type_descriptor,
inner_value);
}
}
}
return rv;
}
asn_enc_rval_t
OPEN_TYPE_encode_aper(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, asn_per_outp_t *po) {
const void *memb_ptr; /* Pointer to the member */
asn_TYPE_member_t *elm; /* CHOICE's element */
asn_enc_rval_t er = {0,0,0};
unsigned present;
(void)constraints;
present = CHOICE_variant_get_presence(td, sptr);
if(present == 0 || present > td->elements_count) {
ASN__ENCODE_FAILED;
} else {
present--;
}
ASN_DEBUG("Encoding %s OPEN TYPE element %d", td->name, present);
elm = &td->elements[present];
if(elm->flags & ATF_POINTER) {
/* Member is a pointer to another structure */
memb_ptr =
*(const void *const *)((const char *)sptr + elm->memb_offset);
if(!memb_ptr) ASN__ENCODE_FAILED;
} else {
memb_ptr = (const char *)sptr + elm->memb_offset;
}
if(aper_open_type_put(elm->type, NULL, memb_ptr, po) < 0) {
ASN__ENCODE_FAILED;
}
er.encoded = 0;
ASN__ENCODED_OK(er);
}

View File

@@ -9,50 +9,78 @@
* ObjectDescriptor basic type description. * ObjectDescriptor basic type description.
*/ */
static const ber_tlv_tag_t asn_DEF_ObjectDescriptor_tags[] = { static const ber_tlv_tag_t asn_DEF_ObjectDescriptor_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (7 << 2)), /* [UNIVERSAL 7] IMPLICIT ... */ (ASN_TAG_CLASS_UNIVERSAL | (7 << 2)), /* [UNIVERSAL 7] IMPLICIT ... */
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */ (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
}; };
asn_TYPE_operation_t asn_OP_ObjectDescriptor = { asn_TYPE_operation_t asn_OP_ObjectDescriptor = {
OCTET_STRING_free, OCTET_STRING_free,
OCTET_STRING_print_utf8, /* Treat as ASCII subset (it's not) */ #if !defined(ASN_DISABLE_PRINT_SUPPORT)
OCTET_STRING_compare, OCTET_STRING_print_utf8, /* Treat as ASCII subset (it's not) */
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
#ifdef ASN_DISABLE_OER_SUPPORT
0,
0,
#else #else
0, 0,
0, #endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
#endif /* ASN_DISABLE_OER_SUPPORT */ OCTET_STRING_compare,
#ifdef ASN_DISABLE_PER_SUPPORT #if !defined(ASN_DISABLE_BER_SUPPORT)
0, OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
0, OCTET_STRING_encode_der,
0,
0,
#else #else
OCTET_STRING_decode_uper, 0,
OCTET_STRING_encode_uper, 0,
OCTET_STRING_decode_aper, #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
OCTET_STRING_encode_aper, #if !defined(ASN_DISABLE_XER_SUPPORT)
#endif /* ASN_DISABLE_PER_SUPPORT */ OCTET_STRING_decode_xer_utf8,
0, /* Not supported for ObjectDescriptor */ OCTET_STRING_encode_xer_utf8,
0 /* Use generic outmost tag fetcher */ #else
0,
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
0,
0,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
OCTET_STRING_decode_aper,
OCTET_STRING_encode_aper,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
0, /* Not supported for ObjectDescriptor */
#else
0,
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
0 /* Use generic outmost tag fetcher */
}; };
asn_TYPE_descriptor_t asn_DEF_ObjectDescriptor = { asn_TYPE_descriptor_t asn_DEF_ObjectDescriptor = {
"ObjectDescriptor", "ObjectDescriptor",
"ObjectDescriptor", "ObjectDescriptor",
&asn_OP_ObjectDescriptor, &asn_OP_ObjectDescriptor,
asn_DEF_ObjectDescriptor_tags, asn_DEF_ObjectDescriptor_tags,
sizeof(asn_DEF_ObjectDescriptor_tags) sizeof(asn_DEF_ObjectDescriptor_tags)
/ sizeof(asn_DEF_ObjectDescriptor_tags[0]) - 1, / sizeof(asn_DEF_ObjectDescriptor_tags[0]) - 1,
asn_DEF_ObjectDescriptor_tags, asn_DEF_ObjectDescriptor_tags,
sizeof(asn_DEF_ObjectDescriptor_tags) sizeof(asn_DEF_ObjectDescriptor_tags)
/ sizeof(asn_DEF_ObjectDescriptor_tags[0]), / sizeof(asn_DEF_ObjectDescriptor_tags[0]),
{ 0, 0, asn_generic_unknown_constraint }, {
0, 0, /* No members */ #if !defined(ASN_DISABLE_OER_SUPPORT)
0 /* No specifics */ 0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
asn_generic_unknown_constraint
},
0, 0, /* No members */
0 /* No specifics */
}; };

View File

@@ -16,17 +16,32 @@ typedef GraphicString_t ObjectDescriptor_t; /* Implemented via GraphicString */
extern asn_TYPE_descriptor_t asn_DEF_ObjectDescriptor; extern asn_TYPE_descriptor_t asn_DEF_ObjectDescriptor;
extern asn_TYPE_operation_t asn_OP_ObjectDescriptor; extern asn_TYPE_operation_t asn_OP_ObjectDescriptor;
#define ObjectDescriptor_free OCTET_STRING_free #define ObjectDescriptor_free OCTET_STRING_free
#define ObjectDescriptor_print OCTET_STRING_print_utf8
#define ObjectDescriptor_constraint asn_generic_unknown_constraint #if !defined(ASN_DISABLE_PRINT_SUPPORT)
#define ObjectDescriptor_decode_ber OCTET_STRING_decode_ber #define ObjectDescriptor_print OCTET_STRING_print_utf8
#define ObjectDescriptor_encode_der OCTET_STRING_encode_der #endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
#define ObjectDescriptor_decode_xer OCTET_STRING_decode_xer_utf8
#define ObjectDescriptor_encode_xer OCTET_STRING_encode_xer_utf8 #define ObjectDescriptor_constraint asn_generic_unknown_constraint
#define ObjectDescriptor_decode_uper OCTET_STRING_decode_uper
#define ObjectDescriptor_encode_uper OCTET_STRING_encode_uper #if !defined(ASN_DISABLE_BER_SUPPORT)
#define ObjectDescriptor_decode_aper OCTET_STRING_decode_aper #define ObjectDescriptor_decode_ber OCTET_STRING_decode_ber
#define ObjectDescriptor_encode_aper OCTET_STRING_encode_aper #define ObjectDescriptor_encode_der OCTET_STRING_encode_der
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
#if !defined(ASN_DISABLE_XER_SUPPORT)
#define ObjectDescriptor_decode_xer OCTET_STRING_decode_xer_utf8
#define ObjectDescriptor_encode_xer OCTET_STRING_encode_xer_utf8
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
#define ObjectDescriptor_decode_uper OCTET_STRING_decode_uper
#define ObjectDescriptor_encode_uper OCTET_STRING_encode_uper
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
#define ObjectDescriptor_decode_aper OCTET_STRING_decode_aper
#define ObjectDescriptor_encode_aper OCTET_STRING_encode_aper
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -30,68 +30,98 @@ static const int _PrintableString_code2value[74] = {
* PrintableString basic type description. * PrintableString basic type description.
*/ */
static const ber_tlv_tag_t asn_DEF_PrintableString_tags[] = { static const ber_tlv_tag_t asn_DEF_PrintableString_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (19 << 2)), /* [UNIVERSAL 19] IMPLICIT ...*/ (ASN_TAG_CLASS_UNIVERSAL | (19 << 2)), /* [UNIVERSAL 19] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */ (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
}; };
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
static int asn_DEF_PrintableString_v2c(unsigned int value) { static int asn_DEF_PrintableString_v2c(unsigned int value) {
return _PrintableString_alphabet[value > 255 ? 0 : value] - 1; return _PrintableString_alphabet[value > 255 ? 0 : value] - 1;
} }
static int asn_DEF_PrintableString_c2v(unsigned int code) { static int asn_DEF_PrintableString_c2v(unsigned int code) {
if(code < 74) if(code < 74)
return _PrintableString_code2value[code]; return _PrintableString_code2value[code];
return -1; return -1;
} }
static asn_per_constraints_t asn_DEF_PrintableString_per_constraints = { static asn_per_constraints_t asn_DEF_PrintableString_per_constraints = {
{ APC_CONSTRAINED, 4, 4, 0x20, 0x39 }, /* Value */ { APC_CONSTRAINED, 4, 4, 0x20, 0x39 }, /* Value */
{ APC_SEMI_CONSTRAINED, -1, -1, 0, 0 }, /* Size */ { APC_SEMI_CONSTRAINED, -1, -1, 0, 0 }, /* Size */
asn_DEF_PrintableString_v2c, asn_DEF_PrintableString_v2c,
asn_DEF_PrintableString_c2v asn_DEF_PrintableString_c2v
}; };
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
asn_TYPE_operation_t asn_OP_PrintableString = { asn_TYPE_operation_t asn_OP_PrintableString = {
OCTET_STRING_free, OCTET_STRING_free,
OCTET_STRING_print_utf8, /* ASCII subset */ #if !defined(ASN_DISABLE_PRINT_SUPPORT)
OCTET_STRING_compare, OCTET_STRING_print_utf8, /* ASCII subset */
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
OCTET_STRING_encode_der,
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
#ifdef ASN_DISABLE_OER_SUPPORT
0,
0,
#else #else
OCTET_STRING_decode_oer, 0,
OCTET_STRING_encode_oer, #endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
#endif /* ASN_DISABLE_OER_SUPPORT */ OCTET_STRING_compare,
#ifdef ASN_DISABLE_PER_SUPPORT #if !defined(ASN_DISABLE_BER_SUPPORT)
0, OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
0, OCTET_STRING_encode_der,
0,
0,
#else #else
OCTET_STRING_decode_uper, 0,
OCTET_STRING_encode_uper, 0,
OCTET_STRING_decode_aper, #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
OCTET_STRING_encode_aper, #if !defined(ASN_DISABLE_XER_SUPPORT)
#endif /* ASN_DISABLE_PER_SUPPORT */ OCTET_STRING_decode_xer_utf8,
OCTET_STRING_random_fill, OCTET_STRING_encode_xer_utf8,
0 /* Use generic outmost tag fetcher */ #else
0,
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OCTET_STRING_decode_oer,
OCTET_STRING_encode_oer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
OCTET_STRING_decode_aper,
OCTET_STRING_encode_aper,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
OCTET_STRING_random_fill,
#else
0,
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
0 /* Use generic outmost tag fetcher */
}; };
asn_TYPE_descriptor_t asn_DEF_PrintableString = { asn_TYPE_descriptor_t asn_DEF_PrintableString = {
"PrintableString", "PrintableString",
"PrintableString", "PrintableString",
&asn_OP_PrintableString, &asn_OP_PrintableString,
asn_DEF_PrintableString_tags, asn_DEF_PrintableString_tags,
sizeof(asn_DEF_PrintableString_tags) sizeof(asn_DEF_PrintableString_tags)
/ sizeof(asn_DEF_PrintableString_tags[0]) - 1, / sizeof(asn_DEF_PrintableString_tags[0]) - 1,
asn_DEF_PrintableString_tags, asn_DEF_PrintableString_tags,
sizeof(asn_DEF_PrintableString_tags) sizeof(asn_DEF_PrintableString_tags)
/ sizeof(asn_DEF_PrintableString_tags[0]), / sizeof(asn_DEF_PrintableString_tags[0]),
{ 0, &asn_DEF_PrintableString_per_constraints, PrintableString_constraint }, {
0, 0, /* No members */ #if !defined(ASN_DISABLE_OER_SUPPORT)
0 /* No specifics */ 0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
&asn_DEF_PrintableString_per_constraints,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
PrintableString_constraint
},
0, 0, /* No members */
0 /* No specifics */
}; };
int int
PrintableString_constraint(const asn_TYPE_descriptor_t *td, const void *sptr, PrintableString_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
asn_app_constraint_failed_f *ctfailcb, asn_app_constraint_failed_f *ctfailcb,

View File

@@ -16,19 +16,34 @@ typedef OCTET_STRING_t PrintableString_t; /* Implemented via OCTET STRING */
extern asn_TYPE_descriptor_t asn_DEF_PrintableString; extern asn_TYPE_descriptor_t asn_DEF_PrintableString;
extern asn_TYPE_operation_t asn_OP_PrintableString; extern asn_TYPE_operation_t asn_OP_PrintableString;
#define PrintableString_free OCTET_STRING_free
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
#define PrintableString_print OCTET_STRING_print_utf8
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
#define PrintableString_compare OCTET_STRING_compare
asn_constr_check_f PrintableString_constraint; asn_constr_check_f PrintableString_constraint;
#define PrintableString_free OCTET_STRING_free #if !defined(ASN_DISABLE_BER_SUPPORT)
#define PrintableString_print OCTET_STRING_print_utf8 #define PrintableString_decode_ber OCTET_STRING_decode_ber
#define PrintableString_compare OCTET_STRING_compare #define PrintableString_encode_der OCTET_STRING_encode_der
#define PrintableString_decode_ber OCTET_STRING_decode_ber #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
#define PrintableString_encode_der OCTET_STRING_encode_der
#define PrintableString_decode_xer OCTET_STRING_decode_xer_utf8 #if !defined(ASN_DISABLE_XER_SUPPORT)
#define PrintableString_encode_xer OCTET_STRING_encode_xer_utf8 #define PrintableString_decode_xer OCTET_STRING_decode_xer_utf8
#define PrintableString_decode_uper OCTET_STRING_decode_uper #define PrintableString_encode_xer OCTET_STRING_encode_xer_utf8
#define PrintableString_encode_uper OCTET_STRING_encode_uper #endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#define PrintableString_decode_aper OCTET_STRING_decode_aper
#define PrintableString_encode_aper OCTET_STRING_encode_aper #if !defined(ASN_DISABLE_UPER_SUPPORT)
#define PrintableString_decode_uper OCTET_STRING_decode_uper
#define PrintableString_encode_uper OCTET_STRING_encode_uper
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
#define PrintableString_decode_aper OCTET_STRING_decode_aper
#define PrintableString_encode_aper OCTET_STRING_encode_aper
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -0,0 +1,219 @@
/*-
* Copyright (c) 2003, 2004, 2006 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <UTF8String.h>
/*
* UTF8String basic type description.
*/
static const ber_tlv_tag_t asn_DEF_UTF8String_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (12 << 2)), /* [UNIVERSAL 12] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), /* ... OCTET STRING */
};
asn_TYPE_operation_t asn_OP_UTF8String = {
OCTET_STRING_free,
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
UTF8String_print,
#else
0,
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
OCTET_STRING_compare,
#if !defined(ASN_DISABLE_BER_SUPPORT)
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
OCTET_STRING_encode_der,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
#if !defined(ASN_DISABLE_XER_SUPPORT)
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OCTET_STRING_decode_oer,
OCTET_STRING_encode_oer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
OCTET_STRING_decode_aper,
OCTET_STRING_encode_aper,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
UTF8String_random_fill,
#else
0,
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
0 /* Use generic outmost tag fetcher */
};
asn_TYPE_descriptor_t asn_DEF_UTF8String = {
"UTF8String",
"UTF8String",
&asn_OP_UTF8String,
asn_DEF_UTF8String_tags,
sizeof(asn_DEF_UTF8String_tags)
/ sizeof(asn_DEF_UTF8String_tags[0]) - 1,
asn_DEF_UTF8String_tags,
sizeof(asn_DEF_UTF8String_tags)
/ sizeof(asn_DEF_UTF8String_tags[0]),
{
#if !defined(ASN_DISABLE_OER_SUPPORT)
0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
UTF8String_constraint
},
0, 0, /* No members */
0 /* No specifics */
};
/*
* This is the table of length expectations.
* The second half of this table is only applicable to the long sequences.
*/
static const int UTF8String_ht[2][16] = {
{ /* 0x0 ... 0x7 */
/* 0000..0111 */
1, 1, 1, 1, 1, 1, 1, 1,
/* 1000..1011(0), 1100..1101(2), 1110(3), 1111(-1) */
0, 0, 0, 0, 2, 2, 3, -1 },
{ /* 0xF0 .. 0xF7 */
/* 11110000..11110111 */
4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 6, 6, -1, -1 }
};
static const int32_t UTF8String_mv[7] = { 0, 0,
0x00000080,
0x00000800,
0x00010000,
0x00200000,
0x04000000
};
/* Internal aliases for return codes */
#define U8E_TRUNC -1 /* UTF-8 sequence truncated */
#define U8E_ILLSTART -2 /* Illegal UTF-8 sequence start */
#define U8E_NOTCONT -3 /* Continuation expectation failed */
#define U8E_NOTMIN -4 /* Not minimal length encoding */
#define U8E_EINVAL -5 /* Invalid arguments */
int
UTF8String_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
ssize_t len = UTF8String_length((const UTF8String_t *)sptr);
switch(len) {
case U8E_EINVAL:
ASN__CTFAIL(app_key, td, sptr,
"%s: value not given", td->name);
break;
case U8E_TRUNC:
ASN__CTFAIL(app_key, td, sptr,
"%s: truncated UTF-8 sequence (%s:%d)",
td->name, __FILE__, __LINE__);
break;
case U8E_ILLSTART:
ASN__CTFAIL(app_key, td, sptr,
"%s: UTF-8 illegal start of encoding (%s:%d)",
td->name, __FILE__, __LINE__);
break;
case U8E_NOTCONT:
ASN__CTFAIL(app_key, td, sptr,
"%s: UTF-8 not continuation (%s:%d)",
td->name, __FILE__, __LINE__);
break;
case U8E_NOTMIN:
ASN__CTFAIL(app_key, td, sptr,
"%s: UTF-8 not minimal sequence (%s:%d)",
td->name, __FILE__, __LINE__);
break;
}
return (len < 0) ? -1 : 0;
}
static ssize_t
UTF8String__process(const UTF8String_t *st, uint32_t *dst, size_t dstlen) {
size_t length;
uint8_t *buf = st->buf;
uint8_t *end = buf + st->size;
uint32_t *dstend = dst + dstlen;
for(length = 0; buf < end; length++) {
int ch = *buf;
uint8_t *cend;
int32_t value;
int want;
/* Compute the sequence length */
want = UTF8String_ht[0][ch >> 4];
switch(want) {
case -1:
/* Second half of the table, long sequence */
want = UTF8String_ht[1][ch & 0x0F];
if(want != -1) break;
/* Fall through */
case 0:
return U8E_ILLSTART;
}
/* assert(want >= 1 && want <= 6) */
/* Check character sequence length */
if(buf + want > end) return U8E_TRUNC;
value = ch & (0xff >> want);
cend = buf + want;
for(buf++; buf < cend; buf++) {
ch = *buf;
if(ch < 0x80 || ch > 0xbf) return U8E_NOTCONT;
value = (value << 6) | (ch & 0x3F);
}
if(value < UTF8String_mv[want])
return U8E_NOTMIN;
if(dst < dstend)
*dst++ = value; /* Record value */
}
if(dst < dstend) *dst = 0; /* zero-terminate */
return length;
}
ssize_t
UTF8String_length(const UTF8String_t *st) {
if(st && st->buf) {
return UTF8String__process(st, 0, 0);
} else {
return U8E_EINVAL;
}
}
size_t
UTF8String_to_wcs(const UTF8String_t *st, uint32_t *dst, size_t dstlen) {
if(st && st->buf) {
ssize_t ret = UTF8String__process(st, dst, dstlen);
return (ret < 0) ? 0 : ret;
} else {
return 0;
}
}

View File

@@ -0,0 +1,80 @@
/*-
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _UTF8String_H_
#define _UTF8String_H_
#include <OCTET_STRING.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef OCTET_STRING_t UTF8String_t; /* Implemented via OCTET STRING */
extern asn_TYPE_descriptor_t asn_DEF_UTF8String;
extern asn_TYPE_operation_t asn_OP_UTF8String;
#define UTF8String_free OCTET_STRING_free
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
asn_struct_print_f UTF8String_print;
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
#define UTF8String_compare OCTET_STRING_compare
asn_constr_check_f UTF8String_constraint;
#if !defined(ASN_DISABLE_BER_SUPPORT)
#define UTF8String_decode_ber OCTET_STRING_decode_ber
#define UTF8String_encode_der OCTET_STRING_encode_der
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
#if !defined(ASN_DISABLE_XER_SUPPORT)
#define UTF8String_decode_xer OCTET_STRING_decode_xer_utf8
#define UTF8String_encode_xer OCTET_STRING_encode_xer_utf8
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
#define UTF8String_decode_uper OCTET_STRING_decode_uper
#define UTF8String_encode_uper OCTET_STRING_encode_uper
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
#define UTF8String_decode_aper OCTET_STRING_decode_aper
#define UTF8String_encode_aper OCTET_STRING_encode_aper
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
asn_random_fill_f UTF8String_random_fill;
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
/*
* Returns length of the given UTF-8 string in characters,
* or a negative error code:
* -1: UTF-8 sequence truncated
* -2: Illegal UTF-8 sequence start
* -3: Continuation expectation failed
* -4: Not minimal length encoding
* -5: Invalid arguments
*/
ssize_t UTF8String_length(const UTF8String_t *st);
/*
* Convert the UTF-8 string into a sequence of wide characters.
* Returns the number of characters necessary.
* Returned value might be greater than dstlen.
* In case of conversion error, 0 is returned.
*
* If st points to a valid UTF-8 string, calling
* UTF8String_to_wcs(st, 0, 0);
* is equivalent to
* UTF8String_length(const UTF8String_t *st);
*/
size_t UTF8String_to_wcs(const UTF8String_t *st, uint32_t *dst, size_t dstlen);
#ifdef __cplusplus
}
#endif
#endif /* _UTF8String_H_ */

View File

@@ -0,0 +1,22 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <UTF8String.h>
int
UTF8String_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
asn_app_consume_bytes_f *cb, void *app_key) {
const UTF8String_t *st = (const UTF8String_t *)sptr;
(void)td; /* Unused argument */
(void)ilevel; /* Unused argument */
if(st && st->buf) {
return (cb(st->buf, st->size, app_key) < 0) ? -1 : 0;
} else {
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <UTF8String.h>
/*
* Biased function for randomizing UTF-8 sequences.
*/
static size_t
UTF8String__random_char(uint8_t *b, size_t size) {
static const struct rnd_value {
const char *value;
size_t size;
} values[] = {{"\0", 1},
{"\x01", 1},
{"\x7f", 1},
{"\xc2\xa2", 2},
{"\xe2\x82\xac", 3},
{"\xf0\x90\x8d\x88", 4},
{"\xf4\x8f\xbf\xbf", 4}};
const struct rnd_value *v;
size_t max_idx = 0;
switch(size) {
case 0:
assert(size != 0);
return 0;
case 1:
max_idx = 2;
break;
case 2:
max_idx = 3;
break;
default:
case 4:
max_idx = sizeof(values) / sizeof(values[0]) - 1;
break;
}
v = &values[asn_random_between(0, max_idx)];
memcpy(b, v->value, v->size);
return v->size;
}
asn_random_fill_result_t
UTF8String_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
const asn_encoding_constraints_t *constraints,
size_t max_length) {
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
uint8_t *buf;
uint8_t *bend;
uint8_t *b;
size_t rnd_len;
size_t idx;
UTF8String_t *st;
if(max_length == 0 && !*sptr) return result_skipped;
/* Figure out how far we should go */
rnd_len = OCTET_STRING_random_length_constrained(td, constraints,
max_length / 4);
buf = CALLOC(4, rnd_len + 1);
if(!buf) return result_failed;
bend = &buf[4 * rnd_len];
for(b = buf, idx = 0; idx < rnd_len; idx++) {
b += UTF8String__random_char(b, (bend - b));
}
*(uint8_t *)b = 0;
if(*sptr) {
st = *sptr;
FREEMEM(st->buf);
} else {
st = (OCTET_STRING_t *)(*sptr = CALLOC(1, sizeof(UTF8String_t)));
if(!st) {
FREEMEM(buf);
return result_failed;
}
}
st->buf = buf;
st->size = b - buf;
assert(UTF8String_length(st) == (ssize_t)rnd_len);
return result_ok;
}

View File

@@ -0,0 +1,130 @@
/*-
* Copyright (c) 2003, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <VisibleString.h>
/*
* VisibleString basic type description.
*/
static const ber_tlv_tag_t asn_DEF_VisibleString_tags[] = {
(ASN_TAG_CLASS_UNIVERSAL | (26 << 2)), /* [UNIVERSAL 26] IMPLICIT ...*/
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) /* ... OCTET STRING */
};
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
static asn_per_constraints_t asn_DEF_VisibleString_constraints = {
{ APC_CONSTRAINED, 7, 7, 0x20, 0x7e }, /* Value */
{ APC_SEMI_CONSTRAINED, -1, -1, 0, 0 }, /* Size */
0, 0
};
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
asn_TYPE_operation_t asn_OP_VisibleString = {
OCTET_STRING_free,
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
OCTET_STRING_print_utf8, /* ASCII subset */
#else
0,
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
OCTET_STRING_compare,
#if !defined(ASN_DISABLE_BER_SUPPORT)
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
OCTET_STRING_encode_der,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
#if !defined(ASN_DISABLE_XER_SUPPORT)
OCTET_STRING_decode_xer_utf8,
OCTET_STRING_encode_xer_utf8,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_OER_SUPPORT)
OCTET_STRING_decode_oer,
OCTET_STRING_encode_oer,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
OCTET_STRING_decode_uper,
OCTET_STRING_encode_uper,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
OCTET_STRING_decode_aper,
OCTET_STRING_encode_aper,
#else
0,
0,
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
OCTET_STRING_random_fill,
#else
0,
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
0 /* Use generic outmost tag fetcher */
};
asn_TYPE_descriptor_t asn_DEF_VisibleString = {
"VisibleString",
"VisibleString",
&asn_OP_VisibleString,
asn_DEF_VisibleString_tags,
sizeof(asn_DEF_VisibleString_tags)
/ sizeof(asn_DEF_VisibleString_tags[0]) - 1,
asn_DEF_VisibleString_tags,
sizeof(asn_DEF_VisibleString_tags)
/ sizeof(asn_DEF_VisibleString_tags[0]),
{
#if !defined(ASN_DISABLE_OER_SUPPORT)
0,
#endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
&asn_DEF_VisibleString_constraints,
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
VisibleString_constraint
},
0, 0, /* No members */
0 /* No specifics */
};
int
VisibleString_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
const VisibleString_t *st = (const VisibleString_t *)sptr;
if(st && st->buf) {
uint8_t *buf = st->buf;
uint8_t *end = buf + st->size;
/*
* Check the alphabet of the VisibleString.
* ISO646, ISOReg#6
* The alphabet is a subset of ASCII between the space
* and "~" (tilde).
*/
for(; buf < end; buf++) {
if(*buf < 0x20 || *buf > 0x7e) {
ASN__CTFAIL(app_key, td, sptr,
"%s: value byte %ld (%d) "
"not in VisibleString alphabet (%s:%d)",
td->name,
(long)((buf - st->buf) + 1),
*buf,
__FILE__, __LINE__);
return -1;
}
}
} else {
ASN__CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
return 0;
}

View File

@@ -0,0 +1,52 @@
/*-
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _VisibleString_H_
#define _VisibleString_H_
#include <OCTET_STRING.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef OCTET_STRING_t VisibleString_t; /* Implemented via OCTET STRING */
extern asn_TYPE_descriptor_t asn_DEF_VisibleString;
extern asn_TYPE_operation_t asn_OP_VisibleString;
#define VisibleString_free OCTET_STRING_free
#if !defined(ASN_DISABLE_PRINT_SUPPORT)
#define VisibleString_print OCTET_STRING_print
#endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
#define VisibleString_compare OCTET_STRING_compare
asn_constr_check_f VisibleString_constraint;
#if !defined(ASN_DISABLE_BER_SUPPORT)
#define VisibleString_decode_ber OCTET_STRING_decode_ber
#define VisibleString_encode_der OCTET_STRING_encode_der
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
#if !defined(ASN_DISABLE_XER_SUPPORT)
#define VisibleString_decode_xer OCTET_STRING_decode_xer_hex
#define VisibleString_encode_xer OCTET_STRING_encode_xer
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
#define VisibleString_decode_uper OCTET_STRING_decode_uper
#define VisibleString_encode_uper OCTET_STRING_encode_uper
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
#define VisibleString_decode_aper OCTET_STRING_decode_aper
#define VisibleString_encode_aper OCTET_STRING_encode_aper
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#ifdef __cplusplus
}
#endif
#endif /* _VisibleString_H_ */

View File

@@ -0,0 +1,91 @@
#include <asn_application.h>
#include <asn_internal.h>
#include <aper_decoder.h>
asn_dec_rval_t
aper_decode_complete(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void **sptr,
const void *buffer, size_t size) {
asn_dec_rval_t rval;
rval = aper_decode(opt_codec_ctx, td, sptr, buffer, size, 0, 0);
if(rval.consumed) {
/*
* We've always given 8-aligned data,
* so convert bits to integral bytes.
*/
rval.consumed += 7;
rval.consumed >>= 3;
} else if(rval.code == RC_OK) {
if(size) {
if(((const uint8_t *)buffer)[0] == 0) {
rval.consumed = 1; /* 1 byte */
} else {
ASN_DEBUG("Expecting single zeroed byte");
rval.code = RC_FAIL;
}
} else {
/* Must contain at least 8 bits. */
rval.code = RC_WMORE;
}
}
return rval;
}
asn_dec_rval_t
aper_decode(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void **sptr, const void *buffer,
size_t size, int skip_bits, int unused_bits) {
asn_codec_ctx_t s_codec_ctx;
asn_dec_rval_t rval;
asn_per_data_t pd;
if(skip_bits < 0 || skip_bits > 7
|| unused_bits < 0 || unused_bits > 7
|| (unused_bits > 0 && !size))
ASN__DECODE_FAILED;
/*
* Stack checker requires that the codec context
* must be allocated on the stack.
*/
if(opt_codec_ctx) {
if(opt_codec_ctx->max_stack_size) {
s_codec_ctx = *opt_codec_ctx;
opt_codec_ctx = &s_codec_ctx;
}
} else {
/* If context is not given, be security-conscious anyway */
memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
s_codec_ctx.max_stack_size = ASN__DEFAULT_STACK_MAX;
opt_codec_ctx = &s_codec_ctx;
}
/* Fill in the position indicator */
memset(&pd, 0, sizeof(pd));
pd.buffer = (const uint8_t *)buffer;
pd.nboff = skip_bits;
pd.nbits = 8 * size - unused_bits; /* 8 is CHAR_BIT from <limits.h> */
if(pd.nboff > pd.nbits)
ASN__DECODE_FAILED;
/*
* Invoke type-specific decoder.
*/
if(!td->op->aper_decoder)
ASN__DECODE_FAILED; /* PER is not compiled in */
rval = td->op->aper_decoder(opt_codec_ctx, td, 0, sptr, &pd);
if(rval.code == RC_OK) {
/* Return the number of consumed bits */
rval.consumed = ((pd.buffer - (const uint8_t *)buffer) << 3)
+ pd.nboff - skip_bits;
ASN_DEBUG("PER decoding consumed %zu, counted %zu",
rval.consumed, pd.moved);
assert(rval.consumed == pd.moved);
} else {
/* PER codec is not a restartable */
rval.consumed = 0;
}
return rval;
}

View File

@@ -0,0 +1,47 @@
/*-
* Copyright (c) 2005-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _APER_DECODER_H_
#define _APER_DECODER_H_
#include <asn_application.h>
#include <aper_support.h>
#ifdef __cplusplus
extern "C" {
#endif
struct asn_TYPE_descriptor_s; /* Forward declaration */
/*
* Aligned PER decoder of a "complete encoding" as per X.691#10.1.
* On success, this call always returns (.consumed >= 1), in BITS, as per X.691#10.1.3.
*/
asn_dec_rval_t aper_decode_complete(
const struct asn_codec_ctx_s *opt_codec_ctx,
const struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */
void **struct_ptr, /* Pointer to a target structure's pointer */
const void *buffer, /* Data to be decoded */
size_t size /* Size of data buffer */
);
/*
* Aligned PER decoder of any ASN.1 type. May be invoked by the application.
* WARNING: This call returns the number of BITS read from the stream. Beware.
*/
asn_dec_rval_t aper_decode(
const struct asn_codec_ctx_s *opt_codec_ctx,
const struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */
void **struct_ptr, /* Pointer to a target structure's pointer */
const void *buffer, /* Data to be decoded */
size_t size, /* Size of data buffer */
int skip_bits, /* Number of unused leading bits, 0..7 */
int unused_bits /* Number of unused tailing bits, 0..7 */
);
#ifdef __cplusplus
}
#endif
#endif /* _APER_DECODER_H_ */

View File

@@ -0,0 +1,129 @@
#include <asn_application.h>
#include <asn_internal.h>
#include <aper_encoder.h>
/*
* Argument type and callback necessary for aper_encode_to_buffer().
*/
typedef struct enc_to_buf_arg {
void *buffer;
size_t left;
} enc_to_buf_arg;
static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) {
enc_to_buf_arg *arg = (enc_to_buf_arg *)key;
if(arg->left < size)
return -1; /* Data exceeds the available buffer size */
memcpy(arg->buffer, buffer, size);
arg->buffer = ((char *)arg->buffer) + size;
arg->left -= size;
return 0;
}
asn_enc_rval_t
aper_encode_to_buffer(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, void *buffer, size_t buffer_size) {
enc_to_buf_arg key;
key.buffer = buffer;
key.left = buffer_size;
if(td) ASN_DEBUG("Encoding \"%s\" using ALIGNED PER", td->name);
return aper_encode(td, constraints, sptr, encode_to_buffer_cb, &key);
}
ssize_t
aper_encode_to_new_buffer(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, void **buffer_r) {
asn_enc_rval_t er = {0,0,0};
enc_dyn_arg key;
memset(&key, 0, sizeof(key));
er = aper_encode(td, constraints, sptr, encode_dyn_cb, &key);
switch(er.encoded) {
case -1:
FREEMEM(key.buffer);
return -1;
case 0:
FREEMEM(key.buffer);
key.buffer = MALLOC(1);
if(key.buffer) {
*(char *)key.buffer = '\0';
*buffer_r = key.buffer;
return 1;
} else {
return -1;
}
default:
*buffer_r = key.buffer;
ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
return ((er.encoded + 7) >> 3);
}
}
/*
* Internally useful functions.
*/
/* Flush partially filled buffer */
static int
_aper_encode_flush_outp(asn_per_outp_t *po) {
uint8_t *buf;
if(po->nboff == 0 && po->buffer == po->tmpspace)
return 0;
buf = po->buffer + (po->nboff >> 3);
/* Make sure we account for the last, partially filled */
if(po->nboff & 0x07) {
buf[0] &= 0xff << (8 - (po->nboff & 0x07));
buf++;
}
if (po->output) {
return po->output(po->tmpspace, buf - po->tmpspace, po->op_key);
}
return 0;
}
asn_enc_rval_t
aper_encode(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, asn_app_consume_bytes_f *cb, void *app_key) {
asn_per_outp_t po;
asn_enc_rval_t er = {0,0,0};
/*
* Invoke type-specific encoder.
*/
if(!td || !td->op->aper_encoder)
ASN__ENCODE_FAILED; /* PER is not compiled in */
po.buffer = po.tmpspace;
po.nboff = 0;
po.nbits = 8 * sizeof(po.tmpspace);
po.output = cb ? cb : ignore_output;
po.op_key = app_key;
po.flushed_bytes = 0;
er = td->op->aper_encoder(td, constraints, sptr, &po);
if(er.encoded != -1) {
size_t bits_to_flush;
bits_to_flush = ((po.buffer - po.tmpspace) << 3) + po.nboff;
/* Set number of bits encoded to a firm value */
er.encoded = (po.flushed_bytes << 3) + bits_to_flush;
if(_aper_encode_flush_outp(&po))
ASN__ENCODE_FAILED;
}
return er;
}

View File

@@ -0,0 +1,63 @@
/*-
* Copyright (c) 2006-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _APER_ENCODER_H_
#define _APER_ENCODER_H_
#include <asn_application.h>
#include <aper_support.h>
#ifdef __cplusplus
extern "C" {
#endif
struct asn_TYPE_descriptor_s; /* Forward declaration */
/*
* Aligned PER encoder of any ASN.1 type. May be invoked by the application.
* WARNING: This function returns the number of encoded bits in the .encoded
* field of the return value. Use the following formula to convert to bytes:
* bytes = ((.encoded + 7) / 8)
*/
asn_enc_rval_t aper_encode(
const struct asn_TYPE_descriptor_s *type_descriptor,
const asn_per_constraints_t *constraints,
const void *struct_ptr, /* Structure to be encoded */
asn_app_consume_bytes_f *consume_bytes_cb, /* Data collector */
void *app_key /* Arbitrary callback argument */
);
/*
* A variant of aper_encode() which encodes data into the existing buffer
* WARNING: This function returns the number of encoded bits in the .encoded
* field of the return value.
*/
asn_enc_rval_t aper_encode_to_buffer(
const struct asn_TYPE_descriptor_s *type_descriptor,
const asn_per_constraints_t *constraints,
const void *struct_ptr, /* Structure to be encoded */
void *buffer, /* Pre-allocated buffer */
size_t buffer_size /* Initial buffer size (max) */
);
/*
* A variant of aper_encode_to_buffer() which allocates buffer itself.
* Returns the number of bytes in the buffer or -1 in case of failure.
* WARNING: This function produces a "Production of the complete encoding",
* with length of at least one octet. Contrast this to precise bit-packing
* encoding of aper_encode() and aper_encode_to_buffer().
*/
ssize_t
aper_encode_to_new_buffer(
const struct asn_TYPE_descriptor_s *td,
const asn_per_constraints_t *constraints,
const void *sptr,
void **buffer_r
);
#ifdef __cplusplus
}
#endif
#endif /* _APER_ENCODER_H_ */

View File

@@ -0,0 +1,149 @@
/*
* Copyright (c) 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_internal.h>
#include <aper_encoder.h>
#include <aper_support.h>
#include <aper_opentype.h>
static asn_dec_rval_t
aper_open_type_get_simple(const asn_codec_ctx_t *ctx,
const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
asn_dec_rval_t rv;
ssize_t chunk_bytes;
int repeat;
uint8_t *buf = 0;
size_t bufLen = 0;
size_t bufSize = 0;
asn_per_data_t spd;
size_t padding;
ASN__STACK_OVERFLOW_CHECK(ctx);
ASN_DEBUG("Getting open type %s...", td->name);
do {
chunk_bytes = aper_get_length(pd, -1, -1, &repeat);
if(chunk_bytes < 0) {
FREEMEM(buf);
ASN__DECODE_STARVED;
}
if(bufLen + chunk_bytes > bufSize) {
void *ptr;
bufSize = chunk_bytes + (bufSize << 2);
ptr = REALLOC(buf, bufSize);
if(!ptr) {
FREEMEM(buf);
ASN__DECODE_FAILED;
}
buf = ptr;
}
if(per_get_many_bits(pd, buf + bufLen, 0, chunk_bytes << 3)) {
FREEMEM(buf);
ASN__DECODE_STARVED;
}
bufLen += chunk_bytes;
} while(repeat);
ASN_DEBUG("Getting open type %s encoded in %ld bytes", td->name,
(long)bufLen);
memset(&spd, 0, sizeof(spd));
spd.buffer = buf;
spd.nbits = bufLen << 3;
ASN_DEBUG_INDENT_ADD(+4);
rv = td->op->aper_decoder(ctx, td, constraints, sptr, &spd);
ASN_DEBUG_INDENT_ADD(-4);
if(rv.code == RC_OK) {
/* Check padding validity */
padding = spd.nbits - spd.nboff;
if (((padding > 0 && padding < 8) ||
/* X.691#10.1.3 */
(spd.nboff == 0 && spd.nbits == 8 && spd.buffer == buf)) &&
per_get_few_bits(&spd, padding) == 0) {
/* Everything is cool */
FREEMEM(buf);
return rv;
}
FREEMEM(buf);
if(padding >= 8) {
ASN_DEBUG("Too large padding %d in open type", (int)padding);
ASN__DECODE_FAILED;
} else {
ASN_DEBUG("No padding");
}
} else {
FREEMEM(buf);
/* rv.code could be RC_WMORE, nonsense in this context */
rv.code = RC_FAIL; /* Noone would give us more */
}
return rv;
}
int
aper_open_type_put(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, asn_per_outp_t *po) {
void *buf;
void *bptr;
ssize_t size;
size_t toGo;
ASN_DEBUG("Open type put %s ...", td->name);
size = aper_encode_to_new_buffer(td, constraints, sptr, &buf);
if(size <= 0) return -1;
for(bptr = buf, toGo = size; toGo;) {
int need_eom = 0;
ssize_t maySave = aper_put_length(po, -1, toGo, &need_eom);
if(maySave < 0) break;
if(per_put_many_bits(po, bptr, maySave * 8)) break;
bptr = (char *)bptr + maySave;
toGo -= maySave;
if(need_eom && aper_put_length(po, -1, 0, 0)) {
FREEMEM(buf);
return -1;
}
}
FREEMEM(buf);
if(toGo) return -1;
ASN_DEBUG("Open type put %s of length %ld + overhead (1byte?)",
td->name, size);
return 0;
}
asn_dec_rval_t
aper_open_type_get(const asn_codec_ctx_t *ctx,
const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
void **sptr, asn_per_data_t *pd) {
return aper_open_type_get_simple(ctx, td, constraints, sptr, pd);
}
int
aper_open_type_skip(const asn_codec_ctx_t *ctx, asn_per_data_t *pd) {
asn_TYPE_descriptor_t s_td;
asn_dec_rval_t rv;
asn_TYPE_operation_t op_t;
memset(&op_t, 0, sizeof(op_t));
s_td.name = "<unknown extension>";
s_td.op = &op_t;
s_td.op->aper_decoder = uper_sot_suck;
rv = aper_open_type_get(ctx, &s_td, 0, 0, pd);
if(rv.code != RC_OK)
return -1;
else
return 0;
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) 2007-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _APER_OPENTYPE_H_
#define _APER_OPENTYPE_H_
#include <per_opentype.h>
#ifdef __cplusplus
extern "C" {
#endif
asn_dec_rval_t aper_open_type_get(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
void **sptr, asn_per_data_t *pd);
int aper_open_type_skip(const asn_codec_ctx_t *opt_codec_ctx, asn_per_data_t *pd);
int aper_open_type_put(const asn_TYPE_descriptor_t *td,
const asn_per_constraints_t *constraints,
const void *sptr, asn_per_outp_t *po);
#ifdef __cplusplus
}
#endif
#endif /* _APER_OPENTYPE_H_ */

View File

@@ -0,0 +1,292 @@
/*
* Copyright (c) 2005-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#include <asn_system.h>
#include <asn_internal.h>
#include <aper_support.h>
int32_t
aper_get_align(asn_per_data_t *pd) {
if(pd->nboff & 0x7) {
ASN_DEBUG("Aligning %ld bits", 8 - ((unsigned long)pd->nboff & 0x7));
return per_get_few_bits(pd, 8 - (pd->nboff & 0x7));
}
return 0;
}
ssize_t
aper_get_length(asn_per_data_t *pd, int range, int ebits, int *repeat) {
ssize_t value;
*repeat = 0;
/*
* ITU-T X.691(08/2015)
* #11.9.4.2
*
* If the length determinant "n" to be encoded is a normally small length,
* or a constrained whole number with "ub" greater than or equal to 64K,
* or is a semi-constrained whole number, then "n" shall be encoded
* as specified in 11.9.3.4 to 11.9.3.8.4.
*
* NOTE Thus, if "ub" is greater than or equal to 64K,
* the encoding of the length determinant is the same as it would be
* if the length were unconstrained.
*/
if (range <= 65535 && range >= 0)
return aper_get_nsnnwn(pd, range);
if (aper_get_align(pd) < 0)
return -1;
if(ebits >= 0) return per_get_few_bits(pd, ebits);
value = per_get_few_bits(pd, 8);
if(value < 0) return -1;
if((value & 128) == 0) /* #11.9.3.6 */
return (value & 0x7F);
if((value & 64) == 0) { /* #11.9.3.7 */
value = ((value & 63) << 8) | per_get_few_bits(pd, 8);
if(value < 0) return -1;
return value;
}
value &= 63; /* this is "m" from X.691, #11.9.3.8 */
if(value < 1 || value > 4)
return -1;
*repeat = 1;
return (16384 * value);
}
ssize_t
aper_get_nslength(asn_per_data_t *pd) {
ssize_t length;
ASN_DEBUG("Getting normally small length");
if(per_get_few_bits(pd, 1) == 0) {
length = per_get_few_bits(pd, 6) + 1;
if(length <= 0) return -1;
ASN_DEBUG("l=%ld", length);
return length;
} else {
int repeat;
length = aper_get_length(pd, -1, -1, &repeat);
if(length >= 0 && !repeat) return length;
return -1; /* Error, or do not support >16K extensions */
}
}
#if !defined(USE_OLDER_APER_NSNNWN)
ssize_t
aper_get_nsnnwn(asn_per_data_t *pd, int range) {
ssize_t value;
int bytes = 0;
ASN_DEBUG("getting nsnnwn with range %d", range);
if(range <= 255) {
int i;
if (range < 0) return -1;
/* 1 -> 8 bits */
for (i = 1; i <= 8; i++) {
int upper = 1 << i;
if (upper >= range)
break;
}
value = per_get_few_bits(pd, i);
return value;
} else if (range == 256){
/* 1 byte */
bytes = 1;
} else if (range <= 65536) {
/* 2 bytes */
bytes = 2;
} else {
//return -1;
int length;
/* handle indefinite range */
length = per_get_few_bits(pd, 1);
if (length == 0)
return per_get_few_bits(pd, 6);
if (aper_get_align(pd) < 0)
return -1;
length = per_get_few_bits(pd, 8);
/* the length is not likely to be that big */
if (length > 4)
return -1;
value = 0;
if (per_get_many_bits(pd, (uint8_t *)&value, 0, length * 8) < 0)
return -1;
return value;
}
if (aper_get_align(pd) < 0)
return -1;
value = per_get_few_bits(pd, 8 * bytes);
return value;
}
#else /* old APER codec */
ssize_t
aper_get_nsnnwn(asn_per_data_t *pd, int dummy_range) {
ssize_t value;
ASN_DEBUG("Get the normally small non-negative whole number APER");
value = per_get_few_bits(pd, 7);
if(value & 64) { /* implicit (value < 0) */
value &= 63;
value <<= 2;
value |= per_get_few_bits(pd, 2);
if(value & 128) /* implicit (value < 0) */
return -1;
if(value == 0)
return 0;
if(value >= 3)
return -1;
value = per_get_few_bits(pd, 8 * value);
return value;
}
return value;
}
#endif /* don't use old APER */
int aper_put_align(asn_per_outp_t *po) {
if(po->nboff & 0x7) {
ASN_DEBUG("Aligning %ld bits", 8 - ((unsigned long)po->nboff & 0x7));
if(per_put_few_bits(po, 0x00, (8 - (po->nboff & 0x7))))
return -1;
}
return 0;
}
ssize_t
aper_put_length(asn_per_outp_t *po, int range, size_t length, int *need_eom) {
int dummy = 0;
if(!need_eom) need_eom = &dummy;
*need_eom = 0;
ASN_DEBUG("APER put length %zu with range %d", length, range);
/* 11.9 X.691 Note 2 */
if (range <= 65536 && range >= 0)
return aper_put_nsnnwn(po, range, length);
if (aper_put_align(po) < 0)
return -1;
if(length <= 127) /* #11.9.3.6 */{
return per_put_few_bits(po, length, 8)
? -1 : (ssize_t)length;
}
else if(length < 16384) /* #11.9.3.7 */
return per_put_few_bits(po, length|0x8000, 16)
? -1 : (ssize_t)length;
*need_eom = 0 == (length & 16383);
length >>= 14;
if(length > 4) {
*need_eom = 0;
length = 4;
}
return per_put_few_bits(po, 0xC0 | length, 8)
? -1 : (ssize_t)(length << 14);
}
int
aper_put_nslength(asn_per_outp_t *po, size_t length) {
if(length <= 64) {
/* #11.9.3.4 */
if(length == 0) return -1;
return per_put_few_bits(po, length-1, 7) ? -1 : 0;
} else {
if(aper_put_length(po, -1, length, 0) != (ssize_t)length) {
/* This might happen in case of >16K extensions */
return -1;
}
}
return 0;
}
#if !defined(USE_OLDER_APER_NSNNWN)
int
aper_put_nsnnwn(asn_per_outp_t *po, int range, int number) {
int bytes;
ASN_DEBUG("aper put nsnnwn %d with range %d", number, range);
/* 10.5.7.1 X.691 */
if(range < 0) {
int i;
for (i = 1; ; i++) {
int bits = 1 << (8 * i);
if (number <= bits)
break;
}
bytes = i;
assert(i <= 4);
}
if(range <= 255) {
int i;
for (i = 1; i <= 8; i++) {
int bits = 1 << i;
if (range <= bits)
break;
}
return per_put_few_bits(po, number, i);
} else if(range == 256) {
bytes = 1;
} else if(range <= 65536) {
bytes = 2;
} else { /* Ranges > 64K */
int i;
for (i = 1; ; i++) {
int bits = 1 << (8 * i);
if (range <= bits)
break;
}
assert(i <= 4);
bytes = i;
}
if(aper_put_align(po) < 0) /* Aligning on octet */
return -1;
/* if(per_put_few_bits(po, bytes, 8))
return -1;
*/
return per_put_few_bits(po, number, 8 * bytes);
}
#else /* preserve old code base in case */
int
aper_put_nsnnwn(asn_per_outp_t *po, int dummy_range, int n) {
int bytes;
ASN_DEBUG("aper_put_nsnnwn");
if(n <= 63) {
if(n < 0) return -1;
return per_put_few_bits(po, n, 7);
}
if(n < 256)
bytes = 1;
else if(n < 65536)
bytes = 2;
else if(n < 256 * 65536)
bytes = 3;
else
return -1; /* This is not a "normally small" value */
if(per_put_few_bits(po, bytes, 8))
return -1;
return per_put_few_bits(po, n, 8 * bytes);
}
#endif /* which aper_put_nsnnwn() */

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2005-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
#ifndef _APER_SUPPORT_H_
#define _APER_SUPPORT_H_
#include <asn_system.h> /* Platform-specific types */
#include <per_support.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* X.691 (08/2015) #11.9 "General rules for encoding a length determinant"
* Get the length "n" from the Aligned PER stream.
*/
ssize_t aper_get_length(asn_per_data_t *pd, int range,
int effective_bound_bits, int *repeat);
/*
* Get the normally small length "n".
*/
ssize_t aper_get_nslength(asn_per_data_t *pd);
/*
* Get the normally small non-negative whole number.
*/
ssize_t aper_get_nsnnwn(asn_per_data_t *pd, int range);
/*
* X.691 (08/2015) #11.9 "General rules for encoding a length determinant"
* Put the length "whole_length" to the Aligned PER stream.
* If (opt_need_eom) is given, it will be set to 1 if final 0-length is needed.
* In that case, invoke uper_put_length(po, 0, 0) after encoding the last block.
* This function returns the number of units which may be flushed
* in the next units saving iteration.
*/
ssize_t aper_put_length(asn_per_outp_t *po, int range, size_t length,
int *opt_need_eom);
/* Align the current bit position to octet bundary */
int aper_put_align(asn_per_outp_t *po);
int32_t aper_get_align(asn_per_data_t *pd);
/*
* Put the normally small length "n" to the Unaligned PER stream.
* Returns 0 or -1.
*/
int aper_put_nslength(asn_per_outp_t *po, size_t length);
/*
* Put the normally small non-negative whole number.
*/
int aper_put_nsnnwn(asn_per_outp_t *po, int range, int number);
#ifdef __cplusplus
}
#endif
#endif /* _APER_SUPPORT_H_ */

View File

@@ -226,7 +226,9 @@ asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, const void *sptr, const asn_TYPE_descriptor_t *td, const void *sptr,
asn_app_consume_bytes_f *callback, void *callback_key) { asn_app_consume_bytes_f *callback, void *callback_key) {
asn_enc_rval_t er = {0,0,0}; asn_enc_rval_t er = {0,0,0};
#if !defined(ASN_DISABLE_XER_SUPPORT)
enum xer_encoder_flags_e xer_flags = XER_F_CANONICAL; enum xer_encoder_flags_e xer_flags = XER_F_CANONICAL;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
(void)opt_codec_ctx; /* Parameters are not checked on encode yet. */ (void)opt_codec_ctx; /* Parameters are not checked on encode yet. */
@@ -265,6 +267,7 @@ asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
errno = ENOENT; /* Randomization doesn't make sense on output. */ errno = ENOENT; /* Randomization doesn't make sense on output. */
ASN__ENCODE_FAILED; ASN__ENCODE_FAILED;
#if !defined(ASN_DISABLE_BER_SUPPORT)
case ATS_BER: case ATS_BER:
/* BER is a superset of DER. */ /* BER is a superset of DER. */
/* Fall through. */ /* Fall through. */
@@ -273,27 +276,29 @@ asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
er = der_encode(td, sptr, callback, callback_key); er = der_encode(td, sptr, callback, callback_key);
if(er.encoded == -1) { if(er.encoded == -1) {
if(er.failed_type && er.failed_type->op->der_encoder) { if(er.failed_type && er.failed_type->op->der_encoder) {
errno = EBADF; /* Structure has incorrect form. */ errno = EBADF; /* Structure has incorrect form. */
} else { } else {
errno = ENOENT; /* DER is not defined for this type. */ errno = ENOENT; /* DER is not defined for this type. */
} }
} }
} else { } else {
errno = ENOENT; /* Transfer syntax is not defined for this type. */ errno = ENOENT; /* Transfer syntax is not defined for this type. */
ASN__ENCODE_FAILED; ASN__ENCODE_FAILED;
} }
break; break;
case ATS_CER: case ATS_CER:
errno = ENOENT; /* Transfer syntax is not defined for any type. */ errno = ENOENT; /* Transfer syntax is not defined for any type. */
ASN__ENCODE_FAILED;
#else
case ATS_BER:
case ATS_DER:
case ATS_CER:
errno = ENOENT; /* BER is not defined. */
ASN__ENCODE_FAILED; ASN__ENCODE_FAILED;
#ifdef ASN_DISABLE_OER_SUPPORT #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
case ATS_BASIC_OER:
case ATS_CANONICAL_OER: #if !defined(ASN_DISABLE_OER_SUPPORT)
errno = ENOENT; /* PER is not defined. */
ASN__ENCODE_FAILED;
break;
#else /* ASN_DISABLE_OER_SUPPORT */
case ATS_BASIC_OER: case ATS_BASIC_OER:
/* CANONICAL-OER is a superset of BASIC-OER. */ /* CANONICAL-OER is a superset of BASIC-OER. */
/* Fall through. */ /* Fall through. */
@@ -302,27 +307,25 @@ asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
er = oer_encode(td, sptr, callback, callback_key); er = oer_encode(td, sptr, callback, callback_key);
if(er.encoded == -1) { if(er.encoded == -1) {
if(er.failed_type && er.failed_type->op->oer_encoder) { if(er.failed_type && er.failed_type->op->oer_encoder) {
errno = EBADF; /* Structure has incorrect form. */ errno = EBADF; /* Structure has incorrect form. */
} else { } else {
errno = ENOENT; /* OER is not defined for this type. */ errno = ENOENT; /* OER is not defined for this type. */
} }
} }
} else { } else {
errno = ENOENT; /* Transfer syntax is not defined for this type. */ errno = ENOENT; /* Transfer syntax is not defined for this type. */
ASN__ENCODE_FAILED; ASN__ENCODE_FAILED;
} }
break; break;
#endif /* ASN_DISABLE_OER_SUPPORT */ #else
case ATS_BASIC_OER:
#ifdef ASN_DISABLE_PER_SUPPORT case ATS_CANONICAL_OER:
case ATS_UNALIGNED_BASIC_PER: errno = ENOENT; /* OER is not defined. */
case ATS_UNALIGNED_CANONICAL_PER:
case ATS_ALIGNED_BASIC_PER:
case ATS_ALIGNED_CANONICAL_PER:
errno = ENOENT; /* PER is not defined. */
ASN__ENCODE_FAILED; ASN__ENCODE_FAILED;
break; break;
#else /* ASN_DISABLE_PER_SUPPORT */ #endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
#if !defined(ASN_DISABLE_UPER_SUPPORT)
case ATS_UNALIGNED_BASIC_PER: case ATS_UNALIGNED_BASIC_PER:
/* CANONICAL-UPER is a superset of BASIC-UPER. */ /* CANONICAL-UPER is a superset of BASIC-UPER. */
/* Fall through. */ /* Fall through. */
@@ -331,9 +334,9 @@ asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
er = uper_encode(td, 0, sptr, callback, callback_key); er = uper_encode(td, 0, sptr, callback, callback_key);
if(er.encoded == -1) { if(er.encoded == -1) {
if(er.failed_type && er.failed_type->op->uper_encoder) { if(er.failed_type && er.failed_type->op->uper_encoder) {
errno = EBADF; /* Structure has incorrect form. */ errno = EBADF; /* Structure has incorrect form. */
} else { } else {
errno = ENOENT; /* UPER is not defined for this type. */ errno = ENOENT; /* UPER is not defined for this type. */
} }
} else { } else {
ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded); ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
@@ -343,16 +346,24 @@ asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
errno = EBADF; errno = EBADF;
ASN__ENCODE_FAILED; ASN__ENCODE_FAILED;
} }
er.encoded = 8; /* Exactly 8 zero bits is added. */ er.encoded = 8; /* Exactly 8 zero bits is added. */
} }
/* Convert bits into bytes */ /* Convert bits into bytes */
er.encoded = (er.encoded + 7) >> 3; er.encoded = (er.encoded + 7) >> 3;
} }
} else { } else {
errno = ENOENT; /* Transfer syntax is not defined for this type. */ errno = ENOENT; /* Transfer syntax is not defined for this type. */
ASN__ENCODE_FAILED; ASN__ENCODE_FAILED;
} }
break; break;
#else
case ATS_UNALIGNED_BASIC_PER:
case ATS_UNALIGNED_CANONICAL_PER:
errno = ENOENT; /* UPER is not defined. */
ASN__ENCODE_FAILED;
break;
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
case ATS_ALIGNED_BASIC_PER: case ATS_ALIGNED_BASIC_PER:
/* CANONICAL-APER is a superset of BASIC-APER. */ /* CANONICAL-APER is a superset of BASIC-APER. */
/* Fall through. */ /* Fall through. */
@@ -361,9 +372,9 @@ asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
er = aper_encode(td, 0, sptr, callback, callback_key); er = aper_encode(td, 0, sptr, callback, callback_key);
if(er.encoded == -1) { if(er.encoded == -1) {
if(er.failed_type && er.failed_type->op->aper_encoder) { if(er.failed_type && er.failed_type->op->aper_encoder) {
errno = EBADF; /* Structure has incorrect form. */ errno = EBADF; /* Structure has incorrect form. */
} else { } else {
errno = ENOENT; /* APER is not defined for this type. */ errno = ENOENT; /* APER is not defined for this type. */
} }
} else { } else {
ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded); ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
@@ -373,18 +384,25 @@ asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
errno = EBADF; errno = EBADF;
ASN__ENCODE_FAILED; ASN__ENCODE_FAILED;
} }
er.encoded = 8; /* Exactly 8 zero bits is added. */ er.encoded = 8; /* Exactly 8 zero bits is added. */
} }
/* Convert bits into bytes */ /* Convert bits into bytes */
er.encoded = (er.encoded + 7) >> 3; er.encoded = (er.encoded + 7) >> 3;
} }
} else { } else {
errno = ENOENT; /* Transfer syntax is not defined for this type. */ errno = ENOENT; /* Transfer syntax is not defined for this type. */
ASN__ENCODE_FAILED; ASN__ENCODE_FAILED;
} }
break; break;
#endif /* ASN_DISABLE_PER_SUPPORT */ #else
case ATS_ALIGNED_BASIC_PER:
case ATS_ALIGNED_CANONICAL_PER:
errno = ENOENT; /* APER is not defined. */
ASN__ENCODE_FAILED;
break;
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
#if !defined(ASN_DISABLE_XER_SUPPORT)
case ATS_BASIC_XER: case ATS_BASIC_XER:
/* CANONICAL-XER is a superset of BASIC-XER. */ /* CANONICAL-XER is a superset of BASIC-XER. */
xer_flags &= ~XER_F_CANONICAL; xer_flags &= ~XER_F_CANONICAL;
@@ -395,16 +413,23 @@ asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
er = xer_encode(td, sptr, xer_flags, callback, callback_key); er = xer_encode(td, sptr, xer_flags, callback, callback_key);
if(er.encoded == -1) { if(er.encoded == -1) {
if(er.failed_type && er.failed_type->op->xer_encoder) { if(er.failed_type && er.failed_type->op->xer_encoder) {
errno = EBADF; /* Structure has incorrect form. */ errno = EBADF; /* Structure has incorrect form. */
} else { } else {
errno = ENOENT; /* XER is not defined for this type. */ errno = ENOENT; /* XER is not defined for this type. */
} }
} }
} else { } else {
errno = ENOENT; /* Transfer syntax is not defined for this type. */ errno = ENOENT; /* Transfer syntax is not defined for this type. */
ASN__ENCODE_FAILED; ASN__ENCODE_FAILED;
} }
break; break;
#else
case ATS_BASIC_XER:
case ATS_CANONICAL_XER:
errno = ENOENT; /* XER is not defined. */
ASN__ENCODE_FAILED;
break;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
default: default:
errno = ENOENT; errno = ENOENT;
@@ -430,6 +455,7 @@ asn_decode(const asn_codec_ctx_t *opt_codec_ctx,
ASN__DECODE_FAILED; ASN__DECODE_FAILED;
case ATS_RANDOM: case ATS_RANDOM:
#if !defined(ASN_DISABLE_RFILL_SUPPORT)
if(!td->op->random_fill) { if(!td->op->random_fill) {
ASN__DECODE_FAILED; ASN__DECODE_FAILED;
} else { } else {
@@ -441,41 +467,55 @@ asn_decode(const asn_codec_ctx_t *opt_codec_ctx,
} }
} }
break; break;
#else
errno = ENOENT;
ASN__DECODE_FAILED;
#endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
case ATS_DER: case ATS_DER:
case ATS_BER: case ATS_BER:
#if !defined(ASN_DISABLE_BER_SUPPORT)
return ber_decode(opt_codec_ctx, td, sptr, buffer, size); return ber_decode(opt_codec_ctx, td, sptr, buffer, size);
#else
errno = ENOENT;
ASN__DECODE_FAILED;
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
case ATS_BASIC_OER: case ATS_BASIC_OER:
case ATS_CANONICAL_OER: case ATS_CANONICAL_OER:
#ifdef ASN_DISABLE_OER_SUPPORT #if !defined(ASN_DISABLE_OER_SUPPORT)
return oer_decode(opt_codec_ctx, td, sptr, buffer, size);
#else
errno = ENOENT; errno = ENOENT;
ASN__DECODE_FAILED; ASN__DECODE_FAILED;
#else #endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
return oer_decode(opt_codec_ctx, td, sptr, buffer, size);
#endif
case ATS_UNALIGNED_BASIC_PER: case ATS_UNALIGNED_BASIC_PER:
case ATS_UNALIGNED_CANONICAL_PER: case ATS_UNALIGNED_CANONICAL_PER:
#ifdef ASN_DISABLE_PER_SUPPORT #if !defined(ASN_DISABLE_UPER_SUPPORT)
return uper_decode_complete(opt_codec_ctx, td, sptr, buffer, size);
#else
errno = ENOENT; errno = ENOENT;
ASN__DECODE_FAILED; ASN__DECODE_FAILED;
#else #endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
return uper_decode_complete(opt_codec_ctx, td, sptr, buffer, size);
#endif
case ATS_ALIGNED_BASIC_PER: case ATS_ALIGNED_BASIC_PER:
case ATS_ALIGNED_CANONICAL_PER: case ATS_ALIGNED_CANONICAL_PER:
#ifdef ASN_DISABLE_PER_SUPPORT #if !defined(ASN_DISABLE_APER_SUPPORT)
return aper_decode_complete(opt_codec_ctx, td, sptr, buffer, size);
#else
errno = ENOENT; errno = ENOENT;
ASN__DECODE_FAILED; ASN__DECODE_FAILED;
#else #endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
return aper_decode_complete(opt_codec_ctx, td, sptr, buffer, size);
#endif
case ATS_BASIC_XER: case ATS_BASIC_XER:
case ATS_CANONICAL_XER: case ATS_CANONICAL_XER:
#if !defined(ASN_DISABLE_XER_SUPPORT)
return xer_decode(opt_codec_ctx, td, sptr, buffer, size); return xer_decode(opt_codec_ctx, td, sptr, buffer, size);
#else
errno = ENOENT;
ASN__DECODE_FAILED;
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
} }
} }

View File

@@ -10,6 +10,7 @@
#include "asn_system.h" /* for platform-dependent types */ #include "asn_system.h" /* for platform-dependent types */
#include "asn_codecs.h" /* for ASN.1 codecs specifics */ #include "asn_codecs.h" /* for ASN.1 codecs specifics */
#include "asn_config.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@@ -4,115 +4,6 @@
*/ */
#include <asn_internal.h> #include <asn_internal.h>
#include <asn_codecs_prim.h> #include <asn_codecs_prim.h>
#include <errno.h>
/*
* Decode an always-primitive type.
*/
asn_dec_rval_t
ber_decode_primitive(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void **sptr,
const void *buf_ptr, size_t size, int tag_mode) {
ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
asn_dec_rval_t rval;
ber_tlv_len_t length = 0; /* =0 to avoid [incorrect] warning. */
/*
* If the structure is not there, allocate it.
*/
if(st == NULL) {
st = (ASN__PRIMITIVE_TYPE_t *)CALLOC(1, sizeof(*st));
if(st == NULL) ASN__DECODE_FAILED;
*sptr = (void *)st;
}
ASN_DEBUG("Decoding %s as plain primitive (tm=%d)",
td->name, tag_mode);
/*
* Check tags and extract value length.
*/
rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
tag_mode, 0, &length, 0);
if(rval.code != RC_OK)
return rval;
ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
/*
* Make sure we have this length.
*/
buf_ptr = ((const char *)buf_ptr) + rval.consumed;
size -= rval.consumed;
if(length > (ber_tlv_len_t)size) {
rval.code = RC_WMORE;
rval.consumed = 0;
return rval;
}
st->size = (int)length;
/* The following better be optimized away. */
if(sizeof(st->size) != sizeof(length)
&& (ber_tlv_len_t)st->size != length) {
st->size = 0;
ASN__DECODE_FAILED;
}
st->buf = (uint8_t *)MALLOC(length + 1);
if(!st->buf) {
st->size = 0;
ASN__DECODE_FAILED;
}
memcpy(st->buf, buf_ptr, length);
st->buf[length] = '\0'; /* Just in case */
rval.code = RC_OK;
rval.consumed += length;
ASN_DEBUG("Took %ld/%ld bytes to encode %s",
(long)rval.consumed,
(long)length, td->name);
return rval;
}
/*
* Encode an always-primitive type using DER.
*/
asn_enc_rval_t
der_encode_primitive(const asn_TYPE_descriptor_t *td, const void *sptr,
int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
asn_enc_rval_t erval = {0,0,0};
const ASN__PRIMITIVE_TYPE_t *st = (const ASN__PRIMITIVE_TYPE_t *)sptr;
ASN_DEBUG("%s %s as a primitive type (tm=%d)",
cb?"Encoding":"Estimating", td->name, tag_mode);
erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag,
cb, app_key);
ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded);
if(erval.encoded == -1) {
erval.failed_type = td;
erval.structure_ptr = sptr;
return erval;
}
if(cb && st->buf) {
if(cb(st->buf, st->size, app_key) < 0) {
erval.encoded = -1;
erval.failed_type = td;
erval.structure_ptr = sptr;
return erval;
}
} else {
assert(st->buf || st->size == 0);
}
erval.encoded += st->size;
ASN__ENCODED_OK(erval);
}
void void
ASN__PRIMITIVE_TYPE_free(const asn_TYPE_descriptor_t *td, void *sptr, ASN__PRIMITIVE_TYPE_free(const asn_TYPE_descriptor_t *td, void *sptr,
@@ -138,180 +29,3 @@ ASN__PRIMITIVE_TYPE_free(const asn_TYPE_descriptor_t *td, void *sptr,
break; break;
} }
} }
/*
* Local internal type passed around as an argument.
*/
struct xdp_arg_s {
const asn_TYPE_descriptor_t *type_descriptor;
void *struct_key;
xer_primitive_body_decoder_f *prim_body_decoder;
int decoded_something;
int want_more;
};
/*
* Since some kinds of primitive values can be encoded using value-specific
* tags (<MINUS-INFINITY>, <enum-element>, etc), the primitive decoder must
* be supplied with such tags to parse them as needed.
*/
static int
xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) {
struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
enum xer_pbd_rval bret;
/*
* The chunk_buf is guaranteed to start at '<'.
*/
assert(chunk_size && ((const char *)chunk_buf)[0] == 0x3c);
/*
* Decoding was performed once already. Prohibit doing it again.
*/
if(arg->decoded_something)
return -1;
bret = arg->prim_body_decoder(arg->type_descriptor,
arg->struct_key, chunk_buf, chunk_size);
switch(bret) {
case XPBD_SYSTEM_FAILURE:
case XPBD_DECODER_LIMIT:
case XPBD_BROKEN_ENCODING:
break;
case XPBD_BODY_CONSUMED:
/* Tag decoded successfully */
arg->decoded_something = 1;
/* Fall through */
case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
return 0;
}
return -1;
}
static ssize_t
xer_decode__primitive_body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) {
struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
enum xer_pbd_rval bret;
size_t lead_wsp_size;
if(arg->decoded_something) {
if(xer_whitespace_span(chunk_buf, chunk_size) == chunk_size) {
/*
* Example:
* "<INTEGER>123<!--/--> </INTEGER>"
* ^- chunk_buf position.
*/
return chunk_size;
}
/*
* Decoding was done once already. Prohibit doing it again.
*/
return -1;
}
if(!have_more) {
/*
* If we've received something like "1", we can't really
* tell whether it is really `1` or `123`, until we know
* that there is no more data coming.
* The have_more argument will be set to 1 once something
* like this is available to the caller of this callback:
* "1<tag_start..."
*/
arg->want_more = 1;
return -1;
}
lead_wsp_size = xer_whitespace_span(chunk_buf, chunk_size);
chunk_buf = (const char *)chunk_buf + lead_wsp_size;
chunk_size -= lead_wsp_size;
bret = arg->prim_body_decoder(arg->type_descriptor,
arg->struct_key, chunk_buf, chunk_size);
switch(bret) {
case XPBD_SYSTEM_FAILURE:
case XPBD_DECODER_LIMIT:
case XPBD_BROKEN_ENCODING:
break;
case XPBD_BODY_CONSUMED:
/* Tag decoded successfully */
arg->decoded_something = 1;
/* Fall through */
case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
return lead_wsp_size + chunk_size;
}
return -1;
}
asn_dec_rval_t
xer_decode_primitive(const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *td, void **sptr,
size_t struct_size, const char *opt_mname,
const void *buf_ptr, size_t size,
xer_primitive_body_decoder_f *prim_body_decoder) {
const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
asn_struct_ctx_t s_ctx;
struct xdp_arg_s s_arg;
asn_dec_rval_t rc;
/*
* Create the structure if does not exist.
*/
if(!*sptr) {
*sptr = CALLOC(1, struct_size);
if(!*sptr) ASN__DECODE_FAILED;
}
memset(&s_ctx, 0, sizeof(s_ctx));
s_arg.type_descriptor = td;
s_arg.struct_key = *sptr;
s_arg.prim_body_decoder = prim_body_decoder;
s_arg.decoded_something = 0;
s_arg.want_more = 0;
rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
xml_tag, buf_ptr, size,
xer_decode__unexpected_tag, xer_decode__primitive_body);
switch(rc.code) {
case RC_OK:
if(!s_arg.decoded_something) {
char ch;
ASN_DEBUG("Primitive body is not recognized, "
"supplying empty one");
/*
* Decoding opportunity has come and gone.
* Where's the result?
* Try to feed with empty body, see if it eats it.
*/
if(prim_body_decoder(s_arg.type_descriptor,
s_arg.struct_key, &ch, 0)
!= XPBD_BODY_CONSUMED) {
/*
* This decoder does not like empty stuff.
*/
ASN__DECODE_FAILED;
}
}
break;
case RC_WMORE:
/*
* Redo the whole thing later.
* We don't have a context to save intermediate parsing state.
*/
rc.consumed = 0;
break;
case RC_FAIL:
rc.consumed = 0;
if(s_arg.want_more)
rc.code = RC_WMORE;
else
ASN__DECODE_FAILED;
break;
}
return rc;
}

View File

@@ -12,23 +12,27 @@ extern "C" {
#endif #endif
typedef struct ASN__PRIMITIVE_TYPE_s { typedef struct ASN__PRIMITIVE_TYPE_s {
uint8_t *buf; /* Buffer with consecutive primitive encoding bytes */ uint8_t *buf; /* Buffer with consecutive primitive encoding bytes */
size_t size; /* Size of the buffer */ size_t size; /* Size of the buffer */
} ASN__PRIMITIVE_TYPE_t; /* Do not use this type directly! */ } ASN__PRIMITIVE_TYPE_t; /* Do not use this type directly! */
asn_struct_free_f ASN__PRIMITIVE_TYPE_free; asn_struct_free_f ASN__PRIMITIVE_TYPE_free;
#if !defined(ASN_DISABLE_BER_SUPPORT)
ber_type_decoder_f ber_decode_primitive; ber_type_decoder_f ber_decode_primitive;
der_type_encoder_f der_encode_primitive; der_type_encoder_f der_encode_primitive;
#endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
#if !defined(ASN_DISABLE_XER_SUPPORT)
/* /*
* A callback specification for the xer_decode_primitive() function below. * A callback specification for the xer_decode_primitive() function below.
*/ */
enum xer_pbd_rval { enum xer_pbd_rval {
XPBD_SYSTEM_FAILURE, /* System failure (memory shortage, etc) */ XPBD_SYSTEM_FAILURE, /* System failure (memory shortage, etc) */
XPBD_DECODER_LIMIT, /* Hit some decoder limitation or deficiency */ XPBD_DECODER_LIMIT, /* Hit some decoder limitation or deficiency */
XPBD_BROKEN_ENCODING, /* Encoding of a primitive body is broken */ XPBD_BROKEN_ENCODING, /* Encoding of a primitive body is broken */
XPBD_NOT_BODY_IGNORE, /* Not a body format, but safe to ignore */ XPBD_NOT_BODY_IGNORE, /* Not a body format, but safe to ignore */
XPBD_BODY_CONSUMED /* Body is recognized and consumed */ XPBD_BODY_CONSUMED /* Body is recognized and consumed */
}; };
typedef enum xer_pbd_rval(xer_primitive_body_decoder_f)( typedef enum xer_pbd_rval(xer_primitive_body_decoder_f)(
const asn_TYPE_descriptor_t *td, void *struct_ptr, const void *chunk_buf, const asn_TYPE_descriptor_t *td, void *struct_ptr, const void *chunk_buf,
@@ -43,6 +47,7 @@ asn_dec_rval_t xer_decode_primitive(
const asn_TYPE_descriptor_t *type_descriptor, void **struct_ptr, const asn_TYPE_descriptor_t *type_descriptor, void **struct_ptr,
size_t struct_size, const char *opt_mname, const void *buf_ptr, size_t size, size_t struct_size, const char *opt_mname, const void *buf_ptr, size_t size,
xer_primitive_body_decoder_f *prim_body_decoder); xer_primitive_body_decoder_f *prim_body_decoder);
#endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -0,0 +1,6 @@
// Generated automatically. Don't edit manually!
#define ASN_DISABLE_BER_SUPPORT 1
#define ASN_DISABLE_XER_SUPPORT 1
#define ASN_DISABLE_OER_SUPPORT 1
#define ASN_DISABLE_UPER_SUPPORT 1

View File

@@ -21,6 +21,15 @@
extern "C" { extern "C" {
#endif #endif
#if !defined(ASN_DISABLE_UPER_SUPPORT)
#include <uper_decoder.h>
#include <uper_encoder.h>
#endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
#if !defined(ASN_DISABLE_APER_SUPPORT)
#include <aper_decoder.h>
#include <aper_encoder.h>
#endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
/* Environment version might be used to avoid running with the old library */ /* Environment version might be used to avoid running with the old library */
#define ASN1C_ENVIRONMENT_VERSION 923 /* Compile-time version */ #define ASN1C_ENVIRONMENT_VERSION 923 /* Compile-time version */
int get_asn1c_environment_version(void); /* Run-time version */ int get_asn1c_environment_version(void); /* Run-time version */
@@ -136,6 +145,13 @@ asn__format_to_callback(
* Check stack against overflow, if limit is set. * Check stack against overflow, if limit is set.
*/ */
#define ASN__DEFAULT_STACK_MAX (30000) #define ASN__DEFAULT_STACK_MAX (30000)
#ifdef ASN_DISABLE_STACK_OVERFLOW_CHECK
static int CC_NOTUSED
ASN__STACK_OVERFLOW_CHECK(const asn_codec_ctx_t *ctx) {
(void)ctx;
return 0;
}
#else
static int CC_NOTUSED static int CC_NOTUSED
ASN__STACK_OVERFLOW_CHECK(const asn_codec_ctx_t *ctx) { ASN__STACK_OVERFLOW_CHECK(const asn_codec_ctx_t *ctx) {
if(ctx && ctx->max_stack_size) { if(ctx && ctx->max_stack_size) {
@@ -153,6 +169,7 @@ ASN__STACK_OVERFLOW_CHECK(const asn_codec_ctx_t *ctx) {
} }
return 0; return 0;
} }
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -43,12 +43,17 @@ asn_random_between(intmax_t lb, intmax_t rb) {
uintmax_t value = 0; uintmax_t value = 0;
uintmax_t got_entropy = 0; uintmax_t got_entropy = 0;
(void)intmax_max;
assert(RAND_MAX > 0xffffff); /* Seen 7ffffffd! */ assert(RAND_MAX > 0xffffff); /* Seen 7ffffffd! */
assert(range < intmax_max); assert(range < intmax_max);
for(; got_entropy < range;) { for(; got_entropy < range;) {
got_entropy = (got_entropy << 24) | 0xffffff; got_entropy = (got_entropy << 24) | 0xffffff;
#ifdef HAVE_RANDOM
value = (value << 24) | (random() % 0xffffff); value = (value << 24) | (random() % 0xffffff);
#else
value = (value << 24) | (rand() % 0xffffff);
#endif
} }
return lb + (intmax_t)(value % (range + 1)); return lb + (intmax_t)(value % (range + 1));

View File

@@ -75,7 +75,9 @@ typedef unsigned int uint32_t;
#else /* !defined(__vxworks) */ #else /* !defined(__vxworks) */
#include <inttypes.h> /* C99 specifies this file */ #include <inttypes.h> /* C99 specifies this file */
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h> /* for ntohl() */ #include <netinet/in.h> /* for ntohl() */
#endif
#define sys_ntohl(foo) ntohl(foo) #define sys_ntohl(foo) ntohl(foo)
#endif /* defined(__vxworks) */ #endif /* defined(__vxworks) */
@@ -86,11 +88,25 @@ typedef unsigned int uint32_t;
#else #else
#define CC_ATTRIBUTE(attr) #define CC_ATTRIBUTE(attr)
#endif #endif
#define CC_PRINTFLIKE(fmt, var) CC_ATTRIBUTE(format(printf, fmt, var)) #if defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__>= 4) || __GNUC__ > 4)
#define CC_PRINTFLIKE(fmt, var) CC_ATTRIBUTE(format(gnu_printf, fmt, var))
#elif defined(__GNUC__)
#if defined(ANDROID)
#define CC_PRINTFLIKE(fmt, var) CC_ATTRIBUTE(__format__(__printf__, fmt, var))
#else
#define CC_PRINTFLIKE(fmt, var) CC_ATTRIBUTE(format(printf, fmt, var))
#endif
#else
#define CC_PRINTFLIKE(fmt, var)
#endif
#define CC_NOTUSED CC_ATTRIBUTE(unused) #define CC_NOTUSED CC_ATTRIBUTE(unused)
#ifndef CC_ATTR_NO_SANITIZE #ifndef CC_ATTR_NO_SANITIZE
#if __GNUC__ < 8
#define CC_ATTR_NO_SANITIZE(what)
#else
#define CC_ATTR_NO_SANITIZE(what) CC_ATTRIBUTE(no_sanitize(what)) #define CC_ATTR_NO_SANITIZE(what) CC_ATTRIBUTE(no_sanitize(what))
#endif #endif
#endif
/* Figure out if thread safety is requested */ /* Figure out if thread safety is requested */
#if !defined(ASN_THREAD_SAFE) && (defined(THREAD_SAFE) || defined(_REENTRANT)) #if !defined(ASN_THREAD_SAFE) && (defined(THREAD_SAFE) || defined(_REENTRANT))

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More