#Presentation The MM-2350 board has two Ethernet ports with two independent 'encX24j600' controllers. It has no wireless functionality. It can therefore be used to build trusted devices. For a presentation of the MM-2350 board, [click here >>](https://minimacy.net/MM-2350.html) [](html) Network diodes are devices that allow traffic to flow in only one direction, such that no information can travel back the other way. A fiber optic cable is typically used with a light emitter on one side and a receiver on the other, which physically guarantees the one-way flow. But these devices are extremely expensive. By using lighter equipment based on an OS and an IP stack, such as Linux, you always run the risk that an attacker takes control of your system and modifies the diode to let certain messages through. [](html) The [MM-2350 board](https://minimacy.net/MM-2350.html) offers a trustworthy and low-cost solution: no OS, no admin access, a single-purpose application with minimal code. The IP stack is not even loaded. Plug in both Ethernet ports and power on the [MM-2350 board](https://minimacy.net/MM-2350.html), and that's it. The screen shows in real time: - the direction of the diode - the connection status - the number of accepted packets and the number of blocked packets The diode only allows UDP broadcast traffic to pass from left to right. Why this choice? - accepting non-broadcast UDP traffic normally requires allowing ARP traffic in both directions: the left-hand side asks for the MAC address associated with the target IP address, and the right-hand side is expected to reply. Whether or not it replies is already a binary piece of information (one bit: reply/no reply), and so the diode leaks Accepting TCP traffic raises the same kind of problem: - by only allowing frames with no data (SYN, ACK, FIN), the presence or absence of these frames is already information - by using the diode as a proxy, and even by buffering data to isolate the left side from the right, it is enough for the recipient to become unavailable or to adopt a certain acknowledgement rhythm to transmit information back to the left - and in all cases, the ARP question mentioned for UDP also applies to TCP #Setup - clone the demo repository: >git clone https://github.com/ambermind/simple-diode-MM-2350.git The example consists of two files: boot.mcy and mm2350.diode.simple.mcy #Usage - Copy both files boot.mcy and mm2350.diode.simple.mcy onto an SD card formatted as FAT32. - Insert the SD card into the [MM-2350 board](https://minimacy.net/MM-2350.html) - Plug in both Ethernet cables - Power on the board [](html) Later you may copy the SD card content into the internal Flash, so you can remove the SD card. [Follow the documentation >>](https://minimacy.net/book/#/tag/mm-2350) #Implementation Every Minimacy host defines a specific constant ending in 'Device': WindowsDevice, UnixDevice, MacOsCmdLineDevice, ... For the [MM-2350 board](https://minimacy.net/MM-2350.html), it is 'MM2350Device'. ## boot The boot.mcy file is very short: #ifdef MM2350Device fun main()= start("mm2350.diode.simple");; #else fun main()= echoLn "This programs runs only on the MM-2350 board. See: https://minimacy.net/MM-2350.html";; #endif It ensures the diode is only launched on the [MM-2350 board](https://minimacy.net/MM-2350.html) and displays a message for all other platforms. ## imports and variables The mm2350.diode.simple.mcy file is not very long either. //------------------- imports and constants use driver.generic.display;; use driver.generic.spi.encX24j600.ethernet;; use baremetal.mm2350.boot;; We first import: - driver.generic.display: the generic display management package for the [MM-2350 board](https://minimacy.net/MM-2350.html) - driver.generic.spi.encX24j600.ethernet: the Ethernet controller driver - baremetal.mm2350.boot: the board's hardware boot, which defines the functions ethLeft() and ethRight() that refer to the two already-initialised Ethernet controllers. We then define three global variables that will be used to count packets. var CountLeftBlocked= 0;; var CountLeftOk= 0;; var CountRightBlocked= 0;; ## diode We then define an Ethernet frame filtering function. The function returns [[true]] if the frame has the broadcast MAC address FF:FF:FF:FF:FF:FF and uses the UDP-IP protocol. fun udpBroadcastFilter(frame)= let strLeft(frame, 6) -> macDest in if macDest=="\$ff\$ff\$ff\$ff\$ff\$ff" then let strRead16Msb(frame, 12) -> protocol in if protocol==0x0800 then // IP let strRead8(frame, 23) -> ipType in ipType==17;; // UDP Next comes the core function of the diode, which defines the behaviour when a frame arrives from the left or from the right. fun ethInit ()= encX24j600OnReceive(ethLeft(), lambda(frame)= if udpBroadcastFilter(frame) then ( // we transfer and count filtered frames from left to right encX24j600Send(ethRight(), frame); set CountLeftOk=CountLeftOk+1; ) else set CountLeftBlocked=CountLeftBlocked+1; ); encX24j600OnReceive(ethRight(), lambda(frame)= // we block everything from right set CountRightBlocked=CountRightBlocked+1; );; That is all for the diode function. We then move on to displaying information on the screen. ## display [](html) We first have a uiInit() function that draws the diode symbol around the horizontal line y=37 (the [MM-2350 board](https://minimacy.net/MM-2350.html)'s screen is 128x64 monochrome pixels). To do this, we use the Minimacy generic API with the [[uiStart]], [[uiUpdate]] and [[uiBuffer]] functions, which allow the screen to be managed as a simple [[Bitmap]]. With a monochrome display, anything that is not black will be rendered in white. Drawing functions such as [[bitmapErase]], [[bitmapLine]], and [[bitmapFillRectangle]] are available. For text, the driver.generic.display package provides access to a 6x8 pixel font and the functions drawString, drawStringCenter, drawStringRight, whose last boolean parameter indicates whether the text is displayed as white on black or black on white. const DIODE_Y=37;; fun triangleDraw(x0, y0, len)= // we draw the triangle that is part of the diode symbol, pointing to the right for i=1;i<=len do let x0-i -> x in bitmapLine(uiBuffer(), x, y0-i, x, y0+i, 0xffffff, nil);; fun diodeDraw()= // we display an horizontal diode symbol from left to right bitmapLine(uiBuffer(), 0, DIODE_Y, 127, DIODE_Y, 0xffffff, nil); triangleDraw(64, DIODE_Y, 7); bitmapLine(uiBuffer(), 64, DIODE_Y-7, 64, DIODE_Y+7, 0xffffff, nil);; fun uiInit()= // we start the UI and display the background on which we will periodically draw the counters and the link status uiStart(0, 0, 128, 64, nil, "Diode"); bitmapErase(uiBuffer(), 0); drawStringCenter(64, 0, "Packet counter", false); diodeDraw(); bitmapFillRectangle(uiBuffer(), 0, 55, nil, nil, 0xffffff, nil); drawStringCenter(64, 56, "UDP broadcast diode", true); uiUpdate();; We then define a uiLoop() function that periodically refreshes the information on the screen: the packet counters and the diode's connection status. fun counterRedraw()= drawString(0, 14, strFormat(">OK *", CountLeftOk), false); drawString(0, 22, strFormat(">no *", CountLeftBlocked), false); drawStringRight(128, 46, strFormat("* no<", CountRightBlocked), false);; fun linkStatusRedraw()= // we draw white or black segments around the diode symbol on the horizontal line to show the link status bitmapLine(uiBuffer(), 16, DIODE_Y, 31, DIODE_Y, if encX24j600LinkStatus(ethLeft()) then 0xffffff, nil); bitmapLine(uiBuffer(), 96, DIODE_Y, 111, DIODE_Y, if encX24j600LinkStatus(ethRight()) then 0xffffff, nil);; fun uiLoop()= // every second we redraw the counters and the link status counterRedraw(); linkStatusRedraw(); uiUpdate(); onTimeout(1000, #uiLoop);; Finally, the main() function initialises Ethernet and the UI before launching the refresh loop in a separate thread. fun main ()= uiInit(); ethInit(); threadStart("ui", #uiLoop);; #Case Use 3D Slash to modelize and 3d print your case. [](html) [Open model >>](https://www.3dslash.net/slash.php?alias=19081e4bb767c9eae4da743a1587be401a94f1a07c4667e350f1aff51cb75517)