blob: ed93bce5d83a92ccd13edfbe807a25ac7ffd73ab [file] [log] [blame]
Lev Walkin288527b2014-10-26 20:12:53 -07001\batchmode
Lev Walkin464166c2010-11-09 08:34:38 -08002\documentclass[english,oneside,12pt]{book}
Lev Walkin194b2102013-03-28 01:29:06 -07003\usepackage[no-math]{fontspec}
4\usepackage{MnSymbol}
Lev Walkin464166c2010-11-09 08:34:38 -08005\usepackage{xunicode}
6\usepackage{xltxtra}
7
Lev Walkin11c9a8c2013-03-26 00:46:55 -07008\usepackage[hmargin={1in,1in},vmargin={1.5in,1.5in}]{geometry}
Lev Walkin464166c2010-11-09 08:34:38 -08009
10\defaultfontfeatures{Mapping=tex-text}
Lev Walkin11c9a8c2013-03-26 00:46:55 -070011\setmainfont{PT Sans}
12\setsansfont{PT Sans}
Lev Walkin464166c2010-11-09 08:34:38 -080013\setmonofont{Consolas}
14
Lev Walkined44bf42010-11-08 02:04:55 -080015\usepackage{fancyhdr}
Lev Walkind5627a12017-11-07 01:04:40 -080016\usepackage{fancyref}
Lev Walkined44bf42010-11-08 02:04:55 -080017\usepackage{longtable}
Lev Walkin464166c2010-11-09 08:34:38 -080018\usepackage{booktabs}
Lev Walkined44bf42010-11-08 02:04:55 -080019\usepackage{url}
Lev Walkin11c9a8c2013-03-26 00:46:55 -070020\usepackage{xcolor}
21\usepackage{listings}
22\usepackage{setspace}
Lev Walkin194b2102013-03-28 01:29:06 -070023\usepackage{unicode-math}
24\usepackage{perpage}
25\MakePerPage{footnote}
Lev Walkin11c9a8c2013-03-26 00:46:55 -070026
27\setstretch{1.1}
28
29% Courier 10 Pitch
30\def\courierFont{Courier10 BT WGL4}
31%\def\courierFont{Consolas}
32\setmonofont[Scale=1.05]{\courierFont}
Lev Walkin194b2102013-03-28 01:29:06 -070033\setmathfont[Scale=1.05]{Cambria Math}
Lev Walkin11c9a8c2013-03-26 00:46:55 -070034
Lev Walkined44bf42010-11-08 02:04:55 -080035
36\makeatletter
37
Lev Walkined44bf42010-11-08 02:04:55 -080038%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Textclass specific LaTeX commands.
Lev Walkin11c9a8c2013-03-26 00:46:55 -070039\lstloadlanguages{C,bash}
40\newfontfamily\listingfont[Scale=1.05]{\courierFont}
41\newfontfamily\inlinelistingfont[Scale=1.05]{\courierFont}
42\definecolor{clrlcomment}{gray}{0.3}
43\definecolor{clrlkeyword}{rgb}{0.588,0.145,0.18}
44\newcommand{\listingkeyword}[1]{\color{clrlkeyword}{#1}}
45\newcommand{\listingstring}[1]{\color{clrlcomment}{#1}}
46\newcommand{\listingcomment}[1]{\color{clrlcomment}{#1}}
47\lstset{tabsize=4,
48 showstringspaces=false,
49 showtabs=false,
50 showspaces=false,
51 keywordstyle=\listingkeyword,
52 stringstyle=\listingstring,
53 commentstyle=\listingcomment,
54 xleftmargin=\parindent,
55 columns=fixed,
56 escapechar=\%,
57 texcl
58}
59\lstdefinestyle{listingStyle}{
60 basicstyle=\small\listingfont,
61 stringstyle=\listingstring,
62 breaklines=true,
63 breakatwhitespace=true,
64 flexiblecolumns=false
65 }
66\lstdefinelanguage{asn1}{
Lev Walkind5627a12017-11-07 01:04:40 -080067 morekeywords={DEFINITIONS,BEGIN,END,AUTOMATIC,TAGS,SEQUENCE,SET,OF,CHOICE,OPTIONAL,INTEGER,MAX},
Lev Walkin11c9a8c2013-03-26 00:46:55 -070068 morecomment=[l]{--},
69 morecomment=[n]{/*}{*/}
70 }
71
72\lstnewenvironment{codesample}[1][]{\lstset{style=listingStyle,language=C,#1}}{}
Lev Walkin2a744a72013-03-27 01:56:23 -070073\lstnewenvironment{bash}[1][]{\lstset{style=listingStyle,language=bash,#1}}{}
Lev Walkin11c9a8c2013-03-26 00:46:55 -070074\lstnewenvironment{asn}[1][]{\lstset{style=listingStyle,language=asn1,#1}}{}
Lev Walkinf3334582017-11-07 00:02:24 -080075
76\newcommand{\code}[1]{\lstinline{#1}}
77\newcommand{\cmd}[1]{\texttt{#1}}
Lev Walkined44bf42010-11-08 02:04:55 -080078
79%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% User specified LaTeX commands.
80\usepackage{extramarks}
81\lhead{\firstxmark}
82\rfoot{\lastxmark}
Lev Walkin11c9a8c2013-03-26 00:46:55 -070083\definecolor{clrlink}{rgb}{0,0.4,0}
84\definecolor{clrurl}{rgb}{0,0,.6}
Lev Walkined44bf42010-11-08 02:04:55 -080085\usepackage[colorlinks=true,
Lev Walkin11c9a8c2013-03-26 00:46:55 -070086 linkcolor={clrlink},
87 citecolor={clrlink},
88 urlcolor={clrurl},
89 pdfauthor={Lev Walkin},
90 pdftitle={Using the Open Source ASN.1 Compiler},
91 pdfkeywords={ASN.1,asn1c,compiler},
92 bookmarksopen,bookmarksopenlevel=1,
93 pdffitwindow,
94 xetex
Lev Walkined44bf42010-11-08 02:04:55 -080095]{hyperref}
Lev Walkined44bf42010-11-08 02:04:55 -080096
97\makeatother
98
99\usepackage{babel}
100
101\begin{document}
102
Lev Walkin50155de2014-10-26 19:46:16 -0700103\title{Using the Open Source ASN.1 Compiler\\
Lev Walkin288527b2014-10-26 20:12:53 -0700104\vspace*{0.4cm}
Lev Walkin50155de2014-10-26 19:46:16 -0700105\Large Documentation for asn1c version \asnver{}}
Lev Walkined44bf42010-11-08 02:04:55 -0800106\author{Lev Walkin <\href{mailto:vlm@lionet.info?Subject=asn1c}{vlm@lionet.info}>}
107
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700108\pagestyle{fancy}
109\fancyhead[L]{\leftmark}
Lev Walkin50155de2014-10-26 19:46:16 -0700110\fancyhead[R]{\href{http://lionet.info/asn1c}{asn1c-\asnver}}
Lev Walkined44bf42010-11-08 02:04:55 -0800111\maketitle
Lev Walkined44bf42010-11-08 02:04:55 -0800112
113\tableofcontents{}
114
Lev Walkind5627a12017-11-07 01:04:40 -0800115\chapter{\label{chap:Quick-start-examples}Quick start examples}
Lev Walkined44bf42010-11-08 02:04:55 -0800116
Lev Walkinf3334582017-11-07 00:02:24 -0800117\section{A “Rectangle” converter and debugger}
Lev Walkined44bf42010-11-08 02:04:55 -0800118
Lev Walkinf3334582017-11-07 00:02:24 -0800119One of the most common need is to create some sort of analysis tool
120for the existing ASN.1 data files. Let's build a converter for existing
121Rectangle binary files between BER, OER, PER, and XER (XML).
122
123\begin{enumerate}
124\item Create a file named \textbf{rectangle.asn} with the following contents:
125\begin{asn}
126RectangleModule DEFINITIONS ::= BEGIN
127
128Rectangle ::= SEQUENCE {
129 height INTEGER,
130 width INTEGER
131}
132
133END
134\end{asn}
135
136\item Compile it into the set of .c and .h files using \cmd{asn1c} compiler:
137
138\begin{bash}
139asn1c -pdu=%\textbf{Rectangle}% -gen-OER -gen-PER %\textbf{rectangle.asn}%
140\end{bash}
141
142\item Create the converter and dumper:
143
144\begin{bash}
145make -f Makefile.am.example
146\end{bash}
147
148\item Done. The binary file converter is ready:
149
150\begin{bash}
151./converter-example -h
152\end{bash}
153\end{enumerate}
154
155\section{A “Rectangle” Encoder}
Lev Walkined44bf42010-11-08 02:04:55 -0800156
157This example will help you create a simple BER and XER encoder of
Lev Walkin464166c2010-11-09 08:34:38 -0800158a ``Rectangle'' type used throughout this document.
Lev Walkined44bf42010-11-08 02:04:55 -0800159\begin{enumerate}
Lev Walkinf3334582017-11-07 00:02:24 -0800160\item Create a file named \textbf{rectangle.asn} with the following contents:
Lev Walkined44bf42010-11-08 02:04:55 -0800161
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700162\begin{asn}
Lev Walkinf3334582017-11-07 00:02:24 -0800163RectangleModule DEFINITIONS ::= BEGIN
Lev Walkined44bf42010-11-08 02:04:55 -0800164
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700165Rectangle ::= SEQUENCE {
166 height INTEGER,
167 width INTEGER
168}
Lev Walkined44bf42010-11-08 02:04:55 -0800169
170END
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700171\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -0800172\item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}:
173
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700174\begin{bash}
Lev Walkinf3334582017-11-07 00:02:24 -0800175asn1c %\textbf{rectangle.asn}%
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700176\end{bash}
Lev Walkined44bf42010-11-08 02:04:55 -0800177\item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading
Lev Walkinf3334582017-11-07 00:02:24 -0800178the \textbf{rectangle.asn} file into the Web form and unpacking the
Lev Walkined44bf42010-11-08 02:04:55 -0800179produced archive on your computer.
180\item By this time, you should have gotten multiple files in the current
181directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}.
182\item Create a main() routine which creates the Rectangle\_t structure in
183memory and encodes it using BER and XER encoding rules. Let's name
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700184the file \textbf{main.c}:
Lev Walkined44bf42010-11-08 02:04:55 -0800185
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700186\begin{codesample}[basicstyle=\scriptsize\listingfont]
187#include <stdio.h>
188#include <sys/types.h>
189#include <Rectangle.h> /* Rectangle ASN.1 type */
Lev Walkined44bf42010-11-08 02:04:55 -0800190
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700191/* Write the encoded output into some FILE stream. */
192static int write_out(const void *buffer, size_t size, void *app_key) {
193 FILE *out_fp = app_key;
194 size_t wrote = fwrite(buffer, 1, size, out_fp);
195 return (wrote == size) ? 0 : -1;
196}
197
198int main(int ac, char **av) {
199 Rectangle_t *rectangle; /* Type to encode */
200 asn_enc_rval_t ec; /* Encoder return value */
Lev Walkined44bf42010-11-08 02:04:55 -0800201
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700202 /* Allocate the Rectangle_t */
203 rectangle = calloc(1, sizeof(Rectangle_t)); /* not malloc! */
204 if(!rectangle) {
205 perror("calloc() failed");
206 exit(1);
207 }
Lev Walkined44bf42010-11-08 02:04:55 -0800208
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700209 /* Initialize the Rectangle members */
210 rectangle->height = 42; /* any random value */
211 rectangle->width = 23; /* any random value */
Lev Walkined44bf42010-11-08 02:04:55 -0800212
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700213 /* BER encode the data if filename is given */
214 if(ac < 2) {
215 fprintf(stderr, "Specify filename for BER output\n");
216 } else {
217 const char *filename = av[1];
218 FILE *fp = fopen(filename, "wb"); /* for BER output */
219
220 if(!fp) {
221 perror(filename);
222 exit(1);
223 }
Lev Walkined44bf42010-11-08 02:04:55 -0800224
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700225 /* Encode the Rectangle type as BER (DER) */
226 ec = der_encode(&asn_DEF_Rectangle, rectangle, write_out, fp);
227 fclose(fp);
228 if(ec.encoded == -1) {
229 fprintf(stderr, "Could not encode Rectangle (at %\%%s)\n",
230 ec.failed_type ? ec.failed_type->name : "unknown");
231 exit(1);
232 } else {
233 fprintf(stderr, "Created %\%%s with BER encoded Rectangle\n", filename);
234 }
235 }
Lev Walkined44bf42010-11-08 02:04:55 -0800236
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700237 /* Also print the constructed Rectangle XER encoded (XML) */
238 xer_fprint(stdout, &asn_DEF_Rectangle, rectangle);
Lev Walkined44bf42010-11-08 02:04:55 -0800239
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700240 return 0; /* Encoding finished successfully */
241 }
242\end{codesample}
Lev Walkined44bf42010-11-08 02:04:55 -0800243\item Compile all files together using C compiler (varies by platform):
244
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700245\begin{bash}
246cc -I. -o %\textbf{\emph{rencode}} \emph{*.c}%
247\end{bash}
Lev Walkinf3334582017-11-07 00:02:24 -0800248\item Done. You have just created the BER and XER encoder of a Rectangle
Lev Walkined44bf42010-11-08 02:04:55 -0800249type, named \textbf{rencode}!
250\end{enumerate}
Lev Walkined44bf42010-11-08 02:04:55 -0800251
Lev Walkinf3334582017-11-07 00:02:24 -0800252\section{\label{sec:A-Rectangle-Decoder}A “Rectangle” Decoder}
Lev Walkined44bf42010-11-08 02:04:55 -0800253
254This example will help you to create a simple BER decoder of a simple
Lev Walkin464166c2010-11-09 08:34:38 -0800255``Rectangle'' type used throughout this document.
Lev Walkined44bf42010-11-08 02:04:55 -0800256\begin{enumerate}
Lev Walkinf3334582017-11-07 00:02:24 -0800257\item Create a file named \textbf{rectangle.asn} with the following contents:
Lev Walkined44bf42010-11-08 02:04:55 -0800258
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700259\begin{asn}
Lev Walkinf3334582017-11-07 00:02:24 -0800260RectangleModule DEFINITIONS ::= BEGIN
Lev Walkined44bf42010-11-08 02:04:55 -0800261
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700262Rectangle ::= SEQUENCE {
263 height INTEGER,
264 width INTEGER
265}
Lev Walkined44bf42010-11-08 02:04:55 -0800266
267END
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700268\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -0800269\item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}:
270
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700271\begin{bash}
Lev Walkinf3334582017-11-07 00:02:24 -0800272asn1c %\textbf{rectangle.asn}%
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700273\end{bash}
Lev Walkined44bf42010-11-08 02:04:55 -0800274\item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading
Lev Walkinf3334582017-11-07 00:02:24 -0800275the \textbf{rectangle.asn} file into the Web form and unpacking the
Lev Walkined44bf42010-11-08 02:04:55 -0800276produced archive on your computer.
277\item By this time, you should have gotten multiple files in the current
278directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}.
279\item Create a main() routine which takes the binary input file, decodes
280it as it were a BER-encoded Rectangle type, and prints out the text
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700281(XML) representation of the Rectangle type. Let's name the file \textbf{main.c}:
Lev Walkined44bf42010-11-08 02:04:55 -0800282
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700283\begin{codesample}[basicstyle=\scriptsize\listingfont]
284#include <stdio.h>
285#include <sys/types.h>
286#include <Rectangle.h> /* Rectangle ASN.1 type */
Lev Walkined44bf42010-11-08 02:04:55 -0800287
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700288int main(int ac, char **av) {
289 char buf[1024]; /* Temporary buffer */
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700290 asn_dec_rval_t rval; /* Decoder return value */
Lev Walkin194b2102013-03-28 01:29:06 -0700291 Rectangle_t *%$\underbracket{\textrm{\listingfont rectangle = 0}}$%; /* Type to decode. %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700292 FILE *fp; /* Input file handler */
293 size_t size; /* Number of bytes read */
294 char *filename; /* Input file name */
Lev Walkined44bf42010-11-08 02:04:55 -0800295
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700296 /* Require a single filename argument */
297 if(ac != 2) {
298 fprintf(stderr, "Usage: %\%%s <file.ber>\n", av[0]);
299 exit(1);
300 } else {
301 filename = av[1];
302 }
Lev Walkined44bf42010-11-08 02:04:55 -0800303
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700304 /* Open input file as read-only binary */
305 fp = fopen(filename, "rb");
306 if(!fp) {
307 perror(filename);
308 exit(1);
309 }
Lev Walkined44bf42010-11-08 02:04:55 -0800310
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700311 /* Read up to the buffer size */
312 size = fread(buf, 1, sizeof(buf), fp);
313 fclose(fp);
314 if(!size) {
315 fprintf(stderr, "%\%%s: Empty or broken\n", filename);
316 exit(1);
317 }
Lev Walkined44bf42010-11-08 02:04:55 -0800318
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700319 /* Decode the input buffer as Rectangle type */
320 rval = ber_decode(0, &asn_DEF_Rectangle, (void **)&rectangle, buf, size);
321 if(rval.code != RC_OK) {
322 fprintf(stderr, "%\%%s: Broken Rectangle encoding at byte %\%%ld\n", filename, (long)rval.consumed);
323 exit(1);
324 }
Lev Walkined44bf42010-11-08 02:04:55 -0800325
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700326 /* Print the decoded Rectangle type as XML */
327 xer_fprint(stdout, &asn_DEF_Rectangle, rectangle);
Lev Walkined44bf42010-11-08 02:04:55 -0800328
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700329 return 0; /* Decoding finished successfully */
Lev Walkin194b2102013-03-28 01:29:06 -0700330}
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700331\end{codesample}
Lev Walkined44bf42010-11-08 02:04:55 -0800332\item Compile all files together using C compiler (varies by platform):
333
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700334\begin{bash}
335cc -I. -o %\textbf{\emph{rdecode}} \emph{*.c}%
336\end{bash}
Lev Walkinf3334582017-11-07 00:02:24 -0800337\item Done. You have just created the BER decoder of a Rectangle type,
Lev Walkined44bf42010-11-08 02:04:55 -0800338named \textbf{rdecode}!
339\end{enumerate}
340
Lev Walkind5627a12017-11-07 01:04:40 -0800341\section{Adding constraints to a “Rectangle”}
Lev Walkined44bf42010-11-08 02:04:55 -0800342
343This example shows how to add basic constraints to the ASN.1 specification
344and how to invoke the constraints validation code in your application.
345\begin{enumerate}
Lev Walkind5627a12017-11-07 01:04:40 -0800346
Lev Walkinf3334582017-11-07 00:02:24 -0800347\item Create a file named \textbf{rectangle.asn} with the following contents:
Lev Walkined44bf42010-11-08 02:04:55 -0800348
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700349\begin{asn}
350RectangleModuleWithConstraints DEFINITIONS ::= BEGIN
Lev Walkined44bf42010-11-08 02:04:55 -0800351
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700352Rectangle ::= SEQUENCE {
353 height INTEGER (0..100), -- Value range constraint
354 width INTEGER (0..MAX) -- Makes width non-negative
355}
Lev Walkined44bf42010-11-08 02:04:55 -0800356
357END
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700358\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -0800359
Lev Walkind5627a12017-11-07 01:04:40 -0800360\item Compile the file according to procedures shown in \fref{sec:A-Rectangle-Decoder}.
361\item Modify the Rectangle type processing routine (you can start with the
362main() routine shown in the \fref{sec:A-Rectangle-Decoder})
363by placing the following snippet of code \emph{before} encoding and/or
364\emph{after} decoding the Rectangle type:
365
366\begin{codesample}[basicstyle=\scriptsize\listingfont]
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700367int ret; /* Return value */
368char errbuf[128]; /* Buffer for error message */
369size_t errlen = sizeof(errbuf); /* Size of the buffer */
Lev Walkined44bf42010-11-08 02:04:55 -0800370
Lev Walkin2e554fc2014-10-26 19:21:58 -0700371/* ... here goes the Rectangle %\emph{decoding}% code ... */
Lev Walkined44bf42010-11-08 02:04:55 -0800372
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700373ret = asn_check_constraints(&asn_DEF_Rectangle, rectangle, errbuf, &errlen);
374/* assert(errlen < sizeof(errbuf)); // you may rely on that */
375if(ret) {
Lev Walkind5627a12017-11-07 01:04:40 -0800376 fprintf(stderr, "Constraint validation failed: %\%%s\n", errbuf);
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700377 /* exit(...); // Replace with appropriate action */
378 }
Lev Walkined44bf42010-11-08 02:04:55 -0800379
Lev Walkin2e554fc2014-10-26 19:21:58 -0700380/* ... here goes the Rectangle %\emph{encoding}% code ... */
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700381\end{codesample}
Lev Walkined44bf42010-11-08 02:04:55 -0800382\item Compile the resulting C code as shown in the previous chapters.
Lev Walkind5627a12017-11-07 01:04:40 -0800383\item Test the constraints checking code by assigning integer value
Lev Walkined44bf42010-11-08 02:04:55 -0800384101 to the \textbf{.height} member of the Rectangle structure, or
Lev Walkind5627a12017-11-07 01:04:40 -0800385a negative value to the \textbf{.width} member.
386The program will fail with ``Constraint validation failed'' message.
Lev Walkined44bf42010-11-08 02:04:55 -0800387\item Done.
388\end{enumerate}
389
Lev Walkind5627a12017-11-07 01:04:40 -0800390\chapter{ASN.1 Compiler}
391
392\section{The asn1c compiler tool}
393
394The purpose of the ASN.1 compiler is to convert the specifications
395in ASN.1 notation into some other language, such as C.
396
397The compiler reads the specification and emits a series of target
398language structures (C structs, unions, enums) describing the corresponding
399ASN.1 types. The compiler also creates the code which allows automatic
400serialization and deserialization of these structures using several
401standardized encoding rules (BER, DER, OER, PER, XER).
402
403Let's take the following ASN.1 example%
404\footnote{\Fref{chap:Abstract-Syntax-Notation} provides a quick reference
405on the ASN.1 notation.}:
406\begin{asn}
407RectangleModule DEFINITIONS ::= BEGIN
408
409Rectangle ::= SEQUENCE {
410 height INTEGER, -- Height of the rectangle
411 width INTEGER -- Width of the rectangle
412}
413
414END
415\end{asn}
416The asn1c compiler reads this ASN.1 definition and produce the following
417C type:
418\begin{codesample}
419typedef struct Rectangle_s {
420 long height;
421 long width;
422} Rectangle_t;
423\end{codesample}
424The asn1c compiler also creates the code for converting this structure into
425platform-independent wire representation and the decoder
426of such wire representation back into local, machine-specific type.
427These encoders and decoders are also called serializers and deserializers,
428marshallers and unmarshallers, or codecs.
429
430Compiling ASN.1 modules into C codecs can be as simple as invoking \cmd{asn1c}:
431may be used to compile the ASN.1 modules:
432\begin{bash}
433asn1c %\emph{<modules.asn>}%
434\end{bash}
435
436If several ASN.1 modules contain interdependencies, all of the files
437must be specified altogether:
438\begin{bash}
439asn1c %\emph{<module1.asn> <module2.asn> ...}%
440\end{bash}
441The compiler \textbf{-E} and \textbf{-EF} options are used for testing
442the parser and the semantic fixer, respectively. These options will
443instruct the compiler to dump out the parsed (and fixed, if \textbf{-F}
444is involved) ASN.1 specification as it was understood
445by the compiler. It might be useful to check whether a particular
446syntactic construct is properly supported by the compiler.
447\begin{bash}
448asn1c %\textbf{-EF} \emph{<module-to-test.asn>}%
449\end{bash}
450The \textbf{-P} option is used to dump the compiled output on the
451screen instead of creating a bunch of .c and .h files on disk in the
452current directory. You would probably want to start with \textbf{-P}
453option instead of creating a mess in your current directory. Another
454option, \textbf{-R}, asks compiler to only generate the files which
455need to be generated, and supress linking in the numerous support
456files.
457
458Print the compiled output instead of creating multiple source files:
459\begin{bash}
460asn1c %\textbf{-P} \emph{<module-to-compile-and-print.asn>}%
461\end{bash}
462
463\clearpage{}
464\section{Compiler output}
465
466The \cmd{asn1c} compiler produces a number of files:
467\begin{itemize}
468\item A set of .c and .h files for each type defined
469in the ASN.1 specification. These files will be named similarly to
470the ASN.1 types (\textbf{Rectangle.c} and \textbf{Rectangle.h} for the
471RectangleModule ASN.1 module defined in the beginning of this document).
472\item A set of helper .c and .h files which contain the generic encoders,
473decoders and other useful routines.
474Sometimes they are referred to by the term \emph{skeletons}.
475There will be quite a few of them, some
476of them are not even always necessary, but the overall amount of code
477after compilation will be rather small anyway.
478\item A \textbf{Makefile.am.libasncodecs} file which explicitly lists all the
479generated files.
480This makefile can be used on its own to build the just the codec library.
481\item A \textbf{converter-example.c} file containing the \emph{int main()} function with a fully functioning encoder and data format converter. It can convert a given PDU between BER, XER and possibly OER and PER (if \cmd{-gen-OER} or \cmd{-gen-PER} options to \cmd{asn1c} were in effect). At some point you will want to replace this file with your own file containing the \emph{int main()} function.
482\item A \textbf{Makefile.am.example} file which binds together
483\textbf{Makefile.am.libasncodecs} and \textbf{converter-example.c}
484to build a versatile converter and debugger for your data formats.
485\end{itemize}
486It is possible to compile everything with just a couple of instructions:
487\begin{bash}
488asn1c -pdu=%\emph{Rectangle}% *.asn
489make -f Makefile.am.example # If you use `make`
490\end{bash}
491or
492\begin{bash}
493asn1c *.asn
494cc -I. -DPDU=%\emph{Rectangle}% -o rectangle.exe *.c # ... or like this
495\end{bash}
496Refer to the \fref{chap:Quick-start-examples} for a sample
497\emph{int main()} function if you want some custom logic and not satisfied
498with the supplied \emph{converter-example.c}.
499
500\clearpage{}
501\section{\label{sec:Command-line-options}Command line options}
502
503The following table summarizes the \cmd{asn1c} command line options.
504
505\renewcommand{\arraystretch}{1.33}
506\begin{longtable}{lp{4in}}
507\textbf{Stage Selection Options} & \textbf{Description}\\
508\midrule
509{\ttfamily -E} & {\small Stop after the parsing stage and print the reconstructed ASN.1
510specification code to the standard output.}\\
511{\ttfamily -F} & {\small Used together with \texttt{-E}, instructs the compiler to stop after
512the ASN.1 syntax tree fixing stage and dump the reconstructed ASN.1
513specification to the standard output.}\\
514{\ttfamily -P} & {\small Dump the compiled output to the standard output instead of
515creating the target language files on disk.}\\
516{\ttfamily -R} & {\small Restrict the compiler to generate only the ASN.1 tables, omitting the usual support code.}\\
517{\ttfamily -S~\emph{<directory>}} & {\small Use the specified directory with ASN.1 skeleton files.}\\
518{\ttfamily -X} & {\small Generate the XML DTD for the specified ASN.1 modules.}\\\\
519\textbf{Warning Options} & \textbf{Description}\\
520\midrule
521{\ttfamily -Werror} & {\small Treat warnings as errors; abort if any warning is produced.}\\
522{\ttfamily -Wdebug-parser} & {\small Enable the parser debugging during the ASN.1 parsing stage.}\\
523{\ttfamily -Wdebug-lexer} & {\small Enable the lexer debugging during the ASN.1 parsing stage.}\\
524{\ttfamily -Wdebug-fixer} & {\small Enable the ASN.1 syntax tree fixer debugging during the fixing stage.}\\
525{\ttfamily -Wdebug-compiler} & {\small Enable debugging during the actual compile time.}\\ \\
526\textbf{Language Options} & \textbf{Description}\\
527\midrule
528{\ttfamily -fbless-SIZE} & {\small Allow SIZE() constraint for INTEGER, ENUMERATED, and other types for which this constraint is normally prohibited by the standard.
529This is a violation of an ASN.1 standard and compiler may fail to produce the meaningful code.}\\
530{\ttfamily -fcompound-names} & {\small Use complex names for C structures. Using complex names prevents
531name clashes in case the module reuses the same identifiers in multiple
532contexts.}\\
533{\ttfamily -findirect-choice} & {\small When generating code for a CHOICE type, compile the CHOICE
534members as indirect pointers instead of declaring them inline. Consider
535using this option together with \texttt{-fno-include-deps}
536to prevent circular references.}\\
537{\ttfamily -fincludes-quoted} & {\small Generate \#include lines in "double" instead of <angle> quotes.}\\
538{\ttfamily -fknown-extern-type=\emph{<name>}} & {\small Pretend the specified type is known. The compiler will assume
539the target language source files for the given type have been provided
540manually. }\\
541{\ttfamily -fline-refs} & {\small Include ASN.1 module's line numbers in generated code comments.}\\
542{\ttfamily -fno-constraints} & {\small Do not generate ASN.1 subtype constraint checking code. This
543may produce a shorter executable.}\\
544{\ttfamily -fno-include-deps} & {\small Do not generate courtesy \#include lines for non-critical dependencies.}\\
545{\ttfamily -funnamed-unions} & {\small Enable unnamed unions in the definitions of target language's structures.}\\
546{\ttfamily -fwide-types} & {\small Use the wide integer types (INTEGER\_t, REAL\_t) instead of machine's native data types (long, double). }\\\\
547\textbf{Codecs Generation Options} & \textbf{Description}\\
548\midrule
549{\ttfamily -gen-OER} & {\small Generate the Octet Encoding Rules (OER) support code.}\\
550{\ttfamily -gen-PER} & {\small Generate the Packed Encoding Rules (PER) support code.}\\
551{\ttfamily -pdu=\{\textbf{all}|\textbf{auto}|\emph{Type}\}} & {\small Create a PDU table for specified types, or discover the Protocol Data Units automatically.
552In case of \texttt{-pdu=\textbf{all}}, all ASN.1 types defined in all modules wil form a PDU table. In case of \texttt{-pdu=\textbf{auto}}, all types not referenced by any other type will form a PDU table. If \texttt{\emph{Type}} is an ASN.1 type identifier, it is added to a PDU table. The last form may be specified multiple times.}\\ \\
553\textbf{Output Options} & \textbf{Description}\\
554\midrule
555{\ttfamily -print-class-matrix} & {\small When \texttt{-EF} options are given, this option instructs the compiler to print out the collected Information Object Class matrix.}\\
556{\ttfamily -print-constraints} & {\small With \texttt{-EF}, this option instructs the compiler
557to explain its internal understanding of subtype constraints.}\\
558{\ttfamily -print-lines} & {\small Generate \texttt{``-{}- \#line''} comments
559in \texttt{-E} output.}\\
560\end{longtable}
561\renewcommand{\arraystretch}{1}
Lev Walkined44bf42010-11-08 02:04:55 -0800562
563
Lev Walkind5627a12017-11-07 01:04:40 -0800564\chapter{API reference}
565
566\section{ASN\_STRUCT\_FREE}
567\section{ASN\_STRUCT\_FREE\_CONTENTS\_ONLY}
568\section{ASN\_STRUCT\_RESET}
569\section{asn\_check\_constraints}
570\section{asn\_decode}
571\section{asn\_encode}
572\section{asn\_encode\_to\_buffer}
573\section{asn\_encode\_to\_new\_buffer}
574\section{asn\_fprint}
575\section{ber\_decode}
576\section{der\_encode}
577\section{der\_encode\_to\_buffer}
578\section{oer\_decode}
579\section{oer\_encode}
580\section{oer\_encode\_to\_buffer}
581\section{uper\_decode}
582\section{uper\_decode\_complete}
583\section{uper\_encode}
584\section{uper\_encode\_to\_buffer}
585\section{uper\_encode\_to\_new\_buffer}
586\section{xer\_decode}
587\section{xer\_encode}
588\section{xer\_equivalent}
589\section{xer\_fprint}
590
591\chapter{API usage examples}
592
593Let's start with including the necessary header files into your
594application. Normally it is enough to include the header file of
595the main PDU type. For our \emph{Rectangle} module, including the \emph{Rectangle.h} file is sufficient:
596\begin{codesample}
597#include <Rectangle.h>
598\end{codesample}
599The header files defines a C structure corresponding to the ASN.1
600definition of a rectangle and the declaration of the ASN.1
601\emph{type descriptor}. A type descriptor is a special globally accessible
602object which is used as an argument to most of the API functions provided by
603the ASN.1 codec. A type descriptor starts with \emph{asn\_DEF\_\ldots{}}. For example, here is the code which frees the Rectangle\_t structure:
604\begin{codesample}
605Rectangle_t *rect = ...;
606
607ASN_STRUCT_FREE(%\textbf{asn\_DEF\_}%Rectangle, rect);
608\end{codesample}
609This code defines a \emph{rect} pointer which points to the Rectangle\_t
610structure which needs to be freed. The second line uses a generic
611\code{ASN\_STRUCT\_FREE()} macro which invokes the memory deallocation routine
612created specifically for this Rectangle\_t structure.
613The \emph{asn\_DEF\_Rectangle} is the type descriptor which holds
614a collection of routines and operations defined for the Rectangle\_t structure.
615
616\section{\label{sec:Generic-Encoding}Generic encoders and decoders}
617
618Before we start describing specific encoders and decoders, let's step back
619a little and check out a simple high level way.
620
621The asn1c runtime supplies (see \emph{asn\_application.h}) two sets of high level functions, \emph{asn\_encode*} and \emph{asn\_decode*}, which take a transfer syntax selector as the argument. The transfer syntax selector is defined as this:
622
623\begin{codesample}[basicstyle=\scriptsize\listingfont]
624/*
625 * A selection of ASN.1 Transfer Syntaxes to use with generalized encoders and decoders.
626 */
627enum asn_transfer_syntax {
628 ATS_INVALID,
629 ATS_NONSTANDARD_PLAINTEXT,
630 ATS_BER,
631 ATS_DER,
632 ATS_CER,
633 ATS_BASIC_OER,
634 ATS_CANONICAL_OER,
635 ATS_UNALIGNED_BASIC_PER,
636 ATS_UNALIGNED_CANONICAL_PER,
637 ATS_BASIC_XER,
638 ATS_CANONICAL_XER,
639};
640\end{codesample}
641
642Using this encoding selector, encoding and decoding becomes very generic:
643
644\noindent{}Encoding:
645
646\begin{codesample}[basicstyle=\scriptsize\listingfont]
647uint8_t buffer[128];
648size_t buf_size = sizeof(buffer);
649asn_enc_rval_t er;
650
651er = %\textbf{asn\_encode\emph{\_to\_buffer}}%(0, %\textbf{ATS\_DER}%, &asn_DEF_Rectangle, buffer, buf_size);
652
653if(er.encoded > buf_size) {
654 fprintf(stderr, "Buffer of size %\%%zu is too small for %\%%s, need %\%%zu\n",
655 buf_size, asn_DEF_Rectangle.name, er.encoded);
656}
657\end{codesample}
658
659\noindent{}Decoding:
660
661\begin{codesample}[basicstyle=\scriptsize\listingfont]
662Rectangle_t *%$\underbracket{\textrm{\listingfont rect = 0}}$%; /* %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */
663
664... = %\textbf{asn\_decode}%(0, %\textbf{ATS\_BER}%, &asn_DEF_Rectangle, (void **)%$\underbracket{\textrm{\listingfont \&rect}}$%, buffer, buf_size);
665\end{codesample}
666
667\section{\label{sec:Decoding-BER}Decoding BER}
668
669The Basic Encoding Rules describe the most widely used (by the ASN.1
670community) way to encode and decode a given structure in a machine-independent
671way. Several other encoding rules (CER, DER) define a more restrictive
672versions of BER, so the generic BER parser is also capable of decoding
673the data encoded by the CER and DER encoders. The opposite is not true.
674
675\emph{The ASN.1 compiler provides the generic BER decoder which is
676capable of decoding BER, CER and DER encoded data.}
677
678The decoder is restartable (stream-oriented), which means that in
679case the buffer has less data than it is expected, the decoder will
680process whatever there is available and ask for more data to be provided.
681Please note that the decoder may actually process less data than it
682was given in the buffer, which means that you must be able to make
683the next buffer contain the unprocessed part of the previous buffer.
684
685Suppose, you have two buffers of encoded data: 100 bytes and 200 bytes.
686\begin{itemize}
687\item You can concatenate these buffers and feed the BER decoder with 300
688bytes of data, or
689\item You can feed it the first buffer of 100 bytes of data, realize that
690the ber\_decoder consumed only 95 bytes from it and later feed the
691decoder with 205 bytes buffer which consists of 5 unprocessed bytes
692from the first buffer and the additional 200 bytes from the second
693buffer.
694\end{itemize}
695This is not as convenient as it could be (the BER encoder could
696consume the whole 100 bytes and keep these 5 bytes in some temporary
697storage), but in case of existing stream based processing it might
698actually fit well into existing algorithm. Suggestions are welcome.
699
700Here is the example of BER decoding of a simple structure:
701
702\begin{codesample}
703Rectangle_t *
704simple_deserializer(const void *buffer, size_t buf_size) {
705 asn_dec_rval_t rval;
706 Rectangle_t *%$\underbracket{\textrm{\listingfont rect = 0}}$%; /* %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */
707
708 rval = %\textbf{asn\_DEF\_Rectangle.op->ber\_decoder}%(0,
709 &asn_DEF_Rectangle,
710 (void **)%$\underbracket{\textrm{\listingfont \&rect}}$%, /* Decoder %\emph{changes}% the pointer */
711 buffer, buf_size, 0);
712
713 if(rval%\textbf{.code}% == RC_OK) {
714 return rect; /* Decoding succeeded */
715 } else {
716 /* Free the partially decoded rectangle */
717 ASN_STRUCT_FREE(asn_DEF_Rectangle, rect);
718 return 0;
719 }
720}
721\end{codesample}
722
723The code above defines a function, \emph{simple\_deserializer}, which
724takes a buffer and its length and is expected to return a pointer
725to the Rectangle\_t structure. Inside, it tries to convert the bytes
726passed into the target structure (rect) using the BER decoder and
727returns the rect pointer afterwards. If the structure cannot be deserialized,
728it frees the memory which might be left allocated by the unfinished
729\emph{ber\_decoder} routine and returns 0 (no data). (This \textbf{freeing
730is necessary} because the ber\_decoder is a restartable procedure,
731and may fail just because there is more data needs to be provided
732before decoding could be finalized). The code above obviously does
733not take into account the way the \emph{ber\_decoder()} failed, so
734the freeing is necessary because the part of the buffer may already
735be decoded into the structure by the time something goes wrong.
736
737A little less wordy would be to invoke a globally available \emph{ber\_decode()}
738function instead of dereferencing the asn\_DEF\_Rectangle type descriptor:
739\begin{codesample}
740rval = ber_decode(0, &asn_DEF_Rectangle, (void **)&rect, buffer, buf_size);
741\end{codesample}
742Note that the initial (asn\_DEF\_Rectangle.op->ber\_decoder) reference
743is gone, and also the last argument (0) is no longer necessary.
744
745These two ways of BER decoder invocations are fully equivalent.
746
747The BER de\emph{coder} may fail because of (\emph{the following RC\_\ldots{}
748codes are defined in ber\_decoder.h}):
749\begin{itemize}
750\item RC\_WMORE: There is more data expected than it is provided (stream
751mode continuation feature);
752\item RC\_FAIL: General failure to decode the buffer;
753\item \ldots{} other codes may be defined as well.
754\end{itemize}
755Together with the return code (.code) the asn\_dec\_rval\_t type contains
756the number of bytes which is consumed from the buffer. In the previous
757hypothetical example of two buffers (of 100 and 200 bytes), the first
758call to ber\_decode() would return with .code = RC\_WMORE and .consumed
759= 95. The .consumed field of the BER decoder return value is \textbf{always}
760valid, even if the decoder succeeds or fails with any other return
761code.
762
763Look into ber\_decoder.h for the precise definition of ber\_decode()
764and related types.
765
766
767\section{\label{sec:Encoding-DER}Encoding DER}
768
769The Distinguished Encoding Rules is the \emph{canonical} variant of
770BER encoding rules. The DER is best suited to encode the structures
771where all the lengths are known beforehand. This is probably exactly
772how you want to encode: either after a BER decoding or after a manual
773fill-up, the target structure contains the data which size is implicitly
774known before encoding. Among other uses, the DER encoding is used
775to encode X.509 certificates.
776
777As with BER decoder, the DER encoder may be invoked either directly
778from the ASN.1 type descriptor (asn\_DEF\_Rectangle) or from the stand-alone
779function, which is somewhat simpler:
780\begin{codesample}
781/*
782 * This is the serializer itself.
783 * It supplies the DER encoder with the
784 * pointer to the custom output function.
785 */
786ssize_t
787simple_serializer(FILE *ostream, Rectangle_t *rect) {
788 asn_enc_rval_t er; /* Encoder return value */
789
790 er = der_encode(&asn_DEF_Rect, rect, write_stream, ostream);
791 if(er%\textbf{.encoded}% == -1) {
792 fprintf(stderr, "Cannot encode %\%%s: %\%%s\n",
793 er%\textbf{.failed\_type}%->name, strerror(errno));
794 return -1;
795 } else {
796 /* Return the number of bytes */
797 return er.encoded;
798 }
799}
800\end{codesample}
801As you see, the DER encoder does not write into some sort of buffer.
802It just invokes the custom function (possible, multiple
803times) which would save the data into appropriate storage. The optional
804argument \emph{app\_key} is opaque for the DER encoder code and just
805used by \emph{\_write\_stream()} as the pointer to the appropriate
806output stream to be used.
807
808If the custom write function is not given (passed as 0), then the
809DER encoder will essentially do the same thing (i.~e., encode the data)
810but no callbacks will be invoked (so the data goes nowhere). It may
811prove useful to determine the size of the structure's encoding before
812actually doing the encoding%
813\footnote{It is actually faster too: the encoder might skip over some computations
814which aren't important for the size determination.%
815}.
816
817Look into der\_encoder.h for the precise definition of der\_encode()
818and related types.
819
820
821\section{\label{sec:Encoding-XER}Encoding XER}
822
823The XER stands for XML Encoding Rules, where XML, in turn, is eXtensible
824Markup Language, a text-based format for information exchange. The
825encoder routine API comes in two flavors: stdio-based and callback-based.
826With the callback-based encoder, the encoding process is very similar
827to the DER one, described in \fref{sec:Encoding-DER}. The
828following example uses the definition of write\_stream() from up there.
829\begin{codesample}
830/*
831 * This procedure generates an XML document
832 * by invoking the XER encoder.
833 * NOTE: Do not copy this code verbatim!
834 * If the stdio output is necessary,
835 * use the xer_fprint() procedure instead.
836 * See %\fref{sec:Printing-the-target}%.
837 */
838int
839print_as_XML(FILE *ostream, Rectangle_t *rect) {
840 asn_enc_rval_t er; /* Encoder return value */
841
842 er = xer_encode(&asn_DEF_Rectangle, rect,
843 XER_F_BASIC, /* BASIC-XER or CANONICAL-XER */
844 write_stream, ostream);
845
846 return (er.encoded == -1) ? -1 : 0;
847}
848\end{codesample}
849Look into xer\_encoder.h for the precise definition of xer\_encode()
850and related types.
851
852See \fref{sec:Printing-the-target} for the example of stdio-based
853XML encoder and other pretty-printing suggestions.
854
855
856\section{\label{sec:Decoding-XER}Decoding XER}
857
858The data encoded using the XER rules can be subsequently decoded using
859the xer\_decode() API call:
860\begin{codesample}
861Rectangle_t *
862XML_to_Rectangle(const void *buffer, size_t buf_size) {
863 asn_dec_rval_t rval;
864 Rectangle_t *%$\underbracket{\textrm{\listingfont rect = 0}}$%; /* %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */
865
866 rval = xer_decode(0, &asn_DEF_Rectangle, (void **)&rect, buffer, buf_size);
867
868 if(rval%\textbf{.code}% == RC_OK) {
869 return rect; /* Decoding succeeded */
870 } else {
871 /* Free partially decoded rect */
872 ASN_STRUCT_FREE(asn_DEF_Rectangle, rect);
873 return 0;
874 }
875}
876\end{codesample}
877The decoder takes both BASIC-XER and CANONICAL-XER encodings.
878
879The decoder shares its data consumption properties with BER decoder;
880please read the \fref{sec:Decoding-BER} to know more.
881
882Look into xer\_decoder.h for the precise definition of xer\_decode()
883and related types.
884
885
886\section{\label{sec:Validating-the-target}Validating the target structure}
887
888Sometimes the target structure needs to be validated. For example,
889if the structure was created by the application (as opposed to being
890decoded from some external source), some important information required
891by the ASN.1 specification might be missing. On the other hand, the
892successful decoding of the data from some external source does not
893necessarily mean that the data is fully valid either. It might well
894be the case that the specification describes some subtype constraints
895that were not taken into account during decoding, and it would actually
896be useful to perform the last check when the data is ready to be encoded
897or when the data has just been decoded to ensure its validity according
898to some stricter rules.
899
900The asn\_check\_constraints() function checks the type for various
901implicit and explicit constraints. It is recommended to use asn\_check\_constraints()
902function after each decoding and before each encoding.
903
904Look into constraints.h for the precise definition of asn\_check\_constraints()
905and related types.
906
907
908\section{\label{sec:Printing-the-target}Printing the target structure}
909
910There are two ways to print the target structure: either invoke the
911print\_struct member of the ASN.1 type descriptor, or using the asn\_fprint()
912function, which is a simpler wrapper of the former:
913\begin{codesample}
914asn_fprint(stdout, &asn_DEF_Rectangle, rect);
915\end{codesample}
916Look into constr\_TYPE.h for the precise definition of asn\_fprint()
917and related types.
918
919Another practical alternative to this custom format printing would
920be to invoke XER encoder. The default BASIC-XER encoder performs reasonable
921formatting for the output to be useful and human readable. To invoke
922the XER decoder in a manner similar to asn\_fprint(), use the xer\_fprint()
923call:
924\begin{codesample}
925xer_fprint(stdout, &asn_DEF_Rectangle, rect);
926\end{codesample}
927See \fref{sec:Encoding-XER} for XML-related details.
928
929
930\section{\label{sec:Freeing-the-target}Freeing the target structure}
931
932Freeing the structure is slightly more complex than it may seem to.
933When the ASN.1 structure is freed, all the members of the structure
934and their submembers are recursively freed as well.
935The ASN\_STRUCT\_FREE() macro helps with that.
936
937But it might not always be feasible to free the whole structure.
938In the following example, the application programmer defines a custom
939structure with one ASN.1-derived member (rect).
940\begin{codesample}
941struct my_figure { /* The custom structure */
942 int flags; /* <some custom member> */
943 /* The type is generated by the ASN.1 compiler */
944 Rectangle_t rect;
945 /* other members of the structure */
946};
947\end{codesample}
948This member is not a reference to the Rectangle\_t, but an in-place inclusion
949of the Rectangle\_t structure.
950If there's a need to free the \code{rect} member, the usual procedure of
951freeing everything must not be applied to the \code{\&rect} pointer itself,
952because it does not point to the beginning of memory block allocated by
953the memory allocation routine, but instead lies within a block allocated for
954the my\_figure structure.
955
956To solve this problem, in addition to ASN\_STRUCT\_FREE() macro, the asn1c
957skeletons define the ASN\_STRUCT\_RESET() macro which doesn't free the passed
958pointer and instead resets the structure into the clean and safe state.
959\begin{codesample}
960/* %\textbf{1. Rectangle\_t is defined within my\_figure}% */
961struct my_figure {
962 Rectangle_t rect;
963} *mf = ...;
964/*
965 * Freeing the Rectangle_t
966 * without freeing the mf->rect area.
967 */
968ASN_STRUCT_RESET(asn_DEF_Rectangle, &mf->rect);
969
970/* %\textbf{2. Rectangle\_t is a stand-alone pointer}% */
971Rectangle_t *rect = ...;
972/*
973 * Freeing the Rectangle_t
974 * and freeing the rect pointer.
975 */
976ASN_STRUCT_FREE(asn_DEF_Rectangle, rect);
977\end{codesample}
978It is safe to invoke both macros with the target structure pointer
979set to 0 (NULL). In this case, the function will do nothing.
980
981\chapter{\label{chap:Abstract-Syntax-Notation}Abstract Syntax Notation: ASN.1}
Lev Walkined44bf42010-11-08 02:04:55 -0800982
983\emph{This chapter defines some basic ASN.1 concepts and describes
984several most widely used types. It is by no means an authoritative
985or complete reference. For more complete ASN.1 description, please
986refer to Olivier Dubuisson's book \cite{Dub00} or the ASN.1 body
987of standards itself \cite{ITU-T/ASN.1}.}
988
989The Abstract Syntax Notation One is used to formally describe the
Lev Walkin507f6002014-10-26 20:22:16 -0700990data transmitted across the network. Two communicating parties may employ
991different formats of their native data types (e.~g., different number
992of bits for the native integer type), thus it is important to have
Lev Walkined44bf42010-11-08 02:04:55 -0800993a way to describe the data in a manner which is independent from the
Lev Walkin507f6002014-10-26 20:22:16 -0700994particular machine's representation.
995The ASN.1 specifications are used to achieve the following:
Lev Walkined44bf42010-11-08 02:04:55 -0800996\begin{itemize}
997\item The specification expressed in the ASN.1 notation is a formal and
Lev Walkin507f6002014-10-26 20:22:16 -0700998precise way to communicate the structure of data to human readers;
Lev Walkined44bf42010-11-08 02:04:55 -0800999\item The ASN.1 specifications may be used as input for automatic compilers
1000which produce the code for some target language (C, C++, Java, etc)
Lev Walkin507f6002014-10-26 20:22:16 -07001001to encode and decode the data according to some encoding formats.
1002Several such encoding formats (called Transfer Encoding Rules)
1003have been defined by the ASN.1 standard.
Lev Walkined44bf42010-11-08 02:04:55 -08001004\end{itemize}
1005Consider the following example:
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001006\begin{asn}
1007Rectangle ::= SEQUENCE {
1008 height INTEGER,
1009 width INTEGER
1010}
1011\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -08001012This ASN.1 specification describes a constructed type, \emph{Rectangle},
1013containing two integer fields. This specification may tell the reader
1014that there exists this kind of data structure and that some entity
1015may be prepared to send or receive it. The question on \emph{how}
1016that entity is going to send or receive the \emph{encoded data} is
1017outside the scope of ASN.1. For example, this data structure may be
1018encoded according to some encoding rules and sent to the destination
1019using the TCP protocol. The ASN.1 specifies several ways of encoding
Lev Walkin464166c2010-11-09 08:34:38 -08001020(or ``serializing'', or ``marshaling'') the data: BER, PER, XER
Lev Walkined44bf42010-11-08 02:04:55 -08001021and others, including CER and DER derivatives from BER.
1022
1023The complete specification must be wrapped in a module, which looks
1024like this:
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001025\begin{asn}
Lev Walkined44bf42010-11-08 02:04:55 -08001026RectangleModule1
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001027 { iso org(3) dod(6) internet(1) private(4)
1028 enterprise(1) spelio(9363) software(1)
1029 asn1c(5) docs(2) rectangle(1) 1 }
1030 DEFINITIONS AUTOMATIC TAGS ::=
Lev Walkined44bf42010-11-08 02:04:55 -08001031BEGIN
1032
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001033-- This is a comment which describes nothing.
1034Rectangle ::= SEQUENCE {
1035 height INTEGER, -- Height of the rectangle
1036 width INTEGER -- Width of the rectangle
1037}
Lev Walkined44bf42010-11-08 02:04:55 -08001038
1039END
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001040\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -08001041The module header consists of module name (RectangleModule1), the
Lev Walkin464166c2010-11-09 08:34:38 -08001042module object identifier (\{...\}), a keyword ``DEFINITIONS'', a
1043set of module flags (AUTOMATIC TAGS) and ``::= BEGIN''. The module
1044ends with an ``END'' statement.
Lev Walkined44bf42010-11-08 02:04:55 -08001045
1046
1047\section{Some of the ASN.1 Basic Types}
1048
1049
1050\subsection{The BOOLEAN type}
1051
1052The BOOLEAN type models the simple binary TRUE/FALSE, YES/NO, ON/OFF
1053or a similar kind of two-way choice.
1054
1055
1056\subsection{The INTEGER type}
1057
1058The INTEGER type is a signed natural number type without any restrictions
1059on its size. If the automatic checking on INTEGER value bounds are
1060necessary, the subtype constraints must be used.
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001061\begin{asn}
1062SimpleInteger ::= INTEGER
Lev Walkined44bf42010-11-08 02:04:55 -08001063
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001064-- An integer with a very limited range
1065SmallPositiveInt ::= INTEGER (0..127)
Lev Walkined44bf42010-11-08 02:04:55 -08001066
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001067-- Integer, negative
1068NegativeInt ::= INTEGER (MIN..0)
1069\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -08001070
1071\subsection{The ENUMERATED type}
1072
1073The ENUMERATED type is semantically equivalent to the INTEGER type
1074with some integer values explicitly named.
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001075\begin{asn}
1076FruitId ::= ENUMERATED { apple(1), orange(2) }
Lev Walkined44bf42010-11-08 02:04:55 -08001077
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001078-- The numbers in braces are optional,
1079-- the enumeration can be performed
1080-- automatically by the compiler
1081ComputerOSType ::= ENUMERATED {
1082 FreeBSD, -- acquires value 0
1083 Windows, -- acquires value 1
1084 Solaris(5), -- remains 5
1085 Linux, -- becomes 6
1086 MacOS -- becomes 7
1087}
1088\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -08001089
1090\subsection{The OCTET STRING type}
1091
1092This type models the sequence of 8-bit bytes. This may be used to
1093transmit some opaque data or data serialized by other types of encoders
Lev Walkin507f6002014-10-26 20:22:16 -07001094(e.~g., video file, photo picture, etc).
Lev Walkined44bf42010-11-08 02:04:55 -08001095
1096\subsection{The OBJECT IDENTIFIER type}
1097
1098The OBJECT IDENTIFIER is used to represent the unique identifier of
1099any object, starting from the very root of the registration tree.
1100If your organization needs to uniquely identify something (a router,
1101a room, a person, a standard, or whatever), you are encouraged to
1102get your own identification subtree at \url{http://www.iana.org/protocols/forms.htm}.
1103
1104For example, the very first ASN.1 module in this Chapter (RectangleModule1)
1105has the following OBJECT IDENTIFIER: 1 3 6 1 4 1 9363 1 5 2 1 1.
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001106\begin{asn}
1107ExampleOID ::= OBJECT IDENTIFIER
Lev Walkined44bf42010-11-08 02:04:55 -08001108
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001109rectangleModule1-oid ExampleOID
1110 ::= { 1 3 6 1 4 1 9363 1 5 2 1 1 }
Lev Walkined44bf42010-11-08 02:04:55 -08001111
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001112-- An identifier of the Internet.
1113internet-id OBJECT IDENTIFIER
1114 ::= { iso(1) identified-organization(3)
1115 dod(6) internet(1) }
1116\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -08001117As you see, names are optional.
1118
1119
1120\subsection{The RELATIVE-OID type}
1121
1122The RELATIVE-OID type has the semantics of a subtree of an OBJECT
1123IDENTIFIER. There may be no need to repeat the whole sequence of numbers
1124from the root of the registration tree where the only thing of interest
1125is some of the tree's subsequence.
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001126\begin{asn}
1127this-document RELATIVE-OID ::= { docs(2) usage(1) }
Lev Walkined44bf42010-11-08 02:04:55 -08001128
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001129this-example RELATIVE-OID ::= {
1130 this-document assorted-examples(0) this-example(1) }
1131\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -08001132
1133\section{Some of the ASN.1 String Types}
1134
1135
1136\subsection{The IA5String type}
1137
1138This is essentially the ASCII, with 128 character codes available
1139(7 lower bits of an 8-bit byte).
1140
1141
1142\subsection{The UTF8String type}
1143
1144This is the character string which encodes the full Unicode range
1145(4 bytes) using multibyte character sequences.
1146
1147
1148\subsection{The NumericString type}
1149
1150This type represents the character string with the alphabet consisting
Lev Walkin464166c2010-11-09 08:34:38 -08001151of numbers (``0'' to ``9'') and a space.
Lev Walkined44bf42010-11-08 02:04:55 -08001152
1153
1154\subsection{The PrintableString type}
1155
Lev Walkin464166c2010-11-09 08:34:38 -08001156The character string with the following alphabet: space, ``\textbf{'}''
1157(single quote), ``\textbf{(}'', ``\textbf{)}'', ``\textbf{+}'',
1158``\textbf{,}'' (comma), ``\textbf{-}'', ``\textbf{.}'', ``\textbf{/}'',
1159digits (``0'' to ``9''), ``\textbf{:}'', ``\textbf{=}'', ``\textbf{?}'',
1160upper-case and lower-case letters (``A'' to ``Z'' and ``a''
1161to ``z'').
Lev Walkined44bf42010-11-08 02:04:55 -08001162
1163
1164\subsection{The VisibleString type}
1165
1166The character string with the alphabet which is more or less a subset
Lev Walkin464166c2010-11-09 08:34:38 -08001167of ASCII between the space and the ``\textbf{\textasciitilde{}}''
Lev Walkined44bf42010-11-08 02:04:55 -08001168symbol (tilde).
1169
1170Alternatively, the alphabet may be described as the PrintableString
Lev Walkin464166c2010-11-09 08:34:38 -08001171alphabet presented earlier, plus the following characters: ``\textbf{!}'',
1172``\textbf{``}'', ``\textbf{\#}'', ``\textbf{\$}'', ``\textbf{\%}'',
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001173``\textbf{\&}'', ``\textbf{*}'', ``\textbf{;}'', ``\textbf{<}'',
Lev Walkin464166c2010-11-09 08:34:38 -08001174``\textbf{>}'', ``\textbf{{[}}'', ``\textbf{\textbackslash{}}'',
1175``\textbf{{]}}'', ``\textbf{\textasciicircum{}}'', ``\textbf{\_}'',
1176``\textbf{`}`` (single left quote), ``\textbf{\{}'', ``\textbf{|}'',
1177``\textbf{\}}'', ``\textbf{\textasciitilde{}}''.
Lev Walkined44bf42010-11-08 02:04:55 -08001178
1179
1180\section{ASN.1 Constructed Types}
1181
1182
1183\subsection{The SEQUENCE type}
1184
1185This is an ordered collection of other simple or constructed types.
Lev Walkin464166c2010-11-09 08:34:38 -08001186The SEQUENCE constructed type resembles the C ``struct'' statement.
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001187\begin{asn}
1188Address ::= SEQUENCE {
1189 -- The apartment number may be omitted
1190 apartmentNumber NumericString OPTIONAL,
1191 streetName PrintableString,
1192 cityName PrintableString,
1193 stateName PrintableString,
1194 -- This one may be omitted too
1195 zipNo NumericString OPTIONAL
1196}
1197\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -08001198
1199\subsection{The SET type}
1200
1201This is a collection of other simple or constructed types. Ordering
1202is not important. The data may arrive in the order which is different
1203from the order of specification. Data is encoded in the order not
1204necessarily corresponding to the order of specification.
1205
1206
1207\subsection{The CHOICE type}
1208
1209This type is just a choice between the subtypes specified in it. The
1210CHOICE type contains at most one of the subtypes specified, and it
1211is always implicitly known which choice is being decoded or encoded.
Lev Walkin464166c2010-11-09 08:34:38 -08001212This one resembles the C ``union'' statement.
Lev Walkined44bf42010-11-08 02:04:55 -08001213
1214The following type defines a response code, which may be either an
Lev Walkin464166c2010-11-09 08:34:38 -08001215integer code or a boolean ``true''/``false'' code.
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001216\begin{asn}
1217ResponseCode ::= CHOICE {
1218 intCode INTEGER,
1219 boolCode BOOLEAN
1220}
1221\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -08001222
1223\subsection{The SEQUENCE OF type}
1224
1225This one is the list (array) of simple or constructed types:
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001226\begin{asn}
1227-- Example 1
1228ManyIntegers ::= SEQUENCE OF INTEGER
Lev Walkined44bf42010-11-08 02:04:55 -08001229
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001230-- Example 2
1231ManyRectangles ::= SEQUENCE OF Rectangle
Lev Walkined44bf42010-11-08 02:04:55 -08001232
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001233-- More complex example:
1234-- an array of structures defined in place.
1235ManyCircles ::= SEQUENCE OF SEQUENCE {
1236 radius INTEGER
1237 }
1238\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -08001239
1240\subsection{The SET OF type}
1241
1242The SET OF type models the bag of structures. It resembles the SEQUENCE
Lev Walkin507f6002014-10-26 20:22:16 -07001243OF type, but the order is not important. The elements may arrive
Lev Walkined44bf42010-11-08 02:04:55 -08001244in the order which is not necessarily the same as the in-memory order
1245on the remote machines.
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001246\begin{asn}
1247-- A set of structures defined elsewhere
1248SetOfApples :: SET OF Apple
Lev Walkined44bf42010-11-08 02:04:55 -08001249
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001250-- Set of integers encoding the kind of a fruit
1251FruitBag ::= SET OF ENUMERATED { apple, orange }
1252\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -08001253\begin{thebibliography}{ITU-T/ASN.1}
1254\bibitem[ASN1C]{ASN1C}The Open Source ASN.1 Compiler. \url{http://lionet.info/asn1c}
1255
1256\bibitem[AONL]{AONL}Online ASN.1 Compiler. \url{http://lionet.info/asn1c/asn1c.cgi}
1257
1258\bibitem[Dub00]{Dub00}Olivier Dubuisson --- \emph{ASN.1 Communication
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001259between heterogeneous systems} --- Morgan Kaufmann Publishers, 2000.
Lev Walkined44bf42010-11-08 02:04:55 -08001260\url{http://asn1.elibel.tm.fr/en/book/}. ISBN:0-12-6333361-0.
1261
Lev Walkin464166c2010-11-09 08:34:38 -08001262\bibitem[ITU-T/ASN.1]{ITU-T/ASN.1}ITU-T Study Group 17 --- Languages
Lev Walkined44bf42010-11-08 02:04:55 -08001263for Telecommunication Systems \url{http://www.itu.int/ITU-T/studygroups/com17/languages/}
1264\end{thebibliography}
1265
1266\end{document}