lib60870: a C implementation of the IEC 60870-5 telecontrol protocols
Official repository for lib60870 an implementation of the IEC 60870-5-101/104 protocol (read-only mirror)
At a glance
- What is it?
- lib60870 is a portable C99 library for IEC 60870-5-101 over serial links and IEC 60870-5-104 over TCP/IP, with master and slave roles, redundancy groups, file services and optional TLS. It is developed by MZ Automation and can be used under the GPLv3 or a commercial licence.
- Who is it for?
- Adopt lib60870 if you are building a supervisory control or energy system that must speak IEC 60870-5-101 over a serial link or 60870-5-104 over TCP/IP and you want a proven C implementation rather than your own protocol stack. Skip it if you are building a commercial product and cannot accept GPLv3 obligations, since a commercial licence is the alternative the vendor sells, and skip it if you need secure authentication under IEC 60870-5-7, which is a commercial add-on.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 53 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Two protocols, one library, both link types
lib60870 is a library for the IEC 60870-5 family of protocols in C, and the current implementation contains code for IEC 60870-5-101 covering the application layer and the serial link layer, plus IEC 60870-5-104, which is the protocol over TCP/IP. The feature list names the coverage precisely. There is support for all application layer message types. There are master and slave roles, which is the distinction between a controlling station and a controlled one, and both sides are implemented rather than one being a stub. For CS 101 serial communication there are balanced and unbalanced link layers, and for CS 104 there is a client and server model over TCP/IP. There is CS 104 redundancy group support, which is how a pair of redundant controllers is coordinated so that only one is active at a time and the other can take over. There is file service support for a CS101 slave and a CS104 server, which is how measurement files and configuration data are transferred. The last line of the list is the one that decides the deployment target, portable C99 code, which matters because the library is used in supervisory control equipment where the compiler and the memory budget are fixed by the hardware.
Security is a build option, and one feature is not in the open source
The security story has three parts and they are worth separating, because two of them are available and one is not. The library supports most of the TLS features required by IEC 62351-3, which is the companion standard that adds security to the 60870-5 series, and the implementation uses third party code, mbedtls, which you have to supply. Support for secure authentication under IEC 60870-5-7:2013 is available as a commercially available add-on, and that is the part you cannot get from this repository. The distinction is significant in practice. TLS protects the channel, so an observer cannot read the traffic and cannot tamper with it. Secure authentication under 60870-5-7 is a different mechanism, an application layer scheme that proves to the receiving station that a command came from an authorised controller, and it exists because in a power grid the transport encryption alone is not the same as proof of origin. If your system is a grid protection or control system, the difference between the two is often the difference between an acceptable and an unacceptable risk assessment, and the add-on is the answer the vendor sells rather than the answer this repository provides.
Building it is a make, and the TLS path has a specific dependency layout
Compiling the library and the examples is straightforward with make. You build the library in the lib60870-C folder, then go to the examples folder and build the examples with make in each examples directory. The library and the examples can also be built with CMake, and the instructions for an out-of-tree build are a sequence of three commands.
Run `mkdir build`, change into it with `cd build`, then run `cmake ..` to create the build files.
TLS support is where the build stops being trivial, because mbedtls is not vendored and has to be placed exactly where the build system looks for it. You download mbedtls version 2.28.x, unpack the tarball in the dependencies folder so that a folder named dependencies/mbedtls-2.28 exists, and the CMake build system will automatically detect the mbedtls source and build the library with TLS support and mbedtls included. With make you have to say so explicitly.
The make equivalent is `make WITH_MBEDTLS=1`.
The two build systems behave differently here, and the version pin matters, since the README asks for the 2.28.x line specifically rather than the current release. The examples are the fastest way to see the library in use, since the repository ships one per example directory and they exercise the protocol rather than a toy subset of it.
Compiling out the HAL and common code
The library contains some common code and a platform abstraction layer, the HAL, that is shared with other protocol libraries from the same vendor, with libiec61850 given as the example. The point of mentioning that sharing is a practical one: if you use two of the vendor's protocol libraries together, compiling both with their own copies of the common parts means duplicated symbols and the friction of a link error, or worse, subtle differences in behaviour between two copies of the same helper. To avoid that, the library can be compiled without the common parts, using the WITHOUT_HAL and WITHOUT_COMMON defines when calling make.
The make invocation is `make WITHOUT_HAL=1 WITHOUT_COMMON=1`.
This is a design decision worth reading as a statement about the vendor's ecosystem rather than as a build trick. The common code and the HAL are factored out precisely so that a device speaking both IEC 60870 and IEC 61850, which is a normal combination in a substation gateway, can share one implementation of the platform layer, one set of utility functions and one memory handling strategy. A library that only had to serve its own protocol would not need a HAL to be separable at all, and the fact that it is separable, and documented as separable, tells you the vendor expects these libraries to be used together. The trade is that turning them off means you take responsibility for whatever the HAL was abstracting for you.
Configuration, memory and the shape of a CS104 slave
The library has both runtime and compile-time configuration options, and the compile-time ones exist for a reason. They can be used to shrink down the library for small embedded systems, and they are changed by modifying the file config/lib60870_config.h. On memory, the library uses dynamic memory allocation, with malloc and calloc wrapped by its own functions that can be replaced when required, which is the standard way to give an embedded project a pool allocator or a static arena without touching the library. The specific allocation behaviour of the CS104 slave is stated as well: it uses dynamic memory allocation only at setup time, when you call CS104_Slave_create and CS104_Slave_start or CS104_Slave_startThreadless. That is a meaningful property for a device that must run for years without restarting, because it means the steady state does not fragment the heap. It also means the connection setup is where the memory is committed, and a device with a tight memory budget has to have that much available at once. The startThreadless variant is worth noting as well, since it lets you drive the slave from your own event loop instead of giving the library its own thread, which is often what an embedded integrator wants.
The repository on GitHub is a mirror, and pull requests are ignored
The repository description says it plainly, this is the official repository for lib60870 and it is a read-only mirror, and the contributing section says it even more directly. If you want to contribute to the improvement and development of the library you should send comments, feature requests, bug reports or patches, and you should not create pull requests for the GitHub repository because it is a read-only copy, and pull requests may be silently ignored. For more than trivial contributions the author requires a Contributor License Agreement, and the instruction is to contact the vendor. The top level of the tree supports the read-only reading, since it holds the CHANGELOG, COPYING, SECURITY.md, a clang-format configuration, a sonar-project.properties file for static analysis, a user_guide.adoc in AsciiDoc, and the build pipeline files for Bitbucket Pipelines and GitHub Actions, with the actual library under lib60870-C/. The library is developed by Michael Zillgith and supported by MZ Automation GmbH, with bug reports, hints and support directed to a single address. Practically, this means you plan to work against the upstream project rather than through the mirror, and that a patch contribution is a conversation with the maintainer.
Dual licensing, and what that means for a commercial device
The licensing section gives the commercial decision its own section, which is unusual and appropriate for a library that ships inside industrial equipment. The software can be dual licensed under the GPLv3 and a commercial license agreement, and the README is direct that when using the library in commercial and non-GPL applications you should buy a commercial license. Support and commercial license options are provided by MZ Automation GmbH through the same contact address. The reason this matters is the GPLv3's reach. Linking a GPL library into a proprietary controller firmware makes the derived work subject to the GPL's source distribution obligations, and a vendor that ships closed firmware cannot do that. A dual licence removes the conflict by selling a separate grant, and the price of that grant is negotiated rather than published. The contrast with the security add-on from earlier in the README is instructive, since both are commercial extras, and together they define the shape of adoption. The free path gives you the protocol stack, and the paid paths give you the pieces a shipping grid device tends to need, which are a commercial licence and secure authentication.
Editorial conclusion
Adopt lib60870 if you are building a supervisory control or energy system that must speak IEC 60870-5-101 over a serial link or 60870-5-104 over TCP/IP and you want a proven C implementation rather than your own protocol stack. Skip it if you are building a commercial product and cannot accept GPLv3 obligations, since a commercial licence is the alternative the vendor sells, and skip it if you need secure authentication under IEC 60870-5-7, which is a commercial add-on. Verify first that the target platform matches the compiler and operating system you intend to use, that TLS is only compiled in when mbedtls 2.28.x is present, and which configuration options you need to shrink the library for your hardware.
Frequently asked questions
Which IEC 60870 protocols does lib60870 implement?
The current implementation covers IEC 60870-5-101, both the application layer and the serial link layer, and IEC 60870-5-104 over TCP/IP. It supports master and slave roles, balanced and unbalanced link layers for 101 serial links, client and server for 104, CS 104 redundancy groups and file service support.
How do I build lib60870 with TLS support?
Download mbedtls version 2.28.x and unpack it in the dependencies folder so a folder named dependencies/mbedtls-2.28 exists. The CMake build then detects it automatically; with make you pass the option explicitly with make WITH_MBEDTLS=1.
Can I use lib60870 in a closed source commercial product?
Not under the GPLv3 terms, which apply to non-GPL commercial applications. The library is dual licensed, and the README says you should buy a commercial license for such use, with support and licensing options provided by MZ Automation GmbH.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/mz-automation-lib60870)Was this useful?