blob: b18033f7fa0543fbee1aa7a9442e24820d621ddd [file] [log] [blame]
Lev Walkin464166c2010-11-09 08:34:38 -08001\documentclass[english,oneside,12pt]{book}
2\usepackage{fontspec}
3\usepackage{xunicode}
4\usepackage{xltxtra}
5
6\usepackage[hmargin={1in,1in},vmargin={2in,2in}]{geometry}
7
8\defaultfontfeatures{Mapping=tex-text}
9\setmainfont{Myriad Pro}
10\setsansfont{Myriad Pro}
11\setmonofont{Consolas}
12
Lev Walkined44bf42010-11-08 02:04:55 -080013\usepackage{fancyhdr}
14\pagestyle{fancy}
Lev Walkined44bf42010-11-08 02:04:55 -080015\usepackage{longtable}
Lev Walkin464166c2010-11-09 08:34:38 -080016\usepackage{booktabs}
Lev Walkined44bf42010-11-08 02:04:55 -080017\usepackage{varioref}
18\usepackage{url}
19
20\makeatletter
21
22%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% LyX specific LaTeX commands.
23%% Because html converters don't know tabularnewline
24\providecommand{\tabularnewline}{\\}
25
26%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Textclass specific LaTeX commands.
27\newenvironment{lyxcode}
28{\par\begin{list}{}{
29\setlength{\rightmargin}{\leftmargin}
30\setlength{\listparindent}{0pt}% needed for AMS classes
31\raggedright
32\setlength{\itemsep}{0pt}
33\setlength{\parsep}{0pt}
34\normalfont\ttfamily}%
35 \item[]}
36{\end{list}}
37
38%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% User specified LaTeX commands.
39\usepackage{extramarks}
40\lhead{\firstxmark}
41\rfoot{\lastxmark}
42\usepackage{color}
Lev Walkin464166c2010-11-09 08:34:38 -080043\definecolor{linkred}{rgb}{0.8235,0.0863,0.1843}
Lev Walkined44bf42010-11-08 02:04:55 -080044\definecolor{urlblue}{rgb}{0,0,.6}
45\usepackage[colorlinks=true,
Lev Walkin464166c2010-11-09 08:34:38 -080046linkcolor={linkred},
Lev Walkined44bf42010-11-08 02:04:55 -080047urlcolor={urlblue},
48pdfauthor={Lev Walkin},
49pdftitle={Using the Open Source ASN.1 Compiler},
Lev Walkin464166c2010-11-09 08:34:38 -080050pdfkeywords={ASN.1,asn1c,compiler},
51xetex
Lev Walkined44bf42010-11-08 02:04:55 -080052]{hyperref}
53%\fancyhf{}
54%\fancyhead[LE,RO]{\thepage}
55%\fancyhead[LO]{\rightmark}
56%\fancyhead[RE]{\leftmark}
57%\fancyfoot[R]{\lastxmark}
58
59\makeatother
60
61\usepackage{babel}
62
63\begin{document}
64
65\title{Using the Open Source ASN.1 Compiler}
66
67
68\author{Lev Walkin <\href{mailto:vlm@lionet.info?Subject=asn1c}{vlm@lionet.info}>}
69
70\maketitle
71\lhead{This document describes \href{http://lionet.info/asn1c}{asn1c-0.9.21}}
72
73\rhead{$Revision$}
74
75\tableofcontents{}
76
77\pagestyle{headings}
78
79
80\part{Using the ASN.1 Compiler}
81
82
83\chapter{Introduction to the ASN.1 Compiler}
84
85The purpose of the ASN.1 compiler is to convert the specifications
86in ASN.1 notation into some other language. At this moment, only C
87and C++ target languages are supported, the latter is in upward compatibility
88mode.
89
90The compiler reads the specification and emits a series of target
Lev Walkin464166c2010-11-09 08:34:38 -080091language structures (C structs, unions, enums) describing the corresponding
Lev Walkined44bf42010-11-08 02:04:55 -080092ASN.1 types. The compiler also creates the code which allows automatic
93serialization and deserialization of these structures using several
Lev Walkin464166c2010-11-09 08:34:38 -080094standardized encoding rules (BER, DER, XER, PER).
Lev Walkined44bf42010-11-08 02:04:55 -080095
96For example, suppose the following ASN.1 module is given%
Lev Walkin464166c2010-11-09 08:34:38 -080097\footnote{Part \vref{par:ASN.1-Basics} provides a quick reference
98on the ASN.1 notation.}:
Lev Walkined44bf42010-11-08 02:04:55 -080099\begin{lyxcode}
100RectangleTest~DEFINITIONS~::=
101
102BEGIN
103
104~
105
106Rectangle~::=~SEQUENCE~\{
107
108~~~~height~~INTEGER,~~~~~~~~-{}-~Height~of~the~rectangle
109
110~~~~width~~~INTEGER~~~~~~~~~-{}-~Width~of~the~rectangle
111
112\}
113
114~
115
116END
117\end{lyxcode}
118The compiler would read this ASN.1 definition and produce the following
119C type%
120\footnote{\emph{-fnative-types} compiler option is used to produce basic C \emph{int}
121types instead of infinite width INTEGER\_t structures. See Section
122\vref{sec:Command-line-options}.%
123}:
124\begin{lyxcode}
125typedef~struct~Rectangle\_s~\{
126
127~~~~int~height;
128
129~~~~int~width;
130
131\}~Rectangle\_t;
132\end{lyxcode}
133It would also create the code for converting this structure into platform-independent
134wire representation (a serializer API) and the decoder of such wire
135representation back into local, machine-specific type (a deserializer
136API).
137
138
139\section{Quick start with asn1c}
140
141After building and installing the compiler, the \emph{asn1c}%
Lev Walkin464166c2010-11-09 08:34:38 -0800142\footnote{The 1 symbol in asn\textbf{1}c is a digit, not an ``ell'' letter.%
Lev Walkined44bf42010-11-08 02:04:55 -0800143} command may be used to compile the ASN.1 module%
Lev Walkin464166c2010-11-09 08:34:38 -0800144\footnote{This is probably \textbf{not} what you want to try out right now. Read through the rest of this chapter and check the Section \vref{sec:Command-line-options}
Lev Walkined44bf42010-11-08 02:04:55 -0800145to find out about \textbf{-P} and \textbf{-R} options.%
146}:
147\begin{lyxcode}
148asn1c~\emph{<module.asn1>}
149\end{lyxcode}
150If several ASN.1 modules contain interdependencies, all of the files
151must be specified altogether:
152\begin{lyxcode}
153asn1c~\emph{<module1.asn1>~<module2.asn1>~...}
154\end{lyxcode}
155The compiler \textbf{-E} and \textbf{-EF} options are used for testing
156the parser and the semantic fixer, respectively. These options will
157instruct the compiler to dump out the parsed (and fixed, if \textbf{-F}
Lev Walkin464166c2010-11-09 08:34:38 -0800158is involved) ASN.1 specification as it was ``understood''
Lev Walkined44bf42010-11-08 02:04:55 -0800159by the compiler. It might be useful to check whether a particular
160syntactic construction is properly supported by the compiler.
161\begin{lyxcode}
162asn1c~\textbf{-EF}~\emph{<module-to-test.asn1>}
163\end{lyxcode}
164The \textbf{-P} option is used to dump the compiled output on the
165screen instead of creating a bunch of .c and .h files on disk in the
166current directory. You would probably want to start with \textbf{-P}
167option instead of creating a mess in your current directory. Another
168option, \textbf{-R}, asks compiler to only generate the files which
169need to be generated, and supress linking in the numerous support
170files.
171
172Print the compiled output instead of creating multiple source files:
173\begin{lyxcode}
174asn1c~\textbf{-P}~\emph{<module-to-compile-and-print.asn1>}
175\end{lyxcode}
176
177\section{Recognizing compiler output}
178
179After compiling, the following entities will be created in your current
180directory:
181\begin{itemize}
182\item A set of .c and .h files, generally a single pair for each type defined
183in the ASN.1 specifications. These files will be named similarly to
184the ASN.1 types (\emph{Rectangle.c} and \emph{Rectangle.h} for the
185RectangleTest ASN.1 module defined in the beginning of this document).
186\item A set of helper .c and .h files which contain generic encoders, decoders
187and other useful routines. There will be quite a few of them, some
188of them even are not always necessary, but the overall amount of code
189after compilation will be rather small anyway.
190\item A \emph{Makefile.am.sample} file mentioning all the files created
191at the earlier steps. This file is suitable for either automake suite
192or the plain `make` utility.
193\end{itemize}
194It is your responsibility to create .c file with the \emph{int main()}
195routine.
196
197In other words, after compiling the Rectangle module, you have the
Lev Walkin464166c2010-11-09 08:34:38 -0800198following set of files: \{~Makefile.am.sample, Rectangle.c, Rectangle.h,
199\textbf{\ldots{}} \}, where ``\textbf{\ldots{}}'' stands for the
200set of additional ``helper'' files created by the compiler. If you
Lev Walkined44bf42010-11-08 02:04:55 -0800201add a simple file with the \emph{int main()} routine, it would even
202be possible to compile everything with the single instruction:
203\begin{lyxcode}
204cc~-I.~-o~rectangle.exe~{*}.c~~~\#~It~could~be~\emph{that}~simple
205\end{lyxcode}
206Refer to the Chapter \vref{cha:Step-by-step-examples} for a sample
207\emph{int main()} routine.
208
209
210\section{\label{sec:Command-line-options}Command line options}
211
212The following table summarizes the asn1c command line options.
213
Lev Walkin464166c2010-11-09 08:34:38 -0800214\renewcommand{\arraystretch}{1.33}
215\begin{longtable}{lp{4in}}
216\toprule
Lev Walkined44bf42010-11-08 02:04:55 -0800217\textbf{\small Overall Options} & \textbf{\small Description}\tabularnewline
Lev Walkin464166c2010-11-09 08:34:38 -0800218\midrule
Lev Walkined44bf42010-11-08 02:04:55 -0800219{\small -E} & {\small Stop after the parsing stage and print the reconstructed ASN.1
220specification code to the standard output.}\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800221{\small -F} & {\small Used together with -E, instructs the compiler to stop after
222the ASN.1 syntax tree fixing stage and dump the reconstructed ASN.1
223specification to the standard output.}\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800224{\small -P} & {\small Dump the compiled output to the standard output instead of
Lev Walkin464166c2010-11-09 08:34:38 -0800225creating the target language files on disk.}\tabularnewline
226{\small -R} & {\small Restrict the compiler to generate only the ASN.1 tables, omitting the usual support code.}\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800227{\small -S }\emph{\small <directory>} & {\small Use the specified directory with ASN.1 skeleton files.}\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800228{\small -X} & {\small Generate the XML DTD for the specified ASN.1 modules.}\tabularnewline
Lev Walkin464166c2010-11-09 08:34:38 -0800229\midrule\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800230\textbf{\small Warning Options} & \textbf{\small Description}\tabularnewline
Lev Walkin464166c2010-11-09 08:34:38 -0800231\midrule
Lev Walkined44bf42010-11-08 02:04:55 -0800232{\small -Werror} & {\small Treat warnings as errors; abort if any warning is produced.}\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800233{\small -Wdebug-lexer} & {\small Enable lexer debugging during the ASN.1 parsing stage.}\tabularnewline
Lev Walkin464166c2010-11-09 08:34:38 -0800234{\small -Wdebug-fixer} & {\small Enable ASN.1 syntax tree fixer debugging during the
Lev Walkined44bf42010-11-08 02:04:55 -0800235 fixing stage.}\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800236{\small -Wdebug-compiler} & {\small Enable debugging during the actual compile time.}\tabularnewline
Lev Walkin464166c2010-11-09 08:34:38 -0800237\midrule\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800238\textbf{\small Language Options} & \textbf{\small Description}\tabularnewline
Lev Walkin464166c2010-11-09 08:34:38 -0800239\midrule
Lev Walkined44bf42010-11-08 02:04:55 -0800240{\small -fbless-SIZE} & {\small Allow SIZE() constraint for INTEGER, ENUMERATED, and other
241types for which this constraint is normally prohibited by the standard.
242This is a violation of an ASN.1 standard and compiler may fail to
243produce the meaningful code.}\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800244{\small -fcompound-names} & {\small Use complex names for C structures. Using complex names prevents
245name clashes in case the module reuses the same identifiers in multiple
246contexts.}\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800247{\small -findirect-choice} & {\small When generating code for a CHOICE type, compile the CHOICE
248members as indirect pointers instead of declaring them inline. Consider
249using this option together with }\textbf{\small -fno-include-deps}{\small{}
250to prevent circular references. }\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800251{\small -fknown-extern-type=}\emph{\small <name>} & {\small Pretend the specified type is known. The compiler will assume
252the target language source files for the given type have been provided
253manually. }\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800254{\small -fnative-types} & {\small Use the native machine's data types (int, double) whenever
255possible, instead of the compound INTEGER\_t, ENUMERATED\_t and REAL\_t
256types. }\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800257{\small -fno-constraints} & {\small Do not generate ASN.1 subtype constraint checking code. This
258may produce a shorter executable.}\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800259{\small -fno-include-deps} & {\small Do not generate courtesy \#include lines for non-critical
260dependencies.}\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800261{\small -funnamed-unions} & {\small Enable unnamed unions in the definitions of target language's
262structures.}\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800263{\small -fskeletons-copy} & {\small Copy support files rather than symlink them.}\tabularnewline
Lev Walkin464166c2010-11-09 08:34:38 -0800264\midrule\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800265\textbf{\small Codecs Generation Options} & \textbf{\small Description}\tabularnewline
Lev Walkin464166c2010-11-09 08:34:38 -0800266\midrule
Lev Walkined44bf42010-11-08 02:04:55 -0800267{\small -gen-PER} & {\small Generate Packed Encoding Rules (PER) support code.}\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800268{\small -pdu=}\emph{\small auto} & {\small Generate PDU tables by discovering Protocol Data Units automatically.}\tabularnewline
Lev Walkin464166c2010-11-09 08:34:38 -0800269\midrule\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800270\textbf{\small Output Options} & \textbf{\small Description}\tabularnewline
Lev Walkin464166c2010-11-09 08:34:38 -0800271\midrule
Lev Walkined44bf42010-11-08 02:04:55 -0800272{\small -print-constraints} & {\small When -EF are also specified, this option forces the compiler
273to explain its internal understanding of subtype constraints.}\tabularnewline
Lev Walkin464166c2010-11-09 08:34:38 -0800274{\small -print-lines} & {\small Generate ``-{}- \#line'' comments
Lev Walkined44bf42010-11-08 02:04:55 -0800275in -E output.}\tabularnewline
Lev Walkin464166c2010-11-09 08:34:38 -0800276\bottomrule
Lev Walkined44bf42010-11-08 02:04:55 -0800277\end{longtable}
Lev Walkin464166c2010-11-09 08:34:38 -0800278\renewcommand{\arraystretch}{1}
Lev Walkined44bf42010-11-08 02:04:55 -0800279
280
281\chapter{Using the ASN.1 Compiler}
282
283
284\section[Invoking the helper code]{Invoking the ASN.1 helper code}
285
286First of all, you should include one or more header files into your
287application. Typically, it is enough to include the header file of
288the main PDU type. For our Rectangle module, including the Rectangle.h
289file is sufficient:
290\begin{lyxcode}
291\#include~<Rectangle.h>
292\end{lyxcode}
293The header files defines the C structure corresponding to the ASN.1
294definition of a rectangle and the declaration of the ASN.1 type descriptor,
295which is used as an argument to most of the functions provided by
296the ASN.1 module. For example, here is the code which frees the Rectangle\_t
297structure:
298\begin{lyxcode}
299Rectangle\_t~{*}rect~=~...;
300
301~
302
Lev Walkin464166c2010-11-09 08:34:38 -0800303asn\_DEF\_Rectangle.free\_struct(\&asn\_DEF\_Rectangle, rect,~0);
Lev Walkined44bf42010-11-08 02:04:55 -0800304\end{lyxcode}
305This code defines a \emph{rect} pointer which points to the Rectangle\_t
306structure which needs to be freed. The second line invokes the generic
307\emph{free\_struct()} routine created specifically for this Rectangle\_t
308structure. The \emph{asn\_DEF\_Rectangle} is the type descriptor,
309which holds a collection of routines to deal with the Rectangle\_t
310structure.
311
312The following member functions of the asn\_DEF\_Rectangle type descriptor
313are of interest:
314\begin{description}
315\item [{ber\_decoder}] This is the generic \emph{restartable}%
316\footnote{Restartable means that if the decoder encounters the end of the buffer,
317it will fail, but may later be invoked again with the rest of the
318buffer to continue decoding.%
319} BER decoder (Basic Encoding Rules). This decoder would create and/or
320fill the target structure for you. See Section \vref{sub:Decoding-BER}.
321\item [{der\_encoder}] This is the generic DER encoder (Distinguished Encoding
322Rules). This encoder will take the target structure and encode it
323into a series of bytes. See Section \vref{sub:Encoding-DER}. NOTE:
324DER encoding is a subset of BER. Any BER decoder should be able to
325handle DER input.
326\item [{xer\_decoder}] This is the generic XER decoder. It takes both BASIC-XER
327or CANONICAL-XER encodings and deserializes the data into a local,
328machine-dependent representation. See Section \vref{sub:Decoding-XER}.
329\item [{xer\_encoder}] This is the XER encoder (XML Encoding Rules). This
330encoder will take the target structure and represent it as an XML
331(text) document using either BASIC-XER or CANONICAL-XER encoding rules.
332See Section \vref{sub:Encoding-XER}.
333\item [{uper\_decoder}] This is the Unaligned PER decoder.
334\item [{uper\_encoder}] This is the Unaligned Basic PER encoder. This encoder
335will take the target structure and encode it into a series of bytes.
336\item [{check\_constraints}] Check that the contents of the target structure
337are semantically valid and constrained to appropriate implicit or
338explicit subtype constraints. See Section \vref{sub:Validating-the-target}.
339\item [{print\_struct}] This function convert the contents of the passed
340target structure into human readable form. This form is not formal
341and cannot be converted back into the structure, but it may turn out
342to be useful for debugging or quick-n-dirty printing. See Section
343\vref{sub:Printing-the-target}.
344\item [{free\_struct}] This is a generic disposal which frees the target
345structure. See Section \vref{sub:Freeing-the-target}.
346\end{description}
347Each of the above function takes the type descriptor (\emph{asn\_DEF\_\ldots{}})
348and the target structure (\emph{rect}, in the above example).
349
350
351\subsection{\label{sub:Decoding-BER}Decoding BER}
352
353The Basic Encoding Rules describe the most widely used (by the ASN.1
354community) way to encode and decode a given structure in a machine-independent
355way. Several other encoding rules (CER, DER) define a more restrictive
356versions of BER, so the generic BER parser is also capable of decoding
357the data encoded by CER and DER encoders. The opposite is not true.
358
359\emph{The ASN.1 compiler provides the generic BER decoder which is
360implicitly capable of decoding BER, CER and DER encoded data.}
361
362The decoder is restartable (stream-oriented), which means that in
363case the buffer has less data than it is expected, the decoder will
364process whatever there is available and ask for more data to be provided.
365Please note that the decoder may actually process less data than it
366was given in the buffer, which means that you must be able to make
367the next buffer contain the unprocessed part of the previous buffer.
368
369Suppose, you have two buffers of encoded data: 100 bytes and 200 bytes.
370\begin{itemize}
371\item You may concatenate these buffers and feed the BER decoder with 300
372bytes of data, or
373\item You may feed it the first buffer of 100 bytes of data, realize that
374the ber\_decoder consumed only 95 bytes from it and later feed the
375decoder with 205 bytes buffer which consists of 5 unprocessed bytes
376from the first buffer and the additional 200 bytes from the second
377buffer.
378\end{itemize}
379This is not as convenient as it could be (like, the BER encoder could
380consume the whole 100 bytes and keep these 5 bytes in some temporary
381storage), but in case of existing stream based processing it might
382actually fit well into existing algorithm. Suggestions are welcome.
383
384Here is the simplest example of BER decoding.
385\begin{lyxcode}
386Rectangle\_t~{*}
387
388simple\_deserializer(const~void~{*}buffer,~size\_t~buf\_size)~\{
389
390~~~~Rectangle\_t~{*}rect~=~0;~~~~/{*}~Note~this~0!~{*}/
391
392~~~~asn\_dec\_rval\_t~rval;
393
394~
395
396~~~~rval~=~\textbf{asn\_DEF\_Rectangle.ber\_decoder}(0,
397
398~~~~~~~~~~\&asn\_DEF\_Rectangle,
399
400~~~~~~~~~~(void~{*}{*})\&rect,
401
402~~~~~~~~~~buffer,~buf\_size,
403
404~~~~~~~~~~0);
405
406~
407
408~~~~if(rval\textbf{.code}~==~RC\_OK)~\{
409
410~~~~~~~~return~rect;~~~~~~~~~~/{*}~Decoding~succeeded~{*}/
411
412~~~~\}~else~\{
413
414~~~~~~~~/{*}~Free~partially~decoded~rect~{*}/
415
Lev Walkin464166c2010-11-09 08:34:38 -0800416~~~~~~~~asn\_DEF\_Rectangle.free\_struct(\&asn\_DEF\_Rectangle,~rect,~0);
Lev Walkined44bf42010-11-08 02:04:55 -0800417
418~~~~~~~~return~0;
419
420~~~~\}
421
422\}
423\end{lyxcode}
424The code above defines a function, \emph{simple\_deserializer}, which
425takes a buffer and its length and is expected to return a pointer
426to the Rectangle\_t structure. Inside, it tries to convert the bytes
427passed into the target structure (rect) using the BER decoder and
428returns the rect pointer afterwards. If the structure cannot be deserialized,
429it frees the memory which might be left allocated by the unfinished
430\emph{ber\_decoder} routine and returns 0 (no data). (This \textbf{freeing
431is necessary} because the ber\_decoder is a restartable procedure,
432and may fail just because there is more data needs to be provided
433before decoding could be finalized). The code above obviously does
434not take into account the way the \emph{ber\_decoder()} failed, so
435the freeing is necessary because the part of the buffer may already
436be decoded into the structure by the time something goes wrong.
437
438A little less wordy would be to invoke a globally available \emph{ber\_decode()}
439function instead of dereferencing the asn\_DEF\_Rectangle type descriptor:
440\begin{lyxcode}
441rval~=~ber\_decode(0,~\&asn\_DEF\_Rectangle,~(void~{*}{*})\&rect,
442
443~~~~buffer,~buf\_size);
444\end{lyxcode}
445Note that the initial (asn\_DEF\_Rectangle.ber\_decoder) reference
446is gone, and also the last argument (0) is no longer necessary.
447
448These two ways of BER decoder invocations are fully equivalent.
449
450The BER de\emph{coder} may fail because of (\emph{the following RC\_\ldots{}
451codes are defined in ber\_decoder.h}):
452\begin{itemize}
453\item RC\_WMORE: There is more data expected than it is provided (stream
454mode continuation feature);
455\item RC\_FAIL: General failure to decode the buffer;
456\item \ldots{} other codes may be defined as well.
457\end{itemize}
458Together with the return code (.code) the asn\_dec\_rval\_t type contains
459the number of bytes which is consumed from the buffer. In the previous
460hypothetical example of two buffers (of 100 and 200 bytes), the first
461call to ber\_decode() would return with .code = RC\_WMORE and .consumed
462= 95. The .consumed field of the BER decoder return value is \textbf{always}
463valid, even if the decoder succeeds or fails with any other return
464code.
465
Lev Walkin464166c2010-11-09 08:34:38 -0800466Look into ber\_decoder.h for the precise definition of ber\_decode()
Lev Walkined44bf42010-11-08 02:04:55 -0800467and related types.
468
469
470\subsection{\label{sub:Encoding-DER}Encoding DER}
471
472The Distinguished Encoding Rules is the \emph{canonical} variant of
473BER encoding rules. The DER is best suited to encode the structures
474where all the lengths are known beforehand. This is probably exactly
475how you want to encode: either after a BER decoding or after a manual
476fill-up, the target structure contains the data which size is implicitly
477known before encoding. Among other uses, the DER encoding is used
478to encode X.509 certificates.
479
480As with BER decoder, the DER encoder may be invoked either directly
481from the ASN.1 type descriptor (asn\_DEF\_Rectangle) or from the stand-alone
482function, which is somewhat simpler:
483\begin{lyxcode}
484~
485
486/{*}
487
488~{*}~This~is~the~serializer~itself,
489
490~{*}~it~supplies~the~DER~encoder~with~the
491
492~{*}~pointer~to~the~custom~output~function.
493
494~{*}/
495
496ssize\_t
497
498simple\_serializer(FILE~{*}ostream,~Rectangle\_t~{*}rect)~\{
499
500~~~~asn\_enc\_rval\_t~er;~~/{*}~Encoder~return~value~{*}/
501
502~
503
504~~~~er~=~der\_encode(\&asn\_DEF\_Rect,~rect,
505
506~~~~~~~~write\_stream,~ostream);
507
508~~~~if(er.\textbf{encoded}~==~-1)~\{
509
510~~~~~~~~/{*}
511
512~~~~~~~~~{*}~Failed~to~encode~the~rectangle~data.
513
514~~~~~~~~~{*}/
515
516~~~~~~~~fprintf(stderr,~''Cannot~encode~\%s:~\%s\textbackslash{}n'',
517
Lev Walkin464166c2010-11-09 08:34:38 -0800518~~~~~~~~~~~~er.\textbf{failed\_type}->name, strerror(errno));
Lev Walkined44bf42010-11-08 02:04:55 -0800519
520~~~~~~~~return~-1;
521
522~~~~\}~else~\{
523
524~~~~~~~~/{*}~Return~the~number~of~bytes~{*}/
525
526~~~~~~~~return~er.encoded;
527
528~~~~\}
529
530\}
531\end{lyxcode}
532As you see, the DER encoder does not write into some sort of buffer
533or something. It just invokes the custom function (possible, multiple
534times) which would save the data into appropriate storage. The optional
535argument \emph{app\_key} is opaque for the DER encoder code and just
536used by \emph{\_write\_stream()} as the pointer to the appropriate
537output stream to be used.
538
539If the custom write function is not given (passed as 0), then the
540DER encoder will essentially do the same thing (i.e., encode the data)
541but no callbacks will be invoked (so the data goes nowhere). It may
542prove useful to determine the size of the structure's encoding before
543actually doing the encoding%
544\footnote{It is actually faster too: the encoder might skip over some computations
545which aren't important for the size determination.%
546}.
547
Lev Walkin464166c2010-11-09 08:34:38 -0800548Look into der\_encoder.h for the precise definition of der\_encode()
Lev Walkined44bf42010-11-08 02:04:55 -0800549and related types.
550
551
552\subsection{\label{sub:Encoding-XER}Encoding XER}
553
554The XER stands for XML Encoding Rules, where XML, in turn, is eXtensible
555Markup Language, a text-based format for information exchange. The
556encoder routine API comes in two flavors: stdio-based and callback-based.
557With the callback-based encoder, the encoding process is very similar
558to the DER one, described in Section \vref{sub:Encoding-DER}. The
559following example uses the definition of write\_stream() from up there.
560\begin{lyxcode}
561/{*}
562
563~{*}~This~procedure~generates~the~XML~document
564
565~{*}~by~invoking~the~XER~encoder.
566
567~{*}~NOTE:~Do~not~copy~this~code~verbatim!
568
569~{*}~~~~~~~If~the~stdio~output~is~necessary,
570
571~{*}~~~~~~~use~the~xer\_fprint()~procedure~instead.
572
573~{*}~~~~~~~See~Section~\vref{sub:Printing-the-target}.
574
575~{*}/
576
577int
578
579print\_as\_XML(FILE~{*}ostream,~Rectangle\_t~{*}rect)~\{
580
581~~~~asn\_enc\_rval\_t~er;~~/{*}~Encoder~return~value~{*}/
582
583~
584
585~~~~er~=~xer\_encode(\&asn\_DEF\_Rectangle,~rect,
586
587~~~~~~~~XER\_F\_BASIC,~/{*}~BASIC-XER~or~CANONICAL-XER~{*}/
588
589~~~~~~~~write\_stream,~ostream);
590
591~
592
593~~~~return~(er.encoded~==~-1)~?~-1~:~0;
594
595\}
596\end{lyxcode}
Lev Walkin464166c2010-11-09 08:34:38 -0800597Look into xer\_encoder.h for the precise definition of xer\_encode()
Lev Walkined44bf42010-11-08 02:04:55 -0800598and related types.
599
600See Section \ref{sub:Printing-the-target} for the example of stdio-based
601XML encoder and other pretty-printing suggestions.
602
603
604\subsection{\label{sub:Decoding-XER}Decoding XER}
605
606The data encoded using the XER rules can be subsequently decoded using
607the xer\_decode() API call:
608\begin{lyxcode}
609Rectangle\_t~{*}
610
611XML\_to\_Rectangle(const~void~{*}buffer,~size\_t~buf\_size)~\{
612
613~~~~Rectangle\_t~{*}rect~=~0;~/{*}~Note~this~0!~{*}/
614
615~~~~asn\_dec\_rval\_t~rval;
616
617~~
618
619~~~~rval~=~xer\_decode(0,~\&asn\_DEF\_Rectangle,~(void~{*}{*})\&rect,
620
621~~~~~~~~buffer,~buf\_size);
622
623~~~~if(rval\textbf{.code}~==~RC\_OK)~\{
624
625~~~~~~~~return~rect;~~~~~~~~~~/{*}~Decoding~succeeded~{*}/
626
627~~~~\}~else~\{
628
629~~~~~~~~/{*}~Free~partially~decoded~rect~{*}/
630
Lev Walkin464166c2010-11-09 08:34:38 -0800631~~~~~~~~asn\_DEF\_Rectangle.free\_struct(\&asn\_DEF\_Rectangle,~rect,~0);
Lev Walkined44bf42010-11-08 02:04:55 -0800632
633~~~~~~~~return~0;
634
635~~~~\}
636
637\}
638\end{lyxcode}
639The decoder takes both BASIC-XER and CANONICAL-XER encodings.
640
641The decoder shares its data consumption properties with BER decoder;
642please read the Section \vref{sub:Decoding-BER} to know more.
643
Lev Walkin464166c2010-11-09 08:34:38 -0800644Look into xer\_decoder.h for the precise definition of xer\_decode()
Lev Walkined44bf42010-11-08 02:04:55 -0800645and related types.
646
647
648\subsection{\label{sub:Validating-the-target}Validating the target structure}
649
650Sometimes the target structure needs to be validated. For example,
651if the structure was created by the application (as opposed to being
652decoded from some external source), some important information required
653by the ASN.1 specification might be missing. On the other hand, the
654successful decoding of the data from some external source does not
655necessarily mean that the data is fully valid either. It might well
656be the case that the specification describes some subtype constraints
657that were not taken into account during decoding, and it would actually
658be useful to perform the last check when the data is ready to be encoded
659or when the data has just been decoded to ensure its validity according
660to some stricter rules.
661
662The asn\_check\_constraints() function checks the type for various
663implicit and explicit constraints. It is recommended to use asn\_check\_constraints()
664function after each decoding and before each encoding.
665
Lev Walkin464166c2010-11-09 08:34:38 -0800666Look into constraints.h for the precise definition of asn\_check\_constraints()
Lev Walkined44bf42010-11-08 02:04:55 -0800667and related types.
668
669
670\subsection{\label{sub:Printing-the-target}Printing the target structure}
671
672There are two ways to print the target structure: either invoke the
673print\_struct member of the ASN.1 type descriptor, or using the asn\_fprint()
674function, which is a simpler wrapper of the former:
675\begin{lyxcode}
676asn\_fprint(stdout,~\&asn\_DEF\_Rectangle,~rect);
677\end{lyxcode}
Lev Walkin464166c2010-11-09 08:34:38 -0800678Look into constr\_TYPE.h for the precise definition of asn\_fprint()
Lev Walkined44bf42010-11-08 02:04:55 -0800679and related types.
680
681Another practical alternative to this custom format printing would
682be to invoke XER encoder. The default BASIC-XER encoder performs reasonable
683formatting for the output to be useful and human readable. To invoke
684the XER decoder in a manner similar to asn\_fprint(), use the xer\_fprint()
685call:
686\begin{lyxcode}
687xer\_fprint(stdout,~\&asn\_DEF\_Rectangle,~rect);
688\end{lyxcode}
689See Section \vref{sub:Encoding-XER} for XML-related details.
690
691
692\subsection{\label{sub:Freeing-the-target}Freeing the target structure}
693
694Freeing the structure is slightly more complex than it may seem to.
695When the ASN.1 structure is freed, all the members of the structure
696and their submembers are recursively freed as well. But it might not
697be feasible to free the structure itself. Consider the following case:
698\begin{lyxcode}
699struct~my\_figure~\{~~~~~~~/{*}~The~custom~structure~{*}/
700
701~~~~int~flags;~~~~~~~~~~~/{*}~<some~custom~member>~{*}/
702
703~~~~/{*}~The~type~is~generated~by~the~ASN.1~compiler~{*}/
704
705~~~~\emph{Rectangle\_t~rect;}
706
707~~~~/{*}~other~members~of~the~structure~{*}/
708
709\};
710\end{lyxcode}
711In this example, the application programmer defined a custom structure
712with one ASN.1-derived member (rect). This member is not a reference
713to the Rectangle\_t, but an in-place inclusion of the Rectangle\_t
714structure. If the freeing is necessary, the usual procedure of freeing
715everything must not be applied to the \&rect pointer itself, because
716it does not point to the memory block directly allocated by the memory
717allocation routine, but instead lies within a block allocated for
718the my\_figure structure.
719
720To solve this problem, the free\_struct routine has the additional
721argument (besides the obvious type descriptor and target structure
722pointers), which is the flag specifying whether the outer pointer
723itself must be freed (0, default) or it should be left intact (non-zero
724value).
725\begin{lyxcode}
726\textbf{/{*}~1.~Rectangle\_t~is~defined~within~my\_figure~{*}/}
727
728struct~my\_figure~\{
729
730~~~~Rectangle\_t~rect;
731
732\}~{*}mf~=~\textbf{...};
733
734/{*}
735
736~{*}~Freeing~the~Rectangle\_t
737
738~{*}~without~freeing~the~mf->rect~area
739
740~{*}/
741
742asn\_DEF\_Rectangle.free\_struct(
743
744~~~~\&asn\_DEF\_Rectangle,~\&mf->rect,~\textbf{1}~\textbf{/{*}~!free~{*}/});
745
746~~~~
747
748~~
749
750\textbf{/{*}~2.~Rectangle\_t~is~a~stand-alone~pointer~{*}/}
751
752Rectangle\_t~{*}rect~=~\textbf{...};
753
754/{*}
755
756~{*}~Freeing~the~Rectangle\_t
757
758~{*}~and~freeing~the~rect~pointer
759
760~{*}/
761
762asn\_DEF\_Rectangle.free\_struct(
763
764~~~~\&asn\_DEF\_Rectangle,~rect,~\textbf{0}~\textbf{/{*}~free~the~pointer~too~{*}/});
765\end{lyxcode}
766It is safe to invoke the \emph{free\_struct} function with the target
767structure pointer set to 0 (NULL), the function will do nothing.
768
769For the programmer's convenience, the following macros are available:
770\begin{lyxcode}
771ASN\_STRUCT\_FREE(asn\_DEF,~ptr);
772
773ASN\_STRUCT\_FREE\_CONTENTS\_ONLY(asn\_DEF,~ptr);
774\end{lyxcode}
775These macros bear the same semantics as the \emph{free\_struct} function
776invocation, discussed above.
777
778
779\chapter{\label{cha:Step-by-step-examples}Step by step examples}
780
781
Lev Walkin464166c2010-11-09 08:34:38 -0800782\section{A ``Rectangle'' Encoder}
Lev Walkined44bf42010-11-08 02:04:55 -0800783
784This example will help you create a simple BER and XER encoder of
Lev Walkin464166c2010-11-09 08:34:38 -0800785a ``Rectangle'' type used throughout this document.
Lev Walkined44bf42010-11-08 02:04:55 -0800786\begin{enumerate}
787\item Create a file named \textbf{rectangle.asn1} with the following contents:
788
789\begin{lyxcode}
790RectangleModule1~DEFINITIONS~::=
791
792BEGIN
793
794~
795
796Rectangle~::=~SEQUENCE~\{
797
798~~~~height~~INTEGER,
799
800~~~~width~~~INTEGER
801
802\}
803
804~
805
806END
807\end{lyxcode}
808\item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}:
809
810\begin{lyxcode}
811\emph{asn1c~-fnative-types}~\textbf{rectangle.asn1}
812\end{lyxcode}
813\item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading
814the \textbf{rectangle.asn1} file into the Web form and unpacking the
815produced archive on your computer.
816\item By this time, you should have gotten multiple files in the current
817directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}.
818\item Create a main() routine which creates the Rectangle\_t structure in
819memory and encodes it using BER and XER encoding rules. Let's name
820the file \textbf{main.c}:\clearpage{}
821
822\begin{lyxcode}
823{\small \#include~<stdio.h>}{\small \par}
824
825{\small \#include~<sys/types.h>}{\small \par}
826
827{\small \#include~<Rectangle.h>~~~/{*}~Rectangle~ASN.1~type~~{*}/}{\small \par}
828
829~
830
831{\small /{*}}{\small \par}
832
833{\small{}~{*}~This~is~a~custom~function~which~writes~the}{\small \par}
834
835{\small{}~{*}~encoded~output~into~some~FILE~stream.}{\small \par}
836
837{\small{}~{*}/}{\small \par}
838
839{\small static~int}{\small \par}
840
841{\small write\_out(const~void~{*}buffer,~size\_t~size,~void~{*}app\_key)~\{}{\small \par}
842
843{\small{}~~~~FILE~{*}out\_fp~=~app\_key;}{\small \par}
844
845{\small{}~~~~size\_t~wrote;}{\small \par}
846
847{\small{}~}{\small \par}
848
849{\small{}~~~~wrote~=~fwrite(buffer,~1,~size,~out\_fp);}{\small \par}
850
851{\small{}~}{\small \par}
852
853{\small{}~~~~return~(wrote~==~size)~?~0~:~-1;}{\small \par}
854
855{\small \}}{\small \par}
856
857~
858
859{\small int~main(int~ac,~char~{*}{*}av)~\{}{\small \par}
860
861{\small{}~~~~Rectangle\_t~{*}rectangle;~/{*}~Type~to~encode~~~~~~~~{*}/}{\small \par}
862
863{\small{}~~~~asn\_enc\_rval\_t~ec;~~~~~~/{*}~Encoder~return~value~~{*}/}{\small \par}
864
865{\small{}~}{\small \par}
866
867{\small{}~~~~/{*}~Allocate~the~Rectangle\_t~{*}/}{\small \par}
868
869{\small{}~~~~rectangle~=~calloc(1,~sizeof(Rectangle\_t));~/{*}~not~malloc!~{*}/}{\small \par}
870
871{\small{}~~~~if(!rectangle)~\{}{\small \par}
872
873{\small{}~~~~~~perror(''calloc()~failed'');}{\small \par}
874
875{\small{}~~~~~~exit(71);~/{*}~better,~EX\_OSERR~{*}/}{\small \par}
876
877{\small{}~~~~\}}{\small \par}
878
879{\small{}~}{\small \par}
880
881{\small{}~~~~/{*}~Initialize~the~Rectangle~members~{*}/}{\small \par}
882
883{\small{}~~~~rectangle->height~=~42;~~/{*}~any~random~value~{*}/}{\small \par}
884
885{\small{}~~~~rectangle->width~~=~23;~~/{*}~any~random~value~{*}/}{\small \par}
886
887{\small{}~~~~~}{\small \par}
888
889{\small{}~~~~/{*}~BER~encode~the~data~if~filename~is~given~{*}/}{\small \par}
890
891{\small{}~~~~if(ac~<~2)~\{}{\small \par}
892
893{\small{}~~~~~~fprintf(stderr,~''Specify~filename~for~BER~output\textbackslash{}n'');}{\small \par}
894
895{\small{}~~~~\}~else~\{}{\small \par}
896
897{\small{}~~~~~~const~char~{*}filename~=~av{[}1{]};}{\small \par}
898
899{\small{}~~~~~~FILE~{*}fp~=~fopen(filename,~''wb'');~~~/{*}~for~BER~output~{*}/}{\small \par}
900
901~
902
903{\small{}~~~~~~if(!fp)~\{}{\small \par}
904
905{\small{}~~~~~~~~perror(filename);}{\small \par}
906
907{\small{}~~~~~~~~exit(71);~/{*}~better,~EX\_OSERR~{*}/}{\small \par}
908
909{\small{}~~~~~~\}}{\small \par}
910
911{\small{}~~}{\small \par}
912
913{\small{}~~~~~~/{*}~Encode~the~Rectangle~type~as~BER~(DER)~{*}/}{\small \par}
914
915{\small{}~~~~~~ec~=~der\_encode(\&asn\_DEF\_Rectangle,}{\small \par}
916
917{\small{}~~~~~~~~~~~~rectangle,~write\_out,~fp);}{\small \par}
918
919{\small{}~~~~~~fclose(fp);}{\small \par}
920
921{\small{}~~~~~~if(ec.encoded~==~-1)~\{}{\small \par}
922
923{\small{}~~~~~~~~fprintf(stderr,}{\small \par}
924
925{\small{}~~~~~~~~~~''Could~not~encode~Rectangle~(at~\%s)\textbackslash{}n'',}{\small \par}
926
927{\small{}~~~~~~~~~~ec.failed\_type~?~ec.failed\_type->name~:~''unknown'');}{\small \par}
928
929{\small{}~~~~~~~~exit(65);~/{*}~better,~EX\_DATAERR~{*}/}{\small \par}
930
931{\small{}~~~~~~\}~else~\{}{\small \par}
932
933{\small{}~~~~~~~~fprintf(stderr,~''Created~\%s~with~BER~encoded~Rectangle\textbackslash{}n'',}{\small \par}
934
935{\small{}~~~~~~~~~~filename);}{\small \par}
936
937{\small{}~~~~~~\}}{\small \par}
938
939{\small{}~~~~\}}{\small \par}
940
941{\small{}~}{\small \par}
942
943{\small{}~~~~/{*}~Also~print~the~constructed~Rectangle~XER~encoded~(XML)~{*}/}{\small \par}
944
945{\small{}~~~~xer\_fprint(stdout,~\&asn\_DEF\_Rectangle,~rectangle);}{\small \par}
946
947{\small{}~}{\small \par}
948
949{\small{}~~~~return~0;~/{*}~Encoding~finished~successfully~{*}/}{\small \par}
950
951{\small \}}{\small \par}
952\end{lyxcode}
953\item Compile all files together using C compiler (varies by platform):
954
955\begin{lyxcode}
956\emph{cc~-I.~-o}~\textbf{\emph{rencode}}~\emph{{*}.c}
957\end{lyxcode}
958\item Voila! You have just created the BER and XER encoder of a Rectangle
959type, named \textbf{rencode}!
960\end{enumerate}
961\clearpage{}
962
963
Lev Walkin464166c2010-11-09 08:34:38 -0800964\section{\label{sec:A-Rectangle-Decoder}A ``Rectangle'' Decoder}
Lev Walkined44bf42010-11-08 02:04:55 -0800965
966This example will help you to create a simple BER decoder of a simple
Lev Walkin464166c2010-11-09 08:34:38 -0800967``Rectangle'' type used throughout this document.
Lev Walkined44bf42010-11-08 02:04:55 -0800968\begin{enumerate}
969\item Create a file named \textbf{rectangle.asn1} with the following contents:
970
971\begin{lyxcode}
972RectangleModule1~DEFINITIONS~::=
973
974BEGIN
975
976~
977
978Rectangle~::=~SEQUENCE~\{
979
980~~~~height~~INTEGER,
981
982~~~~width~~~INTEGER
983
984\}
985
986~
987
988END
989\end{lyxcode}
990\item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}:
991
992\begin{lyxcode}
993\emph{asn1c~-fnative-types}~\textbf{rectangle.asn1}
994\end{lyxcode}
995\item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading
996the \textbf{rectangle.asn1} file into the Web form and unpacking the
997produced archive on your computer.
998\item By this time, you should have gotten multiple files in the current
999directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}.
1000\item Create a main() routine which takes the binary input file, decodes
1001it as it were a BER-encoded Rectangle type, and prints out the text
1002(XML) representation of the Rectangle type. Let's name the file \textbf{main.c}:\clearpage{}
1003
1004\begin{lyxcode}
1005{\small \#include~<stdio.h>}{\small \par}
1006
1007{\small \#include~<sys/types.h>}{\small \par}
1008
1009{\small \#include~<Rectangle.h>~~~/{*}~Rectangle~ASN.1~type~~{*}/}{\small \par}
1010
1011{\small{}~}{\small \par}
1012
1013{\small int~main(int~ac,~char~{*}{*}av)~\{}{\small \par}
1014
1015{\small{}~~~~char~buf{[}1024{]};~~~~~~/{*}~Temporary~buffer~~~~~~{*}/}{\small \par}
1016
1017{\small{}~~~~Rectangle\_t~{*}rectangle~=~0;~/{*}~Type~to~decode~{*}/}{\small \par}
1018
1019{\small{}~~~~asn\_dec\_rval\_t~rval;~/{*}~Decoder~return~value~~{*}/}{\small \par}
1020
1021{\small{}~~~~FILE~{*}fp;~~~~~~~~~~~~/{*}~Input~file~handler~~~~{*}/}{\small \par}
1022
1023{\small{}~~~~size\_t~size;~~~~~~~~~/{*}~Number~of~bytes~read~~{*}/}{\small \par}
1024
1025{\small{}~~~~char~{*}filename;~~~~~~/{*}~Input~file~name~{*}/}{\small \par}
1026
1027{\small{}~}{\small \par}
1028
1029{\small{}~~~~/{*}~Require~a~single~filename~argument~{*}/}{\small \par}
1030
1031{\small{}~~~~if(ac~!=~2)~\{}{\small \par}
1032
1033{\small{}~~~~~~fprintf(stderr,~''Usage:~\%s~<file.ber>\textbackslash{}n'',~av{[}0{]});}{\small \par}
1034
1035{\small{}~~~~~~exit(64);~/{*}~better,~EX\_USAGE~{*}/}{\small \par}
1036
1037{\small{}~~~~\}~else~\{}{\small \par}
1038
1039{\small{}~~~~~~filename~=~av{[}1{]};}{\small \par}
1040
1041{\small{}~~~~\}}{\small \par}
1042
1043{\small{}~}{\small \par}
1044
1045{\small{}~~~~/{*}~Open~input~file~as~read-only~binary~{*}/}{\small \par}
1046
1047{\small{}~~~~fp~=~fopen(filename,~''rb'');}{\small \par}
1048
1049{\small{}~~~~if(!fp)~\{}{\small \par}
1050
1051{\small{}~~~~~~perror(filename);}{\small \par}
1052
1053{\small{}~~~~~~exit(66);~/{*}~better,~EX\_NOINPUT~{*}/}{\small \par}
1054
1055{\small{}~~~~\}}{\small \par}
1056
1057{\small{}~~}{\small \par}
1058
1059{\small{}~~~~/{*}~Read~up~to~the~buffer~size~{*}/}{\small \par}
1060
1061{\small{}~~~~size~=~fread(buf,~1,~sizeof(buf),~fp);}{\small \par}
1062
1063{\small{}~~~~fclose(fp);}{\small \par}
1064
1065{\small{}~~~~if(!size)~\{}{\small \par}
1066
1067{\small{}~~~~~~fprintf(stderr,~''\%s:~Empty~or~broken\textbackslash{}n'',~filename);}{\small \par}
1068
1069{\small{}~~~~~~exit(65);~/{*}~better,~EX\_DATAERR~{*}/}{\small \par}
1070
1071{\small{}~~~~\}}{\small \par}
1072
1073{\small{}~}{\small \par}
1074
1075{\small{}~~~~/{*}~Decode~the~input~buffer~as~Rectangle~type~{*}/}{\small \par}
1076
1077{\small{}~~~~rval~=~ber\_decode(0,~\&asn\_DEF\_Rectangle,}{\small \par}
1078
1079{\small{}~~~~~~(void~{*}{*})\&rectangle,~buf,~size);}{\small \par}
1080
1081{\small{}~~~~if(rval.code~!=~RC\_OK)~\{}{\small \par}
1082
1083{\small{}~~~~~~fprintf(stderr,}{\small \par}
1084
1085{\small{}~~~~~~~~''\%s:~Broken~Rectangle~encoding~at~byte~\%ld\textbackslash{}n'',}{\small \par}
1086
1087{\small{}~~~~~~~~filename,~(long)rval.consumed);}{\small \par}
1088
1089{\small{}~~~~~~exit(65);~/{*}~better,~EX\_DATAERR~{*}/}{\small \par}
1090
1091{\small{}~~~~\}}{\small \par}
1092
1093{\small{}~}{\small \par}
1094
1095{\small{}~~~~/{*}~Print~the~decoded~Rectangle~type~as~XML~{*}/}{\small \par}
1096
1097{\small{}~~~~xer\_fprint(stdout,~\&asn\_DEF\_Rectangle,~rectangle);}{\small \par}
1098
1099{\small{}~}{\small \par}
1100
1101{\small{}~~~~return~0;~/{*}~Decoding~finished~successfully~{*}/}{\small \par}
1102
1103{\small \}}{\small \par}
1104\end{lyxcode}
1105\item Compile all files together using C compiler (varies by platform):
1106
1107\begin{lyxcode}
1108\emph{cc~-I.~-o}~\textbf{\emph{rdecode}}~\emph{{*}.c}
1109\end{lyxcode}
1110\item Voila! You have just created the BER decoder of a Rectangle type,
1111named \textbf{rdecode}!
1112\end{enumerate}
1113
1114\chapter{Constraint validation examples}
1115
1116This chapter shows how to define ASN.1 constraints and use the generated
1117validation code.
1118
1119
Lev Walkin464166c2010-11-09 08:34:38 -08001120\section{Adding constraints into ``Rectangle'' type}
Lev Walkined44bf42010-11-08 02:04:55 -08001121
1122This example shows how to add basic constraints to the ASN.1 specification
1123and how to invoke the constraints validation code in your application.
1124\begin{enumerate}
1125\item Create a file named \textbf{rectangle.asn1} with the following contents:
1126
1127\begin{lyxcode}
1128RectangleModuleWithConstraints~DEFINITIONS~::=
1129
1130BEGIN
1131
1132~
1133
1134Rectangle~::=~SEQUENCE~\{
1135
1136~~~~height~~INTEGER~(0..100),~-{}-~Value~range~constraint
1137
1138~~~~width~~~INTEGER~(0..MAX)~~-{}-~Makes~width~non-negative~
1139
1140\}
1141
1142~
1143
1144END
1145\end{lyxcode}
1146\item Compile the file according to procedures shown in the previous chapter.
1147\item Modify the Rectangle type processing routine (you can start with the
1148main() routine shown in the Section \vref{sec:A-Rectangle-Decoder})
1149by placing the following snippet of code \emph{before} encoding and/or
1150\emph{after} decoding the Rectangle type%
1151\footnote{Placing the constraint checking code \emph{before} encoding helps
1152to make sure you know the data is correct and within constraints before
1153sharing the data with anyone else.
1154
1155Placing the constraint checking code \emph{after} decoding, but before
1156any further action depending on the decoded data, helps to make sure
1157the application got the valid contents before making use of it.%
1158}:\clearpage{}
1159
1160\begin{lyxcode}
1161{\small int~ret;~~~~~~~~~~~/{*}~Return~value~{*}/}{\small \par}
1162
1163{\small char~errbuf{[}128{]};~~/{*}~Buffer~for~error~message~{*}/}{\small \par}
1164
1165{\small size\_t~errlen~=~sizeof(errbuf);~~/{*}~Size~of~the~buffer~{*}/}{\small \par}
1166
1167{\small{}~~}{\small \par}
1168
1169{\small /{*}~...~here~may~go~Rectangle~decoding~code~...~{*}/}{\small \par}
1170
1171{\small{}~}{\small \par}
1172
1173{\small ret~=~asn\_check\_constraints(\&asn\_DEF\_Rectangle,}{\small \par}
1174
1175{\small{}~~~~~~~~rectangle,~errbuf,~\&errlen);}{\small \par}
1176
1177{\small /{*}~assert(errlen~<~sizeof(errbuf));~//~you~may~rely~on~that~{*}/}{\small \par}
1178
1179{\small if(ret)~\{}{\small \par}
1180
1181{\small{}~~~~~~~~fprintf(stderr,~''Constraint~validation~failed:~\%s\textbackslash{}n'',}{\small \par}
1182
1183{\small{}~~~~~~~~~~errbuf~~~/{*}~errbuf~is~properly~nul-terminated~{*}/}{\small \par}
1184
1185{\small{}~~~~~~~~);}{\small \par}
1186
1187{\small{}~~~~~~~~/{*}~exit(...);~//~Replace~with~appropriate~action~{*}/}{\small \par}
1188
1189{\small \}}{\small \par}
1190
1191{\small{}~}{\small \par}
1192
1193{\small /{*}~...~here~may~go~Rectangle~encoding~code~...~{*}/}{\small \par}
1194\end{lyxcode}
1195\item Compile the resulting C code as shown in the previous chapters.
1196\item Try to test the constraints checking code by assigning integer value
1197101 to the \textbf{.height} member of the Rectangle structure, or
1198a negative value to the \textbf{.width} member. In either case, the
Lev Walkin464166c2010-11-09 08:34:38 -08001199program should print ``Constraint validation failed'' message, followed
Lev Walkined44bf42010-11-08 02:04:55 -08001200by the short explanation why validation did not succeed.
1201\item Done.
1202\end{enumerate}
1203
1204\part{\label{par:ASN.1-Basics}ASN.1 Basics}
1205
1206
1207\chapter{\label{cha:Abstract-Syntax-Notation:}Abstract Syntax Notation: ASN.1}
1208
1209\emph{This chapter defines some basic ASN.1 concepts and describes
1210several most widely used types. It is by no means an authoritative
1211or complete reference. For more complete ASN.1 description, please
1212refer to Olivier Dubuisson's book \cite{Dub00} or the ASN.1 body
1213of standards itself \cite{ITU-T/ASN.1}.}
1214
1215The Abstract Syntax Notation One is used to formally describe the
1216semantics of data transmitted across the network. Two communicating
1217parties may have different formats of their native data types (i.e.
1218number of bits in the integer type), thus it is important to have
1219a way to describe the data in a manner which is independent from the
1220particular machine's representation. The ASN.1 specifications are
1221used to achieve the following:
1222\begin{itemize}
1223\item The specification expressed in the ASN.1 notation is a formal and
1224precise way to communicate the data semantics to human readers;
1225\item The ASN.1 specifications may be used as input for automatic compilers
1226which produce the code for some target language (C, C++, Java, etc)
1227to encode and decode the data according to some encoding rules (which
1228are also defined by the ASN.1 standard).
1229\end{itemize}
1230Consider the following example:
1231\begin{lyxcode}
1232Rectangle~::=~SEQUENCE~\{
1233
1234~~~~height~~INTEGER,
1235
1236~~~~width~~~INTEGER
1237
1238\}
1239\end{lyxcode}
1240This ASN.1 specification describes a constructed type, \emph{Rectangle},
1241containing two integer fields. This specification may tell the reader
1242that there exists this kind of data structure and that some entity
1243may be prepared to send or receive it. The question on \emph{how}
1244that entity is going to send or receive the \emph{encoded data} is
1245outside the scope of ASN.1. For example, this data structure may be
1246encoded according to some encoding rules and sent to the destination
1247using the TCP protocol. The ASN.1 specifies several ways of encoding
Lev Walkin464166c2010-11-09 08:34:38 -08001248(or ``serializing'', or ``marshaling'') the data: BER, PER, XER
Lev Walkined44bf42010-11-08 02:04:55 -08001249and others, including CER and DER derivatives from BER.
1250
1251The complete specification must be wrapped in a module, which looks
1252like this:
1253\begin{lyxcode}
1254RectangleModule1
1255
1256~~~~\{~iso~org(3)~dod(6)~internet(1)~private(4)
1257
1258~~~~~~enterprise(1)~spelio(9363)~software(1)
1259
1260~~~~~~asn1c(5)~docs(2)~rectangle(1)~1~\}~
1261
1262~~~~DEFINITIONS~AUTOMATIC~TAGS~::=
1263
1264BEGIN
1265
1266~
1267
1268-{}-~This~is~a~comment~which~describes~nothing.
1269
1270Rectangle~::=~SEQUENCE~\{
1271
1272~~~~height~~INTEGER,~~~~~~~~-{}-~Height~of~the~rectangle
1273
1274~~~~width~~~INTEGER~~~~~~~~~-{}-~Width~of~the~rectangle
1275
1276\}
1277
1278~
1279
1280END
1281\end{lyxcode}
1282The module header consists of module name (RectangleModule1), the
Lev Walkin464166c2010-11-09 08:34:38 -08001283module object identifier (\{...\}), a keyword ``DEFINITIONS'', a
1284set of module flags (AUTOMATIC TAGS) and ``::= BEGIN''. The module
1285ends with an ``END'' statement.
Lev Walkined44bf42010-11-08 02:04:55 -08001286
1287
1288\section{Some of the ASN.1 Basic Types}
1289
1290
1291\subsection{The BOOLEAN type}
1292
1293The BOOLEAN type models the simple binary TRUE/FALSE, YES/NO, ON/OFF
1294or a similar kind of two-way choice.
1295
1296
1297\subsection{The INTEGER type}
1298
1299The INTEGER type is a signed natural number type without any restrictions
1300on its size. If the automatic checking on INTEGER value bounds are
1301necessary, the subtype constraints must be used.
1302\begin{lyxcode}
1303SimpleInteger~::=~INTEGER
1304
1305~
1306
1307-{}-~An~integer~with~a~very~limited~range
1308
1309SmallPositiveInt~::=~INTEGER~(0..127)
1310
1311~
1312
1313-{}-~Integer,~negative
1314
1315NegativeInt~::=~INTEGER~(MIN..0)
1316\end{lyxcode}
1317
1318\subsection{The ENUMERATED type}
1319
1320The ENUMERATED type is semantically equivalent to the INTEGER type
1321with some integer values explicitly named.
1322\begin{lyxcode}
1323FruitId~::=~ENUMERATED~\{~apple(1),~orange(2)~\}
1324
1325~
1326
1327-{}-~The~numbers~in~braces~are~optional,
1328
1329-{}-~the~enumeration~can~be~performed
1330
1331-{}-~automatically~by~the~compiler
1332
1333ComputerOSType~::=~ENUMERATED~\{
1334
1335~~~~FreeBSD,~~~~~~~~~~-{}-~acquires~value~0
1336
1337~~~~Windows,~~~~~~~~~~-{}-~acquires~value~1
1338
1339~~~~Solaris(5),~~~~~~~-{}-~remains~5
1340
1341~~~~Linux,~~~~~~~~~~~~-{}-~becomes~6
1342
1343~~~~MacOS~~~~~~~~~~~~~-{}-~becomes~7
1344
1345\}
1346\end{lyxcode}
1347
1348\subsection{The OCTET STRING type}
1349
1350This type models the sequence of 8-bit bytes. This may be used to
1351transmit some opaque data or data serialized by other types of encoders
1352(i.e. video file, photo picture, etc).
1353
1354
1355\subsection{The OBJECT IDENTIFIER type}
1356
1357The OBJECT IDENTIFIER is used to represent the unique identifier of
1358any object, starting from the very root of the registration tree.
1359If your organization needs to uniquely identify something (a router,
1360a room, a person, a standard, or whatever), you are encouraged to
1361get your own identification subtree at \url{http://www.iana.org/protocols/forms.htm}.
1362
1363For example, the very first ASN.1 module in this Chapter (RectangleModule1)
1364has the following OBJECT IDENTIFIER: 1 3 6 1 4 1 9363 1 5 2 1 1.
1365\begin{lyxcode}
1366ExampleOID~::=~OBJECT~IDENTIFIER
1367
1368~
1369
1370rectangleModule1-oid~ExampleOID
1371
1372~~::=~\{~1~3~6~1~4~1~9363~1~5~2~1~1~\}
1373
1374~
1375
1376-{}-~An~identifier~of~the~Internet.
1377
1378internet-id~OBJECT~IDENTIFIER
1379
1380~~::=~\{~iso(1)~identified-organization(3)
1381
1382~~~~~~~~dod(6)~internet(1)~\}
1383\end{lyxcode}
1384As you see, names are optional.
1385
1386
1387\subsection{The RELATIVE-OID type}
1388
1389The RELATIVE-OID type has the semantics of a subtree of an OBJECT
1390IDENTIFIER. There may be no need to repeat the whole sequence of numbers
1391from the root of the registration tree where the only thing of interest
1392is some of the tree's subsequence.
1393\begin{lyxcode}
1394this-document~RELATIVE-OID~::=~\{~docs(2)~usage(1)~\}
1395
1396~
1397
1398this-example~RELATIVE-OID~::=~\{
1399
1400~~~~this-document~assorted-examples(0)~this-example(1)~\}
1401\end{lyxcode}
1402
1403\section{Some of the ASN.1 String Types}
1404
1405
1406\subsection{The IA5String type}
1407
1408This is essentially the ASCII, with 128 character codes available
1409(7 lower bits of an 8-bit byte).
1410
1411
1412\subsection{The UTF8String type}
1413
1414This is the character string which encodes the full Unicode range
1415(4 bytes) using multibyte character sequences.
1416
1417
1418\subsection{The NumericString type}
1419
1420This type represents the character string with the alphabet consisting
Lev Walkin464166c2010-11-09 08:34:38 -08001421of numbers (``0'' to ``9'') and a space.
Lev Walkined44bf42010-11-08 02:04:55 -08001422
1423
1424\subsection{The PrintableString type}
1425
Lev Walkin464166c2010-11-09 08:34:38 -08001426The character string with the following alphabet: space, ``\textbf{'}''
1427(single quote), ``\textbf{(}'', ``\textbf{)}'', ``\textbf{+}'',
1428``\textbf{,}'' (comma), ``\textbf{-}'', ``\textbf{.}'', ``\textbf{/}'',
1429digits (``0'' to ``9''), ``\textbf{:}'', ``\textbf{=}'', ``\textbf{?}'',
1430upper-case and lower-case letters (``A'' to ``Z'' and ``a''
1431to ``z'').
Lev Walkined44bf42010-11-08 02:04:55 -08001432
1433
1434\subsection{The VisibleString type}
1435
1436The character string with the alphabet which is more or less a subset
Lev Walkin464166c2010-11-09 08:34:38 -08001437of ASCII between the space and the ``\textbf{\textasciitilde{}}''
Lev Walkined44bf42010-11-08 02:04:55 -08001438symbol (tilde).
1439
1440Alternatively, the alphabet may be described as the PrintableString
Lev Walkin464166c2010-11-09 08:34:38 -08001441alphabet presented earlier, plus the following characters: ``\textbf{!}'',
1442``\textbf{``}'', ``\textbf{\#}'', ``\textbf{\$}'', ``\textbf{\%}'',
1443``\textbf{\&}'', ``\textbf{{*}}'', ``\textbf{;}'', ``\textbf{<}'',
1444``\textbf{>}'', ``\textbf{{[}}'', ``\textbf{\textbackslash{}}'',
1445``\textbf{{]}}'', ``\textbf{\textasciicircum{}}'', ``\textbf{\_}'',
1446``\textbf{`}`` (single left quote), ``\textbf{\{}'', ``\textbf{|}'',
1447``\textbf{\}}'', ``\textbf{\textasciitilde{}}''.
Lev Walkined44bf42010-11-08 02:04:55 -08001448
1449
1450\section{ASN.1 Constructed Types}
1451
1452
1453\subsection{The SEQUENCE type}
1454
1455This is an ordered collection of other simple or constructed types.
Lev Walkin464166c2010-11-09 08:34:38 -08001456The SEQUENCE constructed type resembles the C ``struct'' statement.
Lev Walkined44bf42010-11-08 02:04:55 -08001457\begin{lyxcode}
1458Address~::=~SEQUENCE~\{
1459
1460~~~~-{}-~The~apartment~number~may~be~omitted
1461
1462~~~~apartmentNumber~~~~~~NumericString~OPTIONAL,
1463
1464~~~~streetName~~~~~~~~~~~PrintableString,
1465
1466~~~~cityName~~~~~~~~~~~~~PrintableString,
1467
1468~~~~stateName~~~~~~~~~~~~PrintableString,
1469
1470~~~~-{}-~This~one~may~be~omitted~too
1471
1472~~~~zipNo~~~~~~~~~~~~~~~~NumericString~OPTIONAL
1473
1474\}
1475\end{lyxcode}
1476
1477\subsection{The SET type}
1478
1479This is a collection of other simple or constructed types. Ordering
1480is not important. The data may arrive in the order which is different
1481from the order of specification. Data is encoded in the order not
1482necessarily corresponding to the order of specification.
1483
1484
1485\subsection{The CHOICE type}
1486
1487This type is just a choice between the subtypes specified in it. The
1488CHOICE type contains at most one of the subtypes specified, and it
1489is always implicitly known which choice is being decoded or encoded.
Lev Walkin464166c2010-11-09 08:34:38 -08001490This one resembles the C ``union'' statement.
Lev Walkined44bf42010-11-08 02:04:55 -08001491
1492The following type defines a response code, which may be either an
Lev Walkin464166c2010-11-09 08:34:38 -08001493integer code or a boolean ``true''/``false'' code.
Lev Walkined44bf42010-11-08 02:04:55 -08001494\begin{lyxcode}
1495ResponseCode~::=~CHOICE~\{
1496
1497~~~~intCode~~~~INTEGER,
1498
1499~~~~boolCode~~~BOOLEAN
1500
1501\}
1502
1503
1504\end{lyxcode}
1505
1506\subsection{The SEQUENCE OF type}
1507
1508This one is the list (array) of simple or constructed types:
1509\begin{lyxcode}
1510-{}-~Example~1
1511
1512ManyIntegers~::=~SEQUENCE~OF~INTEGER
1513
1514~
1515
1516-{}-~Example~2
1517
1518ManyRectangles~::=~SEQUENCE~OF~Rectangle
1519
1520~
1521
1522-{}-~More~complex~example:
1523
1524-{}-~an~array~of~structures~defined~in~place.
1525
1526ManyCircles~::=~SEQUENCE~OF~SEQUENCE~\{
1527
1528~~~~~~~~~~~~~~~~~~~~~~~~~~~~radius~INTEGER
1529
1530~~~~~~~~~~~~~~~~~~~~~~~~~~~~\}
1531\end{lyxcode}
1532
1533\subsection{The SET OF type}
1534
1535The SET OF type models the bag of structures. It resembles the SEQUENCE
1536OF type, but the order is not important: i.e. the elements may arrive
1537in the order which is not necessarily the same as the in-memory order
1538on the remote machines.
1539\begin{lyxcode}
1540-{}-~A~set~of~structures~defined~elsewhere
1541
1542SetOfApples~::~SET~OF~Apple
1543
1544~
1545
1546-{}-~Set~of~integers~encoding~the~kind~of~a~fruit
1547
1548FruitBag~::=~SET~OF~ENUMERATED~\{~apple,~orange~\}\end{lyxcode}
1549\begin{thebibliography}{ITU-T/ASN.1}
1550\bibitem[ASN1C]{ASN1C}The Open Source ASN.1 Compiler. \url{http://lionet.info/asn1c}
1551
1552\bibitem[AONL]{AONL}Online ASN.1 Compiler. \url{http://lionet.info/asn1c/asn1c.cgi}
1553
1554\bibitem[Dub00]{Dub00}Olivier Dubuisson --- \emph{ASN.1 Communication
Lev Walkin464166c2010-11-09 08:34:38 -08001555between heterogeneous systems}~---~Morgan Kaufmann Publishers, 2000.
Lev Walkined44bf42010-11-08 02:04:55 -08001556\url{http://asn1.elibel.tm.fr/en/book/}. ISBN:0-12-6333361-0.
1557
Lev Walkin464166c2010-11-09 08:34:38 -08001558\bibitem[ITU-T/ASN.1]{ITU-T/ASN.1}ITU-T Study Group 17 --- Languages
Lev Walkined44bf42010-11-08 02:04:55 -08001559for Telecommunication Systems \url{http://www.itu.int/ITU-T/studygroups/com17/languages/}
1560\end{thebibliography}
1561
1562\end{document}