blob: 846f5b2bfd137cabd4b93b754dc9dcf26745ab5e [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 Walkin464166c2010-11-09 08:34:38 -0800263\midrule\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800264\textbf{\small Codecs Generation Options} & \textbf{\small Description}\tabularnewline
Lev Walkin464166c2010-11-09 08:34:38 -0800265\midrule
Lev Walkined44bf42010-11-08 02:04:55 -0800266{\small -gen-PER} & {\small Generate Packed Encoding Rules (PER) support code.}\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800267{\small -pdu=}\emph{\small auto} & {\small Generate PDU tables by discovering Protocol Data Units automatically.}\tabularnewline
Lev Walkin464166c2010-11-09 08:34:38 -0800268\midrule\tabularnewline
Lev Walkined44bf42010-11-08 02:04:55 -0800269\textbf{\small Output Options} & \textbf{\small Description}\tabularnewline
Lev Walkin464166c2010-11-09 08:34:38 -0800270\midrule
Lev Walkined44bf42010-11-08 02:04:55 -0800271{\small -print-constraints} & {\small When -EF are also specified, this option forces the compiler
272to explain its internal understanding of subtype constraints.}\tabularnewline
Lev Walkin464166c2010-11-09 08:34:38 -0800273{\small -print-lines} & {\small Generate ``-{}- \#line'' comments
Lev Walkined44bf42010-11-08 02:04:55 -0800274in -E output.}\tabularnewline
Lev Walkin464166c2010-11-09 08:34:38 -0800275\bottomrule
Lev Walkined44bf42010-11-08 02:04:55 -0800276\end{longtable}
Lev Walkin464166c2010-11-09 08:34:38 -0800277\renewcommand{\arraystretch}{1}
Lev Walkined44bf42010-11-08 02:04:55 -0800278
279
280\chapter{Using the ASN.1 Compiler}
281
282
283\section[Invoking the helper code]{Invoking the ASN.1 helper code}
284
285First of all, you should include one or more header files into your
286application. Typically, it is enough to include the header file of
287the main PDU type. For our Rectangle module, including the Rectangle.h
288file is sufficient:
289\begin{lyxcode}
290\#include~<Rectangle.h>
291\end{lyxcode}
292The header files defines the C structure corresponding to the ASN.1
293definition of a rectangle and the declaration of the ASN.1 type descriptor,
294which is used as an argument to most of the functions provided by
295the ASN.1 module. For example, here is the code which frees the Rectangle\_t
296structure:
297\begin{lyxcode}
298Rectangle\_t~{*}rect~=~...;
299
300~
301
Lev Walkin464166c2010-11-09 08:34:38 -0800302asn\_DEF\_Rectangle.free\_struct(\&asn\_DEF\_Rectangle, rect,~0);
Lev Walkined44bf42010-11-08 02:04:55 -0800303\end{lyxcode}
304This code defines a \emph{rect} pointer which points to the Rectangle\_t
305structure which needs to be freed. The second line invokes the generic
306\emph{free\_struct()} routine created specifically for this Rectangle\_t
307structure. The \emph{asn\_DEF\_Rectangle} is the type descriptor,
308which holds a collection of routines to deal with the Rectangle\_t
309structure.
310
311The following member functions of the asn\_DEF\_Rectangle type descriptor
312are of interest:
313\begin{description}
314\item [{ber\_decoder}] This is the generic \emph{restartable}%
315\footnote{Restartable means that if the decoder encounters the end of the buffer,
316it will fail, but may later be invoked again with the rest of the
317buffer to continue decoding.%
318} BER decoder (Basic Encoding Rules). This decoder would create and/or
319fill the target structure for you. See Section \vref{sub:Decoding-BER}.
320\item [{der\_encoder}] This is the generic DER encoder (Distinguished Encoding
321Rules). This encoder will take the target structure and encode it
322into a series of bytes. See Section \vref{sub:Encoding-DER}. NOTE:
323DER encoding is a subset of BER. Any BER decoder should be able to
324handle DER input.
325\item [{xer\_decoder}] This is the generic XER decoder. It takes both BASIC-XER
326or CANONICAL-XER encodings and deserializes the data into a local,
327machine-dependent representation. See Section \vref{sub:Decoding-XER}.
328\item [{xer\_encoder}] This is the XER encoder (XML Encoding Rules). This
329encoder will take the target structure and represent it as an XML
330(text) document using either BASIC-XER or CANONICAL-XER encoding rules.
331See Section \vref{sub:Encoding-XER}.
332\item [{uper\_decoder}] This is the Unaligned PER decoder.
333\item [{uper\_encoder}] This is the Unaligned Basic PER encoder. This encoder
334will take the target structure and encode it into a series of bytes.
335\item [{check\_constraints}] Check that the contents of the target structure
336are semantically valid and constrained to appropriate implicit or
337explicit subtype constraints. See Section \vref{sub:Validating-the-target}.
338\item [{print\_struct}] This function convert the contents of the passed
339target structure into human readable form. This form is not formal
340and cannot be converted back into the structure, but it may turn out
341to be useful for debugging or quick-n-dirty printing. See Section
342\vref{sub:Printing-the-target}.
343\item [{free\_struct}] This is a generic disposal which frees the target
344structure. See Section \vref{sub:Freeing-the-target}.
345\end{description}
346Each of the above function takes the type descriptor (\emph{asn\_DEF\_\ldots{}})
347and the target structure (\emph{rect}, in the above example).
348
349
350\subsection{\label{sub:Decoding-BER}Decoding BER}
351
352The Basic Encoding Rules describe the most widely used (by the ASN.1
353community) way to encode and decode a given structure in a machine-independent
354way. Several other encoding rules (CER, DER) define a more restrictive
355versions of BER, so the generic BER parser is also capable of decoding
356the data encoded by CER and DER encoders. The opposite is not true.
357
358\emph{The ASN.1 compiler provides the generic BER decoder which is
359implicitly capable of decoding BER, CER and DER encoded data.}
360
361The decoder is restartable (stream-oriented), which means that in
362case the buffer has less data than it is expected, the decoder will
363process whatever there is available and ask for more data to be provided.
364Please note that the decoder may actually process less data than it
365was given in the buffer, which means that you must be able to make
366the next buffer contain the unprocessed part of the previous buffer.
367
368Suppose, you have two buffers of encoded data: 100 bytes and 200 bytes.
369\begin{itemize}
370\item You may concatenate these buffers and feed the BER decoder with 300
371bytes of data, or
372\item You may feed it the first buffer of 100 bytes of data, realize that
373the ber\_decoder consumed only 95 bytes from it and later feed the
374decoder with 205 bytes buffer which consists of 5 unprocessed bytes
375from the first buffer and the additional 200 bytes from the second
376buffer.
377\end{itemize}
378This is not as convenient as it could be (like, the BER encoder could
379consume the whole 100 bytes and keep these 5 bytes in some temporary
380storage), but in case of existing stream based processing it might
381actually fit well into existing algorithm. Suggestions are welcome.
382
383Here is the simplest example of BER decoding.
384\begin{lyxcode}
385Rectangle\_t~{*}
386
387simple\_deserializer(const~void~{*}buffer,~size\_t~buf\_size)~\{
388
389~~~~Rectangle\_t~{*}rect~=~0;~~~~/{*}~Note~this~0!~{*}/
390
391~~~~asn\_dec\_rval\_t~rval;
392
393~
394
395~~~~rval~=~\textbf{asn\_DEF\_Rectangle.ber\_decoder}(0,
396
397~~~~~~~~~~\&asn\_DEF\_Rectangle,
398
399~~~~~~~~~~(void~{*}{*})\&rect,
400
401~~~~~~~~~~buffer,~buf\_size,
402
403~~~~~~~~~~0);
404
405~
406
407~~~~if(rval\textbf{.code}~==~RC\_OK)~\{
408
409~~~~~~~~return~rect;~~~~~~~~~~/{*}~Decoding~succeeded~{*}/
410
411~~~~\}~else~\{
412
413~~~~~~~~/{*}~Free~partially~decoded~rect~{*}/
414
Lev Walkin464166c2010-11-09 08:34:38 -0800415~~~~~~~~asn\_DEF\_Rectangle.free\_struct(\&asn\_DEF\_Rectangle,~rect,~0);
Lev Walkined44bf42010-11-08 02:04:55 -0800416
417~~~~~~~~return~0;
418
419~~~~\}
420
421\}
422\end{lyxcode}
423The code above defines a function, \emph{simple\_deserializer}, which
424takes a buffer and its length and is expected to return a pointer
425to the Rectangle\_t structure. Inside, it tries to convert the bytes
426passed into the target structure (rect) using the BER decoder and
427returns the rect pointer afterwards. If the structure cannot be deserialized,
428it frees the memory which might be left allocated by the unfinished
429\emph{ber\_decoder} routine and returns 0 (no data). (This \textbf{freeing
430is necessary} because the ber\_decoder is a restartable procedure,
431and may fail just because there is more data needs to be provided
432before decoding could be finalized). The code above obviously does
433not take into account the way the \emph{ber\_decoder()} failed, so
434the freeing is necessary because the part of the buffer may already
435be decoded into the structure by the time something goes wrong.
436
437A little less wordy would be to invoke a globally available \emph{ber\_decode()}
438function instead of dereferencing the asn\_DEF\_Rectangle type descriptor:
439\begin{lyxcode}
440rval~=~ber\_decode(0,~\&asn\_DEF\_Rectangle,~(void~{*}{*})\&rect,
441
442~~~~buffer,~buf\_size);
443\end{lyxcode}
444Note that the initial (asn\_DEF\_Rectangle.ber\_decoder) reference
445is gone, and also the last argument (0) is no longer necessary.
446
447These two ways of BER decoder invocations are fully equivalent.
448
449The BER de\emph{coder} may fail because of (\emph{the following RC\_\ldots{}
450codes are defined in ber\_decoder.h}):
451\begin{itemize}
452\item RC\_WMORE: There is more data expected than it is provided (stream
453mode continuation feature);
454\item RC\_FAIL: General failure to decode the buffer;
455\item \ldots{} other codes may be defined as well.
456\end{itemize}
457Together with the return code (.code) the asn\_dec\_rval\_t type contains
458the number of bytes which is consumed from the buffer. In the previous
459hypothetical example of two buffers (of 100 and 200 bytes), the first
460call to ber\_decode() would return with .code = RC\_WMORE and .consumed
461= 95. The .consumed field of the BER decoder return value is \textbf{always}
462valid, even if the decoder succeeds or fails with any other return
463code.
464
Lev Walkin464166c2010-11-09 08:34:38 -0800465Look into ber\_decoder.h for the precise definition of ber\_decode()
Lev Walkined44bf42010-11-08 02:04:55 -0800466and related types.
467
468
469\subsection{\label{sub:Encoding-DER}Encoding DER}
470
471The Distinguished Encoding Rules is the \emph{canonical} variant of
472BER encoding rules. The DER is best suited to encode the structures
473where all the lengths are known beforehand. This is probably exactly
474how you want to encode: either after a BER decoding or after a manual
475fill-up, the target structure contains the data which size is implicitly
476known before encoding. Among other uses, the DER encoding is used
477to encode X.509 certificates.
478
479As with BER decoder, the DER encoder may be invoked either directly
480from the ASN.1 type descriptor (asn\_DEF\_Rectangle) or from the stand-alone
481function, which is somewhat simpler:
482\begin{lyxcode}
483~
484
485/{*}
486
487~{*}~This~is~the~serializer~itself,
488
489~{*}~it~supplies~the~DER~encoder~with~the
490
491~{*}~pointer~to~the~custom~output~function.
492
493~{*}/
494
495ssize\_t
496
497simple\_serializer(FILE~{*}ostream,~Rectangle\_t~{*}rect)~\{
498
499~~~~asn\_enc\_rval\_t~er;~~/{*}~Encoder~return~value~{*}/
500
501~
502
503~~~~er~=~der\_encode(\&asn\_DEF\_Rect,~rect,
504
505~~~~~~~~write\_stream,~ostream);
506
507~~~~if(er.\textbf{encoded}~==~-1)~\{
508
509~~~~~~~~/{*}
510
511~~~~~~~~~{*}~Failed~to~encode~the~rectangle~data.
512
513~~~~~~~~~{*}/
514
515~~~~~~~~fprintf(stderr,~''Cannot~encode~\%s:~\%s\textbackslash{}n'',
516
Lev Walkin464166c2010-11-09 08:34:38 -0800517~~~~~~~~~~~~er.\textbf{failed\_type}->name, strerror(errno));
Lev Walkined44bf42010-11-08 02:04:55 -0800518
519~~~~~~~~return~-1;
520
521~~~~\}~else~\{
522
523~~~~~~~~/{*}~Return~the~number~of~bytes~{*}/
524
525~~~~~~~~return~er.encoded;
526
527~~~~\}
528
529\}
530\end{lyxcode}
531As you see, the DER encoder does not write into some sort of buffer
532or something. It just invokes the custom function (possible, multiple
533times) which would save the data into appropriate storage. The optional
534argument \emph{app\_key} is opaque for the DER encoder code and just
535used by \emph{\_write\_stream()} as the pointer to the appropriate
536output stream to be used.
537
538If the custom write function is not given (passed as 0), then the
539DER encoder will essentially do the same thing (i.e., encode the data)
540but no callbacks will be invoked (so the data goes nowhere). It may
541prove useful to determine the size of the structure's encoding before
542actually doing the encoding%
543\footnote{It is actually faster too: the encoder might skip over some computations
544which aren't important for the size determination.%
545}.
546
Lev Walkin464166c2010-11-09 08:34:38 -0800547Look into der\_encoder.h for the precise definition of der\_encode()
Lev Walkined44bf42010-11-08 02:04:55 -0800548and related types.
549
550
551\subsection{\label{sub:Encoding-XER}Encoding XER}
552
553The XER stands for XML Encoding Rules, where XML, in turn, is eXtensible
554Markup Language, a text-based format for information exchange. The
555encoder routine API comes in two flavors: stdio-based and callback-based.
556With the callback-based encoder, the encoding process is very similar
557to the DER one, described in Section \vref{sub:Encoding-DER}. The
558following example uses the definition of write\_stream() from up there.
559\begin{lyxcode}
560/{*}
561
562~{*}~This~procedure~generates~the~XML~document
563
564~{*}~by~invoking~the~XER~encoder.
565
566~{*}~NOTE:~Do~not~copy~this~code~verbatim!
567
568~{*}~~~~~~~If~the~stdio~output~is~necessary,
569
570~{*}~~~~~~~use~the~xer\_fprint()~procedure~instead.
571
572~{*}~~~~~~~See~Section~\vref{sub:Printing-the-target}.
573
574~{*}/
575
576int
577
578print\_as\_XML(FILE~{*}ostream,~Rectangle\_t~{*}rect)~\{
579
580~~~~asn\_enc\_rval\_t~er;~~/{*}~Encoder~return~value~{*}/
581
582~
583
584~~~~er~=~xer\_encode(\&asn\_DEF\_Rectangle,~rect,
585
586~~~~~~~~XER\_F\_BASIC,~/{*}~BASIC-XER~or~CANONICAL-XER~{*}/
587
588~~~~~~~~write\_stream,~ostream);
589
590~
591
592~~~~return~(er.encoded~==~-1)~?~-1~:~0;
593
594\}
595\end{lyxcode}
Lev Walkin464166c2010-11-09 08:34:38 -0800596Look into xer\_encoder.h for the precise definition of xer\_encode()
Lev Walkined44bf42010-11-08 02:04:55 -0800597and related types.
598
599See Section \ref{sub:Printing-the-target} for the example of stdio-based
600XML encoder and other pretty-printing suggestions.
601
602
603\subsection{\label{sub:Decoding-XER}Decoding XER}
604
605The data encoded using the XER rules can be subsequently decoded using
606the xer\_decode() API call:
607\begin{lyxcode}
608Rectangle\_t~{*}
609
610XML\_to\_Rectangle(const~void~{*}buffer,~size\_t~buf\_size)~\{
611
612~~~~Rectangle\_t~{*}rect~=~0;~/{*}~Note~this~0!~{*}/
613
614~~~~asn\_dec\_rval\_t~rval;
615
616~~
617
618~~~~rval~=~xer\_decode(0,~\&asn\_DEF\_Rectangle,~(void~{*}{*})\&rect,
619
620~~~~~~~~buffer,~buf\_size);
621
622~~~~if(rval\textbf{.code}~==~RC\_OK)~\{
623
624~~~~~~~~return~rect;~~~~~~~~~~/{*}~Decoding~succeeded~{*}/
625
626~~~~\}~else~\{
627
628~~~~~~~~/{*}~Free~partially~decoded~rect~{*}/
629
Lev Walkin464166c2010-11-09 08:34:38 -0800630~~~~~~~~asn\_DEF\_Rectangle.free\_struct(\&asn\_DEF\_Rectangle,~rect,~0);
Lev Walkined44bf42010-11-08 02:04:55 -0800631
632~~~~~~~~return~0;
633
634~~~~\}
635
636\}
637\end{lyxcode}
638The decoder takes both BASIC-XER and CANONICAL-XER encodings.
639
640The decoder shares its data consumption properties with BER decoder;
641please read the Section \vref{sub:Decoding-BER} to know more.
642
Lev Walkin464166c2010-11-09 08:34:38 -0800643Look into xer\_decoder.h for the precise definition of xer\_decode()
Lev Walkined44bf42010-11-08 02:04:55 -0800644and related types.
645
646
647\subsection{\label{sub:Validating-the-target}Validating the target structure}
648
649Sometimes the target structure needs to be validated. For example,
650if the structure was created by the application (as opposed to being
651decoded from some external source), some important information required
652by the ASN.1 specification might be missing. On the other hand, the
653successful decoding of the data from some external source does not
654necessarily mean that the data is fully valid either. It might well
655be the case that the specification describes some subtype constraints
656that were not taken into account during decoding, and it would actually
657be useful to perform the last check when the data is ready to be encoded
658or when the data has just been decoded to ensure its validity according
659to some stricter rules.
660
661The asn\_check\_constraints() function checks the type for various
662implicit and explicit constraints. It is recommended to use asn\_check\_constraints()
663function after each decoding and before each encoding.
664
Lev Walkin464166c2010-11-09 08:34:38 -0800665Look into constraints.h for the precise definition of asn\_check\_constraints()
Lev Walkined44bf42010-11-08 02:04:55 -0800666and related types.
667
668
669\subsection{\label{sub:Printing-the-target}Printing the target structure}
670
671There are two ways to print the target structure: either invoke the
672print\_struct member of the ASN.1 type descriptor, or using the asn\_fprint()
673function, which is a simpler wrapper of the former:
674\begin{lyxcode}
675asn\_fprint(stdout,~\&asn\_DEF\_Rectangle,~rect);
676\end{lyxcode}
Lev Walkin464166c2010-11-09 08:34:38 -0800677Look into constr\_TYPE.h for the precise definition of asn\_fprint()
Lev Walkined44bf42010-11-08 02:04:55 -0800678and related types.
679
680Another practical alternative to this custom format printing would
681be to invoke XER encoder. The default BASIC-XER encoder performs reasonable
682formatting for the output to be useful and human readable. To invoke
683the XER decoder in a manner similar to asn\_fprint(), use the xer\_fprint()
684call:
685\begin{lyxcode}
686xer\_fprint(stdout,~\&asn\_DEF\_Rectangle,~rect);
687\end{lyxcode}
688See Section \vref{sub:Encoding-XER} for XML-related details.
689
690
691\subsection{\label{sub:Freeing-the-target}Freeing the target structure}
692
693Freeing the structure is slightly more complex than it may seem to.
694When the ASN.1 structure is freed, all the members of the structure
695and their submembers are recursively freed as well. But it might not
696be feasible to free the structure itself. Consider the following case:
697\begin{lyxcode}
698struct~my\_figure~\{~~~~~~~/{*}~The~custom~structure~{*}/
699
700~~~~int~flags;~~~~~~~~~~~/{*}~<some~custom~member>~{*}/
701
702~~~~/{*}~The~type~is~generated~by~the~ASN.1~compiler~{*}/
703
704~~~~\emph{Rectangle\_t~rect;}
705
706~~~~/{*}~other~members~of~the~structure~{*}/
707
708\};
709\end{lyxcode}
710In this example, the application programmer defined a custom structure
711with one ASN.1-derived member (rect). This member is not a reference
712to the Rectangle\_t, but an in-place inclusion of the Rectangle\_t
713structure. If the freeing is necessary, the usual procedure of freeing
714everything must not be applied to the \&rect pointer itself, because
715it does not point to the memory block directly allocated by the memory
716allocation routine, but instead lies within a block allocated for
717the my\_figure structure.
718
719To solve this problem, the free\_struct routine has the additional
720argument (besides the obvious type descriptor and target structure
721pointers), which is the flag specifying whether the outer pointer
722itself must be freed (0, default) or it should be left intact (non-zero
723value).
724\begin{lyxcode}
725\textbf{/{*}~1.~Rectangle\_t~is~defined~within~my\_figure~{*}/}
726
727struct~my\_figure~\{
728
729~~~~Rectangle\_t~rect;
730
731\}~{*}mf~=~\textbf{...};
732
733/{*}
734
735~{*}~Freeing~the~Rectangle\_t
736
737~{*}~without~freeing~the~mf->rect~area
738
739~{*}/
740
741asn\_DEF\_Rectangle.free\_struct(
742
743~~~~\&asn\_DEF\_Rectangle,~\&mf->rect,~\textbf{1}~\textbf{/{*}~!free~{*}/});
744
745~~~~
746
747~~
748
749\textbf{/{*}~2.~Rectangle\_t~is~a~stand-alone~pointer~{*}/}
750
751Rectangle\_t~{*}rect~=~\textbf{...};
752
753/{*}
754
755~{*}~Freeing~the~Rectangle\_t
756
757~{*}~and~freeing~the~rect~pointer
758
759~{*}/
760
761asn\_DEF\_Rectangle.free\_struct(
762
763~~~~\&asn\_DEF\_Rectangle,~rect,~\textbf{0}~\textbf{/{*}~free~the~pointer~too~{*}/});
764\end{lyxcode}
765It is safe to invoke the \emph{free\_struct} function with the target
766structure pointer set to 0 (NULL), the function will do nothing.
767
768For the programmer's convenience, the following macros are available:
769\begin{lyxcode}
770ASN\_STRUCT\_FREE(asn\_DEF,~ptr);
771
772ASN\_STRUCT\_FREE\_CONTENTS\_ONLY(asn\_DEF,~ptr);
773\end{lyxcode}
774These macros bear the same semantics as the \emph{free\_struct} function
775invocation, discussed above.
776
777
778\chapter{\label{cha:Step-by-step-examples}Step by step examples}
779
780
Lev Walkin464166c2010-11-09 08:34:38 -0800781\section{A ``Rectangle'' Encoder}
Lev Walkined44bf42010-11-08 02:04:55 -0800782
783This example will help you create a simple BER and XER encoder of
Lev Walkin464166c2010-11-09 08:34:38 -0800784a ``Rectangle'' type used throughout this document.
Lev Walkined44bf42010-11-08 02:04:55 -0800785\begin{enumerate}
786\item Create a file named \textbf{rectangle.asn1} with the following contents:
787
788\begin{lyxcode}
789RectangleModule1~DEFINITIONS~::=
790
791BEGIN
792
793~
794
795Rectangle~::=~SEQUENCE~\{
796
797~~~~height~~INTEGER,
798
799~~~~width~~~INTEGER
800
801\}
802
803~
804
805END
806\end{lyxcode}
807\item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}:
808
809\begin{lyxcode}
810\emph{asn1c~-fnative-types}~\textbf{rectangle.asn1}
811\end{lyxcode}
812\item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading
813the \textbf{rectangle.asn1} file into the Web form and unpacking the
814produced archive on your computer.
815\item By this time, you should have gotten multiple files in the current
816directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}.
817\item Create a main() routine which creates the Rectangle\_t structure in
818memory and encodes it using BER and XER encoding rules. Let's name
819the file \textbf{main.c}:\clearpage{}
820
821\begin{lyxcode}
822{\small \#include~<stdio.h>}{\small \par}
823
824{\small \#include~<sys/types.h>}{\small \par}
825
826{\small \#include~<Rectangle.h>~~~/{*}~Rectangle~ASN.1~type~~{*}/}{\small \par}
827
828~
829
830{\small /{*}}{\small \par}
831
832{\small{}~{*}~This~is~a~custom~function~which~writes~the}{\small \par}
833
834{\small{}~{*}~encoded~output~into~some~FILE~stream.}{\small \par}
835
836{\small{}~{*}/}{\small \par}
837
838{\small static~int}{\small \par}
839
840{\small write\_out(const~void~{*}buffer,~size\_t~size,~void~{*}app\_key)~\{}{\small \par}
841
842{\small{}~~~~FILE~{*}out\_fp~=~app\_key;}{\small \par}
843
844{\small{}~~~~size\_t~wrote;}{\small \par}
845
846{\small{}~}{\small \par}
847
848{\small{}~~~~wrote~=~fwrite(buffer,~1,~size,~out\_fp);}{\small \par}
849
850{\small{}~}{\small \par}
851
852{\small{}~~~~return~(wrote~==~size)~?~0~:~-1;}{\small \par}
853
854{\small \}}{\small \par}
855
856~
857
858{\small int~main(int~ac,~char~{*}{*}av)~\{}{\small \par}
859
860{\small{}~~~~Rectangle\_t~{*}rectangle;~/{*}~Type~to~encode~~~~~~~~{*}/}{\small \par}
861
862{\small{}~~~~asn\_enc\_rval\_t~ec;~~~~~~/{*}~Encoder~return~value~~{*}/}{\small \par}
863
864{\small{}~}{\small \par}
865
866{\small{}~~~~/{*}~Allocate~the~Rectangle\_t~{*}/}{\small \par}
867
868{\small{}~~~~rectangle~=~calloc(1,~sizeof(Rectangle\_t));~/{*}~not~malloc!~{*}/}{\small \par}
869
870{\small{}~~~~if(!rectangle)~\{}{\small \par}
871
872{\small{}~~~~~~perror(''calloc()~failed'');}{\small \par}
873
874{\small{}~~~~~~exit(71);~/{*}~better,~EX\_OSERR~{*}/}{\small \par}
875
876{\small{}~~~~\}}{\small \par}
877
878{\small{}~}{\small \par}
879
880{\small{}~~~~/{*}~Initialize~the~Rectangle~members~{*}/}{\small \par}
881
882{\small{}~~~~rectangle->height~=~42;~~/{*}~any~random~value~{*}/}{\small \par}
883
884{\small{}~~~~rectangle->width~~=~23;~~/{*}~any~random~value~{*}/}{\small \par}
885
886{\small{}~~~~~}{\small \par}
887
888{\small{}~~~~/{*}~BER~encode~the~data~if~filename~is~given~{*}/}{\small \par}
889
890{\small{}~~~~if(ac~<~2)~\{}{\small \par}
891
892{\small{}~~~~~~fprintf(stderr,~''Specify~filename~for~BER~output\textbackslash{}n'');}{\small \par}
893
894{\small{}~~~~\}~else~\{}{\small \par}
895
896{\small{}~~~~~~const~char~{*}filename~=~av{[}1{]};}{\small \par}
897
898{\small{}~~~~~~FILE~{*}fp~=~fopen(filename,~''wb'');~~~/{*}~for~BER~output~{*}/}{\small \par}
899
900~
901
902{\small{}~~~~~~if(!fp)~\{}{\small \par}
903
904{\small{}~~~~~~~~perror(filename);}{\small \par}
905
906{\small{}~~~~~~~~exit(71);~/{*}~better,~EX\_OSERR~{*}/}{\small \par}
907
908{\small{}~~~~~~\}}{\small \par}
909
910{\small{}~~}{\small \par}
911
912{\small{}~~~~~~/{*}~Encode~the~Rectangle~type~as~BER~(DER)~{*}/}{\small \par}
913
914{\small{}~~~~~~ec~=~der\_encode(\&asn\_DEF\_Rectangle,}{\small \par}
915
916{\small{}~~~~~~~~~~~~rectangle,~write\_out,~fp);}{\small \par}
917
918{\small{}~~~~~~fclose(fp);}{\small \par}
919
920{\small{}~~~~~~if(ec.encoded~==~-1)~\{}{\small \par}
921
922{\small{}~~~~~~~~fprintf(stderr,}{\small \par}
923
924{\small{}~~~~~~~~~~''Could~not~encode~Rectangle~(at~\%s)\textbackslash{}n'',}{\small \par}
925
926{\small{}~~~~~~~~~~ec.failed\_type~?~ec.failed\_type->name~:~''unknown'');}{\small \par}
927
928{\small{}~~~~~~~~exit(65);~/{*}~better,~EX\_DATAERR~{*}/}{\small \par}
929
930{\small{}~~~~~~\}~else~\{}{\small \par}
931
932{\small{}~~~~~~~~fprintf(stderr,~''Created~\%s~with~BER~encoded~Rectangle\textbackslash{}n'',}{\small \par}
933
934{\small{}~~~~~~~~~~filename);}{\small \par}
935
936{\small{}~~~~~~\}}{\small \par}
937
938{\small{}~~~~\}}{\small \par}
939
940{\small{}~}{\small \par}
941
942{\small{}~~~~/{*}~Also~print~the~constructed~Rectangle~XER~encoded~(XML)~{*}/}{\small \par}
943
944{\small{}~~~~xer\_fprint(stdout,~\&asn\_DEF\_Rectangle,~rectangle);}{\small \par}
945
946{\small{}~}{\small \par}
947
948{\small{}~~~~return~0;~/{*}~Encoding~finished~successfully~{*}/}{\small \par}
949
950{\small \}}{\small \par}
951\end{lyxcode}
952\item Compile all files together using C compiler (varies by platform):
953
954\begin{lyxcode}
955\emph{cc~-I.~-o}~\textbf{\emph{rencode}}~\emph{{*}.c}
956\end{lyxcode}
957\item Voila! You have just created the BER and XER encoder of a Rectangle
958type, named \textbf{rencode}!
959\end{enumerate}
960\clearpage{}
961
962
Lev Walkin464166c2010-11-09 08:34:38 -0800963\section{\label{sec:A-Rectangle-Decoder}A ``Rectangle'' Decoder}
Lev Walkined44bf42010-11-08 02:04:55 -0800964
965This example will help you to create a simple BER decoder of a simple
Lev Walkin464166c2010-11-09 08:34:38 -0800966``Rectangle'' type used throughout this document.
Lev Walkined44bf42010-11-08 02:04:55 -0800967\begin{enumerate}
968\item Create a file named \textbf{rectangle.asn1} with the following contents:
969
970\begin{lyxcode}
971RectangleModule1~DEFINITIONS~::=
972
973BEGIN
974
975~
976
977Rectangle~::=~SEQUENCE~\{
978
979~~~~height~~INTEGER,
980
981~~~~width~~~INTEGER
982
983\}
984
985~
986
987END
988\end{lyxcode}
989\item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}:
990
991\begin{lyxcode}
992\emph{asn1c~-fnative-types}~\textbf{rectangle.asn1}
993\end{lyxcode}
994\item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading
995the \textbf{rectangle.asn1} file into the Web form and unpacking the
996produced archive on your computer.
997\item By this time, you should have gotten multiple files in the current
998directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}.
999\item Create a main() routine which takes the binary input file, decodes
1000it as it were a BER-encoded Rectangle type, and prints out the text
1001(XML) representation of the Rectangle type. Let's name the file \textbf{main.c}:\clearpage{}
1002
1003\begin{lyxcode}
1004{\small \#include~<stdio.h>}{\small \par}
1005
1006{\small \#include~<sys/types.h>}{\small \par}
1007
1008{\small \#include~<Rectangle.h>~~~/{*}~Rectangle~ASN.1~type~~{*}/}{\small \par}
1009
1010{\small{}~}{\small \par}
1011
1012{\small int~main(int~ac,~char~{*}{*}av)~\{}{\small \par}
1013
1014{\small{}~~~~char~buf{[}1024{]};~~~~~~/{*}~Temporary~buffer~~~~~~{*}/}{\small \par}
1015
1016{\small{}~~~~Rectangle\_t~{*}rectangle~=~0;~/{*}~Type~to~decode~{*}/}{\small \par}
1017
1018{\small{}~~~~asn\_dec\_rval\_t~rval;~/{*}~Decoder~return~value~~{*}/}{\small \par}
1019
1020{\small{}~~~~FILE~{*}fp;~~~~~~~~~~~~/{*}~Input~file~handler~~~~{*}/}{\small \par}
1021
1022{\small{}~~~~size\_t~size;~~~~~~~~~/{*}~Number~of~bytes~read~~{*}/}{\small \par}
1023
1024{\small{}~~~~char~{*}filename;~~~~~~/{*}~Input~file~name~{*}/}{\small \par}
1025
1026{\small{}~}{\small \par}
1027
1028{\small{}~~~~/{*}~Require~a~single~filename~argument~{*}/}{\small \par}
1029
1030{\small{}~~~~if(ac~!=~2)~\{}{\small \par}
1031
1032{\small{}~~~~~~fprintf(stderr,~''Usage:~\%s~<file.ber>\textbackslash{}n'',~av{[}0{]});}{\small \par}
1033
1034{\small{}~~~~~~exit(64);~/{*}~better,~EX\_USAGE~{*}/}{\small \par}
1035
1036{\small{}~~~~\}~else~\{}{\small \par}
1037
1038{\small{}~~~~~~filename~=~av{[}1{]};}{\small \par}
1039
1040{\small{}~~~~\}}{\small \par}
1041
1042{\small{}~}{\small \par}
1043
1044{\small{}~~~~/{*}~Open~input~file~as~read-only~binary~{*}/}{\small \par}
1045
1046{\small{}~~~~fp~=~fopen(filename,~''rb'');}{\small \par}
1047
1048{\small{}~~~~if(!fp)~\{}{\small \par}
1049
1050{\small{}~~~~~~perror(filename);}{\small \par}
1051
1052{\small{}~~~~~~exit(66);~/{*}~better,~EX\_NOINPUT~{*}/}{\small \par}
1053
1054{\small{}~~~~\}}{\small \par}
1055
1056{\small{}~~}{\small \par}
1057
1058{\small{}~~~~/{*}~Read~up~to~the~buffer~size~{*}/}{\small \par}
1059
1060{\small{}~~~~size~=~fread(buf,~1,~sizeof(buf),~fp);}{\small \par}
1061
1062{\small{}~~~~fclose(fp);}{\small \par}
1063
1064{\small{}~~~~if(!size)~\{}{\small \par}
1065
1066{\small{}~~~~~~fprintf(stderr,~''\%s:~Empty~or~broken\textbackslash{}n'',~filename);}{\small \par}
1067
1068{\small{}~~~~~~exit(65);~/{*}~better,~EX\_DATAERR~{*}/}{\small \par}
1069
1070{\small{}~~~~\}}{\small \par}
1071
1072{\small{}~}{\small \par}
1073
1074{\small{}~~~~/{*}~Decode~the~input~buffer~as~Rectangle~type~{*}/}{\small \par}
1075
1076{\small{}~~~~rval~=~ber\_decode(0,~\&asn\_DEF\_Rectangle,}{\small \par}
1077
1078{\small{}~~~~~~(void~{*}{*})\&rectangle,~buf,~size);}{\small \par}
1079
1080{\small{}~~~~if(rval.code~!=~RC\_OK)~\{}{\small \par}
1081
1082{\small{}~~~~~~fprintf(stderr,}{\small \par}
1083
1084{\small{}~~~~~~~~''\%s:~Broken~Rectangle~encoding~at~byte~\%ld\textbackslash{}n'',}{\small \par}
1085
1086{\small{}~~~~~~~~filename,~(long)rval.consumed);}{\small \par}
1087
1088{\small{}~~~~~~exit(65);~/{*}~better,~EX\_DATAERR~{*}/}{\small \par}
1089
1090{\small{}~~~~\}}{\small \par}
1091
1092{\small{}~}{\small \par}
1093
1094{\small{}~~~~/{*}~Print~the~decoded~Rectangle~type~as~XML~{*}/}{\small \par}
1095
1096{\small{}~~~~xer\_fprint(stdout,~\&asn\_DEF\_Rectangle,~rectangle);}{\small \par}
1097
1098{\small{}~}{\small \par}
1099
1100{\small{}~~~~return~0;~/{*}~Decoding~finished~successfully~{*}/}{\small \par}
1101
1102{\small \}}{\small \par}
1103\end{lyxcode}
1104\item Compile all files together using C compiler (varies by platform):
1105
1106\begin{lyxcode}
1107\emph{cc~-I.~-o}~\textbf{\emph{rdecode}}~\emph{{*}.c}
1108\end{lyxcode}
1109\item Voila! You have just created the BER decoder of a Rectangle type,
1110named \textbf{rdecode}!
1111\end{enumerate}
1112
1113\chapter{Constraint validation examples}
1114
1115This chapter shows how to define ASN.1 constraints and use the generated
1116validation code.
1117
1118
Lev Walkin464166c2010-11-09 08:34:38 -08001119\section{Adding constraints into ``Rectangle'' type}
Lev Walkined44bf42010-11-08 02:04:55 -08001120
1121This example shows how to add basic constraints to the ASN.1 specification
1122and how to invoke the constraints validation code in your application.
1123\begin{enumerate}
1124\item Create a file named \textbf{rectangle.asn1} with the following contents:
1125
1126\begin{lyxcode}
1127RectangleModuleWithConstraints~DEFINITIONS~::=
1128
1129BEGIN
1130
1131~
1132
1133Rectangle~::=~SEQUENCE~\{
1134
1135~~~~height~~INTEGER~(0..100),~-{}-~Value~range~constraint
1136
1137~~~~width~~~INTEGER~(0..MAX)~~-{}-~Makes~width~non-negative~
1138
1139\}
1140
1141~
1142
1143END
1144\end{lyxcode}
1145\item Compile the file according to procedures shown in the previous chapter.
1146\item Modify the Rectangle type processing routine (you can start with the
1147main() routine shown in the Section \vref{sec:A-Rectangle-Decoder})
1148by placing the following snippet of code \emph{before} encoding and/or
1149\emph{after} decoding the Rectangle type%
1150\footnote{Placing the constraint checking code \emph{before} encoding helps
1151to make sure you know the data is correct and within constraints before
1152sharing the data with anyone else.
1153
1154Placing the constraint checking code \emph{after} decoding, but before
1155any further action depending on the decoded data, helps to make sure
1156the application got the valid contents before making use of it.%
1157}:\clearpage{}
1158
1159\begin{lyxcode}
1160{\small int~ret;~~~~~~~~~~~/{*}~Return~value~{*}/}{\small \par}
1161
1162{\small char~errbuf{[}128{]};~~/{*}~Buffer~for~error~message~{*}/}{\small \par}
1163
1164{\small size\_t~errlen~=~sizeof(errbuf);~~/{*}~Size~of~the~buffer~{*}/}{\small \par}
1165
1166{\small{}~~}{\small \par}
1167
1168{\small /{*}~...~here~may~go~Rectangle~decoding~code~...~{*}/}{\small \par}
1169
1170{\small{}~}{\small \par}
1171
1172{\small ret~=~asn\_check\_constraints(\&asn\_DEF\_Rectangle,}{\small \par}
1173
1174{\small{}~~~~~~~~rectangle,~errbuf,~\&errlen);}{\small \par}
1175
1176{\small /{*}~assert(errlen~<~sizeof(errbuf));~//~you~may~rely~on~that~{*}/}{\small \par}
1177
1178{\small if(ret)~\{}{\small \par}
1179
1180{\small{}~~~~~~~~fprintf(stderr,~''Constraint~validation~failed:~\%s\textbackslash{}n'',}{\small \par}
1181
1182{\small{}~~~~~~~~~~errbuf~~~/{*}~errbuf~is~properly~nul-terminated~{*}/}{\small \par}
1183
1184{\small{}~~~~~~~~);}{\small \par}
1185
1186{\small{}~~~~~~~~/{*}~exit(...);~//~Replace~with~appropriate~action~{*}/}{\small \par}
1187
1188{\small \}}{\small \par}
1189
1190{\small{}~}{\small \par}
1191
1192{\small /{*}~...~here~may~go~Rectangle~encoding~code~...~{*}/}{\small \par}
1193\end{lyxcode}
1194\item Compile the resulting C code as shown in the previous chapters.
1195\item Try to test the constraints checking code by assigning integer value
1196101 to the \textbf{.height} member of the Rectangle structure, or
1197a negative value to the \textbf{.width} member. In either case, the
Lev Walkin464166c2010-11-09 08:34:38 -08001198program should print ``Constraint validation failed'' message, followed
Lev Walkined44bf42010-11-08 02:04:55 -08001199by the short explanation why validation did not succeed.
1200\item Done.
1201\end{enumerate}
1202
1203\part{\label{par:ASN.1-Basics}ASN.1 Basics}
1204
1205
1206\chapter{\label{cha:Abstract-Syntax-Notation:}Abstract Syntax Notation: ASN.1}
1207
1208\emph{This chapter defines some basic ASN.1 concepts and describes
1209several most widely used types. It is by no means an authoritative
1210or complete reference. For more complete ASN.1 description, please
1211refer to Olivier Dubuisson's book \cite{Dub00} or the ASN.1 body
1212of standards itself \cite{ITU-T/ASN.1}.}
1213
1214The Abstract Syntax Notation One is used to formally describe the
1215semantics of data transmitted across the network. Two communicating
1216parties may have different formats of their native data types (i.e.
1217number of bits in the integer type), thus it is important to have
1218a way to describe the data in a manner which is independent from the
1219particular machine's representation. The ASN.1 specifications are
1220used to achieve the following:
1221\begin{itemize}
1222\item The specification expressed in the ASN.1 notation is a formal and
1223precise way to communicate the data semantics to human readers;
1224\item The ASN.1 specifications may be used as input for automatic compilers
1225which produce the code for some target language (C, C++, Java, etc)
1226to encode and decode the data according to some encoding rules (which
1227are also defined by the ASN.1 standard).
1228\end{itemize}
1229Consider the following example:
1230\begin{lyxcode}
1231Rectangle~::=~SEQUENCE~\{
1232
1233~~~~height~~INTEGER,
1234
1235~~~~width~~~INTEGER
1236
1237\}
1238\end{lyxcode}
1239This ASN.1 specification describes a constructed type, \emph{Rectangle},
1240containing two integer fields. This specification may tell the reader
1241that there exists this kind of data structure and that some entity
1242may be prepared to send or receive it. The question on \emph{how}
1243that entity is going to send or receive the \emph{encoded data} is
1244outside the scope of ASN.1. For example, this data structure may be
1245encoded according to some encoding rules and sent to the destination
1246using the TCP protocol. The ASN.1 specifies several ways of encoding
Lev Walkin464166c2010-11-09 08:34:38 -08001247(or ``serializing'', or ``marshaling'') the data: BER, PER, XER
Lev Walkined44bf42010-11-08 02:04:55 -08001248and others, including CER and DER derivatives from BER.
1249
1250The complete specification must be wrapped in a module, which looks
1251like this:
1252\begin{lyxcode}
1253RectangleModule1
1254
1255~~~~\{~iso~org(3)~dod(6)~internet(1)~private(4)
1256
1257~~~~~~enterprise(1)~spelio(9363)~software(1)
1258
1259~~~~~~asn1c(5)~docs(2)~rectangle(1)~1~\}~
1260
1261~~~~DEFINITIONS~AUTOMATIC~TAGS~::=
1262
1263BEGIN
1264
1265~
1266
1267-{}-~This~is~a~comment~which~describes~nothing.
1268
1269Rectangle~::=~SEQUENCE~\{
1270
1271~~~~height~~INTEGER,~~~~~~~~-{}-~Height~of~the~rectangle
1272
1273~~~~width~~~INTEGER~~~~~~~~~-{}-~Width~of~the~rectangle
1274
1275\}
1276
1277~
1278
1279END
1280\end{lyxcode}
1281The module header consists of module name (RectangleModule1), the
Lev Walkin464166c2010-11-09 08:34:38 -08001282module object identifier (\{...\}), a keyword ``DEFINITIONS'', a
1283set of module flags (AUTOMATIC TAGS) and ``::= BEGIN''. The module
1284ends with an ``END'' statement.
Lev Walkined44bf42010-11-08 02:04:55 -08001285
1286
1287\section{Some of the ASN.1 Basic Types}
1288
1289
1290\subsection{The BOOLEAN type}
1291
1292The BOOLEAN type models the simple binary TRUE/FALSE, YES/NO, ON/OFF
1293or a similar kind of two-way choice.
1294
1295
1296\subsection{The INTEGER type}
1297
1298The INTEGER type is a signed natural number type without any restrictions
1299on its size. If the automatic checking on INTEGER value bounds are
1300necessary, the subtype constraints must be used.
1301\begin{lyxcode}
1302SimpleInteger~::=~INTEGER
1303
1304~
1305
1306-{}-~An~integer~with~a~very~limited~range
1307
1308SmallPositiveInt~::=~INTEGER~(0..127)
1309
1310~
1311
1312-{}-~Integer,~negative
1313
1314NegativeInt~::=~INTEGER~(MIN..0)
1315\end{lyxcode}
1316
1317\subsection{The ENUMERATED type}
1318
1319The ENUMERATED type is semantically equivalent to the INTEGER type
1320with some integer values explicitly named.
1321\begin{lyxcode}
1322FruitId~::=~ENUMERATED~\{~apple(1),~orange(2)~\}
1323
1324~
1325
1326-{}-~The~numbers~in~braces~are~optional,
1327
1328-{}-~the~enumeration~can~be~performed
1329
1330-{}-~automatically~by~the~compiler
1331
1332ComputerOSType~::=~ENUMERATED~\{
1333
1334~~~~FreeBSD,~~~~~~~~~~-{}-~acquires~value~0
1335
1336~~~~Windows,~~~~~~~~~~-{}-~acquires~value~1
1337
1338~~~~Solaris(5),~~~~~~~-{}-~remains~5
1339
1340~~~~Linux,~~~~~~~~~~~~-{}-~becomes~6
1341
1342~~~~MacOS~~~~~~~~~~~~~-{}-~becomes~7
1343
1344\}
1345\end{lyxcode}
1346
1347\subsection{The OCTET STRING type}
1348
1349This type models the sequence of 8-bit bytes. This may be used to
1350transmit some opaque data or data serialized by other types of encoders
1351(i.e. video file, photo picture, etc).
1352
1353
1354\subsection{The OBJECT IDENTIFIER type}
1355
1356The OBJECT IDENTIFIER is used to represent the unique identifier of
1357any object, starting from the very root of the registration tree.
1358If your organization needs to uniquely identify something (a router,
1359a room, a person, a standard, or whatever), you are encouraged to
1360get your own identification subtree at \url{http://www.iana.org/protocols/forms.htm}.
1361
1362For example, the very first ASN.1 module in this Chapter (RectangleModule1)
1363has the following OBJECT IDENTIFIER: 1 3 6 1 4 1 9363 1 5 2 1 1.
1364\begin{lyxcode}
1365ExampleOID~::=~OBJECT~IDENTIFIER
1366
1367~
1368
1369rectangleModule1-oid~ExampleOID
1370
1371~~::=~\{~1~3~6~1~4~1~9363~1~5~2~1~1~\}
1372
1373~
1374
1375-{}-~An~identifier~of~the~Internet.
1376
1377internet-id~OBJECT~IDENTIFIER
1378
1379~~::=~\{~iso(1)~identified-organization(3)
1380
1381~~~~~~~~dod(6)~internet(1)~\}
1382\end{lyxcode}
1383As you see, names are optional.
1384
1385
1386\subsection{The RELATIVE-OID type}
1387
1388The RELATIVE-OID type has the semantics of a subtree of an OBJECT
1389IDENTIFIER. There may be no need to repeat the whole sequence of numbers
1390from the root of the registration tree where the only thing of interest
1391is some of the tree's subsequence.
1392\begin{lyxcode}
1393this-document~RELATIVE-OID~::=~\{~docs(2)~usage(1)~\}
1394
1395~
1396
1397this-example~RELATIVE-OID~::=~\{
1398
1399~~~~this-document~assorted-examples(0)~this-example(1)~\}
1400\end{lyxcode}
1401
1402\section{Some of the ASN.1 String Types}
1403
1404
1405\subsection{The IA5String type}
1406
1407This is essentially the ASCII, with 128 character codes available
1408(7 lower bits of an 8-bit byte).
1409
1410
1411\subsection{The UTF8String type}
1412
1413This is the character string which encodes the full Unicode range
1414(4 bytes) using multibyte character sequences.
1415
1416
1417\subsection{The NumericString type}
1418
1419This type represents the character string with the alphabet consisting
Lev Walkin464166c2010-11-09 08:34:38 -08001420of numbers (``0'' to ``9'') and a space.
Lev Walkined44bf42010-11-08 02:04:55 -08001421
1422
1423\subsection{The PrintableString type}
1424
Lev Walkin464166c2010-11-09 08:34:38 -08001425The character string with the following alphabet: space, ``\textbf{'}''
1426(single quote), ``\textbf{(}'', ``\textbf{)}'', ``\textbf{+}'',
1427``\textbf{,}'' (comma), ``\textbf{-}'', ``\textbf{.}'', ``\textbf{/}'',
1428digits (``0'' to ``9''), ``\textbf{:}'', ``\textbf{=}'', ``\textbf{?}'',
1429upper-case and lower-case letters (``A'' to ``Z'' and ``a''
1430to ``z'').
Lev Walkined44bf42010-11-08 02:04:55 -08001431
1432
1433\subsection{The VisibleString type}
1434
1435The character string with the alphabet which is more or less a subset
Lev Walkin464166c2010-11-09 08:34:38 -08001436of ASCII between the space and the ``\textbf{\textasciitilde{}}''
Lev Walkined44bf42010-11-08 02:04:55 -08001437symbol (tilde).
1438
1439Alternatively, the alphabet may be described as the PrintableString
Lev Walkin464166c2010-11-09 08:34:38 -08001440alphabet presented earlier, plus the following characters: ``\textbf{!}'',
1441``\textbf{``}'', ``\textbf{\#}'', ``\textbf{\$}'', ``\textbf{\%}'',
1442``\textbf{\&}'', ``\textbf{{*}}'', ``\textbf{;}'', ``\textbf{<}'',
1443``\textbf{>}'', ``\textbf{{[}}'', ``\textbf{\textbackslash{}}'',
1444``\textbf{{]}}'', ``\textbf{\textasciicircum{}}'', ``\textbf{\_}'',
1445``\textbf{`}`` (single left quote), ``\textbf{\{}'', ``\textbf{|}'',
1446``\textbf{\}}'', ``\textbf{\textasciitilde{}}''.
Lev Walkined44bf42010-11-08 02:04:55 -08001447
1448
1449\section{ASN.1 Constructed Types}
1450
1451
1452\subsection{The SEQUENCE type}
1453
1454This is an ordered collection of other simple or constructed types.
Lev Walkin464166c2010-11-09 08:34:38 -08001455The SEQUENCE constructed type resembles the C ``struct'' statement.
Lev Walkined44bf42010-11-08 02:04:55 -08001456\begin{lyxcode}
1457Address~::=~SEQUENCE~\{
1458
1459~~~~-{}-~The~apartment~number~may~be~omitted
1460
1461~~~~apartmentNumber~~~~~~NumericString~OPTIONAL,
1462
1463~~~~streetName~~~~~~~~~~~PrintableString,
1464
1465~~~~cityName~~~~~~~~~~~~~PrintableString,
1466
1467~~~~stateName~~~~~~~~~~~~PrintableString,
1468
1469~~~~-{}-~This~one~may~be~omitted~too
1470
1471~~~~zipNo~~~~~~~~~~~~~~~~NumericString~OPTIONAL
1472
1473\}
1474\end{lyxcode}
1475
1476\subsection{The SET type}
1477
1478This is a collection of other simple or constructed types. Ordering
1479is not important. The data may arrive in the order which is different
1480from the order of specification. Data is encoded in the order not
1481necessarily corresponding to the order of specification.
1482
1483
1484\subsection{The CHOICE type}
1485
1486This type is just a choice between the subtypes specified in it. The
1487CHOICE type contains at most one of the subtypes specified, and it
1488is always implicitly known which choice is being decoded or encoded.
Lev Walkin464166c2010-11-09 08:34:38 -08001489This one resembles the C ``union'' statement.
Lev Walkined44bf42010-11-08 02:04:55 -08001490
1491The following type defines a response code, which may be either an
Lev Walkin464166c2010-11-09 08:34:38 -08001492integer code or a boolean ``true''/``false'' code.
Lev Walkined44bf42010-11-08 02:04:55 -08001493\begin{lyxcode}
1494ResponseCode~::=~CHOICE~\{
1495
1496~~~~intCode~~~~INTEGER,
1497
1498~~~~boolCode~~~BOOLEAN
1499
1500\}
1501
1502
1503\end{lyxcode}
1504
1505\subsection{The SEQUENCE OF type}
1506
1507This one is the list (array) of simple or constructed types:
1508\begin{lyxcode}
1509-{}-~Example~1
1510
1511ManyIntegers~::=~SEQUENCE~OF~INTEGER
1512
1513~
1514
1515-{}-~Example~2
1516
1517ManyRectangles~::=~SEQUENCE~OF~Rectangle
1518
1519~
1520
1521-{}-~More~complex~example:
1522
1523-{}-~an~array~of~structures~defined~in~place.
1524
1525ManyCircles~::=~SEQUENCE~OF~SEQUENCE~\{
1526
1527~~~~~~~~~~~~~~~~~~~~~~~~~~~~radius~INTEGER
1528
1529~~~~~~~~~~~~~~~~~~~~~~~~~~~~\}
1530\end{lyxcode}
1531
1532\subsection{The SET OF type}
1533
1534The SET OF type models the bag of structures. It resembles the SEQUENCE
1535OF type, but the order is not important: i.e. the elements may arrive
1536in the order which is not necessarily the same as the in-memory order
1537on the remote machines.
1538\begin{lyxcode}
1539-{}-~A~set~of~structures~defined~elsewhere
1540
1541SetOfApples~::~SET~OF~Apple
1542
1543~
1544
1545-{}-~Set~of~integers~encoding~the~kind~of~a~fruit
1546
1547FruitBag~::=~SET~OF~ENUMERATED~\{~apple,~orange~\}\end{lyxcode}
1548\begin{thebibliography}{ITU-T/ASN.1}
1549\bibitem[ASN1C]{ASN1C}The Open Source ASN.1 Compiler. \url{http://lionet.info/asn1c}
1550
1551\bibitem[AONL]{AONL}Online ASN.1 Compiler. \url{http://lionet.info/asn1c/asn1c.cgi}
1552
1553\bibitem[Dub00]{Dub00}Olivier Dubuisson --- \emph{ASN.1 Communication
Lev Walkin464166c2010-11-09 08:34:38 -08001554between heterogeneous systems}~---~Morgan Kaufmann Publishers, 2000.
Lev Walkined44bf42010-11-08 02:04:55 -08001555\url{http://asn1.elibel.tm.fr/en/book/}. ISBN:0-12-6333361-0.
1556
Lev Walkin464166c2010-11-09 08:34:38 -08001557\bibitem[ITU-T/ASN.1]{ITU-T/ASN.1}ITU-T Study Group 17 --- Languages
Lev Walkined44bf42010-11-08 02:04:55 -08001558for Telecommunication Systems \url{http://www.itu.int/ITU-T/studygroups/com17/languages/}
1559\end{thebibliography}
1560
1561\end{document}